Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Imshow breaks if given a unyt_array input #18077

Copy link
Copy link
Closed
@neutrinoceros

Description

@neutrinoceros
Issue body actions

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)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.