Skip to content

feat: metadata filtering (#45) and force-categorical toggle (#35) - #51

Merged
RaredonLab merged 1 commit into
RaredonLab:devfrom
msraredon:dev
Aug 6, 2026
Merged

feat: metadata filtering (#45) and force-categorical toggle (#35)#51
RaredonLab merged 1 commit into
RaredonLab:devfrom
msraredon:dev

Conversation

@RaredonLab

Copy link
Copy Markdown
Owner

Closes #35
Closes #45

Both issues are the same question asked twice — "what kind of thing is this metadata column?" — so they share one module, readers/metadata_filter.py.

#35 — treat as categorical
Integer cluster IDs from Seurat were routed to a viridis gradient by dtype.
color_values() and edge_color_values() now take an explicit categorical
override, and category labels sort numerically so cluster 10 follows 2.

_color_values_meta moves to the base class. All six readers carried a
near-identical copy and the copies had drifted: CosMx filled NaN with ""/0
where the others dropped it, and only some sorted with key=str. A reader now
supplies only _metadata_frame().

The frontend stops guessing the type from the schema dtype — it could not,
since the rule also depends on cardinality. The old guess disagreed for
exactly the columns this issue is about: the canvas drew discrete colours
while the panel showed a gradient with two sliders that did nothing. Panel 0
now reports the type the backend returned. That also removed the duplicate
color-values fetch both legends were making for themselves.

#45 — select cells and edges by metadata
A MetadataFilter is a categorical allowlist or an inclusive numeric range,
resolved server-side and applied BEFORE sampling. That ordering is the point:
both queries sample on the server, so a client-side filter would leave a
fraction of a subset — a cluster holding 5% of cells at a 10% sample would
draw 0.5% of the tissue.

cell_boundaries() takes cell_ids in all five readers. query_grouped() takes
cell_ids and edge_filter; an edge survives only when both endpoints do, since
a half-outside edge runs off to a cell that is not drawn. Large id sets go
through a registered DuckDB relation rather than an IN list.

An unknown column raises 400 rather than rendering everything under an
apparently-active filter.

Also fixed, because the filter exposed it: useCellBoundaries picks its auto fraction from the previous fetch's total, which a filter invalidates, and nothing else triggered a refetch — so the layer sat showing a tenth of an already-small subset until the user panned. It now recalibrates once.

Guard extended to 191 probes across 7 datasets, covering both features on every platform. The demo fixture gains a 12-level seurat_clusters column so the repo's own data reproduces #35.

…RaredonLab#35)

Closes RaredonLab#35
Closes RaredonLab#45

Both issues are the same question asked twice — "what kind of thing is this
metadata column?" — so they share one module, readers/metadata_filter.py.

RaredonLab#35 — treat as categorical
  Integer cluster IDs from Seurat were routed to a viridis gradient by dtype.
  color_values() and edge_color_values() now take an explicit `categorical`
  override, and category labels sort numerically so cluster 10 follows 2.

  _color_values_meta moves to the base class. All six readers carried a
  near-identical copy and the copies had drifted: CosMx filled NaN with ""/0
  where the others dropped it, and only some sorted with key=str. A reader now
  supplies only _metadata_frame().

  The frontend stops guessing the type from the schema dtype — it could not,
  since the rule also depends on cardinality. The old guess disagreed for
  exactly the columns this issue is about: the canvas drew discrete colours
  while the panel showed a gradient with two sliders that did nothing. Panel 0
  now reports the type the backend returned. That also removed the duplicate
  color-values fetch both legends were making for themselves.

RaredonLab#45 — select cells and edges by metadata
  A MetadataFilter is a categorical allowlist or an inclusive numeric range,
  resolved server-side and applied BEFORE sampling. That ordering is the point:
  both queries sample on the server, so a client-side filter would leave a
  fraction of a subset — a cluster holding 5% of cells at a 10% sample would
  draw 0.5% of the tissue.

  cell_boundaries() takes cell_ids in all five readers. query_grouped() takes
  cell_ids and edge_filter; an edge survives only when both endpoints do, since
  a half-outside edge runs off to a cell that is not drawn. Large id sets go
  through a registered DuckDB relation rather than an IN list.

  An unknown column raises 400 rather than rendering everything under an
  apparently-active filter.

Also fixed, because the filter exposed it: useCellBoundaries picks its auto
fraction from the previous fetch's total, which a filter invalidates, and
nothing else triggered a refetch — so the layer sat showing a tenth of an
already-small subset until the user panned. It now recalibrates once.

Guard extended to 191 probes across 7 datasets, covering both features on every
platform. The demo fixture gains a 12-level seurat_clusters column so the repo's
own data reproduces RaredonLab#35.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@RaredonLab
RaredonLab merged commit 56587f5 into RaredonLab:dev Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow user to select cells/edges by meta data Force-categorical toggle for numeric metadata columns (cluster IDs)

2 participants