Skip to content

Commit 6b739e1

Browse files
Backport PR #30098: Fix label_outer in the presence of colorbars. (#30228)
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
1 parent daf4c05 commit 6b739e1

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4693,14 +4693,25 @@ def label_outer(self, remove_inner_ticks=False):
46934693
self._label_outer_yaxis(skip_non_rectangular_axes=False,
46944694
remove_inner_ticks=remove_inner_ticks)
46954695

4696+
def _get_subplotspec_with_optional_colorbar(self):
4697+
"""
4698+
Return the subplotspec for this Axes, except that if this Axes has been
4699+
moved to a subgridspec to make room for a colorbar, then return the
4700+
subplotspec that encloses both this Axes and the colorbar Axes.
4701+
"""
4702+
ss = self.get_subplotspec()
4703+
if any(cax.get_subplotspec() for cax in self._colorbars):
4704+
ss = ss.get_gridspec()._subplot_spec
4705+
return ss
4706+
46964707
def _label_outer_xaxis(self, *, skip_non_rectangular_axes,
46974708
remove_inner_ticks=False):
46984709
# see documentation in label_outer.
46994710
if skip_non_rectangular_axes and not isinstance(self.patch,
47004711
mpl.patches.Rectangle):
47014712
return
4702-
ss = self.get_subplotspec()
4703-
if not ss:
4713+
ss = self._get_subplotspec_with_optional_colorbar()
4714+
if ss is None:
47044715
return
47054716
label_position = self.xaxis.get_label_position()
47064717
if not ss.is_first_row(): # Remove top label/ticklabels/offsettext.
@@ -4726,8 +4737,8 @@ def _label_outer_yaxis(self, *, skip_non_rectangular_axes,
47264737
if skip_non_rectangular_axes and not isinstance(self.patch,
47274738
mpl.patches.Rectangle):
47284739
return
4729-
ss = self.get_subplotspec()
4730-
if not ss:
4740+
ss = self._get_subplotspec_with_optional_colorbar()
4741+
if ss is None:
47314742
return
47324743
label_position = self.yaxis.get_label_position()
47334744
if not ss.is_first_col(): # Remove left label/ticklabels/offsettext.

lib/matplotlib/colorbar.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,8 +1453,7 @@ def make_axes(parents, location=None, orientation=None, fraction=0.15,
14531453

14541454
cax = fig.add_axes(pbcb, label="<colorbar>")
14551455
for a in parents:
1456-
# tell the parent it has a colorbar
1457-
a._colorbars += [cax]
1456+
a._colorbars.append(cax) # tell the parent it has a colorbar
14581457
cax._colorbar_info = dict(
14591458
parents=parents,
14601459
location=location,
@@ -1547,6 +1546,7 @@ def make_axes_gridspec(parent, *, location=None, orientation=None,
15471546

15481547
fig = parent.get_figure()
15491548
cax = fig.add_subplot(ss_cb, label="<colorbar>")
1549+
parent._colorbars.append(cax) # tell the parent it has a colorbar
15501550
cax.set_anchor(anchor)
15511551
cax.set_box_aspect(aspect)
15521552
cax.set_aspect('auto')

lib/matplotlib/tests/test_subplots.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import numpy as np
55
import pytest
66

7+
import matplotlib as mpl
78
from matplotlib.axes import Axes, SubplotBase
89
import matplotlib.pyplot as plt
910
from matplotlib.testing.decorators import check_figures_equal, image_comparison
@@ -111,10 +112,15 @@ def test_shared():
111112

112113

113114
@pytest.mark.parametrize('remove_ticks', [True, False])
114-
def test_label_outer(remove_ticks):
115-
f, axs = plt.subplots(2, 2, sharex=True, sharey=True)
115+
@pytest.mark.parametrize('layout_engine', ['none', 'tight', 'constrained'])
116+
@pytest.mark.parametrize('with_colorbar', [True, False])
117+
def test_label_outer(remove_ticks, layout_engine, with_colorbar):
118+
fig = plt.figure(layout=layout_engine)
119+
axs = fig.subplots(2, 2, sharex=True, sharey=True)
116120
for ax in axs.flat:
117121
ax.set(xlabel="foo", ylabel="bar")
122+
if with_colorbar:
123+
fig.colorbar(mpl.cm.ScalarMappable(), ax=ax)
118124
ax.label_outer(remove_inner_ticks=remove_ticks)
119125
check_ticklabel_visible(
120126
axs.flat, [False, False, True, True], [True, False, True, False])

0 commit comments

Comments
 (0)