From b20e36c3b47dcac8d863883c9c4cea14504f13e7 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Mon, 30 Nov 2020 20:13:07 +0100 Subject: [PATCH 1/2] Deprecate Tick.apply_tickdir. apply_tickdir doesn't actually update the tick markers on the existing Line2D objects used to draw the ticks (as can be checked with e.g. `plt.gca().xaxis.majorTicks[2].apply_tickdir("inout")`), so it's really mostly an internal helper that cannot be meaningfully called from outside (it needs to cooperate with `_apply_params` to actually work). --- doc/api/axis_api.rst | 2 -- .../deprecations/19655-AL.rst | 5 ++++ lib/matplotlib/axis.py | 23 +++++++++++-------- 3 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 doc/api/next_api_changes/deprecations/19655-AL.rst diff --git a/doc/api/axis_api.rst b/doc/api/axis_api.rst index 4bc9ad0c6e89..9282b69a1744 100644 --- a/doc/api/axis_api.rst +++ b/doc/api/axis_api.rst @@ -266,8 +266,6 @@ specify a matching series of labels. Calling ``set_ticks`` makes a :template: autosummary.rst :nosignatures: - - Tick.apply_tickdir Tick.get_loc Tick.get_pad Tick.get_pad_pixels diff --git a/doc/api/next_api_changes/deprecations/19655-AL.rst b/doc/api/next_api_changes/deprecations/19655-AL.rst new file mode 100644 index 000000000000..aaa8969d1dc3 --- /dev/null +++ b/doc/api/next_api_changes/deprecations/19655-AL.rst @@ -0,0 +1,5 @@ +``Tick.apply_tickdir`` is deprecated +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``apply_tickdir`` didn't actually update the tick markers on the existing +Line2D objects used to draw the ticks; use `.Axis.set_tick_params` instead. diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index c28d185057b8..fa80f83c0c63 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -148,7 +148,7 @@ def __init__(self, axes, loc, label=None, grid_alpha = mpl.rcParams["grid.alpha"] grid_kw = {k[5:]: v for k, v in kw.items()} - self.apply_tickdir(tickdir) + self._apply_tickdir(tickdir) self.tick1line = mlines.Line2D( [], [], @@ -209,15 +209,18 @@ def _set_labelrotation(self, labelrotation): _api.check_in_list(['auto', 'default'], labelrotation=mode) self._labelrotation = (mode, angle) - def apply_tickdir(self, tickdir): + def _apply_tickdir(self, tickdir): """Set tick direction. Valid values are 'out', 'in', 'inout'.""" + # Overriding subclasses should also compute _tickmarkers here. if tickdir is None: tickdir = mpl.rcParams[f'{self.__name__}.direction'] _api.check_in_list(['in', 'out', 'inout'], tickdir=tickdir) self._tickdir = tickdir self._pad = self._base_pad + self.get_tick_padding() self.stale = True - # Subclass overrides should compute _tickmarkers as appropriate here. + + apply_tickdir = _api.deprecate_privatize_attribute( + "3.5", alternative="axis.set_tick_params") def get_tickdir(self): return self._tickdir @@ -363,15 +366,15 @@ def _apply_params(self, **kw): # convenient to leave it here. self._width = kw.pop('width', self._width) self._base_pad = kw.pop('pad', self._base_pad) - # apply_tickdir uses _size and _base_pad to make _pad, + # _apply_tickdir uses _size and _base_pad to make _pad, # and also makes _tickmarkers. - self.apply_tickdir(kw.pop('tickdir', self._tickdir)) + self._apply_tickdir(kw.pop('tickdir', self._tickdir)) self.tick1line.set_marker(self._tickmarkers[0]) self.tick2line.set_marker(self._tickmarkers[1]) for line in (self.tick1line, self.tick2line): line.set_markersize(self._size) line.set_markeredgewidth(self._width) - # _get_text1_transform uses _pad from apply_tickdir. + # _get_text1_transform uses _pad from _apply_tickdir. trans = self._get_text1_transform()[0] self.label1.set_transform(trans) trans = self._get_text2_transform()[0] @@ -451,9 +454,9 @@ def _get_text1_transform(self): def _get_text2_transform(self): return self.axes.get_xaxis_text2_transform(self._pad) - def apply_tickdir(self, tickdir): + def _apply_tickdir(self, tickdir): # docstring inherited - super().apply_tickdir(tickdir) + super()._apply_tickdir(tickdir) self._tickmarkers = { 'out': (mlines.TICKDOWN, mlines.TICKUP), 'in': (mlines.TICKUP, mlines.TICKDOWN), @@ -518,9 +521,9 @@ def _get_text1_transform(self): def _get_text2_transform(self): return self.axes.get_yaxis_text2_transform(self._pad) - def apply_tickdir(self, tickdir): + def _apply_tickdir(self, tickdir): # docstring inherited - super().apply_tickdir(tickdir) + super()._apply_tickdir(tickdir) self._tickmarkers = { 'out': (mlines.TICKLEFT, mlines.TICKRIGHT), 'in': (mlines.TICKRIGHT, mlines.TICKLEFT), From 48b2e6521e2a03b837817007b3870c12e933353e Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sun, 7 Mar 2021 19:47:38 +0100 Subject: [PATCH 2/2] Further simplify apply_tickdir logic by removing _tickmarkers. ... which is otherwise just an attribute to coordinate between _apply_params and _apply_tickdir. --- lib/matplotlib/axis.py | 63 ++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index fa80f83c0c63..39fa5d40fb97 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -148,8 +148,6 @@ def __init__(self, axes, loc, label=None, grid_alpha = mpl.rcParams["grid.alpha"] grid_kw = {k[5:]: v for k, v in kw.items()} - self._apply_tickdir(tickdir) - self.tick1line = mlines.Line2D( [], [], color=color, linestyle="none", zorder=zorder, visible=tick1On, @@ -174,6 +172,9 @@ def __init__(self, axes, loc, label=None, self.label2 = mtext.Text( np.nan, np.nan, fontsize=labelsize, color=labelcolor, visible=label2On) + + self._apply_tickdir(tickdir) + for meth, attr in [("_get_tick1line", "tick1line"), ("_get_tick2line", "tick2line"), ("_get_gridline", "gridline"), @@ -211,16 +212,20 @@ def _set_labelrotation(self, labelrotation): def _apply_tickdir(self, tickdir): """Set tick direction. Valid values are 'out', 'in', 'inout'.""" - # Overriding subclasses should also compute _tickmarkers here. + # This method is responsible for updating `_pad`, and, in subclasses, + # for setting the tick{1,2}line markers as well. From the user + # perspective this should always be called though _apply_params, which + # further updates ticklabel positions using the new pads. if tickdir is None: tickdir = mpl.rcParams[f'{self.__name__}.direction'] _api.check_in_list(['in', 'out', 'inout'], tickdir=tickdir) self._tickdir = tickdir self._pad = self._base_pad + self.get_tick_padding() - self.stale = True - apply_tickdir = _api.deprecate_privatize_attribute( - "3.5", alternative="axis.set_tick_params") + @_api.deprecated("3.5", alternative="axis.set_tick_params") + def apply_tickdir(self, tickdir): + self._apply_tickdir() + self.stale = True def get_tickdir(self): return self._tickdir @@ -366,11 +371,9 @@ def _apply_params(self, **kw): # convenient to leave it here. self._width = kw.pop('width', self._width) self._base_pad = kw.pop('pad', self._base_pad) - # _apply_tickdir uses _size and _base_pad to make _pad, - # and also makes _tickmarkers. + # _apply_tickdir uses _size and _base_pad to make _pad, and also + # sets the ticklines markers. self._apply_tickdir(kw.pop('tickdir', self._tickdir)) - self.tick1line.set_marker(self._tickmarkers[0]) - self.tick2line.set_marker(self._tickmarkers[1]) for line in (self.tick1line, self.tick2line): line.set_markersize(self._size) line.set_markeredgewidth(self._width) @@ -422,20 +425,13 @@ class XTick(Tick): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # x in data coords, y in axes coords + ax = self.axes self.tick1line.set( - xdata=[0], ydata=[0], - transform=self.axes.get_xaxis_transform(which="tick1"), - marker=self._tickmarkers[0], - ) + data=([0], [0]), transform=ax.get_xaxis_transform("tick1")) self.tick2line.set( - xdata=[0], ydata=[1], - transform=self.axes.get_xaxis_transform(which="tick2"), - marker=self._tickmarkers[1], - ) + data=([0], [1]), transform=ax.get_xaxis_transform("tick2")) self.gridline.set( - xdata=[0, 0], ydata=[0, 1], - transform=self.axes.get_xaxis_transform(which="grid"), - ) + data=([0, 0], [0, 1]), transform=ax.get_xaxis_transform("grid")) # the y loc is 3 points below the min of y axis trans, va, ha = self._get_text1_transform() self.label1.set( @@ -457,12 +453,13 @@ def _get_text2_transform(self): def _apply_tickdir(self, tickdir): # docstring inherited super()._apply_tickdir(tickdir) - self._tickmarkers = { + mark1, mark2 = { 'out': (mlines.TICKDOWN, mlines.TICKUP), 'in': (mlines.TICKUP, mlines.TICKDOWN), 'inout': ('|', '|'), }[self._tickdir] - self.stale = True + self.tick1line.set_marker(mark1) + self.tick2line.set_marker(mark2) def update_position(self, loc): """Set the location of tick in data coords with scalar *loc*.""" @@ -489,20 +486,13 @@ class YTick(Tick): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # x in axes coords, y in data coords + ax = self.axes self.tick1line.set( - xdata=[0], ydata=[0], - transform=self.axes.get_yaxis_transform(which="tick1"), - marker=self._tickmarkers[0], - ) + data=([0], [0]), transform=ax.get_yaxis_transform("tick1")) self.tick2line.set( - xdata=[1], ydata=[0], - transform=self.axes.get_yaxis_transform(which="tick2"), - marker=self._tickmarkers[1], - ) + data=([1], [0]), transform=ax.get_yaxis_transform("tick2")) self.gridline.set( - xdata=[0, 1], ydata=[0, 0], - transform=self.axes.get_yaxis_transform(which="grid"), - ) + data=([0, 1], [0, 0]), transform=ax.get_yaxis_transform("grid")) # the y loc is 3 points below the min of y axis trans, va, ha = self._get_text1_transform() self.label1.set( @@ -524,12 +514,13 @@ def _get_text2_transform(self): def _apply_tickdir(self, tickdir): # docstring inherited super()._apply_tickdir(tickdir) - self._tickmarkers = { + mark1, mark2 = { 'out': (mlines.TICKLEFT, mlines.TICKRIGHT), 'in': (mlines.TICKRIGHT, mlines.TICKLEFT), 'inout': ('_', '_'), }[self._tickdir] - self.stale = True + self.tick1line.set_marker(mark1) + self.tick2line.set_marker(mark2) def update_position(self, loc): """Set the location of tick in data coords with scalar *loc*."""