anyplotlib.Plot2D#

class anyplotlib.Plot2D(data, x_axis=None, y_axis=None, units='px', cmap=None, vmin=None, vmax=None, origin='upper', gpu='auto', tile='auto', integration_method='mean', overview_method='mean', tile_backend=None)[source]#

Bases: _BasePlot, _PanelMixin, _MarkerMixin

2-D image plot panel.

Not an anywidget. Holds state in _state dict; every mutation calls _push() which writes to the parent Figure’s panel trait.

The marker API follows matplotlib conventions:

plot.add_circles(offsets, name=”g1”, facecolors=”#f00”, radius=5) plot.markers[“circles”][“g1”].set(radius=8)

Parameters:
TILE_THRESHOLD = 1024#
OVERVIEW_MAX = 1024#
VIEW_OVERFETCH = 2.0#
VIEW_ZOOM_MIN = 1.05#
RANGE_SAMPLE_MAX = 2048#
property gpu_active: bool#

True when this image is being rendered by the WebGPU path (reported by JS after the device resolves and the panel flips to GPU). False on the Canvas2D path (small image, gpu=False, no GPU, or a GPU failure/fallback).

enable_tile(backend=None, integration_method='mean', overview_method=None)[source]#

Turn tile mode ON (or reconfigure it) AFTER construction — for a consumer whose large frame isn’t known at imshow time (e.g. a live navigator whose signal frame arrives later and changes). Registers the internal view→tile loop (once), sets the logical size from the backend, and paints the overview base. Call update_tile_source(new_frame) on each subsequent data change.

backend: a TileBackend (or an ndarray, wrapped). None keeps the current backend (just re-enable / change method).

overview_method: sampling method for the base overview texture ("mean"|"subsample"|"max"). None keeps the current setting (default "mean" from construction). Use "subsample" to restore the old fast nearest-neighbour path when a full-frame area-mean is too expensive.

Parameters:
  • integration_method (str)

  • overview_method (str | None)

Return type:

None

update_tile_source(array=None)[source]#

The backing DATA changed (e.g. a movie navigator advanced a frame) — keep the current zoom/subselection but refresh the pixels. Re-samples the overview base AND (if a detail tile is currently shown) the SAME detail region from the new data, so a live source updates in place without a view change.

array: swap the numpy backend’s source first (convenience for the common ndarray case). For a custom backend that already mutated its own source, call update_tile_source() with no argument to just re-sample.

Return type:

None

to_state_dict()[source]#

Return a JSON-serialisable copy of the current state.

On the binary-transport path _state["image_b64"] may hold a tiny "\x00bin:<checksum>" change-token instead of a base64 string — the real pixels ride the PLOTBIN channel (_electron._route_change reads them from the Figure’s _raw_pixels side-table). The token is the correct WIRE representation and is passed through untouched here so the hot Figure._push path does NOT re-encode base64 every frame.

A COLD consumer with no binary channel (save_html / standalone / Jupyter) must instead materialise real base64; it calls resolve_pixel_tokens() on the returned dict (Figure._push does this for the standalone trait when binary transport is off).

Return type:

dict

resolve_pixel_tokens(d)[source]#

Replace any "\x00bin:…" pixel change-token in d with the real base64 (materialised from the Figure’s _raw_pixels side-table), in place, and return d. Used by the COLD paths (save_html / standalone) that have no PLOTBIN channel and need the pixels inline. A no-op for a normal base64 string. See to_state_dict().

Also materialises every LAYER’s pixels: each layer has a top-level geom key layer_<id>_b64 AND a mirror image_b64 field inside its layers entry — both are resolved so a save_html snapshot of a layered plot is self-contained.

Parameters:

d (dict)

Return type:

dict

property data: ndarray#

The image data in the original user coordinate system (read-only).

Returns a float64 copy with writeable=False. To replace the data call set_data().

The float64 cast happens HERE, lazily, not in set_data — a scrub pushes a new frame every tick but rarely reads .data back, and a full float64 copy of a 4k frame is ~12 ms. set_data keeps the frame in its source dtype (self._data); we cast + copy only on the (rare) read.

set_data(data, x_axis=None, y_axis=None, units=None, clim=None, tile=None)[source]#

Replace the image data.

The origin supplied at construction is automatically re-applied so the new data is displayed with the same orientation.

tile — per-call override of the tile decision (default None uses the plot’s construction preference). False forces a PLAIN full-frame push even for a large frame (the caller manages its own decimation); True forces tile mode. A live consumer that only wants tiling on some frames (e.g. only when its GPU is active, sending the NATIVE frame then, but a pre-decimated frame otherwise) passes tile=False on the decimated frames so they don’t get auto-tiled at the wrong logical size.

clim — optional (vmin, vmax) display range applied in the SAME push as the new data. Without it the caller must follow with a separate set_clim, which pushes a SECOND time: the first push shows the image stretched over its full data range (wrong contrast) and the second corrects it, producing a one-frame flash on every update. Passing clim here makes data + contrast a single atomic frame (no flash).

Raises:

ValueError – If data has an invalid shape/ndim, or if this plot has image layers (add_layer()) and data’s (H, W) differs from the current image shape. A layer keeps the size it had when it was added/last updated, so a shape-changing base update would silently stretch stale-sized layer pixels over the new image. Remove all layers (remove_layer) before changing the base image’s shape, then re-add them at the new size.

Parameters:
Return type:

None

set_overlay_mask(mask, color='#ff4444', alpha=0.4)[source]#

Set (or clear) a transparent boolean mask drawn over the image.

The mask is composited client-side in the browser at alpha opacity using color for all True pixels. Call with mask=None to remove any existing overlay.

Parameters:
  • mask (ndarray of shape (H, W), bool or uint8, or None) – Boolean array aligned to the image data. True / non-zero pixels are filled with color at transparency alpha. Pass None to clear the overlay.

  • color (str, optional) – CSS hex colour for the overlay, e.g. "#ff4444". Default red. Must be in #RRGGBB format.

  • alpha (float, optional) – Opacity in [0, 1]. Default 0.4 (40 % opaque).

Return type:

None

property layers: list#

The list of Layer handles, in z-order (index 0 drawn first, above the base image).

add_layer(data, *, cmap='magma', alpha=0.5, clim=None, visible=True, tint=None)[source]#

Add an image LAYER drawn over the base image.

Each layer has its OWN colormap, display range (clim), and opacity (alpha), and is composited on top of the base image (and previously added layers) with the SAME zoom/pan transform, so it tracks the base exactly. This is the multi-image overlay primitive; for a single-colour boolean mask use set_overlay_mask() instead.

Parameters:
  • data (ndarray, shape (H, W)) – 2-D scalar array, the same size as the base image. Normalised to uint8 via clim → LUT exactly like the base image. A shape mismatch raises ValueError.

  • cmap (str, optional) – Colormap name (default "magma"). Ignored for display while tint is set (the tint LUT replaces the colormap), but kept so set(cmap=...) can revert to it.

  • alpha (float, optional) – Opacity in [0, 1] (default 0.5).

  • clim ((vmin, vmax) or None, optional) – Display range; None (default) auto-scales to the data min/max.

  • visible (bool, optional) – Whether the layer is drawn (default True).

  • tint (str or None, optional) – A #rgb / #rrggbb hex colour. When set, the layer renders as a clear→colour intensity ramp instead of a named colormap: RGB is tint at every intensity and per-texel alpha ramps linearly 0 → 255 (transparent at low intensity → opaque tint at high). The per-texel alpha multiplies with the layer’s alpha. None (default) keeps the named-colormap behaviour. An invalid colour raises ValueError.

Returns:

A handle with .set(...) / .set_data(frame) / .remove().

Return type:

Layer

Raises:
  • RuntimeError – If the plot is in TILE mode — layers are incompatible with tiling (a layer would have to be tiled independently against the same view). Load the plot with tile=False to use layers.

  • ValueError – If data is not 2-D or does not match the base image size.

remove_layer(layer)[source]#

Remove layer (a Layer handle or its id string).

Return type:

None

set_colormap(name)[source]#
Parameters:

name (str)

Return type:

None

set_clim(vmin=None, vmax=None)[source]#

Set the display range. Because scalar frames are quantised to uint8 over their clim (so a hot pixel / zero beam can’t crush the signal — see _normalize_image), a new range is honoured by RE-QUANTISING from the cached raw frame, not merely re-windowing the existing codes (which are saturated outside the previous band and so couldn’t widen past it). For an RGB frame (no scalar quantisation) or when no raw frame is cached, fall back to a pure display-window update.

Return type:

None

set_detail(tile=None, x0=None, x1=None, y0=None, y1=None)[source]#

Upload a HIGH-RES detail tile covering the LOGICAL image-pixel rectangle [x0:x1, y0:y1] of the base image (in the SAME orientation as the frame passed to set_data — already origin-applied), so a zoom-in shows true native pixels for the visible region WITHOUT transferring the whole full-res frame. The shader samples this tile instead of the base whenever the current zoom window lies inside [x0:x1, y0:y1]; otherwise it falls back to the base texture. set_detail(None) clears it (revert to base).

tile is quantised to uint8 over the SAME display range as the base (display_min/display_max) so its contrast matches seamlessly — a zoom crop must look identical to the base, just sharper. Only meaningful for scalar (non-RGB) images.

Return type:

None

set_scale_mode(mode)[source]#
Parameters:

mode (str)

Return type:

None

property colormap_name: str#
set_xlabel(label, fontsize=None)[source]#

Set the x-axis label.

Parameters:
  • label (str) – Label text. Supports the mini-TeX subset for scientific notation, e.g. r"$q$ ($\AA^{-1}$)" or r"$10^{-3}$ m" — see _BasePlot notes.

  • fontsize (float, optional) – Font size in CSS pixels. Default 11. None keeps the current size.

Return type:

None

set_ylabel(label, fontsize=None)[source]#

Set the y-axis label. Same semantics as set_xlabel().

Parameters:
Return type:

None

set_xlim(xmin, xmax)[source]#
Parameters:
Return type:

None

set_ylim(ymin, ymax)[source]#
Parameters:
Return type:

None

get_xlim()[source]#
Return type:

tuple

get_ylim()[source]#
Return type:

tuple

get_xbound()[source]#
Return type:

tuple

set_extent(x_axis, y_axis, units=None)[source]#

Recalibrate the image axes to the given coordinate arrays.

Sets has_axes so the front-end draws physical tick gutters + the scale bar — the same gate set_data(x_axis=, y_axis=) sets. Without this a tiled image (which is calibrated ONLY through set_extent / enable_tile, never through set_data with axis args) would show no ticks and no scale bar (the has_axes gate stayed False). Pass units to update the scale-bar unit label in the same push.

Parameters:

units (str | None)

Return type:

None

set_colorbar_label(label, fontsize=None)[source]#

Set the colorbar label (mini-TeX allowed; default size 10 px).

Parameters:
Return type:

None

set_colorbar_visible(visible)[source]#
Parameters:

visible (bool)

Return type:

None

set_colorbar_pad(pad)[source]#

Set the gap in px between the image and the colorbar strip.

Parameters:

pad (float or None) – Gap in CSS pixels. None restores the default (6 px). The gap comes out of the image width, so widening it shrinks the image rather than pushing the strip off the panel.

Return type:

None

set_aspect(ratio)[source]#
Return type:

None

set_scalebar_style(color=None, bgcolor=None)[source]#

Recolour the automatic scale bar.

The scale bar appears on its own whenever the panel has calibrated axes (units other than "px"). It defaults to white on a translucent dark pill, which reads well on most images but not on a light one.

Parameters:
  • color (str, optional) – CSS colour for the bar and its label. None (default) leaves it at white.

  • bgcolor (str, optional) – CSS colour for the pill behind them, or the string "none" to draw no pill at all. None (default) leaves it at the translucent dark pill.

Return type:

None

Examples

>>> plot.set_scalebar_style(color="black", bgcolor="none")
add_widget(kind, color='#00e5ff', **kwargs)[source]#

Add an overlay widget by kind name.

Dispatches to the dedicated add_<kind>_widget method. Supported kinds: "circle", "rectangle", "annular", "polygon", "crosshair", "label", "arrow", "line", "brush", "vline", "hline".

Every kind also accepts show_handles (default True) to toggle the grab-handle dots without changing hit-testing / draggability. vline / hline have no handles — the whole line is the grab target — so they ignore it, and neither does brush (a freehand stroke has no grab point).

Parameters:
Return type:

Widget

add_circle_widget(cx=None, cy=None, r=None, color='#00e5ff', linewidth=2, show_handles=True)[source]#

Add a draggable circle overlay.

Parameters:
Return type:

CircleWidget

add_rectangle_widget(x=None, y=None, w=None, h=None, color='#00e5ff', linewidth=2, show_handles=True, max_extent=None)[source]#

Add a draggable rectangle overlay.

max_extent caps the rectangle’s size in the widget’s coordinates — a scalar caps both axes, a (max_w, max_h) pair caps them separately. The rectangle then physically stops growing at the cap while dragging (the dragged corner pins, the opposite corner stays put).

Parameters:
Return type:

RectangleWidget

add_annular_widget(cx=None, cy=None, r_outer=None, r_inner=None, color='#00e5ff', linewidth=2, show_handles=True)[source]#

Add a draggable annular (ring) overlay.

Parameters:
Return type:

AnnularWidget

add_polygon_widget(vertices=None, color='#00e5ff', linewidth=2, show_handles=True)[source]#

Add a draggable polygon overlay.

Parameters:
Return type:

PolygonWidget

add_brush_widget(radius=None, color='#00e5ff', colors=None, class_id=0, strokes=None, stroke_classes=None, alpha=0.6, active=True, erase=False)[source]#

Add a freehand paint-brush overlay for labelling regions.

Shift + drag paints a stroke; a bare drag still pans the image and still drags other widgets. One brush can hold several label classes at once — a stroke is tagged with the widget’s current class_id and drawn in colors[class_id].

Painting is modal: while the brush is armed, a Shift-press over the image no longer emits a panel pointer_down, so a host that binds Shift-click to something else needs a different modifier (or active=False while that mode is on). A Shift-drag starting in the axis margin is not a brush gesture and pans as usual.

The stroke accumulates in the browser and reaches Python once, on release, as a pointer_up event — pointer_move does not fire for a brush. See BrushWidget.

Parameters:
  • radius (float, optional) – Brush radius in image pixels; the painted band is 2 * radius wide. Defaults to 2 % of the smaller image dimension (at least 2), so the default is visible on a 4096² image and usable on a 64² one.

  • color (str, optional) – CSS colour for classes not covered by colors. Default "#00e5ff".

  • colors (list of str, optional) – Per-class CSS colours, indexed by class_id.

  • class_id (int, optional) – Label class new strokes are tagged with. Default 0.

  • strokes (list, optional) – Pre-existing strokes [[[x, y], ...], ...] in image pixels.

  • stroke_classes (list of int, optional) – Class id per entry of strokes; must be the same length.

  • alpha (float, optional) – Stroke opacity. Default 0.6, so the labelled feature stays visible underneath.

  • active (bool, optional) – Accept Shift-drag painting. Default True; False parks the tool with its strokes still drawn.

  • erase (bool, optional) – Armed drags remove stroke points within radius instead of painting. Default False.

Returns:

Widget object. widget.strokes / widget.stroke_classes hold the painted geometry; clear_strokes() and strokes_for_class() manage it.

Return type:

BrushWidget

add_crosshair_widget(cx=None, cy=None, color='#00e5ff', linewidth=2, show_handles=True)[source]#

Add a draggable crosshair overlay.

Parameters:
Return type:

CrosshairWidget

add_label_widget(x=None, y=None, text='Label', fontsize=14, color='#00e5ff', show_handles=True)[source]#

Add a draggable text label overlay.

Parameters:
Return type:

LabelWidget

add_arrow_widget(x=None, y=None, u=None, v=None, color='#00e5ff', linewidth=2, show_handles=True)[source]#

Add a draggable arrow overlay (tail at (x, y), head at (x + u, y + v)). Defaults place the tail at 25 %, 25 % of the image with a vector of 15 % of the image size, mirroring add_label_widget()’s defaulting.

Parameters:
Return type:

ArrowWidget

add_line_widget(x1=None, y1=None, x2=None, y2=None, color='#00e5ff', linewidth=2, show_handles=True)[source]#

Add a draggable two-endpoint line segment overlay.

A bare segment with a grab handle at each end — no arrowhead (see add_arrow_widget()) and no closed path (see add_polygon_widget()). Use it for a line profile, a cross-section cut, or a two-point measurement.

Parameters:
  • x1 (float, optional) – First endpoint in image coordinates. Defaults to 25 % of the image size.

  • y1 (float, optional) – First endpoint in image coordinates. Defaults to 25 % of the image size.

  • x2 (float, optional) – Second endpoint. Defaults to 75 % of the image size.

  • y2 (float, optional) – Second endpoint. Defaults to 75 % of the image size.

  • color (str, optional) – CSS colour string. Default "#00e5ff".

  • linewidth (float, optional) – Stroke width in px. Default 2.

  • show_handles (bool, optional) – Draw the endpoint grab handles. Default True.

Returns:

Widget object. widget.length gives the segment length in data coordinates.

Return type:

LineWidget

add_vline_widget(x=None, color='#00e5ff', linewidth=2)[source]#

Add a draggable full-height vertical line overlay.

The line spans the whole panel and is grabbable anywhere along its length, which makes it the right pointer for “select a column” — a crosshair pinned to one axis leaves a stray perpendicular line.

Parameters:
  • x (float, optional) – Initial x position in image coordinates. Defaults to the middle.

  • color (str, optional) – CSS colour string. Default "#00e5ff".

  • linewidth (float, optional) – Stroke width in px. Default 2.

Return type:

VLineWidget

add_hline_widget(y=None, color='#00e5ff', linewidth=2)[source]#

Add a draggable full-width horizontal line overlay.

The row counterpart of add_vline_widget(); grabbable anywhere along its length.

Parameters:
  • y (float, optional) – Initial y position in image coordinates. Defaults to the middle.

  • color (str, optional) – CSS colour string. Default "#00e5ff".

  • linewidth (float, optional) – Stroke width in px. Default 2.

Return type:

HLineWidget

set_view(x0=None, x1=None, y0=None, y1=None)[source]#

Set the viewport to a data-space rectangle.

Parameters:
  • x0 (float, optional) – Horizontal data-space range to show. If omitted the full x-extent is used for zoom calculation.

  • x1 (float, optional) – Horizontal data-space range to show. If omitted the full x-extent is used for zoom calculation.

  • y0 (float, optional) – Vertical data-space range to show. If omitted the full y-extent is used for zoom calculation.

  • y1 (float, optional) – Vertical data-space range to show. If omitted the full y-extent is used for zoom calculation.

  • center_x (Translates the requested rectangle into the zoom /)

  • renderer. (/ center_y state values used by the 2-D JS)

Return type:

None

reset_view()[source]#

Reset pan and zoom to show the full image.

Return type:

None

add_circles(offsets, name=None, *, radius=5, facecolors=None, edgecolors='#ff0000', linewidths=1.5, alpha=0.3, hover_edgecolors=None, hover_facecolors=None, labels=None, label=None, transform='data', clip_display=True, size_units='data')[source]#

Add circle markers at (x, y) positions in data coordinates.

size_units="px" pins radius to screen pixels so the circles keep their size through a zoom; the default "data" scales them with the data, as a shape drawn on the image does.

Parameters:
  • transform (str)

  • clip_display (bool)

  • size_units (str)

Return type:

MarkerGroup

add_points(offsets, name=None, *, sizes=5, color='#ff0000', facecolors=None, linewidths=1.5, alpha=0.3, hover_edgecolors=None, hover_facecolors=None, labels=None, label=None, transform='data', clip_display=True, size_units='data')[source]#

Add point markers at (x, y) positions in data coordinates.

A marker standing in for a point usually wants size_units="px" so it does not grow with zoom — that is what matplotlib does, sizing scatter markers in display points.

Parameters:
  • transform (str)

  • clip_display (bool)

  • size_units (str)

Return type:

MarkerGroup

add_hlines(y_values, name=None, *, color='#ff0000', linewidths=1.5, hover_edgecolors=None, labels=None, label=None, transform='data', clip_display=True)[source]#

Add static horizontal lines at the given y positions.

Parameters:
  • transform (str)

  • clip_display (bool)

Return type:

MarkerGroup

add_vlines(x_values, name=None, *, color='#ff0000', linewidths=1.5, hover_edgecolors=None, labels=None, label=None, transform='data', clip_display=True)[source]#

Add static vertical lines at the given x positions.

Parameters:
  • transform (str)

  • clip_display (bool)

Return type:

MarkerGroup

add_arrows(offsets, U, V, name=None, *, edgecolors='#ff0000', linewidths=1.5, hover_edgecolors=None, labels=None, label=None, transform='data', clip_display=True)[source]#
Parameters:
  • transform (str)

  • clip_display (bool)

Return type:

MarkerGroup

add_ellipses(offsets, widths, heights, name=None, *, angles=0, facecolors=None, edgecolors='#ff0000', linewidths=1.5, alpha=0.3, hover_edgecolors=None, hover_facecolors=None, labels=None, label=None, transform='data', clip_display=True, size_units='data')[source]#
Parameters:
  • transform (str)

  • clip_display (bool)

  • size_units (str)

Return type:

MarkerGroup

add_lines(segments, name=None, *, edgecolors='#ff0000', linewidths=1.5, hover_edgecolors=None, labels=None, label=None, transform='data', clip_display=True)[source]#
Parameters:
  • transform (str)

  • clip_display (bool)

Return type:

MarkerGroup

add_rectangles(offsets, widths, heights, name=None, *, angles=0, facecolors=None, edgecolors='#ff0000', linewidths=1.5, alpha=0.3, hover_edgecolors=None, hover_facecolors=None, labels=None, label=None, transform='data', clip_display=True, size_units='data')[source]#
Parameters:
  • transform (str)

  • clip_display (bool)

  • size_units (str)

Return type:

MarkerGroup

add_squares(offsets, widths, name=None, *, angles=0, facecolors=None, edgecolors='#ff0000', linewidths=1.5, alpha=0.3, hover_edgecolors=None, hover_facecolors=None, labels=None, label=None, transform='data', clip_display=True, size_units='data')[source]#
Parameters:
  • transform (str)

  • clip_display (bool)

  • size_units (str)

Return type:

MarkerGroup

add_polygons(vertices_list, name=None, *, facecolors=None, edgecolors='#ff0000', linewidths=1.5, alpha=0.3, hover_edgecolors=None, hover_facecolors=None, labels=None, label=None, transform='data', clip_display=True)[source]#
Parameters:
  • transform (str)

  • clip_display (bool)

Return type:

MarkerGroup

add_texts(offsets, texts, name=None, *, color='#ff0000', fontsize=12, hover_edgecolors=None, labels=None, label=None, transform='data', clip_display=True)[source]#
Parameters:
  • transform (str)

  • clip_display (bool)

Return type:

MarkerGroup