diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 91badadf088e..0511b89602fd 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -737,7 +737,8 @@ def axhline(self, y=0, xmin=0, xmax=1, **kwargs): trans = self.get_yaxis_transform(which='grid') l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs) self.add_line(l) - self._request_autoscale_view(scalex=False, scaley=scaley) + if scaley: + self._request_autoscale_view("y") return l @docstring.dedent_interpd @@ -804,7 +805,8 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs): trans = self.get_xaxis_transform(which='grid') l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs) self.add_line(l) - self._request_autoscale_view(scalex=scalex, scaley=False) + if scalex: + self._request_autoscale_view("x") return l @staticmethod @@ -934,7 +936,7 @@ def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs): p = mpatches.Polygon(verts, **kwargs) p.set_transform(self.get_yaxis_transform(which="grid")) self.add_patch(p) - self._request_autoscale_view(scalex=False) + self._request_autoscale_view("y") return p @docstring.dedent_interpd @@ -991,7 +993,7 @@ def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs): p.set_transform(self.get_xaxis_transform(which="grid")) p.get_path()._interpolation_steps = 100 self.add_patch(p) - self._request_autoscale_view(scaley=False) + self._request_autoscale_view("x") return p @_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"], @@ -1627,7 +1629,10 @@ def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs): lines = [*self._get_lines(*args, data=data, **kwargs)] for line in lines: self.add_line(line) - self._request_autoscale_view(scalex=scalex, scaley=scaley) + if scalex: + self._request_autoscale_view("x") + if scaley: + self._request_autoscale_view("y") return lines @_preprocess_data(replace_names=["x", "y"], label_namer="y") @@ -4045,8 +4050,7 @@ def do_patch(xs, ys, **kwargs): axis.set_major_formatter(formatter) formatter.seq = [*formatter.seq, *datalabels] - self._request_autoscale_view( - scalex=self._autoscaleXon, scaley=self._autoscaleYon) + self._request_autoscale_view() return dict(whiskers=whiskers, caps=caps, boxes=boxes, medians=medians, fliers=fliers, means=means) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index ac7dd97e3b5b..3e0d3a04e338 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -781,24 +781,26 @@ def viewLim(self): self._unstale_viewLim() return self._viewLim - # API could be better, right now this is just to match the old calls to - # autoscale_view() after each plotting method. - def _request_autoscale_view(self, tight=None, **kwargs): - # kwargs are "scalex", "scaley" (& "scalez" for 3D) and default to True - want_scale = {name: True for name in self._axis_names} - for k, v in kwargs.items(): # Validate args before changing anything. - if k.startswith("scale"): - name = k[5:] - if name in want_scale: - want_scale[name] = v - continue - raise TypeError( - f"_request_autoscale_view() got an unexpected argument {k!r}") + def _request_autoscale_view(self, axis="all", tight=None): + """ + Mark a single axis, or all of them, as stale wrt. autoscaling. + + No computation is performed until the next autoscaling; thus, separate + calls to control individual axises incur negligible performance cost. + + Parameters + ---------- + axis : str, default: "all" + Either an element of ``self._axis_names``, or "all". + tight : bool or None, default: None + """ + axis_names = _api.check_getitem( + {**{k: [k] for k in self._axis_names}, "all": self._axis_names}, + axis=axis) + for name in axis_names: + self._stale_viewlims[name] = True if tight is not None: self._tight = tight - for k, v in want_scale.items(): - if v: - self._stale_viewlims[k] = True # Else keep old state. def _set_lim_and_transforms(self): """ @@ -2425,8 +2427,7 @@ def _unit_change_handler(self, axis_name, event=None): for line in self.lines: line.recache_always() self.relim() - self._request_autoscale_view(scalex=(axis_name == "x"), - scaley=(axis_name == "y")) + self._request_autoscale_view(axis_name) def relim(self, visible_only=False): """ @@ -2634,7 +2635,7 @@ def set_xmargin(self, m): if m <= -0.5: raise ValueError("margin must be greater than -0.5") self._xmargin = m - self._request_autoscale_view(scalex=True, scaley=False) + self._request_autoscale_view("x") self.stale = True def set_ymargin(self, m): @@ -2657,7 +2658,7 @@ def set_ymargin(self, m): if m <= -0.5: raise ValueError("margin must be greater than -0.5") self._ymargin = m - self._request_autoscale_view(scalex=False, scaley=True) + self._request_autoscale_view("y") self.stale = True def margins(self, *margins, x=None, y=None, tight=True): @@ -2774,7 +2775,8 @@ def autoscale(self, enable=True, axis='both', tight=None): True turns autoscaling on, False turns it off. None leaves the autoscaling state unchanged. axis : {'both', 'x', 'y'}, default: 'both' - Which axis to operate on. + The axis on which to operate. (For 3D axes, *axis* can also be set + to 'z', and 'both' refers to all three axes.) tight : bool or None, default: None If True, first set the margins to zero. Then, this argument is forwarded to `autoscale_view` (regardless of its value); see the @@ -2796,7 +2798,10 @@ def autoscale(self, enable=True, axis='both', tight=None): self._xmargin = 0 if tight and scaley: self._ymargin = 0 - self._request_autoscale_view(tight=tight, scalex=scalex, scaley=scaley) + if scalex: + self._request_autoscale_view("x", tight=tight) + if scaley: + self._request_autoscale_view("y", tight=tight) def autoscale_view(self, tight=None, scalex=True, scaley=True): """ @@ -3312,8 +3317,8 @@ def locator_params(self, axis='both', tight=None, **kwargs): Parameters ---------- axis : {'both', 'x', 'y'}, default: 'both' - The axis on which to operate. - + The axis on which to operate. (For 3D axes, *axis* can also be + set to 'z', and 'both' refers to all three axes.) tight : bool or None, optional Parameter passed to `~.Axes.autoscale_view`. Default is None, for no change. @@ -3335,15 +3340,12 @@ def locator_params(self, axis='both', tight=None, **kwargs): ax.locator_params(tight=True, nbins=4) """ - _api.check_in_list(['x', 'y', 'both'], axis=axis) - update_x = axis in ['x', 'both'] - update_y = axis in ['y', 'both'] - if update_x: - self.xaxis.get_major_locator().set_params(**kwargs) - if update_y: - self.yaxis.get_major_locator().set_params(**kwargs) - self._request_autoscale_view(tight=tight, - scalex=update_x, scaley=update_y) + _api.check_in_list([*self._axis_names, "both"], axis=axis) + for name in self._axis_names: + if axis in [name, "both"]: + loc = self._get_axis_map()[name].get_major_locator() + loc.set_params(**kwargs) + self._request_autoscale_view(name, tight=tight) self.stale = True def tick_params(self, axis='both', **kwargs): diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index a29b075e030d..a9846d4d584e 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -476,17 +476,6 @@ def get_axis_position(self): zhigh = tc[0][2] > tc[2][2] return xhigh, yhigh, zhigh - def _unit_change_handler(self, axis_name, event=None): - # docstring inherited - if event is None: # Allow connecting `self._unit_change_handler(name)` - return functools.partial( - self._unit_change_handler, axis_name, event=object()) - _api.check_in_list(self._get_axis_map(), axis_name=axis_name) - self.relim() - self._request_autoscale_view(scalex=(axis_name == "x"), - scaley=(axis_name == "y"), - scalez=(axis_name == "z")) - def update_datalim(self, xys, **kwargs): pass @@ -514,24 +503,6 @@ def set_autoscalez_on(self, b): """ self._autoscaleZon = b - def set_xmargin(self, m): - # docstring inherited - scalez = self._stale_viewlims["z"] - super().set_xmargin(m) - # Superclass is 2D and will call _request_autoscale_view with defaults - # for unknown Axis, which would be scalez=True, but it shouldn't be for - # this call, so restore it. - self._stale_viewlims["z"] = scalez - - def set_ymargin(self, m): - # docstring inherited - scalez = self._stale_viewlims["z"] - super().set_ymargin(m) - # Superclass is 2D and will call _request_autoscale_view with defaults - # for unknown Axis, which would be scalez=True, but it shouldn't be for - # this call, so restore it. - self._stale_viewlims["z"] = scalez - def set_zmargin(self, m): """ Set padding of Z data limits prior to autoscaling. @@ -544,7 +515,7 @@ def set_zmargin(self, m): if m < 0 or m > 1: raise ValueError("margin must be in range 0 to 1") self._zmargin = m - self._request_autoscale_view(scalex=False, scaley=False, scalez=True) + self._request_autoscale_view("z") self.stale = True def margins(self, *margins, x=None, y=None, z=None, tight=True): @@ -638,8 +609,12 @@ def autoscale(self, enable=True, axis='both', tight=None): self._autoscaleZon = scalez = bool(enable) else: scalez = False - self._request_autoscale_view(tight=tight, scalex=scalex, scaley=scaley, - scalez=scalez) + if scalex: + self._request_autoscale_view("x", tight=tight) + if scaley: + self._request_autoscale_view("y", tight=tight) + if scalez: + self._request_autoscale_view("z", tight=tight) def auto_scale_xyz(self, X, Y, Z=None, had_data=None): # This updates the bounding boxes as to keep a record as to what the @@ -1343,29 +1318,6 @@ def grid(self, visible=True, **kwargs): self._draw_grid = visible self.stale = True - def locator_params(self, axis='both', tight=None, **kwargs): - """ - Convenience method for controlling tick locators. - - See :meth:`matplotlib.axes.Axes.locator_params` for full - documentation. Note that this is for Axes3D objects, - therefore, setting *axis* to 'both' will result in the - parameters being set for all three axes. Also, *axis* - can also take a value of 'z' to apply parameters to the - z axis. - """ - _x = axis in ['x', 'both'] - _y = axis in ['y', 'both'] - _z = axis in ['z', 'both'] - if _x: - self.xaxis.get_major_locator().set_params(**kwargs) - if _y: - self.yaxis.get_major_locator().set_params(**kwargs) - if _z: - self.zaxis.get_major_locator().set_params(**kwargs) - self._request_autoscale_view(tight=tight, scalex=_x, scaley=_y, - scalez=_z) - def tick_params(self, axis='both', **kwargs): """ Convenience method for changing the appearance of ticks and