Selection synchronization (views, pages, filters, Python)#
Highlighting feels “simple” until you use multi-view snapshots, change filters, or try to coordinate with Python/Jupyter. This page makes the scope rules explicit so you can predict what will happen.
At A Glance#
Audience
Wet lab / beginner: understand “why did my selection disappear when I clicked another panel?”
Computational users: understand reproducibility and what is view-scoped vs global.
Developers: understand which state lives in the viewer vs the app state, and what is session-persisted.
Time
~15–25 minutes
Prerequisites
Familiarity with views/snapshots:
../c_core_interactions/04_view_layout_live_snapshots_small_multiples
Familiarity with the highlight UI:
03_highlight_ui
What you’ll learn
What syncs across views/snapshots
What switching highlight pages changes (and what it does not)
How filters affect selection and highlight visibility
What to expect from Python/Jupyter integration (and how to diagnose when it’s not active)
The scopes table (bookmark this)#
Thing |
Scope |
Persists? |
Notes |
|---|---|---|---|
Filters / visibility mask |
Per view (live + each snapshot may differ) |
Session (dataset-dependent) |
Filters control which cells are selectable and drawn in that view. |
Selection tool mode (annotation / lasso / proximity / KNN) |
Global UI choice |
Session (dataset-dependent layout) |
Affects how |
Selection candidate set (in-progress selection) |
Global (shared across tools) |
No |
Temporary; can be confirmed into a group or canceled. |
Preview highlight (while selecting) |
Global, rendered per view |
No |
Shown only for visible cells in each view. |
Highlight pages |
Global (dataset-scoped) |
Yes (session, dataset-dependent) |
Pages are alternate “workspaces” of highlight groups. |
Highlight groups (inside a page) |
Global (dataset-scoped), but page-local |
Yes (session, dataset-dependent) |
Groups store explicit arrays of cell indices. |
Active highlight page |
Global |
Yes (session, dataset-dependent) |
Switching pages changes which groups contribute to highlighting. |
Dataset identity |
Global |
N/A |
Cell indices are meaningful only for a specific dataset ordering. |
Important
If a session’s dataset fingerprint does not match the currently loaded dataset, dataset-dependent state (including highlights) is intentionally skipped on restore.
Sync between views and snapshots#
What users usually expect#
People typically expect:
“If I highlight cells, they should highlight in every panel.”
“If I select cells in one view, I should see the corresponding cells in other views.”
“If I switch focus to a different view panel, I shouldn’t lose my selection.”
What actually happens (current behavior)#
Permanent highlights (confirmed groups)
Are global: once you confirm a selection into a group, those cells are highlighted across all panels.
Are still subject to visibility: each panel will only show highlights for cells that are visible in that panel (filters apply per view).
In-progress selection (candidate set + preview highlight)
The candidate set is global (shared across selection tools).
The preview highlight is global, but rendered per view (visible cells only).
The gesture you perform is tied to the specific panel you start it in (especially for lasso).
Lasso in multi-view grid
Lasso selection is anchored to the panel you started drawing in.
Keep the lasso path inside one panel to avoid “wrong panel” confusion.
Proximity/KNN in multi-view
The seed click happens in one panel, but the resulting selected indices are global.
Filters in the target panel can affect which cells are selectable (filtered-out cells are excluded).
Common confusion patterns (and the mental fix)#
“I selected in panel A but panel B didn’t change.”
Most likely: panel B is filtering out those cells (visibility differs).
Or: you have not confirmed (you are only seeing preview highlight, and the other panel is hiding those cells).
“My selection disappeared when I clicked another panel.”
Often: you changed focus, not state.
Look for the step controls: if they still show your step count and candidate count, the selection is still in progress.
“I switched from Grid compare to Edit selected view and things changed.”
Layout changes can change what you notice (one panel full size vs small multiples), but the underlying highlight page/group state is global.
Sync with filtering and color-by#
Filters and selection#
Selection tools only select visible cells. This is intentional:
it prevents selecting “ghost” cells you cannot see,
it makes selection consistent across multi-view where each panel may have different filters.
Practical workflow tip:
If your goal is “select all cells in category X across the dataset”, disable filters first.
Filters and confirmed highlights#
Confirmed highlights can include cells that are currently filtered out (because you confirmed them earlier when they were visible).
This is why the highlight count can show:
“X of Y highlighted cells visible”
Color-by and selection/highlighting#
Changing the active color-by field:
does not change group membership,
can change which selection tool behaviors are available for annotation-based selection (because that tool depends on the active field’s kind: categorical vs continuous),
can change how easy it is to visually judge the correctness of your selection.
Sync with highlight pages#
What switching pages does#
Switching the active highlight page:
changes which groups contribute to highlighting,
changes what appears in the group list,
changes the highlight count and what is emphasized in the canvas.
What switching pages does not do#
Switching pages does not:
change filters (visibility masks),
change the dataset,
automatically “merge” pages (you must explicitly combine pages via union/intersection).
Page combine (union / intersection) is a reproducibility tool#
Because page combination is a deterministic set operation, it’s a good way to:
create a derived page that’s stable and shareable (via sessions),
avoid manual “redo selection” when you want intersections/unions of prior work.
Python/Jupyter synchronization (advanced)#
Cellucid has a Jupyter bridge via cellucid-python. Conceptually, it supports two directions:
Python → UI (commands)#
Examples from cellucid-python include:
viewer.highlight_cells([...])viewer.set_color_by("cell_type")viewer.set_visibility([...], visible=False)
These commands identify cells by cell index. That means they only make sense when:
the dataset in the viewer is the one you think it is, and
indices are aligned with your Python object (AnnData ordering).
UI → Python (events / hooks)#
UI interactions POST events to the Python server (/_cellucid/events), so hooks like @viewer.on_selection can fire.
Important nuance for selection:
In notebooks, the selection event is emitted when you confirm a selection (i.e. when it becomes a real highlight group), not while you are mid-dragging with a preview highlight.
Hover/click events are high-frequency; hover is debounced.
If you are debugging Python synchronization, start from:
cellucid/markdown/HOOKS_DEVELOPMENT.md
Common failure modes (Python/Jupyter)#
Wrong
viewerId(messages routed to the wrong embedded viewer)Dataset mismatch (indices don’t refer to the same cells)
Server unreachable from the viewer (HTTPS/remote notebooks without Jupyter Server Proxy, or remote/HPC without tunneling)
Embedded UI assets blocked (hosted-asset proxy blocked and no cached copy available)
First-line diagnostic:
viewer.debug_connection()(server probes + ping/pong + frontend debug snapshot + forwarded console errors)