Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3d9af3d

Browse files
committed
BUG: Fix weird behavior with mask and units (Fixes #8908)
Refactor many places that check for masked arrays, and fill the masked values with nans, with a helper to accomplish that. In the helper, replace the isinstance check with a attribute check for 'mask'. This allows libraries, like pint, that wrap mask arrays to pass the check and be converted appropriately. Also fix one spot using atleast_1d with _check_1d.
1 parent 5fd199c commit 3d9af3d

File tree

4 files changed

+28
-33
lines changed

4 files changed

+28
-33
lines changed

lib/matplotlib/cbook/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1963,6 +1963,17 @@ def is_math_text(s):
19631963
return even_dollars
19641964

19651965

1966+
def _to_unmasked_float_array(x):
1967+
"""
1968+
Convert a sequence to a float array; if input was a masked array, masked
1969+
values are converted to nans.
1970+
"""
1971+
if hasattr(x, 'mask'):
1972+
return np.ma.asarray(x, float).filled(np.nan)
1973+
else:
1974+
return np.asarray(x, float)
1975+
1976+
19661977
def _check_1d(x):
19671978
'''
19681979
Converts a sequence of less than 1 dimension, to an array of 1
@@ -2249,7 +2260,7 @@ def index_of(y):
22492260
try:
22502261
return y.index.values, y.values
22512262
except AttributeError:
2252-
y = np.atleast_1d(y)
2263+
y = _check_1d(y)
22532264
return np.arange(y.shape[0], dtype=float), y
22542265

22552266

lib/matplotlib/collections.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,8 @@ def get_datalim(self, transData):
186186
offsets = transOffset.transform_non_affine(offsets)
187187
transOffset = transOffset.get_affine()
188188

189-
if isinstance(offsets, np.ma.MaskedArray):
190-
offsets = offsets.filled(np.nan)
191-
# get_path_collection_extents handles nan but not masked arrays
189+
# get_path_collection_extents handles nan but not masked arrays
190+
offsets = cbook._to_unmasked_float_array(offsets)
192191

193192
if len(paths) and len(offsets):
194193
result = mpath.get_path_collection_extents(
@@ -235,10 +234,9 @@ def _prepare_points(self):
235234
# This might have changed an ndarray into a masked array.
236235
transOffset = transOffset.get_affine()
237236

238-
if isinstance(offsets, np.ma.MaskedArray):
239-
offsets = offsets.filled(np.nan)
240-
# Changing from a masked array to nan-filled ndarray
241-
# is probably most efficient at this point.
237+
# Changing from a masked array to nan-filled ndarray
238+
# is probably most efficient at this point.
239+
offsets = cbook._to_unmasked_float_array(offsets)
242240

243241
return transform, transOffset, offsets, paths
244242

@@ -895,9 +893,9 @@ def __init__(self, verts, sizes=None, closed=True, **kwargs):
895893

896894
def set_verts(self, verts, closed=True):
897895
'''This allows one to delay initialization of the vertices.'''
898-
if isinstance(verts, np.ma.MaskedArray):
899-
verts = verts.astype(float).filled(np.nan)
900-
# This is much faster than having Path do it one at a time.
896+
# This is much faster than having Path do it one at a time.
897+
verts = cbook._to_unmasked_float_array(verts)
898+
901899
if closed:
902900
self._paths = []
903901
for xy in verts:

lib/matplotlib/lines.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
from . import artist, colors as mcolors, docstring, rcParams
1717
from .artist import Artist, allow_rasterization
1818
from .cbook import (
19-
iterable, is_numlike, ls_mapper, ls_mapper_r, STEP_LOOKUP_MAP)
19+
_to_unmasked_float_array, iterable, is_numlike, ls_mapper, ls_mapper_r,
20+
STEP_LOOKUP_MAP)
2021
from .markers import MarkerStyle
2122
from .path import Path
2223
from .transforms import Bbox, TransformedPath, IdentityTransform
@@ -648,20 +649,12 @@ def recache_always(self):
648649
def recache(self, always=False):
649650
if always or self._invalidx:
650651
xconv = self.convert_xunits(self._xorig)
651-
if isinstance(self._xorig, np.ma.MaskedArray):
652-
x = np.ma.asarray(xconv, float).filled(np.nan)
653-
else:
654-
x = np.asarray(xconv, float)
655-
x = x.ravel()
652+
x = _to_unmasked_float_array(xconv).ravel()
656653
else:
657654
x = self._x
658655
if always or self._invalidy:
659656
yconv = self.convert_yunits(self._yorig)
660-
if isinstance(self._yorig, np.ma.MaskedArray):
661-
y = np.ma.asarray(yconv, float).filled(np.nan)
662-
else:
663-
y = np.asarray(yconv, float)
664-
y = y.ravel()
657+
y = _to_unmasked_float_array(yconv).ravel()
665658
else:
666659
y = self._y
667660

lib/matplotlib/path.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
import numpy as np
2424

2525
from . import _path, rcParams
26-
from .cbook import simple_linear_interpolation, maxdict
26+
from .cbook import (_to_unmasked_float_array, simple_linear_interpolation,
27+
maxdict)
2728

2829

2930
class Path(object):
@@ -129,11 +130,7 @@ def __init__(self, vertices, codes=None, _interpolation_steps=1,
129130
Makes the path behave in an immutable way and sets the vertices
130131
and codes as read-only arrays.
131132
"""
132-
if isinstance(vertices, np.ma.MaskedArray):
133-
vertices = vertices.astype(float).filled(np.nan)
134-
else:
135-
vertices = np.asarray(vertices, float)
136-
133+
vertices = _to_unmasked_float_array(vertices)
137134
if (vertices.ndim != 2) or (vertices.shape[1] != 2):
138135
msg = "'vertices' must be a 2D list or array with shape Nx2"
139136
raise ValueError(msg)
@@ -185,11 +182,7 @@ def _fast_from_codes_and_verts(cls, verts, codes, internals=None):
185182
"""
186183
internals = internals or {}
187184
pth = cls.__new__(cls)
188-
if isinstance(verts, np.ma.MaskedArray):
189-
verts = verts.astype(float).filled(np.nan)
190-
else:
191-
verts = np.asarray(verts, float)
192-
pth._vertices = verts
185+
pth._vertices = _to_unmasked_float_array(verts)
193186
pth._codes = codes
194187
pth._readonly = internals.pop('readonly', False)
195188
pth.should_simplify = internals.pop('should_simplify', True)

0 commit comments

Comments
 (0)