spatialdata 0.7.3a1__tar.gz → 0.7.3a2__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.
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.github/workflows/test.yaml +7 -7
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.pre-commit-config.yaml +3 -3
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/PKG-INFO +2 -2
- spatialdata-0.7.3a2/_version.py +24 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/pyproject.toml +3 -1
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/_elements.py +3 -22
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/centroids.py +22 -37
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/io_points.py +1 -1
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/io_raster.py +12 -2
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/io_shapes.py +1 -1
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/io_table.py +1 -1
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/datasets.py +4 -1
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/models/models.py +7 -3
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/conftest.py +95 -22
- spatialdata-0.7.3a2/tests/core/operations/conftest.py +1 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/test_spatialdata_operations.py +14 -13
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/test_transform.py +1 -1
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/test_vectorize.py +25 -22
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/query/test_relational_query.py +2 -2
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/query/test_relational_query_match_sdata_to_table.py +9 -8
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/test_data_extent.py +13 -9
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/test_get_attrs.py +5 -9
- spatialdata-0.7.3a2/tests/dataloader/conftest.py +1 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_attrs_io.py +2 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_format.py +2 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_metadata.py +5 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_partial_read.py +47 -25
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_pyramids_performance.py +22 -1
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_readwrite.py +43 -15
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/models/test_models.py +6 -5
- spatialdata-0.7.3a1/_version.py +0 -34
- spatialdata-0.7.3a1/docs/_templates/.gitkeep +0 -0
- spatialdata-0.7.3a1/docs/_templates/autosummary/base.rst +0 -5
- spatialdata-0.7.3a1/docs/_templates/autosummary/class.rst +0 -61
- spatialdata-0.7.3a1/docs/_templates/autosummary/function.rst +0 -5
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.bumpversion.cfg +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.editorconfig +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.github/codecov.yml +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.github/release.yml +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.github/workflows/build_image.yml +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.github/workflows/release.yaml +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.gitignore +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.gitmodules +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.mypy.ini +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/.readthedocs.yaml +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/CHANGELOG.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/Dockerfile +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/LICENSE +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/README.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/asv.conf.json +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/benchmarks/README.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/benchmarks/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/benchmarks/benchmark_imports.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/benchmarks/spatialdata_benchmark.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/benchmarks/utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/Makefile +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/_static/.gitkeep +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/_static/css/custom.css +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/_static/img/spatialdata_horizontal.png +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/SpatialData.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/data_formats.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/dataloader.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/datasets.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/io.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/models.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/models_utils.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/operations.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/testing.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/transformations.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api/transformations_utils.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/api.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/changelog.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/conf.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/contributing.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/design_doc.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/extensions/typed_returns.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/glossary.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/index.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/installation.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/references.bib +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/references.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/docs/user_guide.md +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/__main__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_bridges/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/_deepcopy.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/concatenate.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/data_extent.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/aggregate.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/map.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/rasterize.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/rasterize_bins.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/transform.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/operations/vectorize.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/query/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/query/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/query/relational_query.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/query/spatial_query.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/spatialdata.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_core/validation.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_docs.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/format.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_io/io_zarr.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_logging.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_types.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/config.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/dataloader/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/dataloader/datasets.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/io/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/models/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/models/_accessor.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/models/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/models/chunks_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/models/pyramids_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/testing.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/ngff/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/ngff/_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/ngff/ngff_coordinate_system.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/ngff/ngff_transformations.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/operations.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/src/spatialdata/transformations/transformations.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/test_aggregations.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/test_map.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/test_rasterize.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/operations/test_rasterize_bins.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/query/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/query/test_spatial_query.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/test_centroids.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/test_deepcopy.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/core/test_validation.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/data/multipolygon.json +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/data/points.json +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/data/polygon.json +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/dataloader/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/dataloader/test_datasets.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/datasets/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/datasets/test_datasets.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_multi_table.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/io/test_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/models/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/models/test_accessor.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/models/test_chunks_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/models/test_pyramids_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/test_init.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/transformations/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/transformations/ngff/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/transformations/ngff/conftest.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/transformations/ngff/test_ngff_coordinate_system.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/transformations/ngff/test_ngff_transformations.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/transformations/test_transformations.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/transformations/test_transformations_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/utils/__init__.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/utils/test_element_utils.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/utils/test_sanitize.py +0 -0
- {spatialdata-0.7.3a1 → spatialdata-0.7.3a2}/tests/utils/test_testing.py +0 -0
|
@@ -19,12 +19,12 @@ jobs:
|
|
|
19
19
|
fail-fast: false
|
|
20
20
|
matrix:
|
|
21
21
|
include:
|
|
22
|
-
- {os: windows-latest, python: "3.11", dask-version: "2025.12.0", name: "
|
|
23
|
-
- {os: windows-latest, python: "3.
|
|
24
|
-
- {os: ubuntu-latest, python: "3.11", dask-version: "latest"
|
|
25
|
-
- {os: ubuntu-latest, python: "3.
|
|
26
|
-
- {os: macos-latest, python: "3.11", dask-version: "latest"
|
|
27
|
-
- {os: macos-latest, python: "3.
|
|
22
|
+
- {os: windows-latest, python: "3.11", dask-version: "2025.12.0", name: "min dask"}
|
|
23
|
+
- {os: windows-latest, python: "3.14", dask-version: "latest"}
|
|
24
|
+
- {os: ubuntu-latest, python: "3.11", dask-version: "latest"}
|
|
25
|
+
- {os: ubuntu-latest, python: "3.14", dask-version: "latest"}
|
|
26
|
+
- {os: macos-latest, python: "3.11", dask-version: "latest"}
|
|
27
|
+
- {os: macos-latest, python: "3.14", prerelease: "allow", name: "prerelease"}
|
|
28
28
|
env:
|
|
29
29
|
OS: ${{ matrix.os }}
|
|
30
30
|
PYTHON: ${{ matrix.python }}
|
|
@@ -59,7 +59,7 @@ jobs:
|
|
|
59
59
|
PLATFORM: ${{ matrix.os }}
|
|
60
60
|
DISPLAY: :42
|
|
61
61
|
run: |
|
|
62
|
-
uv run pytest --cov --color=yes --cov-report=xml
|
|
62
|
+
uv run pytest --cov --color=yes --cov-report=xml -n auto --dist worksteal
|
|
63
63
|
- name: Upload coverage to Codecov
|
|
64
64
|
uses: codecov/codecov-action@v5
|
|
65
65
|
with:
|
|
@@ -9,18 +9,18 @@ ci:
|
|
|
9
9
|
skip: []
|
|
10
10
|
repos:
|
|
11
11
|
- repo: https://github.com/rbubley/mirrors-prettier
|
|
12
|
-
rev: v3.8.
|
|
12
|
+
rev: v3.8.3
|
|
13
13
|
hooks:
|
|
14
14
|
- id: prettier
|
|
15
15
|
exclude: ^.github/workflows/test.yaml
|
|
16
16
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
17
|
-
rev: v1.
|
|
17
|
+
rev: v1.20.2
|
|
18
18
|
hooks:
|
|
19
19
|
- id: mypy
|
|
20
20
|
additional_dependencies: [numpy, types-requests]
|
|
21
21
|
exclude: tests/|docs/
|
|
22
22
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
23
|
-
rev: v0.15.
|
|
23
|
+
rev: v0.15.12
|
|
24
24
|
hooks:
|
|
25
25
|
- id: ruff
|
|
26
26
|
args: [--fix, --exit-non-zero-on-fix]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatialdata
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3a2
|
|
4
4
|
Summary: Spatial data format.
|
|
5
5
|
Project-URL: Documentation, https://spatialdata.scverse.org/en/latest
|
|
6
6
|
Project-URL: Source, https://github.com/scverse/spatialdata.git
|
|
@@ -38,7 +38,7 @@ License: BSD 3-Clause License
|
|
|
38
38
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
39
39
|
License-File: LICENSE
|
|
40
40
|
Requires-Python: >=3.11
|
|
41
|
-
Requires-Dist: anndata>=0.
|
|
41
|
+
Requires-Dist: anndata>=0.9.1
|
|
42
42
|
Requires-Dist: annsel>=0.1.2
|
|
43
43
|
Requires-Dist: click
|
|
44
44
|
Requires-Dist: dask-image
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.7.3a2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 7, 3, 'a2')
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|
|
@@ -22,7 +22,7 @@ dynamic= [
|
|
|
22
22
|
license = {file = "LICENSE"}
|
|
23
23
|
readme = "README.md"
|
|
24
24
|
dependencies = [
|
|
25
|
-
"anndata>=0.
|
|
25
|
+
"anndata>=0.9.1",
|
|
26
26
|
"annsel>=0.1.2",
|
|
27
27
|
"click",
|
|
28
28
|
"dask-image",
|
|
@@ -69,6 +69,7 @@ test = [
|
|
|
69
69
|
"pytest",
|
|
70
70
|
"pytest-cov",
|
|
71
71
|
"pytest-mock",
|
|
72
|
+
"pytest-xdist",
|
|
72
73
|
"torch",
|
|
73
74
|
]
|
|
74
75
|
docs = [
|
|
@@ -102,6 +103,7 @@ strict = true
|
|
|
102
103
|
addopts = [
|
|
103
104
|
"--import-mode=importlib", # allow using test files with same name
|
|
104
105
|
"-s", # print output from tests
|
|
106
|
+
"-p no:napari", # napari registers a pytest plugin via its entry point; disable it here since spatialdata tests don't need it
|
|
105
107
|
]
|
|
106
108
|
# These are all markers coming from xarray, dask or anndata. Added here to silence warnings.
|
|
107
109
|
markers = [
|
|
@@ -21,7 +21,6 @@ from spatialdata.models import (
|
|
|
21
21
|
PointsModel,
|
|
22
22
|
ShapesModel,
|
|
23
23
|
TableModel,
|
|
24
|
-
get_axes_names,
|
|
25
24
|
get_model,
|
|
26
25
|
)
|
|
27
26
|
|
|
@@ -50,6 +49,7 @@ class Elements(UserDict[str, T]):
|
|
|
50
49
|
raise KeyError(*e.args) from e
|
|
51
50
|
|
|
52
51
|
def __setitem__(self, key: str, value: T) -> None:
|
|
52
|
+
# note that each __setitem__ in the subclasses calls get_model(), which performs data validation
|
|
53
53
|
self._add_shared_key(key)
|
|
54
54
|
super().__setitem__(key, value)
|
|
55
55
|
|
|
@@ -72,15 +72,7 @@ class Images(Elements[DataArray | DataTree]):
|
|
|
72
72
|
schema = get_model(value)
|
|
73
73
|
if schema not in (Image2DModel, Image3DModel):
|
|
74
74
|
raise TypeError(f"Unknown element type with schema: {schema!r}.")
|
|
75
|
-
|
|
76
|
-
if ndim == 3:
|
|
77
|
-
Image2DModel.validate(value)
|
|
78
|
-
super().__setitem__(key, value)
|
|
79
|
-
elif ndim == 4:
|
|
80
|
-
Image3DModel.validate(value)
|
|
81
|
-
super().__setitem__(key, value)
|
|
82
|
-
else:
|
|
83
|
-
NotImplementedError("TODO: implement for ndim > 4.")
|
|
75
|
+
super().__setitem__(key, value)
|
|
84
76
|
|
|
85
77
|
|
|
86
78
|
class Labels(Elements[DataArray | DataTree]):
|
|
@@ -89,15 +81,7 @@ class Labels(Elements[DataArray | DataTree]):
|
|
|
89
81
|
schema = get_model(value)
|
|
90
82
|
if schema not in (Labels2DModel, Labels3DModel):
|
|
91
83
|
raise TypeError(f"Unknown element type with schema: {schema!r}.")
|
|
92
|
-
|
|
93
|
-
if ndim == 2:
|
|
94
|
-
Labels2DModel.validate(value)
|
|
95
|
-
super().__setitem__(key, value)
|
|
96
|
-
elif ndim == 3:
|
|
97
|
-
Labels3DModel.validate(value)
|
|
98
|
-
super().__setitem__(key, value)
|
|
99
|
-
else:
|
|
100
|
-
NotImplementedError("TODO: implement for ndim > 3.")
|
|
84
|
+
super().__setitem__(key, value)
|
|
101
85
|
|
|
102
86
|
|
|
103
87
|
class Shapes(Elements[GeoDataFrame]):
|
|
@@ -106,7 +90,6 @@ class Shapes(Elements[GeoDataFrame]):
|
|
|
106
90
|
schema = get_model(value)
|
|
107
91
|
if schema != ShapesModel:
|
|
108
92
|
raise TypeError(f"Unknown element type with schema: {schema!r}.")
|
|
109
|
-
ShapesModel.validate(value)
|
|
110
93
|
super().__setitem__(key, value)
|
|
111
94
|
|
|
112
95
|
|
|
@@ -116,7 +99,6 @@ class Points(Elements[DaskDataFrame]):
|
|
|
116
99
|
schema = get_model(value)
|
|
117
100
|
if schema != PointsModel:
|
|
118
101
|
raise TypeError(f"Unknown element type with schema: {schema!r}.")
|
|
119
|
-
PointsModel.validate(value)
|
|
120
102
|
super().__setitem__(key, value)
|
|
121
103
|
|
|
122
104
|
|
|
@@ -126,5 +108,4 @@ class Tables(Elements[AnnData]):
|
|
|
126
108
|
schema = get_model(value)
|
|
127
109
|
if schema != TableModel:
|
|
128
110
|
raise TypeError(f"Unknown element type with schema: {schema!r}.")
|
|
129
|
-
TableModel.validate(value)
|
|
130
111
|
super().__setitem__(key, value)
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from collections import defaultdict
|
|
4
3
|
from functools import singledispatch
|
|
5
4
|
|
|
6
|
-
import
|
|
5
|
+
import numpy as np
|
|
7
6
|
import pandas as pd
|
|
8
7
|
import xarray as xr
|
|
9
8
|
from dask.dataframe import DataFrame as DaskDataFrame
|
|
@@ -56,40 +55,29 @@ def get_centroids(
|
|
|
56
55
|
raise ValueError(f"The object type {type(e)} is not supported.")
|
|
57
56
|
|
|
58
57
|
|
|
59
|
-
def
|
|
58
|
+
def _get_centroids_for_labels(xdata: xr.DataArray) -> pd.DataFrame:
|
|
60
59
|
"""
|
|
61
|
-
Compute
|
|
60
|
+
Compute centroids for all labels in a DataArray in a single O(n_voxels) pass.
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
----------
|
|
65
|
-
xdata
|
|
66
|
-
The xarray DataArray containing the labels.
|
|
67
|
-
axis
|
|
68
|
-
The axis for which the centroids are computed.
|
|
69
|
-
|
|
70
|
-
Returns
|
|
71
|
-
-------
|
|
72
|
-
pd.DataFrame
|
|
73
|
-
A DataFrame containing one column, named after "axis", with the centroids of the labels along that axis.
|
|
74
|
-
The index of the DataFrame is the collection of label values, sorted in ascending order.
|
|
62
|
+
Works for any number of spatial dimensions (2D and 3D labels).
|
|
75
63
|
"""
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return pd.DataFrame(
|
|
64
|
+
arr = xdata.data.compute()
|
|
65
|
+
axes = list(xdata.dims)
|
|
66
|
+
|
|
67
|
+
# Map label values to a contiguous range for bincount efficiency.
|
|
68
|
+
label_ids, inverse = np.unique(arr, return_inverse=True)
|
|
69
|
+
flat_inverse = inverse.ravel()
|
|
70
|
+
counts = np.bincount(flat_inverse) # per-label pixel counts
|
|
71
|
+
|
|
72
|
+
# indexing="ij" (matrix convention) ensures the i-th grid varies along the i-th
|
|
73
|
+
# dimension of the output, correctly aligning with xdata.dims for any number of axes.
|
|
74
|
+
coord_grids = np.meshgrid(*[xdata[ax].values for ax in axes], indexing="ij")
|
|
75
|
+
data: dict[str, np.ndarray] = {}
|
|
76
|
+
for ax, grid in zip(axes, coord_grids, strict=True):
|
|
77
|
+
coord_sums = np.bincount(flat_inverse, weights=grid.ravel().astype(float))
|
|
78
|
+
data[ax] = coord_sums / counts # counts > 0 by construction (unique guarantees this)
|
|
79
|
+
|
|
80
|
+
return pd.DataFrame(data, index=label_ids)
|
|
93
81
|
|
|
94
82
|
|
|
95
83
|
@get_centroids.register(DataArray)
|
|
@@ -109,10 +97,7 @@ def _(
|
|
|
109
97
|
assert len(e["scale0"]) == 1
|
|
110
98
|
e = next(iter(e["scale0"].values()))
|
|
111
99
|
|
|
112
|
-
|
|
113
|
-
for axis in get_axes_names(e):
|
|
114
|
-
dfs.append(_get_centroids_for_axis(e, axis))
|
|
115
|
-
df = pd.concat(dfs, axis=1)
|
|
100
|
+
df = _get_centroids_for_labels(e)
|
|
116
101
|
if not return_background and 0 in df.index:
|
|
117
102
|
df = df.drop(index=0) # drop the background label
|
|
118
103
|
t = get_transformation(e, coordinate_system)
|
|
@@ -24,7 +24,7 @@ def _read_points(
|
|
|
24
24
|
store: str | Path,
|
|
25
25
|
) -> DaskDataFrame:
|
|
26
26
|
"""Read points from a zarr store."""
|
|
27
|
-
f = zarr.open(store, mode="r")
|
|
27
|
+
f = zarr.open(Path(store), mode="r") # Path avoids zarr v3 URL-parsing special chars (e.g. #) in names
|
|
28
28
|
|
|
29
29
|
version = _parse_version(f, expect_attrs_key=True)
|
|
30
30
|
assert version is not None
|
|
@@ -316,7 +316,7 @@ def _write_raster(
|
|
|
316
316
|
**metadata,
|
|
317
317
|
)
|
|
318
318
|
elif isinstance(raster_data, DataTree):
|
|
319
|
-
_write_raster_datatree(
|
|
319
|
+
group = _write_raster_datatree(
|
|
320
320
|
raster_type,
|
|
321
321
|
group,
|
|
322
322
|
name,
|
|
@@ -409,7 +409,7 @@ def _write_raster_datatree(
|
|
|
409
409
|
raster_format: RasterFormatType,
|
|
410
410
|
storage_options: JSONDict | list[JSONDict] | None = None,
|
|
411
411
|
**metadata: str | JSONDict | list[JSONDict],
|
|
412
|
-
) ->
|
|
412
|
+
) -> zarr.Group:
|
|
413
413
|
"""Write raster data of type DataTree to disk.
|
|
414
414
|
|
|
415
415
|
Parameters
|
|
@@ -460,6 +460,15 @@ def _write_raster_datatree(
|
|
|
460
460
|
# os.replace is called. These can also be alleviated by using 'single-threaded' scheduler.
|
|
461
461
|
da.compute(*dask_delayed, optimize_graph=False)
|
|
462
462
|
|
|
463
|
+
# Workaround for https://github.com/scverse/spatialdata/issues/1024.
|
|
464
|
+
# ome-zarr-py bundles write_multiscales_metadata() as a dask.delayed task in the compute=False
|
|
465
|
+
# code path (see https://github.com/ome/ome-zarr-py/issues/580). When da.compute() runs with
|
|
466
|
+
# the 'processes' scheduler that task executes in a subprocess: the on-disk zarr.json is written
|
|
467
|
+
# correctly, but the zarr.Group held in this process keeps its original in-memory GroupMetadata
|
|
468
|
+
# and never sees the update. Re-opening the group forces a fresh read from the store.
|
|
469
|
+
# This workaround should not be needed once https://github.com/ome/ome-zarr-py/issues/580 is fixed.
|
|
470
|
+
group = zarr.open_group(store=group.store, path=group.path, mode="r+", use_consolidated=False)
|
|
471
|
+
|
|
463
472
|
trans_group = group["labels"][element_name] if raster_type == "labels" else group
|
|
464
473
|
overwrite_coordinate_transformations_raster(
|
|
465
474
|
group=trans_group,
|
|
@@ -467,6 +476,7 @@ def _write_raster_datatree(
|
|
|
467
476
|
axes=tuple(input_axes),
|
|
468
477
|
raster_format=raster_format,
|
|
469
478
|
)
|
|
479
|
+
return group
|
|
470
480
|
|
|
471
481
|
|
|
472
482
|
def write_image(
|
|
@@ -34,7 +34,7 @@ def _read_shapes(
|
|
|
34
34
|
store: str | Path,
|
|
35
35
|
) -> GeoDataFrame:
|
|
36
36
|
"""Read shapes from a zarr store."""
|
|
37
|
-
f = zarr.open(store, mode="r")
|
|
37
|
+
f = zarr.open(Path(store), mode="r") # Path avoids zarr v3 URL-parsing special chars (e.g. #) in names
|
|
38
38
|
version = _parse_version(f, expect_attrs_key=True)
|
|
39
39
|
assert version is not None
|
|
40
40
|
shape_format = ShapesFormats[version]
|
|
@@ -22,7 +22,7 @@ from spatialdata.models import TableModel, get_table_keys
|
|
|
22
22
|
def _read_table(store: str | Path) -> AnnData:
|
|
23
23
|
table = read_anndata_zarr(str(store))
|
|
24
24
|
|
|
25
|
-
f = zarr.open(store, mode="r")
|
|
25
|
+
f = zarr.open(Path(store), mode="r") # Path avoids zarr v3 URL-parsing special chars (e.g. #) in names
|
|
26
26
|
version = _parse_version(f, expect_attrs_key=False)
|
|
27
27
|
assert version is not None
|
|
28
28
|
table_format = TablesFormats[version]
|
|
@@ -397,7 +397,10 @@ def blobs_annotating_element(name: BlobsTypes) -> SpatialData:
|
|
|
397
397
|
index = sdata[name].index
|
|
398
398
|
instance_id = index.compute().tolist() if isinstance(index, dask.dataframe.Index) else index.tolist()
|
|
399
399
|
n = len(instance_id)
|
|
400
|
-
|
|
400
|
+
obs_df = pd.DataFrame(
|
|
401
|
+
{"region": pd.Categorical([name] * n), "instance_id": instance_id}, index=[str(i) for i in range(n)]
|
|
402
|
+
)
|
|
403
|
+
new_table = AnnData(shape=(n, 0), obs=obs_df)
|
|
401
404
|
new_table = TableModel.parse(new_table, region=name, region_key="region", instance_key="instance_id")
|
|
402
405
|
del sdata.tables["table"]
|
|
403
406
|
sdata["table"] = new_table
|
|
@@ -266,7 +266,7 @@ class RasterSchema:
|
|
|
266
266
|
# Chunk single scale images
|
|
267
267
|
if chunks is not None:
|
|
268
268
|
if isinstance(chunks, tuple):
|
|
269
|
-
chunks =
|
|
269
|
+
chunks = dict(zip(data.dims, chunks, strict=True))
|
|
270
270
|
data = data.chunk(chunks=chunks)
|
|
271
271
|
# recompute coordinates for (multiscale) spatial image
|
|
272
272
|
data = compute_coordinates(data)
|
|
@@ -1250,14 +1250,17 @@ Schema_t: TypeAlias = (
|
|
|
1250
1250
|
|
|
1251
1251
|
def get_model(
|
|
1252
1252
|
e: SpatialElement,
|
|
1253
|
+
validate: bool = True,
|
|
1253
1254
|
) -> Schema_t:
|
|
1254
1255
|
"""
|
|
1255
|
-
Get the model for the given element.
|
|
1256
|
+
Get the model for the given element. Validate using the model if `validate` is `True`.
|
|
1256
1257
|
|
|
1257
1258
|
Parameters
|
|
1258
1259
|
----------
|
|
1259
1260
|
e
|
|
1260
1261
|
The element.
|
|
1262
|
+
validate
|
|
1263
|
+
Whether to validate the element using the model.
|
|
1261
1264
|
|
|
1262
1265
|
Returns
|
|
1263
1266
|
-------
|
|
@@ -1268,7 +1271,8 @@ def get_model(
|
|
|
1268
1271
|
schema: Schema_t,
|
|
1269
1272
|
e: SpatialElement,
|
|
1270
1273
|
) -> Schema_t:
|
|
1271
|
-
|
|
1274
|
+
if validate:
|
|
1275
|
+
schema.validate(e)
|
|
1272
1276
|
return schema
|
|
1273
1277
|
|
|
1274
1278
|
if isinstance(e, DataArray | DataTree):
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
# Disable numba JIT for the test suite (the test data is small so initializing the JIT is slower than using plain
|
|
7
|
+
# Python). Force-set (not setdefault) so the runner environment cannot accidentally override with "0".
|
|
8
|
+
os.environ["NUMBA_DISABLE_JIT"] = "1"
|
|
9
|
+
# If a pytest plugin already imported numba before this conftest ran, patch the cached config value too.
|
|
10
|
+
if "numba.core.config" in sys.modules:
|
|
11
|
+
sys.modules["numba.core.config"].NUMBA_DISABLE_JIT = 1
|
|
12
|
+
|
|
13
|
+
import copy as _copy
|
|
14
|
+
from collections.abc import Callable, Sequence
|
|
4
15
|
from pathlib import Path
|
|
5
16
|
from typing import Any
|
|
6
17
|
|
|
@@ -33,6 +44,25 @@ from spatialdata.models import (
|
|
|
33
44
|
TableModel,
|
|
34
45
|
)
|
|
35
46
|
|
|
47
|
+
|
|
48
|
+
def _fast_deepcopy_sdata(sd: SpatialData) -> SpatialData:
|
|
49
|
+
"""
|
|
50
|
+
Fast deepcopy for SpatialData objects in tests.
|
|
51
|
+
|
|
52
|
+
Uses copy.deepcopy (which skips model re-validation) and manually restores
|
|
53
|
+
the attrs that copy.deepcopy loses for DaskDataFrame (issue #503) and
|
|
54
|
+
GeoDataFrame (issue #286).
|
|
55
|
+
"""
|
|
56
|
+
points_attrs = {k: _copy.deepcopy(v._attrs) for k, v in sd.points.items()}
|
|
57
|
+
shapes_attrs = {k: _copy.deepcopy(v.attrs) for k, v in sd.shapes.items()}
|
|
58
|
+
sd_copy = _copy.deepcopy(sd)
|
|
59
|
+
for k, attrs in points_attrs.items():
|
|
60
|
+
sd_copy.points[k]._attrs = attrs
|
|
61
|
+
for k, attrs in shapes_attrs.items():
|
|
62
|
+
sd_copy.shapes[k].attrs = attrs
|
|
63
|
+
return sd_copy
|
|
64
|
+
|
|
65
|
+
|
|
36
66
|
SEED = 0
|
|
37
67
|
RNG = default_rng(seed=SEED)
|
|
38
68
|
|
|
@@ -41,16 +71,26 @@ MULTIPOLYGON_PATH = Path(__file__).parent / "data/polygon.json"
|
|
|
41
71
|
POINT_PATH = Path(__file__).parent / "data/points.json"
|
|
42
72
|
|
|
43
73
|
|
|
44
|
-
@pytest.fixture()
|
|
45
|
-
def
|
|
74
|
+
@pytest.fixture(scope="session")
|
|
75
|
+
def _images_session() -> SpatialData:
|
|
46
76
|
return SpatialData(images=_get_images())
|
|
47
77
|
|
|
48
78
|
|
|
49
79
|
@pytest.fixture()
|
|
50
|
-
def
|
|
80
|
+
def images(_images_session: SpatialData) -> SpatialData:
|
|
81
|
+
return _fast_deepcopy_sdata(_images_session)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@pytest.fixture(scope="session")
|
|
85
|
+
def _labels_session() -> SpatialData:
|
|
51
86
|
return SpatialData(labels=_get_labels())
|
|
52
87
|
|
|
53
88
|
|
|
89
|
+
@pytest.fixture()
|
|
90
|
+
def labels(_labels_session: SpatialData) -> SpatialData:
|
|
91
|
+
return _fast_deepcopy_sdata(_labels_session)
|
|
92
|
+
|
|
93
|
+
|
|
54
94
|
@pytest.fixture()
|
|
55
95
|
def shapes() -> SpatialData:
|
|
56
96
|
return SpatialData(shapes=_get_shapes())
|
|
@@ -87,8 +127,8 @@ def tables() -> list[AnnData]:
|
|
|
87
127
|
return _tables
|
|
88
128
|
|
|
89
129
|
|
|
90
|
-
@pytest.fixture()
|
|
91
|
-
def
|
|
130
|
+
@pytest.fixture(scope="session")
|
|
131
|
+
def _full_sdata_session() -> SpatialData:
|
|
92
132
|
return SpatialData(
|
|
93
133
|
images=_get_images(),
|
|
94
134
|
labels=_get_labels(),
|
|
@@ -98,6 +138,22 @@ def full_sdata() -> SpatialData:
|
|
|
98
138
|
)
|
|
99
139
|
|
|
100
140
|
|
|
141
|
+
@pytest.fixture()
|
|
142
|
+
def full_sdata(_full_sdata_session: SpatialData) -> SpatialData:
|
|
143
|
+
return _fast_deepcopy_sdata(_full_sdata_session)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@pytest.fixture(scope="session")
|
|
147
|
+
def _sdata_full_session() -> SpatialData:
|
|
148
|
+
return SpatialData(
|
|
149
|
+
images=_get_images(),
|
|
150
|
+
labels=_get_labels(),
|
|
151
|
+
shapes=_get_shapes(),
|
|
152
|
+
points=_get_points(),
|
|
153
|
+
tables=_get_tables(region="labels2d"),
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
101
157
|
@pytest.fixture(
|
|
102
158
|
# params=["labels"]
|
|
103
159
|
params=["full", "empty"]
|
|
@@ -110,15 +166,9 @@ def full_sdata() -> SpatialData:
|
|
|
110
166
|
]
|
|
111
167
|
# + ["empty_" + x for x in ["table"]] # TODO: empty table not supported yet
|
|
112
168
|
)
|
|
113
|
-
def sdata(request) -> SpatialData:
|
|
169
|
+
def sdata(request, _sdata_full_session: SpatialData) -> SpatialData:
|
|
114
170
|
if request.param == "full":
|
|
115
|
-
return
|
|
116
|
-
images=_get_images(),
|
|
117
|
-
labels=_get_labels(),
|
|
118
|
-
shapes=_get_shapes(),
|
|
119
|
-
points=_get_points(),
|
|
120
|
-
tables=_get_tables(region="labels2d"),
|
|
121
|
-
)
|
|
171
|
+
return _fast_deepcopy_sdata(_sdata_full_session)
|
|
122
172
|
if request.param == "empty":
|
|
123
173
|
return SpatialData()
|
|
124
174
|
return request.getfixturevalue(request.param)
|
|
@@ -304,18 +354,38 @@ def _get_new_table(spatial_element: None | str | Sequence[str], instance_id: Non
|
|
|
304
354
|
return TableModel.parse(adata=adata, spatial_element=spatial_element, instance_id=instance_id)
|
|
305
355
|
|
|
306
356
|
|
|
307
|
-
@pytest.fixture()
|
|
308
|
-
def
|
|
309
|
-
"""Create a 2D labels."""
|
|
357
|
+
@pytest.fixture(scope="session")
|
|
358
|
+
def _labels_blobs_session() -> ArrayLike:
|
|
310
359
|
return BlobsDataset()._labels_blobs()
|
|
311
360
|
|
|
312
361
|
|
|
313
362
|
@pytest.fixture()
|
|
314
|
-
def
|
|
363
|
+
def labels_blobs(_labels_blobs_session: ArrayLike) -> ArrayLike:
|
|
315
364
|
"""Create a 2D labels."""
|
|
365
|
+
return deepcopy(_labels_blobs_session)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
@pytest.fixture(scope="session")
|
|
369
|
+
def _sdata_blobs_session() -> SpatialData:
|
|
316
370
|
from spatialdata.datasets import blobs
|
|
317
371
|
|
|
318
|
-
return
|
|
372
|
+
return blobs(256, 300, 3)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
@pytest.fixture()
|
|
376
|
+
def sdata_blobs(_sdata_blobs_session: SpatialData) -> SpatialData:
|
|
377
|
+
"""Create a 2D labels."""
|
|
378
|
+
return _fast_deepcopy_sdata(_sdata_blobs_session)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
@pytest.fixture()
|
|
382
|
+
def blobs_factory(_sdata_blobs_session: SpatialData) -> Callable[[], SpatialData]:
|
|
383
|
+
"""Return a factory that creates cheap fresh copies of the session-scoped blobs dataset."""
|
|
384
|
+
|
|
385
|
+
def _make() -> SpatialData:
|
|
386
|
+
return _fast_deepcopy_sdata(_sdata_blobs_session)
|
|
387
|
+
|
|
388
|
+
return _make
|
|
319
389
|
|
|
320
390
|
|
|
321
391
|
def _make_points(coordinates: np.ndarray) -> DaskDataFrame:
|
|
@@ -542,7 +612,8 @@ def complex_sdata() -> SpatialData:
|
|
|
542
612
|
"instance_id": range(1, 51), # Skip background (0)
|
|
543
613
|
"cell_type": pd.Categorical(RNG.choice(["T cell", "B cell", "Macrophage"], size=50)),
|
|
544
614
|
"size": RNG.uniform(10, 100, size=50),
|
|
545
|
-
}
|
|
615
|
+
},
|
|
616
|
+
index=[str(i) for i in range(50)],
|
|
546
617
|
)
|
|
547
618
|
|
|
548
619
|
var1 = pd.DataFrame(
|
|
@@ -577,7 +648,8 @@ def complex_sdata() -> SpatialData:
|
|
|
577
648
|
"category": pd.Categorical(RNG.choice(["A", "B", "C"], size=total_items)),
|
|
578
649
|
"value": RNG.normal(size=total_items),
|
|
579
650
|
"count": RNG.poisson(10, size=total_items),
|
|
580
|
-
}
|
|
651
|
+
},
|
|
652
|
+
index=[str(i) for i in range(total_items)],
|
|
581
653
|
)
|
|
582
654
|
|
|
583
655
|
var2 = pd.DataFrame(
|
|
@@ -608,7 +680,8 @@ def complex_sdata() -> SpatialData:
|
|
|
608
680
|
"cluster": pd.Categorical(RNG.choice(["cluster_1", "cluster_2", "cluster_3"], size=40)),
|
|
609
681
|
"sample": pd.Categorical(["sample_A"] * 20 + ["sample_B"] * 20),
|
|
610
682
|
"qc_pass": RNG.choice([True, False], p=[0.8, 0.2], size=40),
|
|
611
|
-
}
|
|
683
|
+
},
|
|
684
|
+
index=[str(i) for i in range(40)],
|
|
612
685
|
)
|
|
613
686
|
|
|
614
687
|
var3 = pd.DataFrame(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from __future__ import annotations
|