neu_vol.pyramid

Multiscale pyramid: downsample schedule, type-aware reducers, OME transforms.

Strict level-by-level coarsening: each level is produced from the previous (finer) level on disk. This module supplies the pure pieces — the schedule (per-level integer factors), the reducers (mean for image/probability, mode for label-preserving segmentation), and the coordinate transforms (center-aligned scale/translation) for OME-NGFF metadata. The orchestration lives in ops/ (block-map per level).

Attributes

Functions

auto_factor(voxel_size, *[, isotropy_threshold]) → tuple[int, ...]

Per-axis factor for one level, coarsening the finest axes toward isotropy.

cumulative_factors(schedule, ndim) → list[tuple[int, ...]]

Cumulative factors relative to level 0, for levels 0..L (level 0 = all 1s).

downsample_schedule(shape, voxel_size, *[, factors, ...]) → list[tuple[int, ...]]

Return per-level relative downsample factors for levels 1..L (level 0 excluded).

get_reducer(kind) → Callable[[numpy.ndarray, Sequence[int]], numpy.ndarray]

level_scale_translation(voxel_size, offset, cum_factor) → tuple[list[float], list[float]]

Center-aligned (scale, translation) for a level with cumulative cum_factor.

mean_downsample(arr, factors) → numpy.ndarray

Mask-weighted mean downsample (anti-aliasing); ragged edges use real voxels only.

mode_downsample(arr, factors) → numpy.ndarray

Label-preserving mode downsample; ties broken to the smallest label.

Module Contents

neu_vol.pyramid.auto_factor(voxel_size: Sequence[float], *, isotropy_threshold: float = 2.0) → tuple[int, ...]

Per-axis factor for one level, coarsening the finest axes toward isotropy.

Downsample an axis by 2 iff its voxel size is within isotropy_threshold of the finest axis; otherwise leave it (factor 1). Isotropic input -> all 2s.

neu_vol.pyramid.cumulative_factors(schedule: Sequence[Sequence[int]], ndim: int) → list[tuple[int, ...]]

Cumulative factors relative to level 0, for levels 0..L (level 0 = all 1s).

ndim is required so the level-0 identity is correct even when schedule is empty (single-scale output).

neu_vol.pyramid.downsample_schedule(shape: Sequence[int], voxel_size: Sequence[float], *, factors: Sequence[Sequence[int]] | None = None, max_levels: int = 8, min_dim: int = 128, isotropy_threshold: float = 2.0) → list[tuple[int, ...]]

Return per-level relative downsample factors for levels 1..L (level 0 excluded).

If factors is given it is used verbatim — max_levels and min_dim do not apply to an explicit schedule. Otherwise factors are derived with auto_factor(), stopping when the volume’s largest spatial dimension is <= min_dim, when no axis can be coarsened, or at max_levels.

max_levels counts levels including level 0, so the returned list has at most max_levels - 1 entries: max_levels=8 gives levels 0..7, and max_levels=1 a single-scale volume.

neu_vol.pyramid.get_reducer(kind: str) → Callable[[numpy.ndarray, Sequence[int]], numpy.ndarray]
neu_vol.pyramid.level_scale_translation(voxel_size: Sequence[float], offset: Sequence[float], cum_factor: Sequence[int]) → tuple[list[float], list[float]]

Center-aligned (scale, translation) for a level with cumulative cum_factor.

scale = voxel_size * F; translation = offset + 0.5 * (F - 1) * voxel_size (a downsampled voxel’s center sits at the centroid of the source voxels it covers). Matches ngff-zarr’s convention.

neu_vol.pyramid.mean_downsample(arr: numpy.ndarray, factors: Sequence[int]) → numpy.ndarray

Mask-weighted mean downsample (anti-aliasing); ragged edges use real voxels only.

Integer dtypes are rounded; float dtypes preserved. For images/probabilities.

The per-window sum is accumulated at the output size rather than upcasting the whole input to float64, and the validity mask is built only for a ragged block, which keeps a 512^3 block at a few GB instead of ~30 GB.

neu_vol.pyramid.mode_downsample(arr: numpy.ndarray, factors: Sequence[int]) → numpy.ndarray

Label-preserving mode downsample; ties broken to the smallest label.

For segmentations (never interpolate IDs). Vectorized for small windows (prod(factors) small, e.g. 8 for 2x2x2); chunk the input for very large windows if memory-bound.

neu_vol.pyramid.REDUCERS: dict[str, Callable[[numpy.ndarray, Sequence[int]], numpy.ndarray]]