Skip to content

Commit b5a2198

Browse files
committed
ENH/FIX: Don't auto reposition axes if axes.titlepad not None
Automatic title repositioning is now suppressed if the title padding is set to a non-None value by the user (either in the pad kwarg, or the rcParam axes.titlepad)
1 parent bb75f73 commit b5a2198

File tree

7 files changed

+47
-14
lines changed

7 files changed

+47
-14
lines changed

doc/api/next_api_changes/behaviour.rst

+14-3
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ deprecation warning.
9898
`~.Axes.errorbar` now color cycles when only errorbar color is set
9999
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100100

101-
Previously setting the *ecolor* would turn off automatic color cycling for the plot, leading to the
102-
the lines and markers defaulting to whatever the first color in the color cycle was in the case of
103-
multiple plot calls.
101+
Previously setting the *ecolor* would turn off automatic color cycling for the plot, leading to the
102+
the lines and markers defaulting to whatever the first color in the color cycle was in the case of
103+
multiple plot calls.
104104

105105
`.rcsetup.validate_color_for_prop_cycle` now always raises TypeError for bytes input
106106
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -155,3 +155,14 @@ support for it will be dropped in a future Matplotlib release.
155155
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
156156
Previously, keyword arguments were silently ignored when no positional
157157
arguments were given.
158+
159+
:rc:`axes.titlepad` and *pad* argument of `~.Axes.set_title` now default to ``None``
160+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161+
162+
Since 3.0, Axes titles are automatically repositioned, primarily to avoid
163+
xlabels or xticks at the top of the axes. The user could turn this
164+
off using the optional *y* argument to `~.Axes.set_title`). However, that
165+
made it impossible to manually set the *pad* argument; Now *pad* defaults to
166+
``None`` and the rcParam :rc:`axes.titlepad` defaults to ``None``, which will
167+
allow automatic title placement. However, if these are set to a float, then
168+
the automatic placement of the title is turned off.

lib/matplotlib/axes/_axes.py

+6
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,14 @@ def set_title(self, label, fontdict=None, loc=None, pad=None, **kwargs):
169169
titlecolor = rcParams['axes.titlecolor']
170170
if not cbook._str_lower_equal(titlecolor, 'auto'):
171171
default["color"] = titlecolor
172+
172173
if pad is None:
173174
pad = rcParams['axes.titlepad']
175+
if pad is not None:
176+
self._autotitlepos = False
177+
else:
178+
pad = 6 # default.
179+
174180
self._set_title_offset_trans(float(pad))
175181
title.set_text(label)
176182
title.update(default)

lib/matplotlib/axes/_base.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -1061,11 +1061,9 @@ def cla(self):
10611061
verticalalignment='baseline',
10621062
horizontalalignment='right',
10631063
)
1064-
title_offset_points = mpl.rcParams['axes.titlepad']
1065-
# refactor this out so it can be called in ax.set_title if
1066-
# pad argument used...
1067-
self._set_title_offset_trans(title_offset_points)
1068-
# determine if the title position has been set manually:
1064+
# this needs to be called in case cla is not called on
1065+
# axes later...
1066+
self._set_title_offset_trans(mpl.rcParams['axes.titlepad'])
10691067
self._autotitlepos = None
10701068

10711069
for _title in (self.title, self._left_title, self._right_title):
@@ -1123,6 +1121,9 @@ def _set_title_offset_trans(self, title_offset_points):
11231121
Set the offset for the title either from :rc:`axes.titlepad`
11241122
or from set_title kwarg ``pad``.
11251123
"""
1124+
if title_offset_points is None:
1125+
# dummy default in case cla hasn't been called.
1126+
title_offset_points = 0
11261127
self.titleOffsetTrans = mtransforms.ScaledTranslation(
11271128
0.0, title_offset_points / 72,
11281129
self.figure.dpi_scale_trans)
@@ -2565,7 +2566,7 @@ def _update_title_position(self, renderer):
25652566
'already placed manually: %f', y)
25662567
return
25672568
self._autotitlepos = True
2568-
2569+
25692570
for title in titles:
25702571
x, _ = title.get_position()
25712572
# need to start again in case of window resizing

lib/matplotlib/rcsetup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ def _convert_validator_spec(key, conv):
12191219
'axes.titlelocation': ['center', ['left', 'center', 'right']], # alignment of axes title
12201220
'axes.titleweight': ['normal', validate_fontweight], # font weight of axes title
12211221
'axes.titlecolor': ['auto', validate_color_or_auto], # font color of axes title
1222-
'axes.titlepad': [6.0, validate_float], # pad from axes top to title in points
1222+
'axes.titlepad': [None, validate_float_or_None], # pad from axes top to title in points; None means allow auto position of title
12231223
'axes.grid': [False, validate_bool], # display grid or not
12241224
'axes.grid.which': ['major', ['minor', 'both', 'major']], # set whether the grid is drawn on
12251225
# 'major' 'minor' or 'both' ticks

lib/matplotlib/tests/test_axes.py

+15
Original file line numberDiff line numberDiff line change
@@ -5523,6 +5523,8 @@ def test_titlesetpos():
55235523
def test_title_xticks_top():
55245524
# Test that title moves if xticks on top of axes.
55255525
fig, ax = plt.subplots()
5526+
# set to the new default (from 5, which will suppress title reposition)
5527+
mpl.rcParams['axes.titlepad'] = None
55265528
ax.xaxis.set_ticks_position('top')
55275529
ax.set_title('xlabel top')
55285530
fig.canvas.draw()
@@ -5532,13 +5534,26 @@ def test_title_xticks_top():
55325534
def test_title_xticks_top_both():
55335535
# Test that title moves if xticks on top of axes.
55345536
fig, ax = plt.subplots()
5537+
# set to the new default (from 5, which will suppress title reposition)
5538+
mpl.rcParams['axes.titlepad'] = None
55355539
ax.tick_params(axis="x",
55365540
bottom=True, top=True, labelbottom=True, labeltop=True)
55375541
ax.set_title('xlabel top')
55385542
fig.canvas.draw()
55395543
assert ax.title.get_position()[1] > 1.04
55405544

55415545

5546+
def test_title_noauto_pad():
5547+
# test that if we pad, then the title does not autopos
5548+
5549+
fig, ax = plt.subplots()
5550+
ax.set_title(f"Title 1", pad=-20)
5551+
ax.tick_params(axis="x",
5552+
bottom=True, top=True, labelbottom=True, labeltop=True)
5553+
fig.canvas.draw()
5554+
assert ax.title.get_position()[1] == 1.0
5555+
5556+
55425557
def test_offset_label_color():
55435558
# Tests issue 6440
55445559
fig = plt.figure()

lib/matplotlib/tests/test_tightlayout.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def example_plot(ax, fontsize=12):
1919
ax.set_title('Title', fontsize=fontsize)
2020

2121

22-
@image_comparison(['tight_layout1'])
22+
@image_comparison(['tight_layout1'], tol=1.87)
2323
def test_tight_layout1():
2424
"""Test tight_layout for a single subplot."""
2525
fig, ax = plt.subplots()
@@ -115,7 +115,7 @@ def test_tight_layout6():
115115
h_pad=0.45)
116116

117117

118-
@image_comparison(['tight_layout7'])
118+
@image_comparison(['tight_layout7'], tol=1.87)
119119
def test_tight_layout7():
120120
# tight layout with left and right titles
121121
fontsize = 24

matplotlibrc.template

+2-2
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@
326326
#mathtext.sf: sans
327327
#mathtext.tt: monospace
328328
#mathtext.fallback: cm # Select fallback font from ['cm' (Computer Modern), 'stix'
329-
# 'stixsans'] when a symbol can not be found in one of the
329+
# 'stixsans'] when a symbol can not be found in one of the
330330
# custom math fonts. Select 'None' to not perform fallback
331331
# and replace the missing character by a dummy symbol.
332332
#mathtext.default: it # The default font to use for math.
@@ -352,7 +352,7 @@
352352
#axes.titleweight: normal # font weight of title
353353
#axes.titlecolor: auto # color of the axes title, auto falls back to
354354
# text.color as default value
355-
#axes.titlepad: 6.0 # pad between axes and title in points
355+
#axes.titlepad: None # pad between axes and title in points, None means allow automatic positioning
356356
#axes.labelsize: medium # fontsize of the x any y labels
357357
#axes.labelpad: 4.0 # space between label and axis
358358
#axes.labelweight: normal # weight of the x and y labels

0 commit comments

Comments
 (0)