Interactive Widgets#

anyplotlib.widgets — interactive overlay widget classes.

Base Class

Widget

Base class for all overlay widgets.

Concrete Widgets

RectangleWidget

Draggable rectangle overlay widget for 2-D plots.

CircleWidget

Draggable circle overlay widget for 2-D plots.

AnnularWidget

Draggable annular (ring) overlay widget for 2-D plots.

CrosshairWidget

Draggable crosshair overlay widget for 2-D plots.

PolygonWidget

Draggable polygon overlay widget for 2-D plots.

BrushWidget

Freehand paint-brush overlay widget for 2-D plots.

LabelWidget

Text label overlay widget for 2-D plots.

VLineWidget

Draggable vertical line overlay widget for 1-D plots.

HLineWidget

Draggable horizontal line overlay widget for bar charts.

RangeWidget

Draggable range selection widget.

Full Reference

class anyplotlib.widgets.Widget(wtype, push_fn, **kwargs)[source]

Bases: _EventMixin

Base class for all overlay widgets.

Provides attribute-based state access, callbacks for interaction events, and automatic synchronization with the JavaScript renderer.

Parameters:
  • wtype (str) – Widget type (e.g., ‘rectangle’, ‘circle’, ‘crosshair’).

  • push_fn (Callable) – Zero-arg callback to send position updates to the JavaScript renderer.

  • **kwargs (dict) – Initial widget state (position, size, color, etc.).

callbacks

Event callback registry. Register handlers via widget.add_event_handler(fn, "pointer_move") or as a decorator: @widget.add_event_handler("pointer_move").

Common event types:

  • "pointer_move" — fires on every drag frame

  • "pointer_up" — fires once when drag settles

  • "pointer_down" — fires on click/press event

Type:

CallbackRegistry

set(_push=True, _notify=True, **kwargs)[source]

Update properties and send targeted update to JavaScript.

Parameters:
  • _push (bool, optional) – Whether to push update to renderer. Default True. Set to False internally to avoid echo loops.

  • _notify (bool, optional) –

    Whether to fire pointer_move callbacks. Default True.

    A set() from Python is otherwise indistinguishable from a user drag: handlers that react to the widget moving will run, and one that writes back to the widget feeds into itself. Pass _notify=False when you are the one moving the widget and the handlers are only meant to hear about user input:

    widget.set(_notify=False, x=new_x)
    

    This supersedes wrapping the call in pause_events(), which suppresses every event type for the duration rather than just this update’s echo.

  • **kwargs (dict) – Properties to update (e.g., x=100, y=50, radius=20).

Return type:

None

Notes

Both flags are spelled with a leading underscore so they can never collide with a widget property of the same name in **kwargs.

Updates are sent as targeted widget updates, not full panel re-renders. This is more efficient for frequent updates during dragging.

get(key, default=None)[source]

Get a widget property by name.

Parameters:
  • key (str) – Property name.

  • default (optional) – Default value if property not found.

Returns:

The property value.

Return type:

object

to_dict()[source]

Return a dict copy of the widget state.

Returns:

All widget properties including id and type.

Return type:

dict

property visible: bool

True if the widget is rendered; False if hidden.

show()[source]

Show the widget. Does not fire pointer_move callbacks.

Return type:

None

hide()[source]

Hide the widget without removing it or its callbacks.

Call show() to make it visible again. Does not fire pointer_move callbacks.

Return type:

None

remove()[source]

Remove this widget from the plot that owns it.

Equivalent to plot.remove_widget(widget), but callable when you only hold the widget — handle-based APIs otherwise have to re-derive the owning plot to delete something they already have.

Removing a widget that is not attached to a plot, or removing twice, is a no-op.

Return type:

None

property id: str

Return the widget’s unique identifier.

class anyplotlib.widgets.RectangleWidget(push_fn, *, x, y, w, h, color='#00e5ff', linewidth=2, show_handles=True, max_extent=None)[source]

Bases: Widget

Draggable rectangle overlay widget for 2-D plots.

Parameters:
  • push_fn (Callable) – Update callback.

  • x (float) – Top-left corner position in pixel/data coordinates.

  • y (float) – Top-left corner position in pixel/data coordinates.

  • w (float) – Width and height in pixel/data coordinates.

  • h (float) – Width and height in pixel/data coordinates.

  • color (str, optional) – CSS colour for the rectangle outline. Default "#00e5ff".

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

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

  • max_extent (float or (float, float), optional) –

    Maximum width/height in the widget’s coordinates. A scalar caps both axes; a (max_w, max_h) pair caps them separately. When set, the rectangle physically stops growing at the cap while dragging — the dragged corner pins and the opposite corner stays put. None (default) leaves it unbounded.

    Use this when the rectangle’s area costs real work downstream — e.g. an integrating ROI whose size is a number of frames to read.

class anyplotlib.widgets.CircleWidget(push_fn, *, cx, cy, r, color='#00e5ff', linewidth=2, show_handles=True)[source]

Bases: Widget

Draggable circle overlay widget for 2-D plots.

Parameters:
  • push_fn (Callable) – Update callback.

  • cx (float) – Center position in pixel/data coordinates.

  • cy (float) – Center position in pixel/data coordinates.

  • r (float) – Radius in pixel/data coordinates.

  • color (str, optional) – CSS colour for the circle outline. Default "#00e5ff".

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

  • show_handles (bool, optional) – Draw the radius grab handle. Default True.

class anyplotlib.widgets.AnnularWidget(push_fn, *, cx, cy, r_outer, r_inner, color='#00e5ff', linewidth=2, show_handles=True)[source]

Bases: Widget

Draggable annular (ring) overlay widget for 2-D plots.

Parameters:
  • push_fn (Callable) – Update callback.

  • cx (float) – Center position in pixel/data coordinates.

  • cy (float) – Center position in pixel/data coordinates.

  • r_outer (float) – Outer and inner radii in pixel/data coordinates. Inner radius must be less than outer radius.

  • r_inner (float) – Outer and inner radii in pixel/data coordinates. Inner radius must be less than outer radius.

  • color (str, optional) – CSS colour for the ring outline. Default "#00e5ff".

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

  • show_handles (bool, optional) – Draw the inner/outer radius grab handles. Default True.

Raises:

ValueError – If r_inner >= r_outer.

class anyplotlib.widgets.CrosshairWidget(push_fn, *, cx, cy, color='#00e5ff', linewidth=2, show_handles=True)[source]

Bases: Widget

Draggable crosshair overlay widget for 2-D plots.

Parameters:
  • push_fn (Callable) – Update callback.

  • cx (float) – Center position in pixel/data coordinates.

  • cy (float) – Center position in pixel/data coordinates.

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

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

  • show_handles (bool, optional) – Draw the centre dot handle. Default True.

class anyplotlib.widgets.PolygonWidget(push_fn, *, vertices, color='#00e5ff', linewidth=2, show_handles=True)[source]

Bases: Widget

Draggable polygon overlay widget for 2-D plots.

Parameters:
  • push_fn (Callable) – Update callback.

  • vertices (list of tuple) – Polygon vertices [(x0, y0), (x1, y1), ...] in pixel/data coordinates. Must have at least 3 vertices.

  • color (str, optional) – CSS colour for the polygon outline. Default "#00e5ff".

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

  • show_handles (bool, optional) – Draw the per-vertex grab handles. Default True.

Raises:

ValueError – If fewer than 3 vertices provided.

class anyplotlib.widgets.BrushWidget(push_fn, *, radius=8.0, color='#00e5ff', colors=None, class_id=0, strokes=None, stroke_classes=None, alpha=0.6, active=True, erase=False)[source]

Bases: Widget

Freehand paint-brush overlay widget for 2-D plots.

Shift-drag on the image to paint a stroke; every stroke is a polyline of image-pixel points, stroked with round caps and joins at a width of 2 * radius image pixels. Built for labelling regions — painting training scribbles for a pixel classifier, marking a defect, masking a beam stop — where a polygon or a rectangle is the wrong shape.

Two gates govern the painting so a brush can coexist with pan / click / other widgets on the same panel:

  1. active — Python-side arming. False keeps the strokes drawn but ignores all input, which is how you park the tool without losing work.

  2. Shift — the drag modifier. A bare drag still pans the image and still drags other widgets; only Shift + drag paints. A brush that claimed a plain drag would hit-test as “anywhere in the image” and kill panning and click-to-select outright.

Painting is modal: while a brush is armed, a Shift-press that starts over the image is consumed by the brush and no longer produces a panel pointer_down. If the host binds Shift-click to something else (multi-select is the common one), give it a different modifier or set active=False while that mode is on. A Shift-drag beginning outside the image — in the axis margin — is not a brush gesture and pans as usual.

While the stroke is being drawn the points accumulate in the browser and only the finished stroke reaches Python, once, as a pointer_up event. So pointer_move does not fire for a brush stroke — register on pointer_up:

brush = plot.add_brush_widget(radius=6, colors=["#f44", "#4f4"])

@brush.add_event_handler("pointer_up")
def stroke_done(event):
    update_labels(brush.strokes, brush.stroke_classes)
Parameters:
  • push_fn (Callable) – Update callback.

  • radius (float, optional) – Brush radius in image pixels — the painted band is 2 * radius wide, and an erase drag removes stroke points within this distance. Default 8.

  • color (str, optional) – CSS colour used when colors has no entry for a stroke’s class. Default "#00e5ff".

  • colors (list of str, optional) – Per-class CSS colours, indexed by class_id. Lets one brush carry several label classes at once. Default None (every class draws in color).

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

  • strokes (list, optional) – Pre-existing strokes, [[[x, y], ...], ...] in image-pixel coordinates. Default None (empty).

  • stroke_classes (list of int, optional) – Class id per entry of strokes; must be the same length. Default None (every seeded stroke takes class_id).

  • alpha (float, optional) – Stroke opacity in [0, 1]. Default 0.6 — a scribble you can see the image through, since the point is to label what is underneath.

  • active (bool, optional) – Accept Shift-drag painting. Default True.

  • erase (bool, optional) – When True an armed drag removes stroke points within radius instead of painting. Default False.

strokes

Painted strokes, [[[x, y], ...], ...] in image pixels. Read-only in practice — mutating the list in place does not reach the renderer; use add_stroke() / set_strokes() / clear_strokes().

Type:

list

stroke_classes

Class id of each stroke, parallel to strokes.

Type:

list of int

Raises:

ValueError – If radius <= 0, class_id < 0, alpha is outside [0, 1], colors is not a sequence of strings, a stroke is malformed, or stroke_classes does not match strokes in length.

See also

PolygonWidget

Closed straight-edged region with draggable vertices.

property n_strokes: int

Number of painted strokes.

clear_strokes()[source]

Discard every painted stroke. Does not change class_id.

Return type:

None

add_stroke(points, class_id=None)[source]

Append one stroke.

Parameters:
  • points (list of tuple) – [(x, y), ...] in image-pixel coordinates; at least one point.

  • class_id (int, optional) – Label class for this stroke. Defaults to the widget’s current class_id.

Raises:

ValueError – If points is empty or a point is not an (x, y) pair.

Return type:

None

set_strokes(strokes, classes=None)[source]

Replace every stroke (and its class) in one push.

This is the sanctioned way to write strokes: it keeps the parallel stroke_classes list in lockstep, which a bare brush.strokes = ... assignment cannot do.

Parameters:
  • strokes (list) – [[[x, y], ...], ...] in image-pixel coordinates.

  • classes (list of int, optional) – Class id per stroke. Defaults to the widget’s current class_id for every stroke.

Raises:

ValueError – If a stroke is malformed or classes has the wrong length.

Return type:

None

strokes_for_class(class_id)[source]

Return only the strokes tagged with class_id.

Parameters:

class_id (int) – Label class to select.

Returns:

[[[x, y], ...], ...] — the matching strokes, in paint order.

Return type:

list

class anyplotlib.widgets.LabelWidget(push_fn, *, x, y, text='Label', fontsize=14, color='#00e5ff', show_handles=True)[source]

Bases: Widget

Text label overlay widget for 2-D plots.

Parameters:
  • push_fn (Callable) – Update callback.

  • x (float) – Label position in pixel/data coordinates.

  • y (float) – Label position in pixel/data coordinates.

  • text (str, optional) – Label text. Default "Label".

  • fontsize (int, optional) – Font size in points. Default 14.

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

  • show_handles (bool, optional) – Draw the anchor grab handle. Default True.

class anyplotlib.widgets.VLineWidget(push_fn, *, x, color='#00e5ff', linewidth=2, snap_values=None)[source]

Bases: Widget

Draggable vertical line overlay widget for 1-D plots.

Allows interactive selection of a single x-axis value. The line can be dragged left/right to change the selected position.

Parameters:
  • push_fn (Callable) – Update callback.

  • x (float) – Initial x-position in data coordinates.

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

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

class anyplotlib.widgets.HLineWidget(push_fn, *, y, color='#00e5ff', linewidth=2, snap_values=None)[source]

Bases: Widget

Draggable horizontal line overlay widget for bar charts.

Allows interactive selection of a single y-axis value. The line can be dragged up/down to change the selected value.

Parameters:
  • push_fn (Callable) – Update callback.

  • y (float) – Initial y-position in data coordinates.

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

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

class anyplotlib.widgets.RangeWidget(push_fn, *, x0, x1, color='#00e5ff', style='band', y=0.0, linewidth=2, max_extent=None, orientation='horizontal', snap_values=None)[source]

Bases: Widget

Draggable range selection widget.

Two display styles are available:

style='band' (default)

Two connected vertical lines with a translucent fill band. Either line can be dragged independently; the whole band can be dragged by clicking inside it.

style='fwhm'

Two circular handles joined by a dashed horizontal line drawn at height y (the half-maximum level). Only the x-positions of the handles are draggable. Use this to show/edit a FWHM interval on a peak.

With orientation='vertical' the band spans the plot width and selects a range on the value axis instead — for picking an intensity window rather than a spectral one.

Parameters:
  • push_fn (Callable) – Update callback.

  • x0 (float) – The two edges of the range, in data coordinates along the selection axis: x positions when horizontal, y values when vertical. The names do not change with orientation, mirroring how matplotlib’s SpanSelector.extents is read the same way for either direction.

  • x1 (float) – The two edges of the range, in data coordinates along the selection axis: x positions when horizontal, y values when vertical. The names do not change with orientation, mirroring how matplotlib’s SpanSelector.extents is read the same way for either direction.

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

  • style ({'band', 'fwhm'}, optional) – Visual style. Default "band". 'fwhm' is horizontal-only.

  • y (float, optional) – Y-position (data coordinates) for the connecting line when style='fwhm'. Ignored for style='band'. Default 0.0.

  • orientation ({'horizontal', 'vertical'}, optional) – Which axis the range selects along. Default "horizontal".

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

  • max_extent (float, optional) –

    Maximum span width in DATA units. When set, the span physically stops growing at this width while dragging: the edge under the cursor is pinned and the opposite edge stays put, so the range never exceeds the cap and never jumps. None (default) leaves it unbounded.

    Use this when span width costs real work downstream — e.g. an integrating selector where the width is a number of frames to read. Enforcing it in the widget makes the limit visible (the edge simply stops) instead of applying a silent clamp after the fact.

  • snap_values (sequence of float, optional) – Allowed edge positions. While dragging, each edge follows the cursor but lands only on the nearest of these values — matplotlib’s SpanSelector.snap_values. None (default) drags continuously. Set it later with widget.snap_values = [...].

Raises:

ValueError – If orientation is not 'horizontal' or 'vertical', or if style='fwhm' is combined with a vertical orientation.