Skip to content

Commit

Permalink
ExperimentAxisQuery, AxisIndexer are explicitly ABCs
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-williams committed Nov 15, 2024
1 parent 2b183cb commit 8d76a8a
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 26 deletions.
6 changes: 4 additions & 2 deletions python-spec/src/somacore/experiment.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import abc
from abc import ABC
from abc import abstractmethod
from typing import Generic, Optional, TypeVar

from typing_extensions import Final
Expand All @@ -25,7 +26,7 @@
class Experiment( # type: ignore[misc] # __eq__ false positive
collection.BaseCollection[_RootSO],
Generic[_DF, _MeasColl, _SceneColl, _RootSO],
abc.ABC,
ABC,
):
"""A collection subtype representing an annotated 2D matrix of measurements.
Expand Down Expand Up @@ -65,6 +66,7 @@ class Experiment( # type: ignore[misc] # __eq__ false positive
``scene_id`` and ``False`` otherwise.
"""

@abstractmethod
def axis_query(
self,
measurement_name: str,
Expand Down
68 changes: 44 additions & 24 deletions python-spec/src/somacore/query/query.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from abc import ABC
from abc import abstractmethod
from typing import (
Any,
Mapping,
Expand Down Expand Up @@ -39,7 +41,7 @@ class AxisColumnNames(TypedDict, total=False):
"""var columns to use. All columns if ``None`` or not present."""


class ExperimentAxisQuery:
class ExperimentAxisQuery(ABC):
"""Axis-based query against a SOMA Experiment.
ExperimentAxisQuery allows easy selection and extraction of data from a
Expand All @@ -53,6 +55,7 @@ class ExperimentAxisQuery:
Lifecycle: maturing
"""

@abstractmethod
def obs(
self,
*,
Expand All @@ -68,8 +71,9 @@ def obs(
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def var(
self,
*,
Expand All @@ -85,46 +89,52 @@ def var(
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def obs_joinids(self) -> pa.IntegerArray:
"""Returns ``obs`` ``soma_joinids`` as an Arrow array.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def var_joinids(self) -> pa.IntegerArray:
"""Returns ``var`` ``soma_joinids`` as an Arrow array.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
@property
def n_obs(self) -> int:
"""The number of ``obs`` axis query results.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
@property
def n_vars(self) -> int:
"""The number of ``var`` axis query results.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
@property
def indexer(self) -> "AxisIndexer":
"""A ``soma_joinid`` indexer for both ``obs`` and ``var`` axes.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def X(
self,
layer_name: str,
Expand All @@ -149,50 +159,57 @@ def X(
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def obsp(self, layer: str) -> SparseRead:
"""Returns an ``obsp`` layer as a sparse read.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def varp(self, layer: str) -> SparseRead:
"""Returns a ``varp`` layer as a sparse read.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def obsm(self, layer: str) -> SparseRead:
"""Returns an ``obsm`` layer as a sparse read.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def varm(self, layer: str) -> SparseRead:
"""Returns a ``varm`` layer as a sparse read.
Lifecycle: maturing
"""
raise NotImplementedError
...

@abstractmethod
def obs_scene_ids(self) -> pa.Array:
"""Returns a pyarrow array with scene ids that contain obs from this
query.
Lifecycle: experimental
"""
raise NotImplementedError
...

@abstractmethod
def var_scene_ids(self) -> pa.Array:
"""Return a pyarrow array with scene ids that contain var from this
query.
Lifecycle: experimental
"""
raise NotImplementedError
...

@abstractmethod
def to_anndata(
self,
X_name: str,
Expand Down Expand Up @@ -230,44 +247,47 @@ def to_anndata(
Lifecycle: maturing
"""
raise NotImplementedError
...

# Context management

@abstractmethod
def close(self) -> None:
"""Releases resources associated with this query.
This method must be idempotent.
Lifecycle: maturing
"""
raise NotImplementedError
...

def __enter__(self) -> Self:
raise NotImplementedError
@abstractmethod
def __enter__(self) -> Self: ...

def __exit__(self, *_: Any) -> None:
raise NotImplementedError
@abstractmethod
def __exit__(self, *_: Any) -> None: ...


Numpyable = Union[pa.Array, pa.ChunkedArray, npt.NDArray[np.int64]]
"""Things that can be converted to a NumPy array."""


class AxisIndexer:
class AxisIndexer(ABC):
"""
Given a query, provides index-building services for obs/var axis.
Lifecycle: maturing
"""

@abstractmethod
def by_obs(self, coords: Numpyable) -> npt.NDArray[np.intp]:
"""Reindex the coords (soma_joinids) over the ``obs`` axis."""
raise NotImplementedError
...

@abstractmethod
def by_var(self, coords: Numpyable) -> npt.NDArray[np.intp]:
"""Reindex for the coords (soma_joinids) over the ``var`` axis."""
raise NotImplementedError
...


class Experimentish(Protocol):
Expand Down

0 comments on commit 8d76a8a

Please sign in to comment.