Layout Utilities

Utilities for tightening layouts without juggling plt.subplots_adjust. simple_layout optimizes margins with L-BFGS-B so axes fit inside a bounding box; make_offset nudges text/legends in point units; and set_decimal/get_bounding_box provide quick helpers when formatting axes.

simple_layout(fig, gs=None, margins=(0.05, 0.05, 0.05, 0.05), bbox=(0, 1, 0, 1), verbose=False, gtol=1e-2, bound_margin=0.2, use_all_axes=True, importance_weights=(1, 1, 1, 1))
  • Parameters: - fig: target figure (required). - gs: GridSpec to adjust; None picks the first axes’ GridSpec. - margins: padding in inches (left, right, bottom, top). - bbox: figure-relative target box; shrink to reserve space for headers. - importance_weights: emphasize specific sides during optimization. - bound_margin: how far each side may move away from bbox. - gtol: optimizer tolerance. - verbose: toggle optimizer logging. - use_all_axes: True considers every axes; False limits to gs.

  • Returns: - scipy.optimize.OptimizeResult; layout changes are applied in-place.

make_offset(x, y, fig)
  • Parameters: - x: horizontal offset in points. - y: vertical offset in points. - fig: figure providing DPI scaling.

  • Returns: - matplotlib.transforms.ScaledTranslation to add to an axes transform.

set_decimal(ax, xn=None, yn=None)
  • Parameters: - ax: axes object to update. - xn: decimal places for x ticks; None leaves them unchanged. - yn: decimal places for y ticks; None leaves them unchanged.

  • Returns: - None; tick labels are replaced.

get_bounding_box(boxes)
  • Parameters: - boxes: iterable with p0, width, height (e.g., from get_tightbbox).

  • Returns: - tuple (min_x, min_y, width, height) covering them all.

Example

fig, ax = plt.subplots()
ax.plot(x, y)

# Keep slightly wider right margin for a legend slot
simple_layout(
    fig,
    margins=(0.08, 0.12, 0.1, 0.08),
    importance_weights=(1, 2, 1, 1)
)

# Pixel-perfect title nudge
ax.set_title("Clean title", transform=ax.transAxes + make_offset(0, 6, fig))
set_decimal(ax, xn=2, yn=1)
dartwork_mpl.simple_layout(fig: Figure, gs: GridSpec | None = None, margins: tuple[float, float, float, float] = (0.05, 0.05, 0.05, 0.05), bbox: tuple[float, float, float, float] = (0, 1, 0, 1), verbose: bool = False, gtol: float = 0.01, bound_margin: float = 0.2, use_all_axes: bool = True, importance_weights: tuple[float, float, float, float] = (1, 1, 1, 1)) OptimizeResult[source]

Apply simple layout to figure for given grid spec.

Parameters:
  • fig (matplotlib.figure.Figure) – Figure object.

  • gs (matplotlib.gridspec.GridSpec, optional(default=None)) – Grid spec object. If None, use the first grid spec.

  • margins (tuple(float, float, float, float), optional(default=(0.05, 0.05, 0.05, 0.05))) – Margins in inches, (left, right, bottom, top).

  • bbox (tuple(float, float, float, float), optional(default=(0, 1, 0, 1))) – Bounding box in figure coordinates, (left, right, bottom, top).

  • verbose (bool, optional(default=True)) – Print verbose.

  • gtol (float, optional(default=1e-2)) – Gradient tolerance. If the maximum change in the objective function is less than gtol, the optimization will stop.

  • bound_margin (float, optional(default=0.1)) – Margin for bounds generation.

  • use_all_axes (bool, optional(default=True)) – Use all axes in the figure. If False, use only axes in the given grid spec. IF True, use all axes in the figure.

  • importance_weights (tuple(float, float, float, float), optional(default=(1, 1, 1, 1))) – Importance weights for each target. (left, right, bottom, top).

Returns:

result – Optimization result.

Return type:

scipy.optimize.OptimizeResult

dartwork_mpl.make_offset(x: float, y: float, fig: Figure) ScaledTranslation[source]

Create a translation offset for figure elements.

Parameters:
  • x (float) – X offset in points.

  • y (float) – Y offset in points.

  • fig (matplotlib.figure.Figure) – Figure to create offset for.

Returns:

Offset transform.

Return type:

matplotlib.transforms.ScaledTranslation

dartwork_mpl.util.get_bounding_box(boxes: list) tuple[float, float, float, float][source]

Get the bounding box that contains all given boxes.

Parameters:

boxes (list) – List of box objects with p0, width, and height attributes.

Returns:

(min_x, min_y, bbox_width, bbox_height) of the bounding box.

Return type:

tuple

dartwork_mpl.util.set_decimal(ax: Axes, xn: int | None = None, yn: int | None = None) None[source]

Set decimal places for tick labels.

Parameters:
  • ax (matplotlib.axes.Axes) – Axes object to modify.

  • xn (int, optional) – Number of decimal places for x-axis tick labels.

  • yn (int, optional) – Number of decimal places for y-axis tick labels.