Open Pat-Wachiraphan opened 4 months ago
@Pat-Wachiraphan , could you please send me the example Rainbow
objects you're dividing here? I'd love to test this out with what you have. (In the meantime I'll play with some simulated noise, but it'd be good to test with the same data as you.)
I'm guessing this might have something to do with the way that the imshowed pixels are being downsampled from the super-high time resolution of the dataset, but the fact that you showed me yesterday that the automatic color scales change dramatically suggests something else weird potentially happening.
Hi @zkbt, sure! I attached a OneDrive link to the file here.
It is not exactly the same as provided in the original post, but it should show the difference.
It looks like this has to do with the way that matplotlib
renders images when the data in the imshow
or pcolormesh
is at much higher resolution than the image is actually being displayed on the screen or in an image file. If it has to visually average multiple data pixels together into one screen pixel, there are different choices for how that's done.
The issue is described to some extent here. I believe that the simplest fix for this is to use keywords of interpolation='antialiased'
for imshow
and 'antialiased=Truefor
pcolormesh`, but I'm still working on putting together a working example demonstrating this is definitely the case.
Ug, OK, this is turning out to be slightly more complicated. Here a gist exploring what's going on with different options.
I think that above fix will work for imshow
uniform (or log-uniform) arrays, in the sense that interpolation='antialiased'
seems to do a good job both zoomed out (showing big patterns and not just high frequency noise) and zoomed in (showing hard edges between pixels, instead of ugly interpolated smoothing).
However, as far as I can tell, even though pcolormesh
accepts an antialiased=True
keyword, it doesn't actually seem to do anything. There's no difference with it turned on or off. This inactive matplotlib issue seems to confirm someone else had similar problems. It looks like, maybe, pcolor
will work though?
import matplotlib.pyplot as plt
import numpy as np
for dpi in [50, 500]:
for f in ['pcolormesh', 'pcolor']:
fig, ax = plt.subplots(1, 2, figsize=(8,4), dpi=dpi)
x = np.arange(500) / 500 - 0.5
y = np.arange(500) / 500 - 0.5
X, Y = np.meshgrid(x, y)
R = np.sqrt(X**2 + Y**2)
f0 = 10
k = 250
a = np.sin(np.pi * 2 * (f0 * R + k * R**2 / 2))
for i, anti in enumerate([False, True]):
exec(f'ax[i].{f}(a, antialiased=anti)')
ax[i].set_title(f'dpi={dpi}, antialiased={anti}')
plt.suptitle(f)
plt.show()
So, I think the solution is just to replace pcolormesh
with pcolor
, and use the antialiased=True
option?
Ug, with pcolor
it is both annoyingly slow (like a minute for the MIRI/LRS dataset) and the behavior is not super intuitive. Whereas I think imshow(interpolation='antialiased')
is doing the required interpolation in data space (see here), I suspect that pcolor(antialiaseds=True)
is maybe doing it in RGBA space, so it's producing colors in the rasterized image that don't appear in the actual colorbar.
It also seems to be adding little white spaces between pixels, that affect the overall color intensity, unless we explicitly draw edges between the faces, but that still ends up looking icky. I can kind of see the large scale bumps in these antialiased pcolor
images, but I think it comes at too high of a cost for interpretability.
I have a feeling that we might need to do imshow
but in a weird log-scale on y-axis?
Yes, I think so.
All of these issues fundamentally come down to it being hard to make matplotlib
make the right choice in how to visually bin together adjacent colorful pixels that it's trying to render. I think these problems only emerge when we're trying to display more pixels than fit in the image. I think that instead of asking it to do the very hard thing of doing an intuitive and understandable binning when trying to display a massive (244w, 22862t) array, we should just bin it ourselves to a more sensible grid, and then display it.
binned = rainbow.bin(dw=0.1*u.micron, dt=1*u.minute)
fi, ax = plt.subplots(1, 2, figsize=(8, 3))
binned.imshow(ax=ax[0])
binned.pcolormesh(ax=ax[1])
I'm about to get off the bus, but I'll try to push up the small changes to fix imshow
and maybe add a warning to pcolormesh
(much?) later tonight.
Sorry this took me so long, and I still wasn't even able to solve it!
Hi, I'm running
chromatic
version 0.4.11The problem: I was trying to use
Rainbow/Rainbow
feature and then encountered this issue. The plot fromRainbow/Rainbow
and flux1/flux2 (outsidechromatic
) are not the same as shown below.This is from![visit1_diff_chromatic](https://github.com/zkbt/chromatic/assets/104591349/56d47575-1ba9-49b3-b646-5e2a81a500b5)
chromatic
This is just from straight plt.imshow![visit1_diff_python](https://github.com/zkbt/chromatic/assets/104591349/dd65a65e-b3ad-406e-af31-b01b57947ab5)
You can see that all the sudden changes has been smeared out and overall scatter seems higher.
Cause of problem: It seem that
Rainbow.imshow()
have a defaultinterpolation='nearest'
andRainbow.pcolormesh()
have a defaultshading='flat'
which I'm not sure if we want that to be a default or not.Potential Solution: I managed to change
interpolation=None
for imshow but I couldn't find the way to turn offshading
forpcolormesh()