Closed
Description
Bug summary
When pcolormesh
receives a masked array, it seems to be writing back to the mask. Since numpy 1.24 this now causes pcolormesh
to fail if the mask is read-only.
Code for reproduction
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(6).reshape(2, 3)
mask = np.broadcast_to([False, True, False], data.shape) # read-only array
masked_data = np.ma.array(data, mask=mask)
plt.pcolormesh(masked_data)
Actual outcome
Traceback (most recent call last):
File "pcolormesh_read_only_mask.py", line 9, in <module>
plt.pcolormesh(masked_data)
File "[conda-env-path]/lib/python3.11/site-packages/matplotlib/pyplot.py", line 2773, in pcolormesh
__ret = gca().pcolormesh(
^^^^^^^^^^^^^^^^^
File "[conda-env-path]/lib/python3.11/site-packages/matplotlib/__init__.py", line 1442, in inner
return func(ax, *map(sanitize_sequence, args), **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[conda-env-path]/lib/python3.11/site-packages/matplotlib/axes/_axes.py", line 6220, in pcolormesh
X, Y, C, shading = self._pcolorargs('pcolormesh', *args,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[conda-env-path]/lib/python3.11/site-packages/matplotlib/axes/_axes.py", line 5704, in _pcolorargs
C = cbook.safe_masked_invalid(C)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[conda-env-path]/lib/python3.11/site-packages/matplotlib/cbook/__init__.py", line 715, in safe_masked_invalid
xm = np.ma.masked_invalid(x, copy=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[conda-env-path]/lib/python3.11/site-packages/numpy/ma/core.py", line 2360, in masked_invalid
res = masked_where(~(np.isfinite(a)), a, copy=copy)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "[conda-env-path]/lib/python3.11/site-packages/numpy/ma/core.py", line 1942, in masked_where
result.mask = _shrink_mask(cond)
^^^^^^^^^^^
File "[conda-env-path]/lib/python3.11/site-packages/numpy/ma/core.py", line 3516, in mask
self.__setmask__(value)
File "[conda-env-path]/lib/python3.11/site-packages/numpy/ma/core.py", line 3462, in __setmask__
current_mask.flat = mask
^^^^^^^^^^^^^^^^^
ValueError: array is read-only
Expected outcome
No error
Additional information
The code above runs fine with numpy v1.23, although the output from broadcast_to
was already read-only at that version. From numpy release notes, this looks like the likely reason for the change:
https://numpy.org/doc/stable/release/1.24.0-notes.html#masked-invalid-now-modifies-the-mask-in-place
Aside from the new error, if a user passes a masked array that has nans or infs at the unmasked points, we are modifying their input array with the call to masked_invalid
.
I guess we just need to take a copy somewhere?
Operating system
RHEL7
Matplotlib Version
3.7.1
Matplotlib Backend
QtAgg
Python version
3.11.3
Jupyter version
N/A
Installation
conda