You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add sdata.pl.annotate() — interactive region selection via anywidget
Productionises the Sandbox.ipynb prototype as a user-facing method on
PlotAccessor. Public surface is a single function:
sdata.pl.annotate(coordinate_system, element, *, persist=True) -> None
Both args are required positional. The function validates that the image
element is registered in the given coordinate system, renders it to a PNG,
constructs an internal _InteractiveSession with anywidget-driven drawing
tools (rectangle / polygon / lasso), and displays the widget. Drawn shapes
are written into sdata.shapes[name] on click of the Save button; the
optional "Write to disk" button persists via sdata.write_element.
Module layout (src/spatialdata_plot/pl/interactive/):
- _canvas.py DrawCanvas anywidget class
- static/draw_canvas.js ESM module read from disk by anywidget (HMR-friendly)
- _render.py render_to_png: sdata.pl → PNG + ax extent
- _commit.py pixel-coord shape → CS-coord shapely Polygon → ShapesModel
- _persist.py commit_to_memory + persist_to_disk (collision policy)
- _session.py _InteractiveSession orchestrating the widget
The new optional extra `interactive` (anywidget, ipykernel, ipywidgets)
gates this feature behind a clear ImportError when missing:
pip install 'spatialdata-plot[interactive]'
The prototype iteration explored ipympl (rejected: PNG-over-websocket
latency unusable over SSH) and plotly's FigureWidget (rejected: client-
side relayout events don't sync back to Python in VSCode-Remote, plus
plotly 6's anywidget-backed FigureWidget broke the comm path entirely).
The custom anywidget approach was the only architecture that worked
reliably over SSH while staying responsive.
Drawing UX:
- Tools: rect (drag), polygon (click + snap-close), lasso (drag freehand)
- Wheel zoom, shift-drag pan, alt-click shape to delete
- Ctrl+Z undo, R/P/L tool shortcuts, F fit view, Enter close polygon
- Multi-shape bundling: each Save commits all canvas shapes as one
ShapesModel with multiple rows under a single name
Tests cover the unit surface (pixel→CS conversion, ShapesModel transform
registration, render-to-PNG correctness, commit/persist policy, widget
smoke).
Spec at plans/interactive-selection.md updated to document the
architectural pivot from the original ipympl approach.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments