Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d06a3df

Browse filesBrowse files
authored
ENH: allow title autopositioning to be turned off (#17127)
* ENH: allow title autopositioning to be turned off * DOC
1 parent e39c67b commit d06a3df
Copy full SHA for d06a3df

File tree

Expand file treeCollapse file tree

11 files changed

+92
-30
lines changed
Filter options
Expand file treeCollapse file tree

11 files changed

+92
-30
lines changed
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
`~.axes.Axes.set_title` gains a y keyword argument to control auto positioning
2+
------------------------------------------------------------------------------
3+
`~.axes.Axes.set_title` tries to auto-position the title to avoid any
4+
decorators on the top x-axis. This is not always desirable so now
5+
*y* is an explicit keyword argument of `~.axes.Axes.set_title`. It
6+
defaults to *None* which means to use auto-positioning. If a value is
7+
supplied (i.e. the pre-3.0 default was ``y=1.0``) then auto-positioning is
8+
turned off. This can also be set with the new rcParameter :rc:`axes.titley`.

‎examples/text_labels_and_annotations/titles_demo.py

Copy file name to clipboardExpand all lines: examples/text_labels_and_annotations/titles_demo.py
+45-4Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""
2-
===========
3-
Titles Demo
4-
===========
2+
=================
3+
Title positioning
4+
=================
55
6-
matplotlib can display plot titles centered, flush with the left side of
6+
Matplotlib can display plot titles centered, flush with the left side of
77
a set of axes, and flush with the right side of a set of axes.
88
99
"""
@@ -16,3 +16,44 @@
1616
plt.title('Right Title', loc='right')
1717

1818
plt.show()
19+
20+
###########################################################################
21+
# The vertical position is automatically chosen to avoid decorations
22+
# (i.e. labels and ticks) on the topmost x-axis:
23+
24+
fig, axs = plt.subplots(1, 2, constrained_layout=True)
25+
26+
ax = axs[0]
27+
ax.plot(range(10))
28+
ax.xaxis.set_label_position('top')
29+
ax.set_xlabel('X-label')
30+
ax.set_title('Center Title')
31+
32+
ax = axs[1]
33+
ax.plot(range(10))
34+
ax.xaxis.set_label_position('top')
35+
ax.xaxis.tick_top()
36+
ax.set_xlabel('X-label')
37+
ax.set_title('Center Title')
38+
plt.show()
39+
40+
###########################################################################
41+
# Automatic positioning can be turned off by manually specifying the
42+
# *y* kwarg for the title or setting :rc:`axes.titley` in the rcParams.
43+
44+
fig, axs = plt.subplots(1, 2, constrained_layout=True)
45+
46+
ax = axs[0]
47+
ax.plot(range(10))
48+
ax.xaxis.set_label_position('top')
49+
ax.set_xlabel('X-label')
50+
ax.set_title('Manual y', y=1.0, pad=-14)
51+
52+
plt.rcParams['axes.titley'] = 1.0 # y is in axes-relative co-ordinates.
53+
plt.rcParams['axes.titlepad'] = -14 # pad is in points...
54+
ax = axs[1]
55+
ax.plot(range(10))
56+
ax.set_xlabel('X-label')
57+
ax.set_title('rcParam y')
58+
59+
plt.show()

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+15-1Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ def get_title(self, loc="center"):
114114
title = cbook._check_getitem(titles, loc=loc.lower())
115115
return title.get_text()
116116

117-
def set_title(self, label, fontdict=None, loc=None, pad=None, **kwargs):
117+
def set_title(self, label, fontdict=None, loc=None, pad=None, *, y=None,
118+
**kwargs):
118119
"""
119120
Set a title for the axes.
120121
@@ -140,6 +141,11 @@ def set_title(self, label, fontdict=None, loc=None, pad=None, **kwargs):
140141
loc : {'center', 'left', 'right'}, default: :rc:`axes.titlelocation`
141142
Which title to set.
142143
144+
y : float, default: :rc:`axes.titley`
145+
Vertical axes loation for the title (1.0 is the top). If
146+
None (the default), y is determined automatically to avoid
147+
decorators on the axes.
148+
143149
pad : float, default: :rc:`axes.titlepad`
144150
The offset of the title from the top of the axes, in points.
145151
@@ -157,6 +163,14 @@ def set_title(self, label, fontdict=None, loc=None, pad=None, **kwargs):
157163
if loc is None:
158164
loc = rcParams['axes.titlelocation']
159165

166+
if y is None:
167+
y = rcParams['axes.titley']
168+
if y is None:
169+
y = 1.0
170+
else:
171+
self._autotitlepos = False
172+
kwargs['y'] = y
173+
160174
titles = {'left': self._left_title,
161175
'center': self.title,
162176
'right': self._right_title}

‎lib/matplotlib/axes/_base.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_base.py
+10-15Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,19 +1122,26 @@ def cla(self):
11221122
size=mpl.rcParams['axes.titlesize'],
11231123
weight=mpl.rcParams['axes.titleweight'])
11241124

1125+
y = mpl.rcParams['axes.titley']
1126+
if y is None:
1127+
y = 1.0
1128+
self._autotitlepos = True
1129+
else:
1130+
self._autotitlepos = False
1131+
11251132
self.title = mtext.Text(
1126-
x=0.5, y=1.0, text='',
1133+
x=0.5, y=y, text='',
11271134
fontproperties=props,
11281135
verticalalignment='baseline',
11291136
horizontalalignment='center',
11301137
)
11311138
self._left_title = mtext.Text(
1132-
x=0.0, y=1.0, text='',
1139+
x=0.0, y=y, text='',
11331140
fontproperties=props.copy(),
11341141
verticalalignment='baseline',
11351142
horizontalalignment='left', )
11361143
self._right_title = mtext.Text(
1137-
x=1.0, y=1.0, text='',
1144+
x=1.0, y=y, text='',
11381145
fontproperties=props.copy(),
11391146
verticalalignment='baseline',
11401147
horizontalalignment='right',
@@ -1143,8 +1150,6 @@ def cla(self):
11431150
# refactor this out so it can be called in ax.set_title if
11441151
# pad argument used...
11451152
self._set_title_offset_trans(title_offset_points)
1146-
# determine if the title position has been set manually:
1147-
self._autotitlepos = None
11481153

11491154
for _title in (self.title, self._left_title, self._right_title):
11501155
self._set_artist_props(_title)
@@ -2622,16 +2627,6 @@ def _update_title_position(self, renderer):
26222627

26232628
titles = (self.title, self._left_title, self._right_title)
26242629

2625-
if self._autotitlepos is None:
2626-
for title in titles:
2627-
x, y = title.get_position()
2628-
if not np.isclose(y, 1.0):
2629-
self._autotitlepos = False
2630-
_log.debug('not adjusting title pos because a title was '
2631-
'already placed manually: %f', y)
2632-
return
2633-
self._autotitlepos = True
2634-
26352630
for title in titles:
26362631
x, _ = title.get_position()
26372632
# need to start again in case of window resizing

‎lib/matplotlib/mpl-data/stylelib/classic.mplstyle

Copy file name to clipboardExpand all lines: lib/matplotlib/mpl-data/stylelib/classic.mplstyle
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ mathtext.sf : sans\-serif
155155
mathtext.fontset : cm # Should be 'cm' (Computer Modern), 'stix',
156156
# 'stixsans' or 'custom'
157157
mathtext.fallback: cm # Select fallback font from ['cm' (Computer Modern), 'stix'
158-
# 'stixsans'] when a symbol can not be found in one of the
158+
# 'stixsans'] when a symbol can not be found in one of the
159159
# custom math fonts. Select 'None' to not perform fallback
160160
# and replace the missing character by a dummy.
161161

@@ -175,6 +175,7 @@ axes.grid : False # display grid or not
175175
axes.grid.which : major
176176
axes.grid.axis : both
177177
axes.titlesize : large # fontsize of the axes title
178+
axes.titley : 1.0 # at the top, no autopositioning.
178179
axes.titlepad : 5.0 # pad between axes and title in points
179180
axes.titleweight : normal # font weight for axes title
180181
axes.labelsize : medium # fontsize of the x any y labels

‎lib/matplotlib/pyplot.py

Copy file name to clipboardExpand all lines: lib/matplotlib/pyplot.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2931,9 +2931,9 @@ def sci(im):
29312931

29322932
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.
29332933
@_copy_docstring_and_deprecators(Axes.set_title)
2934-
def title(label, fontdict=None, loc=None, pad=None, **kwargs):
2934+
def title(label, fontdict=None, loc=None, pad=None, *, y=None, **kwargs):
29352935
return gca().set_title(
2936-
label, fontdict=fontdict, loc=loc, pad=pad, **kwargs)
2936+
label, fontdict=fontdict, loc=loc, pad=pad, y=y, **kwargs)
29372937

29382938

29392939
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.

‎lib/matplotlib/rcsetup.py

Copy file name to clipboardExpand all lines: lib/matplotlib/rcsetup.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,8 @@ 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.titley': [None, validate_float_or_None], # title location, axes units, None means auto
1223+
'axes.titlepad': [6.0, validate_float], # pad from axes top decoration to title in points
12231224
'axes.grid': [False, validate_bool], # display grid or not
12241225
'axes.grid.which': ['major', ['minor', 'both', 'major']], # set whether the grid is drawn on
12251226
# 'major' 'minor' or 'both' ticks

‎lib/matplotlib/tests/test_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_axes.py
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5522,6 +5522,7 @@ def test_titlesetpos():
55225522

55235523
def test_title_xticks_top():
55245524
# Test that title moves if xticks on top of axes.
5525+
mpl.rcParams['axes.titley'] = None
55255526
fig, ax = plt.subplots()
55265527
ax.xaxis.set_ticks_position('top')
55275528
ax.set_title('xlabel top')
@@ -5531,6 +5532,7 @@ def test_title_xticks_top():
55315532

55325533
def test_title_xticks_top_both():
55335534
# Test that title moves if xticks on top of axes.
5535+
mpl.rcParams['axes.titley'] = None
55345536
fig, ax = plt.subplots()
55355537
ax.tick_params(axis="x",
55365538
bottom=True, top=True, labelbottom=True, labeltop=True)

‎lib/matplotlib/tests/test_text.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_text.py
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ def test_annotation_units(fig_test, fig_ref):
618618
def test_large_subscript_title():
619619
# Remove this line when this test image is regenerated.
620620
plt.rcParams['text.kerning_factor'] = 6
621+
plt.rcParams['axes.titley'] = None
621622

622623
fig, axs = plt.subplots(1, 2, figsize=(9, 2.5), constrained_layout=True)
623624
ax = axs[0]
@@ -626,9 +627,7 @@ def test_large_subscript_title():
626627
ax.set_xticklabels('')
627628

628629
ax = axs[1]
629-
tt = ax.set_title(r'$\sum_{i} x_i$')
630-
x, y = tt.get_position()
631-
tt.set_position((x, 1.01))
630+
tt = ax.set_title(r'$\sum_{i} x_i$', y=1.01)
632631
ax.set_title('Old Way', loc='left')
633632
ax.set_xticklabels('')
634633

‎lib/matplotlib/tests/test_tightlayout.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_tightlayout.py
+2-2Lines changed: 2 additions & 2 deletions
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.9)
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.9)
119119
def test_tight_layout7():
120120
# tight layout with left and right titles
121121
fontsize = 24

‎matplotlibrc.template

Copy file name to clipboardExpand all lines: matplotlibrc.template
+2-1Lines changed: 2 additions & 1 deletion
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,6 +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.titley: None # position title (axes relative units). None implies auto
355356
#axes.titlepad: 6.0 # pad between axes and title in points
356357
#axes.labelsize: medium # fontsize of the x any y labels
357358
#axes.labelpad: 4.0 # space between label and axis

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.