zarr_indexing.boundary
zarr_indexing.boundary ¶
The positional (NumPy) selection dialect, lowered onto the transform algebra.
The transform algebra uses literal domain coordinates: an index is a point
in the view's own coordinate system, which after view = arr[10:50] runs from
10 to 49, and a negative index is a negative coordinate rather than an offset
from the end (TensorStore's convention — see zarr_indexing.transform).
NumPy uses positions: index 0 always means the first element of the object
being indexed, and -1 means the last. This module translates between the two.
It validates a selection against the view's shape with NumPy semantics, then
shifts every coordinate by the domain's origin so the transform layer sees
literal coordinates.
Note
zarr.Array currently carries its own copy of this normalization, tuned to a
different boundary contract (Array.lazy[...] deliberately exposes the literal
dialect, so a view's coordinates keep their meaning across composition). This
module is the generic, zarr-free version used by LazyArray; consolidating
zarr's copy onto it is left to a follow-up.
normalize_positional_selection ¶
normalize_positional_selection(
selection: Any, domain: IndexDomain, mode: SelectionMode
) -> Any
Translate a positional (NumPy-dialect) selection into literal coordinates.
Positions are zero-based offsets into the current view; negatives wrap
from the end. The returned selection addresses the same cells in the
literal coordinate system domain uses, ready for
zarr_indexing.transform.selection_to_transform.
Parameters:
-
selection(Any) –A NumPy-style selection: integers, slices,
Ellipsis, integer arrays or lists, or boolean arrays. -
domain(IndexDomain) –The domain of the view being indexed. Its shape defines the positional bounds and its origin the coordinate shift.
-
mode(SelectionMode) –Which selection dialect the entries follow:
"basic"(integers and slices),"orthogonal"(per-axis arrays, outer product), or"vectorized"(correlated coordinate arrays or a single mask).
Returns:
Raises:
-
IndexError–If a boolean scalar is used as an index, a boolean mask does not match the shape of the axes it covers, an index is out of bounds, or too many indices are supplied.
Source code in src/zarr_indexing/boundary.py
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | |
split_scalar_axes ¶
split_scalar_axes(
selection: Any, domain: IndexDomain, mode: SelectionMode
) -> tuple[tuple[Any, ...] | None, Any]
Peel scalar integer indices out of a fancy selection.
A scalar integer drops its axis, and neither the orthogonal nor the vectorized path of the transform algebra models that — both widen a scalar into a length-1 index array, which keeps the axis — so the scalars are split off here and applied as a separate basic step first.
Applying them first is this package's rule, not NumPy's. NumPy groups a
scalar with the advanced indices for the purpose of placing the broadcast
result, so the two disagree when a scalar and an index array are separated:
a[0, ..., [1, 2]] has shape (2, 3) for a (2, 3, 4) array, where
a[0][..., [1, 2]] has shape (3, 2). The earlier claim here that they
always agree rested on a[0, [1, 2], :], where the indices are adjacent and
they happen to. Scalar-first is the documented dialect (see the lazy_array
module docstring) — the divergence is deliberate, and this note exists so
that the correct end is not "fixed" later.
Parameters:
-
selection(Any) –A positional orthogonal or vectorized selection.
-
domain(IndexDomain) –The domain of the view being indexed.
-
mode(SelectionMode) –"orthogonal"or"vectorized"; controls how many axes each entry covers, which decides where the scalars sit.
Returns:
-
tuple[tuple[Any, ...] | None, Any]–(basic_selection, remaining_selection).basic_selectionis a full-rank basic selection in literal domain coordinates that drops the scalar axes, orNonewhen the selection has no scalar entries (in which caseremaining_selectionisselectionunchanged).
Raises:
-
IndexError–If a boolean scalar is used as an index, an index is out of bounds, or too many indices are supplied.
Source code in src/zarr_indexing/boundary.py
validate_advanced_selection ¶
validate_advanced_selection(
selection: Any,
domain: IndexDomain,
mode: Literal["orthogonal", "vectorized"],
) -> None
Validate advanced-index selector dtypes and boolean mask extents.
This is the validation shared by positional callers such as LazyArray
and direct IndexTransform.oindex / .vindex callers. It deliberately
does not normalize coordinates: direct transforms use literal coordinates,
whereas positional callers shift and wrap them separately.