Skip to content

Commit ecf1553

Browse files
committed
Implement align_titles based on align_xlabels
1 parent 394b80d commit ecf1553

File tree

3 files changed

+68
-8
lines changed

3 files changed

+68
-8
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,8 +2985,13 @@ def _update_title_position(self, renderer):
29852985

29862986
titles = (self.title, self._left_title, self._right_title)
29872987

2988-
# Need to check all our twins too, and all the children as well.
2989-
axs = self._twinned_axes.get_siblings(self) + self.child_axes
2988+
# Need to check all our twins too, aligned axes, and all the children
2989+
# as well.
2990+
axs = set()
2991+
axs.update(self.child_axes)
2992+
axs.update(self._twinned_axes.get_siblings(self))
2993+
axs.update(self.figure._align_label_groups['title'].get_siblings(self))
2994+
29902995
for ax in self.child_axes: # Child positions must be updated first.
29912996
locator = ax.get_axes_locator()
29922997
ax.apply_aspect(locator(self, renderer) if locator else None)

lib/matplotlib/figure.py

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,15 @@ def __init__(self, **kwargs):
132132
self._supxlabel = None
133133
self._supylabel = None
134134

135-
# groupers to keep track of x and y labels we want to align.
136-
# see self.align_xlabels and self.align_ylabels and
137-
# axis._get_tick_boxes_siblings
138-
self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper()}
135+
# groupers to keep track of x, y labels and title we want to
136+
# align.
137+
# see self.align_xlabels, self.align_ylabels,
138+
# self.align_titles, and axis._get_tick_boxes_siblings
139+
self._align_label_groups = {
140+
"x": cbook.Grouper(),
141+
"y": cbook.Grouper(),
142+
"title": cbook.Grouper()
143+
}
139144

140145
self._localaxes = [] # track all Axes
141146
self.artists = []
@@ -1293,7 +1298,7 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None,
12931298

12941299
def align_xlabels(self, axs=None):
12951300
"""
1296-
Align the xlabels of subplots in the same subplot column if label
1301+
Align the xlabels of subplots in the same subplot row if label
12971302
alignment is being done automatically (i.e. the label position is
12981303
not manually set).
12991304
@@ -1314,6 +1319,7 @@ def align_xlabels(self, axs=None):
13141319
See Also
13151320
--------
13161321
matplotlib.figure.Figure.align_ylabels
1322+
matplotlib.figure.Figure.align_titles
13171323
matplotlib.figure.Figure.align_labels
13181324
13191325
Notes
@@ -1375,6 +1381,7 @@ def align_ylabels(self, axs=None):
13751381
See Also
13761382
--------
13771383
matplotlib.figure.Figure.align_xlabels
1384+
matplotlib.figure.Figure.align_titles
13781385
matplotlib.figure.Figure.align_labels
13791386
13801387
Notes
@@ -1412,6 +1419,53 @@ def align_ylabels(self, axs=None):
14121419
# grouper for groups of ylabels to align
14131420
self._align_label_groups['y'].join(ax, axc)
14141421

1422+
def align_titles(self, axs=None):
1423+
"""
1424+
Align the titles of subplots in the same subplot row if title
1425+
alignment is being done automatically (i.e. the title position is
1426+
not manually set).
1427+
1428+
Alignment persists for draw events after this is called.
1429+
1430+
Parameters
1431+
----------
1432+
axs : list of `~matplotlib.axes.Axes`
1433+
Optional list of (or ndarray) `~matplotlib.axes.Axes`
1434+
to align the titles.
1435+
Default is to align all Axes on the figure.
1436+
1437+
See Also
1438+
--------
1439+
matplotlib.figure.Figure.align_xlabels
1440+
matplotlib.figure.Figure.align_ylabels
1441+
matplotlib.figure.Figure.align_labels
1442+
1443+
Notes
1444+
-----
1445+
This assumes that ``axs`` are from the same `.GridSpec`, so that
1446+
their `.SubplotSpec` positions correspond to figure positions.
1447+
1448+
Examples
1449+
--------
1450+
Example with titles::
1451+
1452+
fig, axs = plt.subplots(1, 2)
1453+
axs[0].set_aspect('equal')
1454+
axs[0].set_title('Title 0')
1455+
axs[1].set_title('Title 1')
1456+
fig.align_titles()
1457+
"""
1458+
if axs is None:
1459+
axs = self.axes
1460+
axs = [ax for ax in np.ravel(axs) if ax.get_subplotspec() is not None]
1461+
for ax in axs:
1462+
_log.debug(' Working on: %s', ax.get_title())
1463+
rowspan = ax.get_subplotspec().rowspan
1464+
for axc in axs:
1465+
rowspanc = axc.get_subplotspec().rowspan
1466+
if (rowspan.start == rowspanc.start):
1467+
self._align_label_groups['title'].join(ax, axc)
1468+
14151469
def align_labels(self, axs=None):
14161470
"""
14171471
Align the xlabels and ylabels of subplots with the same subplots
@@ -1430,8 +1484,8 @@ def align_labels(self, axs=None):
14301484
See Also
14311485
--------
14321486
matplotlib.figure.Figure.align_xlabels
1433-
14341487
matplotlib.figure.Figure.align_ylabels
1488+
matplotlib.figure.Figure.align_titles
14351489
"""
14361490
self.align_xlabels(axs=axs)
14371491
self.align_ylabels(axs=axs)

lib/matplotlib/figure.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class FigureBase(Artist):
161161
) -> None: ...
162162
def align_xlabels(self, axs: Iterable[Axes] | None = ...) -> None: ...
163163
def align_ylabels(self, axs: Iterable[Axes] | None = ...) -> None: ...
164+
def align_titles(self, axs: Iterable[Axes] | None = ...) -> None: ...
164165
def align_labels(self, axs: Iterable[Axes] | None = ...) -> None: ...
165166
def add_gridspec(self, nrows: int = ..., ncols: int = ..., **kwargs) -> GridSpec: ...
166167
@overload

0 commit comments

Comments
 (0)