spatialdata 0.2.2__tar.gz → 0.2.3__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.2.3/.github/ISSUE_TEMPLATE/bug_report.md +53 -0
- spatialdata-0.2.3/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.pre-commit-config.yaml +2 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/CHANGELOG.md +13 -4
- {spatialdata-0.2.2 → spatialdata-0.2.3}/PKG-INFO +1 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/_version.py +2 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/rasterize.py +1 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/rasterize_bins.py +4 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/transform.py +2 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/query/relational_query.py +16 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/query/spatial_query.py +20 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/spatialdata.py +3 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/io_zarr.py +2 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_types.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/datasets.py +14 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/models/models.py +31 -9
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/conftest.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_aggregations.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_map.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_rasterize_bins.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_spatialdata_operations.py +2 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_transform.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_vectorize.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/query/test_relational_query.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/query/test_spatial_query.py +37 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/test_centroids.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/test_data_extent.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/test_deepcopy.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/dataloader/test_datasets.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/io/test_format.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/io/test_metadata.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/io/test_utils.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/models/test_models.py +23 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/ngff/test_ngff_coordinate_system.py +1 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/test_transformations.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/utils/test_element_utils.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/utils/test_testing.py +2 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.bumpversion.cfg +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.editorconfig +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.github/codecov.yml +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.github/workflows/build.yaml +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.github/workflows/release.yaml +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.github/workflows/test.yaml +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.gitignore +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.gitmodules +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.mypy.ini +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/.readthedocs.yaml +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/Dockerfile +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/LICENSE +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/README.md +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/pyproject.toml +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/__main__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/_deepcopy.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/_elements.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/centroids.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/concatenate.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/data_extent.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/aggregate.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/map.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/operations/vectorize.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/query/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_core/query/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/format.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/io_points.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/io_raster.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/io_shapes.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_io/io_table.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_logging.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/dataloader/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/dataloader/datasets.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/models/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/models/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/testing.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/ngff/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/ngff/_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/ngff/ngff_coordinate_system.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/ngff/ngff_transformations.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/operations.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/transformations.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_rasterize.py +2 -2
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/query/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/data/multipolygon.json +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/data/points.json +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/data/polygon.json +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/dataloader/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/datasets/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/datasets/test_datasets.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/io/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/io/test_multi_table.py +1 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/io/test_readwrite.py +1 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/io/test_versions.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/models/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/ngff/__init__.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/ngff/conftest.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/ngff/test_ngff_transformations.py +1 -1
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/test_transformations_utils.py +0 -0
- {spatialdata-0.2.2 → spatialdata-0.2.3}/tests/utils/__init__.py +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a report to help us improve
|
|
4
|
+
title: ""
|
|
5
|
+
labels: ""
|
|
6
|
+
assignees: ""
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Recommendation: attach a minimal working example**
|
|
10
|
+
Generally, the easier it is for us to reproduce the issue, the faster we can work on it. It is not required, but if you can, please:
|
|
11
|
+
|
|
12
|
+
1. Reproduce using the [`blobs` dataset](https://spatialdata.scverse.org/en/latest/generated/spatialdata.datasets.blobs.html)
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
from spatialdata.datasets import blobs
|
|
16
|
+
|
|
17
|
+
sdata = blobs()
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
You can also use [`blobs_annotating_element`](https://spatialdata.scverse.org/en/latest/generated/spatialdata.datasets.blobs_annotating_element.html) for more control:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
from spatialdata.datasets import blobs_annotating_element
|
|
24
|
+
sdata = blobs_annotating_element('blobs_labels')
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
2. If the above is not possible, reproduce using a public dataset and explain how we can download the data.
|
|
28
|
+
3. If the data is private, consider sharing an anonymized version/subset via a [Zulip private message](https://scverse.zulipchat.com/#user/480560), or provide screenshots/GIFs showing the behavior.
|
|
29
|
+
|
|
30
|
+
**Describe the bug**
|
|
31
|
+
A clear and concise description of what the bug is; please report only one bug per issue.
|
|
32
|
+
|
|
33
|
+
**To Reproduce**
|
|
34
|
+
Steps to reproduce the behavior:
|
|
35
|
+
|
|
36
|
+
1. Go to '...'
|
|
37
|
+
2. Click on '....'
|
|
38
|
+
3. Scroll down to '....'
|
|
39
|
+
4. See error
|
|
40
|
+
|
|
41
|
+
**Expected behavior**
|
|
42
|
+
A clear and concise description of what you expected to happen.
|
|
43
|
+
|
|
44
|
+
**Screenshots**
|
|
45
|
+
If applicable, add screenshots to help explain your problem.
|
|
46
|
+
|
|
47
|
+
**Desktop (optional):**
|
|
48
|
+
|
|
49
|
+
- OS: [e.g. macOS, Windows, Linux]
|
|
50
|
+
- Version [e.g. 22]
|
|
51
|
+
|
|
52
|
+
**Additional context**
|
|
53
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for this project
|
|
4
|
+
title: ""
|
|
5
|
+
labels: ""
|
|
6
|
+
assignees: ""
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Is your feature request related to a problem? Please describe.**
|
|
10
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
11
|
+
|
|
12
|
+
**Describe the solution you'd like**
|
|
13
|
+
A clear and concise description of what you want to happen.
|
|
14
|
+
|
|
15
|
+
**Describe alternatives you've considered**
|
|
16
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
|
17
|
+
|
|
18
|
+
**Additional context**
|
|
19
|
+
Add any other context or screenshots about the feature request here.
|
|
@@ -21,13 +21,13 @@ repos:
|
|
|
21
21
|
hooks:
|
|
22
22
|
- id: blacken-docs
|
|
23
23
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
24
|
-
rev: v1.11.
|
|
24
|
+
rev: v1.11.2
|
|
25
25
|
hooks:
|
|
26
26
|
- id: mypy
|
|
27
27
|
additional_dependencies: [numpy, types-requests]
|
|
28
28
|
exclude: tests/|docs/
|
|
29
29
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
30
|
-
rev: v0.
|
|
30
|
+
rev: v0.6.3
|
|
31
31
|
hooks:
|
|
32
32
|
- id: ruff
|
|
33
33
|
args: [--fix, --exit-non-zero-on-fix]
|
|
@@ -8,20 +8,29 @@ 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.
|
|
11
|
+
## [0.2.3] - 2024-09-25
|
|
12
|
+
|
|
13
|
+
### Minor
|
|
14
|
+
|
|
15
|
+
- Added `clip: bool = False` parameter to `polygon_query()` #670
|
|
16
|
+
- Add `sort` parameter to `PointsModel.parse()` #672
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Fix interpolation artifact multiscale computation for labels #697
|
|
12
21
|
|
|
13
22
|
## [0.2.2] - 2024-08-07
|
|
14
23
|
|
|
15
|
-
|
|
24
|
+
### Major
|
|
16
25
|
|
|
17
26
|
- New disk format for shapes using `GeoParquet` (the change is backward compatible) #542
|
|
18
27
|
|
|
19
|
-
|
|
28
|
+
### Minor
|
|
20
29
|
|
|
21
30
|
- Add `return_background` as argument to `get_centroids` and `get_element_instances` #621
|
|
22
31
|
- Ability to save data using older disk formats #542
|
|
23
32
|
|
|
24
|
-
|
|
33
|
+
### Fixed
|
|
25
34
|
|
|
26
35
|
- Circles validation now checks for inf or nan radii #653
|
|
27
36
|
- Bug with table name in torch dataset #654 @LLehner
|
|
@@ -336,7 +336,7 @@ def rasterize(
|
|
|
336
336
|
element_name = data if isinstance(data, str) else None
|
|
337
337
|
kwargs = {"sdata": sdata, "element_name": element_name} if element_name is not None else {"element": data}
|
|
338
338
|
values = get_values(value_key, table_name=table_name, **kwargs).iloc[:, 0] # type: ignore[arg-type, union-attr]
|
|
339
|
-
max_index = np.max(values.index)
|
|
339
|
+
max_index: int = np.max(values.index)
|
|
340
340
|
assigner = np.zeros(max_index + 1, dtype=values.dtype)
|
|
341
341
|
assigner[values.index] = values
|
|
342
342
|
# call-arg is ignored because model is never TableModel (the error is that the transformation param is not
|
|
@@ -14,6 +14,7 @@ from skimage.transform import estimate_transform
|
|
|
14
14
|
from xarray import DataArray
|
|
15
15
|
|
|
16
16
|
from spatialdata._core.query.relational_query import get_values
|
|
17
|
+
from spatialdata._types import ArrayLike
|
|
17
18
|
from spatialdata.models import Image2DModel, get_table_keys
|
|
18
19
|
from spatialdata.transformations import Affine, Sequence, get_transformation
|
|
19
20
|
|
|
@@ -113,8 +114,9 @@ def rasterize_bins(
|
|
|
113
114
|
if value_key is None:
|
|
114
115
|
shape = (n_rows, n_cols)
|
|
115
116
|
|
|
116
|
-
def channel_rasterization(block_id: tuple[int, int, int] | None) ->
|
|
117
|
-
|
|
117
|
+
def channel_rasterization(block_id: tuple[int, int, int] | None) -> ArrayLike:
|
|
118
|
+
|
|
119
|
+
image: ArrayLike = np.zeros((1, *shape), dtype=dtype)
|
|
118
120
|
|
|
119
121
|
if block_id is None:
|
|
120
122
|
return image
|
|
@@ -49,11 +49,11 @@ def _transform_raster(
|
|
|
49
49
|
v: ArrayLike = np.hstack(c_channel + [binary, np.ones(len(binary)).reshape((-1, 1))])
|
|
50
50
|
matrix = transformation.to_affine_matrix(input_axes=axes, output_axes=axes)
|
|
51
51
|
inverse_matrix = transformation.inverse().to_affine_matrix(input_axes=axes, output_axes=axes)
|
|
52
|
-
new_v = (matrix @ v.T).T
|
|
52
|
+
new_v: ArrayLike = (matrix @ v.T).T
|
|
53
53
|
c_shape: tuple[int, ...]
|
|
54
54
|
c_shape = (data.shape[0],) if "c" in axes else ()
|
|
55
55
|
new_spatial_shape = tuple(
|
|
56
|
-
int(np.max(new_v[:, i]) - np.min(new_v[:, i])) for i in range(len(c_shape), n_spatial_dims + len(c_shape))
|
|
56
|
+
int(np.max(new_v[:, i]) - np.min(new_v[:, i])) for i in range(len(c_shape), n_spatial_dims + len(c_shape)) # type: ignore[operator]
|
|
57
57
|
)
|
|
58
58
|
output_shape = c_shape + new_spatial_shape
|
|
59
59
|
translation_vector = np.min(new_v[:, :-1], axis=0)
|
|
@@ -220,8 +220,8 @@ def _filter_table_by_elements(
|
|
|
220
220
|
merged = pd.merge(table_df, pd.DataFrame(index=instances), left_on=instance_key, right_index=True, how="right")
|
|
221
221
|
matched_positions = merged["position"].to_numpy()
|
|
222
222
|
table = table[matched_positions, :]
|
|
223
|
-
_inplace_fix_subset_categorical_obs(subset_adata=table, original_adata=original_table)
|
|
224
223
|
table = table.copy()
|
|
224
|
+
_inplace_fix_subset_categorical_obs(subset_adata=table, original_adata=original_table)
|
|
225
225
|
table.uns[TableModel.ATTRS_KEY][TableModel.REGION_KEY] = table.obs[region_key].unique().tolist()
|
|
226
226
|
return table
|
|
227
227
|
|
|
@@ -623,6 +623,11 @@ def join_spatialelement_table(
|
|
|
623
623
|
If the provided join type is not supported.
|
|
624
624
|
ValueError
|
|
625
625
|
If an incorrect value is given for `match_rows`.
|
|
626
|
+
|
|
627
|
+
See Also
|
|
628
|
+
--------
|
|
629
|
+
match_element_to_table : Function to match elements to a table.
|
|
630
|
+
join_spatialelement_table : Function to join spatial elements with a table.
|
|
626
631
|
"""
|
|
627
632
|
if spatial_element_names is None:
|
|
628
633
|
raise ValueError("`spatial_element_names` must be provided.")
|
|
@@ -698,6 +703,11 @@ def match_table_to_element(sdata: SpatialData, element_name: str, table_name: st
|
|
|
698
703
|
Returns
|
|
699
704
|
-------
|
|
700
705
|
Table with the rows matching the instances of the element
|
|
706
|
+
|
|
707
|
+
See Also
|
|
708
|
+
--------
|
|
709
|
+
match_element_to_table : Function to match a spatial element to a table.
|
|
710
|
+
join_spatialelement_table : General function, to join spatial elements with a table with more control.
|
|
701
711
|
"""
|
|
702
712
|
if table_name is None:
|
|
703
713
|
warnings.warn(
|
|
@@ -731,6 +741,11 @@ def match_element_to_table(
|
|
|
731
741
|
Returns
|
|
732
742
|
-------
|
|
733
743
|
A tuple containing the joined elements as a dictionary and the joined table as an AnnData object.
|
|
744
|
+
|
|
745
|
+
See Also
|
|
746
|
+
--------
|
|
747
|
+
match_table_to_element : Function to match a table to a spatial element.
|
|
748
|
+
join_spatialelement_table : General function, to join spatial elements with a table with more control.
|
|
734
749
|
"""
|
|
735
750
|
element_dict, table = join_spatialelement_table(
|
|
736
751
|
sdata=sdata, spatial_element_names=element_name, table_name=table_name, how="right", match_rows="right"
|
|
@@ -13,7 +13,7 @@ import numpy as np
|
|
|
13
13
|
from dask.dataframe import DataFrame as DaskDataFrame
|
|
14
14
|
from datatree import DataTree
|
|
15
15
|
from geopandas import GeoDataFrame
|
|
16
|
-
from shapely.geometry import MultiPolygon, Polygon
|
|
16
|
+
from shapely.geometry import MultiPolygon, Point, Polygon
|
|
17
17
|
from xarray import DataArray
|
|
18
18
|
|
|
19
19
|
from spatialdata import to_polygons
|
|
@@ -758,6 +758,7 @@ def polygon_query(
|
|
|
758
758
|
polygon: Polygon | MultiPolygon,
|
|
759
759
|
target_coordinate_system: str,
|
|
760
760
|
filter_table: bool = True,
|
|
761
|
+
clip: bool = False,
|
|
761
762
|
shapes: bool = True,
|
|
762
763
|
points: bool = True,
|
|
763
764
|
images: bool = True,
|
|
@@ -777,6 +778,12 @@ def polygon_query(
|
|
|
777
778
|
filter_table
|
|
778
779
|
Specifies whether to filter the tables to only include tables that annotate elements in the retrieved
|
|
779
780
|
SpatialData object of the query.
|
|
781
|
+
clip
|
|
782
|
+
If `True`, the shapes are clipped to the polygon. This behavior is implemented only when querying
|
|
783
|
+
polygons/multipolygons or circles, and it is ignored for other types of elements (images, labels, points).
|
|
784
|
+
Importantly, when clipping is enabled, the circles will be converted to polygons before the clipping. This may
|
|
785
|
+
affect downstream operations that rely on the circle radius or on performance, so it is recommended to disable
|
|
786
|
+
clipping when querying circles or when querying a `SpatialData` object that contains circles.
|
|
780
787
|
shapes [Deprecated]
|
|
781
788
|
This argument is now ignored and will be removed. Please filter the SpatialData object before calling this
|
|
782
789
|
function.
|
|
@@ -810,6 +817,7 @@ def _(
|
|
|
810
817
|
polygon: Polygon | MultiPolygon,
|
|
811
818
|
target_coordinate_system: str,
|
|
812
819
|
filter_table: bool = True,
|
|
820
|
+
clip: bool = False,
|
|
813
821
|
shapes: bool = True,
|
|
814
822
|
points: bool = True,
|
|
815
823
|
images: bool = True,
|
|
@@ -825,6 +833,7 @@ def _(
|
|
|
825
833
|
polygon_query,
|
|
826
834
|
polygon=polygon,
|
|
827
835
|
target_coordinate_system=target_coordinate_system,
|
|
836
|
+
clip=clip,
|
|
828
837
|
)
|
|
829
838
|
new_elements[element_type] = queried_elements
|
|
830
839
|
|
|
@@ -891,6 +900,7 @@ def _(
|
|
|
891
900
|
element: GeoDataFrame,
|
|
892
901
|
polygon: Polygon | MultiPolygon,
|
|
893
902
|
target_coordinate_system: str,
|
|
903
|
+
clip: bool = False,
|
|
894
904
|
**kwargs: Any,
|
|
895
905
|
) -> GeoDataFrame | None:
|
|
896
906
|
from spatialdata.transformations import get_transformation, set_transformation
|
|
@@ -912,9 +922,18 @@ def _(
|
|
|
912
922
|
queried_shapes = element[indices]
|
|
913
923
|
queried_shapes.index = buffered[indices][OLD_INDEX]
|
|
914
924
|
queried_shapes.index.name = None
|
|
925
|
+
|
|
926
|
+
if clip:
|
|
927
|
+
if isinstance(element.geometry.iloc[0], Point):
|
|
928
|
+
queried_shapes = buffered[indices]
|
|
929
|
+
queried_shapes.index = buffered[indices][OLD_INDEX]
|
|
930
|
+
queried_shapes.index.name = None
|
|
931
|
+
queried_shapes = queried_shapes.clip(polygon_gdf, keep_geom_type=True)
|
|
932
|
+
|
|
915
933
|
del buffered[OLD_INDEX]
|
|
916
934
|
if OLD_INDEX in queried_shapes.columns:
|
|
917
935
|
del queried_shapes[OLD_INDEX]
|
|
936
|
+
|
|
918
937
|
transformation = get_transformation(buffered, target_coordinate_system)
|
|
919
938
|
queried_shapes = ShapesModel.parse(queried_shapes)
|
|
920
939
|
set_transformation(queried_shapes, transformation, target_coordinate_system)
|
|
@@ -628,7 +628,7 @@ class SpatialData:
|
|
|
628
628
|
found_element_name: list[str] = []
|
|
629
629
|
for element_type in ["images", "labels", "points", "shapes", "tables"]:
|
|
630
630
|
for element_name, element_value in getattr(self, element_type).items():
|
|
631
|
-
if
|
|
631
|
+
if element_value is element:
|
|
632
632
|
found.append(element_value)
|
|
633
633
|
found_element_type.append(element_type)
|
|
634
634
|
found_element_name.append(element_name)
|
|
@@ -2225,6 +2225,7 @@ class QueryManager:
|
|
|
2225
2225
|
polygon: Polygon | MultiPolygon,
|
|
2226
2226
|
target_coordinate_system: str,
|
|
2227
2227
|
filter_table: bool = True,
|
|
2228
|
+
clip: bool = False,
|
|
2228
2229
|
) -> SpatialData:
|
|
2229
2230
|
"""
|
|
2230
2231
|
Perform a polygon query on the SpatialData object.
|
|
@@ -2239,6 +2240,7 @@ class QueryManager:
|
|
|
2239
2240
|
polygon=polygon,
|
|
2240
2241
|
target_coordinate_system=target_coordinate_system,
|
|
2241
2242
|
filter_table=filter_table,
|
|
2243
|
+
clip=clip,
|
|
2242
2244
|
)
|
|
2243
2245
|
|
|
2244
2246
|
def __call__(self, request: BaseSpatialRequest, **kwargs) -> SpatialData: # type: ignore[no-untyped-def]
|
|
@@ -128,8 +128,8 @@ def read_zarr(store: Union[str, Path, zarr.Group], selection: Optional[tuple[str
|
|
|
128
128
|
|
|
129
129
|
if "table" in selector and "table" in f:
|
|
130
130
|
warnings.warn(
|
|
131
|
-
f"Table group found in zarr store at location {f_store_path}. Please update the zarr store"
|
|
132
|
-
f"
|
|
131
|
+
f"Table group found in zarr store at location {f_store_path}. Please update the zarr store to use tables "
|
|
132
|
+
f"instead.",
|
|
133
133
|
DeprecationWarning,
|
|
134
134
|
stacklevel=2,
|
|
135
135
|
)
|
|
@@ -6,7 +6,7 @@ import numpy as np
|
|
|
6
6
|
from datatree import DataTree
|
|
7
7
|
from xarray import DataArray
|
|
8
8
|
|
|
9
|
-
__all__ = ["ArrayLike", "DTypeLike", "Raster_T"]
|
|
9
|
+
__all__ = ["ArrayLike", "ColorLike", "DTypeLike", "Raster_T"]
|
|
10
10
|
|
|
11
11
|
try:
|
|
12
12
|
from numpy.typing import DTypeLike, NDArray
|
|
@@ -17,3 +17,4 @@ except (ImportError, TypeError):
|
|
|
17
17
|
DTypeLike = np.dtype # type: ignore[misc]
|
|
18
18
|
|
|
19
19
|
Raster_T = Union[DataArray, DataTree]
|
|
20
|
+
ColorLike = Union[tuple[float, ...], str]
|
|
@@ -63,8 +63,7 @@ def blobs(
|
|
|
63
63
|
|
|
64
64
|
Returns
|
|
65
65
|
-------
|
|
66
|
-
SpatialData
|
|
67
|
-
SpatialData object with blobs dataset.
|
|
66
|
+
SpatialData object with blobs dataset.
|
|
68
67
|
"""
|
|
69
68
|
return BlobsDataset(
|
|
70
69
|
length=length,
|
|
@@ -355,6 +354,19 @@ BlobsTypes = Literal[
|
|
|
355
354
|
|
|
356
355
|
|
|
357
356
|
def blobs_annotating_element(name: BlobsTypes) -> SpatialData:
|
|
357
|
+
"""
|
|
358
|
+
Return the blobs dataset with the desired element annotated by the table.
|
|
359
|
+
|
|
360
|
+
Parameters
|
|
361
|
+
----------
|
|
362
|
+
name
|
|
363
|
+
Name of the element to annotate. One of "blobs_labels", "blobs_multiscale_labels", "blobs_circles",
|
|
364
|
+
"blobs_polygons", "blobs_multipolygons".
|
|
365
|
+
|
|
366
|
+
Returns
|
|
367
|
+
-------
|
|
368
|
+
SpatialData object with the desired element annotated by the table.
|
|
369
|
+
"""
|
|
358
370
|
sdata = blobs(length=50)
|
|
359
371
|
if name in ["blobs_labels", "blobs_multiscale_labels"]:
|
|
360
372
|
instance_id = get_element_instances(sdata[name]).tolist()
|
|
@@ -255,6 +255,17 @@ class Labels2DModel(RasterSchema):
|
|
|
255
255
|
**kwargs,
|
|
256
256
|
)
|
|
257
257
|
|
|
258
|
+
@classmethod
|
|
259
|
+
def parse( # noqa: D102
|
|
260
|
+
self,
|
|
261
|
+
*args: Any,
|
|
262
|
+
**kwargs: Any,
|
|
263
|
+
) -> DataArray | DataTree:
|
|
264
|
+
if kwargs.get("scale_factors") is not None and kwargs.get("method") is None:
|
|
265
|
+
# Override default scaling method to preserve labels
|
|
266
|
+
kwargs["method"] = Methods.DASK_IMAGE_NEAREST
|
|
267
|
+
return super().parse(*args, **kwargs)
|
|
268
|
+
|
|
258
269
|
|
|
259
270
|
class Labels3DModel(RasterSchema):
|
|
260
271
|
dims = DimsSchema((Z, Y, X))
|
|
@@ -270,6 +281,13 @@ class Labels3DModel(RasterSchema):
|
|
|
270
281
|
**kwargs,
|
|
271
282
|
)
|
|
272
283
|
|
|
284
|
+
@classmethod
|
|
285
|
+
def parse(self, *args: Any, **kwargs: Any) -> DataArray | DataTree: # noqa: D102
|
|
286
|
+
if kwargs.get("scale_factors") is not None and kwargs.get("method") is None:
|
|
287
|
+
# Override default scaling method to preserve labels
|
|
288
|
+
kwargs["method"] = Methods.DASK_IMAGE_NEAREST
|
|
289
|
+
return super().parse(*args, **kwargs)
|
|
290
|
+
|
|
273
291
|
|
|
274
292
|
class Image2DModel(RasterSchema):
|
|
275
293
|
dims = DimsSchema((C, Y, X))
|
|
@@ -656,14 +674,18 @@ class PointsModel:
|
|
|
656
674
|
)
|
|
657
675
|
ndim = len(coordinates)
|
|
658
676
|
axes = [X, Y, Z][:ndim]
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
677
|
+
if "sort" not in kwargs:
|
|
678
|
+
index_monotonically_increasing = data.index.is_monotonic_increasing
|
|
679
|
+
if not isinstance(index_monotonically_increasing, bool):
|
|
680
|
+
index_monotonically_increasing = index_monotonically_increasing.compute()
|
|
681
|
+
sort = index_monotonically_increasing
|
|
682
|
+
else:
|
|
683
|
+
sort = kwargs["sort"]
|
|
684
|
+
if not sort:
|
|
663
685
|
warnings.warn(
|
|
664
686
|
"The index of the dataframe is not monotonic increasing. It is recommended to sort the data to "
|
|
665
|
-
"adjust the order of the index before calling .parse() to avoid possible
|
|
666
|
-
"divisions",
|
|
687
|
+
"adjust the order of the index before calling .parse() (or call `parse(sort=True)`) to avoid possible "
|
|
688
|
+
"problems due to unknown divisions.",
|
|
667
689
|
UserWarning,
|
|
668
690
|
stacklevel=2,
|
|
669
691
|
)
|
|
@@ -671,16 +693,16 @@ class PointsModel:
|
|
|
671
693
|
table: DaskDataFrame = dd.from_pandas( # type: ignore[attr-defined]
|
|
672
694
|
pd.DataFrame(data[[coordinates[ax] for ax in axes]].to_numpy(), columns=axes, index=data.index),
|
|
673
695
|
# we need to pass sort=True also when the index is sorted to ensure that the divisions are computed
|
|
674
|
-
sort=
|
|
696
|
+
sort=sort,
|
|
675
697
|
**kwargs,
|
|
676
698
|
)
|
|
677
699
|
# we cannot compute the divisions whne the index is not monotonically increasing and npartitions > 1
|
|
678
|
-
if not table.known_divisions and (
|
|
700
|
+
if not table.known_divisions and (sort or table.npartitions == 1):
|
|
679
701
|
table.divisions = table.compute_current_divisions()
|
|
680
702
|
if feature_key is not None:
|
|
681
703
|
feature_categ = dd.from_pandas(
|
|
682
704
|
data[feature_key].astype(str).astype("category"),
|
|
683
|
-
sort=
|
|
705
|
+
sort=sort,
|
|
684
706
|
**kwargs,
|
|
685
707
|
) # type: ignore[attr-defined]
|
|
686
708
|
table[feature_key] = feature_categ
|
|
@@ -21,6 +21,8 @@ from scipy import ndimage as ndi
|
|
|
21
21
|
from shapely import linearrings, polygons
|
|
22
22
|
from shapely.geometry import MultiPolygon, Point, Polygon
|
|
23
23
|
from skimage import data
|
|
24
|
+
from xarray import DataArray
|
|
25
|
+
|
|
24
26
|
from spatialdata._core._deepcopy import deepcopy
|
|
25
27
|
from spatialdata._core.spatialdata import SpatialData
|
|
26
28
|
from spatialdata._types import ArrayLike
|
|
@@ -34,7 +36,6 @@ from spatialdata.models import (
|
|
|
34
36
|
ShapesModel,
|
|
35
37
|
TableModel,
|
|
36
38
|
)
|
|
37
|
-
from xarray import DataArray
|
|
38
39
|
|
|
39
40
|
SEED = 0
|
|
40
41
|
RNG = default_rng(seed=SEED)
|
|
@@ -8,6 +8,7 @@ from anndata import AnnData
|
|
|
8
8
|
from anndata.tests.helpers import assert_equal
|
|
9
9
|
from geopandas import GeoDataFrame
|
|
10
10
|
from numpy.random import default_rng
|
|
11
|
+
|
|
11
12
|
from spatialdata import aggregate, to_polygons
|
|
12
13
|
from spatialdata._core._deepcopy import deepcopy as _deepcopy
|
|
13
14
|
from spatialdata._core.spatialdata import SpatialData
|
|
@@ -366,7 +367,7 @@ def test_aggregate_requiring_alignment(sdata_blobs: SpatialData, values, by) ->
|
|
|
366
367
|
raise pytest.skip("Aggregation mixing raster and vector data is not currently supported.")
|
|
367
368
|
values = sdata_blobs[values]
|
|
368
369
|
by = sdata_blobs[by]
|
|
369
|
-
if
|
|
370
|
+
if values is by:
|
|
370
371
|
# warning: this will give problems when aggregation labels by labels (not supported yet), because of this: https://github.com/scverse/spatialdata/issues/269
|
|
371
372
|
by = _deepcopy(by)
|
|
372
373
|
assert by.attrs["transform"] is not values.attrs["transform"]
|
|
@@ -2,9 +2,10 @@ import re
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pytest
|
|
5
|
+
from xarray import DataArray
|
|
6
|
+
|
|
5
7
|
from spatialdata._core.operations.map import map_raster
|
|
6
8
|
from spatialdata.transformations import Translation, get_transformation, set_transformation
|
|
7
|
-
from xarray import DataArray
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def _multiply(arr, parameter=10):
|
|
@@ -8,6 +8,7 @@ from numpy.random import default_rng
|
|
|
8
8
|
from pandas import DataFrame
|
|
9
9
|
from scipy.sparse import csr_matrix
|
|
10
10
|
from shapely.geometry import Polygon
|
|
11
|
+
|
|
11
12
|
from spatialdata._core.data_extent import are_extents_equal, get_extent
|
|
12
13
|
from spatialdata._core.operations.rasterize_bins import rasterize_bins
|
|
13
14
|
from spatialdata._core.spatialdata import SpatialData
|
{spatialdata-0.2.2 → spatialdata-0.2.3}/tests/core/operations/test_spatialdata_operations.py
RENAMED
|
@@ -5,6 +5,7 @@ import math
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import pytest
|
|
7
7
|
from anndata import AnnData
|
|
8
|
+
|
|
8
9
|
from spatialdata._core.concatenate import _concatenate_tables, concatenate
|
|
9
10
|
from spatialdata._core.data_extent import are_extents_equal, get_extent
|
|
10
11
|
from spatialdata._core.operations._utils import transform_to_data_extent
|
|
@@ -21,7 +22,6 @@ from spatialdata.transformations.transformations import (
|
|
|
21
22
|
Sequence,
|
|
22
23
|
Translation,
|
|
23
24
|
)
|
|
24
|
-
|
|
25
25
|
from tests.conftest import _get_table
|
|
26
26
|
|
|
27
27
|
|
|
@@ -296,7 +296,7 @@ def test_locate_spatial_element(full_sdata: SpatialData) -> None:
|
|
|
296
296
|
|
|
297
297
|
|
|
298
298
|
def test_get_item(points: SpatialData) -> None:
|
|
299
|
-
assert
|
|
299
|
+
assert points["points_0"] is points.points["points_0"]
|
|
300
300
|
|
|
301
301
|
# removed this test after this change: https://github.com/scverse/spatialdata/pull/145#discussion_r1133122720
|
|
302
302
|
# to be uncommented/removed/modified after this is closed: https://github.com/scverse/spatialdata/issues/186
|
|
@@ -6,6 +6,8 @@ import numpy as np
|
|
|
6
6
|
import pytest
|
|
7
7
|
from datatree import DataTree
|
|
8
8
|
from geopandas.testing import geom_almost_equals
|
|
9
|
+
from xarray import DataArray
|
|
10
|
+
|
|
9
11
|
from spatialdata import transform
|
|
10
12
|
from spatialdata._core.data_extent import are_extents_equal, get_extent
|
|
11
13
|
from spatialdata._core.spatialdata import SpatialData
|
|
@@ -28,7 +30,6 @@ from spatialdata.transformations.transformations import (
|
|
|
28
30
|
Sequence,
|
|
29
31
|
Translation,
|
|
30
32
|
)
|
|
31
|
-
from xarray import DataArray
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class TestElementsTransform:
|
|
@@ -4,6 +4,7 @@ import numpy as np
|
|
|
4
4
|
import pytest
|
|
5
5
|
from geopandas import GeoDataFrame
|
|
6
6
|
from shapely import MultiPoint, Point
|
|
7
|
+
|
|
7
8
|
from spatialdata._core.operations.vectorize import to_circles, to_polygons
|
|
8
9
|
from spatialdata.datasets import blobs
|
|
9
10
|
from spatialdata.models.models import ShapesModel
|
|
@@ -11,6 +11,9 @@ from dask.dataframe import DataFrame as DaskDataFrame
|
|
|
11
11
|
from datatree import DataTree
|
|
12
12
|
from geopandas import GeoDataFrame
|
|
13
13
|
from shapely import MultiPolygon, Point, Polygon
|
|
14
|
+
from xarray import DataArray
|
|
15
|
+
|
|
16
|
+
from spatialdata._core.data_extent import get_extent
|
|
14
17
|
from spatialdata._core.query.spatial_query import (
|
|
15
18
|
BaseSpatialRequest,
|
|
16
19
|
BoundingBoxRequest,
|
|
@@ -29,8 +32,6 @@ from spatialdata.models import (
|
|
|
29
32
|
)
|
|
30
33
|
from spatialdata.testing import assert_spatial_data_objects_are_identical
|
|
31
34
|
from spatialdata.transformations import Identity, MapAxis, set_transformation
|
|
32
|
-
from xarray import DataArray
|
|
33
|
-
|
|
34
35
|
from tests.conftest import _make_points, _make_squares
|
|
35
36
|
|
|
36
37
|
|
|
@@ -686,3 +687,37 @@ def test_spatial_query_different_axes(full_sdata, name: str):
|
|
|
686
687
|
return
|
|
687
688
|
|
|
688
689
|
raise RuntimeError(f"Unexpected type {type(original)}")
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def test_query_with_clipping(sdata_blobs):
|
|
693
|
+
circles = sdata_blobs["blobs_circles"]
|
|
694
|
+
circles.index = [10, 100, 1]
|
|
695
|
+
polygons = sdata_blobs["blobs_polygons"]
|
|
696
|
+
polygons.index = [10, 100, 1]
|
|
697
|
+
|
|
698
|
+
# define square to use as query geometry
|
|
699
|
+
minx = 120
|
|
700
|
+
maxx = 170
|
|
701
|
+
miny = 150
|
|
702
|
+
maxy = 210
|
|
703
|
+
x_coords = [minx, maxx, maxx, minx, minx]
|
|
704
|
+
y_coords = [miny, miny, maxy, maxy, miny]
|
|
705
|
+
polygon = Polygon(zip(x_coords, y_coords))
|
|
706
|
+
|
|
707
|
+
queried_circles = polygon_query(circles, polygon=polygon, target_coordinate_system="global", clip=True)
|
|
708
|
+
queried_polygons = polygon_query(polygons, polygon=polygon, target_coordinate_system="global", clip=True)
|
|
709
|
+
|
|
710
|
+
assert queried_circles.index.tolist() == [100]
|
|
711
|
+
assert queried_polygons.index.tolist() == [100]
|
|
712
|
+
|
|
713
|
+
extent_circles = get_extent(queried_circles)
|
|
714
|
+
extent_polygons = get_extent(queried_polygons)
|
|
715
|
+
|
|
716
|
+
def query_polyon_contains_queried_data(extent: dict[str, tuple[float, float]]) -> None:
|
|
717
|
+
assert extent["x"][0] >= minx
|
|
718
|
+
assert extent["x"][1] <= maxx
|
|
719
|
+
assert extent["y"][0] >= miny
|
|
720
|
+
assert extent["y"][1] <= maxy
|
|
721
|
+
|
|
722
|
+
query_polyon_contains_queried_data(extent_circles)
|
|
723
|
+
query_polyon_contains_queried_data(extent_polygons)
|
|
@@ -5,6 +5,7 @@ import pandas as pd
|
|
|
5
5
|
import pytest
|
|
6
6
|
from anndata import AnnData
|
|
7
7
|
from numpy.random import default_rng
|
|
8
|
+
|
|
8
9
|
from spatialdata._core.centroids import get_centroids
|
|
9
10
|
from spatialdata._core.query.relational_query import get_element_instances
|
|
10
11
|
from spatialdata.models import Labels2DModel, Labels3DModel, PointsModel, TableModel, get_axes_names
|
|
@@ -6,6 +6,7 @@ import pytest
|
|
|
6
6
|
from geopandas import GeoDataFrame
|
|
7
7
|
from numpy.random import default_rng
|
|
8
8
|
from shapely.geometry import MultiPolygon, Point, Polygon
|
|
9
|
+
|
|
9
10
|
from spatialdata import SpatialData, get_extent, transform
|
|
10
11
|
from spatialdata._core._deepcopy import deepcopy as _deepcopy
|
|
11
12
|
from spatialdata.datasets import blobs
|
|
@@ -22,6 +22,8 @@ from numpy.random import default_rng
|
|
|
22
22
|
from shapely.geometry import MultiPolygon, Point, Polygon
|
|
23
23
|
from shapely.io import to_ragged_array
|
|
24
24
|
from spatial_image import to_spatial_image
|
|
25
|
+
from xarray import DataArray
|
|
26
|
+
|
|
25
27
|
from spatialdata._core.spatialdata import SpatialData
|
|
26
28
|
from spatialdata._types import ArrayLike
|
|
27
29
|
from spatialdata.models._utils import (
|
|
@@ -51,8 +53,6 @@ from spatialdata.transformations.operations import (
|
|
|
51
53
|
set_transformation,
|
|
52
54
|
)
|
|
53
55
|
from spatialdata.transformations.transformations import Identity, Scale
|
|
54
|
-
from xarray import DataArray
|
|
55
|
-
|
|
56
56
|
from tests.conftest import (
|
|
57
57
|
MULTIPOLYGON_PATH,
|
|
58
58
|
POINT_PATH,
|
|
@@ -195,6 +195,27 @@ class TestModels:
|
|
|
195
195
|
with pytest.raises(ValueError):
|
|
196
196
|
model.parse(image, **kwargs)
|
|
197
197
|
|
|
198
|
+
@pytest.mark.parametrize("model", [Labels2DModel, Labels3DModel])
|
|
199
|
+
def test_labels_model_with_multiscales(self, model):
|
|
200
|
+
# Passing "scale_factors" should generate multiscales with a "method" appropriate for labels
|
|
201
|
+
dims = np.array(model.dims.dims).tolist()
|
|
202
|
+
n_dims = len(dims)
|
|
203
|
+
|
|
204
|
+
# A labels image with one label value 4, that partially covers 2×2 blocks.
|
|
205
|
+
# Downsampling with interpolation would produce values 1, 2, 3, 4.
|
|
206
|
+
image: ArrayLike = np.array([[0, 0, 0, 0], [0, 4, 4, 4], [4, 4, 4, 4], [0, 4, 4, 4]], dtype=np.uint16)
|
|
207
|
+
if n_dims == 3:
|
|
208
|
+
image = np.stack([image] * image.shape[0])
|
|
209
|
+
actual = model.parse(image, scale_factors=(2,))
|
|
210
|
+
assert isinstance(actual, DataTree)
|
|
211
|
+
assert actual.children.keys() == {"scale0", "scale1"}
|
|
212
|
+
assert actual.scale0.image.dtype == image.dtype
|
|
213
|
+
assert actual.scale1.image.dtype == image.dtype
|
|
214
|
+
assert set(np.unique(image)) == set(np.unique(actual.scale0.image)), "Scale0 should be preserved"
|
|
215
|
+
assert set(np.unique(image)) >= set(
|
|
216
|
+
np.unique(actual.scale1.image)
|
|
217
|
+
), "Subsequent scales should not have interpolation artifacts"
|
|
218
|
+
|
|
198
219
|
@pytest.mark.parametrize("model", [ShapesModel])
|
|
199
220
|
@pytest.mark.parametrize("path", [POLYGON_PATH, MULTIPOLYGON_PATH, POINT_PATH])
|
|
200
221
|
def test_shapes_model(self, model: ShapesModel, path: Path) -> None:
|
|
@@ -4,6 +4,8 @@ from copy import deepcopy
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pytest
|
|
6
6
|
import xarray.testing
|
|
7
|
+
from xarray import DataArray
|
|
8
|
+
|
|
7
9
|
from spatialdata import transform
|
|
8
10
|
from spatialdata.datasets import blobs
|
|
9
11
|
from spatialdata.models import Image2DModel, PointsModel
|
|
@@ -32,7 +34,6 @@ from spatialdata.transformations.transformations import (
|
|
|
32
34
|
_decompose_transformation,
|
|
33
35
|
_get_affine_for_element,
|
|
34
36
|
)
|
|
35
|
-
from xarray import DataArray
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
def test_identity():
|
|
@@ -4,10 +4,11 @@ import dask_image.ndinterp
|
|
|
4
4
|
import pytest
|
|
5
5
|
import xarray
|
|
6
6
|
from datatree import DataTree
|
|
7
|
+
from xarray import DataArray
|
|
8
|
+
|
|
7
9
|
from spatialdata._utils import unpad_raster
|
|
8
10
|
from spatialdata.models import get_model
|
|
9
11
|
from spatialdata.transformations import Affine
|
|
10
|
-
from xarray import DataArray
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def _pad_raster(data: DataArray, axes: tuple[str, ...]) -> DataArray:
|
|
@@ -3,6 +3,8 @@ import copy
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pytest
|
|
5
5
|
from datatree import DataTree
|
|
6
|
+
from xarray import DataArray
|
|
7
|
+
|
|
6
8
|
from spatialdata import SpatialData, deepcopy
|
|
7
9
|
from spatialdata.models import (
|
|
8
10
|
Image2DModel,
|
|
@@ -16,7 +18,6 @@ from spatialdata.models import (
|
|
|
16
18
|
)
|
|
17
19
|
from spatialdata.testing import assert_elements_are_identical, assert_spatial_data_objects_are_identical
|
|
18
20
|
from spatialdata.transformations import Scale, set_transformation
|
|
19
|
-
from xarray import DataArray
|
|
20
21
|
|
|
21
22
|
scale = Scale([1.0], axes=("x",))
|
|
22
23
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatialdata-0.2.2 → spatialdata-0.2.3}/src/spatialdata/transformations/ngff/ngff_transformations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -11,6 +11,8 @@ from geopandas import GeoDataFrame
|
|
|
11
11
|
from multiscale_spatial_image import MultiscaleSpatialImage
|
|
12
12
|
from shapely import MultiPolygon, box
|
|
13
13
|
from spatial_image import SpatialImage
|
|
14
|
+
from xarray import DataArray
|
|
15
|
+
|
|
14
16
|
from spatialdata import SpatialData, get_extent
|
|
15
17
|
from spatialdata._core.operations.rasterize import rasterize
|
|
16
18
|
from spatialdata._core.query.relational_query import get_element_instances
|
|
@@ -18,8 +20,6 @@ from spatialdata._io._utils import _iter_multiscale
|
|
|
18
20
|
from spatialdata.models import PointsModel, ShapesModel, TableModel, get_axes_names
|
|
19
21
|
from spatialdata.models._utils import get_spatial_axes
|
|
20
22
|
from spatialdata.transformations import MapAxis
|
|
21
|
-
from xarray import DataArray
|
|
22
|
-
|
|
23
23
|
from tests.conftest import _get_images, _get_labels
|
|
24
24
|
|
|
25
25
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -4,9 +4,9 @@ import pandas as pd
|
|
|
4
4
|
import pytest
|
|
5
5
|
from anndata import AnnData
|
|
6
6
|
from anndata.tests.helpers import assert_equal
|
|
7
|
+
|
|
7
8
|
from spatialdata import SpatialData, concatenate
|
|
8
9
|
from spatialdata.models import TableModel
|
|
9
|
-
|
|
10
10
|
from tests.conftest import _get_shapes, _get_table
|
|
11
11
|
|
|
12
12
|
# notes on paths: https://github.com/orgs/scverse/projects/17/views/1?pane=issue&itemId=44066734
|
|
@@ -8,6 +8,7 @@ import numpy as np
|
|
|
8
8
|
import pytest
|
|
9
9
|
from anndata import AnnData
|
|
10
10
|
from numpy.random import default_rng
|
|
11
|
+
|
|
11
12
|
from spatialdata import SpatialData, deepcopy, read_zarr
|
|
12
13
|
from spatialdata._io._utils import _are_directories_identical, get_dask_backing_files
|
|
13
14
|
from spatialdata.datasets import blobs
|
|
@@ -19,7 +20,6 @@ from spatialdata.transformations.operations import (
|
|
|
19
20
|
set_transformation,
|
|
20
21
|
)
|
|
21
22
|
from spatialdata.transformations.transformations import Identity, Scale
|
|
22
|
-
|
|
23
23
|
from tests.conftest import _get_images, _get_labels, _get_points, _get_shapes
|
|
24
24
|
|
|
25
25
|
RNG = default_rng(0)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatialdata-0.2.2 → spatialdata-0.2.3}/tests/transformations/ngff/test_ngff_transformations.py
RENAMED
|
@@ -4,6 +4,7 @@ import json
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import pytest
|
|
7
|
+
|
|
7
8
|
from spatialdata._types import ArrayLike
|
|
8
9
|
from spatialdata.models import C, X, Y, Z
|
|
9
10
|
from spatialdata.transformations.ngff._utils import get_default_coordinate_system
|
|
@@ -19,7 +20,6 @@ from spatialdata.transformations.ngff.ngff_transformations import (
|
|
|
19
20
|
NgffSequence,
|
|
20
21
|
NgffTranslation,
|
|
21
22
|
)
|
|
22
|
-
|
|
23
23
|
from tests.transformations.ngff.conftest import (
|
|
24
24
|
c_cs,
|
|
25
25
|
cyx_cs,
|
|
File without changes
|
|
File without changes
|