spatial-aim 1.3.0__tar.gz → 1.4.0__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.
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/PKG-INFO +28 -25
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/README.md +26 -23
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/environment.yml +1 -1
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/pyproject.toml +1 -1
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatial_aim.egg-info/PKG-INFO +28 -25
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatial_aim.egg-info/SOURCES.txt +7 -2
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatial_aim.egg-info/requires.txt +1 -1
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatial_aim.egg-info/scm_file_list.json +7 -2
- spatial_aim-1.4.0/src/spatial_aim.egg-info/scm_version.json +8 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/adata_schema.py +6 -3
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/coherence.py +4 -44
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/compare_ks/__init__.py +2 -2
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/compare_ks/collect.py +37 -22
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/compare_ks/criteria.py +5 -6
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/compare_ks/scoring.py +12 -33
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/reconstruction.py +25 -46
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/run.py +3 -3
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/shape_consistency.py +4 -3
- spatial_aim-1.4.0/src/spatialaim/analysis/topology.py +65 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/cli.py +25 -32
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/clustering.py +33 -26
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/config.py +7 -5
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_03_mouse_liver.py +3 -13
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_04_mouse_kidney.py +27 -42
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_05_mouse_embryo.py +20 -45
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_06_mouse_retina.py +5 -43
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_07_mouse_mpfc.py +2 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_08_mouse_visual_cortex.py +36 -48
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/__main__.py +6 -0
- spatial_aim-1.4.0/src/spatialaim/gui/app.py +189 -0
- spatial_aim-1.4.0/src/spatialaim/gui/compute.py +175 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/data_access.py +138 -36
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/loaders.py +8 -4
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/__init__.py +1 -1
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/cell_type.py +17 -49
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/ksweep.py +9 -22
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/markers.py +15 -7
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/report.py +25 -12
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/scatter.py +54 -33
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/scaffold.py +30 -28
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/sidebar.py +159 -82
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/state_names.py +74 -14
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/texts.py +0 -16
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/cards.py +0 -20
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/cell_type_modal.py +8 -17
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/compare_tab.py +12 -12
- spatial_aim-1.4.0/src/spatialaim/gui/views/controls.py +80 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/mapper_tab.py +104 -20
- spatial_aim-1.4.0/src/spatialaim/gui/views/overview.py +116 -0
- spatial_aim-1.4.0/src/spatialaim/gui/views/pages.py +258 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/report.py +2 -52
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/io.py +19 -7
- spatial_aim-1.4.0/src/spatialaim/metrics/topology.py +65 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/sweep.py +112 -57
- spatial_aim-1.4.0/src/spatialaim/utils.py +37 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/tests/test_cli.py +30 -8
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/tests/test_gui_imports.py +2 -0
- spatial_aim-1.4.0/tests/test_gui_overview.py +53 -0
- spatial_aim-1.4.0/tests/test_sweep_sample.py +197 -0
- spatial_aim-1.4.0/tests/test_topology.py +67 -0
- spatial_aim-1.4.0/tests/test_utils.py +25 -0
- spatial_aim-1.3.0/src/spatial_aim.egg-info/scm_version.json +0 -8
- spatial_aim-1.3.0/src/spatialaim/analysis/spatial_organization.py +0 -122
- spatial_aim-1.3.0/src/spatialaim/gui/app.py +0 -228
- spatial_aim-1.3.0/src/spatialaim/gui/compute.py +0 -112
- spatial_aim-1.3.0/src/spatialaim/gui/views/controls.py +0 -46
- spatial_aim-1.3.0/src/spatialaim/metrics/topology.py +0 -49
- spatial_aim-1.3.0/src/spatialaim/utils.py +0 -18
- spatial_aim-1.3.0/tests/test_sweep_sample.py +0 -126
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/.github/workflows/ci.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/.github/workflows/release.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/.gitignore +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/.pre-commit-config.yaml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/LICENSE +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/docs/aim_gui.gif +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/docs/figure_2_1.png +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/renovate.json +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/sample_dataset/ST/index.csv +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/sample_dataset/ST/sample_st.h5ad +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/sample_dataset/pairs.csv +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/sample_dataset/scRNA/index.csv +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/sample_dataset/scRNA/sample_sc.h5ad +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/setup.cfg +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatial_aim.egg-info/dependency_links.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatial_aim.egg-info/entry_points.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatial_aim.egg-info/top_level.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/__main__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/aggregation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/compare_ks/run.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/compare_ks/selection.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/analysis/loading.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/README.md +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/_common.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/_segmentation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_01_mouse_ssp.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_02_colorectal_cancer.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_09_human_breast_cancer.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/curate_10_human_mtg.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/dump_retina_counts.R +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/curate_datasets/environment_retina_qs.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/validate/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/validate/common.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/validate/runner.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/validate/validate_pair.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/validate/validate_sc.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/validate/validate_segmentation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/data/validate/validate_st.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/common.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/headline.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/render/shape.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/validation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/choose_k.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/views/reference_tab.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/widgets/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/widgets/headline_plot.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/widgets/linked_plot.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/widgets/plotly_fit.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/gui/widgets/slider.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/mapping/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/mapping/base.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/mapping/confidence.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/mapping/nearest_centroid.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/mapping/reference.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/mapping/wann.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/metrics/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/metrics/cossim.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/metrics/modularity.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/metrics/shape_consistency.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/environment_dot.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/environment_tacco.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/environment_tangram.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/registry.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/run_dot.R +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/run_dot.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/run_tacco.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/reference_aligners/run_tangram.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/src/spatialaim/tree.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.4.0}/tests/test_registry.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatial-aim
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: SpatialAIM — annotation-independent mapping of scRNA-seq references onto high-resolution spatial transcriptomics
|
|
5
5
|
Author-email: Dominik Pysch <dominik.pysch@fau.de>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -705,7 +705,7 @@ Requires-Dist: umap-learn>=0.5
|
|
|
705
705
|
Requires-Dist: tifffile>=2024.8
|
|
706
706
|
Requires-Dist: zarr>=2.16
|
|
707
707
|
Requires-Dist: scikit-image>=0.22
|
|
708
|
-
Requires-Dist: streamlit>=1.
|
|
708
|
+
Requires-Dist: streamlit>=1.61
|
|
709
709
|
Requires-Dist: plotly>=5.20
|
|
710
710
|
Requires-Dist: kaleido>=0.2
|
|
711
711
|
Provides-Extra: data
|
|
@@ -747,8 +747,8 @@ The spot→state step is **modular**. In principle, any scRNA to ST alignment to
|
|
|
747
747
|
We implement two baseline mappers (`nearest_centroid`, `wann`) and three reference mappers (`tangram`, `tacco`, `dot`).
|
|
748
748
|
You are invited to add and try out your mapper of choice!
|
|
749
749
|
|
|
750
|
-
If you want to
|
|
751
|
-
`--
|
|
750
|
+
If you also want to start Step 1 from your own annotations,
|
|
751
|
+
`--annotation` runs the sweep a second time (once per annotation) with an existing annotation's `L` cell types as the start clusters.
|
|
752
752
|
|
|
753
753
|

|
|
754
754
|
|
|
@@ -864,8 +864,10 @@ spatialaim gui [--server_port 8501]
|
|
|
864
864
|
|
|
865
865
|
Open the printed URL (default http://localhost:8501), set the inputs, pick one or multiple mapper(s), and click **Run**.
|
|
866
866
|
As soon as both `.h5ad` paths are set, the GUI runs the same checks as [`spatialaim validate`](#validate-a-dataset-pair-spatialaim-validate) on that pair: a clean pair is confirmed with a tick in the sidebar, any error or warning is shown in a dialog you can close to continue anyway.
|
|
867
|
-
The GUI
|
|
868
|
-
|
|
867
|
+
The GUI always runs from the Leiden over-clustering; pick annotations under *Also start from annotations* to additionally start from them (the same as `--annotation`).
|
|
868
|
+
It writes the same layout as the CLI, `<output_dir>/<start>/<mapper>/`. The results are pages in a top navigation: **Overview** (a table of every starting point × mapper at its best overall K, sorted by the overall score; a selected row opens it in Explore), **Explore** (pick starting clusters, method and K in one control bar; switching start or method lands on that combination's best K), **Compare** (several methods of one starting point side by side, once two have finished) and **Single-cell reference**.
|
|
869
|
+
Once an output folder holds results, its linkage is fixed. Mappers and annotations can still be added: the next *Run* computes every missing starting point × mapper combination. Output folders written by earlier versions (`<output_dir>/<mapper>/`) can still be opened and viewed.
|
|
870
|
+
An optional **Segmentation path** (the ST slice's cell segmentation mask, see the sidebar's *Info*) is validated with the pair and passed to the runs; their Explore views then get a "Shape features" card (shape consistency and the cells' area / eccentricity / solidity per cell type), and the cell-type modal a "Shape features" view. Without it the GUI is unchanged.
|
|
869
871
|
|
|
870
872
|
### Run via CLI (`spatialaim run`)
|
|
871
873
|
|
|
@@ -881,10 +883,10 @@ The linkage of the agglomeration tree over the start clusters is chosen with `--
|
|
|
881
883
|
- **`average`** (default): UPGMA — average pairwise distance; no size term, tends to peel small tight groups off a growing dominant state.
|
|
882
884
|
- **`ward`**: Ward's criterion (R's `ward.D`); carries a size term and tends to produce balanced states.
|
|
883
885
|
|
|
884
|
-
The **start clusters** the tree is built over come from the Leiden over-clustering
|
|
885
|
-
Pass `--
|
|
886
|
-
and `K` sweeps from the number of annotated types down
|
|
887
|
-
|
|
886
|
+
The **start clusters** the tree is built over come from the Leiden over-clustering.
|
|
887
|
+
Pass `--annotation <obs_column> [<obs_column> ...]` to additionally start from pre-existing annotations: the sweep then runs once from the Leiden clusters
|
|
888
|
+
and once per annotation, whose cell types become the start clusters (`K` sweeps from the number of annotated types down).
|
|
889
|
+
Every annotation must label every cell; a missing column or an unlabelled cell is an error (in batch mode, that pair fails).
|
|
888
890
|
|
|
889
891
|
**Single pair**
|
|
890
892
|
|
|
@@ -895,7 +897,7 @@ spatialaim run --scdata path/to/sc.h5ad \
|
|
|
895
897
|
[--segmentation path/to/mask.tif] \
|
|
896
898
|
[--mapping nearest_centroid|wann|tangram|tacco|dot] \
|
|
897
899
|
[--linkage_method average|ward] \
|
|
898
|
-
[--
|
|
900
|
+
[--annotation <obs_column> ...] \
|
|
899
901
|
[--leiden_resolution 3.0] \
|
|
900
902
|
[--k_min 1] [--k_max <L>] [--k_step 1] \
|
|
901
903
|
[--logging verbose]
|
|
@@ -912,7 +914,7 @@ spatialaim run --pairs_csv path/to/pairs.csv \
|
|
|
912
914
|
--output_dir path/to/out_dir \
|
|
913
915
|
[--mapping nearest_centroid|wann|tangram|tacco|dot] \
|
|
914
916
|
[--linkage_method average|ward] \
|
|
915
|
-
[--
|
|
917
|
+
[--annotation <obs_column> ...] \
|
|
916
918
|
[--leiden_resolution 3.0] \
|
|
917
919
|
[--k_min 1] [--k_max <L>] [--k_step 1] \
|
|
918
920
|
[--logging verbose]
|
|
@@ -924,17 +926,18 @@ Each pair is written to `<out_dir>/<PairID>_<scName>__<stName>/`.
|
|
|
924
926
|
|
|
925
927
|
```
|
|
926
928
|
<out_dir>/
|
|
927
|
-
├── reference_scaffold.h5ad # cached reference preparation, shared by all mappers
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
├── start_clustering.h5ad # each reference cell's start cluster
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
929
|
+
├── reference_scaffold.h5ad # cached reference preparation, shared by all starts and mappers
|
|
930
|
+
├── cell_shape_features.csv # only with a segmentation mask: area, eccentricity, solidity per cell
|
|
931
|
+
└── <start>/ # leiden/, plus annotation_<obs_column>/ per --annotation
|
|
932
|
+
├── start_clustering.h5ad # each reference cell's start cluster (shared by the mappers)
|
|
933
|
+
└── <mapping>/ # one folder per mapper, e.g. nearest_centroid/
|
|
934
|
+
├── config.yaml # the run's settings (start_from_annotation: this start)
|
|
935
|
+
├── k_<kkk>/ # one folder per K
|
|
936
|
+
│ ├── spot_to_state_mapping_soft.h5ad # the mapping P (spots × K), plus confidence if the mapper has one
|
|
937
|
+
│ ├── start_cluster_to_state.csv # which state each start cluster belongs to
|
|
938
|
+
│ └── analysis/ # the metrics for this K (the GUI plots them)
|
|
939
|
+
├── k_comparison.csv # one row per K: all metrics and the K-selection scores
|
|
940
|
+
└── k_selection.json # the suggested K, overall and per criterion
|
|
938
941
|
```
|
|
939
942
|
|
|
940
943
|
**Sample-dataset example:**
|
|
@@ -950,7 +953,7 @@ spatialaim run \
|
|
|
950
953
|
|
|
951
954
|
### Annotation-based baseline
|
|
952
955
|
|
|
953
|
-
There is no separate command for it: `spatialaim run --
|
|
956
|
+
There is no separate command for it: `spatialaim run --annotation <obs_column>` covers it.
|
|
954
957
|
The annotated types become the start clusters, and the sweep's **`K` = number-of-types** level is the baseline.
|
|
955
958
|
|
|
956
959
|
## For developers
|
|
@@ -1012,7 +1015,7 @@ ReferenceAligner("<name>", "<name>_env", "spatialaim.reference_aligners.run_<nam
|
|
|
1012
1015
|
It is then selectable everywhere automatically:
|
|
1013
1016
|
|
|
1014
1017
|
- `spatialaim gui` (it will be selectable in the sidebar)
|
|
1015
|
-
- `spatialaim run --mapping <name>` (as an SpatialAIM reference mapper, one alignment per `K`) — including `--
|
|
1018
|
+
- `spatialaim run --mapping <name>` (as an SpatialAIM reference mapper, one alignment per `K`) — including the `--annotation` starts, where it maps onto a pre-existing annotation
|
|
1016
1019
|
|
|
1017
1020
|
**4. Create PR**
|
|
1018
1021
|
|
|
@@ -22,8 +22,8 @@ The spot→state step is **modular**. In principle, any scRNA to ST alignment to
|
|
|
22
22
|
We implement two baseline mappers (`nearest_centroid`, `wann`) and three reference mappers (`tangram`, `tacco`, `dot`).
|
|
23
23
|
You are invited to add and try out your mapper of choice!
|
|
24
24
|
|
|
25
|
-
If you want to
|
|
26
|
-
`--
|
|
25
|
+
If you also want to start Step 1 from your own annotations,
|
|
26
|
+
`--annotation` runs the sweep a second time (once per annotation) with an existing annotation's `L` cell types as the start clusters.
|
|
27
27
|
|
|
28
28
|

|
|
29
29
|
|
|
@@ -139,8 +139,10 @@ spatialaim gui [--server_port 8501]
|
|
|
139
139
|
|
|
140
140
|
Open the printed URL (default http://localhost:8501), set the inputs, pick one or multiple mapper(s), and click **Run**.
|
|
141
141
|
As soon as both `.h5ad` paths are set, the GUI runs the same checks as [`spatialaim validate`](#validate-a-dataset-pair-spatialaim-validate) on that pair: a clean pair is confirmed with a tick in the sidebar, any error or warning is shown in a dialog you can close to continue anyway.
|
|
142
|
-
The GUI
|
|
143
|
-
|
|
142
|
+
The GUI always runs from the Leiden over-clustering; pick annotations under *Also start from annotations* to additionally start from them (the same as `--annotation`).
|
|
143
|
+
It writes the same layout as the CLI, `<output_dir>/<start>/<mapper>/`. The results are pages in a top navigation: **Overview** (a table of every starting point × mapper at its best overall K, sorted by the overall score; a selected row opens it in Explore), **Explore** (pick starting clusters, method and K in one control bar; switching start or method lands on that combination's best K), **Compare** (several methods of one starting point side by side, once two have finished) and **Single-cell reference**.
|
|
144
|
+
Once an output folder holds results, its linkage is fixed. Mappers and annotations can still be added: the next *Run* computes every missing starting point × mapper combination. Output folders written by earlier versions (`<output_dir>/<mapper>/`) can still be opened and viewed.
|
|
145
|
+
An optional **Segmentation path** (the ST slice's cell segmentation mask, see the sidebar's *Info*) is validated with the pair and passed to the runs; their Explore views then get a "Shape features" card (shape consistency and the cells' area / eccentricity / solidity per cell type), and the cell-type modal a "Shape features" view. Without it the GUI is unchanged.
|
|
144
146
|
|
|
145
147
|
### Run via CLI (`spatialaim run`)
|
|
146
148
|
|
|
@@ -156,10 +158,10 @@ The linkage of the agglomeration tree over the start clusters is chosen with `--
|
|
|
156
158
|
- **`average`** (default): UPGMA — average pairwise distance; no size term, tends to peel small tight groups off a growing dominant state.
|
|
157
159
|
- **`ward`**: Ward's criterion (R's `ward.D`); carries a size term and tends to produce balanced states.
|
|
158
160
|
|
|
159
|
-
The **start clusters** the tree is built over come from the Leiden over-clustering
|
|
160
|
-
Pass `--
|
|
161
|
-
and `K` sweeps from the number of annotated types down
|
|
162
|
-
|
|
161
|
+
The **start clusters** the tree is built over come from the Leiden over-clustering.
|
|
162
|
+
Pass `--annotation <obs_column> [<obs_column> ...]` to additionally start from pre-existing annotations: the sweep then runs once from the Leiden clusters
|
|
163
|
+
and once per annotation, whose cell types become the start clusters (`K` sweeps from the number of annotated types down).
|
|
164
|
+
Every annotation must label every cell; a missing column or an unlabelled cell is an error (in batch mode, that pair fails).
|
|
163
165
|
|
|
164
166
|
**Single pair**
|
|
165
167
|
|
|
@@ -170,7 +172,7 @@ spatialaim run --scdata path/to/sc.h5ad \
|
|
|
170
172
|
[--segmentation path/to/mask.tif] \
|
|
171
173
|
[--mapping nearest_centroid|wann|tangram|tacco|dot] \
|
|
172
174
|
[--linkage_method average|ward] \
|
|
173
|
-
[--
|
|
175
|
+
[--annotation <obs_column> ...] \
|
|
174
176
|
[--leiden_resolution 3.0] \
|
|
175
177
|
[--k_min 1] [--k_max <L>] [--k_step 1] \
|
|
176
178
|
[--logging verbose]
|
|
@@ -187,7 +189,7 @@ spatialaim run --pairs_csv path/to/pairs.csv \
|
|
|
187
189
|
--output_dir path/to/out_dir \
|
|
188
190
|
[--mapping nearest_centroid|wann|tangram|tacco|dot] \
|
|
189
191
|
[--linkage_method average|ward] \
|
|
190
|
-
[--
|
|
192
|
+
[--annotation <obs_column> ...] \
|
|
191
193
|
[--leiden_resolution 3.0] \
|
|
192
194
|
[--k_min 1] [--k_max <L>] [--k_step 1] \
|
|
193
195
|
[--logging verbose]
|
|
@@ -199,17 +201,18 @@ Each pair is written to `<out_dir>/<PairID>_<scName>__<stName>/`.
|
|
|
199
201
|
|
|
200
202
|
```
|
|
201
203
|
<out_dir>/
|
|
202
|
-
├── reference_scaffold.h5ad # cached reference preparation, shared by all mappers
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
├── start_clustering.h5ad # each reference cell's start cluster
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
204
|
+
├── reference_scaffold.h5ad # cached reference preparation, shared by all starts and mappers
|
|
205
|
+
├── cell_shape_features.csv # only with a segmentation mask: area, eccentricity, solidity per cell
|
|
206
|
+
└── <start>/ # leiden/, plus annotation_<obs_column>/ per --annotation
|
|
207
|
+
├── start_clustering.h5ad # each reference cell's start cluster (shared by the mappers)
|
|
208
|
+
└── <mapping>/ # one folder per mapper, e.g. nearest_centroid/
|
|
209
|
+
├── config.yaml # the run's settings (start_from_annotation: this start)
|
|
210
|
+
├── k_<kkk>/ # one folder per K
|
|
211
|
+
│ ├── spot_to_state_mapping_soft.h5ad # the mapping P (spots × K), plus confidence if the mapper has one
|
|
212
|
+
│ ├── start_cluster_to_state.csv # which state each start cluster belongs to
|
|
213
|
+
│ └── analysis/ # the metrics for this K (the GUI plots them)
|
|
214
|
+
├── k_comparison.csv # one row per K: all metrics and the K-selection scores
|
|
215
|
+
└── k_selection.json # the suggested K, overall and per criterion
|
|
213
216
|
```
|
|
214
217
|
|
|
215
218
|
**Sample-dataset example:**
|
|
@@ -225,7 +228,7 @@ spatialaim run \
|
|
|
225
228
|
|
|
226
229
|
### Annotation-based baseline
|
|
227
230
|
|
|
228
|
-
There is no separate command for it: `spatialaim run --
|
|
231
|
+
There is no separate command for it: `spatialaim run --annotation <obs_column>` covers it.
|
|
229
232
|
The annotated types become the start clusters, and the sweep's **`K` = number-of-types** level is the baseline.
|
|
230
233
|
|
|
231
234
|
## For developers
|
|
@@ -287,7 +290,7 @@ ReferenceAligner("<name>", "<name>_env", "spatialaim.reference_aligners.run_<nam
|
|
|
287
290
|
It is then selectable everywhere automatically:
|
|
288
291
|
|
|
289
292
|
- `spatialaim gui` (it will be selectable in the sidebar)
|
|
290
|
-
- `spatialaim run --mapping <name>` (as an SpatialAIM reference mapper, one alignment per `K`) — including `--
|
|
293
|
+
- `spatialaim run --mapping <name>` (as an SpatialAIM reference mapper, one alignment per `K`) — including the `--annotation` starts, where it maps onto a pre-existing annotation
|
|
291
294
|
|
|
292
295
|
**4. Create PR**
|
|
293
296
|
|
|
@@ -27,7 +27,7 @@ dependencies:
|
|
|
27
27
|
# --- core (pip-only) ---
|
|
28
28
|
- igraph # modularity (metrics.modularity)
|
|
29
29
|
- leidenalg # Leiden over-clustering
|
|
30
|
-
- squidpy # spatial metrics (analysis.
|
|
30
|
+
- squidpy # spatial metrics (analysis.topology)
|
|
31
31
|
# --- GUI only ---
|
|
32
32
|
- streamlit
|
|
33
33
|
- plotly
|
|
@@ -48,7 +48,7 @@ dependencies = [
|
|
|
48
48
|
"zarr>=2.16", # reading large masks in bands
|
|
49
49
|
"scikit-image>=0.22", # shape-consistency metric (regionprops), rasterising masks
|
|
50
50
|
# GUI
|
|
51
|
-
"streamlit>=1.
|
|
51
|
+
"streamlit>=1.61", # persist_state (sidebar survives st.switch_page)
|
|
52
52
|
"plotly>=5.20",
|
|
53
53
|
"kaleido>=0.2"
|
|
54
54
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatial-aim
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: SpatialAIM — annotation-independent mapping of scRNA-seq references onto high-resolution spatial transcriptomics
|
|
5
5
|
Author-email: Dominik Pysch <dominik.pysch@fau.de>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -705,7 +705,7 @@ Requires-Dist: umap-learn>=0.5
|
|
|
705
705
|
Requires-Dist: tifffile>=2024.8
|
|
706
706
|
Requires-Dist: zarr>=2.16
|
|
707
707
|
Requires-Dist: scikit-image>=0.22
|
|
708
|
-
Requires-Dist: streamlit>=1.
|
|
708
|
+
Requires-Dist: streamlit>=1.61
|
|
709
709
|
Requires-Dist: plotly>=5.20
|
|
710
710
|
Requires-Dist: kaleido>=0.2
|
|
711
711
|
Provides-Extra: data
|
|
@@ -747,8 +747,8 @@ The spot→state step is **modular**. In principle, any scRNA to ST alignment to
|
|
|
747
747
|
We implement two baseline mappers (`nearest_centroid`, `wann`) and three reference mappers (`tangram`, `tacco`, `dot`).
|
|
748
748
|
You are invited to add and try out your mapper of choice!
|
|
749
749
|
|
|
750
|
-
If you want to
|
|
751
|
-
`--
|
|
750
|
+
If you also want to start Step 1 from your own annotations,
|
|
751
|
+
`--annotation` runs the sweep a second time (once per annotation) with an existing annotation's `L` cell types as the start clusters.
|
|
752
752
|
|
|
753
753
|

|
|
754
754
|
|
|
@@ -864,8 +864,10 @@ spatialaim gui [--server_port 8501]
|
|
|
864
864
|
|
|
865
865
|
Open the printed URL (default http://localhost:8501), set the inputs, pick one or multiple mapper(s), and click **Run**.
|
|
866
866
|
As soon as both `.h5ad` paths are set, the GUI runs the same checks as [`spatialaim validate`](#validate-a-dataset-pair-spatialaim-validate) on that pair: a clean pair is confirmed with a tick in the sidebar, any error or warning is shown in a dialog you can close to continue anyway.
|
|
867
|
-
The GUI
|
|
868
|
-
|
|
867
|
+
The GUI always runs from the Leiden over-clustering; pick annotations under *Also start from annotations* to additionally start from them (the same as `--annotation`).
|
|
868
|
+
It writes the same layout as the CLI, `<output_dir>/<start>/<mapper>/`. The results are pages in a top navigation: **Overview** (a table of every starting point × mapper at its best overall K, sorted by the overall score; a selected row opens it in Explore), **Explore** (pick starting clusters, method and K in one control bar; switching start or method lands on that combination's best K), **Compare** (several methods of one starting point side by side, once two have finished) and **Single-cell reference**.
|
|
869
|
+
Once an output folder holds results, its linkage is fixed. Mappers and annotations can still be added: the next *Run* computes every missing starting point × mapper combination. Output folders written by earlier versions (`<output_dir>/<mapper>/`) can still be opened and viewed.
|
|
870
|
+
An optional **Segmentation path** (the ST slice's cell segmentation mask, see the sidebar's *Info*) is validated with the pair and passed to the runs; their Explore views then get a "Shape features" card (shape consistency and the cells' area / eccentricity / solidity per cell type), and the cell-type modal a "Shape features" view. Without it the GUI is unchanged.
|
|
869
871
|
|
|
870
872
|
### Run via CLI (`spatialaim run`)
|
|
871
873
|
|
|
@@ -881,10 +883,10 @@ The linkage of the agglomeration tree over the start clusters is chosen with `--
|
|
|
881
883
|
- **`average`** (default): UPGMA — average pairwise distance; no size term, tends to peel small tight groups off a growing dominant state.
|
|
882
884
|
- **`ward`**: Ward's criterion (R's `ward.D`); carries a size term and tends to produce balanced states.
|
|
883
885
|
|
|
884
|
-
The **start clusters** the tree is built over come from the Leiden over-clustering
|
|
885
|
-
Pass `--
|
|
886
|
-
and `K` sweeps from the number of annotated types down
|
|
887
|
-
|
|
886
|
+
The **start clusters** the tree is built over come from the Leiden over-clustering.
|
|
887
|
+
Pass `--annotation <obs_column> [<obs_column> ...]` to additionally start from pre-existing annotations: the sweep then runs once from the Leiden clusters
|
|
888
|
+
and once per annotation, whose cell types become the start clusters (`K` sweeps from the number of annotated types down).
|
|
889
|
+
Every annotation must label every cell; a missing column or an unlabelled cell is an error (in batch mode, that pair fails).
|
|
888
890
|
|
|
889
891
|
**Single pair**
|
|
890
892
|
|
|
@@ -895,7 +897,7 @@ spatialaim run --scdata path/to/sc.h5ad \
|
|
|
895
897
|
[--segmentation path/to/mask.tif] \
|
|
896
898
|
[--mapping nearest_centroid|wann|tangram|tacco|dot] \
|
|
897
899
|
[--linkage_method average|ward] \
|
|
898
|
-
[--
|
|
900
|
+
[--annotation <obs_column> ...] \
|
|
899
901
|
[--leiden_resolution 3.0] \
|
|
900
902
|
[--k_min 1] [--k_max <L>] [--k_step 1] \
|
|
901
903
|
[--logging verbose]
|
|
@@ -912,7 +914,7 @@ spatialaim run --pairs_csv path/to/pairs.csv \
|
|
|
912
914
|
--output_dir path/to/out_dir \
|
|
913
915
|
[--mapping nearest_centroid|wann|tangram|tacco|dot] \
|
|
914
916
|
[--linkage_method average|ward] \
|
|
915
|
-
[--
|
|
917
|
+
[--annotation <obs_column> ...] \
|
|
916
918
|
[--leiden_resolution 3.0] \
|
|
917
919
|
[--k_min 1] [--k_max <L>] [--k_step 1] \
|
|
918
920
|
[--logging verbose]
|
|
@@ -924,17 +926,18 @@ Each pair is written to `<out_dir>/<PairID>_<scName>__<stName>/`.
|
|
|
924
926
|
|
|
925
927
|
```
|
|
926
928
|
<out_dir>/
|
|
927
|
-
├── reference_scaffold.h5ad # cached reference preparation, shared by all mappers
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
├── start_clustering.h5ad # each reference cell's start cluster
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
929
|
+
├── reference_scaffold.h5ad # cached reference preparation, shared by all starts and mappers
|
|
930
|
+
├── cell_shape_features.csv # only with a segmentation mask: area, eccentricity, solidity per cell
|
|
931
|
+
└── <start>/ # leiden/, plus annotation_<obs_column>/ per --annotation
|
|
932
|
+
├── start_clustering.h5ad # each reference cell's start cluster (shared by the mappers)
|
|
933
|
+
└── <mapping>/ # one folder per mapper, e.g. nearest_centroid/
|
|
934
|
+
├── config.yaml # the run's settings (start_from_annotation: this start)
|
|
935
|
+
├── k_<kkk>/ # one folder per K
|
|
936
|
+
│ ├── spot_to_state_mapping_soft.h5ad # the mapping P (spots × K), plus confidence if the mapper has one
|
|
937
|
+
│ ├── start_cluster_to_state.csv # which state each start cluster belongs to
|
|
938
|
+
│ └── analysis/ # the metrics for this K (the GUI plots them)
|
|
939
|
+
├── k_comparison.csv # one row per K: all metrics and the K-selection scores
|
|
940
|
+
└── k_selection.json # the suggested K, overall and per criterion
|
|
938
941
|
```
|
|
939
942
|
|
|
940
943
|
**Sample-dataset example:**
|
|
@@ -950,7 +953,7 @@ spatialaim run \
|
|
|
950
953
|
|
|
951
954
|
### Annotation-based baseline
|
|
952
955
|
|
|
953
|
-
There is no separate command for it: `spatialaim run --
|
|
956
|
+
There is no separate command for it: `spatialaim run --annotation <obs_column>` covers it.
|
|
954
957
|
The annotated types become the start clusters, and the sweep's **`K` = number-of-types** level is the baseline.
|
|
955
958
|
|
|
956
959
|
## For developers
|
|
@@ -1012,7 +1015,7 @@ ReferenceAligner("<name>", "<name>_env", "spatialaim.reference_aligners.run_<nam
|
|
|
1012
1015
|
It is then selectable everywhere automatically:
|
|
1013
1016
|
|
|
1014
1017
|
- `spatialaim gui` (it will be selectable in the sidebar)
|
|
1015
|
-
- `spatialaim run --mapping <name>` (as an SpatialAIM reference mapper, one alignment per `K`) — including `--
|
|
1018
|
+
- `spatialaim run --mapping <name>` (as an SpatialAIM reference mapper, one alignment per `K`) — including the `--annotation` starts, where it maps onto a pre-existing annotation
|
|
1016
1019
|
|
|
1017
1020
|
**4. Create PR**
|
|
1018
1021
|
|
|
@@ -39,7 +39,7 @@ src/spatialaim/analysis/loading.py
|
|
|
39
39
|
src/spatialaim/analysis/reconstruction.py
|
|
40
40
|
src/spatialaim/analysis/run.py
|
|
41
41
|
src/spatialaim/analysis/shape_consistency.py
|
|
42
|
-
src/spatialaim/analysis/
|
|
42
|
+
src/spatialaim/analysis/topology.py
|
|
43
43
|
src/spatialaim/analysis/compare_ks/__init__.py
|
|
44
44
|
src/spatialaim/analysis/compare_ks/collect.py
|
|
45
45
|
src/spatialaim/analysis/compare_ks/criteria.py
|
|
@@ -97,6 +97,8 @@ src/spatialaim/gui/views/choose_k.py
|
|
|
97
97
|
src/spatialaim/gui/views/compare_tab.py
|
|
98
98
|
src/spatialaim/gui/views/controls.py
|
|
99
99
|
src/spatialaim/gui/views/mapper_tab.py
|
|
100
|
+
src/spatialaim/gui/views/overview.py
|
|
101
|
+
src/spatialaim/gui/views/pages.py
|
|
100
102
|
src/spatialaim/gui/views/reference_tab.py
|
|
101
103
|
src/spatialaim/gui/views/report.py
|
|
102
104
|
src/spatialaim/gui/widgets/__init__.py
|
|
@@ -126,5 +128,8 @@ src/spatialaim/reference_aligners/run_tacco.py
|
|
|
126
128
|
src/spatialaim/reference_aligners/run_tangram.py
|
|
127
129
|
tests/test_cli.py
|
|
128
130
|
tests/test_gui_imports.py
|
|
131
|
+
tests/test_gui_overview.py
|
|
129
132
|
tests/test_registry.py
|
|
130
|
-
tests/test_sweep_sample.py
|
|
133
|
+
tests/test_sweep_sample.py
|
|
134
|
+
tests/test_topology.py
|
|
135
|
+
tests/test_utils.py
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"src/spatialaim/analysis/reconstruction.py",
|
|
33
33
|
"src/spatialaim/analysis/run.py",
|
|
34
34
|
"src/spatialaim/analysis/shape_consistency.py",
|
|
35
|
-
"src/spatialaim/analysis/
|
|
35
|
+
"src/spatialaim/analysis/topology.py",
|
|
36
36
|
"src/spatialaim/cli.py",
|
|
37
37
|
"src/spatialaim/clustering.py",
|
|
38
38
|
"src/spatialaim/config.py",
|
|
@@ -87,6 +87,8 @@
|
|
|
87
87
|
"src/spatialaim/gui/views/compare_tab.py",
|
|
88
88
|
"src/spatialaim/gui/views/controls.py",
|
|
89
89
|
"src/spatialaim/gui/views/mapper_tab.py",
|
|
90
|
+
"src/spatialaim/gui/views/overview.py",
|
|
91
|
+
"src/spatialaim/gui/views/pages.py",
|
|
90
92
|
"src/spatialaim/gui/views/reference_tab.py",
|
|
91
93
|
"src/spatialaim/gui/views/report.py",
|
|
92
94
|
"src/spatialaim/gui/widgets/__init__.py",
|
|
@@ -120,7 +122,10 @@
|
|
|
120
122
|
"src/spatialaim/utils.py",
|
|
121
123
|
"tests/test_cli.py",
|
|
122
124
|
"tests/test_gui_imports.py",
|
|
125
|
+
"tests/test_gui_overview.py",
|
|
123
126
|
"tests/test_registry.py",
|
|
124
|
-
"tests/test_sweep_sample.py"
|
|
127
|
+
"tests/test_sweep_sample.py",
|
|
128
|
+
"tests/test_topology.py",
|
|
129
|
+
"tests/test_utils.py"
|
|
125
130
|
]
|
|
126
131
|
}
|
|
@@ -8,9 +8,12 @@ Convention for the sc/st AnnData objects.
|
|
|
8
8
|
# -------------------- adata_sc --------------------
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
# (n_cells,) int — start-cluster label (0..L-1): the all-gene Leiden over-cluster, or the annotated type
|
|
11
|
+
# (n_cells,) int — start-cluster label (0..L-1) of the current start: the all-gene Leiden over-cluster, or the annotated type for an annotation start
|
|
12
12
|
OBS_START_CLUSTER = "start_cluster"
|
|
13
13
|
|
|
14
|
+
# (n_cells,) int — all-gene Leiden over-cluster label; part of the start-independent scaffold, copied into OBS_START_CLUSTER for the Leiden start
|
|
15
|
+
OBS_LEIDEN_ALL_GENES = "leiden_all_genes"
|
|
16
|
+
|
|
14
17
|
# (n_cells,) int — Leiden label from shared genes only
|
|
15
18
|
OBS_LEIDEN_SHARED_GENES = "leiden_shared_genes"
|
|
16
19
|
|
|
@@ -23,7 +26,7 @@ UNS_N_START_CLUSTERS = "n_start_clusters"
|
|
|
23
26
|
# list[str] — display name per start cluster, index-aligned to OBS_START_CLUSTER: the annotated type names, or "cluster_<i>" in Leiden mode
|
|
24
27
|
UNS_START_CLUSTER_NAMES = "start_cluster_names"
|
|
25
28
|
|
|
26
|
-
# float — resolution of the all-gene Leiden over-clustering
|
|
29
|
+
# float — resolution of the all-gene Leiden over-clustering
|
|
27
30
|
UNS_LEIDEN_RESOLUTION_ALL_GENES = "leiden_resolution"
|
|
28
31
|
|
|
29
32
|
# float — resolution (shared genes)
|
|
@@ -90,7 +93,7 @@ OBS_MAPPING_CONFIDENCE = "mapping_confidence"
|
|
|
90
93
|
|
|
91
94
|
# obsm/obsp/uns — K-independent spatial/expression graphs, built once and reused across the K-sweep
|
|
92
95
|
|
|
93
|
-
# (n_spots x n_spots) sparse — squidpy spatial KNN graph (
|
|
96
|
+
# (n_spots x n_spots) sparse — squidpy spatial KNN graph (the spatial assortativity)
|
|
94
97
|
OBSP_SPATIAL_CONNECTIVITIES = "spatial_connectivities"
|
|
95
98
|
|
|
96
99
|
# (n_spots x n_spots) sparse — ST all-gene expression KNN graph for the mapping modularity
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Transcriptional coherence of one K's mapping: modularities of the states on the
|
|
3
|
-
reference and ST expression graphs
|
|
3
|
+
reference and ST expression graphs.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
@@ -8,7 +8,6 @@ import json
|
|
|
8
8
|
import logging
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
import numpy as np
|
|
11
|
-
import pandas as pd
|
|
12
11
|
import scanpy as sc
|
|
13
12
|
from anndata import AnnData
|
|
14
13
|
from spatialaim.adata_schema import (
|
|
@@ -28,12 +27,9 @@ def analyse_modularities(
|
|
|
28
27
|
adata_st: AnnData,
|
|
29
28
|
output_data_dir: Path,
|
|
30
29
|
):
|
|
31
|
-
"""Write ``modularity_metrics.json
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
kNN graphs and on the ST expression kNN graph, plus per state the chance
|
|
35
|
-
level of its coherence (see :func:`_per_state_coherence`).
|
|
36
|
-
"""
|
|
30
|
+
"""Write ``modularity_metrics.json``: the modularity of the states on the
|
|
31
|
+
reference's all-gene and shared-gene kNN graphs and on the ST expression
|
|
32
|
+
kNN graph."""
|
|
37
33
|
cell_states = adata_sc.obs[OBS_COMPUTED_STATE].astype(int).to_numpy()
|
|
38
34
|
|
|
39
35
|
modularity_all = compute_modularity(adata_sc, cell_states)
|
|
@@ -41,7 +37,6 @@ def analyse_modularities(
|
|
|
41
37
|
adata_sc, cell_states, obsp_key=OBSP_CONNECTIVITIES_SHARED_GENES
|
|
42
38
|
)
|
|
43
39
|
modularity_st_expression = _spatial_expression_modularity(adata_st)
|
|
44
|
-
per_state = _per_state_coherence(adata_st, cell_states, output_data_dir)
|
|
45
40
|
|
|
46
41
|
with open(output_data_dir / "modularity_metrics.json", "w") as f:
|
|
47
42
|
json.dump(
|
|
@@ -49,7 +44,6 @@ def analyse_modularities(
|
|
|
49
44
|
"modularity_all": float(modularity_all),
|
|
50
45
|
"modularity_shared": float(modularity_shared),
|
|
51
46
|
"modularity_st_expression": float(modularity_st_expression),
|
|
52
|
-
"per_state": per_state,
|
|
53
47
|
},
|
|
54
48
|
f,
|
|
55
49
|
indent=4,
|
|
@@ -78,37 +72,3 @@ def _spatial_expression_modularity(adata_st: AnnData) -> float:
|
|
|
78
72
|
)
|
|
79
73
|
hard_labels = adata_st.obs[OBS_MAPPING_HARD].astype(int).to_numpy()
|
|
80
74
|
return compute_modularity(graph, hard_labels)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def _per_state_coherence(
|
|
84
|
-
adata_st: AnnData, cell_states: np.ndarray, output_data_dir: Path
|
|
85
|
-
) -> dict:
|
|
86
|
-
"""Per spot, the share of its ST-expression neighbours mapped to its own
|
|
87
|
-
state (written to ``coherence_per_spot.csv``). Returns per state its chance
|
|
88
|
-
level, the state's share of spots; every reference state gets an entry,
|
|
89
|
-
also one without spots."""
|
|
90
|
-
hard = adata_st.obs[OBS_MAPPING_HARD].astype(int).to_numpy()
|
|
91
|
-
share = _same_label_share(hard, adata_st.obsp[OBSP_ST_EXPR_CONNECTIVITIES])
|
|
92
|
-
pd.DataFrame({"id": adata_st.obs_names, "same_label_share": share}).to_csv(
|
|
93
|
-
output_data_dir / "coherence_per_spot.csv", index=False
|
|
94
|
-
)
|
|
95
|
-
return {
|
|
96
|
-
str(int(s)): {"chance": float(np.mean(hard == s))}
|
|
97
|
-
for s in np.union1d(np.unique(hard), np.unique(cell_states))
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def _same_label_share(labels: np.ndarray, connectivities) -> np.ndarray:
|
|
102
|
-
"""Per node, the share of its graph neighbours with its own label (NaN
|
|
103
|
-
without neighbours). Neighbours are the stored entries of its row, weights
|
|
104
|
-
ignored, itself excluded."""
|
|
105
|
-
A = connectivities.tocoo()
|
|
106
|
-
off = A.row != A.col
|
|
107
|
-
row, col = A.row[off], A.col[off]
|
|
108
|
-
n = A.shape[0]
|
|
109
|
-
same = np.bincount(
|
|
110
|
-
row, weights=(labels[row] == labels[col]).astype(np.float64), minlength=n
|
|
111
|
-
).astype(np.int64)
|
|
112
|
-
degree = np.bincount(row, minlength=n).astype(np.int64)
|
|
113
|
-
with np.errstate(divide="ignore", invalid="ignore"):
|
|
114
|
-
return np.where(degree > 0, same / degree, np.nan)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from .criteria import CRITERIA, CRITERION, NULL_SUFFIX, SCATTER_PAIRS, Criterion
|
|
2
2
|
from .run import compare_k_runs
|
|
3
|
-
from .scoring import harmonic_mean, overall,
|
|
3
|
+
from .scoring import curves, harmonic_mean, overall, score_table
|
|
4
4
|
from .selection import best_ks, pareto_mask
|
|
5
5
|
|
|
6
6
|
__all__ = [
|
|
@@ -11,9 +11,9 @@ __all__ = [
|
|
|
11
11
|
"Criterion",
|
|
12
12
|
"best_ks",
|
|
13
13
|
"compare_k_runs",
|
|
14
|
+
"curves",
|
|
14
15
|
"harmonic_mean",
|
|
15
16
|
"overall",
|
|
16
17
|
"pareto_mask",
|
|
17
|
-
"scaled_curves",
|
|
18
18
|
"score_table",
|
|
19
19
|
]
|