Data¶
Data stores hold the arrays backing each visual, along with the request and slice-result types used to fetch data for the current view.
Common¶
cellier.data.DataStoreType
module-attribute
¶
DataStoreType = Annotated[Union[MultiscaleZarrDataStore, ImageMemoryStore, OMEZarrImageDataStore, LabelMemoryStore, OMEZarrLabelDataStore, PointsMemoryStore, LinesMemoryStore, MeshMemoryStore, MultiscaleMeshStore, GraphMemoryStore], Field(discriminator='store_type')]
Images¶
cellier.data.image.ImageMemoryStore ¶
Bases: BaseDataStore
In-memory image data store backed by a numpy array.
Serves axis-aligned slices or full sub-volumes to the AsyncSlicer.
All reads are synchronous (the array is in CPU RAM); the method is
still declared async to satisfy the AsyncSlicer contract.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ndarray
|
The image data. Any dtype; coerced to float32 on construction. Shape convention follows numpy axis order — e.g. (D, H, W) for 3-D, (H, W) for 2-D, (T, C, D, H, W) for 5-D. |
required |
name
|
str
|
Human-readable label. Default |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
The store's coordinate system, as a one-entry list built by the
caller, with one axis per array dimension. A voxel grid is
sample-indexed, so build its axes with |
required |
level_scales
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_translations
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_transforms
|
list[AffineTransform]
|
The level-0 identity, installed from |
required |
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
level_shapes
property
¶
List with one entry (level 0 = the full array).
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The edge convention: an axis of size voxels spans
[-0.5, size - 0.5]. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
__setattr__ ¶
Assign a field, announcing the change when it is a data field.
A class-level hook rather than a connection to self.events made
in model_post_init: model_copy(deep=True) -- which
to_model and from_model use -- runs no model_post_init, so
a connection would silently go missing on every copy. Construction
assigns through __dict__ and announces nothing.
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
model_post_init ¶
model_post_init(__context: Any) -> None
Check the systems passed at construction and install their transforms.
Stores that open array handles in their own model_post_init call
this after opening them: the level count and rank it checks against
are read off the handles.
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
dataset_info ¶
Describe the array: shape, dtype, value range and footprint.
The value range is a full pass over the array, affordable only
because the data is already resident in RAM. The zarr-backed stores
deliberately omit it (see their dataset_info).
get_data
async
¶
get_data(request: ChunkRequest) -> ndarray
Return the requested sub-region as a float32 array.
Interprets request.axis_selections generically:
intentry → sliced axis; the integer index is applied and the axis is dropped from the output.(start, stop)tuple → displayed axis; a slice is applied and the axis is kept in the output.
Out-of-bounds coordinates are clamped to array extents and zero-padded on the output side so the returned shape always matches what the caller requested.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ChunkRequest
|
Built by |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
float32 array with one dimension per displayed (tuple) axis. |
cellier.data.image.MultiscaleZarrDataStore
pydantic-model
¶
Bases: TensorStoreCacheMixin, BaseDataStore
Data store for a multiscale zarr volume read via tensorstore.
Public fields are validated and serialisable (pydantic).
Tensorstore handles are opened synchronously in model_post_init
and stored as private attributes so they are not serialised.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store_type
|
Literal['multiscale_zarr']
|
Discriminator field. Always |
required |
zarr_path
|
Path to the root directory of the multiscale zarr store.
Pass as a string; |
required | |
scale_names
|
Ordered list of subdirectory names, finest → coarsest,
e.g. |
required | |
level_scales
|
Per-level, per-axis scale of level-k voxels in level-0 voxels.
|
required | |
level_translations
|
The offset half of the same, in level-0 voxels. |
required | |
id
|
Unique identifier. Taken from the |
required | |
data_coordinate_systems
|
One system per resolution level, finest first. The store reads no
axis metadata, so these come from the caller --
:meth: |
required | |
level_transforms
|
Level |
required | |
name
|
Human-readable name for the store (inherited from
|
required |
Attributes (read-only properties)
n_levels :
Number of scale levels (length of scale_names).
level_shapes :
List of shape tuples, one per level.
Config:
arbitrary_types_allowed:True
Fields:
-
id(UUID4 | Annotated[str, AfterValidator(lambda x: UUID(x, version=4))]) -
data_coordinate_systems(list[DataCoordinateSystem]) -
level_scales(list[tuple[float, ...]]) -
level_translations(list[tuple[float, ...]]) -
level_transforms(list[AffineTransform]) -
cache_pool_bytes(int) -
request_concurrency(int) -
file_io_concurrency(int | None) -
recheck_cached_data(bool) -
store_type(Literal['multiscale_zarr']) -
zarr_path(str) -
scale_names(list[str]) -
name(str)
Validators:
-
_check_cache_pool_bytes→cache_pool_bytes -
_check_request_concurrency→request_concurrency -
_check_file_io_concurrency→file_io_concurrency -
_validate_level_geometry
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
ndim
property
¶
ndim: int
Number of data dimensions, read off the level-0 handle.
This store reads no axis metadata -- unlike the OME-Zarr readers it
is constructed from bare scale and translation vectors. Its axes
come from a caller's data_coordinate_system or from the scene it
is added to, and this rank is what either must match.
level_shapes
property
¶
Shape for each scale level, finest first.
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The edge convention: an axis of size voxels spans
[-0.5, size - 0.5]. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
dtype
property
¶
Data type of the underlying arrays.
Read off the level-0 tensorstore handle, which is already open, so
this costs nothing. get_data converts to float32 on the way
out; this reports what is actually on disk.
__setattr__ ¶
Set a field, reopening the handles when the cache settings change.
cache_pool_bytes, request_concurrency and
file_io_concurrency rebuild the pool on a new context.
recheck_cached_data reopens on the same context. Every other
field is set as usual. Assigning the value a field already has is
a no-op, so a redundant write does not throw away a warm cache.
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is out of range for the field. |
RuntimeError
|
If a paint transaction is open on this store. Reopening would leave the paint write buffer holding a handle bound to the discarded pool, so the change is refused until the stroke is committed or aborted. |
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
register_paint_writer ¶
register_paint_writer(writer: Any) -> None
Record the paint write buffer currently open on this store.
Held weakly: a controller that is dropped without tearing down does not leave the store permanently locked.
The first registration reopens the handles with rechecks on, on the same context, so a write from outside this store is not masked by the cache while painting. Registering again while registered (a fresh buffer after an autosave) only swaps the reference. A transaction already open on the old handle is unaffected: it shares the context, so its staged and committed writes are visible through the new handles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
writer
|
Any
|
An object with a |
required |
unregister_paint_writer ¶
Forget the paint write buffer, undoing :meth:register_paint_writer.
Reopens the handles with rechecks off again, unless
recheck_cached_data keeps them on.
revalidate_cache ¶
Revalidate every cached chunk once, on its next read.
Reopens the handles on the same context with
recheck_cached_data="open": chunks cached before now are checked
against the kvstore when next read (unchanged ones cost a 304,
changed ones are refetched), then trusted again. Called for every
announced change (:meth:_invalidate_caches), so a store another
process writes to shows the new data after notify_changed.
A no-op while rechecks are on, since every read revalidates then, and before the handles are opened.
model_post_init ¶
model_post_init(__context: Any) -> None
Open all tensorstore handles.
Called automatically by pydantic after __init__.
Must run before QtAsyncio.run() starts the event loop.
from_scale_and_translation
classmethod
¶
from_scale_and_translation(*, zarr_path: str, scale_names: list[str], level_scales: list[tuple[float, ...]], level_translations: list[tuple[float, ...]], data_coordinate_system: DataCoordinateSystem | None = None, name: str = 'multiscale zarr data store') -> MultiscaleZarrDataStore
Construct from per-level scale and translation vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
zarr_path
|
str
|
Path to the root directory of the multiscale zarr store. |
required |
scale_names
|
list[str]
|
Ordered list of subdirectory names, finest → coarsest. |
required |
level_scales
|
list[tuple[float, ...]]
|
Per-level scale vectors. |
required |
level_translations
|
list[tuple[float, ...]]
|
Per-level translation vectors. |
required |
data_coordinate_system
|
DataCoordinateSystem | None
|
The level-0 coordinate system, one axis per data dimension. The
coarser levels copy its axes (names, types, units and sampling)
with fresh ids, and the store adopts its |
None
|
name
|
str
|
Human-readable name for the store. |
'multiscale zarr data store'
|
dataset_info ¶
Describe the pyramid: path, dtype, and the per-level geometry.
No value range: unlike the in-memory stores, computing one here would mean reading every level-0 chunk off disk or over the network.
The per-level scale rows are derived from level_scales
rather than asserted -- the examples used to hardcode strings like
"2x isotropic" that no longer matched an anisotropic pyramid.
get_data
async
¶
get_data(request: ChunkRequest) -> ndarray
Read a single padded brick, returning a zero-padded float32 array.
Interprets request.axis_selections generically: displayed axes
(tuple ranges) become slice dimensions in the output; sliced axes
(int values) become point selections.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ChunkRequest
|
Padded brick specification. Coordinates may be negative or exceed store bounds; clamping is handled internally. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
out |
ndarray
|
|
cellier.data.image.OMEZarrImageDataStore
pydantic-model
¶
Bases: TensorStoreCacheMixin, BaseDataStore
Data store for an OME-Zarr v0.5 image read via tensorstore.
Use the :meth:from_path class method to construct from an OME-Zarr URI.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store_type
|
Literal['ome_zarr_image']
|
Discriminator field. Always |
required |
zarr_path
|
str
|
URI to the root OME-Zarr group. Must start with |
required |
multiscale_index
|
int
|
Index into |
required |
scale_names
|
list[str]
|
Per-level relative array paths, finest to coarsest. |
required |
level_scales
|
list[tuple[float, ...]]
|
Full-rank (all axes) per-level scale: level-k voxels in level-0 voxels. Level 0 is all ones by construction. |
required |
level_translations
|
list[tuple[float, ...]]
|
The offset half of the same, in level-0 voxels. |
required |
physical_scale
|
list[float]
|
Level-0 data-to-world scale per axis, i.e. the OME global scale
composed with the level-0 dataset scale. |
required |
physical_translation
|
list[float]
|
Level-0 data-to-world translation per axis, the companion to
|
required |
channel_labels
|
list[str] or None
|
One name per channel, in channel-index order, from the image's
|
required |
name
|
str
|
Human-readable name for the store. |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
One system per resolution level, finest first, and the store's only
record of its axis names, types and units. :meth: |
required |
level_transforms
|
list[AffineTransform]
|
Level |
required |
Config:
arbitrary_types_allowed:True
Fields:
-
id(UUID4 | Annotated[str, AfterValidator(lambda x: UUID(x, version=4))]) -
data_coordinate_systems(list[DataCoordinateSystem]) -
level_scales(list[tuple[float, ...]]) -
level_translations(list[tuple[float, ...]]) -
level_transforms(list[AffineTransform]) -
cache_pool_bytes(int) -
request_concurrency(int) -
file_io_concurrency(int | None) -
recheck_cached_data(bool) -
store_type(Literal['ome_zarr_image']) -
zarr_path(str) -
multiscale_index(int) -
scale_names(list[str]) -
physical_scale(list[float]) -
physical_translation(list[float]) -
channel_labels(list[str] | None) -
anonymous(bool) -
name(str)
Validators:
-
_check_cache_pool_bytes→cache_pool_bytes -
_check_request_concurrency→request_concurrency -
_check_file_io_concurrency→file_io_concurrency
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
level_shapes
property
¶
Full-rank shape per level (all axes), finest first.
Returns shapes over all axes, including non-spatial ones.
The controller projects to the displayed subshape using
dims.displayed_axes before constructing the render visual.
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The edge convention: an axis of size voxels spans
[-0.5, size - 0.5]. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
__setattr__ ¶
Set a field, reopening the handles when the cache settings change.
cache_pool_bytes, request_concurrency and
file_io_concurrency rebuild the pool on a new context.
recheck_cached_data reopens on the same context. Every other
field is set as usual. Assigning the value a field already has is
a no-op, so a redundant write does not throw away a warm cache.
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is out of range for the field. |
RuntimeError
|
If a paint transaction is open on this store. Reopening would leave the paint write buffer holding a handle bound to the discarded pool, so the change is refused until the stroke is committed or aborted. |
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
register_paint_writer ¶
register_paint_writer(writer: Any) -> None
Record the paint write buffer currently open on this store.
Held weakly: a controller that is dropped without tearing down does not leave the store permanently locked.
The first registration reopens the handles with rechecks on, on the same context, so a write from outside this store is not masked by the cache while painting. Registering again while registered (a fresh buffer after an autosave) only swaps the reference. A transaction already open on the old handle is unaffected: it shares the context, so its staged and committed writes are visible through the new handles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
writer
|
Any
|
An object with a |
required |
unregister_paint_writer ¶
Forget the paint write buffer, undoing :meth:register_paint_writer.
Reopens the handles with rechecks off again, unless
recheck_cached_data keeps them on.
revalidate_cache ¶
Revalidate every cached chunk once, on its next read.
Reopens the handles on the same context with
recheck_cached_data="open": chunks cached before now are checked
against the kvstore when next read (unchanged ones cost a 304,
changed ones are refetched), then trusted again. Called for every
announced change (:meth:_invalidate_caches), so a store another
process writes to shows the new data after notify_changed.
A no-op while rechecks are on, since every read revalidates then, and before the handles are opened.
model_post_init ¶
model_post_init(__context: Any) -> None
Open all TensorStore handles (synchronous, before QtAsyncio).
from_path
classmethod
¶
from_path(zarr_path: str, *, multiscale_index: int = 0, series_index: int = 0, anonymous: bool = False, cache_pool_bytes: int = DEFAULT_CACHE_POOL_BYTES, request_concurrency: int = DEFAULT_REQUEST_CONCURRENCY, file_io_concurrency: int | None = None, recheck_cached_data: bool = False, data_coordinate_system: DataCoordinateSystem | None = None, name: str = 'ome zarr image data store') -> OMEZarrImageDataStore
Construct from an OME-Zarr v0.5 URI.
Supports both standard Image stores and Bf2Raw (bioformats2raw) multi-series containers. For Bf2Raw stores the series_index selects which child image to open.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
zarr_path
|
str
|
URI with a scheme prefix: |
required |
multiscale_index
|
int
|
Which |
0
|
series_index
|
int
|
For Bf2Raw containers, which image series to open. Ignored for standard Image stores. Defaults to 0. |
0
|
anonymous
|
bool
|
When True, read an |
False
|
cache_pool_bytes
|
int
|
Chunk cache cap for this store, in bytes, shared by all of its
resolution levels. |
DEFAULT_CACHE_POOL_BYTES
|
request_concurrency
|
int
|
Requests outstanding at once against a remote kvstore. Raise it
together with |
DEFAULT_REQUEST_CONCURRENCY
|
file_io_concurrency
|
int or None
|
Reads outstanding at once against the local filesystem. |
None
|
recheck_cached_data
|
bool
|
Revalidate cached chunks on every read. Set it when another process writes this data while it is open. Default False. |
False
|
data_coordinate_system
|
DataCoordinateSystem or None
|
The level-0 coordinate system, one axis per array dimension.
|
None
|
name
|
str
|
Human-readable name for the store. |
'ome zarr image data store'
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the URI scheme is not supported, the series index is out of range, an NGFF axis has an empty type and no data_coordinate_system is passed, or the passed system does not have one axis per array dimension. |
TypeError
|
If the OME metadata is neither Image nor Bf2Raw (e.g. a Plate). |
dataset_info ¶
Describe the store from metadata it already holds.
Reads only fields parsed at construction plus the open tensorstore
handles' shapes and dtype -- it never re-opens the group, which for
an s3:// store would mean a network round trip every time an
appearance panel is built.
No value range, for the same reason: it would be a full read of level 0.
get_data
async
¶
get_data(request: ChunkRequest) -> ndarray
Read a single padded brick, returning a zero-padded float32 array.
Interprets request.axis_selections generically: displayed axes
(tuple ranges) become slice dimensions in the output; sliced axes
(int values) become point selections.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ChunkRequest
|
Padded brick specification. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
|
cellier.data.image.ChunkRequest ¶
Bases: NamedTuple
A request for one padded brick / chunk of data.
All coordinates encode the padded region including overlap. They
may be negative or exceed the store bounds; get_data() on the
MultiscaleZarrDataStore is responsible for clamping and
zero-padding so the returned array always has the full requested
shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_request_id
|
Unique ID for this individual chunk. |
required | |
slice_request_id
|
Shared ID for all chunks that belong to the same planning event. |
required | |
scale_index
|
0-based index into |
required | |
axis_selections
|
Per-axis selection in data axis order. Each element is either:
- |
required |
Labels¶
cellier.data.label.LabelMemoryStore ¶
Bases: BaseDataStore
In-memory label data store backed by a numpy integer array.
Serves axis-aligned slices or full sub-volumes as int32 arrays. Source dtype may be int8, int16, or int32; int64/uint* are rejected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ndarray
|
Integer label array (int8, int16, or int32). Shape follows numpy axis order — e.g. (D, H, W) for 3-D, (H, W) for 2-D. Deserialisation also accepts the |
required |
name
|
str
|
Human-readable label. Default |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
The store's coordinate system, as a one-entry list built by the
caller, with one axis per array dimension. A voxel grid is
sample-indexed, so build its axes with |
required |
level_scales
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_translations
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_transforms
|
list[AffineTransform]
|
The level-0 identity, installed from |
required |
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The edge convention: an axis of size voxels spans
[-0.5, size - 0.5]. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
__setattr__ ¶
Assign a field, announcing the change when it is a data field.
A class-level hook rather than a connection to self.events made
in model_post_init: model_copy(deep=True) -- which
to_model and from_model use -- runs no model_post_init, so
a connection would silently go missing on every copy. Construction
assigns through __dict__ and announces nothing.
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
model_post_init ¶
model_post_init(__context: Any) -> None
Check the systems passed at construction and install their transforms.
Stores that open array handles in their own model_post_init call
this after opening them: the level count and rank it checks against
are read off the handles.
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
dataset_info ¶
Describe the array, including how many distinct labels it holds.
The label count is a full pass over the array (np.unique), which
is affordable only because the data is already resident in RAM.
OMEZarrLabelDataStore deliberately omits it: there the same row
would mean reading every chunk off disk.
get_data
async
¶
get_data(request: ChunkRequest) -> ndarray
Return the requested sub-region as an int32 array.
Interprets request.axis_selections generically:
- int entry → sliced axis (dropped from output)
- (start, stop) tuple → displayed axis (kept in output)
Out-of-bounds coordinates are clamped and zero-padded. Always returns int32 regardless of source dtype.
cellier.data.label.OMEZarrLabelDataStore
pydantic-model
¶
Bases: TensorStoreCacheMixin, BaseDataStore
Multiscale OME-Zarr label store returning int32 bricks.
Use the :meth:from_path class method to construct from a URI that
points to an OME-NGFF label group (containing ome → multiscales
metadata).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
store_type
|
Literal['ome_zarr_label']
|
Discriminator field. Always |
required |
zarr_path
|
str
|
URI to the label group. Must point to the label sub-group
(e.g. |
required |
multiscale_index
|
int
|
Which multiscale entry to use (default 0). |
required |
scale_names
|
list[str]
|
Per-level relative array paths, finest to coarsest. |
required |
level_scales
|
list[tuple[float, ...]]
|
Full-rank per-level scale: level-k voxels in level-0 voxels. |
required |
level_translations
|
list[tuple[float, ...]]
|
The offset half of the same, in level-0 voxels. |
required |
physical_scale
|
list[float]
|
Level-0 data-to-world scale per axis, i.e. the OME global scale
composed with the level-0 dataset scale. |
required |
physical_translation
|
list[float]
|
Level-0 data-to-world translation per axis, the companion to
|
required |
name
|
str
|
Human-readable name for the store. |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
One system per resolution level, finest first, and the store's only
record of its axis names, types and units. :meth: |
required |
level_transforms
|
list[AffineTransform]
|
Level |
required |
Config:
arbitrary_types_allowed:True
Fields:
-
id(UUID4 | Annotated[str, AfterValidator(lambda x: UUID(x, version=4))]) -
data_coordinate_systems(list[DataCoordinateSystem]) -
level_scales(list[tuple[float, ...]]) -
level_translations(list[tuple[float, ...]]) -
level_transforms(list[AffineTransform]) -
cache_pool_bytes(int) -
request_concurrency(int) -
file_io_concurrency(int | None) -
recheck_cached_data(bool) -
store_type(Literal['ome_zarr_label']) -
zarr_path(str) -
multiscale_index(int) -
scale_names(list[str]) -
physical_scale(list[float]) -
physical_translation(list[float]) -
anonymous(bool) -
name(str)
Validators:
-
_check_cache_pool_bytes→cache_pool_bytes -
_check_request_concurrency→request_concurrency -
_check_file_io_concurrency→file_io_concurrency
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
level_shapes
property
¶
Full-rank shape per level (all axes), finest first.
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The edge convention: an axis of size voxels spans
[-0.5, size - 0.5]. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
__setattr__ ¶
Set a field, reopening the handles when the cache settings change.
cache_pool_bytes, request_concurrency and
file_io_concurrency rebuild the pool on a new context.
recheck_cached_data reopens on the same context. Every other
field is set as usual. Assigning the value a field already has is
a no-op, so a redundant write does not throw away a warm cache.
Raises:
| Type | Description |
|---|---|
ValueError
|
If value is out of range for the field. |
RuntimeError
|
If a paint transaction is open on this store. Reopening would leave the paint write buffer holding a handle bound to the discarded pool, so the change is refused until the stroke is committed or aborted. |
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
register_paint_writer ¶
register_paint_writer(writer: Any) -> None
Record the paint write buffer currently open on this store.
Held weakly: a controller that is dropped without tearing down does not leave the store permanently locked.
The first registration reopens the handles with rechecks on, on the same context, so a write from outside this store is not masked by the cache while painting. Registering again while registered (a fresh buffer after an autosave) only swaps the reference. A transaction already open on the old handle is unaffected: it shares the context, so its staged and committed writes are visible through the new handles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
writer
|
Any
|
An object with a |
required |
unregister_paint_writer ¶
Forget the paint write buffer, undoing :meth:register_paint_writer.
Reopens the handles with rechecks off again, unless
recheck_cached_data keeps them on.
revalidate_cache ¶
Revalidate every cached chunk once, on its next read.
Reopens the handles on the same context with
recheck_cached_data="open": chunks cached before now are checked
against the kvstore when next read (unchanged ones cost a 304,
changed ones are refetched), then trusted again. Called for every
announced change (:meth:_invalidate_caches), so a store another
process writes to shows the new data after notify_changed.
A no-op while rechecks are on, since every read revalidates then, and before the handles are opened.
model_post_init ¶
model_post_init(__context: Any) -> None
Open all TensorStore handles (synchronous, before QtAsyncio).
from_path
classmethod
¶
from_path(zarr_path: str, *, multiscale_index: int = 0, anonymous: bool = False, cache_pool_bytes: int = DEFAULT_CACHE_POOL_BYTES, request_concurrency: int = DEFAULT_REQUEST_CONCURRENCY, file_io_concurrency: int | None = None, recheck_cached_data: bool = False, data_coordinate_system: DataCoordinateSystem | None = None, name: str = 'ome zarr label data store') -> OMEZarrLabelDataStore
Construct from a URI pointing directly at an OME-NGFF label group.
The URI must point at a zarr group that carries ome.multiscales
metadata (i.e. the label sub-group itself, not the root OME-Zarr).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
zarr_path
|
str
|
URI with a scheme prefix: |
required |
multiscale_index
|
int
|
Which |
0
|
anonymous
|
bool
|
When True, read an |
False
|
cache_pool_bytes
|
int
|
Chunk cache cap for this store, in bytes, shared by all of its
resolution levels. |
DEFAULT_CACHE_POOL_BYTES
|
request_concurrency
|
int
|
Requests outstanding at once against a remote kvstore. Raise it
together with |
DEFAULT_REQUEST_CONCURRENCY
|
file_io_concurrency
|
int or None
|
Reads outstanding at once against the local filesystem. |
None
|
recheck_cached_data
|
bool
|
Revalidate cached chunks on every read. Set it when another process writes this data while it is open. Default False. |
False
|
data_coordinate_system
|
DataCoordinateSystem or None
|
The level-0 coordinate system, one axis per array dimension.
|
None
|
name
|
str
|
Human-readable name for the store. |
'ome zarr label data store'
|
dataset_info ¶
Describe the store from metadata it already holds.
Like the image store, this never re-opens the group and never reads
array data -- so no label count, which would require a full pass
over level 0. LabelMemoryStore reports one because its data is
already in RAM.
The Data type row names the on-disk dtype and the int32 the
store hands out, which differ whenever the source is int8 or int16.
get_data
async
¶
Read a padded brick, returning int32 (zero-padded for out-of-bounds).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ChunkRequest
|
Padded brick specification with |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
int32 array. |
Points¶
cellier.data.points.PointsMemoryStore ¶
Bases: BaseDataStore
In-memory point-cloud data store backed by numpy arrays.
All reads are synchronous (data is in CPU RAM); get_data is
declared async to satisfy the AsyncSlicer contract and to
provide a single cancellation checkpoint.
Positions are stored in data-axis order: column 0 is axis 0 (z),
column 1 is axis 1 (y), column 2 is axis 2 (x). The render layer
applies the [:, [2, 1, 0]] reversal before uploading to pygfx.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
positions
|
ndarray
|
(n_points, ndim) float32 array. |
required |
colors
|
ndarray | None
|
(n_points, 4) float32 RGBA, index-matched to positions. Pass None for uniform-color rendering. |
required |
sizes
|
ndarray | None
|
(n_points,) float32 per-point sizes. Pass None for uniform-size rendering. |
required |
name
|
str
|
Human-readable label. |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
The store's coordinate system, as a one-entry list built by the
caller, with one axis per |
required |
level_scales
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_translations
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_transforms
|
list[AffineTransform]
|
The level-0 identity, installed from |
required |
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The bounding box of the points, with no padding -- a vertex is a point,
not a cell, so there is no half-voxel to add. None when the
store is empty. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
color_mode
property
¶
color_mode: str
"vertex" when per-point colors are present, else "uniform".
Descriptive only. It reports what this store carries; it does not decide what the material does. Where RGB comes from is declared on the appearance and honoured verbatim (D20) -- the render layer never infers it from the data and never writes it back at commit time.
__setattr__ ¶
Assign a field, announcing the change when it is a data field.
A class-level hook rather than a connection to self.events made
in model_post_init: model_copy(deep=True) -- which
to_model and from_model use -- runs no model_post_init, so
a connection would silently go missing on every copy. Construction
assigns through __dict__ and announces nothing.
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
model_post_init ¶
model_post_init(__context: Any) -> None
Check the systems passed at construction and install their transforms.
Stores that open array handles in their own model_post_init call
this after opening them: the level count and rank it checks against
are read off the handles.
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
dataset_info ¶
Describe the point cloud: count, dimensionality, extent, footprint.
color_mode and size_mode are deliberately absent: they
describe how the points are drawn, not what the store holds, and
the appearance model is where a reader should look for that.
get_data
async
¶
get_data(request: PointsSliceRequest) -> PointsData
Return proximity-filtered point data for request.
Checkpoint
A After the proximity mask is built but before gathering surviving points. Fires if the slider is moved quickly enough to cancel the task before the gather.
If CancelledError fires at the checkpoint, the callback is never called, preventing stale geometry from reaching the GPU.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
PointsSliceRequest
|
Built by GFXPointsMemoryVisual.build_slice_request[_2d]. |
required |
Returns:
| Type | Description |
|---|---|
PointsData
|
Proximity-filtered, projected points ready for GPU upload.
|
cellier.data.points.PointsSliceRequest ¶
Bases: NamedTuple
Request for one proximity-filtered slice of points data.
The first three fields satisfy the AsyncSlicer logging contract:
slice_request_id is the task key; chunk_request_id and
scale_index appear in INFO/DEBUG log lines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slice_request_id
|
UUID
|
Shared ID for all requests in one planning event. Used by AsyncSlicer as the dict key for the running task — REQUIRED. |
required |
chunk_request_id
|
UUID
|
Per-request ID. For points (never tiled) this equals
|
required |
scale_index
|
int
|
Always 0 — no LOD levels. Present for slicer logging compat. |
required |
displayed_axes
|
tuple[int, ...]
|
Axis indices rendered in the canvas (2 for 2D, 3 for 3D). |
required |
retained_axes
|
tuple[int, ...]
|
The data axes this visual's geometry keeps, ascending. Not the same list as |
required |
region
|
ConvexRegion
|
The selected region, already pulled back into data coordinates
(design 3.12). It is the whole filter -- one Until v1 was retired this was optional, and a request without one
fell back to comparing a world position from |
required |
cellier.data.points.PointsData
dataclass
¶
Proximity-filtered points data returned by PointsMemoryStore.get_data().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request_id
|
UUID
|
Echo of PointsSliceRequest.slice_request_id. |
required |
positions
|
ndarray
|
(n_points, n_displayed_dims) float32. Projected onto displayed axes; padded to 3D in the render layer. |
required |
colors
|
ndarray | None
|
(n_points, 4) float32 RGBA, index-matched to positions. None when the store carries no per-point colors. |
required |
sizes
|
ndarray | None
|
(n_points,) float32 per-point sizes. None when the store carries no per-point sizes. |
required |
color_mode
|
str
|
|
'uniform'
|
size_mode
|
str
|
|
'uniform'
|
is_empty
|
bool
|
True when the proximity filter produced zero surviving points and a placeholder geometry was returned. |
False
|
original_indices
|
ndarray | None
|
(n_points,) int array mapping each row of |
None
|
Lines¶
cellier.data.lines.LinesMemoryStore ¶
Bases: BaseDataStore
In-memory line-segment data store backed by numpy arrays.
Stores a collection of line segments as vertex pairs. For segment n,
positions[n * 2] is the start point and positions[n * 2 + 1]
is the end point.
Positions are stored in data-axis order: column 0 is axis 0 (z),
column 1 is axis 1 (y), column 2 is axis 2 (x). The render layer
applies the [:, [2, 1, 0]] reversal before uploading to pygfx.
All reads are synchronous (data is in CPU RAM); get_data is
declared async to satisfy the AsyncSlicer contract and to
provide a single cancellation checkpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
positions
|
ndarray
|
(n_vertices, ndim) float32 array. Must have an even number of rows. |
required |
colors
|
ndarray | None
|
(n_vertices, 4) float32 RGBA, index-matched to positions. Pass None for uniform-color rendering. |
required |
name
|
str
|
Human-readable label. |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
The store's coordinate system, as a one-entry list built by the
caller, with one axis per |
required |
level_scales
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_translations
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_transforms
|
list[AffineTransform]
|
The level-0 identity, installed from |
required |
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The bounding box of the vertices, with no padding -- a vertex is a point,
not a cell, so there is no half-voxel to add. None when the
store is empty. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
color_mode
property
¶
color_mode: str
"vertex" when per-vertex colors are present, else "uniform".
Descriptive only. It reports what this store carries; it does not decide what the material does. Where RGB comes from is declared on the appearance and honoured verbatim (D20) -- the render layer never infers it from the data and never writes it back at commit time.
__setattr__ ¶
Assign a field, announcing the change when it is a data field.
A class-level hook rather than a connection to self.events made
in model_post_init: model_copy(deep=True) -- which
to_model and from_model use -- runs no model_post_init, so
a connection would silently go missing on every copy. Construction
assigns through __dict__ and announces nothing.
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
model_post_init ¶
model_post_init(__context: Any) -> None
Check the systems passed at construction and install their transforms.
Stores that open array handles in their own model_post_init call
this after opening them: the level count and rank it checks against
are read off the handles.
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
dataset_info ¶
Describe the segments: count, dimensionality, extent, footprint.
The vertex count is spelled out beside the segment count to make the
two-vertices-per-segment layout visible; a reader comparing this
block against the raw array would otherwise see twice what they
expect. color_mode is absent -- it is a display property.
get_data
async
¶
get_data(request: LinesSliceRequest) -> LinesData
Return slab-filtered segment data for request.
Checkpoint
A After the per-vertex slab mask is built but before gathering surviving vertices. Fires if the slider is moved quickly enough to cancel the task before the gather.
If CancelledError fires at the checkpoint the callback is never called, preventing stale geometry from reaching the GPU.
Inclusion rule
A segment survives when both of its endpoints pass the
proximity test on every non-displayed axis:
slice_index - thickness <= coord <= slice_index + thickness
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
LinesSliceRequest
|
Built by GFXLinesMemoryVisual.build_slice_request[_2d]. |
required |
Returns:
| Type | Description |
|---|---|
LinesData
|
Filtered, projected segment data ready for GPU upload.
|
cellier.data.lines.LinesSliceRequest ¶
Bases: NamedTuple
Request for one slab-filtered slice of line-segment data.
The first three fields satisfy the AsyncSlicer logging contract:
slice_request_id is the task key; chunk_request_id and
scale_index appear in INFO/DEBUG log lines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slice_request_id
|
UUID
|
Shared ID for all requests in one planning event. Used by AsyncSlicer as the dict key for the running task — REQUIRED. |
required |
chunk_request_id
|
UUID
|
Per-request ID. For lines (never tiled) this equals
|
required |
scale_index
|
int
|
Always 0 — no LOD levels. Present for slicer logging compat. |
required |
displayed_axes
|
tuple[int, ...]
|
Axis indices rendered in the canvas (2 for 2D, 3 for 3D). |
required |
retained_axes
|
tuple[int, ...]
|
The data axes this visual's geometry keeps, ascending. Not the same list as |
required |
region
|
ConvexRegion
|
The selected region, already pulled back into data coordinates
(design 3.12). It is the whole filter -- one Until v1 was retired this was optional, and a request without one
fell back to comparing a world position from |
required |
clip_planes
|
tuple[tuple[tuple[float, ...], float], ...]
|
Clipping planes the read applies on the CPU, as |
required |
cellier.data.lines.LinesData
dataclass
¶
Slab-filtered line-segment data returned by LinesMemoryStore.get_data().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request_id
|
UUID
|
Echo of LinesSliceRequest.slice_request_id. |
required |
positions
|
ndarray
|
(n_vertices, n_displayed_dims) float32. n_vertices is always even;
pair |
required |
colors
|
ndarray | None
|
(n_vertices, 4) float32 RGBA, index-matched to positions. None when the store carries no per-vertex colors. |
required |
color_mode
|
str
|
|
'uniform'
|
is_empty
|
bool
|
True when the slab filter produced zero surviving segments and a placeholder geometry was returned. |
False
|
original_edge_indices
|
ndarray | None
|
(n_segments,) int array mapping each rendered segment to its edge
index in the store's full segment array. This is the slab filter's
surviving-segment list; in a full 3-D view it is the identity
|
None
|
Meshes¶
cellier.data.mesh.MeshMemoryStore ¶
Bases: BaseDataStore
In-memory triangle mesh data store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
positions
|
ndarray
|
(n_vertices, N) float32 vertex positions for any world dimensionality N ≥ 2. For a 3-D scene use shape (n_vertices, 3); for a 5-D scene (t, z, y, x, c) use shape (n_vertices, 5). |
required |
indices
|
ndarray
|
(n_faces, 3) int32 triangle face indices. Must be int32 — pygfx rejects int64 at upload time. int64 input is coerced silently by the validator. |
required |
colors
|
ndarray | None
|
Per-vertex (n_vertices, 4) or per-face (n_faces, 4) float32 RGBA.
Which of the two is declared by |
required |
colors_layout
|
str | None
|
This used to be inferred by comparing |
required |
name
|
str
|
Human-readable label. |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
The store's coordinate system, as a one-entry list built by the
caller, with one axis per |
required |
level_scales
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_translations
|
list[tuple[float, ...]]
|
Unused by this single-resolution store; left empty. |
required |
level_transforms
|
list[AffineTransform]
|
The level-0 identity, installed from |
required |
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
ndim
property
¶
ndim: int
Number of spatial dimensions per vertex.
Present for parity with the points and lines stores, which the mesh
store previously lacked -- every caller had to reach into
positions.shape[1] itself.
axis_extents
property
¶
Per-axis (low, high) extents in level-0 data coordinates.
The bounding box of the vertices, with no padding -- a vertex is a point,
not a cell, so there is no half-voxel to add. None when the
store is empty. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
colors_mode
property
¶
colors_mode: str
'vertex', 'face', or 'none' -- the declared layout.
Reads colors_layout rather than comparing array lengths. The
old inference reported per-vertex colours as per-face on any mesh
with as many vertices as faces.
__setattr__ ¶
Assign a field, announcing the change when it is a data field.
A class-level hook rather than a connection to self.events made
in model_post_init: model_copy(deep=True) -- which
to_model and from_model use -- runs no model_post_init, so
a connection would silently go missing on every copy. Construction
assigns through __dict__ and announces nothing.
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
model_post_init ¶
model_post_init(__context: Any) -> None
Check the systems passed at construction and install their transforms.
Stores that open array handles in their own model_post_init call
this after opening them: the level count and rank it checks against
are read off the handles.
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
dataset_info ¶
Describe the mesh: vertex and face counts, extent, footprint.
colors_mode is deliberately absent: it describes how the mesh is
drawn, not what the store holds.
Closed says whether the surface is watertight, which decides
whether a 2D section of it can be filled: an open surface draws its
outline only. It is worked out by the first 2D section read, so it
reads "not computed" before one.
level_arrays ¶
level_arrays(level: int = 0) -> MeshLevelArrays
The arrays of level; this store has level 0 only.
level_cache ¶
level_cache(level: int = 0) -> LevelCache
What the reads of level share (normals, bounds indexes).
get_data
async
¶
get_data(request: MeshSliceRequest) -> MeshData
Return slab-filtered, reindexed, upload-ready mesh data.
The work runs in an executor thread
(:func:~cellier.data.mesh._mesh_slicing.slice_mesh), so the event
loop stays free. There are no cancellation checkpoints: the chunk
scheduler, which issues these reads, never cancels one.
Inclusion rule
A face survives only when all of its vertices are inside the request's region. This is the mesh analogue of the lines store's "both endpoints must pass" rule and avoids projecting off-slice vertices onto the slice plane with the wrong colors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
MeshSliceRequest
|
Built by |
required |
Returns:
| Type | Description |
|---|---|
MeshData
|
Filtered, reindexed, projected mesh ready for GPU upload.
|
cellier.data.mesh.MultiscaleMeshStore ¶
Bases: BaseDataStore
In-memory triangle mesh with levels of detail.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
levels
|
list[MeshLevel]
|
The mesh at each level, finest first, at least one. Every level
is the same surface in the same data coordinates: there is one data
coordinate system and no per-level transform. Every level has the
same number of position columns. Either every level has colours,
all with the same |
required |
name
|
str
|
Human-readable label. |
required |
id
|
UUID4
|
Unique identifier. Taken from the |
required |
data_coordinate_systems
|
list[DataCoordinateSystem]
|
The store's coordinate system, as a one-entry list, with one axis per position column. Empty by default, in which case the store takes the scene's world axes when it is added to a scene. |
required |
Notes
Level numbers here and on a request (scale_index) are 0-based, 0 the
finest. A visual's GeometryLodConfig.coarse_level is 1-based, like
the image settings.
The store's extent is level 0's. Build levels with quadric decimation rather than quadric clustering: a decimated level stays watertight, so its 2D section still closes and is filled.
Reassigning levels announces a change. A level is frozen; to change
one, assign a new list.
data_coordinate_system
property
¶
data_coordinate_system: DataCoordinateSystem
The level-0 (intrinsic) coordinate system.
Returns:
| Type | Description |
|---|---|
DataCoordinateSystem
|
The finest-resolution system. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the store has no coordinate systems. The message names the two ways to supply them, because this is the error a caller who built a bare in-memory store outside a viewer will hit. |
axis_extents
property
¶
Per-axis (low, high) of the finest level's vertices.
None when that level is empty. See
:attr:~cellier.data._base_data_store.BaseDataStore.axis_extents.
__setattr__ ¶
Assign a field, announcing the change when it is a data field.
A class-level hook rather than a connection to self.events made
in model_post_init: model_copy(deep=True) -- which
to_model and from_model use -- runs no model_post_init, so
a connection would silently go missing on every copy. Construction
assigns through __dict__ and announces nothing.
notify_changed ¶
notify_changed(kind: StoreChangeKind = 'contents', regions: Sequence[DataRegion] | None = None) -> None
Announce that the store's data changed.
Reassigning a data field announces itself; call this after an
in-place write, which nothing can see -- store.data[...] = v
or store.positions[:] = p.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
'extent' or 'contents'
|
|
'contents'
|
regions
|
Sequence[DataRegion] or None
|
Where the data changed, as per-axis |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If kind is not one of the two kinds. |
model_post_init ¶
model_post_init(__context: Any) -> None
Check the systems passed at construction and install their transforms.
Stores that open array handles in their own model_post_init call
this after opening them: the level count and rank it checks against
are read off the handles.
set_data_coordinate_systems ¶
set_data_coordinate_systems(systems: list[DataCoordinateSystem], level_transforms: list[AffineTransform] | None = None) -> None
Install the store's coordinate systems and level transforms.
Assignment rather than construction because the systems are sometimes derived from the scene the store is added to, which the store cannot see at construction time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
systems
|
list[DataCoordinateSystem]
|
One per resolution level, finest first. |
required |
level_transforms
|
list[AffineTransform] or None
|
Level |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If systems is empty, if level_transforms has a different length, or if a multi-level store is given no level transforms -- there is no downsampling factor to infer them from here. Also if the systems are not one per resolution level with one axis per data dimension. |
dataset_info ¶
Describe the mesh: its levels, extent and footprint.
Closed says, per level, whether the surface is watertight, which
decides whether a 2D section of that level can be filled. It is
worked out by the level's first 2D section read.
level_arrays ¶
level_arrays(level: int = 0) -> MeshLevelArrays
The arrays of level (0 is the finest).
level_cache ¶
level_cache(level: int = 0) -> LevelCache
What the reads of level share (normals, bounds indexes).
get_data
async
¶
get_data(request: MeshSliceRequest) -> MeshData | MeshSectionData
Return one level, sliced and upload-ready.
The same read as :meth:MeshMemoryStore.get_data, on the level the
request names (scale_index, 0 the finest). It runs in an
executor thread, with no cancellation checkpoints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
MeshSliceRequest
|
Built by |
required |
Returns:
| Type | Description |
|---|---|
MeshData or MeshSectionData
|
The level's faces inside the request's region, or its section.
|
cellier.data.mesh.MeshLevel
pydantic-model
¶
Bases: BaseModel
One level of detail of a mesh.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
positions
|
ndarray
|
|
required |
indices
|
ndarray
|
|
required |
colors
|
ndarray or None
|
Per-vertex |
required |
colors_layout
|
('vertex', 'face')
|
Required whenever |
"vertex"
|
A
|
|
required | |
the
|
|
required |
Config:
arbitrary_types_allowed:Truefrozen:True
Fields:
-
positions(ndarray) -
indices(ndarray) -
colors(ndarray | None) -
colors_layout(Literal['vertex', 'face'] | None)
Validators:
-
_coerce_positions→positions -
_coerce_indices→indices -
_coerce_colors→colors -
_check_shapes
cellier.data.mesh.MeshSliceRequest ¶
Bases: NamedTuple
Request for one slab-filtered slice of one level of a mesh.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
slice_request_id
|
UUID
|
Shared ID for all requests in one planning event. |
required |
chunk_request_id
|
UUID
|
Per-request ID. For mesh (never tiled) this equals
|
required |
scale_index
|
int
|
The level to read, 0 the finest. A single-level store has level 0 only. |
required |
displayed_axes
|
tuple[int, ...]
|
Axis indices rendered in the canvas. |
required |
retained_axes
|
tuple[int, ...]
|
The data axes this visual's geometry keeps, ascending. Not the same list as |
required |
region
|
ConvexRegion
|
The selected region, already pulled back into data coordinates (design 3.12). It is the whole filter: a face survives when all three of its vertices are inside. |
required |
output_axes
|
tuple[int, ...]
|
The data axes to emit, in the column order of the result. The
render visual passes |
required |
section
|
MeshSectionRequest or None
|
|
required |
cellier.data.mesh.MeshData
dataclass
¶
One level of a mesh at one request, ready to upload.
Returned by a mesh store's get_data. Every array is contiguous and
in the dtype and column order the GPU takes, so the render visual builds
a gfx.Geometry from it without a copy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request_id
|
UUID
|
Echo of MeshSliceRequest.slice_request_id. |
required |
positions
|
ndarray
|
|
required |
indices
|
ndarray
|
(n_faces, 3) int32. Reindexed to reference only the vertices
in |
required |
normals
|
ndarray | None
|
|
required |
colors
|
ndarray | None
|
Per-vertex (n_vertices, 4) or per-face (n_faces, 4) float32 RGBA. None when the store carries no color data. |
required |
color_mode
|
str
|
|
'vertex'
|
is_empty
|
bool
|
True when the slab contained no surviving faces and a placeholder geometry was returned. |
False
|
original_face_indices
|
ndarray | None
|
(n_faces,) int array mapping each row of |
None
|
level
|
int
|
The level the data is of, 0 the finest. |
0
|
bounds
|
ndarray | None
|
|
None
|