diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index a2b487da785a..e6293a8db830 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1890,6 +1890,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' @@ -2133,39 +2163,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. @@ -2460,40 +2465,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 5c15751986a1..af862b6787ed 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! @@ -105,6 +102,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): @@ -420,18 +421,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): @@ -439,23 +428,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 cb0ee9069f42..62c2979a5aea 100644 --- a/lib/mpl_toolkits/tests/test_mplot3d.py +++ b/lib/mpl_toolkits/tests/test_mplot3d.py @@ -801,6 +801,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.
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: