Skip to content

Commit

Permalink
refactor data loader (#299)
Browse files Browse the repository at this point in the history
Co-authored-by: LucaMarconato <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Luca Marconato <[email protected]>
  • Loading branch information
4 people authored Dec 14, 2023
1 parent ef0a2dc commit c9e7d99
Show file tree
Hide file tree
Showing 29 changed files with 573 additions and 304 deletions.
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build:
python: "3.10"
sphinx:
configuration: docs/conf.py
fail_on_warning: false
fail_on_warning: true
python:
install:
- method: pip
Expand Down
8 changes: 0 additions & 8 deletions docs/_templates/autosummary/class.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ Attributes table
~~~~~~~~~~~~~~~~~~

.. autosummary::

{% for item in attributes %}

~{{ fullname }}.{{ item }}

{%- endfor %}
{% endif %}
{% endblock %}
Expand All @@ -27,13 +24,10 @@ Methods table
~~~~~~~~~~~~~

.. autosummary::

{% for item in methods %}

{%- if item != '__init__' %}
~{{ fullname }}.{{ item }}
{%- endif -%}

{%- endfor %}
{% endif %}
{% endblock %}
Expand All @@ -46,7 +40,6 @@ Attributes
{% for item in attributes %}

.. autoattribute:: {{ [objname, item] | join(".") }}

{%- endfor %}

{% endif %}
Expand All @@ -61,7 +54,6 @@ Methods
{%- if item != '__init__' %}

.. automethod:: {{ [objname, item] | join(".") }}

{%- endif -%}
{%- endfor %}

Expand Down
14 changes: 9 additions & 5 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ Operations on `SpatialData` objects.
match_table_to_element
concatenate
rasterize
transform
aggregate
```

### Utilities
### Operations Utilities

```{eval-rst}
.. autosummary::
Expand All @@ -49,6 +48,7 @@ The elements (building-blocks) that consitute `SpatialData`.

```{eval-rst}
.. currentmodule:: spatialdata.models
.. autosummary::
:toctree: generated
Expand All @@ -61,9 +61,11 @@ The elements (building-blocks) that consitute `SpatialData`.
TableModel
```

### Utilities
### Models Utilities

```{eval-rst}
.. currentmodule:: spatialdata.models
.. autosummary::
:toctree: generated
Expand Down Expand Up @@ -94,9 +96,11 @@ The transformations that can be defined between elements and coordinate systems
Sequence
```

### Utilities
### Transformations Utilities

```{eval-rst}
.. currentmodule:: spatialdata.transformations
.. autosummary::
:toctree: generated
Expand All @@ -119,7 +123,7 @@ The transformations that can be defined between elements and coordinate systems
ImageTilesDataset
```

## Input/output
## Input/Output

```{eval-rst}
.. currentmodule:: spatialdata
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ dev = [
docs = [
"sphinx>=4.5",
"sphinx-book-theme>=1.0.0",
"sphinx_rtd_theme",
"myst-nb",
"sphinxcontrib-bibtex>=1.0.0",
"sphinx-autodoc-typehints",
Expand Down
8 changes: 2 additions & 6 deletions src/spatialdata/_core/concatenate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@

from copy import copy # Should probably go up at the top
from itertools import chain
from typing import TYPE_CHECKING, Any
from typing import Any

import numpy as np
from anndata import AnnData

if TYPE_CHECKING:
from spatialdata._core.spatialdata import SpatialData

from spatialdata._core.spatialdata import SpatialData
from spatialdata.models import TableModel

__all__ = [
Expand Down Expand Up @@ -94,8 +92,6 @@ def concatenate(
-------
The concatenated :class:`spatialdata.SpatialData` object.
"""
from spatialdata import SpatialData

merged_images = {**{k: v for sdata in sdatas for k, v in sdata.images.items()}}
if len(merged_images) != np.sum([len(sdata.images) for sdata in sdatas]):
raise KeyError("Images must have unique names across the SpatialData objects to concatenate")
Expand Down
64 changes: 40 additions & 24 deletions src/spatialdata/_core/data_extent.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ def get_extent(
has_labels: bool = True,
has_points: bool = True,
has_shapes: bool = True,
# python 3.9 tests fail if we don't use Union here, see
# https://github.com/scverse/spatialdata/pull/318#issuecomment-1755714287
elements: Union[list[str], None] = None, # noqa: UP007
elements: Union[ # noqa: UP007 # https://github.com/scverse/spatialdata/pull/318#issuecomment-1755714287
list[str], None
] = None,
) -> BoundingBoxDescription:
"""
Get the extent (bounding box) of a SpatialData object or a SpatialElement.
Expand All @@ -129,43 +129,50 @@ def get_extent(
Returns
-------
The bounding box description.
min_coordinate
The minimum coordinate of the bounding box.
max_coordinate
The maximum coordinate of the bounding box.
axes
The names of the dimensions of the bounding box
The names of the dimensions of the bounding box.
exact
If True, the extent is computed exactly. If False, an approximation faster to compute is given. The
approximation is guaranteed to contain all the data, see notes for details.
Whether the extent is computed exactly or not.
- If `True`, the extent is computed exactly.
- If `False`, an approximation faster to compute is given.
The approximation is guaranteed to contain all the data, see notes for details.
has_images
If True, images are included in the computation of the extent.
If `True`, images are included in the computation of the extent.
has_labels
If True, labels are included in the computation of the extent.
If `True`, labels are included in the computation of the extent.
has_points
If True, points are included in the computation of the extent.
If `True`, points are included in the computation of the extent.
has_shapes
If True, shapes are included in the computation of the extent.
If `True`, shapes are included in the computation of the extent.
elements
If not None, only the elements with the given names are included in the computation of the extent.
If not `None`, only the elements with the given names are included in the computation of the extent.
Notes
-----
The extent of a SpatialData object is the extent of the union of the extents of all its elements. The extent of a
SpatialElement is the extent of the element in the coordinate system specified by the argument `coordinate_system`.
The extent of a `SpatialData` object is the extent of the union of the extents of all its elements.
The extent of a `SpatialElement` is the extent of the element in the coordinate system
specified by the argument `coordinate_system`.
If `exact` is False, first the extent of the SpatialElement before any transformation is computed. Then, the extent
is transformed to the target coordinate system. This is faster than computing the extent after the transformation,
since the transformation is applied to extent of the untransformed data, as opposed to transforming the data and
then computing the extent.
If `exact` is `False`, first the extent of the `SpatialElement` before any transformation is computed.
Then, the extent is transformed to the target coordinate system. This is faster than computing the extent
after the transformation, since the transformation is applied to extent of the untransformed data,
as opposed to transforming the data and then computing the extent.
The exact and approximate extent are the same if the transformation doesn't contain any rotation or shear, or in the
case in which the transformation is affine but all the corners of the extent of the untransformed data
The exact and approximate extent are the same if the transformation does not contain any rotation or shear, or in
the case in which the transformation is affine but all the corners of the extent of the untransformed data
(bounding box corners) are part of the dataset itself. Note that this is always the case for raster data.
An extreme case is a dataset composed of the two points (0, 0) and (1, 1), rotated anticlockwise by 45 degrees. The
exact extent is the bounding box [minx, miny, maxx, maxy] = [0, 0, 0, 1.414], while the approximate extent is the
box [minx, miny, maxx, maxy] = [-0.707, 0, 0.707, 1.414].
An extreme case is a dataset composed of the two points `(0, 0)` and `(1, 1)`, rotated anticlockwise by 45 degrees.
The exact extent is the bounding box `[minx, miny, maxx, maxy] = [0, 0, 0, 1.414]`, while the approximate extent is
the box `[minx, miny, maxx, maxy] = [-0.707, 0, 0.707, 1.414]`.
"""
raise ValueError("The object type is not supported.")

Expand All @@ -184,7 +191,9 @@ def _(
elements: Union[list[str], None] = None, # noqa: UP007
) -> BoundingBoxDescription:
"""
Get the extent (bounding box) of a SpatialData object: the extent of the union of the extents of all its elements.
Get the extent (bounding box) of a SpatialData object.
The resulting extent is the union of the extents of all its elements.
Parameters
----------
Expand Down Expand Up @@ -259,7 +268,14 @@ def _get_extent_of_shapes(e: GeoDataFrame) -> BoundingBoxDescription:
@get_extent.register
def _(e: GeoDataFrame, coordinate_system: str = "global", exact: bool = True) -> BoundingBoxDescription:
"""
Compute the extent (bounding box) of a set of shapes.
Get the extent (bounding box) of a SpatialData object.
The resulting extent is the union of the extents of all its elements.
Parameters
----------
e
The SpatialData object.
Returns
-------
Expand Down
7 changes: 2 additions & 5 deletions src/spatialdata/_core/operations/aggregate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import warnings
from typing import TYPE_CHECKING, Any
from typing import Any

import anndata as ad
import dask as da
Expand All @@ -20,6 +20,7 @@
from spatialdata._core.operations.transform import transform
from spatialdata._core.query._utils import circles_to_polygons
from spatialdata._core.query.relational_query import get_values
from spatialdata._core.spatialdata import SpatialData
from spatialdata._types import ArrayLike
from spatialdata.models import (
Image2DModel,
Expand All @@ -32,9 +33,6 @@
)
from spatialdata.transformations import BaseTransformation, Identity, get_transformation

if TYPE_CHECKING:
from spatialdata import SpatialData

__all__ = ["aggregate"]


Expand Down Expand Up @@ -236,7 +234,6 @@ def _create_sdata_from_table_and_shapes(
instance_key: str,
deepcopy: bool,
) -> SpatialData:
from spatialdata import SpatialData
from spatialdata._utils import _deepcopy_geodataframe

table.obs[instance_key] = table.obs_names.copy()
Expand Down
2 changes: 0 additions & 2 deletions src/spatialdata/_core/operations/rasterize.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,6 @@ def _(
target_height: Optional[float] = None,
target_depth: Optional[float] = None,
) -> SpatialData:
from spatialdata import SpatialData

min_coordinate = _parse_list_into_array(min_coordinate)
max_coordinate = _parse_list_into_array(max_coordinate)

Expand Down
6 changes: 2 additions & 4 deletions src/spatialdata/_core/query/relational_query.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING, Any
from typing import Any

import dask.array as da
import numpy as np
Expand All @@ -11,6 +11,7 @@
from multiscale_spatial_image import MultiscaleSpatialImage
from spatial_image import SpatialImage

from spatialdata._core.spatialdata import SpatialData
from spatialdata._utils import _inplace_fix_subset_categorical_obs
from spatialdata.models import (
Labels2DModel,
Expand All @@ -22,9 +23,6 @@
get_model,
)

if TYPE_CHECKING:
from spatialdata import SpatialData


def _filter_table_by_coordinate_system(table: AnnData | None, coordinate_system: str | list[str]) -> AnnData | None:
"""
Expand Down
1 change: 0 additions & 1 deletion src/spatialdata/_core/query/spatial_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ def _(
target_coordinate_system: str,
filter_table: bool = True,
) -> SpatialData:
from spatialdata import SpatialData
from spatialdata._core.query.relational_query import _filter_table_by_elements

min_coordinate = _parse_list_into_array(min_coordinate)
Expand Down
Loading

0 comments on commit c9e7d99

Please sign in to comment.