Summary
The current mask painter renders all cell masks exclusively as outlines. This feature request adds two related enhancements to the mask painter panel: (1) per-class paint mode — each cell class can be configured to render as either an outline or a filled (semi-transparent) polygon; (2) per-class visibility toggle — individual cell classes can be shown or hidden without affecting other classes. Together these allow users to highlight a cell type of interest as a filled overlay on top of the intensity image, while suppressing unimportant classes entirely.
Motivation / Use Case
When reviewing MIBI images it is common to want to visually inspect whether a classifier correctly identified a cell type of interest. The current outline-only rendering makes it difficult to spot small or densely packed cells. A filled semi-transparent overlay makes the spatial distribution of a class immediately legible against the raw intensity image underneath, and hiding unrelated classes at the same time reduces visual clutter.
Proposed UI Changes
In the mask painter panel (currently driven by mask_color_overlay.py + palette_store.py + ui_components.py), add a row of controls per cell class:
| Control |
Behavior |
| Visibility checkbox / eye icon |
Show / hide all cells of this class; unchecking removes them from the rendered overlay entirely |
| Paint mode toggle |
Two-state toggle: outline (current behavior) / filled (flood-fills the cell polygon at the class color with configurable alpha) |
| Opacity / alpha slider (optional) |
When filled mode is active, controls transparency (e.g. 0–100 %) |
The existing per-class color picker and the overall mask opacity slider should remain unchanged.
Proposed Implementation Notes
palette_store.py — extend the per-class state dict to include visible: bool and paint_mode: Literal["outline", "filled"] (plus an optional fill_alpha: float). Defaults: visible=True, paint_mode="outline" to preserve backward compatibility.
mask_color_overlay.py — update the compositing logic to branch on paint_mode: "outline" keeps the existing find_boundaries-based path; "filled" draws the full cell mask region at fill_alpha and optionally draws the boundary on top so cells remain distinguishable. Respect the visible flag by skipping the class entirely during compositing.
ui_components.py — add the eye-icon toggle and paint-mode button next to the existing color picker for each class row in the mask painter widget.
main_viewer.py — wire the new per-class state to the overlay re-render callback (same pattern as the existing color-change observer).
Acceptance Criteria
Related Files
Summary
The current mask painter renders all cell masks exclusively as outlines. This feature request adds two related enhancements to the mask painter panel: (1) per-class paint mode — each cell class can be configured to render as either an outline or a filled (semi-transparent) polygon; (2) per-class visibility toggle — individual cell classes can be shown or hidden without affecting other classes. Together these allow users to highlight a cell type of interest as a filled overlay on top of the intensity image, while suppressing unimportant classes entirely.
Motivation / Use Case
When reviewing MIBI images it is common to want to visually inspect whether a classifier correctly identified a cell type of interest. The current outline-only rendering makes it difficult to spot small or densely packed cells. A filled semi-transparent overlay makes the spatial distribution of a class immediately legible against the raw intensity image underneath, and hiding unrelated classes at the same time reduces visual clutter.
Proposed UI Changes
In the mask painter panel (currently driven by
mask_color_overlay.py+palette_store.py+ui_components.py), add a row of controls per cell class:outline(current behavior) /filled(flood-fills the cell polygon at the class color with configurable alpha)filledmode is active, controls transparency (e.g. 0–100 %)The existing per-class color picker and the overall mask opacity slider should remain unchanged.
Proposed Implementation Notes
palette_store.py— extend the per-class state dict to includevisible: boolandpaint_mode: Literal["outline", "filled"](plus an optionalfill_alpha: float). Defaults:visible=True,paint_mode="outline"to preserve backward compatibility.mask_color_overlay.py— update the compositing logic to branch onpaint_mode:"outline"keeps the existingfind_boundaries-based path;"filled"draws the full cell mask region atfill_alphaand optionally draws the boundary on top so cells remain distinguishable. Respect thevisibleflag by skipping the class entirely during compositing.ui_components.py— add the eye-icon toggle and paint-mode button next to the existing color picker for each class row in the mask painter widget.main_viewer.py— wire the new per-class state to the overlay re-render callback (same pattern as the existing color-change observer).Acceptance Criteria
outline,visible=True) exactly reproduces current behavior — no regressions.tests/coverspalette_storeserialization of the new fields and the compositing branch inmask_color_overlay.Related Files
ueler/viewer/mask_color_overlay.pyueler/viewer/palette_store.pyueler/viewer/ui_components.pyueler/viewer/main_viewer.py