spatialdata-io 0.1.2__tar.gz → 0.1.3.post0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. spatialdata_io-0.1.3.post0/.github/codecov.yml +17 -0
  2. spatialdata_io-0.1.3.post0/.github/workflows/prepare_test_data.yaml +35 -0
  3. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.github/workflows/test.yaml +18 -1
  4. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.gitignore +6 -2
  5. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.pre-commit-config.yaml +6 -6
  6. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/CHANGELOG.md +21 -0
  7. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/PKG-INFO +3 -2
  8. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/README.md +1 -0
  9. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/_version.py +2 -2
  10. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/api.md +27 -6
  11. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/pyproject.toml +1 -1
  12. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/__init__.py +4 -0
  13. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/_constants/_constants.py +108 -0
  14. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/converters/legacy_anndata.py +1 -1
  15. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/experimental/__init__.py +2 -1
  16. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/_utils/_utils.py +18 -0
  17. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/cosmx.py +1 -1
  18. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/dbit.py +66 -35
  19. spatialdata_io-0.1.3.post0/src/spatialdata_io/readers/iss.py +112 -0
  20. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/mcmicro.py +1 -1
  21. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/merscope.py +136 -44
  22. spatialdata_io-0.1.3.post0/src/spatialdata_io/readers/seqfish.py +190 -0
  23. spatialdata_io-0.1.3.post0/src/spatialdata_io/readers/stereoseq.py +341 -0
  24. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/visium.py +6 -0
  25. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/visium_hd.py +26 -16
  26. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/xenium.py +69 -38
  27. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/tests/converters/test_legacy_anndata.py +2 -3
  28. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/tests/test_xenium.py +31 -0
  29. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.bumpversion.cfg +0 -0
  30. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.codecov.yaml +0 -0
  31. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.editorconfig +0 -0
  32. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.flake8 +0 -0
  33. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.github/workflows/build.yaml +0 -0
  34. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.github/workflows/release.yaml +0 -0
  35. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.mypy.ini +0 -0
  36. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/.readthedocs.yaml +0 -0
  37. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/LICENSE +0 -0
  38. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/Makefile +0 -0
  39. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/_static/.gitkeep +0 -0
  40. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/_templates/.gitkeep +0 -0
  41. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/_templates/autosummary/class.rst +0 -0
  42. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/changelog.md +0 -0
  43. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/conf.py +0 -0
  44. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/contributing.md +0 -0
  45. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/extensions/.gitkeep +0 -0
  46. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/extensions/typed_returns.py +0 -0
  47. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/index.md +0 -0
  48. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/make.bat +0 -0
  49. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/references.bib +0 -0
  50. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/references.md +0 -0
  51. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/docs/template_usage.md +0 -0
  52. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/_constants/__init__.py +0 -0
  53. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/_constants/_enum.py +0 -0
  54. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/_docs.py +0 -0
  55. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/_utils.py +0 -0
  56. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/converters/__init__.py +0 -0
  57. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/__init__.py +0 -0
  58. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/_utils/__init__.py +0 -0
  59. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/_utils/_read_10x_h5.py +0 -0
  60. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/codex.py +0 -0
  61. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/curio.py +0 -0
  62. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/src/spatialdata_io/readers/steinbock.py +0 -0
  63. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/tests/__init__.py +0 -0
  64. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/tests/converters/__init__.py +0 -0
  65. {spatialdata_io-0.1.2 → spatialdata_io-0.1.3.post0}/tests/test_basic.py +0 -0
@@ -0,0 +1,17 @@
1
+ # Based on pydata/xarray
2
+ codecov:
3
+ require_ci_to_pass: false
4
+
5
+ coverage:
6
+ status:
7
+ project:
8
+ default:
9
+ # Require 1% coverage, i.e., always succeed
10
+ target: 1
11
+ patch: false
12
+ changes: false
13
+
14
+ comment:
15
+ layout: "diff, flags, files"
16
+ behavior: once
17
+ require_base: false
@@ -0,0 +1,35 @@
1
+ name: Prepare test data
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ # uncomment and adjust the branch name if you need to add new datasets to the artifact
6
+ # push:
7
+ # branches:
8
+ # - main
9
+
10
+ jobs:
11
+ prepare-data:
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v3
16
+
17
+ - name: Download test datasets
18
+ run: |
19
+ mkdir -p ./data
20
+ cd ./data
21
+ curl -O https://cf.10xgenomics.com/samples/xenium/2.0.0/Xenium_V1_human_Breast_2fov/Xenium_V1_human_Breast_2fov_outs.zip
22
+ curl -O https://cf.10xgenomics.com/samples/xenium/2.0.0/Xenium_V1_human_Lung_2fov/Xenium_V1_human_Lung_2fov_outs.zip
23
+
24
+ - name: Unzip files
25
+ run: |
26
+ unzip ./data/Xenium_V1_human_Breast_2fov_outs.zip -d ./data/Xenium_V1_human_Breast_2fov_outs
27
+ unzip ./data/Xenium_V1_human_Lung_2fov_outs.zip -d ./data/Xenium_V1_human_Lung_2fov_outs
28
+ rm ./data/Xenium_V1_human_Breast_2fov_outs.zip
29
+ rm ./data/Xenium_V1_human_Lung_2fov_outs.zip
30
+
31
+ - name: Upload artifacts
32
+ uses: actions/upload-artifact@v3
33
+ with:
34
+ name: data
35
+ path: ./data
@@ -50,6 +50,21 @@ jobs:
50
50
  - name: Install dependencies
51
51
  run: |
52
52
  pip install --pre -e ".[dev,test]"
53
+
54
+ - name: Download artifact of test data
55
+ if: matrix.python == '3.10'
56
+ uses: dawidd6/action-download-artifact@v2
57
+ with:
58
+ workflow: prepare_test_data.yaml
59
+ name: data
60
+ path: ./data
61
+
62
+ - name: List the data directory
63
+ if: matrix.python == '3.10'
64
+ run: |
65
+ ls -l ./data
66
+ pwd
67
+
53
68
  - name: Test
54
69
  env:
55
70
  MPLBACKEND: agg
@@ -58,7 +73,9 @@ jobs:
58
73
  run: |
59
74
  pytest -v --cov --color=yes --cov-report=xml
60
75
  - name: Upload coverage to Codecov
61
- uses: codecov/codecov-action@v3.1.1
76
+ uses: codecov/codecov-action@v4
62
77
  with:
63
78
  name: coverage
64
79
  verbose: true
80
+ env:
81
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -2,6 +2,7 @@
2
2
  .DS_Store
3
3
  *~
4
4
  *.tmp
5
+ temp/
5
6
 
6
7
  # Compiled files
7
8
  __pycache__/
@@ -31,6 +32,9 @@ __pycache__/
31
32
 
32
33
  # other
33
34
  _version.py
34
- .code-workspace
35
- temp/
36
35
  node_modules/
36
+ .code-workspace
37
+
38
+ # test datasets (e.g. Xenium ones)
39
+ data/
40
+ tests/data
@@ -7,7 +7,7 @@ default_stages:
7
7
  minimum_pre_commit_version: 2.16.0
8
8
  repos:
9
9
  - repo: https://github.com/psf/black
10
- rev: 24.3.0
10
+ rev: 24.4.2
11
11
  hooks:
12
12
  - id: black
13
13
  - repo: https://github.com/pre-commit/mirrors-prettier
@@ -15,7 +15,7 @@ repos:
15
15
  hooks:
16
16
  - id: prettier
17
17
  - repo: https://github.com/asottile/blacken-docs
18
- rev: 1.16.0
18
+ rev: 1.18.0
19
19
  hooks:
20
20
  - id: blacken-docs
21
21
  - repo: https://github.com/PyCQA/isort
@@ -23,7 +23,7 @@ repos:
23
23
  hooks:
24
24
  - id: isort
25
25
  - repo: https://github.com/pre-commit/mirrors-mypy
26
- rev: v1.9.0
26
+ rev: v1.10.1
27
27
  hooks:
28
28
  - id: mypy
29
29
  additional_dependencies: [numpy, types-PyYAML]
@@ -40,7 +40,7 @@ repos:
40
40
  - flake8-bugbear
41
41
  - flake8-blind-except
42
42
  - repo: https://github.com/pre-commit/pre-commit-hooks
43
- rev: v4.5.0
43
+ rev: v4.6.0
44
44
  hooks:
45
45
  - id: detect-private-key
46
46
  - id: check-ast
@@ -59,7 +59,7 @@ repos:
59
59
  - --remove-unused-variable
60
60
  - --ignore-init-module-imports
61
61
  - repo: https://github.com/PyCQA/flake8
62
- rev: 7.0.0
62
+ rev: 7.1.0
63
63
  hooks:
64
64
  - id: flake8
65
65
  additional_dependencies:
@@ -70,7 +70,7 @@ repos:
70
70
  - flake8-bugbear
71
71
  - flake8-blind-except
72
72
  - repo: https://github.com/asottile/pyupgrade
73
- rev: v3.15.2
73
+ rev: v3.16.0
74
74
  hooks:
75
75
  - id: pyupgrade
76
76
  args: [--py3-plus, --py39-plus, --keep-runtime-typing]
@@ -8,6 +8,27 @@ and this project adheres to [Semantic Versioning][].
8
8
  [keep a changelog]: https://keepachangelog.com/en/1.0.0/
9
9
  [semantic versioning]: https://semver.org/spec/v2.0.0.html
10
10
 
11
+ ## [0.1.4] - xxxx-xx-xx
12
+
13
+ ## [0.1.3] - 2024-07-03
14
+
15
+ ### Added
16
+
17
+ - (Xenium) support reading multi-polygon selection files from the Xenium Explorer
18
+ - (ISS) An experimental loader to load elemental ISS data objects, e.g. raw.tif, label.tif and anndata.h5ad
19
+ - (Stereo-seq) Added reader @LLehner @timtreis @florianingelfinger #70
20
+ - (MERSCOPE) Optional rioxarray backend for MERSCOPE data (reads chunks)
21
+ - (MERSCOPE) Can choose which elements should be loaded
22
+
23
+ ### Fixed
24
+
25
+ - (Visium) Fixed issue with joining a SpatialElement with a table due to index values not being unique.
26
+ obs_names_make_unique is now called internally to enforce unique index values allowing for join operations.
27
+
28
+ ### Changed
29
+
30
+ - (MERSCOPE) "global" coordinate system is used as a default instead of "microns"
31
+
11
32
  ## [0.1.2] - 2024-03-30
12
33
 
13
34
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: spatialdata-io
3
- Version: 0.1.2
3
+ Version: 0.1.3.post0
4
4
  Summary: SpatialData IO for common techs
5
5
  Project-URL: Documentation, https://spatialdata-io.readthedocs.io/
6
6
  Project-URL: Source, https://github.com/scverse/spatialdata-io
@@ -48,7 +48,7 @@ Requires-Dist: pyarrow
48
48
  Requires-Dist: readfcs
49
49
  Requires-Dist: scanpy
50
50
  Requires-Dist: scikit-image
51
- Requires-Dist: spatialdata
51
+ Requires-Dist: spatialdata>=0.2.1
52
52
  Provides-Extra: dev
53
53
  Requires-Dist: bump2version; extra == 'dev'
54
54
  Requires-Dist: pre-commit; extra == 'dev'
@@ -91,6 +91,7 @@ This package contains reader functions to load common spatial omics formats into
91
91
  - MCMICRO (output data)
92
92
  - NanoString CosMx
93
93
  - Steinbock (output data)
94
+ - STOmics Stereo-seq
94
95
  - Vizgen MERSCOPE (MERFISH)
95
96
 
96
97
  ## Getting started
@@ -21,6 +21,7 @@ This package contains reader functions to load common spatial omics formats into
21
21
  - MCMICRO (output data)
22
22
  - NanoString CosMx
23
23
  - Steinbock (output data)
24
+ - STOmics Stereo-seq
24
25
  - Vizgen MERSCOPE (MERFISH)
25
26
 
26
27
  ## Getting started
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.1.2'
16
- __version_tuple__ = version_tuple = (0, 1, 2)
15
+ __version__ = version = '0.1.3.post0'
16
+ __version_tuple__ = version_tuple = (0, 1, 3)
@@ -20,25 +20,34 @@ I/O for the `spatialdata` project.
20
20
  dbit
21
21
  mcmicro
22
22
  merscope
23
+ seqfish
23
24
  steinbock
25
+ stereoseq
24
26
  visium
25
27
  visium_hd
26
28
  xenium
27
29
  ```
28
30
 
29
- ### Conversion functions
30
-
31
- ### Utility functions
31
+ ### Experimental readers
32
32
 
33
33
  ```{eval-rst}
34
+ .. currentmodule:: spatialdata_io.experimental
35
+
34
36
  .. autosummary::
35
37
  :toctree: generated
36
38
 
37
- xenium_aligned_image
38
- xenium_explorer_selection
39
+ iss
39
40
  ```
40
41
 
41
- ### Experimental readers
42
+ ### Conversion functions
43
+
44
+ ```{eval-rst}
45
+ .. currentmodule:: spatialdata_io
46
+
47
+ .. autosummary::
48
+ :toctree: generated
49
+
50
+ ```
42
51
 
43
52
  ### Experimental conversion functions
44
53
 
@@ -51,3 +60,15 @@ I/O for the `spatialdata` project.
51
60
  from_legacy_anndata
52
61
  to_legacy_anndata
53
62
  ```
63
+
64
+ ### Utility functions
65
+
66
+ ```{eval-rst}
67
+ .. currentmodule:: spatialdata_io
68
+
69
+ .. autosummary::
70
+ :toctree: generated
71
+
72
+ xenium_aligned_image
73
+ xenium_explorer_selection
74
+ ```
@@ -25,7 +25,7 @@ dependencies = [
25
25
  "anndata",
26
26
  "numpy",
27
27
  "scanpy",
28
- "spatialdata",
28
+ "spatialdata>=0.2.1",
29
29
  "scikit-image",
30
30
  "h5py",
31
31
  "joblib",
@@ -6,7 +6,9 @@ from spatialdata_io.readers.curio import curio
6
6
  from spatialdata_io.readers.dbit import dbit
7
7
  from spatialdata_io.readers.mcmicro import mcmicro
8
8
  from spatialdata_io.readers.merscope import merscope
9
+ from spatialdata_io.readers.seqfish import seqfish
9
10
  from spatialdata_io.readers.steinbock import steinbock
11
+ from spatialdata_io.readers.stereoseq import stereoseq
10
12
  from spatialdata_io.readers.visium import visium
11
13
  from spatialdata_io.readers.visium_hd import visium_hd
12
14
  from spatialdata_io.readers.xenium import (
@@ -17,12 +19,14 @@ from spatialdata_io.readers.xenium import (
17
19
 
18
20
  __all__ = [
19
21
  "curio",
22
+ "seqfish",
20
23
  "visium",
21
24
  "xenium",
22
25
  "codex",
23
26
  "cosmx",
24
27
  "mcmicro",
25
28
  "steinbock",
29
+ "stereoseq",
26
30
  "merscope",
27
31
  "xenium_aligned_image",
28
32
  "xenium_explorer_selection",
@@ -59,6 +59,36 @@ class CosmxKeys(ModeEnum):
59
59
  TARGET_OF_TRANSCRIPT = "target"
60
60
 
61
61
 
62
+ @unique
63
+ class SeqfishKeys(ModeEnum):
64
+ """Keys for *Spatial Genomics SeqFISH* formatted dataset."""
65
+
66
+ # file extensions
67
+ CSV_FILE = ".csv"
68
+ TIFF_FILE = ".tiff"
69
+ OME_TIFF_FILE = ".ome.tiff"
70
+ # file identifiers
71
+ SECTION = "section"
72
+ TRANSCRIPT_COORDINATES = "TranscriptCoordinates"
73
+ DAPI = "DAPI"
74
+ COUNTS_FILE = "CxG"
75
+ CELL_MASK_FILE = "CellMask"
76
+ CELL_COORDINATES = "CellCoordinates"
77
+ # transcripts
78
+ TRANSCRIPTS_X = "x"
79
+ TRANSCRIPTS_Y = "y"
80
+ FEATURE_KEY = "name"
81
+ INSTANCE_KEY_POINTS = "cell"
82
+ # cells
83
+ AREA = "area"
84
+ CELL_X = "center_x"
85
+ CELL_Y = "center_y"
86
+ # metadata
87
+ SPATIAL_KEY = "spatial"
88
+ REGION_KEY = "region"
89
+ INSTANCE_KEY_TABLE = "instance_id"
90
+
91
+
62
92
  @unique
63
93
  class XeniumKeys(ModeEnum):
64
94
  """Keys for *10X Genomics Xenium* formatted dataset."""
@@ -121,6 +151,10 @@ class XeniumKeys(ModeEnum):
121
151
  NUCLEUS_COUNT = "nucleus_count"
122
152
  Z_LEVEL = "z_level"
123
153
 
154
+ EXPLORER_SELECTION_X = "X"
155
+ EXPLORER_SELECTION_Y = "Y"
156
+ EXPLORER_SELECTION_KEY = "Selection"
157
+
124
158
 
125
159
  @unique
126
160
  class VisiumKeys(ModeEnum):
@@ -161,6 +195,79 @@ class SteinbockKeys(ModeEnum):
161
195
  LABEL_SUFFIX = ".tiff"
162
196
 
163
197
 
198
+ @unique
199
+ class StereoseqKeys(ModeEnum):
200
+ """Keys for *Stereo-seq* formatted dataset."""
201
+
202
+ # file extensions
203
+ GEF_FILE = ".gef"
204
+ TIF_FILE = ".tif"
205
+ # directories
206
+ MERGE = "01.merge"
207
+ COUNT_DIRECTORY = "02.count"
208
+ REGISTER = "03.register"
209
+ TISSUECUT = "04.tissuecut"
210
+ SPATIALCLUSTER = "05.spatialcluster"
211
+ SATURATION = "06.saturation"
212
+ CELLCUT = "041.cellcut"
213
+ CELLCLUSTER = "051.cellcluster"
214
+ # file identifiers
215
+ MASK_TIF = "_mask.tif"
216
+ REGIST_TIF = "_regist.tif"
217
+ TISSUE_TIF = "_tissue_cut.tif"
218
+ CELL_CLUSTER_H5AD = "cell.cluster.h5ad"
219
+ RAW_GEF = ".raw.gef"
220
+ CELLBIN_GEF = ".cellbin.gef"
221
+ TISSUECUT_GEF = ".tissuecut.gef"
222
+ TISSUE_GEM = ".tissue.gem.gz"
223
+ # transcripts
224
+ FEATURE_KEY = "gene"
225
+ GENE_NAME = "geneName"
226
+ CELL_COUNT = "cellCount"
227
+ MAX_MID_COUNT = "maxMIDcount"
228
+ GENE_EXP = "geneExp"
229
+ EXPRESSION = "expression"
230
+ EXON = "exon"
231
+ GENE_ID = "geneID"
232
+ GENE_EXP_EXON = "geneExpExon"
233
+ # cells
234
+ ID = "id"
235
+ CELL_ID = "cellID"
236
+ GENE_COUNT = "geneCount"
237
+ DNBCOUNT = "dnbCount"
238
+ CELL_AREA = "area"
239
+ CELL_TYPE_ID = "cellTypeID"
240
+ CLUSTER_ID = "clusterID"
241
+ CELL_BIN = "cellBin"
242
+ CELL_EXON = "cellExon"
243
+ CELL_DATASET = "cell"
244
+ GENE_EXON = "geneExon"
245
+ CELL_BORDER = "cellBorder"
246
+ CELL_EXP = "cellExp"
247
+ CELL_EXP_EXON = "cellExpExon"
248
+ PADDING_VALUE = 32767
249
+ # metadata
250
+ COUNT = "count"
251
+ EXP_COUNT = "expCount"
252
+ OFFSET = "offset"
253
+ COORD_X = "x"
254
+ COORD_Y = "y"
255
+ SPATIAL_KEY = "spatial"
256
+ REGION = "cells"
257
+ REGION_KEY = "region"
258
+ INSTANCE_KEY = "instance_id"
259
+ BLOCK_INDEX = "blockIndex"
260
+ BLOCK_SIZE = "blockSize"
261
+ CELL_TYPE_LIST = "cellTypeList"
262
+ # bin data and metadata
263
+ BIN1 = "bin1"
264
+ MIN_X = "minX"
265
+ MIN_Y = "minY"
266
+ MAX_X = "maxX"
267
+ MAX_Y = "maxY"
268
+ RESOLUTION = "resolution"
269
+
270
+
164
271
  @unique
165
272
  class McmicroKeys(ModeEnum):
166
273
  """Keys for *Mcmicro* formatted dataset."""
@@ -238,6 +345,7 @@ class VisiumHDKeys(ModeEnum):
238
345
  DEFAULT_BIN = "square_008um"
239
346
  BIN_PREFIX = "square_"
240
347
  MICROSCOPE_IMAGE = "microscope_image"
348
+ BINNED_OUTPUTS = "binned_outputs"
241
349
 
242
350
  # counts and locations files
243
351
  FILTERED_COUNTS_FILE = "filtered_feature_bc_matrix.h5"
@@ -173,7 +173,7 @@ def to_legacy_anndata(
173
173
  sdata_images = sdata.subset(element_names=list(sdata.images.keys()))
174
174
  for image_name, image in sdata_images.images.items():
175
175
  sdata_pre_rasterize[image_name] = image
176
- bb = get_extent(sdata_images)
176
+ bb = get_extent(sdata_images, coordinate_system=coordinate_system)
177
177
 
178
178
  parameters_dict = {"x": "target_width", "y": "target_height", "z": "target_depth"}
179
179
  longest_side = max(bb, key=bb.get)
@@ -2,5 +2,6 @@ from spatialdata_io.converters.legacy_anndata import (
2
2
  from_legacy_anndata,
3
3
  to_legacy_anndata,
4
4
  )
5
+ from spatialdata_io.readers.iss import iss
5
6
 
6
- __all__ = ["from_legacy_anndata", "to_legacy_anndata"]
7
+ __all__ = ["from_legacy_anndata", "to_legacy_anndata", "iss"]
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import os
4
+ from collections.abc import Mapping
4
5
  from pathlib import Path
5
6
  from typing import Any, Optional, Union
6
7
 
@@ -66,3 +67,20 @@ def _read_counts(
66
67
 
67
68
  adata.uns["spatial"] = {library_id: {"metadata": {}}} # can overwrite
68
69
  return adata, library_id
70
+
71
+
72
+ def _initialize_raster_models_kwargs(
73
+ image_models_kwargs: Mapping[str, Any], labels_models_kwargs: Mapping[str, Any]
74
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
75
+ image_models_kwargs = dict(image_models_kwargs)
76
+ if "chunks" not in image_models_kwargs:
77
+ image_models_kwargs["chunks"] = (1, 4096, 4096)
78
+ if "scale_factors" not in image_models_kwargs:
79
+ image_models_kwargs["scale_factors"] = [2, 2, 2, 2]
80
+
81
+ labels_models_kwargs = dict(labels_models_kwargs)
82
+ if "chunks" not in labels_models_kwargs:
83
+ labels_models_kwargs["chunks"] = (4096, 4096)
84
+ if "scale_factors" not in labels_models_kwargs:
85
+ labels_models_kwargs["scale_factors"] = [2, 2, 2, 2]
86
+ return image_models_kwargs, labels_models_kwargs
@@ -12,7 +12,7 @@ import numpy as np
12
12
  import pandas as pd
13
13
  import pyarrow as pa
14
14
  from anndata import AnnData
15
- from dask.dataframe.core import DataFrame as DaskDataFrame
15
+ from dask.dataframe import DataFrame as DaskDataFrame
16
16
  from dask_image.imread import imread
17
17
  from scipy.sparse import csr_matrix
18
18
 
@@ -37,48 +37,77 @@ def _check_path(
37
37
  ----------
38
38
  path
39
39
  The path of the main directory where to search for the path.
40
- path_specific
41
- path to the file, if it is not in the main directory.
42
40
  pattern
43
41
  regex pattern.
44
42
  key
45
43
  String to match in the path or path_specific path.
44
+ path_specific
45
+ path to the file, if it is not in the main directory.
46
+ If it is given and valid, this is used and 'path' is neglected.
46
47
  optional_arg
47
- User specify if the file to search is mandatory (optional_arg=True, raise an Error if not found)
48
- or optional (optional_arg=False, raise a Warning if not found).
48
+ User specify if the file to search is:
49
+ mandatory: (optional_arg=False, raise an Error if not found)
50
+ optional: (optional_arg=True, raise a Warning if not found).
49
51
 
50
52
  Raises
51
53
  ------
52
54
  FileNotFoundError
53
- The error is raised if no match is found in the given paths and optional_arg=True.
55
+ Raised if no match is found in the given paths and optional_arg=False.
56
+ Exception
57
+ Raised if there are multiple file mathing a pattern.
58
+ IndexError
59
+ Raised if no matching file is found.
54
60
 
55
61
  Returns
56
62
  -------
57
- tuple(pathlib.PosixPath, bool)
58
- return a tuple(pathlib.PosixPath, bool). The bool is a flag that indicate if one of the supplied path arguments points to a file that match the supplied key.
63
+ (tuple[Union[Path, None], bool])
64
+ return the file path if valid, or None if not valid, and a bool.
65
+ The bool is a flag that indicates if one of the supplied path arguments
66
+ points to a file that matches the supplied key.
67
+
59
68
  """
60
69
  flag = False
61
70
  file_path = None
62
- try:
63
- checked_file = [i for i in os.listdir(path) if pattern.match(i)][0] # this is the filename
64
- file_path = Path.joinpath(path, checked_file)
65
- flag = True
66
- except IndexError:
67
- # handle case in which the searched file is not in the same directory as path
68
- if path_specific is not None:
69
- if os.path.isfile(path_specific):
70
- file_path = Path(path_specific)
71
- flag = True
72
- else:
73
- if optional_arg:
74
- logger.warning(f"{path_specific} is not a valid path for {key}. No {key} will be used.")
75
- else:
76
- raise FileNotFoundError(f"{path_specific} is not a valid path for a {key} file.")
71
+ # check if a specific file path is given and is valid.
72
+ # If yes, it is used. Has priority with respect to the 'path' argument.
73
+ if path_specific is not None:
74
+ if os.path.isfile(path_specific):
75
+ file_path = Path(path_specific)
76
+ flag = True
77
77
  else:
78
+ # if path_specific is not valid but optional, give warning
78
79
  if optional_arg:
79
- logger.warning(f"No file containing {key} found in folder {path}. No {key} will be used.")
80
+ logger.warning(f"{path_specific} is not a valid path for {key}. No {key} will be used.")
81
+ # if path_specific is not valid but mandatory, raise error
80
82
  else:
81
- raise FileNotFoundError(f"No file containing {key} found in folder {path}.")
83
+ raise FileNotFoundError(f"{path_specific} is not a valid path for a {key} file.")
84
+
85
+ else:
86
+ # search for the pattern matching file in path
87
+ matches = [i for i in os.listdir(path) if pattern.match(i)]
88
+ if len(matches) > 1:
89
+ message = f"There are {len(matches)} file matching {key} in {Path(path)}. Specify the correct file path to avoid ambiguities."
90
+ if optional_arg:
91
+ logger.warning(message)
92
+ return file_path, flag
93
+ else:
94
+ raise Exception(message)
95
+ else:
96
+ # if there is a matching file, use it
97
+ try:
98
+ checked_file = matches[0] # this is the filename
99
+ file_path = Path.joinpath(path, checked_file)
100
+ flag = True
101
+ # if there are no files matching the pattern, raise error
102
+ except IndexError:
103
+ message = f"There are no files in {path} matching {key}."
104
+ if optional_arg:
105
+ logger.warning(message)
106
+ return file_path, flag
107
+ else:
108
+ raise IndexError(message)
109
+
110
+ logger.warning(f"{file_path} is used.")
82
111
  return file_path, flag
83
112
 
84
113
 
@@ -189,7 +218,7 @@ def _xy2edges(xy: list[int], scale: float = 1.0, border: bool = True, border_sca
189
218
 
190
219
  @inject_docs(vx=DbitKeys)
191
220
  def dbit(
192
- path: str | Path,
221
+ path: Optional[str | Path] = None,
193
222
  anndata_path: Optional[str] = None,
194
223
  barcode_position: Optional[str] = None,
195
224
  image_path: Optional[str] = None,
@@ -236,12 +265,14 @@ def dbit(
236
265
  -------
237
266
  :class:`spatialdata.SpatialData`.
238
267
  """
239
- path = Path(path)
240
- # if path is invalid, raise error
241
- if not os.path.isdir(path):
242
- raise FileNotFoundError(
243
- f"The path you have passed: {path} has not been found. A correct path to the data directory is needed."
244
- )
268
+ if path is not None:
269
+ path = Path(path)
270
+ # if path is invalid, raise error
271
+ if not os.path.isdir(path):
272
+ raise FileNotFoundError(
273
+ f"The path you have passed: {path} has not been found. A correct path to the data directory is needed."
274
+ )
275
+
245
276
  # compile regex pattern to find file name in path, according to _constants.DbitKeys()
246
277
  patt_h5ad = re.compile(f".*{DbitKeys.COUNTS_FILE}")
247
278
  patt_barcode = re.compile(f".*{DbitKeys.BARCODE_POSITION}.*")
@@ -249,13 +280,13 @@ def dbit(
249
280
 
250
281
  # search for files paths. Gives priority to files matching the pattern found in path.
251
282
  anndata_path_checked = _check_path(
252
- path=path, path_specific=anndata_path, pattern=patt_h5ad, key=DbitKeys.COUNTS_FILE
283
+ path=path, path_specific=anndata_path, pattern=patt_h5ad, key=DbitKeys.COUNTS_FILE # type: ignore
253
284
  )[0]
254
285
  barcode_position_checked = _check_path(
255
- path=path, path_specific=barcode_position, pattern=patt_barcode, key=DbitKeys.BARCODE_POSITION
286
+ path=path, path_specific=barcode_position, pattern=patt_barcode, key=DbitKeys.BARCODE_POSITION # type: ignore
256
287
  )[0]
257
288
  image_path_checked, hasimage = _check_path(
258
- path=path,
289
+ path=path, # type: ignore
259
290
  path_specific=image_path,
260
291
  pattern=patt_lowres,
261
292
  key=DbitKeys.IMAGE_LOWRES_FILE,
@@ -324,7 +355,7 @@ def dbit(
324
355
  ra = shapely.to_ragged_array([shapely.Polygon(x) for x in f])
325
356
  grid = sd.models.ShapesModel.parse(ra[1], geometry=ra[0], offsets=ra[2], index=adata.obs["pixel_id"].copy())
326
357
  # create SpatialData object!
327
- sdata = sd.SpatialData(table=table_data, shapes={dataset_id: grid})
358
+ sdata = sd.SpatialData(tables={"table": table_data}, shapes={dataset_id: grid})
328
359
  if hasimage:
329
360
  imgname = dataset_id + "_image"
330
361
  sdata.images[imgname] = image_sd