diff --git a/lib/matplotlib/_constrained_layout.py b/lib/matplotlib/_constrained_layout.py index 90faebc1525a..2b99010b64c6 100644 --- a/lib/matplotlib/_constrained_layout.py +++ b/lib/matplotlib/_constrained_layout.py @@ -403,9 +403,25 @@ def _align_spines(fig, gs): if height0 > height1: ax0._poslayoutbox.constrain_height_min( ax1._poslayoutbox.height * height0 / height1) + # the precise constraint must be weak because + # we may have one col with two axes, and the other + # column with just one, and we want the top and + # bottom of the short axes to align with the large one, + # so the height of the long one is greater than + # twice the height of the small ones. OTOH, if the + # axes are not so constrained, we would like the pos + # boxes to be the proper relative widths. + # See test_constrained_layout17 fo + ax0._poslayoutbox.constrain_height( + ax1._poslayoutbox.height * height0 / height1, + strength='weak') elif height0 < height1: ax1._poslayoutbox.constrain_height_min( ax0._poslayoutbox.height * height1 / height0) + # see above + ax1._poslayoutbox.constrain_height( + ax0._poslayoutbox.height * height1 / height0, + strength='weak') # For widths, do it if the subplots share a row. if not alignwidth and len(colspan0) == len(colspan1): ax0._poslayoutbox.constrain_width( @@ -415,9 +431,17 @@ def _align_spines(fig, gs): if width0 > width1: ax0._poslayoutbox.constrain_width_min( ax1._poslayoutbox.width * width0 / width1) + # see comment above + ax0._poslayoutbox.constrain_width( + ax1._poslayoutbox.width * width0 / width1, + strength='weak') elif width0 < width1: ax1._poslayoutbox.constrain_width_min( ax0._poslayoutbox.width * width1 / width0) + # see comment above + ax1._poslayoutbox.constrain_width_min( + ax0._poslayoutbox.width * width1 / width0, + strength='weak') def _arrange_subplotspecs(gs, hspace=0, wspace=0): diff --git a/lib/matplotlib/tests/test_constrainedlayout.py b/lib/matplotlib/tests/test_constrainedlayout.py index 46e6b9663ef3..95fb4e8779c5 100644 --- a/lib/matplotlib/tests/test_constrainedlayout.py +++ b/lib/matplotlib/tests/test_constrainedlayout.py @@ -399,3 +399,20 @@ def test_hidden_axes(): np.testing.assert_allclose( extents1, [0.045552, 0.548288, 0.47319, 0.982638], rtol=1e-5) + + +def test_two_under_one(): + fig = plt.figure(constrained_layout=True) + gs = fig.add_gridspec(2, 2) + ax0 = fig.add_subplot(gs[0, :]) + ax10 = fig.add_subplot(gs[1, 0]) + ax11 = fig.add_subplot(gs[1, 1]) + fig.canvas.draw() + extents0 = np.copy(ax0.get_position().extents) + extents10 = np.copy(ax10.get_position().extents) + extents11 = np.copy(ax11.get_position().extents) + + np.testing.assert_allclose(extents0[0], extents10[0]) + np.testing.assert_allclose(extents0[2], extents11[2]) + np.testing.assert_allclose(extents11[0] - extents10[2], + 0.077362, atol=1e-6)