Skip to content

Make _request_autoscale_view more generalizable to 3D. #21516

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 1 commit into from
Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
18 changes: 11 additions & 7 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"],
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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)
Expand Down
68 changes: 35 additions & 33 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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):
"""
Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand Down Expand Up @@ -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
Expand All @@ -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):
"""
Expand Down Expand Up @@ -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.
Expand All @@ -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()
Comment on lines +3344 to +3346
Copy link
Member

Choose a reason for hiding this comment

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

Can you join self._get_axis_map().items() as the loop iteration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can, but you don't save a line, and giving a name to the second item of the tuple (the Axis) returned by _get_axis_map().items() is a bit awkward as axis is already the string there...

loc.set_params(**kwargs)
self._request_autoscale_view(name, tight=tight)
self.stale = True

def tick_params(self, axis='both', **kwargs):
Expand Down
62 changes: 7 additions & 55 deletions lib/mpl_toolkits/mplot3d/axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand All @@ -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):
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down