Skip to content

Per-panel colorbars/legends overflow into neighbouring panels in multi-panel plots #687

@timtreis

Description

@timtreis

Problem

In multi-panel figures (multiple coordinate systems, or scanpy-style color=[...]), each panel's colorbar/legend is drawn outside the panel via inset_axes anchored to the right of ax.transAxes. When panels get small (grids, constrained canvases), the colorbar/legend — and especially its tick labels — spill into the adjacent panel.

This is most visible when several panels each carry their own colorbar (continuous) or legend (categorical): the left panel's colorbar collides with the right panel's y-axis labels.

Root cause

_draw_colorbar in pl/basic.py places the colorbar with:

cax = inset_axes(spec.ax, ..., bbox_to_anchor=(1 + pad, 0, fraction, 1), bbox_transform=spec.ax.transAxes)

i.e. outside the panel's cell. No layout engine reserves that space, so it overflows the neighbour. Categorical legends are similarly placed in the right margin.

How scanpy avoids this

scanpy reserves the colorbar/legend space inside each panel's own cell (steals from the axes), so it can never overflow:

  • Continuous: plt.colorbar(cax, ax=ax, pad=0.01, fraction=0.08, aspect=30, location=...)ax=ax shrinks the panel and places the colorbar in the reclaimed space.
  • Categorical (multi-panel): shrink the axis first, then add the legend in the freed space:
    box = ax.get_position(); ax.set_position([box.x0, box.y0, box.width * 0.91, box.height])

Proposed fix

Switch the colorbar subsystem to space-stealing plt.colorbar(ax=ax, location=, fraction=, pad=) and adopt the shrink-then-place pattern for categorical legends. This makes both single- and multi-panel layouts robust at any figure size.

Note: library-wide rendering change — affects every colorbar/legend and requires regenerating a large set of visual baselines. Preserve the existing public knobs (location left/right/top/bottom, colorbar_params, same-side stacking, alpha, label).

Discovered while implementing #611 (multi-panel color=[...]).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions