Skip to content

Add async oindex and vindex methods to AsyncArray #3083

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/zarr/core/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
)
from zarr.core.config import config as zarr_config
from zarr.core.indexing import (
AsyncOIndex,
AsyncVIndex,
BasicIndexer,
BasicSelection,
BlockIndex,
Expand Down Expand Up @@ -1358,6 +1360,42 @@
)
return await self._get_selection(indexer, prototype=prototype)

async def get_orthogonal_selection(
self,
selection: OrthogonalSelection,
*,

Check warning on line 1366 in src/zarr/core/array.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/array.py#L1363-L1366

Added lines #L1363 - L1366 were not covered by tests
out: NDBuffer | None = None,
fields: Fields | None = None,
prototype: BufferPrototype | None = None,
) -> NDArrayLike:
if prototype is None:
prototype = default_buffer_prototype()
indexer = OrthogonalIndexer(selection, self.shape, self.metadata.chunk_grid)
return await self._get_selection(
indexer=indexer, out=out, fields=fields, prototype=prototype
)

@_deprecate_positional_args
async def get_coordinate_selection(
self,
selection: CoordinateSelection,
*,

Check warning on line 1382 in src/zarr/core/array.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/array.py#L1379-L1382

Added lines #L1379 - L1382 were not covered by tests
out: NDBuffer | None = None,
fields: Fields | None = None,
prototype: BufferPrototype | None = None,
) -> NDArrayLikeOrScalar:

Check warning on line 1386 in src/zarr/core/array.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/array.py#L1386

Added line #L1386 was not covered by tests
if prototype is None:
prototype = default_buffer_prototype()
indexer = CoordinateIndexer(selection, self.shape, self.metadata.chunk_grid)

Check warning on line 1389 in src/zarr/core/array.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/array.py#L1388-L1389

Added lines #L1388 - L1389 were not covered by tests
out_array = await self._get_selection(
indexer=indexer, out=out, fields=fields, prototype=prototype
)

if hasattr(out_array, "shape"):
# restore shape
out_array = np.array(out_array).reshape(indexer.sel_shape)
return out_array

async def _save_metadata(self, metadata: ArrayMetadata, ensure_parents: bool = False) -> None:
"""
Asynchronously save the array metadata.
Expand Down Expand Up @@ -1488,6 +1526,16 @@
)
return await self._set_selection(indexer, value, prototype=prototype)

@property

Check warning on line 1529 in src/zarr/core/array.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/array.py#L1529

Added line #L1529 was not covered by tests
def oindex(self) -> AsyncOIndex:
"""Shortcut for orthogonal (outer) indexing, see :func:`get_orthogonal_selection` and
:func:`set_orthogonal_selection` for documentation and examples."""
return AsyncOIndex(self)

@property
def vindex(self) -> AsyncVIndex:
return AsyncVIndex(self)

async def resize(self, new_shape: ShapeLike, delete_outside_chunks: bool = True) -> None:
"""
Asynchronously resize the array to a new shape.
Expand Down
45 changes: 44 additions & 1 deletion src/zarr/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from zarr.core.common import product

if TYPE_CHECKING:
from zarr.core.array import Array
from zarr.core.array import Array, AsyncArray
from zarr.core.buffer import NDArrayLikeOrScalar
from zarr.core.chunk_grids import ChunkGrid
from zarr.core.common import ChunkCoords
Expand Down Expand Up @@ -960,6 +960,25 @@
)


@dataclass(frozen=True)
class AsyncOIndex:
array: AsyncArray

async def getitem(self, selection: OrthogonalSelection | Array) -> NDArrayLike:
from zarr.core.array import Array

Check warning on line 968 in src/zarr/core/indexing.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/indexing.py#L968

Added line #L968 was not covered by tests

# if input is a Zarr array, we materialize it now.
if isinstance(selection, Array):
selection = _zarr_array_to_int_or_bool_array(selection)

Check warning on line 972 in src/zarr/core/indexing.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/indexing.py#L971-L972

Added lines #L971 - L972 were not covered by tests

fields, new_selection = pop_fields(selection)
new_selection = ensure_tuple(new_selection)
new_selection = replace_lists(new_selection)
return await self.array.get_orthogonal_selection(

Check warning on line 977 in src/zarr/core/indexing.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/indexing.py#L974-L977

Added lines #L974 - L977 were not covered by tests
cast(OrthogonalSelection, new_selection), fields=fields
)


@dataclass(frozen=True)
class BlockIndexer(Indexer):
dim_indexers: list[SliceDimIndexer]
Expand Down Expand Up @@ -1268,6 +1287,30 @@
raise VindexInvalidSelectionError(new_selection)


@dataclass(frozen=True)
class AsyncVIndex:
array: AsyncArray

# TODO: develop Array generic and move zarr.Array[np.intp] | zarr.Array[np.bool_] to ArrayOfIntOrBool
async def getitem(
self, selection: CoordinateSelection | MaskSelection | Array
) -> NDArrayLikeOrScalar:
from zarr.core.array import Array

Check warning on line 1298 in src/zarr/core/indexing.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/indexing.py#L1298

Added line #L1298 was not covered by tests

# if input is a Zarr array, we materialize it now.
if isinstance(selection, Array):
selection = _zarr_array_to_int_or_bool_array(selection)
fields, new_selection = pop_fields(selection)
new_selection = ensure_tuple(new_selection)
new_selection = replace_lists(new_selection)
if is_coordinate_selection(new_selection, self.array.shape):
return await self.array.get_coordinate_selection(new_selection, fields=fields)
elif is_mask_selection(new_selection, self.array.shape):
return self.array.get_mask_selection(new_selection, fields=fields)

Check warning on line 1309 in src/zarr/core/indexing.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/indexing.py#L1301-L1309

Added lines #L1301 - L1309 were not covered by tests
else:
raise VindexInvalidSelectionError(new_selection)

Check warning on line 1311 in src/zarr/core/indexing.py

View check run for this annotation

Codecov / codecov/patch

src/zarr/core/indexing.py#L1311

Added line #L1311 was not covered by tests


def check_fields(fields: Fields | None, dtype: np.dtype[Any]) -> np.dtype[Any]:
# early out
if fields is None:
Expand Down
Loading