From acfd0163a89f91069c205130590bc9f881696989 Mon Sep 17 00:00:00 2001 From: Ryan May Date: Wed, 16 Aug 2017 21:40:58 -0600 Subject: [PATCH 1/4] 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. --- lib/matplotlib/cbook/__init__.py | 13 ++++++++++++- lib/matplotlib/lines.py | 15 ++++----------- lib/matplotlib/path.py | 15 ++++----------- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index 838081e33f66..36986e1b4210 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -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) + + def _check_1d(x): ''' Converts a sequence of less than 1 dimension, to an array of 1 @@ -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 diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index 256e59c2eb2e..9367eb8fc853 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -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 @@ -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 diff --git a/lib/matplotlib/path.py b/lib/matplotlib/path.py index fcaf191dc04b..54ec0b2fa1fc 100644 --- a/lib/matplotlib/path.py +++ b/lib/matplotlib/path.py @@ -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): @@ -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) @@ -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) From a90064ebac99a8a0f135a2b264de55e7d74dc3e4 Mon Sep 17 00:00:00 2001 From: Ryan May Date: Thu, 17 Aug 2017 11:26:27 -0600 Subject: [PATCH 2/4] ENH: Add test for masked units behavior --- .../test_units/plot_masked_units.png | Bin 0 -> 8955 bytes lib/matplotlib/tests/test_units.py | 42 ++++++++++++------ 2 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_units/plot_masked_units.png diff --git a/lib/matplotlib/tests/baseline_images/test_units/plot_masked_units.png b/lib/matplotlib/tests/baseline_images/test_units/plot_masked_units.png new file mode 100644 index 0000000000000000000000000000000000000000..98a07b2654fe03eecdb03caaa8118480d2404517 GIT binary patch literal 8955 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 wQ#fqjEf!i-1lk|BO${=32j -2) & (data < 2)) + data_masked_units = Quantity(data_masked, 'meters') + + fig, ax = plt.subplots() + ax.plot(data_masked_units) From 6eb96c80d107579c45f43f6912b9ad2530869a9c Mon Sep 17 00:00:00 2001 From: Ryan May Date: Fri, 18 Aug 2017 17:18:06 -0600 Subject: [PATCH 3/4] TST: Add test for pint (and alike) behavior (#8910) This tests that unit libraries that wrap arrays, like pint, work properly. This adds an image test that checks current behavior, which seems to be fully correct. --- .../baseline_images/test_units/plot_pint.png | Bin 0 -> 28590 bytes lib/matplotlib/tests/test_units.py | 42 ++++++++++++++---- 2 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_units/plot_pint.png diff --git a/lib/matplotlib/tests/baseline_images/test_units/plot_pint.png b/lib/matplotlib/tests/baseline_images/test_units/plot_pint.png new file mode 100644 index 0000000000000000000000000000000000000000..f15f81fda6f601c37435623833a2cde724c06d92 GIT binary patch literal 28590 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 Date: Wed, 23 Aug 2017 15:28:05 -0600 Subject: [PATCH 4/4] ENH: Update view limits on units change This adds a independent callback for units changes that both updates the data limits (relim) as well as the view limits (autoscale_view). --- lib/matplotlib/axes/_base.py | 17 +++++++++++++---- lib/matplotlib/tests/test_units.py | 1 - lib/mpl_toolkits/mplot3d/axes3d.py | 19 ++++++++++++++----- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 9cf460407511..eeadfc87a1e0 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -556,12 +556,12 @@ def __init__(self, fig, rect, self.update(kwargs) if self.xaxis is not None: - self._xcid = self.xaxis.callbacks.connect('units finalize', - self.relim) + self._xcid = self.xaxis.callbacks.connect( + 'units finalize', lambda: self._on_units_changed(scalex=True)) if self.yaxis is not None: - self._ycid = self.yaxis.callbacks.connect('units finalize', - self.relim) + self._ycid = self.yaxis.callbacks.connect( + 'units finalize', lambda: self._on_units_changed(scaley=True)) self.tick_params( top=rcParams['xtick.top'] and rcParams['xtick.minor.top'], @@ -1891,6 +1891,15 @@ def add_container(self, container): container.set_remove_method(lambda h: self.containers.remove(h)) return container + def _on_units_changed(self, scalex=False, scaley=False): + """ + Callback for processing changes to axis units. + + Currently forces updates of data limits and view limits. + """ + self.relim() + self.autoscale_view(scalex=scalex, scaley=scaley) + def relim(self, visible_only=False): """ Recompute the data limits based on current artists. If you want to diff --git a/lib/matplotlib/tests/test_units.py b/lib/matplotlib/tests/test_units.py index 2f497e2b923e..f72ac2c60476 100644 --- a/lib/matplotlib/tests/test_units.py +++ b/lib/matplotlib/tests/test_units.py @@ -76,7 +76,6 @@ def convert(value, unit, axis): ax.axvline(Quantity(120, 'minutes'), color='tab:green') ax.yaxis.set_units('inches') ax.xaxis.set_units('seconds') - ax.autoscale_view() assert qc.convert.called assert qc.axisinfo.called diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index f387e5a5582e..4738be075f2f 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -110,13 +110,13 @@ def __init__(self, fig, rect=None, *args, **kwargs): # func used to format z -- fall back on major formatters self.fmt_zdata = None - if zscale is not None : + if zscale is not None: self.set_zscale(zscale) - if self.zaxis is not None : - self._zcid = self.zaxis.callbacks.connect('units finalize', - self.relim) - else : + if self.zaxis is not None: + self._zcid = self.zaxis.callbacks.connect( + 'units finalize', lambda: self._on_units_changed(scalez=True)) + else: self._zcid = None self._ready = 1 @@ -307,6 +307,15 @@ def get_axis_position(self): zhigh = tc[0][2] > tc[2][2] return xhigh, yhigh, zhigh + def _on_units_changed(self, scalex=False, scaley=False, scalez=False): + """ + Callback for processing changes to axis units. + + Currently forces updates of data limits and view limits. + """ + self.relim() + self.autoscale_view(scalex=scalex, scaley=scaley, scalez=scalez) + def update_datalim(self, xys, **kwargs): pass pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy