The problem here seems to do with plotting very small numbers. with max_x = 1000, it gives only two non-zero values out of 300, 1.72083369e-260 and 2.05807755e-291; and with max_x = 1100 only one, 7.90845000e-317. Naturally if you change, 300 to 301 then the error does not occur, but that goes beside the point. Matplotlib should not give such errors when plotting small numbers.
Anyway for completeness I get the following warnings for both plt.show and plt.savefig
transforms.py:2558: RuntimeWarning: overflow encountered in double_scalars
y_scale = 1.0 / inh
transforms.py:2560: RuntimeWarning: invalid value encountered in double_scalars
[0.0 , y_scale, (-inb*y_scale)],
with savefig additionally throwing the assertion error
transforms.py, line 2107, in __init__
assert x_transform.is_separable
In [1]: importnumpyasnpIn [2]: np.MachAr(float).xminOut[2]: 2.2250738585072014e-308
So, a possible bug in numpy? Combined with a possible bug in matplotlib. I mean if numpy gives us numbers that shouldn't exist, then that would explain why our calculations fail. I think we should first get some clarification from numpy about this and then decide how to patch it (atm I think doing a test based around (x < np.MachAr().xmin).any(), but I would want to hear from numpy first).
I remember seeing an issue go by on numpy a while ago which was talking
about 'denormal' floats (http://en.wikipedia.org/wiki/Denormal_number) so I
don't think it is a bug in numpy. If the top and bottom of the range are
the same we have some code that make the range non-singular, but it seems
that this is falling in the gap of what triggers that code path and what
works.
In [2]: np.MachAr(float).xmin
Out[2]: 2.2250738585072014e-308
So, a possible bug in numpy? Combined with a possible bug in matplotlib. I
mean if numpy gives us numbers that shouldn't exist, then that would
explain why our calculations fail. I think we should first get some
clarification from numpy about this and then decide how to patch it (atm I
think doing a test based around (x < np.MachAr().xmin).any(), but I want
to hear from numpy first).
—
Reply to this email directly or view it on GitHub #4318 (comment)
.
Thanks for the link, so definitly a matplotlib bug, but I still think a bug in numpy exists over MachAr... I have just submitted a bug on this to numpy numpy/numpy#5755.
@tacaswell forgive my ignorance, but what made you say that it came from the ticks? The overflow error appears from doing a transform for drawing a line:
lines.py, line 712, in draw
tpath, affine = transf_path.get_transformed_path_and_affine()
Nothing changes with respect to this bug when I add:
ax.set_xticks([])
ax.set_yticks([])
Pardon my poor knowledge of the draw code, I only know the backends well atm.
@tacaswellhttps://github.com/tacaswell forgive my ignorance, but what
made you say that it came from the ticks? The overflow error appears from
doing a transform for drawing a line:
lines.py, line 712, in draw
tpath, affine = transf_path.get_transformed_path_and_affine()
This still occurs with the error even if I add:
ax.set_xticks([])
ax.set_yticks([])
Pardon my poor knowledge of the draw code, I only know the backends well
atm.
—
Reply to this email directly or view it on GitHub #4318 (comment)
.
Ahh, the traceback from there, I looked at the first problem, the overflow error, so I stuck a traceback in that line of code... that error happens in BboxTransformFrom.get_matrix and does 1/<y_canvas_max> but as subnormal only extends the minimum exponent, we get an overflow when taking the reciprocal.
This BboxTransformFrom.get_matrix transforms all points from grid space to canvas space, and thus gets called when plotting the line.
So yes, I think we need to change the code to detect singularity from something like if dy == 0: raise Error to if dy < 1/np.MachAr(float).xmax: raise Error. I currently hunt for that line that tests singularity, I have found some very close to the source but only do so on DEBUG, and have now just found a line in axes._base.set_ylim that looks like it, but putting in print statements and passing in a true singular set of data to plot, (i.e. not just from a computational perspective), it has already done so before, so now I will trace up until I find the source of the de-singularisation of the bounding box :).
Ahh, the traceback from there, I looked at the first problem, the overflow
error, so I stuck a traceback in that line of code... that error happens in
BboxTransformFrom.get_matrix and does 1/ but as subnormal only extends
the minimum exponent, we get an overflow when taking the reciprocal.
This BboxTransformFrom.get_matrix transforms all points from grid space
to canvas space, and thus gets called when plotting the line.
So yes, I think we need to change the code to detect singularity from
something like if dy == 0: raise Error to if dy <
1/np.MachAr(float).xmax: raise Error. I currently hunt for that line that
tests singularity, I have found some very close to the source but only do
so on DEBUG, and have now just found a line in axes._base.set_ylim that
looks like it, but putting in print statements and passing in a true
singular set of data to plot, (i.e. not just from a computational
perspective), it has already done so before, so now I will trace up until I
find the source of the de-singularisation of the bounding box :).
—
Reply to this email directly or view it on GitHub #4318 (comment)
.
@efiring rereading, I meant that we need do need to properly deal with small ranges, and if we do that I think we can safely plot subnormals for plotting.
I think we just need to some linear rescaling, x' = mx + c, on par with what we do at the moment for ranges, i.e similar to what we already have with this code (at least visually, I haven't looked at the internals):
frommatplotlibimportpyplotaspltplt.plot([1000, 1001, 1002]) # scales with m = 1, c = -1000plt.show()
posx and posy should be finite values
posx and posy should be finite values
/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/numpy/core/fromnumeric.py:83: RuntimeWarning: invalid value encountered in reduce
return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
posx and posy should be finite values
posx and posy should be finite values
posx and posy should be finite values
Traceback (most recent call last):
File "/Users/dzieciou/projects/example/gocd/reproduce.py", line 31, in <module>
plot.savefig("barplot.png")
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/seaborn/axisgrid.py", line 37, in savefig
self.fig.savefig(*args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/figure.py", line 2094, in savefig
self.canvas.print_figure(fname, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backend_bases.py", line 2075, in print_figure
**kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py", line 510, in print_png
FigureCanvasAgg.draw(self)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py", line 402, in draw
self.figure.draw(self.renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/figure.py", line 1649, in draw
renderer, self, artists, self.suppressComposite)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/image.py", line 138, in _draw_list_compositing_images
a.draw(renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 2610, in draw
mimage._draw_list_compositing_images(renderer, self, artists)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/image.py", line 138, in _draw_list_compositing_images
a.draw(renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 1185, in draw
ticks_to_draw = self._update_ticks(renderer)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 1023, in _update_ticks
tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 967, in iter_ticks
majorLocs = self.major.locator()
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1985, in __call__
return self.tick_values(vmin, vmax)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1993, in tick_values
locs = self._raw_ticks(vmin, vmax)
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1932, in _raw_ticks
nbins = np.clip(self.axis.get_tick_space(),
File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 2543, in get_tick_space
return int(np.floor(length / size))
ValueError: cannot convert float NaN to integer
@ImportanceOfBeingErnest, your comment saved me some time tracking this down! Since the issue was data dependent in my case and I had several plt.text(), this wrapper was useful:
# plots text raising ArgumentError for NaN positions, avoiding "cryptic" error:
# https://github.com/matplotlib/matplotlib/issues/4318#issuecomment-436266884
def pltText(x, y, s, **kwargs):
if np.isnan(x + y):
raise ArgumentError(x, y)
return plt.text(x, y, s, **kwargs)
Maybe plt.text() should do something similar by default; it currently appears to allow what plt.savefig() cannot handle. (I tested only with matplotlib 2.2.4, though, the latest version pip updated to.)
Just to be clear, this bug doesn't exist in master anymore because we now check the bboxes for finite-values before we add them to the tightbbox calculations...
This error also shows when using tight_layout with nan value.
Here's an example:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['figure.figsize'] = 10,10
class MidpointNormalize(matplotlib.colors.Normalize):
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
matplotlib.colors.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
# Note that I'm ignoring clipping and other edge cases here.
result, is_scalar = self.process_value(value)
x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.array(np.interp(value, x, y), mask=result.mask, copy=False)
# make these smaller to increase the resolution
dx, dy = 0.15, 0.05
# generate 2 2d grids for the x & y bounds
y, x = np.mgrid[slice(-3, 3 + dy, dy),
slice(-3, 3 + dx, dx)]
z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()
z [0:2,0:2] = np.nan
plt.pcolormesh(x, y, z, cmap='seismic',norm=MidpointNormalize(midpoint=0.,vmin=-3,vmax=3))
plt.title('pcolormesh')
plt.axis([x.min(), x.max(), y.min(), y.max()])
plt.colorbar(extend='min')
# plt.tight_layout(w_pad=0.1, h_pad=1)
plt.savefig('test.png', dpi = 720)
When I comment out plt.tight_layout(w_pad=0.1, h_pad=1), I got this:
E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\colorbar.py:1042: RuntimeWarning: invalid value encountered in true_divide
z = np.take(y, i0) + (xn - np.take(b, i0)) * dy / db
E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\transforms.py:402: RuntimeWarning: invalid value encountered in double_scalars
return points[1, 0] - points[0, 0]
Traceback (most recent call last):
File "C:\Users\Xin\Desktop\test_extend.py", line 37, in <module>
plt.savefig('test.png', dpi = 720)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\pyplot.py", line 689, in savefig
res = fig.savefig(*args, **kwargs)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\figure.py", line 2094, in savefig
self.canvas.print_figure(fname, **kwargs)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\backend_bases.py", line 2075, in print_figure
**kwargs)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\backends\backend_agg.py", line 510, in print_png
FigureCanvasAgg.draw(self)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\backends\backend_agg.py", line 402, in draw
self.figure.draw(self.renderer)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\figure.py", line 1649, in draw
renderer, self, artists, self.suppressComposite)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
a.draw(renderer)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axes\_base.py", line 2628, in draw
mimage._draw_list_compositing_images(renderer, self, artists)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
a.draw(renderer)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 1185, in draw
ticks_to_draw = self._update_ticks(renderer)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 1023, in _update_ticks
tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 967, in iter_ticks
majorLocs = self.major.locator()
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\ticker.py", line 1985, in __call__
return self.tick_values(vmin, vmax)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\ticker.py", line 1993, in tick_values
locs = self._raw_ticks(vmin, vmax)
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\ticker.py", line 1932, in _raw_ticks
nbins = np.clip(self.axis.get_tick_space(),
File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 2159, in get_tick_space
return int(np.floor(length / size))
ValueError: cannot convert float NaN to integer
The solution:
Add vmin and vmax:
plt.pcolormesh(x, y, z, vmin=z_min, vmax=z_max, cmap='seismic',norm=MidpointNormalize(midpoint=0.,vmin=-3,vmax=3))
Activity
OceanWolf commented on Apr 8, 2015
The problem here seems to do with plotting very small numbers. with max_x = 1000, it gives only two non-zero values out of 300, 1.72083369e-260 and 2.05807755e-291; and with max_x = 1100 only one, 7.90845000e-317. Naturally if you change, 300 to 301 then the error does not occur, but that goes beside the point. Matplotlib should not give such errors when plotting small numbers.
Anyway for completeness I get the following warnings for both plt.show and plt.savefig
with savefig additionally throwing the assertion error
transforms.py, line 2107, in __init__ assert x_transform.is_separabletacaswell commented on Apr 8, 2015
Oddly, the error seems to be coming out of drawing the tick labels.
The issue here seems to be that this is pushing the limits of floats. On my system I only get 1 non-zero value which is
which is notably smaller than what http://docs.scipy.org/doc/numpy/reference/generated/numpy.MachAr.html#numpy.MachAr claims the smallest float should be which makes me think something awful is going on with non-normal floats (and I am now out of my depth on the numerics side of things.).
I think the solution is to make sure we do a better job making sure that auto-limits are non-singular.
tacaswell commented on Apr 8, 2015
Adding ax.set_ylim(0, 1e-300) 'fixes' this problem.
OceanWolf commented on Apr 8, 2015
Hmm, slightly different numbers, what system do you use? I work on debian jessie 64bit python 2.7.9
tacaswell commented on Apr 8, 2015
Ubuntu beta (varient?, something with a v) but using py3k from anaconda.
OceanWolf commented on Apr 8, 2015
and 32bit or 64bit?
oh, I see what you mean...
So, a possible bug in numpy? Combined with a possible bug in matplotlib. I mean if numpy gives us numbers that shouldn't exist, then that would explain why our calculations fail. I think we should first get some clarification from numpy about this and then decide how to patch it (atm I think doing a test based around (x < np.MachAr().xmin).any(), but I would want to hear from numpy first).
tacaswell commented on Apr 8, 2015
I remember seeing an issue go by on numpy a while ago which was talking
about 'denormal' floats (http://en.wikipedia.org/wiki/Denormal_number) so I
don't think it is a bug in numpy. If the top and bottom of the range are
the same we have some code that make the range non-singular, but it seems
that this is falling in the gap of what triggers that code path and what
works.
On Wed, Apr 8, 2015 at 8:43 AM OceanWolf notifications@github.com wrote:
OceanWolf commented on Apr 8, 2015
Thanks for the link, so definitly a matplotlib bug, but I still think a bug in numpy exists over MachAr... I have just submitted a bug on this to numpy numpy/numpy#5755.
OceanWolf commented on Apr 8, 2015
@tacaswell forgive my ignorance, but what made you say that it came from the ticks? The overflow error appears from doing a transform for drawing a line:
Nothing changes with respect to this bug when I add:
Pardon my poor knowledge of the draw code, I only know the backends well atm.
tacaswell commented on Apr 8, 2015
The trace back is raised from in side a text draw inside an axis draw
inside an axes draw.
It would also be worth looking if the same thing happens with one of the
vector backend s
On Wed, Apr 8, 2015, 12:40 OceanWolf notifications@github.com wrote:
OceanWolf commented on Apr 8, 2015
Ahh, the traceback from there, I looked at the first problem, the overflow error, so I stuck a traceback in that line of code... that error happens in BboxTransformFrom.get_matrix and does 1/<y_canvas_max> but as subnormal only extends the minimum exponent, we get an overflow when taking the reciprocal.
This BboxTransformFrom.get_matrix transforms all points from grid space to canvas space, and thus gets called when plotting the line.
So yes, I think we need to change the code to detect singularity from something like if dy == 0: raise Error to if dy < 1/np.MachAr(float).xmax: raise Error. I currently hunt for that line that tests singularity, I have found some very close to the source but only do so on DEBUG, and have now just found a line in axes._base.set_ylim that looks like it, but putting in print statements and passing in a true singular set of data to plot, (i.e. not just from a computational perspective), it has already done so before, so now I will trace up until I find the source of the de-singularisation of the bounding box :).
WeatherGod commented on Apr 8, 2015
desingularization happens in the autoscaling, IIRC. So, it would be prior
to the draw()/show().
On Wed, Apr 8, 2015 at 3:14 PM, OceanWolf notifications@github.com wrote:
OceanWolf commented on Apr 8, 2015
Ahh yes, found it, the transforms.nonsingular function.
12 remaining items
Merge pull request #4717 from efiring/nonsingular
efiring commented on Jul 17, 2015
@OceanWolf, Thanks for your diagnoses and explanations, which were very helpful. Also, I didn't know about np.MachAr() until you pointed it out.
OceanWolf commented on Jul 17, 2015
@efiring rereading, I meant that we need do need to properly deal with small ranges, and if we do that I think we can safely plot subnormals for plotting.
I think we just need to some linear rescaling, x' = mx + c, on par with what we do at the moment for ranges, i.e similar to what we already have with this code (at least visually, I haven't looked at the internals):
dzieciou commented on Nov 6, 2018
I was able to reproduce the issue:
Here's the full stacktrace:
posx and posy should be finite values posx and posy should be finite values /Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/numpy/core/fromnumeric.py:83: RuntimeWarning: invalid value encountered in reduce return ufunc.reduce(obj, axis, dtype, out, **passkwargs) posx and posy should be finite values posx and posy should be finite values posx and posy should be finite values Traceback (most recent call last): File "/Users/dzieciou/projects/example/gocd/reproduce.py", line 31, in <module> plot.savefig("barplot.png") File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/seaborn/axisgrid.py", line 37, in savefig self.fig.savefig(*args, **kwargs) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/figure.py", line 2094, in savefig self.canvas.print_figure(fname, **kwargs) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backend_bases.py", line 2075, in print_figure **kwargs) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py", line 510, in print_png FigureCanvasAgg.draw(self) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py", line 402, in draw self.figure.draw(self.renderer) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/figure.py", line 1649, in draw renderer, self, artists, self.suppressComposite) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/image.py", line 138, in _draw_list_compositing_images a.draw(renderer) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 2610, in draw mimage._draw_list_compositing_images(renderer, self, artists) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/image.py", line 138, in _draw_list_compositing_images a.draw(renderer) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/artist.py", line 50, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 1185, in draw ticks_to_draw = self._update_ticks(renderer) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 1023, in _update_ticks tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 967, in iter_ticks majorLocs = self.major.locator() File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1985, in __call__ return self.tick_values(vmin, vmax) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1993, in tick_values locs = self._raw_ticks(vmin, vmax) File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/ticker.py", line 1932, in _raw_ticks nbins = np.clip(self.axis.get_tick_space(), File "/Users/dzieciou/virtualenvs/seaborn/lib/python3.7/site-packages/matplotlib/axis.py", line 2543, in get_tick_space return int(np.floor(length / size)) ValueError: cannot convert float NaN to integerAny workaround for it?
ImportanceOfBeingErnest commented on Nov 6, 2018
@dzieciou Your issue is that you create a text at a nan position. A minimal example would be
import numpy as np import matplotlib.pyplot as plt plt.text(0, np.nan, "My Text") plt.savefig("barplot.png", bbox_inches="tight") plt.show()Workarounds:
ulrichstern commented on Mar 17, 2019
@ImportanceOfBeingErnest, your comment saved me some time tracking this down! Since the issue was data dependent in my case and I had several plt.text(), this wrapper was useful:
# plots text raising ArgumentError for NaN positions, avoiding "cryptic" error: # https://github.com/matplotlib/matplotlib/issues/4318#issuecomment-436266884 def pltText(x, y, s, **kwargs): if np.isnan(x + y): raise ArgumentError(x, y) return plt.text(x, y, s, **kwargs)Maybe plt.text() should do something similar by default; it currently appears to allow what plt.savefig() cannot handle. (I tested only with matplotlib 2.2.4, though, the latest version pip updated to.)
jklymak commented on Mar 18, 2019
Just to be clear, this bug doesn't exist in master anymore because we now check the bboxes for finite-values before we add them to the tightbbox calculations...
ulrichstern commented on Mar 18, 2019
Great. I should have checked master...
jklymak commented on Mar 18, 2019
No problem! I just wanted it on the record here so folks don’t try to track this bug down.
zxdawn commented on Aug 19, 2019
This error also shows when using tight_layout with nan value.
Here's an example:
import matplotlib import matplotlib.pyplot as plt import numpy as np plt.rcParams['figure.figsize'] = 10,10 class MidpointNormalize(matplotlib.colors.Normalize): def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False): self.midpoint = midpoint matplotlib.colors.Normalize.__init__(self, vmin, vmax, clip) def __call__(self, value, clip=None): # Note that I'm ignoring clipping and other edge cases here. result, is_scalar = self.process_value(value) x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1] return np.ma.array(np.interp(value, x, y), mask=result.mask, copy=False) # make these smaller to increase the resolution dx, dy = 0.15, 0.05 # generate 2 2d grids for the x & y bounds y, x = np.mgrid[slice(-3, 3 + dy, dy), slice(-3, 3 + dx, dx)] z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2) z = z[:-1, :-1] z_min, z_max = -np.abs(z).max(), np.abs(z).max() z [0:2,0:2] = np.nan plt.pcolormesh(x, y, z, cmap='seismic',norm=MidpointNormalize(midpoint=0.,vmin=-3,vmax=3)) plt.title('pcolormesh') plt.axis([x.min(), x.max(), y.min(), y.max()]) plt.colorbar(extend='min') # plt.tight_layout(w_pad=0.1, h_pad=1) plt.savefig('test.png', dpi = 720)When I comment out plt.tight_layout(w_pad=0.1, h_pad=1), I got this:
E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\colorbar.py:1042: RuntimeWarning: invalid value encountered in true_divide z = np.take(y, i0) + (xn - np.take(b, i0)) * dy / db E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\transforms.py:402: RuntimeWarning: invalid value encountered in double_scalars return points[1, 0] - points[0, 0] Traceback (most recent call last): File "C:\Users\Xin\Desktop\test_extend.py", line 37, in <module> plt.savefig('test.png', dpi = 720) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\pyplot.py", line 689, in savefig res = fig.savefig(*args, **kwargs) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\figure.py", line 2094, in savefig self.canvas.print_figure(fname, **kwargs) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\backend_bases.py", line 2075, in print_figure **kwargs) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\backends\backend_agg.py", line 510, in print_png FigureCanvasAgg.draw(self) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\backends\backend_agg.py", line 402, in draw self.figure.draw(self.renderer) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\figure.py", line 1649, in draw renderer, self, artists, self.suppressComposite) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images a.draw(renderer) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axes\_base.py", line 2628, in draw mimage._draw_list_compositing_images(renderer, self, artists) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images a.draw(renderer) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 1185, in draw ticks_to_draw = self._update_ticks(renderer) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 1023, in _update_ticks tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 967, in iter_ticks majorLocs = self.major.locator() File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\ticker.py", line 1985, in __call__ return self.tick_values(vmin, vmax) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\ticker.py", line 1993, in tick_values locs = self._raw_ticks(vmin, vmax) File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\ticker.py", line 1932, in _raw_ticks nbins = np.clip(self.axis.get_tick_space(), File "E:\miniconda3\envs\satpy\lib\site-packages\matplotlib\axis.py", line 2159, in get_tick_space return int(np.floor(length / size)) ValueError: cannot convert float NaN to integerThe solution:
Add vmin and vmax:
tacaswell commented on Aug 20, 2019
@zxdawn Can you please open a new issue with that example and include the version information?
zxdawn commented on Aug 21, 2019
@tacaswell OK, submit to #15093 .