Dim/metadata contract consolidation — change ledger#
Goal: one place (LazyArray) defines the dims/metadata/dimension_specs
contract so a new array class implements only _shape5d, __getitem__,
dtype, can_open, and populates self._metadata. Natural-rank classes
(BinArray 3D, MP4Array 3D, _ChannelView 4D) opt out by overriding
ndim/shape. Suite2p input reader (BinArray) stays 3D.
Removed#
Classes / files:
DimLabels(class) —arrays/features/_dim_labels.py(was event-driven, unsubscribed)DimLabelsMixin(class) + whole filearrays/features/_mixin.pyDimensionSpecMixin(class) —arrays/features/_dim_spec.py(folded intoLazyArray)
Per-class overrides deleted (now inherited from LazyArray):
TiffArray:
shape,ndim,dims,metadataget/setScanImageArray:
ndim,dimsZarrArray:
shape,ndim,dims,_read_ome_dims,_init_dim_labelscallsSuite2pArray:
shape,ndim, twodims,metadataget/set,DimLabelsbuildH5Array:
shape,ndimNumpyArray:
shape,ndimBinArray:
metadataget/setMP4Array:
metadataget/set_ChannelView:
dimsIsoviewArray:
ndim,dimstiff.py: 6x
self._dim_labels = None
Other:
DimensionSpec.to_ome_axisbody (delegates to_dim_tags.dim_to_ome_axis)get_dims_dim_labelsbranch (dead)exports of
DimLabels,DimLabelsMixin,DimensionSpecMixinfromfeatures/__init__
Added#
LazyArray (base) now provides the whole contract:
dimsget/set (declared-or-canonical-by-rank; setter invalidates specs)metadataget/set (dict-backed; setter routes a"dims"key)dimension_specs,invalidate_dimension_specsspatial_dims,iteratable_dims,batch_dims,slider_dimsdim_index,has_dimmodule const
_DEFAULT_DIMS_BY_NDIM
Tests: tests/test_lazyarray_contract.py (8 tests).
New-class contract: implement can_open, _shape5d, __getitem__, dtype,
set self._metadata. Natural-rank classes also override ndim/shape.
Behavior held#
BinArray stays 3D
(T,Y,X)(suite2p input contract).slider_dims ↔ shape/ndim lockstep across T/C/Z singleton cases.
shape ↔ getitem contract.
wrapper array/astype stay explicit (_ChannelView).
Regression found + fixed during pipeline verification#
The base metadata setter initially routed a "dims" key onto self.dims,
which raised when a single-channel write left a 4-element dims in a 5D
array’s metadata (writer.py re-assigns metadata on the .bin hop). Fixed:
the base setter now just stores the dict; only NumpyArray routes dims.
Verified end-to-end on real LBM data (raw SI tiff -> zarr+register_z -> axial
-> tiff -> bin/ops): dims stays TCZYX and dx/dy/fs/pixel_resolution/num_planes
carry through every hop; plane_shifts computed by register_z, applied by the
axial view, and correctly hidden in the baked tiff. Guard:
tests/local/test_metadata_carrythrough.py.