Closed
Description
Bug report
Bug summary
matplotlib.pyplot.imshow
doesn't seem to play nicely with unyt_arrays
like other plotting functions do.
Description
This problem was originally reported on unyt (yt-project/unyt#161)
According to unyt's documentation matplotlib is "unyt_aware", but it seems that some plotting functions are not well behaved.
What I Did
Code for reproduction
import unyt
import numpy as np
from matplotlib import pyplot as plt
arr = unyt.unyt_array(np.ones((16, 16)), "g/cm**3")
plt.pcolormesh(arr) # works
plt.contourf(arr) # works
plt.imshow(arr) # breaks
>> UnitOperationError: The <ufunc 'add'> operator for unyt_arrays with units "g/cm**3"
(dimensions "(mass)/(length)**3") and "dimensionless" (dimensions "1") is not well defined.
Actual outcome
Full trace
UnitOperationError Traceback (most recent call last)
<ipython-input-9-7192cbd0f805> in <module>
----> 1 plt.savefig("hello")
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/pyplot.py in savefig(*args, **kwargs)
840 def savefig(*args, **kwargs):
841 fig = gcf()
--> 842 res = fig.savefig(*args, **kwargs)
843 fig.canvas.draw_idle() # need this if 'transparent=True' to reset colors
844 return res
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/figure.py in savefig(self, fname, transparent, **kwargs)
2309 patch.set_edgecolor('none')
2310
-> 2311 self.canvas.print_figure(fname, **kwargs)
2312
2313 if transparent:
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2208
2209 try:
-> 2210 result = print_method(
2211 filename,
2212 dpi=dpi,
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/backend_bases.py in wrapper(*args, **kwargs)
1637 kwargs.pop(arg)
1638
-> 1639 return func(*args, **kwargs)
1640
1641 return wrapper
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, metadata, pil_kwargs, *args)
507 *metadata*, including the default 'Software' key.
508 """
--> 509 FigureCanvasAgg.draw(self)
510 mpl.image.imsave(
511 filename_or_obj, self.buffer_rgba(), format="png", origin="upper",
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py in draw(self)
405 (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
406 else nullcontext()):
--> 407 self.figure.draw(self.renderer)
408 # A GUI class may be need to update a window using this draw, so
409 # don't forget to call the superclass.
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/figure.py in draw(self, renderer)
1861
1862 self.patch.draw(renderer)
-> 1863 mimage._draw_list_compositing_images(
1864 renderer, self, artists, self.suppressComposite)
1865
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
130 if not_composite or not has_images:
131 for a in artists:
--> 132 a.draw(renderer)
133 else:
134 # Composite any adjacent images together
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/cbook/deprecation.py in wrapper(*inner_args, **inner_kwargs)
409 else deprecation_addendum,
410 **kwargs)
--> 411 return func(*inner_args, **inner_kwargs)
412
413 return wrapper
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
2746 renderer.stop_rasterizing()
2747
-> 2748 mimage._draw_list_compositing_images(renderer, self, artists)
2749
2750 renderer.close_group('axes')
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
130 if not_composite or not has_images:
131 for a in artists:
--> 132 a.draw(renderer)
133 else:
134 # Composite any adjacent images together
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/image.py in draw(self, renderer, *args, **kwargs)
636 renderer.draw_image(gc, l, b, im, trans)
637 else:
--> 638 im, l, b, trans = self.make_image(
639 renderer, renderer.get_image_magnification())
640 if im is not None:
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/image.py in make_image(self, renderer, magnification, unsampled)
921 clip = ((self.get_clip_box() or self.axes.bbox) if self.get_clip_on()
922 else self.figure.bbox)
--> 923 return self._make_image(self._A, bbox, transformed_bbox, clip,
924 magnification, unsampled=unsampled)
925
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/matplotlib/image.py in _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification, unsampled, round_to_pixel_border)
446 self.norm.autoscale_None(A)
447 dv = np.float64(self.norm.vmax) - np.float64(self.norm.vmin)
--> 448 vmid = self.norm.vmin + dv / 2
449 fact = 1e7 if scaled_dtype == np.float64 else 1e4
450 newmin = vmid - dv * fact
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/numpy/ma/core.py in __add__(self, other)
4136 if self._delegate_binop(other):
4137 return NotImplemented
-> 4138 return add(self, other)
4139
4140 def __radd__(self, other):
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/numpy/ma/core.py in __call__(self, a, b, *args, **kwargs)
1019 with np.errstate():
1020 np.seterr(divide='ignore', invalid='ignore')
-> 1021 result = self.f(da, db, *args, **kwargs)
1022 # Get the mask for the result
1023 (ma, mb) = (getmask(a), getmask(b))
~/miniconda3/envs/mpl_latest/lib/python3.8/site-packages/unyt/array.py in __array_ufunc__(self, ufunc, method, *inputs, **kwargs)
1737 raise UnitOperationError(ufunc, u0, u1)
1738 else:
-> 1739 raise UnitOperationError(ufunc, u0, u1)
1740 conv, offset = u1.get_conversion_factor(u0, inp1.dtype)
1741 new_dtype = np.dtype("f" + str(inp1.dtype.itemsize))
UnitOperationError: The <ufunc 'add'> operator for unyt_arrays with units "g/cm**3" (dimensions "(mass)/(length)**3") and "dimensionless" (dimensions "1") is not well defined
Expected outcome
A usable figure :)
Matplotlib version
- Operating system: MacOS
- Matplotlib version: 3.3.0
- Matplotlib backend (
print(matplotlib.get_backend())
): MacOSX - Python version: 3.8.3
- Jupyter version (if applicable):
- Other libraries: IPython 7.16.1
mpl installed via cona (Conda-forge channel)