| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
One additional note. This doesn't seem to be backend dependent. I first noticed the bug on the wxagg backend. Here's some code for reproducing it there if you want:
import matplotlib
matplotlib.rcParams['backend'] = 'WxAgg'
import numpy as np
import wx
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
class ImagePanel(wx.Panel):
def __init__(self, parent, panel_id, name, *args, **kwargs):
wx.Panel.__init__(self, parent, panel_id, *args, name = name, **kwargs)
self.fig = matplotlib.figure.Figure((5,4), 75)
self.canvas = FigureCanvasWxAgg(self, -1, self.fig)
self.draw_cid = self.canvas.mpl_connect('draw_event', self.safe_draw)
self.toolbar = NavigationToolbar2WxAgg(self.canvas)
self.toolbar.Realize()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 1, wx.LEFT|wx.TOP|wx.GROW)
sizer.Add(self.toolbar, 0, wx.GROW)
self.SetSizer(sizer)
def safe_draw(self, event = None):
'''should allow drawing when the panel resizes'''
self.canvas.mpl_disconnect(self.draw_cid)
self.canvas.draw()
self.draw_cid = self.canvas.mpl_connect('draw_event', self.safe_draw)
def showNewImage(self, img):
'''Plots a new image'''
self.img = img
self.fig.clear()
a = self.fig.gca()
self.imgobj = a.imshow(self.img, interpolation = 'nearest')
a.set_title('My Image Title')
a.set_xlabel('x (pixels)')
a.set_ylabel('y (pixels)')
a.axis('image')
self.imgobj.set_clim(0, 5)
self.canvas.draw()
class ImageFrame(wx.Frame):
''' A Frame for testing the image panel '''
def __init__(self, title, frame_id):
wx.Frame.__init__(self, None, frame_id, title, name = 'MainFrame')
self.SetSize((750,750))
self.background_panel = wx.Panel(self, -1)
self.image_panel = ImagePanel(self.background_panel, -1, 'ImagePlotPanel')
sizer = wx.BoxSizer()
sizer.Add(self.image_panel, 1, wx.GROW)
self.background_panel.SetSizer(sizer)
self.loadTestImage()
def loadTestImage(self):
img = np.load('test_image.npy')
self.image_panel.showNewImage(img)
class ImageTestApp(wx.App):
''' A test app '''
def OnInit(self):
frame = ImageFrame('My Image', -1)
self.SetTopWindow(frame)
frame.CenterOnScreen()
frame.Show(True)
return True
if __name__ == "__main__":
app = ImageTestApp(0)
app.MainLoop()What is the datatype of your input data?
Can you reproduce this with synthetic data?
The datatype of the numpy array is uint32 (just realized that's what you meant, so edited this answer).
I haven't tried with synthetic data. If I have a chance, I'll try to generate a dataset and test, but I can't promise I'll have time to do that.
Does it work if you cast to floats first? My knee-jerk guess is that we have gotten too-careful with preserving input types.
If I cast it as a float it works fine, good guess!
I don't understand enough about the inner workings of matplotlib to know why that changed things. Is this something you'll fix going forward, or should I just default to casting to float?
Definitely something that should be fixed (hopefully soon!), but as a work around now casting to float will work.
The root of the issues is we removed a couple of cast-to-float calls (both to save memory and to avoid down-casting float128 values) but apparently now let uint though un cast which means in the normalization step they all end up being 0 or 1 (as it looks like your minimum is 0 and all of the other values are strictly less that the maximum value except the maximum so integer division does it's thing).
Great, thanks! I will look for it in the next release (hopefully). I appreciate the fast response, and all of your hard work, along with the rest of the community.
Pretty sure it was #8966 around line 382 of image.py
First, I think its pretty straightforward to do x = np.ma.masked_greater(x, 1e10) or whatever is adequate to catch your bad flag.
But, I agree that if you specify vmax in imshow that it should do a better job of the scaling.
@tacaswell the interpolation happens at draw time. Should we not use vmin and vmax to do the scaling if they are set?
Oh, hold it, we kind of do, but only if you set both vmin and vmax. The bug here is that vmin=None and then our attempt to make things right fails. Your test above works fine if you set vmin=-2
For pcolor we are rendering individual rectangle patches w for here as for image we resample the image and then pass that to the renderer. In general imshow will be much faster for large arrays.
You can not use vmin and vmax for the rescaling limits because you will not get the interpolation correct as you will be clipping any large values to just above / below the limits.
ah, that means we just need to make sure the norm has auto-scaled.
jklymak, sure I can mask the bad flag, but it's one more step to do and not at all handy if you do not know beforehand what was actually used and you just want to get an impression of the data.
I realized that, if I do the plotting and then re-size the plotting window, using version 2.2.2, it sets back to ok scaling. The same is not true for 2.1.2.
See #11047 for the same fix as before, but this time handling if the norms are None.
@tacaswell, I just used the data min and max rather than relying on a norm autoscaling.
@mmf1982 OK, thats probably because the autoscaling for the norm gets applied at the first draw, so the second draw has the correct info.
There are still problems if the initial dtype is not float64 and the outlier is negative, consider:
x=np.array([[0.1,0.2],[-1.e18,0.3]]).astype("float32");plt.imshow(x,vmin=0,vmax=0.5)
I set both vmin and vmax, but still the result does not look as wanted. In fact, this is even more akward,0.1, 0.2 and -1e18 are coloured as min and 0.3 as maximum.
I still do not see why you "need to do the scaling and unscaling" to the data. If you do not do it, the internal resampling is fine. (?)
@mmf1982 See discussions at #8631 #8966, #5718 and https://matplotlib.org/users/dflt_style_changes.html#colormapping-pipeline for more details.
The dv * 1e7 was too big for float32. Changed to dv * 1e4 seems OK, but that value was just empricallly decided. See change to #11047
Thanks @tacaswell for the references and thanks @jklymak for the fix.
| Back | FazBrowse Home | New Git URL |
Bug report
Bug summary
When using imshow with larger images, you lose pixel resolution for low intensity pixels with lots of nearby zeros (not sure if the intensity or nearby zeros are relevant, or just relative isolation of the pixel). It's like they're being interpolated away, even if interpolation is set to nearest. This is new behavior in version 2.1.
Code for reproduction
Use the attached npy file, which is an image referenced in this test script.
Actual outcome

Using matplotlib 2.1.1:
Screenshot from the display of full image (first plot in code above):
Using the zoom tool to zoom in on a region when the full image is plotted:

Plotting roughly the same zoom region initially (second plot in code above):

Expected outcome

It should all look like the third image. Here's the output when the same code is run in version 2.0.2
Screenshot from the display of full image (first plot in code above):
Using the zoom tool to zoom in on a region when the full image is plotted:

Plotting roughly the same zoom region initially (second plot in code above):

Matplotlib version
All libraries are installed through conda, using the standard channel. This includes both versions of matplotlib (2.1.1 and 2.0.2).
Numpy file with image data:
test_image.zip