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

Skip to content

BUG: Fix weird behavior with mask and units (Fixes #8908) #9049

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 29, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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.
  • Loading branch information
dopplershift committed Aug 23, 2017
commit acfd0163a89f91069c205130590bc9f881696989
13 changes: 12 additions & 1 deletion lib/matplotlib/cbook/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,17 @@ def is_math_text(s):
return even_dollars


def _to_unmasked_float_array(x):
"""
Convert a sequence to a float array; if input was a masked array, masked
values are converted to nans.
"""
if hasattr(x, 'mask'):
return np.ma.asarray(x, float).filled(np.nan)
else:
return np.asarray(x, float)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is asanyarray better here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing code was always going to a straight-up numpy array, and since that part of the behavior didn't seem to be causing any unit-related problems, it seemed best to be conservative and keep it as asarray.



def _check_1d(x):
'''
Converts a sequence of less than 1 dimension, to an array of 1
Expand Down Expand Up @@ -2252,7 +2263,7 @@ def index_of(y):
try:
return y.index.values, y.values
except AttributeError:
y = np.atleast_1d(y)
y = _check_1d(y)
return np.arange(y.shape[0], dtype=float), y


Expand Down
15 changes: 4 additions & 11 deletions lib/matplotlib/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
from . import artist, colors as mcolors, docstring, rcParams
from .artist import Artist, allow_rasterization
from .cbook import (
iterable, is_numlike, ls_mapper, ls_mapper_r, STEP_LOOKUP_MAP)
_to_unmasked_float_array, iterable, is_numlike, ls_mapper, ls_mapper_r,
STEP_LOOKUP_MAP)
from .markers import MarkerStyle
from .path import Path
from .transforms import Bbox, TransformedPath, IdentityTransform
Expand Down Expand Up @@ -648,20 +649,12 @@ def recache_always(self):
def recache(self, always=False):
if always or self._invalidx:
xconv = self.convert_xunits(self._xorig)
if isinstance(self._xorig, np.ma.MaskedArray):
x = np.ma.asarray(xconv, float).filled(np.nan)
else:
x = np.asarray(xconv, float)
x = x.ravel()
x = _to_unmasked_float_array(xconv).ravel()
else:
x = self._x
if always or self._invalidy:
yconv = self.convert_yunits(self._yorig)
if isinstance(self._yorig, np.ma.MaskedArray):
y = np.ma.asarray(yconv, float).filled(np.nan)
else:
y = np.asarray(yconv, float)
y = y.ravel()
y = _to_unmasked_float_array(yconv).ravel()
else:
y = self._y

Expand Down
15 changes: 4 additions & 11 deletions lib/matplotlib/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
import numpy as np

from . import _path, rcParams
from .cbook import simple_linear_interpolation, maxdict
from .cbook import (_to_unmasked_float_array, simple_linear_interpolation,
maxdict)


class Path(object):
Expand Down Expand Up @@ -129,11 +130,7 @@ def __init__(self, vertices, codes=None, _interpolation_steps=1,
Makes the path behave in an immutable way and sets the vertices
and codes as read-only arrays.
"""
if isinstance(vertices, np.ma.MaskedArray):
vertices = vertices.astype(float).filled(np.nan)
else:
vertices = np.asarray(vertices, float)

vertices = _to_unmasked_float_array(vertices)
if (vertices.ndim != 2) or (vertices.shape[1] != 2):
msg = "'vertices' must be a 2D list or array with shape Nx2"
raise ValueError(msg)
Expand Down Expand Up @@ -185,11 +182,7 @@ def _fast_from_codes_and_verts(cls, verts, codes, internals=None):
"""
internals = internals or {}
pth = cls.__new__(cls)
if isinstance(verts, np.ma.MaskedArray):
verts = verts.astype(float).filled(np.nan)
else:
verts = np.asarray(verts, float)
pth._vertices = verts
pth._vertices = _to_unmasked_float_array(verts)
pth._codes = codes
pth._readonly = internals.pop('readonly', False)
pth.should_simplify = internals.pop('should_simplify', True)
Expand Down