vanzelfsprekend

Axes

Everything here acts on a matplotlib axes: apply installs the range frame, and the rest extend, quieten, group or undo it.

apply

apply(
    ax: Axes,
    frame: FrameMode | tuple[FrameMode, FrameMode] = "nice",
    spacing: float | tuple[float, float] | None = None,
    n: int | None = None,
    offset: float
    | tuple[float | None, float | None]
    | None = None,
    nice_numbers: Sequence[float] | None = None,
    weights: dict[str, float] | None = None,
) -> Axes

Apply vanzelfsprekend to ax: range_frame, then mute.

Takes range_frame's arguments and forwards them. restore undoes both steps.

The ink follows the frame: every panel framed as one unit with ax is muted too, not just ax.

Returns:

  • Axes –

    The same axes, for chaining.

restore

restore(ax: Axes) -> None

Remove vanzelfsprekend from ax and every axes framed with it.

Panels that were framed together, because they share an axis or were passed to small_multiples, are restored together: the shared scale cannot survive losing a member. Disconnects each draw hook and restores exactly the properties vanzelfsprekend changed (the original locators, spine visibility, positions and bounds, label alignment, furniture colours, view limits and the colour cycle) from the snapshots taken at first application. A no-op on an axes vanzelfsprekend never touched.

range_frame

range_frame(
    ax: Axes,
    frame: FrameMode | tuple[FrameMode, FrameMode] = "nice",
    spacing: float | tuple[float, float] | None = None,
    n: int | None = None,
    offset: float
    | tuple[float | None, float | None]
    | None = None,
    nice_numbers: Sequence[float] | None = None,
    weights: dict[str, float] | None = None,
) -> Axes

Turn ax into a range frame.

Installs TalbotLocator (linear axes), LogBreaksLocator (log axes), or DateBreaksLocator plus a ConciseDateFormatter (date axes) on both axes, hiding minor ticks on log axes, hides the top and right spines, and keeps the left and bottom spine bounds glued to the data on every draw. Where tick labels crowd, they drift apart just enough to stay readable, keeping their order; the tick marks stay exactly at their values. The ink is left alone: the spines keep their colour and the axes its colour cycle, which is what mute changes. Safe to call repeatedly; later calls update the settings instead of stacking hooks.

A locator you set on an axis before calling range_frame is kept, not overwritten, so ticks and frame compose in either order; the locator-shaping arguments below (spacing, n, nice_numbers, weights) then have nothing to configure and are ignored on that axis. Panels framed as a group (shared axes, small_multiples) are the exception: the shared scale is computed here, so a locator set on a grouped axis is replaced.

Panels that share an axis (sharex, sharey, ax.sharex(other)) are framed together, whichever one you pass: each shared axis is ticked and framed from the union of the panels' data, so the panels stay comparable and every tick lands on a spine. restore undoes them together, and a later range_frame on any of them updates them all. A twin made with twinx or twiny is left out with a warning and keeps its box. small_multiples does the same for a grid, with the inner furniture hidden.

Parameters:

  • ax (Axes) –

    The axes to modify, in place.

  • frame ((nice, data, loose, feature), default: 'nice') –

    'nice' ends the spines at the outermost ticks, 'data' at the exact data minimum and maximum. 'loose' ends the spines at nice numbers bounding the data (frame may extend up to one tick step beyond the data). 'feature' ends the spines at the outermost mark a FixedLocator sets on that axis (as FeatureLocator, SummaryLocator, and QuartileLocator do, or as an AugmentedLocator's .extra side does), even when it lies beyond the data, growing the view to keep it on screen; unlike 'loose' it sits flush by default (offset 0). A tuple (x_mode, y_mode) sets the bottom and left spine independently, and either entry may itself be a pair (low, high) setting that spine's two ends on their own: (("loose", "data"), "nice") runs the bottom spine from the tick below the data to the last observation. All three read the data cut back to the view, so a view pinned inside the data with set_xlim crops the frame to the data on screen, and a view wider than the data changes nothing.

  • spacing (float or tuple of two floats, default: None) –

    The gap to aim for between ticks, in tick-label heights, so the number of ticks follows the axis's length and the labels' size: a small panel gets few, a poster's large labels thin them out. A tuple (x_spacing, y_spacing) sets the axes independently; None (the default) uses (7, 4), which is 70 pt and 40 pt at 10 pt labels, about 2.5 cm and 1.4 cm, since an x label is three to five heights wide along its axis and a y label one. Halving the spacing doubles the ticks.

  • n (int, default: None) –

    The number of ticks to aim for per axis, overriding spacing.

  • offset (float or tuple of (float or None), default: None) –

    Outward displacement of the left and bottom spines, in points. A single number moves both spines; a tuple (x_offset, y_offset) moves the bottom and left spine independently, like frame. None (the whole argument, or either tuple element) resolves to 8 for a spine with a 'loose' end and 0 otherwise.

  • nice_numbers (sequence of float, default: None) –

    Advanced pass-through to TalbotLocator; see there for details. Applies to linear axes only; ignored on log and date axes.

  • weights (dict, default: None) –

    Advanced pass-through to TalbotLocator; see there for details. Applies to linear axes only; ignored on log and date axes.

Returns:

  • Axes –

    The same axes, for chaining.

secondary_frame

secondary_frame(
    ax: Axes,
    functions: tuple[Callable, Callable],
    where: str = "top",
) -> Axes

Add a second-unit axis that mirrors ax's ticks, styled like the frame.

The companion to range_frame for a second unit on the same data (radians and degrees, degrees C and F, a count and its log), never a second dataset. A secondary axis is created on the where side, its major ticks are kept sitting exactly under the host's (relabelled through functions), its spine, ticks and labels take the frame ink, and it follows the host every draw and tears down with restore(ax).

Parameters:

  • ax (Axes) –

    The host axes. Its major ticks drive the secondary's.

  • functions (tuple of two callables) –

    (forward, inverse), passed to matplotlib's secondary_xaxis/secondary_yaxis exactly as they take them: forward maps the host coordinate to the secondary unit, inverse back. The mirror places a secondary tick labelled forward(p) at each host tick position p.

  • where ((top, bottom, left, right), default: 'top') –

    The side, which also picks the axis: x for top/bottom, y for left/right.

Returns:

  • Axes –

    The secondary axes, so a label can be set on it.

Notes

Sets no tick formatter: a mirrored degree axis is already whole numbers, and any other unit takes the default numeric formatter.

mute

Grey the axis furniture so the data carries the ink.

mute

mute(
    ax: Axes,
    text_ink: str | None = None,
    line_ink: str | None = None,
    line_width: float | None = None,
) -> Axes

Grey the axis furniture in two tiers: readable text, receding lines.

Spines and tick marks take line_ink at line_width points; tick labels and axis labels take the darker text_ink, since text is read while lines are only looked at. Passing None (the default) for any of the three takes vanzelfsprekend's own inks: a light grey for lines at 0.7 points and a darker grey for text. Gridlines are turned off, since they are furniture and not data, while the near-side tick marks (bottom, left) are turned on, since they anchor the labels to the spine; data artists are untouched. The prior colours, widths, grid and tick visibility are snapshotted on the first call so restore can undo the change; later calls update the inks without overwriting the snapshot.

The neutral ink cycle is installed as well, so a mark drawn after mute is DATA_INK until you opt into colour with a scheme cycle of your own (palettes.cycle). Only matplotlib's default cycle is replaced; a cycle you set before mute is kept, and restore returns whichever was there.

Returns:

  • Axes –

    The same axes, for chaining.

accent

Pull chosen feature ticks forward: colour their labels; the antonym of mute.

accent

accent(
    ax: Axes,
    at: Sequence[str] | Sequence[float] | None = None,
    color: ColorType
    | Mapping[str, ColorType]
    | None = None,
    axis: str | None = None,
    only_features: bool = False,
    label: str = "value",
) -> Axes

Emphasise named feature ticks by colouring their labels.

Reads the position -> names map off the installed major locator (an AugmentedLocator forwards its extra's map; a named feature locator exposes its own) and colours those ticks' labels with color (default palettes.ACCENT_INK). The tick marks are left in the frame colour. Re-applies on every draw, so the accent survives resize and re-ticking; restore reverts it.

Returns:

  • Axes –

    The same axes, for chaining.

small_multiples

small_multiples(
    axes: Iterable[Axes],
    compare: Literal["figure", "row", "column"] = "figure",
    frame: FrameMode | tuple[FrameMode, FrameMode] = "nice",
    spacing: float | tuple[float, float] | None = None,
    n: int | None = None,
    offset: float | None = None,
    nice_numbers: Sequence[float] | None = None,
    weights: dict[str, float] | None = None,
    xlabel: str | Sequence[str] | None = None,
    ylabel: str | Sequence[str] | None = None,
) -> tuple[Axes, ...]

Frame a grid of axes as small multiples on a common scale.

Frames and mutes every panel, scopes scales by compare ('figure' shares both axes across all panels; 'row' scopes y per row; 'column' scopes x per column), and keeps axis furniture only on the left column and bottom row. Works on grids from plt.subplots, subplot_mosaic or a raw gridspec; builds nothing.

Every panel converges onto one ascending scale per group, so a panel with a deliberately inverted axis is silently re-oriented on the first draw.

Panels already tied with sharex or sharey are fine as long as the sharing does not cut across what compare scopes separately; pass the whole shared set, since a sibling left out still shares the others' ticks. Restoring any panel restores the grid.

Parameters:

  • axes (iterable of matplotlib.axes.Axes) –

    The grid's panels, all from one figure and one gridspec.

  • compare ((figure, row, column), default: 'figure') –

    The smallest set of panels that are fully comparable.

  • frame (FrameMode | tuple[FrameMode, FrameMode], default: 'nice') –

    Forwarded to range_frame per panel; see vanzelfsprekend.range_frame.

  • spacing (FrameMode | tuple[FrameMode, FrameMode], default: 'nice') –

    Forwarded to range_frame per panel; see vanzelfsprekend.range_frame.

  • n (FrameMode | tuple[FrameMode, FrameMode], default: 'nice') –

    Forwarded to range_frame per panel; see vanzelfsprekend.range_frame.

  • offset (FrameMode | tuple[FrameMode, FrameMode], default: 'nice') –

    Forwarded to range_frame per panel; see vanzelfsprekend.range_frame.

  • nice_numbers (FrameMode | tuple[FrameMode, FrameMode], default: 'nice') –

    Forwarded to range_frame per panel; see vanzelfsprekend.range_frame.

  • weights (FrameMode | tuple[FrameMode, FrameMode], default: 'nice') –

    Forwarded to range_frame per panel; see vanzelfsprekend.range_frame.

  • xlabel (str or sequence of str, default: None) –

    Axis labels. A sequence is accepted only for an axis compare scopes to rows or columns, one entry per row or column.

  • ylabel (str or sequence of str, default: None) –

    Axis labels. A sequence is accepted only for an axis compare scopes to rows or columns, one entry per row or column.

Returns:

  • tuple of matplotlib.axes.Axes –

    The panels, in the order given.

tick_direction

tick_direction(ax: Axes, direction: str = 'out') -> Axes

Point the tick marks direction: 'in', 'out', or 'none'.

'none' keeps the tick labels and removes the marks (zero length). The prior direction and lengths are snapshotted on the first call so restore can undo the change; later calls toggle freely without overwriting the snapshot.

Returns:

  • Axes –

    The same axes, for chaining.