From a15bc47816e13ff7383c308441cbea7498ac94b0 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 4 May 2021 22:17:56 +0200 Subject: [PATCH] Fix resetting grid visibility Actually, there were two issues: - 'gridOn' state should always be contained in the _tick_kw settings. This is needed because we support toggling via grid() and thus need to be able to query the state. Therefore, the _tick_kw dicts must be resetted instead of cleared. - grid(some_kwarg=...) i.e. with b=None and keywords must be treated explicitly as b=True as the docs already propose. Closes #20149. --- lib/matplotlib/axis.py | 63 ++++++++++++++++++------------- lib/matplotlib/tests/test_axes.py | 13 +++++++ 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 0d18b5f5ede8..a30cae235e95 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -786,6 +786,18 @@ def get_children(self): return [self.label, self.offsetText, *self.get_major_ticks(), *self.get_minor_ticks()] + def _reset_major_tick_kw(self): + self._major_tick_kw.clear() + self._major_tick_kw['gridOn'] = ( + mpl.rcParams['axes.grid'] and + mpl.rcParams['axes.grid.which'] in ('both', 'major')) + + def _reset_minor_tick_kw(self): + self._minor_tick_kw.clear() + self._minor_tick_kw['gridOn'] = ( + mpl.rcParams['axes.grid'] and + mpl.rcParams['axes.grid.which'] in ('both', 'minor')) + def clear(self): """ Clear the axis. @@ -807,14 +819,8 @@ def clear(self): # Clear the callback registry for this axis, or it may "leak" self.callbacks = cbook.CallbackRegistry() - # whether the grids are on - self._major_tick_kw['gridOn'] = ( - mpl.rcParams['axes.grid'] and - mpl.rcParams['axes.grid.which'] in ('both', 'major')) - self._minor_tick_kw['gridOn'] = ( - mpl.rcParams['axes.grid'] and - mpl.rcParams['axes.grid.which'] in ('both', 'minor')) - + self._reset_major_tick_kw() + self._reset_minor_tick_kw() self.reset_ticks() self.converter = None @@ -861,10 +867,10 @@ def set_tick_params(self, which='major', reset=False, **kw): # future new ticks will automatically get them if reset: if which in ['major', 'both']: - self._major_tick_kw.clear() + self._reset_major_tick_kw() self._major_tick_kw.update(kwtrans) if which in ['minor', 'both']: - self._minor_tick_kw.clear() + self._reset_minor_tick_kw() self._minor_tick_kw.update(kwtrans) self.reset_ticks() else: @@ -1413,35 +1419,40 @@ def grid(self, b=None, which='major', **kwargs): grid(color='r', linestyle='-', linewidth=2) """ - if b is not None: - if 'visible' in kwargs and bool(b) != bool(kwargs['visible']): + TOGGLE = object() + UNSET = object() + visible = kwargs.pop('visible', UNSET) + + if b is None: + if visible is UNSET: + if kwargs: # grid(color='r') + b = True + else: # grid() + b = TOGGLE + else: # grid(visible=v) + b = visible + else: + if visible is not UNSET and bool(b) != bool(visible): + # grid(True, visible=False), grid(False, visible=True) raise ValueError( "'b' and 'visible' specify inconsistent grid visibilities") if kwargs and not b: # something false-like but not None + # grid(0, visible=True) _api.warn_external('First parameter to grid() is false, ' 'but line properties are supplied. The ' 'grid will be enabled.') b = True + which = which.lower() _api.check_in_list(['major', 'minor', 'both'], which=which) gridkw = {'grid_' + item[0]: item[1] for item in kwargs.items()} - if 'grid_visible' in gridkw: - forced_visibility = True - gridkw['gridOn'] = gridkw.pop('grid_visible') - else: - forced_visibility = False - if which in ['minor', 'both']: - if b is None and not forced_visibility: - gridkw['gridOn'] = not self._minor_tick_kw['gridOn'] - elif b is not None: - gridkw['gridOn'] = b + gridkw['gridOn'] = (not self._minor_tick_kw['gridOn'] + if b is TOGGLE else b) self.set_tick_params(which='minor', **gridkw) if which in ['major', 'both']: - if b is None and not forced_visibility: - gridkw['gridOn'] = not self._major_tick_kw['gridOn'] - elif b is not None: - gridkw['gridOn'] = b + gridkw['gridOn'] = (not self._major_tick_kw['gridOn'] + if b is TOGGLE else b) self.set_tick_params(which='major', **gridkw) self.stale = True diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index ec9526c364eb..b793156444fb 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4757,6 +4757,19 @@ def test_grid(): assert not ax.xaxis.majorTicks[0].gridline.get_visible() +def test_reset_grid(): + fig, ax = plt.subplots() + ax.tick_params(reset=True, which='major', labelsize=10) + assert not ax.xaxis.majorTicks[0].gridline.get_visible() + ax.grid(color='red') # enables grid + assert ax.xaxis.majorTicks[0].gridline.get_visible() + + with plt.rc_context({'axes.grid': True}): + ax.clear() + ax.tick_params(reset=True, which='major', labelsize=10) + assert ax.xaxis.majorTicks[0].gridline.get_visible() + + def test_vline_limit(): fig = plt.figure() ax = fig.gca()