CellierController¶
The top-level entry point for building and driving a cellier scene.
cellier.CellierController ¶
The main class for constructing and controlling a cellier visualization.
Wraps a ViewerModel (model layer) and a RenderManager (render layer) and performs the synchronization between both.
incoming_events
property
¶
Incoming event bus for GUI-driven model mutations.
Emit AppearanceUpdateEvent, DimsUpdateEvent, or
AABBUpdateEvent onto this bus to request model changes.
The controller dispatches each event to the corresponding
update_* method, preserving source_id end-to-end.
camera_reslice_enabled
property
writable
¶
camera_reslice_enabled: bool
Whether camera movement triggers automatic reslicing.
camera_settle_threshold_s
property
writable
¶
camera_settle_threshold_s: float
Debounce delay before reslice after camera movement.
set_widget_parent ¶
set_widget_parent(parent: object) -> None
Set the Qt parent for subsequently created canvas widgets.
Only meaningful when self._gui == "qt"; the anywidget gui ignores
the parent (notebook canvases are not laid out by a Qt parent).
from_model
classmethod
¶
from_model(model: ViewerModel, widget_parent: QWidget | None = None, render_config: RenderManagerConfig | None = None) -> CellierController
Construct a controller from a serialized ViewerModel.
Iteratively adds all data stores, scenes, visuals, and canvases through the public API. The order is:
- Data stores — registered before visuals reference them.
- Scenes — registered with render_modes and lighting from model.
- Visuals — added per scene; data stores must already be present.
- Canvases — restored with camera state from model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ViewerModel
|
A ViewerModel loaded from disk or constructed programmatically. |
required |
widget_parent
|
QWidget or None
|
Qt parent for canvas widgets. Defaults to None. |
None
|
render_config
|
RenderManagerConfig or None
|
Render pipeline configuration. Defaults to None (uses defaults). |
None
|
Returns:
| Type | Description |
|---|---|
CellierController
|
|
from_file
classmethod
¶
from_file(path: str | Path, widget_parent: QWidget | None = None, render_config: RenderManagerConfig | None = None) -> CellierController
Deserialize a ViewerModel from disk and construct a controller.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str or Path
|
Path to a JSON file previously written by |
required |
widget_parent
|
QWidget or None
|
Qt parent for canvas widgets. |
None
|
render_config
|
RenderManagerConfig or None
|
Render pipeline configuration. |
None
|
Returns:
| Type | Description |
|---|---|
CellierController
|
|
add_scene_model ¶
Register a pre-built Scene model with the controller.
Used by from_model to restore scenes from a serialized
ViewerModel, and called internally by add_scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene
|
Scene
|
Pre-built scene model. |
required |
Returns:
| Type | Description |
|---|---|
Scene
|
The same object passed in. |
add_scene ¶
add_scene(*, name: str = 'scene', dim: Literal['2d', '3d'] = '3d', coordinate_system: CoordinateSystem | None = None, render_modes: set[Literal['2d', '3d']] | None = None, lighting: Literal['none', 'default'] = 'none') -> Scene
Create a Scene from keyword arguments and register it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable scene name. |
'scene'
|
dim
|
'2d' or '3d'
|
Initial display dimensionality. |
'3d'
|
coordinate_system
|
CoordinateSystem or None
|
World coordinate system. Defaults to a 3-axis |
None
|
render_modes
|
set or None
|
Which rendering modes visuals should support. Defaults to
|
None
|
lighting
|
'none' or 'default'
|
Pass |
'none'
|
Returns:
| Type | Description |
|---|---|
Scene
|
The newly created and registered Scene. |
add_data_store ¶
Register a data store and return it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_store
|
BaseDataStore
|
The store to register. |
required |
Returns:
| Type | Description |
|---|---|
BaseDataStore
|
The same object passed in. |
add_visual ¶
add_visual(scene_id: UUID, visual_model: VisualType, data_store: BaseDataStore | None = None) -> VisualType
Register a pre-built visual model with a scene.
This is the canonical construction path used by from_model.
All typed convenience methods (add_image, add_mesh, etc.)
delegate to this method internally.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of an existing scene. |
required |
visual_model
|
VisualType
|
Pre-built visual model. Its |
required |
data_store
|
BaseDataStore or None
|
If provided, register the store first (no-op if already present),
then use it. If |
None
|
Returns:
| Type | Description |
|---|---|
VisualType
|
The same visual_model passed in. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
TypeError
|
If the visual type is not recognized. |
add_image ¶
add_image(data: ImageMemoryStore, scene_id: UUID, appearance: BaseImageAppearance, name: str = 'image') -> ImageVisual
Add an in-memory image visual to a scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ImageMemoryStore
|
The backing data store. |
required |
scene_id
|
UUID
|
ID of an existing scene. |
required |
appearance
|
BaseImageAppearance
|
Appearance parameters. |
required |
name
|
str
|
Human-readable label. Default |
'image'
|
Returns:
| Type | Description |
|---|---|
ImageVisual
|
|
add_labels ¶
add_labels(data: LabelMemoryStore, scene_id: UUID, appearance: BaseLabelsAppearance | None = None, name: str = 'labels', transform: AffineTransform | None = None) -> LabelMemoryVisual
Add an in-memory label visual to a scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
LabelMemoryStore
|
Backing int32 label store. |
required |
scene_id
|
UUID
|
ID of an existing scene. |
required |
appearance
|
BaseLabelsAppearance or None
|
Appearance parameters. Defaults to InMemoryLabelsAppearance(). |
None
|
name
|
str
|
Human-readable label. Default |
'labels'
|
transform
|
AffineTransform or None
|
Data-to-world transform. Defaults to identity when None. |
None
|
Returns:
| Type | Description |
|---|---|
LabelMemoryVisual
|
|
add_mesh ¶
add_mesh(data: MeshMemoryStore, scene_id: UUID, appearance: MeshAppearance, name: str = 'mesh', transform: AffineTransform | None = None) -> MeshVisual
Add a mesh visual to a scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
MeshMemoryStore
|
In-memory mesh. Normals are auto-computed if not supplied; indices are coerced to int32. |
required |
scene_id
|
UUID
|
ID of an existing scene. |
required |
appearance
|
MeshFlatAppearance | MeshPhongAppearance
|
Appearance. Use MeshPhongAppearance with |
required |
name
|
str
|
Human-readable label. Default |
'mesh'
|
transform
|
AffineTransform or None
|
Data-to-world transform for this visual. Defaults to identity when
|
None
|
Returns:
| Type | Description |
|---|---|
MeshVisual
|
|
add_points ¶
add_points(data: PointsMemoryStore, scene_id: UUID, appearance: PointsMarkerAppearance | None = None, name: str = 'points', transform: AffineTransform | None = None) -> PointsVisual
Add a points visual backed by a PointsMemoryStore.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
PointsMemoryStore
|
The backing data store. |
required |
scene_id
|
UUID
|
ID of the target scene. |
required |
appearance
|
PointsMarkerAppearance or None
|
Appearance model. Defaults to PointsMarkerAppearance() if None. |
None
|
name
|
str
|
Human-readable label for the visual. |
'points'
|
transform
|
AffineTransform or None
|
Data-to-world transform for this visual. Defaults to identity when
|
None
|
Returns:
| Type | Description |
|---|---|
PointsVisual
|
|
add_lines ¶
add_lines(data: LinesMemoryStore, scene_id: UUID, appearance: LinesMemoryAppearance | None = None, name: str = 'lines', transform: AffineTransform | None = None) -> LinesVisual
Add a lines visual backed by a LinesMemoryStore.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
LinesMemoryStore
|
The backing data store. |
required |
scene_id
|
UUID
|
ID of the target scene. |
required |
appearance
|
LinesMemoryAppearance or None
|
Appearance model. Defaults to LinesMemoryAppearance() if None. |
None
|
name
|
str
|
Human-readable label for the visual. |
'lines'
|
transform
|
AffineTransform or None
|
Data-to-world transform for this visual. Defaults to identity when
|
None
|
Returns:
| Type | Description |
|---|---|
LinesVisual
|
|
add_image_multiscale ¶
add_image_multiscale(data: BaseDataStore, scene_id: UUID, appearance: MultiscaleImageAppearance, name: str = 'image', render_config: MultiscaleImageRenderConfig | None = None, transform: AffineTransform | None = None) -> MultiscaleImageVisual
Add a multiscale image visual to a scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
BaseDataStore
|
The backing data store. |
required |
scene_id
|
UUID
|
ID of an existing scene. |
required |
appearance
|
MultiscaleImageAppearance
|
Visual appearance parameters. |
required |
name
|
str
|
Human-readable label. Default |
'image'
|
render_config
|
MultiscaleImageRenderConfig or None
|
Render-layer configuration. Defaults to
|
None
|
transform
|
AffineTransform or None
|
Data-to-world transform. Defaults to identity when None. |
None
|
Returns:
| Type | Description |
|---|---|
MultiscaleImageVisual
|
|
add_labels_multiscale ¶
add_labels_multiscale(data: BaseDataStore, scene_id: UUID, appearance: MultiscaleLabelsAppearance, name: str = 'labels', render_config: MultiscaleLabelRenderConfig | None = None, transform: AffineTransform | None = None) -> MultiscaleLabelVisual
Add a multiscale label visual to a scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
BaseDataStore
|
The backing label data store (e.g. |
required |
scene_id
|
UUID
|
ID of an existing scene. |
required |
appearance
|
MultiscaleLabelsAppearance
|
Visual appearance parameters. |
required |
name
|
str
|
Human-readable label. Default |
'labels'
|
render_config
|
MultiscaleLabelRenderConfig or None
|
Render-layer configuration. Defaults to
|
None
|
transform
|
AffineTransform or None
|
Data-to-world transform. Defaults to identity when None. |
None
|
Returns:
| Type | Description |
|---|---|
MultiscaleLabelVisual
|
|
add_multichannel_image ¶
add_multichannel_image(data: ImageMemoryStore, scene_id: UUID, channel_axis: int, channels: dict[int, ChannelAppearance], name: str = 'multichannel_image', max_channels_2d: int = 8, max_channels_3d: int = 4) -> MultichannelImageVisual
Add an in-memory multichannel image visual to a scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ImageMemoryStore
|
Backing data store. |
required |
scene_id
|
UUID
|
Target scene. |
required |
channel_axis
|
int
|
Data axis index for the channel dimension. |
required |
channels
|
dict[int, ChannelAppearance]
|
Per-channel appearance keyed by channel index. |
required |
name
|
str
|
Display name for the visual. |
'multichannel_image'
|
max_channels_2d
|
int
|
Maximum simultaneous 2D channel nodes. |
8
|
max_channels_3d
|
int
|
Maximum simultaneous 3D channel nodes. |
4
|
Returns:
| Type | Description |
|---|---|
MultichannelImageVisual
|
|
add_multichannel_image_multiscale ¶
add_multichannel_image_multiscale(data: BaseDataStore, scene_id: UUID, channel_axis: int, channels: dict[int, ChannelAppearance], name: str = 'multichannel_image', render_config: MultiscaleImageRenderConfig | None = None, transform: AffineTransform | None = None, max_channels_2d: int = 8, max_channels_3d: int = 4) -> MultichannelMultiscaleImageVisual
Add a multiscale multichannel image visual to a scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
BaseDataStore
|
Backing multiscale data store. |
required |
scene_id
|
UUID
|
Target scene. |
required |
channel_axis
|
int
|
Data axis index for the channel dimension. |
required |
channels
|
dict[int, ChannelAppearance]
|
Per-channel appearance keyed by channel index. |
required |
name
|
str
|
Display name for the visual. |
'multichannel_image'
|
render_config
|
MultiscaleImageRenderConfig or None
|
LOD and rendering configuration; uses defaults when |
None
|
transform
|
AffineTransform or None
|
Data-to-world transform; uses identity when |
None
|
max_channels_2d
|
int
|
Maximum simultaneous 2D channel nodes. |
8
|
max_channels_3d
|
int
|
Maximum simultaneous 3D channel nodes. |
4
|
Returns:
| Type | Description |
|---|---|
MultichannelMultiscaleImageVisual
|
|
add_channel ¶
add_channel(visual_id: UUID, channel_index: int, appearance: ChannelAppearance) -> None
Add a channel to a multichannel image visual.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
ID of a MultichannelImageVisual or MultichannelMultiscaleImageVisual. |
required |
channel_index
|
int
|
Index along the visual's channel_axis. Must not already be present. |
required |
appearance
|
ChannelAppearance
|
Colormap, clim, and opacity settings for the new channel. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If channel_index is already present. |
RuntimeError
|
If the pool is full. |
remove_channel ¶
Remove a channel from a multichannel image visual.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
ID of a MultichannelImageVisual or MultichannelMultiscaleImageVisual. |
required |
channel_index
|
int
|
Index of the channel to remove. |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If channel_index is not in visual.channels. |
add_canvas ¶
add_canvas(scene_id: UUID, render_modes: set[str] | None = None, initial_dim: str | None = None, fov: float = 70.0, depth_range_3d: tuple[float, float] = (1.0, 8000.0), depth_range_2d: tuple[float, float] = (-500.0, 500.0), canvas_size: tuple[int, int] | None = None) -> QWidget
Create a canvas attached to a scene and return its embeddable widget.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of an existing scene. |
required |
render_modes
|
set[str] or None
|
Which camera modes to prepare on the canvas. Each entry must be
|
None
|
initial_dim
|
str or None
|
Which mode is active when the canvas first appears. Must be a
member of |
None
|
fov
|
float
|
Vertical field of view in degrees for the 3D perspective camera.
Ignored when |
70.0
|
depth_range_3d
|
tuple[float, float]
|
|
(1.0, 8000.0)
|
depth_range_2d
|
tuple[float, float]
|
|
(-500.0, 500.0)
|
canvas_size
|
tuple[int, int] or None
|
Initial CSS pixel size for the anywidget canvas. Ignored for the
Qt gui (which is sized by its parent layout). Defaults to
|
None
|
Returns:
| Type | Description |
|---|---|
QWidget
|
The render widget. Embed with |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
add_canvas_model ¶
add_canvas_model(scene_id: UUID, canvas_model: Canvas, initial_dim: str | None = None, canvas_size: tuple[int, int] | None = None) -> QWidget
Register a pre-built Canvas model with a scene.
Used by from_model to restore canvases from a serialized
ViewerModel, and called internally by add_canvas. Camera state
(position, rotation, fov, depth range) is read from the camera models
stored in canvas_model.cameras.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of an existing scene. |
required |
canvas_model
|
Canvas
|
Pre-built canvas model. Must have at least one entry in
|
required |
initial_dim
|
str or None
|
Which dim to activate first. When |
None
|
canvas_size
|
tuple[int, int] or None
|
Initial CSS pixel size for the anywidget canvas. Ignored for the
Qt gui. Defaults to |
None
|
Returns:
| Type | Description |
|---|---|
QWidget
|
The render widget. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
fit_camera ¶
Fit the camera to the current scene bounding box.
Safe to call immediately after add_image / add_image_multiscale
and transform assignment — the node matrix is set at construction time
so no chunk data needs to be loaded first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of the scene whose camera should be fitted. |
required |
canvas_id
|
UUID or None
|
If provided, fit only that canvas. When |
None
|
add_canvas_overlay_model ¶
add_canvas_overlay_model(canvas_id: UUID, overlay: CanvasOverlay) -> CanvasOverlay
Attach a screen-space overlay to a specific canvas.
The overlay is rendered as a post-pass on top of the main scene each
frame. It does not participate in reslicing, has no world-space
transform, and is not added to scene.visuals.
The overlay model is stored in the Canvas.overlays list of
canvas_id, making it part of the serializable model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
ID of the canvas that should display the overlay. Use
:meth: |
required |
overlay
|
CanvasOverlay
|
Model-layer overlay description. Typically a
:class: |
required |
Returns:
| Type | Description |
|---|---|
CanvasOverlay
|
The same overlay object passed in (for ID access or chaining). |
Raises:
| Type | Description |
|---|---|
KeyError
|
If canvas_id is not registered. |
set_overlay_visible ¶
Toggle the visibility of a canvas overlay.
Searches all canvases across all scenes for an overlay with
overlay_id. Updates both the model field and the render layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
overlay_id
|
UUID
|
ID of the :class: |
required |
visible
|
bool
|
|
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If no overlay with |
get_scene_by_name ¶
Return the live Scene model for the given name.
Raises KeyError if no scene with that name exists.
get_canvas_ids ¶
get_canvas_view ¶
get_canvas_view(canvas_id: UUID) -> CanvasView
Return the render-layer CanvasView for canvas_id.
Provides access to the rendering backend (camera, widget, overlays)
for a canvas registered via :meth:add_canvas or
:meth:add_canvas_model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
ID of a registered canvas. |
required |
Returns:
| Type | Description |
|---|---|
CanvasView
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If canvas_id is not registered. |
get_camera_state ¶
get_camera_state(canvas_id: UUID) -> CameraState
Return a snapshot of the current camera state for canvas_id.
Useful for seeding downstream widgets (e.g. orientation overlays)
with the post-fit camera state without constructing a synthetic
CameraChangedEvent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
ID of a registered canvas. |
required |
Returns:
| Type | Description |
|---|---|
CameraState
|
|
Raises:
| Type | Description |
|---|---|
KeyError
|
If canvas_id is not registered. |
screenshot ¶
Capture a screenshot of the canvas as an RGBA uint8 array.
Temporarily resizes the canvas to size (scaled by scale), renders
one frame, grabs the framebuffer, then restores the original size and
camera state. Follows the same pattern as napari's resize_canvas
context manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
ID of a registered canvas. |
required |
size
|
tuple[int, int] or None
|
Target |
None
|
scale
|
float
|
Multiplier applied to size (or the current size when size is
|
1.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
RGBA uint8 array of shape |
get_visual_model ¶
get_visual_model(visual_id: UUID) -> MultiscaleImageVisual
Return the live visual model for visual_id.
Searches all scenes. Raises KeyError if not found.
reslice_scene ¶
reslice_scene(scene_id: UUID, *, on_ready: Callable[[], None] | None = None, owner_id: UUID | None = None) -> None
Trigger a data load for all visuals in one scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of the scene to reslice. |
required |
on_ready
|
Callable[[], None] or None
|
If provided, a zero-argument callback fired exactly once after
all visuals loaded by this reslice have committed to the GPU
(across every canvas attached to the scene). Visuals with no data
in the current view (culled, empty, or hidden) do not delay it.
Works uniformly for in-memory, multiscale, multichannel, and
geometry visuals. See :meth: The callback tracks this reslice generation. If a superseding reslice (e.g. a camera-settle reload) cancels these in-flight reads before they commit, the cancelled visual never reports completion and the callback may not fire. Callers that need a guaranteed startup signal should suppress camera-driven reslicing during the load (the convenience launchers do this automatically). |
None
|
owner_id
|
UUID or None
|
Owner under which the temporary |
None
|
suppress_reslice ¶
suppress_reslice() -> Generator[None, None, None]
Context manager that blocks reslice_scene inside transform handlers.
Use this when updating a visual's transform without needing to reload its underlying data — for example, repositioning a static-geometry mesh by translation only.
.. warning::
_suppress_reslice is a flat boolean. Nested calls or concurrent
async tasks that mutate transforms inside overlapping
suppress_reslice blocks will interfere. Replace with a depth
counter if that becomes necessary.
set_visual_transform ¶
set_visual_transform(visual_id: UUID, transform: AffineTransform, *, reslice: bool = True) -> None
Update the data-to-world transform of a visual.
Assigns transform to the live visual model, which fires its psygnal field event and propagates the change to the render layer via the event bus.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
ID of the visual to update. |
required |
transform
|
AffineTransform
|
New data-to-world transform. |
required |
reslice
|
bool
|
If True (default), a full reslice is triggered after the transform is applied — required for image visuals where the transform changes which data falls in the current slab. Pass False for static-geometry visuals (mesh, points, lines) where the transform only repositions the node and the underlying data is unchanged. |
True
|
update_slice_indices ¶
update_slice_indices(scene_id: UUID, slice_indices: dict[int, int], *, source_id: UUID | None = None) -> None
Set slice_indices on a scene's dims.
Tags the emitted bus event with source_id.
GUI widgets should pass source_id=self._id so their own
DimsChangedEvent subscription can ignore the echo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
Target scene. |
required |
slice_indices
|
dict[int, int]
|
Mapping of axis index → slice position. |
required |
source_id
|
UUID | None
|
UUID to stamp on the emitted |
None
|
update_appearance_field ¶
update_appearance_field(visual_id: UUID, field: str, value: Any, *, source_id: UUID | None = None) -> None
Set one field on a visual's appearance model.
Tags the emitted bus event with source_id.
GUI widgets should pass source_id=self._id so their own
AppearanceChangedEvent subscription can ignore the echo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
Target visual. |
required |
field
|
str
|
Attribute name on the appearance model, e.g. |
required |
value
|
Any
|
New value for the field. |
required |
source_id
|
UUID | None
|
UUID to stamp on the emitted |
None
|
update_channel_appearance_field ¶
update_channel_appearance_field(visual_id: UUID, channel_index: int, field: str, value: Any, *, source_id: UUID | None = None) -> None
Set one field on one channel of a multichannel visual.
Tags the emitted bus event with source_id. GUI widgets should pass
source_id=self._id so their own ChannelAppearanceChangedEvent
subscription can ignore the echo.
This mutates a single visual only. When a channel is shared in
lock-step across several panels (e.g. an OrthoViewer), calling this
on one panel's visual leaves the sibling panels unequal until they are
written too; use update_channel_group_field to keep the group in
lock-step.
A pydantic.ValidationError from a malformed value is allowed to
propagate (matching update_appearance_field).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
Target visual. |
required |
channel_index
|
int
|
Index into |
required |
field
|
str
|
Attribute name on the channel appearance model, e.g. |
required |
value
|
Any
|
New value for the field. |
required |
source_id
|
UUID | None
|
UUID to stamp on the emitted |
None
|
update_channel_group_field ¶
update_channel_group_field(visual_ids: list[UUID], channel_index: int, field: str, value: Any, *, source_id: UUID | None = None) -> None
Set one channel field across a group of visuals in lock-step.
Fan-out over update_channel_appearance_field so every visual in the
group (e.g. the per-panel visuals of an OrthoViewer) receives the
same channel change. This is the programmatic write-side companion to
the widget subscribe-to-all read side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_ids
|
list[UUID]
|
Target visuals sharing the channel set. |
required |
channel_index
|
int
|
Index into each visual's |
required |
field
|
str
|
Attribute name on the channel appearance model. |
required |
value
|
Any
|
New value for the field. |
required |
source_id
|
UUID | None
|
UUID to stamp on each emitted |
None
|
update_aabb_field ¶
update_aabb_field(visual_id: UUID, field: str, value: Any, *, source_id: UUID | None = None) -> None
Set one field on a visual's AABB params model.
Tags the emitted bus event with source_id.
GUI widgets should pass source_id=self._id so their own
AABBChangedEvent subscription can ignore the echo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
Target visual. |
required |
field
|
str
|
Attribute name on the AABB model, e.g. |
required |
value
|
Any
|
New value for the field. |
required |
source_id
|
UUID | None
|
UUID to stamp on the emitted |
None
|
update_displayed_axes ¶
update_displayed_axes(scene_id: UUID, displayed_axes: tuple[int, ...], *, source_id: UUID | None = None) -> None
Set displayed_axes on a scene's dims.
Tags the emitted bus event with source_id.
GUI widgets should pass source_id=self._id so their own
DimsChangedEvent subscription can ignore the echo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
Target scene. |
required |
displayed_axes
|
tuple[int, ...]
|
Tuple of axis indices to display; length 2 for 2D, 3 for 3D. |
required |
source_id
|
UUID | None
|
UUID to stamp on the emitted |
None
|
update_stacked_axes ¶
update_stacked_axes(scene_id: UUID, stacked_axes: tuple[int, ...], *, source_id: UUID | None = None) -> None
Set stacked_axes on a scene's dims.
Tags the emitted bus event with source_id.
GUI widgets should pass source_id=self._id so their own
DimsChangedEvent subscription can ignore the echo.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
Target scene. |
required |
stacked_axes
|
tuple[int, ...]
|
Tuple of axis indices whose full extent is composited by the render
layer (e.g. channel axis). Pass |
required |
source_id
|
UUID | None
|
UUID to stamp on the emitted |
None
|
set_displayed_axes ¶
set_displayed_axes(scene_id: UUID, displayed_axes: tuple[int, ...], *, source_id: UUID | None = None) -> None
Set displayed axes on a scene's dims (preferred public API).
Equivalent to :meth:update_displayed_axes. The controller's
psygnal bridge fires _rebuild_visuals_geometry and
_switch_canvas_cameras automatically when the model field changes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
Target scene. |
required |
displayed_axes
|
tuple[int, ...]
|
Tuple of axis indices to display; length 2 for 2D, 3 for 3D. |
required |
source_id
|
UUID | None
|
UUID stamped on the emitted |
None
|
set_stacked_axes ¶
set_stacked_axes(scene_id: UUID, stacked_axes: tuple[int, ...], *, source_id: UUID | None = None) -> None
Set stacked axes on a scene's dims (preferred public API).
Equivalent to :meth:update_stacked_axes. After updating the model,
notifies each visual via on_stacked_axes_changed so they can
adjust internal state (e.g. LUT channel routing) without a node swap.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
Target scene. |
required |
stacked_axes
|
tuple[int, ...]
|
Tuple of axis indices whose full extent is composited by the
render layer (e.g. channel axis). Pass |
required |
source_id
|
UUID | None
|
UUID stamped on the emitted |
None
|
look_at_visual ¶
look_at_visual(visual_id: UUID, canvas_id: UUID, view_direction: tuple[float, float, float] = (-1, -1, -1), up: tuple[float, float, float] = (0, 0, 1)) -> None
Fit the camera to a visual's bounding box.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
ID of the target visual. |
required |
canvas_id
|
UUID
|
ID of the canvas whose camera should be fitted. |
required |
view_direction
|
tuple[float, float, float]
|
Camera look direction vector (need not be normalized). |
(-1, -1, -1)
|
up
|
tuple[float, float, float]
|
Camera up vector. |
(0, 0, 1)
|
set_camera_depth_range ¶
add_paint_controller ¶
add_paint_controller(visual_id: UUID, canvas_id: UUID, brush_value: int = 1, brush_radius_voxels: float = 2.0, history_depth: int = 100, autosave_interval_s: float | None = None)
Create and wire a paint controller for the visual's data store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
Visual to paint on. |
required |
canvas_id
|
UUID
|
Canvas to bind to. Its camera controller is disabled for
the session. Pass |
required |
brush_value
|
int
|
Integer label ID written to every painted voxel. |
1
|
brush_radius_voxels
|
float
|
Brush radius in level-0 voxel units. |
2.0
|
history_depth
|
int
|
Maximum undoable strokes. |
100
|
autosave_interval_s
|
float | None
|
Seconds between automatic flushes for |
None
|
Returns:
| Type | Description |
|---|---|
AbstractPaintController
|
Fully wired; caller owns the object. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the data store type has no registered paint controller. |
remove_scene ¶
remove_scene(scene_id: UUID) -> None
Remove a scene and all its visuals and canvases.
Teardown order mirrors remove_visual for each child visual, then
cleans up the scene-level maps and render layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of the scene to remove. |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
remove_canvas ¶
remove_canvas(canvas_id: UUID) -> None
Remove a canvas from its scene, disconnecting all wiring.
Teardown order mirrors remove_scene for the canvas-level steps:
1. Cancel any pending camera-settle task.
2. Remove bus subscriptions owned by this canvas.
3. Update controller lookup maps.
4. Remove from the model layer.
5. Render-layer teardown (drops widget and GPU references).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
ID of the canvas to remove. |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
remove_visual ¶
remove_visual(visual_id: UUID) -> None
Remove a visual from its scene, disconnecting all wiring.
Teardown order:
1. Psygnal bridge handlers disconnected first — prevents the
bridge closures from firing during any subsequent model access.
2. Bus subscriptions removed — prevents dangling GFX-layer handlers
from receiving events after the node is gone from the scene graph.
3. Render-layer removal — drops scene-graph node and GPU references.
4. VisualRemovedEvent emitted for external observers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
ID of the visual to remove. |
required |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
remove_data_store ¶
remove_data_store(data_store_id: UUID) -> None
Remove a data store from the model.
Raises ValueError if any live visual still references the store.
Call remove_visual for each referencing visual first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_store_id
|
UUID
|
ID of the data store to remove. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If one or more visuals still reference the store. The error message names each visual so the caller can identify them. |
KeyError
|
If |
on_dims_changed ¶
on_dims_changed(scene_id: UUID, callback: Callable[[DimsChangedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired whenever the dims for scene_id change.
The callback receives the full DimsChangedEvent, which includes
source_id for echo-filtering and dims_state for the new state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
The scene to watch. |
required |
callback
|
Callable[[DimsChangedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. Pass the
caller's own UUID so |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. Use for transient widgets that may be destroyed outside the controller's teardown path. Cannot be used with lambdas. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
Pass to |
on_camera_changed ¶
on_camera_changed(scene_id: UUID, callback: Callable[[CameraChangedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired whenever the camera for scene_id changes.
The callback receives a CameraChangedEvent carrying the latest
CameraState, including extent (width, height) for
OrthographicCamera scenes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
The scene to watch. |
required |
callback
|
Callable[[CameraChangedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. Pass the
caller's own UUID so |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
unsubscribe_mouse ¶
Remove a mouse subscription created by an on_mouse_* method.
Use this in place of EventBus.unsubscribe for handles returned by
the six on_mouse_* methods so the per-canvas picking-subscriber
count stays accurate; the last unsubscribe disables element-detail
extraction for that canvas.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handle
|
SubscriptionHandle
|
A handle returned by one of the |
required |
on_mouse_press_2d ¶
on_mouse_press_2d(canvas_id: UUID, callback: Callable[[CanvasMousePress2DEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired on every pointer-down event on a 2D canvas.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
The canvas to watch. |
required |
callback
|
Callable[[CanvasMousePress2DEvent], None]
|
Called with the CanvasMousePress2DEvent on each press. |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered for bulk removal via unsubscribe_all(owner_id). |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
on_mouse_move_2d ¶
on_mouse_move_2d(canvas_id: UUID, callback: Callable[[CanvasMouseMove2DEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired on every pointer-move event on a 2D canvas.
on_mouse_release_2d ¶
on_mouse_release_2d(canvas_id: UUID, callback: Callable[[CanvasMouseRelease2DEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired on every pointer-up event on a 2D canvas.
on_mouse_press_3d ¶
on_mouse_press_3d(canvas_id: UUID, callback: Callable[[CanvasMousePress3DEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired on every pointer-down event on a 3D canvas.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
The canvas to watch. |
required |
callback
|
Callable[[CanvasMousePress3DEvent], None]
|
Called with the CanvasMousePress3DEvent on each press. |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered for bulk removal via unsubscribe_all(owner_id). |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
on_mouse_move_3d ¶
on_mouse_move_3d(canvas_id: UUID, callback: Callable[[CanvasMouseMove3DEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired on every pointer-move event on a 3D canvas.
on_mouse_release_3d ¶
on_mouse_release_3d(canvas_id: UUID, callback: Callable[[CanvasMouseRelease3DEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired on every pointer-up event on a 3D canvas.
set_camera_controller_enabled ¶
Enable or disable the camera controller for one canvas.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
The canvas whose controller state should change. |
required |
enabled
|
bool
|
False disables the controller (paint session active). True restores normal camera interaction (session ended). |
required |
on_appearance_changed ¶
on_appearance_changed(visual_id: UUID, callback: Callable[[AppearanceChangedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired whenever the appearance of visual_id changes.
The callback receives the full AppearanceChangedEvent, which
includes source_id for echo-filtering, field_name, and
new_value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
The visual to watch. |
required |
callback
|
Callable[[AppearanceChangedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. Pass the
caller's own UUID so |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
on_visual_changed ¶
on_visual_changed(visual_id: UUID, callback: Callable[[AppearanceChangedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Deprecated. Use on_appearance_changed instead.
on_visibility_changed ¶
on_visibility_changed(visual_id: UUID, callback: Callable[[VisualVisibilityChangedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired whenever the visibility of visual_id changes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
The visual to watch. |
required |
callback
|
Callable[[VisualVisibilityChangedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
set_visual_visible ¶
on_scene_added ¶
on_scene_added(scene_id: UUID, callback: Callable[[SceneAddedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired when scene_id is added.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
The scene to watch. |
required |
callback
|
Callable[[SceneAddedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
on_scene_removed ¶
on_scene_removed(scene_id: UUID, callback: Callable[[SceneRemovedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired when scene_id is removed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
The scene to watch. |
required |
callback
|
Callable[[SceneRemovedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
on_visual_added ¶
on_visual_added(visual_id: UUID, callback: Callable[[VisualAddedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired when visual_id is added.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
The visual to watch. |
required |
callback
|
Callable[[VisualAddedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
on_visual_removed ¶
on_visual_removed(visual_id: UUID, callback: Callable[[VisualRemovedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired when visual_id is removed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
The visual to watch. |
required |
callback
|
Callable[[VisualRemovedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
cancel_pending_slices ¶
cancel_pending_slices(scene_id: UUID) -> None
Cancel all in-flight slice requests for scene_id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of the scene whose pending slices to cancel. |
required |
close ¶
Cancel in-flight slices and close every canvas this viewer owns.
Releases the render surfaces and GPU resources held by the controller.
Closing is explicit because the canvases are owned by the GUI backend,
not by Python refcounting, so dropping the controller alone leaks them
(see :meth:CanvasView.close).
Safe to call more than once; the controller must not be used afterwards.
on_aabb_changed ¶
on_aabb_changed(visual_id: UUID, callback: Callable[[AABBChangedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired whenever the AABB params of visual_id change.
The callback receives the full AABBChangedEvent, which includes
source_id for echo-filtering, field_name, and new_value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
The visual to watch. |
required |
callback
|
Callable[[AABBChangedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. Pass the
caller's own UUID so |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
on_reslice_started ¶
on_reslice_started(scene_id: UUID, callback: Callable[[ResliceStartedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired when a reslice cycle begins for scene_id.
Useful for showing a loading indicator. Fired once per reslice submission, before any async data fetching starts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
The scene to watch. |
required |
callback
|
Callable[[ResliceStartedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. Pass the
caller's own UUID so |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
on_reslice_completed ¶
on_reslice_completed(visual_id: UUID, callback: Callable[[ResliceCompletedEvent], None], *, owner_id: UUID, weak: bool = False) -> SubscriptionHandle
Register a callback fired when a reslice cycle completes for visual_id.
Useful for hiding a loading indicator. Fired once per visual per reslice cycle, after all bricks/tiles in the batch are committed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visual_id
|
UUID
|
The visual to watch. |
required |
callback
|
Callable[[ResliceCompletedEvent], None]
|
Called with the |
required |
owner_id
|
UUID
|
UUID under which this subscription is registered. Pass the
caller's own UUID so |
required |
weak
|
bool
|
If True, hold only a weak reference to callback. |
False
|
Returns:
| Type | Description |
|---|---|
SubscriptionHandle
|
|
on_scene_ready ¶
on_scene_ready(scene_id: UUID, callback: Callable[[], None], *, owner_id: UUID | None = None) -> None
Reslice scene_id and fire callback once all its data is on the GPU.
This triggers a reslice of every visual in the scene and invokes callback exactly once, after all visuals loaded by that reslice have committed to the GPU across every attached canvas. Visuals with no data in the current view (frustum-culled, empty slab, or hidden) do not delay the callback.
Unlike :meth:on_reslice_completed (which fires per-visual on every
cycle), this is a scene-level, one-shot readiness signal — the right
hook for fitting the camera or hiding a startup spinner once a mixed
scene of multiscale images, in-memory images, and geometry has fully
loaded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scene_id
|
UUID
|
ID of the scene to reslice and watch. |
required |
callback
|
Callable[[], None]
|
Zero-argument callback fired once the scene's data is resident. |
required |
owner_id
|
UUID or None
|
Owner under which the temporary subscriptions are registered. Defaults to the controller's own id. |
None
|
on_canvas_first_frame ¶
on_canvas_first_frame(canvas_id: UUID, callback: Callable[[], None], *, owner_id: UUID | None = None) -> None
Fire callback once canvas_id has rendered its first frame.
The first rendered frame guarantees the canvas has reached its final
logical size and its camera matrix has been applied — the precondition
for fitting the camera and computing view-dependent (multiscale) slice
requests at the correct level of detail. This is a timer-free
replacement for deferring startup work with QTimer.singleShot(0).
A draw is requested immediately so the frame is guaranteed to arrive whether or not the event loop is already running.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
canvas_id
|
UUID
|
ID of the canvas to watch. |
required |
callback
|
Callable[[], None]
|
Zero-argument callback fired once, on the first frame. |
required |
owner_id
|
UUID or None
|
Owner under which the temporary subscription is registered. Defaults to the controller's own id. |
None
|
unsubscribe_owner ¶
unsubscribe_owner(owner_id: UUID) -> None
Remove all event subscriptions registered under owner_id.
GUI widgets should call this from their Qt closeEvent or
destroyed signal handler to deterministically clean up their
bus subscriptions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
owner_id
|
UUID
|
The UUID used as |
required |
connect_widget ¶
connect_widget(widget: WidgetView, *, subscription_specs: list[SubscriptionSpec] | None = None) -> None
Wire a widget's psygnal signals to the bus and register subscriptions.
Widgets declare their intent through two psygnal signals and an optional
list of SubscriptionSpec objects, so they never import or hold a
reference to CellierController.
The caller is responsible for constructing the widget and passing the
specs — typically obtained from widget.subscription_specs().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
widget
|
WidgetView
|
Any object exposing:
|
required |
subscription_specs
|
list[SubscriptionSpec] | None
|
Optional list of |
None
|