From 538fb748ba9b2e6615a6c2b22b07603c81e7e233 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Sun, 7 Jan 2018 15:31:34 -1000 Subject: [PATCH 1/3] Handle Tick gridline properties like other Tick properties This is a refactoring for internal and API consistency, so that Axis.set_tick_params can set all Tick properties. It also removes some redundant code involving attributes like isDefault_majloc. --- lib/matplotlib/axis.py | 121 ++++++++++++++++++++++------------------ lib/matplotlib/scale.py | 11 +++- 2 files changed, 74 insertions(+), 58 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 6e40f4138042..6c54af06d268 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -28,6 +28,14 @@ GRIDLINE_INTERPOLATION_STEPS = 180 +# This list is being used for compatibility with Axes.grid, which +# allows all Line2D kwargs. +_line_AI = artist.ArtistInspector(mlines.Line2D) +_line_param_names = _line_AI.get_setters() +_line_param_aliases = [list(d.keys())[0] for d in _line_AI.aliasd.values()] +_gridline_param_names = ['grid_' + name + for name in _line_param_names + _line_param_aliases] + class Tick(artist.Artist): """ @@ -86,6 +94,11 @@ def __init__(self, axes, loc, label, label2On=False, major=True, labelrotation=0, + grid_color=None, + grid_linestyle=None, + grid_linewidth=None, + grid_alpha=None, + **kw # Other Line2D kwargs applied to gridlines. ): """ bbox is the Bound2D bounding box in display coords of the Axes @@ -153,6 +166,17 @@ def __init__(self, axes, loc, label, zorder = mlines.Line2D.zorder self._zorder = zorder + self._grid_color = (rcParams['grid.color'] + if grid_color is None else grid_color) + self._grid_linestyle = (rcParams['grid.linestyle'] + if grid_linestyle is None else grid_linestyle) + self._grid_linewidth = (rcParams['grid.linewidth'] + if grid_linewidth is None else grid_linewidth) + self._grid_alpha = (rcParams['grid.alpha'] + if grid_alpha is None else grid_alpha) + + self._grid_kw = {k[5:]: v for k, v in kw.items()} + self.apply_tickdir(tickdir) self.tick1line = self._get_tick1line() @@ -368,6 +392,14 @@ def _apply_params(self, **kw): v = getattr(self.label1, 'get_' + k)() setattr(self, '_label' + k, v) + grid_list = [k for k in six.iteritems(kw) + if k[0] in _gridline_param_names] + if grid_list: + grid_kw = {k[5:]: v for k, v in grid_list} + self.gridline.set(**grid_kw) + for k, v in six.iteritems(grid_kw): + setattr(self, '_grid_' + k, v) + def update_position(self, loc): 'Set the location of tick in data coords with scalar *loc*' raise NotImplementedError('Derived must override') @@ -469,11 +501,12 @@ def _get_gridline(self): 'Get the default line2D instance' # x in data coords, y in axes coords l = mlines.Line2D(xdata=(0.0, 0.0), ydata=(0, 1.0), - color=rcParams['grid.color'], - linestyle=rcParams['grid.linestyle'], - linewidth=rcParams['grid.linewidth'], - alpha=rcParams['grid.alpha'], - markersize=0) + color=self._grid_color, + linestyle=self._grid_linestyle, + linewidth=self._grid_linewidth, + alpha=self._grid_alpha, + markersize=0, + **self._grid_kw) l.set_transform(self.axes.get_xaxis_transform(which='grid')) l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS self._set_artist_props(l) @@ -592,12 +625,12 @@ def _get_gridline(self): 'Get the default line2D instance' # x in axes coords, y in data coords l = mlines.Line2D(xdata=(0, 1), ydata=(0, 0), - color=rcParams['grid.color'], - linestyle=rcParams['grid.linestyle'], - linewidth=rcParams['grid.linewidth'], - alpha=rcParams['grid.alpha'], - markersize=0) - + color=self._grid_color, + linestyle=self._grid_linestyle, + linewidth=self._grid_linewidth, + alpha=self._grid_alpha, + markersize=0, + **self._grid_kw) l.set_transform(self.axes.get_yaxis_transform(which='grid')) l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS self._set_artist_props(l) @@ -650,13 +683,6 @@ def __init__(self, axes, pickradius=15): artist.Artist.__init__(self) self.set_figure(axes.figure) - # Keep track of setting to the default value, this allows use to know - # if any of the following values is explicitly set by the user, so as - # to not overwrite their settings with any of our 'auto' settings. - self.isDefault_majloc = True - self.isDefault_minloc = True - self.isDefault_majfmt = True - self.isDefault_minfmt = True self.isDefault_label = True self.axes = axes @@ -745,22 +771,10 @@ def get_children(self): def cla(self): 'clear the current axis' - self.set_major_locator(mticker.AutoLocator()) - self.set_major_formatter(mticker.ScalarFormatter()) - self.set_minor_locator(mticker.NullLocator()) - self.set_minor_formatter(mticker.NullFormatter()) - self.set_label_text('') - self._set_artist_props(self.label) + self.label.set_text('') # self.set_label_text would change isDefault_ - # Keep track of setting to the default value, this allows use to know - # if any of the following values is explicitly set by the user, so as - # to not overwrite their settings with any of our 'auto' settings. - self.isDefault_majloc = True - self.isDefault_minloc = True - self.isDefault_majfmt = True - self.isDefault_minfmt = True - self.isDefault_label = True + self._set_scale('linear') # Clear the callback registry for this axis, or it may "leak" self.callbacks = cbook.CallbackRegistry() @@ -771,9 +785,6 @@ def cla(self): self._gridOnMinor = (rcParams['axes.grid'] and rcParams['axes.grid.which'] in ('both', 'minor')) - self.label.set_text('') - self._set_artist_props(self.label) - self.reset_ticks() self.converter = None @@ -782,9 +793,11 @@ def cla(self): self.stale = True def reset_ticks(self): - # build a few default ticks; grow as necessary later; only - # define 1 so properties set on ticks will be copied as they - # grow + """ + Re-initialize the major and minor Tick lists. + + Each list starts with a single fresh Tick. + """ del self.majorTicks[:] del self.minorTicks[:] @@ -793,6 +806,11 @@ def reset_ticks(self): self._lastNumMajorTicks = 1 self._lastNumMinorTicks = 1 + try: + self.set_clip_path(self.axes.patch) + except AttributeError: + pass + def set_tick_params(self, which='major', reset=False, **kw): """ Set appearance parameters for ticks and ticklabels. @@ -810,6 +828,7 @@ def set_tick_params(self, which='major', reset=False, **kw): if reset: d.clear() d.update(kwtrans) + if reset: self.reset_ticks() else: @@ -833,7 +852,8 @@ def _translate_tick_kw(kw, to_init_kw=True): kwkeys1 = ['length', 'direction', 'left', 'bottom', 'right', 'top', 'labelleft', 'labelbottom', 'labelright', 'labeltop', 'labelrotation'] - kwkeys = kwkeys0 + kwkeys1 + kwkeys2 = _gridline_param_names + kwkeys = kwkeys0 + kwkeys1 + kwkeys2 kwtrans = dict() if to_init_kw: if 'length' in kw: @@ -975,7 +995,7 @@ def _update_ticks(self, renderer): """ interval = self.get_view_interval() - tick_tups = list(self.iter_ticks()) + tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator if self._smart_bounds and tick_tups: # handle inverted limits view_low, view_high = sorted(interval) @@ -1401,30 +1421,21 @@ def grid(self, b=None, which='major', **kwargs): if len(kwargs): b = True which = which.lower() + gridkw = {'grid_' + item[0]: item[1] for item in kwargs.items()} if which in ['minor', 'both']: if b is None: self._gridOnMinor = not self._gridOnMinor else: self._gridOnMinor = b - for tick in self.minorTicks: # don't use get_ticks here! - if tick is None: - continue - tick.gridOn = self._gridOnMinor - if len(kwargs): - tick.gridline.update(kwargs) - self._minor_tick_kw['gridOn'] = self._gridOnMinor + self.set_tick_params(which='minor', gridOn=self._gridOnMinor, + **gridkw) if which in ['major', 'both']: if b is None: self._gridOnMajor = not self._gridOnMajor else: self._gridOnMajor = b - for tick in self.majorTicks: # don't use get_ticks here! - if tick is None: - continue - tick.gridOn = self._gridOnMajor - if len(kwargs): - tick.gridline.update(kwargs) - self._major_tick_kw['gridOn'] = self._gridOnMajor + self.set_tick_params(which='major', gridOn=self._gridOnMajor, + **gridkw) self.stale = True def update_units(self, data): @@ -1454,11 +1465,11 @@ def _update_axisinfo(self): check the axis converter for the stored units to see if the axis info needs to be updated """ - if self.converter is None: return info = self.converter.axisinfo(self.units, self) + if info is None: return if info.majloc is not None and \ diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index 1fb0b00edd53..d9026a619212 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -6,10 +6,11 @@ import numpy as np from numpy import ma -from matplotlib import cbook, docstring +from matplotlib import cbook, docstring, rcParams from matplotlib.ticker import ( NullFormatter, ScalarFormatter, LogFormatterSciNotation, LogitFormatter, - NullLocator, LogLocator, AutoLocator, SymmetricalLogLocator, LogitLocator) + NullLocator, LogLocator, AutoLocator, AutoMinorLocator, + SymmetricalLogLocator, LogitLocator) from matplotlib.transforms import Transform, IdentityTransform @@ -71,8 +72,12 @@ def set_default_locators_and_formatters(self, axis): """ axis.set_major_locator(AutoLocator()) axis.set_major_formatter(ScalarFormatter()) - axis.set_minor_locator(NullLocator()) axis.set_minor_formatter(NullFormatter()) + # update the minor locator for x and y axis based on rcParams + if rcParams['xtick.minor.visible']: + axis.set_minor_locator(AutoMinorLocator()) + else: + axis.set_minor_locator(NullLocator()) def get_transform(self): """ From 0100cec5046eef5edc76fd62f6eff2bf34a16d21 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Sun, 7 Jan 2018 16:18:37 -1000 Subject: [PATCH 2/3] Add test for using Axes.tick_params to set gridline properties --- lib/matplotlib/tests/test_axes.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 6f3d513e4fbf..61377cb8f212 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5152,6 +5152,18 @@ def test_axis_set_tick_params_labelsize_labelcolor(): assert axis_1.yaxis.majorTicks[0]._labelcolor == 'red' +def test_axes_tick_params_gridlines(): + # Now treating grid params like other Tick params + ax = plt.subplot() + ax.tick_params(grid_color='b', grid_linewidth=5, grid_alpha=0.5, + grid_linestyle='dashdot') + for axis in ax.xaxis, ax.yaxis: + assert axis.majorTicks[0]._grid_color == 'b' + assert axis.majorTicks[0]._grid_linewidth == 5 + assert axis.majorTicks[0]._grid_alpha == 0.5 + assert axis.majorTicks[0]._grid_linestyle == 'dashdot' + + def test_none_kwargs(): fig, ax = plt.subplots() ln, = ax.plot(range(32), linestyle=None) From ee35e584a67aa1304b54af1a72954ecea04d8197 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Sun, 7 Jan 2018 16:52:51 -1000 Subject: [PATCH 3/3] Add a Whats_new entry, and augment docstrings --- .../2018_01_07_tick_params_gridlines.rst | 8 ++++++++ lib/matplotlib/axes/_base.py | 19 ++++++++++++++++--- lib/matplotlib/axis.py | 2 +- 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 doc/users/next_whats_new/2018_01_07_tick_params_gridlines.rst diff --git a/doc/users/next_whats_new/2018_01_07_tick_params_gridlines.rst b/doc/users/next_whats_new/2018_01_07_tick_params_gridlines.rst new file mode 100644 index 000000000000..b14327d3736b --- /dev/null +++ b/doc/users/next_whats_new/2018_01_07_tick_params_gridlines.rst @@ -0,0 +1,8 @@ +`Axes.tick_params` can set gridline properties +---------------------------------------------- + +`Tick` objects hold gridlines as well as the tick mark and its label. +`Axis.set_tick_params`, `Axes.tick_params` and `pyplot.tick_params` +now have keyword arguments 'grid_color', 'grid_alpha', 'grid_linewidth', +and 'grid_linestyle' for overriding the defaults in `rcParams`: +'grid.color', etc. diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index f7819aaf9fd8..614c943d73d1 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2790,7 +2790,7 @@ def locator_params(self, axis='both', tight=None, **kwargs): self.autoscale_view(tight=tight, scalex=_x, scaley=_y) def tick_params(self, axis='both', **kwargs): - """Change the appearance of ticks and tick labels. + """Change the appearance of ticks, tick labels, and gridlines. Parameters ---------- @@ -2848,16 +2848,29 @@ def tick_params(self, axis='both', **kwargs): labelrotation : float Tick label rotation + grid_color : color + Changes the gridline color to the given mpl color spec. + + grid_alpha : float + Transparency of gridlines: 0 (transparent) to 1 (opaque). + + grid_linewidth : float + Width of gridlines in points. + + grid_linestyle : string + Any valid :class:`~matplotlib.lines.Line2D` line style spec. + Examples -------- Usage :: - ax.tick_params(direction='out', length=6, width=2, colors='r') + ax.tick_params(direction='out', length=6, width=2, colors='r', + grid_color='r', grid_alpha=0.5) This will make all major ticks be red, pointing out of the box, and with dimensions 6 points by 2 points. Tick labels will - also be red. + also be red. Gridlines will be red and translucent. """ if axis in ['x', 'both']: diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 6c54af06d268..ac6bf3425c41 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -813,7 +813,7 @@ def reset_ticks(self): def set_tick_params(self, which='major', reset=False, **kw): """ - Set appearance parameters for ticks and ticklabels. + Set appearance parameters for ticks, ticklabels, and gridlines. For documentation of keyword arguments, see :meth:`matplotlib.axes.Axes.tick_params`. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy