Skip to content

Commit d2caede

Browse files
author
sanrishi
committed
fix subfigures wspace/hspace=None using rc defaults instead of zero
1 parent 102a1d2 commit d2caede

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

lib/matplotlib/figure.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,13 @@ def subfigures(self, nrows=1, ncols=1, squeeze=True,
16481648
relative height of ``height_ratios[i] / sum(height_ratios)``.
16491649
If not given, all rows will have the same height.
16501650
"""
1651+
# Without a layout engine, None is documented to mean zero.
1652+
# GridSpec passes None through to SubplotParams, which leaves the
1653+
# rcParam default (0.2) in place, so fix it up here.
1654+
if self.get_layout_engine() is None:
1655+
wspace = wspace if wspace is not None else 0.0
1656+
hspace = hspace if hspace is not None else 0.0
1657+
16511658
gs = GridSpec(nrows=nrows, ncols=ncols, figure=self,
16521659
wspace=wspace, hspace=hspace,
16531660
width_ratios=width_ratios,

lib/matplotlib/tests/test_figure.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,69 @@ def test_subfigures_wspace_hspace():
15691569
np.testing.assert_allclose(sub_figs[1, 2].bbox.max, [w, h * 0.4])
15701570

15711571

1572+
def test_subfigures_partial_spacing():
1573+
# When no layout engine, wspace/hspace=None should mean zero.
1574+
# Regression test for gh-32076 (only one of wspace/hspace set used
1575+
# to fall back to the rcParam default for the other axis).
1576+
fig = plt.figure(figsize=(6, 4), dpi=100)
1577+
w_px, h_px = 600, 400
1578+
1579+
# Both None: no spacing, subfigures tile the figure.
1580+
sfs = fig.subfigures(2, 2, wspace=None, hspace=None)
1581+
for row in sfs:
1582+
for sf in row:
1583+
sf.add_subplot().plot([0, 1], [0, 1])
1584+
fig.canvas.draw()
1585+
np.testing.assert_allclose(sfs[0, 0].bbox.bounds,
1586+
[0, h_px // 2, w_px // 2, h_px // 2])
1587+
np.testing.assert_allclose(sfs[0, 1].bbox.bounds,
1588+
[w_px // 2, h_px // 2, w_px // 2, h_px // 2])
1589+
np.testing.assert_allclose(sfs[1, 0].bbox.bounds,
1590+
[0, 0, w_px // 2, h_px // 2])
1591+
np.testing.assert_allclose(sfs[1, 1].bbox.bounds,
1592+
[w_px // 2, 0, w_px // 2, h_px // 2])
1593+
plt.close(fig)
1594+
1595+
# Only wspace set: horizontal gap, no vertical gap.
1596+
fig = plt.figure(figsize=(6, 4), dpi=100)
1597+
sfs = fig.subfigures(2, 2, wspace=0.2, hspace=None)
1598+
for row in sfs:
1599+
for sf in row:
1600+
sf.add_subplot().plot([0, 1], [0, 1])
1601+
fig.canvas.draw()
1602+
cell = 1 / 2.2
1603+
sep = 0.2 * cell
1604+
np.testing.assert_allclose(
1605+
sfs[0, 0].bbox.bounds,
1606+
[0, h_px / 2, cell * w_px, h_px / 2], rtol=1e-5)
1607+
np.testing.assert_allclose(
1608+
sfs[0, 1].bbox.bounds,
1609+
[(cell + sep) * w_px, h_px / 2, cell * w_px, h_px / 2], rtol=1e-5)
1610+
# Both rows should have equal height (no vertical gap).
1611+
assert sfs[0, 0].bbox.height == pytest.approx(h_px / 2)
1612+
assert sfs[1, 0].bbox.y1 == pytest.approx(sfs[0, 0].bbox.y0)
1613+
plt.close(fig)
1614+
1615+
# Only hspace set: vertical gap, no horizontal gap.
1616+
fig = plt.figure(figsize=(6, 4), dpi=100)
1617+
sfs = fig.subfigures(2, 2, wspace=None, hspace=0.2)
1618+
for row in sfs:
1619+
for sf in row:
1620+
sf.add_subplot().plot([0, 1], [0, 1])
1621+
fig.canvas.draw()
1622+
cell = 1 / 2.2
1623+
np.testing.assert_allclose(
1624+
sfs[0, 0].bbox.bounds,
1625+
[0, (cell + sep) * h_px, w_px / 2, cell * h_px], rtol=1e-5)
1626+
np.testing.assert_allclose(
1627+
sfs[1, 0].bbox.bounds,
1628+
[0, 0, w_px / 2, cell * h_px], rtol=1e-5)
1629+
# Both columns should have equal width (no horizontal gap).
1630+
assert sfs[0, 0].bbox.width == pytest.approx(w_px / 2)
1631+
assert sfs[0, 1].bbox.x0 == pytest.approx(sfs[0, 0].bbox.x1)
1632+
plt.close(fig)
1633+
1634+
15721635
def test_subfigure_remove():
15731636
fig = plt.figure()
15741637
sfs = fig.subfigures(2, 2)

0 commit comments

Comments
 (0)