From 6824811ef4c049cfb2f04c11cd3856f25524cec7 Mon Sep 17 00:00:00 2001 From: Paul Ivanov Date: Mon, 24 Jun 2019 19:41:09 -0700 Subject: [PATCH] Backport PR #14579: Fix inversion of 3d axis. --- lib/matplotlib/axis.py | 97 ++++++++++---------------- lib/mpl_toolkits/mplot3d/axis3d.py | 56 ++++++++------- lib/mpl_toolkits/tests/test_mplot3d.py | 12 ++++ 3 files changed, 82 insertions(+), 83 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 2b701e549881..5cbba5b88d15 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1875,6 +1875,36 @@ def get_minpos(self): raise NotImplementedError() +def _make_getset_interval(method_name, lim_name, attr_name): + """ + Helper to generate ``get_{data,view}_interval`` and + ``set_{data,view}_interval`` implementations. + """ + + def getter(self): + # docstring inherited. + return getattr(getattr(self.axes, lim_name), attr_name) + + def setter(self, vmin, vmax, ignore=False): + # docstring inherited. + if ignore: + setattr(getattr(self.axes, lim_name), attr_name, (vmin, vmax)) + else: + oldmin, oldmax = getter(self) + if oldmin < oldmax: + setter(self, min(vmin, vmax, oldmin), max(vmin, vmax, oldmax), + ignore=True) + else: + setter(self, max(vmin, vmax, oldmax), min(vmin, vmax, oldmin), + ignore=True) + self.stale = True + + getter.__name__ = f"get_{method_name}_interval" + setter.__name__ = f"set_{method_name}_interval" + + return getter, setter + + class XAxis(Axis): __name__ = 'xaxis' axis_name = 'x' @@ -2118,39 +2148,14 @@ def get_ticks_position(self): "default": "default", "unknown": "unknown"}[ self._get_ticks_position()] - def get_view_interval(self): - # docstring inherited - return self.axes.viewLim.intervalx - - def set_view_interval(self, vmin, vmax, ignore=False): - # docstring inherited - if ignore: - self.axes.viewLim.intervalx = vmin, vmax - else: - Vmin, Vmax = self.get_view_interval() - if Vmin < Vmax: - self.axes.viewLim.intervalx = (min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) - else: - self.axes.viewLim.intervalx = (max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) + get_view_interval, set_view_interval = _make_getset_interval( + "view", "viewLim", "intervalx") + get_data_interval, set_data_interval = _make_getset_interval( + "data", "dataLim", "intervalx") def get_minpos(self): return self.axes.dataLim.minposx - def get_data_interval(self): - # docstring inherited - return self.axes.dataLim.intervalx - - def set_data_interval(self, vmin, vmax, ignore=False): - # docstring inherited - if ignore: - self.axes.dataLim.intervalx = vmin, vmax - else: - Vmin, Vmax = self.get_data_interval() - self.axes.dataLim.intervalx = min(vmin, Vmin), max(vmax, Vmax) - self.stale = True - def set_default_intervals(self): # docstring inherited xmin, xmax = 0., 1. @@ -2445,40 +2450,14 @@ def get_ticks_position(self): "default": "default", "unknown": "unknown"}[ self._get_ticks_position()] - def get_view_interval(self): - # docstring inherited - return self.axes.viewLim.intervaly - - def set_view_interval(self, vmin, vmax, ignore=False): - # docstring inherited - if ignore: - self.axes.viewLim.intervaly = vmin, vmax - else: - Vmin, Vmax = self.get_view_interval() - if Vmin < Vmax: - self.axes.viewLim.intervaly = (min(vmin, vmax, Vmin), - max(vmin, vmax, Vmax)) - else: - self.axes.viewLim.intervaly = (max(vmin, vmax, Vmin), - min(vmin, vmax, Vmax)) - self.stale = True + get_view_interval, set_view_interval = _make_getset_interval( + "view", "viewLim", "intervaly") + get_data_interval, set_data_interval = _make_getset_interval( + "data", "dataLim", "intervaly") def get_minpos(self): return self.axes.dataLim.minposy - def get_data_interval(self): - # docstring inherited - return self.axes.dataLim.intervaly - - def set_data_interval(self, vmin, vmax, ignore=False): - # docstring inherited - if ignore: - self.axes.dataLim.intervaly = vmin, vmax - else: - Vmin, Vmax = self.get_data_interval() - self.axes.dataLim.intervaly = min(vmin, Vmin), max(vmax, Vmax) - self.stale = True - def set_default_intervals(self): # docstring inherited ymin, ymax = 0., 1. diff --git a/lib/mpl_toolkits/mplot3d/axis3d.py b/lib/mpl_toolkits/mplot3d/axis3d.py index 6f33d83c1849..ad97515c0a01 100644 --- a/lib/mpl_toolkits/mplot3d/axis3d.py +++ b/lib/mpl_toolkits/mplot3d/axis3d.py @@ -68,9 +68,6 @@ def __init__(self, adir, v_intervalx, d_intervalx, axes, *args, rotate_label=None, **kwargs): # adir identifies which axes this is self.adir = adir - # data and viewing intervals for this direction - self.d_interval = d_intervalx - self.v_interval = v_intervalx # This is a temporary member variable. # Do not depend on this existing in future releases! @@ -109,6 +106,10 @@ def __init__(self, adir, v_intervalx, d_intervalx, axes, *args, }) maxis.XAxis.__init__(self, axes, *args, **kwargs) + + # data and viewing intervals for this direction + self.d_interval = d_intervalx + self.v_interval = v_intervalx self.set_rotate_label(rotate_label) def init3d(self): @@ -426,18 +427,6 @@ def draw(self, renderer): renderer.close_group('axis3d') self.stale = False - def get_view_interval(self): - # docstring inherited - return self.v_interval - - def set_view_interval(self, vmin, vmax, ignore=False): - # docstring inherited - if ignore: - self.v_interval = vmin, vmax - else: - Vmin, Vmax = self.get_view_interval() - self.v_interval = min(vmin, Vmin), max(vmax, Vmax) - # TODO: Get this to work properly when mplot3d supports # the transforms framework. def get_tightbbox(self, renderer): @@ -445,23 +434,42 @@ def get_tightbbox(self, renderer): # doesn't return junk info. return None + @property + def d_interval(self): + return self.get_data_interval() + + @d_interval.setter + def d_interval(self, minmax): + return self.set_data_interval(*minmax) + + @property + def v_interval(self): + return self.get_view_interval() + + @d_interval.setter + def v_interval(self, minmax): + return self.set_view_interval(*minmax) + # Use classes to look at different data limits class XAxis(Axis): - def get_data_interval(self): - # docstring inherited - return self.axes.xy_dataLim.intervalx + get_view_interval, set_view_interval = maxis._make_getset_interval( + "view", "xy_viewLim", "intervalx") + get_data_interval, set_data_interval = maxis._make_getset_interval( + "data", "xy_dataLim", "intervalx") class YAxis(Axis): - def get_data_interval(self): - # docstring inherited - return self.axes.xy_dataLim.intervaly + get_view_interval, set_view_interval = maxis._make_getset_interval( + "view", "xy_viewLim", "intervaly") + get_data_interval, set_data_interval = maxis._make_getset_interval( + "data", "xy_dataLim", "intervaly") class ZAxis(Axis): - def get_data_interval(self): - # docstring inherited - return self.axes.zz_dataLim.intervalx + get_view_interval, set_view_interval = maxis._make_getset_interval( + "view", "zz_viewLim", "intervalx") + get_data_interval, set_data_interval = maxis._make_getset_interval( + "data", "zz_dataLim", "intervalx") diff --git a/lib/mpl_toolkits/tests/test_mplot3d.py b/lib/mpl_toolkits/tests/test_mplot3d.py index 5b62d901fd89..4bfb6f8ffdfc 100644 --- a/lib/mpl_toolkits/tests/test_mplot3d.py +++ b/lib/mpl_toolkits/tests/test_mplot3d.py @@ -851,6 +851,18 @@ def test_line3d_set_get_data_3d(): np.testing.assert_array_equal((x2, y2, z2), line.get_data_3d()) +@check_figures_equal(extensions=["png"]) +def test_inverted(fig_test, fig_ref): + # Plot then invert. + ax = fig_test.add_subplot(projection="3d") + ax.plot([1, 1, 10, 10], [1, 10, 10, 10], [1, 1, 1, 10]) + ax.invert_yaxis() + # Invert then plot. + ax = fig_ref.add_subplot(projection="3d") + ax.invert_yaxis() + ax.plot([1, 1, 10, 10], [1, 10, 10, 10], [1, 1, 1, 10]) + + def test_inverted_cla(): # Github PR #5450. Setting autoscale should reset # axes to be non-inverted. 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