Skip to content

zarr_indexing.composition

zarr_indexing.composition

Composition — chaining two transforms into one.

compose(outer, inner) is the operation that makes views stack. outer maps user coordinates to intermediate coordinates, inner maps those intermediate coordinates to storage, and the result maps user coordinates straight to storage — so a view of a view of an array is still a single IndexTransform, and indexing never accumulates layers to walk at read time.

Composition works one output map at a time, and each case reduces to substituting the outer map into the inner one:

  • A ConstantMap inner map ignores its input, so it survives unchanged.
  • A DimensionMap inner map is affine, so composing it with an outer ConstantMap or DimensionMap folds into new offset/stride values; composing it with an outer ArrayMap leaves the index array alone and rescales around it.
  • An ArrayMap inner map must be evaluated at the coordinates the outer transform produces, which is the only case that touches array data.

compose

compose(
    outer: IndexTransform, inner: IndexTransform
) -> IndexTransform

Compose two IndexTransforms.

outer maps user coords (rank m) to intermediate coords (rank n). inner maps intermediate coords (rank n) to storage coords (rank p). The result maps user coords (rank m) to storage coords (rank p).

Precondition: outer.output_rank == inner.domain.ndim.

Source code in packages/zarr-indexing/src/zarr_indexing/composition.py
def compose(outer: IndexTransform, inner: IndexTransform) -> IndexTransform:
    """Compose two IndexTransforms.

    `outer` maps user coords (rank m) to intermediate coords (rank n).
    `inner` maps intermediate coords (rank n) to storage coords (rank p).
    The result maps user coords (rank m) to storage coords (rank p).

    Precondition: `outer.output_rank == inner.domain.ndim`.
    """
    if outer.output_rank != inner.domain.ndim:
        raise ValueError(
            f"outer output rank ({outer.output_rank}) must match inner input rank "
            f"({inner.domain.ndim})"
        )

    result_output = [_compose_single(outer, inner_map) for inner_map in inner.output]

    return IndexTransform(domain=outer.domain, output=tuple(result_output))