Skip to content

Commit 7427003

Browse files
Merge pull request #75 from BioinfoTongLI/main
Added ISS support of Sanger data format
2 parents ff3f0bb + adf43e1 commit 7427003

File tree

4 files changed

+137
-7
lines changed

4 files changed

+137
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning][].
1313
### Added
1414

1515
- (Xenium) support reading multi-polygon selection files from the Xenium Explorer
16+
- (ISS) An experimental loader to load elemental ISS data objects, e.g. raw.tif, label.tif and anndata.h5ad
1617

1718
### Fixed
1819

docs/api.md

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,26 @@ I/O for the `spatialdata` project.
2626
xenium
2727
```
2828

29-
### Conversion functions
30-
31-
### Utility functions
29+
### Experimental readers
3230

3331
```{eval-rst}
32+
.. currentmodule:: spatialdata_io.experimental
33+
3434
.. autosummary::
3535
:toctree: generated
3636
37-
xenium_aligned_image
38-
xenium_explorer_selection
37+
iss
3938
```
4039

41-
### Experimental readers
40+
### Conversion functions
41+
42+
```{eval-rst}
43+
.. currentmodule:: spatialdata_io
44+
45+
.. autosummary::
46+
:toctree: generated
47+
48+
```
4249

4350
### Experimental conversion functions
4451

@@ -51,3 +58,15 @@ I/O for the `spatialdata` project.
5158
from_legacy_anndata
5259
to_legacy_anndata
5360
```
61+
62+
### Utility functions
63+
64+
```{eval-rst}
65+
.. currentmodule:: spatialdata_io
66+
67+
.. autosummary::
68+
:toctree: generated
69+
70+
xenium_aligned_image
71+
xenium_explorer_selection
72+
```

src/spatialdata_io/experimental/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
from_legacy_anndata,
33
to_legacy_anndata,
44
)
5+
from spatialdata_io.readers.iss import iss
56

6-
__all__ = ["from_legacy_anndata", "to_legacy_anndata"]
7+
__all__ = ["from_legacy_anndata", "to_legacy_anndata", "iss"]

src/spatialdata_io/readers/iss.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from __future__ import annotations
2+
3+
from collections.abc import Mapping
4+
from pathlib import Path
5+
from types import MappingProxyType
6+
from typing import Any
7+
8+
import anndata as ad
9+
from dask_image.imread import imread
10+
from spatialdata import SpatialData
11+
from spatialdata.models import Image2DModel, Labels2DModel, TableModel
12+
from spatialdata.transformations.transformations import Identity
13+
from xarray import DataArray
14+
15+
from spatialdata_io._docs import inject_docs
16+
17+
__all__ = ["iss"]
18+
19+
20+
@inject_docs()
21+
def iss(
22+
path: str | Path,
23+
raw_relative_path: str | Path,
24+
labels_relative_path: str | Path,
25+
h5ad_relative_path: str | Path,
26+
instance_key: str,
27+
dataset_id: str = "region",
28+
multiscale_image: bool = True,
29+
multiscale_labels: bool = True,
30+
imread_kwargs: Mapping[str, Any] = MappingProxyType({}),
31+
image_models_kwargs: Mapping[str, Any] = MappingProxyType({}),
32+
labels_models_kwargs: Mapping[str, Any] = MappingProxyType({}),
33+
) -> SpatialData:
34+
"""
35+
Read *Sanger ISS* formatted dataset.
36+
37+
This function reads the following files:
38+
39+
- ``<dataset_id>``: Counts and metadata file.
40+
- ``<raw_relative_path>``: Raw raster image.
41+
- ``<labels_relative_path>``: Label image.
42+
43+
Parameters
44+
----------
45+
path
46+
Path to the directory containing the data.
47+
raw_relative_path
48+
Relative path to the raw raster image file.
49+
labels_relative_path
50+
Relative path to the label image file.
51+
h5ad_relative_path
52+
Relative path to the counts and metadata file.
53+
instance_key
54+
The name of the column that contains the instance identifiers.
55+
Must be specified to link the table with the labels image (e.g. `cell_id`).
56+
dataset_id
57+
Dataset identifier.
58+
multiscale_image
59+
Whether to process the raw image into a multiscale image.
60+
multiscale_labels
61+
Whether to process the label image into a multiscale image.
62+
imread_kwargs
63+
Keyword arguments passed to :func:`dask_image.imread.imread`.
64+
image_models_kwargs
65+
Keyword arguments passed to :class:`spatialdata.models.Image2DModel`.
66+
labels_models_kwargs
67+
Keyword arguments passed to :class:`spatialdata.models.Labels2DModel`.
68+
69+
Returns
70+
-------
71+
The spatial data object containing the ISS data.
72+
"""
73+
REGION = f"{dataset_id}_labels_image"
74+
REGION_KEY = "region"
75+
path = Path(path)
76+
77+
adata = ad.read(path / h5ad_relative_path)
78+
adata.obs[instance_key] = adata.obs.index.astype(int)
79+
adata.var_names_make_unique()
80+
adata.obs[REGION_KEY] = REGION
81+
table = TableModel.parse(adata, region=REGION, region_key=REGION_KEY, instance_key=instance_key)
82+
83+
transform_original = Identity()
84+
85+
labels_image = imread(path / labels_relative_path, **imread_kwargs).squeeze()
86+
labels_image = DataArray(labels_image[2, :, :], dims=("y", "x"))
87+
88+
labels_image_parsed = Labels2DModel.parse(
89+
labels_image,
90+
scale_factors=[2, 2, 2, 2] if multiscale_labels else None,
91+
transformations={"global": transform_original},
92+
**labels_models_kwargs,
93+
)
94+
95+
raw_image = imread(path / raw_relative_path, **imread_kwargs)
96+
raw_image = DataArray(raw_image, dims=("c", "y", "x"))
97+
98+
raw_image_parsed = Image2DModel.parse(
99+
raw_image,
100+
scale_factors=[2, 2, 2, 2] if multiscale_image else None,
101+
transformations={"global": transform_original},
102+
**image_models_kwargs,
103+
)
104+
105+
return SpatialData(
106+
images={f"{dataset_id}_raw_image": raw_image_parsed},
107+
labels={REGION: labels_image_parsed},
108+
table=table,
109+
)

0 commit comments

Comments
 (0)