Skip to content

Commit 5d9c630

Browse files
committed
FIX: wspace and hspace in subfigures without layout engine
1 parent 7d7f6da commit 5d9c630

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

lib/matplotlib/figure.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,8 +1564,9 @@ def subfigures(self, nrows=1, ncols=1, squeeze=True,
15641564
wspace, hspace : float, default: None
15651565
The amount of width/height reserved for space between subfigures,
15661566
expressed as a fraction of the average subfigure width/height.
1567-
If not given, the values will be inferred from a figure or
1568-
rcParams when necessary.
1567+
If not given, the values will be inferred from rcParams if using
1568+
constrained layout (see `~.ConstrainedLayoutEngine`), or zero if
1569+
not using a layout engine.
15691570
15701571
width_ratios : array-like of length *ncols*, optional
15711572
Defines the relative widths of the columns. Each column gets a
@@ -1580,13 +1581,24 @@ def subfigures(self, nrows=1, ncols=1, squeeze=True,
15801581
gs = GridSpec(nrows=nrows, ncols=ncols, figure=self,
15811582
wspace=wspace, hspace=hspace,
15821583
width_ratios=width_ratios,
1583-
height_ratios=height_ratios)
1584+
height_ratios=height_ratios,
1585+
left=0, right=1, bottom=0, top=1)
15841586

15851587
sfarr = np.empty((nrows, ncols), dtype=object)
15861588
for i in range(ncols):
15871589
for j in range(nrows):
15881590
sfarr[j, i] = self.add_subfigure(gs[j, i], **kwargs)
15891591

1592+
if self.get_layout_engine() is None and (wspace is not None or
1593+
hspace is not None):
1594+
# Gridspec wspace and hspace is ignored on subfigure instantiation,
1595+
# and no space is left. So need to account for it here if required.
1596+
bottoms, tops, lefts, rights = gs.get_grid_positions(self)
1597+
for sfrow, bottom, top in zip(sfarr, bottoms, tops):
1598+
for sf, left, right in zip(sfrow, lefts, rights):
1599+
bbox = Bbox.from_extents(left, bottom, right, top)
1600+
sf._redo_transform_rel_fig(bbox=bbox)
1601+
15901602
if squeeze:
15911603
# Discarding unneeded dimensions that equal 1. If we only have one
15921604
# subfigure, just return it instead of a 1-element array.

lib/matplotlib/tests/test_figure.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,31 @@ def test_subfigure_pdf():
14491449
fig.savefig(buffer, format='pdf')
14501450

14511451

1452+
def test_subfigures_wspace_hspace():
1453+
sub_figs = plt.figure().subfigures(2, 3, hspace=0.5, wspace=1/6.)
1454+
1455+
w = 640
1456+
h = 480
1457+
1458+
np.testing.assert_allclose(sub_figs[0, 0].bbox.min, [0., h * 0.6])
1459+
np.testing.assert_allclose(sub_figs[0, 0].bbox.max, [w * 0.3, h])
1460+
1461+
np.testing.assert_allclose(sub_figs[0, 1].bbox.min, [w * 0.35, h * 0.6])
1462+
np.testing.assert_allclose(sub_figs[0, 1].bbox.max, [w * 0.65, h])
1463+
1464+
np.testing.assert_allclose(sub_figs[0, 2].bbox.min, [w * 0.7, h * 0.6])
1465+
np.testing.assert_allclose(sub_figs[0, 2].bbox.max, [w, h])
1466+
1467+
np.testing.assert_allclose(sub_figs[1, 0].bbox.min, [0, 0])
1468+
np.testing.assert_allclose(sub_figs[1, 0].bbox.max, [w * 0.3, h * 0.4])
1469+
1470+
np.testing.assert_allclose(sub_figs[1, 1].bbox.min, [w * 0.35, 0])
1471+
np.testing.assert_allclose(sub_figs[1, 1].bbox.max, [w * 0.65, h * 0.4])
1472+
1473+
np.testing.assert_allclose(sub_figs[1, 2].bbox.min, [w * 0.7, 0])
1474+
np.testing.assert_allclose(sub_figs[1, 2].bbox.max, [w, h * 0.4])
1475+
1476+
14521477
def test_add_subplot_kwargs():
14531478
# fig.add_subplot() always creates new axes, even if axes kwargs differ.
14541479
fig = plt.figure()

0 commit comments

Comments
 (0)