Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Closed
Milestone
Description
Bug summary
Getting an error when saving an animated RGB image that was loaded from a pickled figure. I've isolated the error to matplotlib 3.9.0, with this code working in 3.8.3, which makes me think that this is to do with the pybind11 upgrade in#26275?
Things I've tried:
- Grayscale images (eg
data = np.random.rand(100, 100)
) work. - Numpy v1.26.4 and v2.0.0 show no difference in behavior
- This shows up at least on WSL and Ubuntu
- In the debugger, both
data.dtype
andout.dtype
are showing'float64'
prior to the_image.resample
call.- However, if I re-cast the arrays with
data = data.astype('float64')
,out = ...
, then the_image.resample
call no longer fails! - If I re-cast only one, then
out.dtype == data.dtype
returnsTrue
, but on the function call I get the errorValueError: Input and output arrays have mismatched types
- ... so something is up with the types, and the C++ code is bombing. But python is saying things line up.
- However, if I re-cast the arrays with
See these parts of the source:
matplotlib/lib/matplotlib/image.py
Lines 205 to 213 ind7d1bba
out=np.zeros(out_shape+data.shape[2:],data.dtype)# 2D->2D, 3D->3D. | |
ifresampleisNone: | |
resample=image_obj.get_resample() | |
_image.resample(data,out,transform, | |
_interpd_[interpolation], | |
resample, | |
alpha, | |
image_obj.get_filternorm(), | |
image_obj.get_filterrad()) |
matplotlib/src/_image_wrapper.cpp
Lines 174 to 199 ind7d1bba
if (auto resampler = | |
(ndim ==2) ? ( | |
(dtype.is(py::dtype::of<std::uint8_t>())) ? resample<agg::gray8> : | |
(dtype.is(py::dtype::of<std::int8_t>())) ? resample<agg::gray8> : | |
(dtype.is(py::dtype::of<std::uint16_t>())) ? resample<agg::gray16> : | |
(dtype.is(py::dtype::of<std::int16_t>())) ? resample<agg::gray16> : | |
(dtype.is(py::dtype::of<float>())) ? resample<agg::gray32> : | |
(dtype.is(py::dtype::of<double>())) ? resample<agg::gray64> : | |
nullptr) : ( | |
// ndim == 3 | |
(dtype.is(py::dtype::of<std::uint8_t>())) ? resample<agg::rgba8> : | |
(dtype.is(py::dtype::of<std::int8_t>())) ? resample<agg::rgba8> : | |
(dtype.is(py::dtype::of<std::uint16_t>())) ? resample<agg::rgba16> : | |
(dtype.is(py::dtype::of<std::int16_t>())) ? resample<agg::rgba16> : | |
(dtype.is(py::dtype::of<float>())) ? resample<agg::rgba32> : | |
(dtype.is(py::dtype::of<double>())) ? resample<agg::rgba64> : | |
nullptr)) { | |
Py_BEGIN_ALLOW_THREADS | |
resampler( | |
input_array.data(), input_array.shape(1), input_array.shape(0), | |
output_array.mutable_data(), output_array.shape(1), output_array.shape(0), | |
params); | |
Py_END_ALLOW_THREADS | |
}else { | |
throwstd::invalid_argument("arrays must be of dtype byte, short, float32 or float64"); | |
} |
Code for reproduction
importioimportpickleimportnumpyasnpimportmatplotlib.pyplotaspltfrompathlibimportPathfrommatplotlib.animationimportFuncAnimationdir=Path(__file__).parent.resolve()# generate random rgb datafig,ax=plt.subplots()np.random.seed(0)data=np.random.rand(100,100,3)ax.imshow(data)# pick the figure and reloadbuf=io.BytesIO()pickle.dump(fig,buf)buf.seek(0)fig_pickled=pickle.load(buf)# Animatedefupdate(frame):returnax,ani=FuncAnimation(fig_pickled,update,frames=2)# Save the animationfilepath=dir/'test.gif'ani.save(filepath)
Actual outcome
Exception has occurred: ValueErrorarrays must be of dtype byte, short, float32 or float64 File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/image.py", line 208, in _resample _image.resample(data, out, transform, File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/image.py", line 567, in _make_image output = _resample( # resample rgb channels ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/image.py", line 952, in make_image return self._make_image(self._A, bbox, transformed_bbox, clip, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/image.py", line 653, in draw im, l, b, trans = self.make_image( ^^^^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/artist.py", line 72, in draw_wrapper return draw(artist, renderer) ^^^^^^^^^^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/image.py", line 132, in _draw_list_compositing_images a.draw(renderer) File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/axes/_base.py", line 3110, in draw mimage._draw_list_compositing_images( File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/artist.py", line 72, in draw_wrapper return draw(artist, renderer) ^^^^^^^^^^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/image.py", line 132, in _draw_list_compositing_images a.draw(renderer) File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/figure.py", line 3157, in draw mimage._draw_list_compositing_images( File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/artist.py", line 72, in draw_wrapper return draw(artist, renderer) ^^^^^^^^^^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/artist.py", line 95, in draw_wrapper result = draw(artist, renderer, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/backends/backend_agg.py", line 387, in draw self.figure.draw(self.renderer) File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/backends/backend_agg.py", line 432, in print_raw FigureCanvasAgg.draw(self) File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/backend_bases.py", line 2054, in <lambda> print_method = functools.wraps(meth)(lambda *args, **kwargs: meth( ^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/backend_bases.py", line 2204, in print_figure result = print_method( ^^^^^^^^^^^^^ File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/backends/backend_qtagg.py", line 75, in print_figure super().print_figure(*args, **kwargs) File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/figure.py", line 3390, in savefig self.canvas.print_figure(fname, **kwargs) File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/animation.py", line 371, in grab_frame self.fig.savefig(self._proc.stdin, format=self.frame_format, File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/lib/matplotlib/animation.py", line 1109, in save writer.grab_frame(**savefig_kwargs) File "/mnt/c/Users/Scott/Documents/Documents/Coding/matplotlib/_test_pybind11_error.py", line 35, in <module> ani.save(filepath)ValueError: arrays must be of dtype byte, short, float32 or float64
Matplotlib Version
3.9.0