Skip to content

[Bug] wspace/hspace ignored in Figure.subfigures (ID: 281) #64

@rowan-stein

Description

@rowan-stein

User Request

[Bug]: wspace and hspace in subfigures not working

Bug summary:

  • wspace and hspace in Figure.subfigures do nothing.

Code for reproduction:

import matplotlib.pyplot as plt

figs = plt.figure().subfigures(2, 2, wspace=0, hspace=0)
for fig in figs.flat:
    fig.subplots().plot([1, 2])
plt.show()

Actual outcome:

  • Same figure independently of the values of hspace and wspace.

Expected outcome:

  • Spacing should be reflected, consistent with Figure.subfigures behavior (see upstream reference in figure.py around lines 1550-1554).

Environment (from reporter):

  • OS/X, Matplotlib 3.7.1, Backend MacOSX, Python 3.10.9, install via conda.

Research Specification (from Emerson Gray)

Summary:

  • In non-constrained layout, SubFigure placement ignores GridSpec’s wspace/hspace. The fix is to compute SubFigure bbox in parent coordinates applying provided wspace and hspace from Figure.subfigures.

Key code paths:

  • lib/matplotlib/figure.py:
    • Figure.subfigures(...) creates a GridSpec and SubFigures.
    • SubFigure._redo_transform_rel_fig(bbox=None) computes subfigure region but currently ignores spacing unless constrained layout passes an explicit bbox.
  • lib/matplotlib/gridspec.py: GridSpec.get_grid_positions(...) shows the reference logic for spacing.
  • lib/matplotlib/_constrained_layout.py: constrained layout path already handles spacing by calling _redo_transform_rel_fig with a bbox.

Algorithm (non-constrained):

  • When _redo_transform_rel_fig is called with bbox=None, compute the subfigure’s rectangle in the parent coordinate system [0,1] using nrows/ncols, width/height ratios, and wspace/hspace from the GridSpec created by Figure.subfigures.
  • Treat wspace/hspace as 0.0 when None (backward-compatible default; previously there were no gaps).
  • Do not involve figure.subplotpars margins; subfigures fill the parent area.
  • For a SubplotSpec span (e.g., gs[r0:r1, c0:c1]), use min left/max right and min bottom/max top over spanned cells including internal separators.

Edge cases:

  • (wspace,hspace) = (0,0): subfigures touch.
  • nrows=1 or ncols=1: spacing has no effect (full size).
  • Nested subfigures: compute inside the parent’s [0,1] space.
  • Mixed subplots and subfigures: leave constrained behavior unchanged; non-constrained defaults remain zero spacing if None.

Testing plan:

  • Add geometry-based tests checking that wspace/hspace produce measurable gaps without constrained layout.
  • Test that default None yields no gaps.
  • Test nested subfigures behavior.

Implementation changes:

  • Modify SubFigure._redo_transform_rel_fig(self, bbox=None) in lib/matplotlib/figure.py to compute bbox_relative using spacing per the algorithm above when bbox is None. Keep the bbox is not None branch unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions