spacr.qt.widgets.umap_explorer

Interactive Image UMAP viewer with click, lasso, and DB annotation.

The lasso also shows where the selected cells are on the plate: the explorer joins the shared selection through spacr.qt.linked_selection.LinkedView: a lasso publishes the objects it caught, and a selection made anywhere else lights up the same points here.

The two directions are deliberately asymmetric, because a filter and a selection are not the same thing:

  • an incoming selection draws a ring around the matching points and changes nothing else. It never removes a point, and it never becomes the local lasso — “Label lasso selection” keeps meaning the lasso drawn here, or a highlight arriving from the database browser could write annotations the user never drew.

  • an incoming filter dims the points it excludes. Removing them would redraw the embedding around the remaining points, so the axes would move each time a filter changed.

Classes

ImageUmapExplorer

Zoomable embedding: click a point, lasso a group, write labels.

UmapDisplaySettings

One window holding every Image UMAP display setting.

Functions

as_settings_keys(→ Dict)

Map Image UMAP display keys to their persisted setting names.

Module Contents

class spacr.qt.widgets.umap_explorer.ImageUmapExplorer(parent=None)[source]

Bases: spacr.qt.linked_selection.LinkedView, PySide6.QtWidgets.QWidget

Zoomable embedding: click a point, lasso a group, write labels.

Linked to the shared selection as "umap". See the module docstring for why an incoming selection highlights and an incoming filter dims.

Parameters:

parent – parent widget.

Build the explorer: the embedding, the gallery and the writers.

Parameters:

parent – parent widget.

apply_display(values: Dict) → bool[source]

Apply display settings to the figure that is already on screen.

Parameters:

values – {display key: value}; keys the explorer does not know and None values are skipped, and None for the whole mapping changes nothing.

Returns:

True when something changed and the canvas was redrawn.

The embedding is never changed. Only the keys in LIVE_DISPLAY_KEYS are applied; anything else is stored for the next run and reported by the caller as needing a re-run.

closeEvent(event)[source]

Stop background work and unlink before going away.

Parameters:

event – the Qt close event.

display_settings() → Dict[source]

The current display values, as plain data.

linked_points() → numpy.ndarray[source]

Indices of the points a selection made elsewhere is highlighting.

on_linked_filter_changed(data_filter: spacr.selection.DataFilter) → None[source]

Re-draw for a filter another view has just set.

Parameters:

data_filter – the new shared filter.

on_linked_selection_changed(selection: spacr.selection.Selection) → None[source]

Ring the points another view selected. Nothing is hidden, and the local lasso — which is what the annotation buttons write — is left exactly as the user drew it.

Parameters:

selection – the Selection another view published; the points whose object keys it names are ringed, and an inactive selection rings none.

open_display_settings() → None[source]

Open the display settings window, apply the live settings, and propagate all of them.

point_keys() → pandas.Index | None[source]

The object key of each point, or None when unidentifiable.

set_payload(payload: Dict) → None[source]

Load the arrays/records attached by generate_image_umap.

payload['frame'] is optional: a DataFrame with one row per point, carrying whatever the caller measured. Without it the explorer can still identify its points (from the records’ prcfo) and so still publishes and receives selections — but a filter on a measurement column has nothing here to test, and is reported as ignored rather than silently drawing everything as if it had applied.

Parameters:

payload – the dict attached by generate_image_umap: embedding (shape (N, 2)), labels and records of the same length, and optionally frame (a DataFrame with N rows) and display (initial display values). A wrong shape or length raises ValueError.

set_propagate_callback(callback) → None[source]

Register callback(dict) to push values into the settings panel.

Optional: the explorer is usable without one, and a widget built in a test has none.

Parameters:

callback – called with a dict of settings, keyed by their persisted names, after the display settings window is accepted; any exception it raises is logged and ignored.

show_point(index: int) → None[source]

Preview one point’s image and database identity.

Parameters:

index – position of the point in the payload’s records; converted to int, and an out-of-range index does nothing.

visible_points() → numpy.ndarray[source]

Boolean mask of the points the shared filter keeps.

class spacr.qt.widgets.umap_explorer.UmapDisplaySettings(values: Dict, parent=None)[source]

Bases: PySide6.QtWidgets.QDialog

One window holding every Image UMAP display setting.

Some apply to the figure on screen and some cannot, and the window says which.

The ones that cannot are not disabled – they are editable, saved, and take effect on the next run.

Parameters:
  • values – the settings to open on. Every key in FIELDS is looked up here; one that is absent falls back to its control’s own default rather than raising, so a settings file written before a field existed still opens.

  • parent – parent widget.

Build the display-settings dialog.

Parameters:
  • values – the settings to start from.

  • parent – parent widget.

live_values() → Dict[source]

Only the values that can be applied to the figure already on screen.

values() → Dict[source]

What the user set, keyed as the settings dict keys.

spacr.qt.widgets.umap_explorer.as_settings_keys(values: Dict) → Dict[source]

Map Image UMAP display keys to their persisted setting names.

Parameters:

values – display values keyed by display name; keys in SETTINGS_KEY_FOR_DISPLAY are renamed and the rest kept as they are. None gives an empty dict.

Nested helpers

ImageUmapExplorer._build_ui._OwnedTimerFigureCanvas.__init__(self, figure)

Wrap a figure in a canvas that owns its own redraw timer.

Parameters:

figure – the Matplotlib Figure to draw. The timer is a child of this canvas, so a queued redraw cannot outlive the object it would draw on – which is what the paragraph above means by owned.

spacr/qt/widgets/umap_explorer.py:437

ImageUmapExplorer._build_ui._OwnedTimerFigureCanvas._spacr_draw(self)

Draw once, if a draw is still pending.

The pending flag is cleared first, so a draw that itself schedules another does not lose it.

spacr/qt/widgets/umap_explorer.py:456

ImageUmapExplorer._build_ui._OwnedTimerFigureCanvas.cancel_pending_draw(self)

Drop any queued redraw.

spacr/qt/widgets/umap_explorer.py:470

ImageUmapExplorer._build_ui._OwnedTimerFigureCanvas.draw_idle(self)

Queue a redraw on the canvas’s own timer.

spacr/qt/widgets/umap_explorer.py:450