Skip to content

Commit 38d92b2

Browse files
authored
Merge pull request #21516 from anntzer/rav
Make _request_autoscale_view more generalizable to 3D.
2 parents cb483fc + e223f30 commit 38d92b2

File tree

3 files changed

+53
-95
lines changed

3 files changed

+53
-95
lines changed

lib/matplotlib/axes/_axes.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,8 @@ def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
736736
trans = self.get_yaxis_transform(which='grid')
737737
l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs)
738738
self.add_line(l)
739-
self._request_autoscale_view(scalex=False, scaley=scaley)
739+
if scaley:
740+
self._request_autoscale_view("y")
740741
return l
741742

742743
@docstring.dedent_interpd
@@ -803,7 +804,8 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
803804
trans = self.get_xaxis_transform(which='grid')
804805
l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs)
805806
self.add_line(l)
806-
self._request_autoscale_view(scalex=scalex, scaley=False)
807+
if scalex:
808+
self._request_autoscale_view("x")
807809
return l
808810

809811
@staticmethod
@@ -933,7 +935,7 @@ def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
933935
p = mpatches.Polygon(verts, **kwargs)
934936
p.set_transform(self.get_yaxis_transform(which="grid"))
935937
self.add_patch(p)
936-
self._request_autoscale_view(scalex=False)
938+
self._request_autoscale_view("y")
937939
return p
938940

939941
@docstring.dedent_interpd
@@ -990,7 +992,7 @@ def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
990992
p.set_transform(self.get_xaxis_transform(which="grid"))
991993
p.get_path()._interpolation_steps = 100
992994
self.add_patch(p)
993-
self._request_autoscale_view(scaley=False)
995+
self._request_autoscale_view("x")
994996
return p
995997

996998
@_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"],
@@ -1632,7 +1634,10 @@ def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs):
16321634
lines = [*self._get_lines(*args, data=data, **kwargs)]
16331635
for line in lines:
16341636
self.add_line(line)
1635-
self._request_autoscale_view(scalex=scalex, scaley=scaley)
1637+
if scalex:
1638+
self._request_autoscale_view("x")
1639+
if scaley:
1640+
self._request_autoscale_view("y")
16361641
return lines
16371642

16381643
@_preprocess_data(replace_names=["x", "y"], label_namer="y")
@@ -4086,8 +4091,7 @@ def do_patch(xs, ys, **kwargs):
40864091
axis.set_major_formatter(formatter)
40874092
formatter.seq = [*formatter.seq, *datalabels]
40884093

4089-
self._request_autoscale_view(
4090-
scalex=self._autoscaleXon, scaley=self._autoscaleYon)
4094+
self._request_autoscale_view()
40914095

40924096
return dict(whiskers=whiskers, caps=caps, boxes=boxes,
40934097
medians=medians, fliers=fliers, means=means)

lib/matplotlib/axes/_base.py

+35-33
Original file line numberDiff line numberDiff line change
@@ -779,24 +779,26 @@ def viewLim(self):
779779
self._unstale_viewLim()
780780
return self._viewLim
781781

782-
# API could be better, right now this is just to match the old calls to
783-
# autoscale_view() after each plotting method.
784-
def _request_autoscale_view(self, tight=None, **kwargs):
785-
# kwargs are "scalex", "scaley" (& "scalez" for 3D) and default to True
786-
want_scale = {name: True for name in self._axis_names}
787-
for k, v in kwargs.items(): # Validate args before changing anything.
788-
if k.startswith("scale"):
789-
name = k[5:]
790-
if name in want_scale:
791-
want_scale[name] = v
792-
continue
793-
raise TypeError(
794-
f"_request_autoscale_view() got an unexpected argument {k!r}")
782+
def _request_autoscale_view(self, axis="all", tight=None):
783+
"""
784+
Mark a single axis, or all of them, as stale wrt. autoscaling.
785+
786+
No computation is performed until the next autoscaling; thus, separate
787+
calls to control individual axises incur negligible performance cost.
788+
789+
Parameters
790+
----------
791+
axis : str, default: "all"
792+
Either an element of ``self._axis_names``, or "all".
793+
tight : bool or None, default: None
794+
"""
795+
axis_names = _api.check_getitem(
796+
{**{k: [k] for k in self._axis_names}, "all": self._axis_names},
797+
axis=axis)
798+
for name in axis_names:
799+
self._stale_viewlims[name] = True
795800
if tight is not None:
796801
self._tight = tight
797-
for k, v in want_scale.items():
798-
if v:
799-
self._stale_viewlims[k] = True # Else keep old state.
800802

801803
def _set_lim_and_transforms(self):
802804
"""
@@ -2424,8 +2426,7 @@ def _unit_change_handler(self, axis_name, event=None):
24242426
for line in self.lines:
24252427
line.recache_always()
24262428
self.relim()
2427-
self._request_autoscale_view(scalex=(axis_name == "x"),
2428-
scaley=(axis_name == "y"))
2429+
self._request_autoscale_view(axis_name)
24292430

24302431
def relim(self, visible_only=False):
24312432
"""
@@ -2632,7 +2633,7 @@ def set_xmargin(self, m):
26322633
if m <= -0.5:
26332634
raise ValueError("margin must be greater than -0.5")
26342635
self._xmargin = m
2635-
self._request_autoscale_view(scalex=True, scaley=False)
2636+
self._request_autoscale_view("x")
26362637
self.stale = True
26372638

26382639
def set_ymargin(self, m):
@@ -2654,7 +2655,7 @@ def set_ymargin(self, m):
26542655
if m <= -0.5:
26552656
raise ValueError("margin must be greater than -0.5")
26562657
self._ymargin = m
2657-
self._request_autoscale_view(scalex=False, scaley=True)
2658+
self._request_autoscale_view("y")
26582659
self.stale = True
26592660

26602661
def margins(self, *margins, x=None, y=None, tight=True):
@@ -2771,7 +2772,8 @@ def autoscale(self, enable=True, axis='both', tight=None):
27712772
True turns autoscaling on, False turns it off.
27722773
None leaves the autoscaling state unchanged.
27732774
axis : {'both', 'x', 'y'}, default: 'both'
2774-
Which axis to operate on.
2775+
The axis on which to operate. (For 3D axes, *axis* can also be set
2776+
to 'z', and 'both' refers to all three axes.)
27752777
tight : bool or None, default: None
27762778
If True, first set the margins to zero. Then, this argument is
27772779
forwarded to `autoscale_view` (regardless of its value); see the
@@ -2793,7 +2795,10 @@ def autoscale(self, enable=True, axis='both', tight=None):
27932795
self._xmargin = 0
27942796
if tight and scaley:
27952797
self._ymargin = 0
2796-
self._request_autoscale_view(tight=tight, scalex=scalex, scaley=scaley)
2798+
if scalex:
2799+
self._request_autoscale_view("x", tight=tight)
2800+
if scaley:
2801+
self._request_autoscale_view("y", tight=tight)
27972802

27982803
def autoscale_view(self, tight=None, scalex=True, scaley=True):
27992804
"""
@@ -3309,8 +3314,8 @@ def locator_params(self, axis='both', tight=None, **kwargs):
33093314
Parameters
33103315
----------
33113316
axis : {'both', 'x', 'y'}, default: 'both'
3312-
The axis on which to operate.
3313-
3317+
The axis on which to operate. (For 3D axes, *axis* can also be
3318+
set to 'z', and 'both' refers to all three axes.)
33143319
tight : bool or None, optional
33153320
Parameter passed to `~.Axes.autoscale_view`.
33163321
Default is None, for no change.
@@ -3332,15 +3337,12 @@ def locator_params(self, axis='both', tight=None, **kwargs):
33323337
ax.locator_params(tight=True, nbins=4)
33333338
33343339
"""
3335-
_api.check_in_list(['x', 'y', 'both'], axis=axis)
3336-
update_x = axis in ['x', 'both']
3337-
update_y = axis in ['y', 'both']
3338-
if update_x:
3339-
self.xaxis.get_major_locator().set_params(**kwargs)
3340-
if update_y:
3341-
self.yaxis.get_major_locator().set_params(**kwargs)
3342-
self._request_autoscale_view(tight=tight,
3343-
scalex=update_x, scaley=update_y)
3340+
_api.check_in_list([*self._axis_names, "both"], axis=axis)
3341+
for name in self._axis_names:
3342+
if axis in [name, "both"]:
3343+
loc = self._get_axis_map()[name].get_major_locator()
3344+
loc.set_params(**kwargs)
3345+
self._request_autoscale_view(name, tight=tight)
33443346
self.stale = True
33453347

33463348
def tick_params(self, axis='both', **kwargs):

lib/mpl_toolkits/mplot3d/axes3d.py

+7-55
Original file line numberDiff line numberDiff line change
@@ -486,17 +486,6 @@ def get_axis_position(self):
486486
zhigh = tc[0][2] > tc[2][2]
487487
return xhigh, yhigh, zhigh
488488

489-
def _unit_change_handler(self, axis_name, event=None):
490-
# docstring inherited
491-
if event is None: # Allow connecting `self._unit_change_handler(name)`
492-
return functools.partial(
493-
self._unit_change_handler, axis_name, event=object())
494-
_api.check_in_list(self._get_axis_map(), axis_name=axis_name)
495-
self.relim()
496-
self._request_autoscale_view(scalex=(axis_name == "x"),
497-
scaley=(axis_name == "y"),
498-
scalez=(axis_name == "z"))
499-
500489
def update_datalim(self, xys, **kwargs):
501490
pass
502491

@@ -524,24 +513,6 @@ def set_autoscalez_on(self, b):
524513
"""
525514
self._autoscaleZon = b
526515

527-
def set_xmargin(self, m):
528-
# docstring inherited
529-
scalez = self._stale_viewlims["z"]
530-
super().set_xmargin(m)
531-
# Superclass is 2D and will call _request_autoscale_view with defaults
532-
# for unknown Axis, which would be scalez=True, but it shouldn't be for
533-
# this call, so restore it.
534-
self._stale_viewlims["z"] = scalez
535-
536-
def set_ymargin(self, m):
537-
# docstring inherited
538-
scalez = self._stale_viewlims["z"]
539-
super().set_ymargin(m)
540-
# Superclass is 2D and will call _request_autoscale_view with defaults
541-
# for unknown Axis, which would be scalez=True, but it shouldn't be for
542-
# this call, so restore it.
543-
self._stale_viewlims["z"] = scalez
544-
545516
def set_zmargin(self, m):
546517
"""
547518
Set padding of Z data limits prior to autoscaling.
@@ -561,7 +532,7 @@ def set_zmargin(self, m):
561532
if m <= -0.5:
562533
raise ValueError("margin must be greater than -0.5")
563534
self._zmargin = m
564-
self._request_autoscale_view(scalex=False, scaley=False, scalez=True)
535+
self._request_autoscale_view("z")
565536
self.stale = True
566537

567538
def margins(self, *margins, x=None, y=None, z=None, tight=True):
@@ -655,8 +626,12 @@ def autoscale(self, enable=True, axis='both', tight=None):
655626
self._autoscaleZon = scalez = bool(enable)
656627
else:
657628
scalez = False
658-
self._request_autoscale_view(tight=tight, scalex=scalex, scaley=scaley,
659-
scalez=scalez)
629+
if scalex:
630+
self._request_autoscale_view("x", tight=tight)
631+
if scaley:
632+
self._request_autoscale_view("y", tight=tight)
633+
if scalez:
634+
self._request_autoscale_view("z", tight=tight)
660635

661636
def auto_scale_xyz(self, X, Y, Z=None, had_data=None):
662637
# This updates the bounding boxes as to keep a record as to what the
@@ -1391,29 +1366,6 @@ def grid(self, visible=True, **kwargs):
13911366
self._draw_grid = visible
13921367
self.stale = True
13931368

1394-
def locator_params(self, axis='both', tight=None, **kwargs):
1395-
"""
1396-
Convenience method for controlling tick locators.
1397-
1398-
See :meth:`matplotlib.axes.Axes.locator_params` for full
1399-
documentation. Note that this is for Axes3D objects,
1400-
therefore, setting *axis* to 'both' will result in the
1401-
parameters being set for all three axes. Also, *axis*
1402-
can also take a value of 'z' to apply parameters to the
1403-
z axis.
1404-
"""
1405-
_x = axis in ['x', 'both']
1406-
_y = axis in ['y', 'both']
1407-
_z = axis in ['z', 'both']
1408-
if _x:
1409-
self.xaxis.get_major_locator().set_params(**kwargs)
1410-
if _y:
1411-
self.yaxis.get_major_locator().set_params(**kwargs)
1412-
if _z:
1413-
self.zaxis.get_major_locator().set_params(**kwargs)
1414-
self._request_autoscale_view(tight=tight, scalex=_x, scaley=_y,
1415-
scalez=_z)
1416-
14171369
def tick_params(self, axis='both', **kwargs):
14181370
"""
14191371
Convenience method for changing the appearance of ticks and

0 commit comments

Comments
 (0)