From d6fc866ea9bfc654574c5cd6e8cbf41302a3b7d4 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Sun, 19 Nov 2017 12:00:05 -0800 Subject: [PATCH] ENH: add pad kwarg to set_title --- .../next_whats_new/2017_11_19_title_pad.rst | 7 ++++++ lib/matplotlib/axes/_axes.py | 12 +++++++++- lib/matplotlib/axes/_base.py | 22 ++++++++++++++----- lib/matplotlib/tests/test_axes.py | 16 ++++++++++++++ 4 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 doc/users/next_whats_new/2017_11_19_title_pad.rst diff --git a/doc/users/next_whats_new/2017_11_19_title_pad.rst b/doc/users/next_whats_new/2017_11_19_title_pad.rst new file mode 100644 index 000000000000..be2fedff8c34 --- /dev/null +++ b/doc/users/next_whats_new/2017_11_19_title_pad.rst @@ -0,0 +1,7 @@ +Add *pad* kwarg to ax.set_title +------------------------------- + +The method `axes.set_title` now has a *pad* kwarg, that specifies the +distance from the top of an axes to where the title is drawn. The units +of *pad* is points, and the default is the value of the (already-existing) +``rcParams['axes.titlepad']``. diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index e4ce15ec4dfc..f706db64d159 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -6,6 +6,7 @@ import functools import itertools +import logging import math import warnings @@ -42,6 +43,7 @@ from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer from matplotlib.axes._base import _AxesBase, _process_plot_format +_log = logging.getLogger(__name__) rcParams = matplotlib.rcParams @@ -134,7 +136,8 @@ def get_title(self, loc="center"): raise ValueError("'%s' is not a valid location" % loc) return title.get_text() - def set_title(self, label, fontdict=None, loc="center", **kwargs): + def set_title(self, label, fontdict=None, loc="center", pad=None, + **kwargs): """ Set a title for the axes. @@ -159,6 +162,10 @@ def set_title(self, label, fontdict=None, loc="center", **kwargs): loc : {'center', 'left', 'right'}, str, optional Which title to set, defaults to 'center' + pad : float + The offset of the title from the top of the axes, in points. + Default is ``None`` to use rcParams['axes.titlepad']. + Returns ------- text : :class:`~matplotlib.text.Text` @@ -182,6 +189,9 @@ def set_title(self, label, fontdict=None, loc="center", **kwargs): 'fontweight': rcParams['axes.titleweight'], 'verticalalignment': 'baseline', 'horizontalalignment': loc.lower()} + if pad is None: + pad = rcParams['axes.titlepad'] + self._set_title_offset_trans(float(pad)) title.set_text(label) title.update(default) if fontdict is not None: diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index e43afda4e431..357e26907b1a 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1053,10 +1053,6 @@ def cla(self): size=rcParams['axes.titlesize'], weight=rcParams['axes.titleweight']) - title_offset_points = rcParams['axes.titlepad'] - self.titleOffsetTrans = mtransforms.ScaledTranslation( - 0.0, title_offset_points / 72.0, - self.figure.dpi_scale_trans) self.title = mtext.Text( x=0.5, y=1.0, text='', fontproperties=props, @@ -1074,10 +1070,12 @@ def cla(self): verticalalignment='baseline', horizontalalignment='right', ) + title_offset_points = rcParams['axes.titlepad'] + # refactor this out so it can be called in ax.set_title if + # pad argument used... + self._set_title_offset_trans(title_offset_points) for _title in (self.title, self._left_title, self._right_title): - _title.set_transform(self.transAxes + self.titleOffsetTrans) - _title.set_clip_box(None) self._set_artist_props(_title) # The patch draws the background of the axes. We want this to be below @@ -1134,6 +1132,18 @@ def set_facecolor(self, color): return self.patch.set_facecolor(color) set_fc = set_facecolor + def _set_title_offset_trans(self, title_offset_points): + """ + Set the offset for the title either from rcParams['axes.titlepad'] + or from set_title kwarg ``pad``. + """ + self.titleOffsetTrans = mtransforms.ScaledTranslation( + 0.0, title_offset_points / 72.0, + self.figure.dpi_scale_trans) + for _title in (self.title, self._left_title, self._right_title): + _title.set_transform(self.transAxes + self.titleOffsetTrans) + _title.set_clip_box(None) + def set_prop_cycle(self, *args, **kwargs): """ Set the property cycle for any future plot commands on this Axes. diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 7e26c0f08e4b..e8c4de74bc48 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4917,6 +4917,22 @@ def test_dash_offset(): ax.plot(x, j*y, ls=(j, (10, 10)), lw=5, color='k') +def test_title_pad(): + # check that title padding puts the title in the right + # place... + fig, ax = plt.subplots() + ax.set_title('aardvark', pad=30.) + m = ax.titleOffsetTrans.get_matrix() + assert m[1, -1] == (30. / 72. * fig.dpi) + ax.set_title('aardvark', pad=0.) + m = ax.titleOffsetTrans.get_matrix() + assert m[1, -1] == 0. + # check that it is reverted... + ax.set_title('aardvark', pad=None) + m = ax.titleOffsetTrans.get_matrix() + assert m[1, -1] == (matplotlib.rcParams['axes.titlepad'] / 72. * fig.dpi) + + def test_title_location_roundtrip(): fig, ax = plt.subplots() ax.set_title('aardvark')