Skip to content

Do not pass width_ratios or height_ratios to inner layouts in subplot_mosaic #24188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/api/next_api_changes/behavior/24188-JB.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
``fig.subplot_mosaic`` no longer passes the ``width_ratios`` or ``height_ratios`` args to the nested gridspecs.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Previously, the entirety of the ``gridspec_kw`` dictionary was passed
to the nested gridspecs. This caused an error if the inner layout was
incompatible with one of these ratios. A new dictionary is now made,
``nested_gs_kw``, where the ``"width_ratios"`` and ``"height_ratios"``
keys have been removed, which is passed to any nested gridspecs. This
prevents such errors.
21 changes: 17 additions & 4 deletions lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1838,21 +1838,27 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False,
Defines the relative widths of the columns. Each column gets a
relative width of ``width_ratios[i] / sum(width_ratios)``.
If not given, all columns will have the same width. Equivalent
to ``gridspec_kw={'width_ratios': [...]}``.
to ``gridspec_kw={'width_ratios': [...]}``. This argument applies
only to the outer layout and will not be passed to the inner
layout.

height_ratios : array-like of length *nrows*, optional
Defines the relative heights of the rows. Each row gets a
relative height of ``height_ratios[i] / sum(height_ratios)``.
If not given, all rows will have the same height. Equivalent
to ``gridspec_kw={'height_ratios': [...]}``.
to ``gridspec_kw={'height_ratios': [...]}``. This argument
applies only to the outer layout and will not be passed to the
inner layout.

subplot_kw : dict, optional
Dictionary with keywords passed to the `.Figure.add_subplot` call
used to create each subplot.

gridspec_kw : dict, optional
Dictionary with keywords passed to the `.GridSpec` constructor used
to create the grid the subplots are placed on.
to create the grid the subplots are placed on. The 'width_ratios'
and 'height_ratios' keys, if present, will be removed from this
dictionary before it is passed to any inner layouts.

empty_sentinel : object, optional
Entry in the layout to mean "leave this space empty". Defaults
Expand Down Expand Up @@ -1999,6 +2005,13 @@ def _do_layout(gs, mosaic, unique_ids, nested):
for (j, k), nested_mosaic in nested.items():
this_level[(j, k)] = (None, nested_mosaic, 'nested')

# must remove these two options from the kwargs passed to the
# nested items, otherwise an error occurs if *any* of the inner
# layouts are not compatible with these ratios
nested_gs_kw = dict([(k, v) for k, v in gridspec_kw.items()
if k != "width_ratios"
and k != "height_ratios"])

# now go through the things in this level and add them
# in order left-to-right top-to-bottom
for key in sorted(this_level):
Expand All @@ -2022,7 +2035,7 @@ def _do_layout(gs, mosaic, unique_ids, nested):
# recursively add the nested mosaic
rows, cols = nested_mosaic.shape
nested_output = _do_layout(
gs[j, k].subgridspec(rows, cols, **gridspec_kw),
gs[j, k].subgridspec(rows, cols, **nested_gs_kw),
nested_mosaic,
*_identify_keys_and_nested(nested_mosaic)
)
Expand Down
20 changes: 20 additions & 0 deletions lib/matplotlib/tests/test_figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,26 @@ def test_nested_tuple(self, fig_test, fig_ref):
fig_ref.subplot_mosaic([["F"], [x]])
fig_test.subplot_mosaic([["F"], [xt]])

def test_nested_width_ratios(self):
x = [["A", [["B"],
["C"]]]]
width_ratios = [2, 1]

fig, axd = plt.subplot_mosaic(x, width_ratios=width_ratios)

assert axd["A"].get_gridspec().get_width_ratios() == width_ratios
assert axd["B"].get_gridspec().get_width_ratios() != width_ratios

def test_nested_height_ratios(self):
x = [["A", [["B"],
["C"]]], ["D", "D"]]
height_ratios = [1, 2]

fig, axd = plt.subplot_mosaic(x, height_ratios=height_ratios)

assert axd["D"].get_gridspec().get_height_ratios() == height_ratios
assert axd["B"].get_gridspec().get_height_ratios() != height_ratios

@check_figures_equal(extensions=["png"])
@pytest.mark.parametrize(
"x, empty_sentinel",
Expand Down