spatial-aim 1.5.2__tar.gz → 1.5.4__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.5.2 → spatial_aim-1.5.4}/PKG-INFO +1 -1
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/deploy/demo/Dockerfile +5 -2
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/deploy/demo/README.md +1 -1
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatial_aim.egg-info/PKG-INFO +1 -1
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatial_aim.egg-info/SOURCES.txt +5 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatial_aim.egg-info/scm_file_list.json +5 -0
- spatial_aim-1.5.4/src/spatial_aim.egg-info/scm_version.json +8 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/README.md +13 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/_segmentation.py +2 -1
- spatial_aim-1.5.4/src/spatialaim/data/curate_datasets/curate_11_human_crc.py +338 -0
- spatial_aim-1.5.4/src/spatialaim/data/curate_datasets/curate_12_human_ovarian_cancer.py +293 -0
- spatial_aim-1.5.4/src/spatialaim/data/curate_datasets/curate_13_human_carotid_plaque.py +205 -0
- spatial_aim-1.5.4/src/spatialaim/data/curate_datasets/curate_14_mouse_kidney_iri.py +242 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/app.py +6 -11
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/demo.py +17 -2
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/cell_type.py +50 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/common.py +3 -2
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/markers.py +26 -8
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/sidebar.py +13 -3
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/cell_type_modal.py +13 -12
- spatial_aim-1.5.4/src/spatialaim/gui/views/gene_modal.py +89 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/mapper_tab.py +72 -25
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/reference_tab.py +1 -1
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/widgets/headline_plot.py +53 -8
- spatial_aim-1.5.2/src/spatial_aim.egg-info/scm_version.json +0 -8
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/.dockerignore +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/.github/workflows/ci.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/.github/workflows/docker-demo.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/.github/workflows/release.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/.gitignore +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/.pre-commit-config.yaml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/LICENSE +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/README.md +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/deploy/demo/legal/imprint.md +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/deploy/demo/legal/privacy.md +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/docs/aim_gui.gif +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/docs/figure_2_1.png +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/environment.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/pyproject.toml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/renovate.json +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/sample_dataset/ST/index.csv +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/sample_dataset/ST/sample_st.h5ad +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/sample_dataset/pairs.csv +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/sample_dataset/scRNA/index.csv +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/sample_dataset/scRNA/sample_sc.h5ad +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/setup.cfg +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatial_aim.egg-info/dependency_links.txt +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatial_aim.egg-info/entry_points.txt +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatial_aim.egg-info/requires.txt +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatial_aim.egg-info/top_level.txt +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/__main__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/adata_schema.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/aggregation.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/coherence.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/compare_ks/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/compare_ks/collect.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/compare_ks/criteria.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/compare_ks/run.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/compare_ks/scoring.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/compare_ks/selection.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/loading.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/reconstruction.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/run.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/shape_consistency.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/analysis/topology.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/cli.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/clustering.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/config.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/_common.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_01_mouse_ssp.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_02_colorectal_cancer.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_03_mouse_liver.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_04_mouse_kidney.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_05_mouse_embryo.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_06_mouse_retina.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_07_mouse_mpfc.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_08_mouse_visual_cortex.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_09_human_breast_cancer.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/curate_10_human_mtg.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/dump_retina_counts.R +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/environment_retina_qs.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/validate/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/validate/common.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/validate/runner.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/validate/validate_pair.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/validate/validate_sc.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/validate/validate_segmentation.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/validate/validate_st.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/__main__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/compute.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/data_access.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/loaders.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/headline.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/ksweep.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/report.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/scatter.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/render/shape.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/scaffold.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/state_names.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/texts.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/validation.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/cards.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/choose_k.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/compare_tab.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/controls.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/overview.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/pages.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/views/report.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/widgets/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/widgets/linked_plot.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/widgets/plotly_fit.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/gui/widgets/slider.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/io.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/mapping/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/mapping/base.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/mapping/confidence.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/mapping/nearest_centroid.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/mapping/reference.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/mapping/wann.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/metrics/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/metrics/cossim.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/metrics/modularity.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/metrics/shape_consistency.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/metrics/topology.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/__init__.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/environment_dot.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/environment_tacco.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/environment_tangram.yml +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/registry.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/run_dot.R +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/run_dot.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/run_tacco.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/reference_aligners/run_tangram.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/sweep.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/timing.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/tree.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/utils.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/tests/test_cli.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/tests/test_gui_imports.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/tests/test_gui_overview.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/tests/test_registry.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/tests/test_sweep_sample.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/tests/test_topology.py +0 -0
- {spatial_aim-1.5.2 → spatial_aim-1.5.4}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatial-aim
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.4
|
|
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
|
|
@@ -36,8 +36,11 @@ COPY deploy/demo/legal ./legal
|
|
|
36
36
|
|
|
37
37
|
RUN useradd --create-home --uid 10001 spatialaim
|
|
38
38
|
USER spatialaim
|
|
39
|
-
#
|
|
40
|
-
|
|
39
|
+
# The container runs read-only with only /tmp writable: numba (via scanpy/umap)
|
|
40
|
+
# caches compiled code next to the sources by default, and anything else that
|
|
41
|
+
# writes to the home folder (~/.streamlit, ~/.cache) lands in /tmp too.
|
|
42
|
+
ENV HOME=/tmp \
|
|
43
|
+
NUMBA_CACHE_DIR=/tmp/numba \
|
|
41
44
|
MPLCONFIGDIR=/tmp/matplotlib
|
|
42
45
|
|
|
43
46
|
EXPOSE 8501
|
|
@@ -68,7 +68,7 @@ workflow run). The pages are linked from the sidebar footer on every page (`/imp
|
|
|
68
68
|
## 4. Run
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
docker run -d --name spatialaim-demo --restart unless-stopped -p 127.0.0.1:8501:8501 -v /
|
|
71
|
+
docker run -d --name spatialaim-demo --restart unless-stopped -p 127.0.0.1:8501:8501 -v /testmount2/zi69hebi/spatialaim-demo/data:/data:ro --read-only --tmpfs /tmp --memory 16g --cpus 4 ghcr.io/domipysch/spatialaim-demo:latest
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
The container serves plain HTTP on port 8501; `127.0.0.1:` keeps it reachable only for the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatial-aim
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.4
|
|
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
|
|
@@ -68,6 +68,10 @@ src/spatialaim/data/curate_datasets/curate_07_mouse_mpfc.py
|
|
|
68
68
|
src/spatialaim/data/curate_datasets/curate_08_mouse_visual_cortex.py
|
|
69
69
|
src/spatialaim/data/curate_datasets/curate_09_human_breast_cancer.py
|
|
70
70
|
src/spatialaim/data/curate_datasets/curate_10_human_mtg.py
|
|
71
|
+
src/spatialaim/data/curate_datasets/curate_11_human_crc.py
|
|
72
|
+
src/spatialaim/data/curate_datasets/curate_12_human_ovarian_cancer.py
|
|
73
|
+
src/spatialaim/data/curate_datasets/curate_13_human_carotid_plaque.py
|
|
74
|
+
src/spatialaim/data/curate_datasets/curate_14_mouse_kidney_iri.py
|
|
71
75
|
src/spatialaim/data/curate_datasets/dump_retina_counts.R
|
|
72
76
|
src/spatialaim/data/curate_datasets/environment_retina_qs.yml
|
|
73
77
|
src/spatialaim/data/validate/__init__.py
|
|
@@ -104,6 +108,7 @@ src/spatialaim/gui/views/cell_type_modal.py
|
|
|
104
108
|
src/spatialaim/gui/views/choose_k.py
|
|
105
109
|
src/spatialaim/gui/views/compare_tab.py
|
|
106
110
|
src/spatialaim/gui/views/controls.py
|
|
111
|
+
src/spatialaim/gui/views/gene_modal.py
|
|
107
112
|
src/spatialaim/gui/views/mapper_tab.py
|
|
108
113
|
src/spatialaim/gui/views/overview.py
|
|
109
114
|
src/spatialaim/gui/views/pages.py
|
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
"src/spatialaim/data/curate_datasets/curate_08_mouse_visual_cortex.py",
|
|
58
58
|
"src/spatialaim/data/curate_datasets/curate_09_human_breast_cancer.py",
|
|
59
59
|
"src/spatialaim/data/curate_datasets/curate_10_human_mtg.py",
|
|
60
|
+
"src/spatialaim/data/curate_datasets/curate_11_human_crc.py",
|
|
61
|
+
"src/spatialaim/data/curate_datasets/curate_12_human_ovarian_cancer.py",
|
|
62
|
+
"src/spatialaim/data/curate_datasets/curate_13_human_carotid_plaque.py",
|
|
63
|
+
"src/spatialaim/data/curate_datasets/curate_14_mouse_kidney_iri.py",
|
|
60
64
|
"src/spatialaim/data/curate_datasets/dump_retina_counts.R",
|
|
61
65
|
"src/spatialaim/data/curate_datasets/environment_retina_qs.yml",
|
|
62
66
|
"src/spatialaim/data/validate/__init__.py",
|
|
@@ -93,6 +97,7 @@
|
|
|
93
97
|
"src/spatialaim/gui/views/choose_k.py",
|
|
94
98
|
"src/spatialaim/gui/views/compare_tab.py",
|
|
95
99
|
"src/spatialaim/gui/views/controls.py",
|
|
100
|
+
"src/spatialaim/gui/views/gene_modal.py",
|
|
96
101
|
"src/spatialaim/gui/views/mapper_tab.py",
|
|
97
102
|
"src/spatialaim/gui/views/overview.py",
|
|
98
103
|
"src/spatialaim/gui/views/pages.py",
|
|
@@ -12,3 +12,16 @@ Only minor pre-processing (deleting near-empty columns etc.) has been applied.
|
|
|
12
12
|
No normalization or log operations are applied to the data, as we are working on raw counts.
|
|
13
13
|
|
|
14
14
|
These 10 script are fully generated by AI (Claude Opus 5.5).
|
|
15
|
+
|
|
16
|
+
## GUI use-case candidates (11-14)
|
|
17
|
+
|
|
18
|
+
`curate_11` to `curate_14` build candidate pairs for the GUI section (scRNA + imaging-based ST, all
|
|
19
|
+
Xenium with segmentation masks). They write to `Data/03_GUI`, not to `01_Datasets_Paper`, and are
|
|
20
|
+
not part of Experiment 1.
|
|
21
|
+
|
|
22
|
+
| Script | Pair(s) | Sources |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| `curate_11_human_crc.py` | `11_human-crc-p2`, `11_human-crc-p5` | Oliveira et al. 2025, Flex + 10x Xenium |
|
|
25
|
+
| `curate_12_human_ovarian_cancer.py` | `12_human-ovarian-cancer` (3 x 3 mm crop) | 10x Flex + Xenium Prime 5K |
|
|
26
|
+
| `curate_13_human_carotid_plaque.py` | `13_human-carotid-plaque` | Nat Commun 2025, Zenodo scRNA + GEO Xenium |
|
|
27
|
+
| `curate_14_mouse_kidney_iri.py` | `14_mouse-kidney-iri` | Kirita et al. 2020 snRNA + Humphreys lab Xenium |
|
{spatial_aim-1.5.2 → spatial_aim-1.5.4}/src/spatialaim/data/curate_datasets/_segmentation.py
RENAMED
|
@@ -300,7 +300,8 @@ def extract_remote_zip_members(
|
|
|
300
300
|
info = next(
|
|
301
301
|
i
|
|
302
302
|
for i in archive.infolist()
|
|
303
|
-
if i.filename.endswith("/" + name)
|
|
303
|
+
if (i.filename == name or i.filename.endswith("/" + name))
|
|
304
|
+
and "__MACOSX" not in i.filename
|
|
304
305
|
)
|
|
305
306
|
logger.info(
|
|
306
307
|
" extract %s (%.0f MB compressed) from %s",
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Build dataset 11_human-crc: two patient-matched pairs (P2, P5), each a Flex
|
|
3
|
+
reference + one Xenium slice, for the GUI use case (Results section 5). Not part
|
|
4
|
+
of the Experiment 1 corpus, so it is written to Data/03_GUI by default, not to
|
|
5
|
+
01_Datasets_Paper.
|
|
6
|
+
|
|
7
|
+
Pairs covered (one per patient, same_paper):
|
|
8
|
+
11_human-crc-p2 <-> 11_human-crc-p2
|
|
9
|
+
11_human-crc-p5 <-> 11_human-crc-p5
|
|
10
|
+
|
|
11
|
+
Paper: Oliveira et al., Nature Genetics 2025, "High-definition spatial
|
|
12
|
+
transcriptomic profiling of immune cell populations in colorectal cancer"
|
|
13
|
+
(https://doi.org/10.1038/s41588-025-02193-3; GEO SuperSeries GSE280318). Per
|
|
14
|
+
patient, both sides come from one FFPE block: the Flex reference was dissociated
|
|
15
|
+
from curls serial to the sections the spatial assays used.
|
|
16
|
+
|
|
17
|
+
Downloads per patient: four Flex libraries, the authors' metadata and three
|
|
18
|
+
Xenium files (P2 ~460 MB, P5 ~330 MB; the segmentation is most of it).
|
|
19
|
+
|
|
20
|
+
------------------------------------------------------------------------------
|
|
21
|
+
scRNA 11_human-crc-p{2,5}.h5ad — Chromium Flex
|
|
22
|
+
------------------------------------------------------------------------------
|
|
23
|
+
counts GSE280311 (Flex). Each patient is one probe barcode in four
|
|
24
|
+
libraries: P2CRC = BC1 in pool 1 (GSM8594533..36, *_P1L{1..4}_*),
|
|
25
|
+
P5CRC = BC3 in pool 2 (GSM8594537..40, *_P2L{1..4}_*);
|
|
26
|
+
files *_count_filtered_feature_bc_matrix.h5
|
|
27
|
+
annotation github.com/10XGenomics/HumanColonCancer_VisiumHD,
|
|
28
|
+
MetaData/SingleCell_MetaData.csv.gz (all 8 Flex samples)
|
|
29
|
+
|
|
30
|
+
The authors' barcodes carry the cellranger-aggr index as suffix (pool 1: two
|
|
31
|
+
samples per library, pool 2: four), so P2CRC's libraries are aggr samples
|
|
32
|
+
1, 3, 5, 7 and P5CRC's 11, 15, 19, 23. A patient's barcodes match its four
|
|
33
|
+
matrices one to one; the authors' QC (``QCFilter == "Keep"``) selects the cells,
|
|
34
|
+
kept in metadata order: P2 41933 -> 35673, P5 24615 -> 23823.
|
|
35
|
+
|
|
36
|
+
Curation:
|
|
37
|
+
* obs index = the authors' ``Barcode``; ``Level1`` and ``Level2`` verbatim.
|
|
38
|
+
Level2 was sub-clustered within Level1 on a 15 % sketch and then
|
|
39
|
+
extended to all cells, so it is only mostly nested (P2: 3.8 % of
|
|
40
|
+
cells sit outside their Level2's main Level1); kept as published.
|
|
41
|
+
* X = the four matrices' columns for those barcodes, float32
|
|
42
|
+
* var index = gene symbols uppercased; three symbols occur twice and are
|
|
43
|
+
summed onto the first occurrence, 18082 -> 18079
|
|
44
|
+
|
|
45
|
+
------------------------------------------------------------------------------
|
|
46
|
+
ST 11_human-crc-p{2,5}.h5ad — Xenium, 422 genes (colon panel + 100 add-on)
|
|
47
|
+
------------------------------------------------------------------------------
|
|
48
|
+
https://cf.10xgenomics.com/samples/xenium/2.0.0/
|
|
49
|
+
Xenium_V1_Human_Colon_Cancer_P{2,5}_CRC_Add_on_FFPE/ (the GSE280314 samples)
|
|
50
|
+
..._cell_feature_matrix.h5, ..._cells.csv.gz, ..._cells.zarr.zip
|
|
51
|
+
|
|
52
|
+
The full outs bundles (14-16 GB) are unnecessary. The authors' repo lists ~1.1M
|
|
53
|
+
cells per slide for a larger Xenium region; the public 10x releases used here
|
|
54
|
+
have P2 340837 and P5 275998 cells and carry no cell-type labels.
|
|
55
|
+
|
|
56
|
+
Curation:
|
|
57
|
+
* cells in the Xenium output's own order; obs index = Xenium ``cell_id``
|
|
58
|
+
* cells with fewer than 10 transcripts over the 422 genes are dropped
|
|
59
|
+
(P2 340837 -> 331383, P5 275998 -> 270956): mapped, they form
|
|
60
|
+
spurious states of near-empty cells
|
|
61
|
+
* X = the 422 ``Gene Expression`` features; unassigned / negative control
|
|
62
|
+
codewords and probes are dropped
|
|
63
|
+
* var index = the feature names uppercased
|
|
64
|
+
* obsm["spatial"] = ``x_centroid``, ``y_centroid`` (um), float32
|
|
65
|
+
* no cell-type column: the paper annotated Visium HD bins, not Xenium cells
|
|
66
|
+
* obs["segmentation_id"], uns["segmentation_pixel_size_um"] = 0.2125 and the
|
|
67
|
+
mask ST/Segmentation/<name>.tif: cells.zarr.zip masks/1, copied as
|
|
68
|
+
is. Its labels are the row of the zarr ``cell_id`` array plus one,
|
|
69
|
+
which is the cells.csv order, so segmentation_id = that row + 1
|
|
70
|
+
(the dropped cells' labels stay in the mask). Xenium 2.0
|
|
71
|
+
multimodal segmentation (boundary stain, then interior stain, then
|
|
72
|
+
5 um nucleus expansion).
|
|
73
|
+
|
|
74
|
+
------------------------------------------------------------------------------
|
|
75
|
+
Usage
|
|
76
|
+
------------------------------------------------------------------------------
|
|
77
|
+
python -m spatialaim.data.curate_datasets.curate_11_human_crc
|
|
78
|
+
python -m spatialaim.data.curate_datasets.curate_11_human_crc --out-dir <root>
|
|
79
|
+
|
|
80
|
+
Sources are downloaded to a temporary folder below --out-dir and deleted again.
|
|
81
|
+
Set SPATIALAIM_KEEP_DOWNLOADS=1 to keep (and on a re-run reuse) them in
|
|
82
|
+
<out-dir>/_downloads/11_human-crc-p{2,5} instead. The 4-5 GB masks are copied
|
|
83
|
+
band by band, never held whole.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
import logging
|
|
87
|
+
from dataclasses import dataclass
|
|
88
|
+
from pathlib import Path
|
|
89
|
+
from typing import Any
|
|
90
|
+
|
|
91
|
+
import anndata as ad
|
|
92
|
+
import numpy as np
|
|
93
|
+
import pandas as pd
|
|
94
|
+
from scipy.sparse import hstack
|
|
95
|
+
|
|
96
|
+
from . import _common, _segmentation
|
|
97
|
+
from .curate_09_human_breast_cancer import (
|
|
98
|
+
GENE_EXPRESSION,
|
|
99
|
+
MASK_PIXEL_UM,
|
|
100
|
+
_check_shape,
|
|
101
|
+
_copy_cell_mask,
|
|
102
|
+
_fold_duplicates,
|
|
103
|
+
_read_10x_h5,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
logger = logging.getLogger(__name__)
|
|
107
|
+
|
|
108
|
+
OUT_ROOT = _common.DATA_ROOT / "03_GUI"
|
|
109
|
+
|
|
110
|
+
GEO_SAMPLES = "https://ftp.ncbi.nlm.nih.gov/geo/samples/GSM8594nnn"
|
|
111
|
+
REPO = "https://raw.githubusercontent.com/10XGenomics/HumanColonCancer_VisiumHD/main"
|
|
112
|
+
SC_META_URL = f"{REPO}/MetaData/SingleCell_MetaData.csv.gz"
|
|
113
|
+
SC_META_BYTES = 7_288_481
|
|
114
|
+
XENIUM = "https://cf.10xgenomics.com/samples/xenium/2.0.0"
|
|
115
|
+
SC_GENES = 18079
|
|
116
|
+
ST_GENES = 422
|
|
117
|
+
MIN_TRANSCRIPTS = 10
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@dataclass(frozen=True)
|
|
121
|
+
class Patient:
|
|
122
|
+
patient: str # the metadata's Patient value, e.g. "P5CRC"
|
|
123
|
+
probe_barcode: str
|
|
124
|
+
# (GSM, library, aggr index of this patient in the authors' barcodes, bytes)
|
|
125
|
+
libraries: tuple[tuple[str, str, int, int], ...]
|
|
126
|
+
n_cells: int
|
|
127
|
+
n_spots: int # all Xenium cells
|
|
128
|
+
n_spots_kept: int # with >= MIN_TRANSCRIPTS
|
|
129
|
+
# bytes of cell_feature_matrix.h5, cells.csv.gz, cells.zarr.zip
|
|
130
|
+
xenium_bytes: tuple[int, int, int]
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def name(self) -> str:
|
|
134
|
+
return f"11_human-crc-{self.patient[:2].lower()}"
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def xenium_prefix(self) -> str:
|
|
138
|
+
sample = f"Xenium_V1_Human_Colon_Cancer_{self.patient[:2]}_CRC_Add_on_FFPE"
|
|
139
|
+
return f"{XENIUM}/{sample}/{sample}"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
PATIENTS = (
|
|
143
|
+
Patient(
|
|
144
|
+
patient="P2CRC",
|
|
145
|
+
probe_barcode="BC1",
|
|
146
|
+
libraries=(
|
|
147
|
+
("GSM8594533", "P1L1", 1, 26_874_789),
|
|
148
|
+
("GSM8594534", "P1L2", 3, 27_306_204),
|
|
149
|
+
("GSM8594535", "P1L3", 5, 27_294_024),
|
|
150
|
+
("GSM8594536", "P1L4", 7, 26_361_551),
|
|
151
|
+
),
|
|
152
|
+
n_cells=35673,
|
|
153
|
+
n_spots=340837,
|
|
154
|
+
n_spots_kept=331383,
|
|
155
|
+
xenium_bytes=(21_438_841, 18_562_765, 291_928_061),
|
|
156
|
+
),
|
|
157
|
+
Patient(
|
|
158
|
+
patient="P5CRC",
|
|
159
|
+
probe_barcode="BC3",
|
|
160
|
+
libraries=(
|
|
161
|
+
("GSM8594537", "P2L1", 11, 9_062_161),
|
|
162
|
+
("GSM8594538", "P2L2", 15, 9_081_608),
|
|
163
|
+
("GSM8594539", "P2L3", 19, 9_784_770),
|
|
164
|
+
("GSM8594540", "P2L4", 23, 9_630_123),
|
|
165
|
+
),
|
|
166
|
+
n_cells=23823,
|
|
167
|
+
n_spots=275998,
|
|
168
|
+
n_spots_kept=270956,
|
|
169
|
+
xenium_bytes=(15_479_659, 14_803_142, 248_276_261),
|
|
170
|
+
),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# --------------------------------------------------------------------------- #
|
|
175
|
+
# scRNA
|
|
176
|
+
# --------------------------------------------------------------------------- #
|
|
177
|
+
def build_scrna(p: Patient, tmp_dir: Path, out_path: Path) -> None:
|
|
178
|
+
logger.info("scRNA %s — Chromium Flex, patient %s (GSE280311)", p.name, p.patient)
|
|
179
|
+
meta_file = _common.download(
|
|
180
|
+
SC_META_URL,
|
|
181
|
+
tmp_dir / "SingleCell_MetaData.csv.gz",
|
|
182
|
+
expected_bytes=SC_META_BYTES,
|
|
183
|
+
)
|
|
184
|
+
meta = pd.read_csv(meta_file)
|
|
185
|
+
meta = meta[meta["Patient"] == p.patient]
|
|
186
|
+
logger.info(" read metadata (%d %s barcodes)", len(meta), p.patient)
|
|
187
|
+
|
|
188
|
+
blocks = []
|
|
189
|
+
barcodes: list[str] = []
|
|
190
|
+
names: np.ndarray | None = None
|
|
191
|
+
for gsm, library, aggr, size in p.libraries:
|
|
192
|
+
file_name = (
|
|
193
|
+
f"{gsm}_{library}_{p.patient}_{p.probe_barcode}"
|
|
194
|
+
"_count_filtered_feature_bc_matrix.h5"
|
|
195
|
+
)
|
|
196
|
+
path = _common.download(
|
|
197
|
+
f"{GEO_SAMPLES}/{gsm}/suppl/{file_name}",
|
|
198
|
+
tmp_dir / file_name,
|
|
199
|
+
expected_bytes=size,
|
|
200
|
+
)
|
|
201
|
+
matrix, library_barcodes, library_names, _ = _read_10x_h5(path)
|
|
202
|
+
if names is not None and not np.array_equal(names, library_names):
|
|
203
|
+
raise ValueError(f"{file_name}: gene list differs from the first library")
|
|
204
|
+
names = library_names
|
|
205
|
+
blocks.append(matrix)
|
|
206
|
+
barcodes.extend(b.split("-")[0] + f"-{aggr}" for b in library_barcodes)
|
|
207
|
+
if names is None:
|
|
208
|
+
raise ValueError(f"{p.patient}: no libraries listed")
|
|
209
|
+
matrix = hstack(blocks).tocsc()
|
|
210
|
+
logger.info(" read %d libraries (%d x %d)", len(blocks), *matrix.shape)
|
|
211
|
+
|
|
212
|
+
if set(barcodes) != set(meta["Barcode"]):
|
|
213
|
+
raise ValueError("the four libraries no longer match the metadata's barcodes")
|
|
214
|
+
meta = meta[meta["QCFilter"] == "Keep"]
|
|
215
|
+
position = pd.Index(barcodes).get_indexer(meta["Barcode"].to_numpy())
|
|
216
|
+
|
|
217
|
+
X = matrix[:, position].T.tocsr().astype(np.float32)
|
|
218
|
+
X, genes = _fold_duplicates(X, np.asarray(_common.uppercase(names)))
|
|
219
|
+
logger.info(" genes %d -> %d (duplicate symbols summed)", len(names), len(genes))
|
|
220
|
+
|
|
221
|
+
adata = ad.AnnData(
|
|
222
|
+
X=X,
|
|
223
|
+
obs=pd.DataFrame(
|
|
224
|
+
{
|
|
225
|
+
level: pd.Categorical(meta[level].astype(str).to_numpy())
|
|
226
|
+
for level in ("Level1", "Level2")
|
|
227
|
+
},
|
|
228
|
+
index=pd.Index(meta["Barcode"].to_numpy(), name=None),
|
|
229
|
+
),
|
|
230
|
+
var=pd.DataFrame(index=pd.Index(genes, name=None)),
|
|
231
|
+
)
|
|
232
|
+
_check_shape(adata, (p.n_cells, SC_GENES), "scRNA")
|
|
233
|
+
for level in ("Level1", "Level2"):
|
|
234
|
+
logger.info(" %s: %d types", level, adata.obs[level].cat.categories.size)
|
|
235
|
+
_common.write(adata, out_path)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# --------------------------------------------------------------------------- #
|
|
239
|
+
# ST
|
|
240
|
+
# --------------------------------------------------------------------------- #
|
|
241
|
+
def build_st(p: Patient, tmp_dir: Path, st_dir: Path) -> None:
|
|
242
|
+
logger.info(
|
|
243
|
+
"ST %s — Xenium human colon cancer %s (GSE280314)", p.name, p.patient[:2]
|
|
244
|
+
)
|
|
245
|
+
tag = f"Xenium_{p.patient[:2]}"
|
|
246
|
+
counts_bytes, cells_bytes, masks_bytes = p.xenium_bytes
|
|
247
|
+
counts_file = _common.download(
|
|
248
|
+
f"{p.xenium_prefix}_cell_feature_matrix.h5",
|
|
249
|
+
tmp_dir / f"{tag}_cell_feature_matrix.h5",
|
|
250
|
+
expected_bytes=counts_bytes,
|
|
251
|
+
)
|
|
252
|
+
cells_file = _common.download(
|
|
253
|
+
f"{p.xenium_prefix}_cells.csv.gz",
|
|
254
|
+
tmp_dir / f"{tag}_cells.csv.gz",
|
|
255
|
+
expected_bytes=cells_bytes,
|
|
256
|
+
)
|
|
257
|
+
masks_file = _common.download(
|
|
258
|
+
f"{p.xenium_prefix}_cells.zarr.zip",
|
|
259
|
+
tmp_dir / f"{tag}_cells.zarr.zip",
|
|
260
|
+
expected_bytes=masks_bytes,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
matrix, barcodes, names, types = _read_10x_h5(counts_file)
|
|
264
|
+
genes = types == GENE_EXPRESSION
|
|
265
|
+
logger.info(
|
|
266
|
+
" read matrix (%d x %d, %d gene features)", *matrix.shape, int(genes.sum())
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
cells = pd.read_csv(cells_file)
|
|
270
|
+
if not np.array_equal(cells["cell_id"].astype(str).to_numpy(), barcodes):
|
|
271
|
+
raise ValueError("cells.csv.gz and the matrix no longer share a cell order")
|
|
272
|
+
|
|
273
|
+
adata = ad.AnnData(
|
|
274
|
+
X=matrix[genes].T.tocsr().astype(np.float32),
|
|
275
|
+
obs=pd.DataFrame(index=pd.Index(barcodes, name=None)),
|
|
276
|
+
var=pd.DataFrame(index=pd.Index(_common.uppercase(names[genes]), name=None)),
|
|
277
|
+
)
|
|
278
|
+
adata.obsm["spatial"] = np.column_stack(
|
|
279
|
+
[cells["x_centroid"].to_numpy(), cells["y_centroid"].to_numpy()]
|
|
280
|
+
).astype(np.float32)
|
|
281
|
+
_check_shape(adata, (p.n_spots, ST_GENES), "ST")
|
|
282
|
+
|
|
283
|
+
_check_mask_order(masks_file, barcodes)
|
|
284
|
+
_copy_cell_mask(masks_file, _segmentation.mask_path(st_dir, p.name), adata.n_obs)
|
|
285
|
+
_segmentation.annotate(adata, np.arange(1, adata.n_obs + 1), MASK_PIXEL_UM)
|
|
286
|
+
|
|
287
|
+
keep = np.asarray(adata.X.sum(axis=1)).ravel() >= MIN_TRANSCRIPTS
|
|
288
|
+
adata = adata[keep].copy()
|
|
289
|
+
logger.info(
|
|
290
|
+
" cells %d -> %d (>= %d transcripts)",
|
|
291
|
+
len(keep),
|
|
292
|
+
adata.n_obs,
|
|
293
|
+
MIN_TRANSCRIPTS,
|
|
294
|
+
)
|
|
295
|
+
_check_shape(adata, (p.n_spots_kept, ST_GENES), "ST")
|
|
296
|
+
_common.write(adata, st_dir / f"{p.name}.h5ad")
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _check_mask_order(zarr_zip: Path, barcodes: np.ndarray) -> None:
|
|
300
|
+
"""Mask label i+1 is the zarr's cell_id row i; assert that row order = ours."""
|
|
301
|
+
import zarr
|
|
302
|
+
|
|
303
|
+
group: Any = zarr.open_group(
|
|
304
|
+
zarr.storage.ZipStore(str(zarr_zip), mode="r"), mode="r"
|
|
305
|
+
)
|
|
306
|
+
rows = np.asarray(group["cell_id"][:])
|
|
307
|
+
# Xenium string ids: the prefix integer in base 16 written with letters a..p
|
|
308
|
+
decoded = np.array(
|
|
309
|
+
[
|
|
310
|
+
[int(prefix.translate(_HEX_LETTERS), 16), int(suffix)]
|
|
311
|
+
for prefix, suffix in (b.split("-") for b in barcodes)
|
|
312
|
+
],
|
|
313
|
+
dtype=rows.dtype,
|
|
314
|
+
)
|
|
315
|
+
if not np.array_equal(decoded, rows):
|
|
316
|
+
raise ValueError("the mask's cell_id rows no longer follow the cells.csv order")
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
_HEX_LETTERS = str.maketrans("abcdefghijklmnop", "0123456789abcdef")
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
# --------------------------------------------------------------------------- #
|
|
323
|
+
def main() -> None:
|
|
324
|
+
_common.setup_logging()
|
|
325
|
+
parser = _common.build_parser(__doc__)
|
|
326
|
+
parser.set_defaults(out_dir=OUT_ROOT)
|
|
327
|
+
args = parser.parse_args()
|
|
328
|
+
sc_dir, st_dir = _common.prepare_dirs(args.out_dir)
|
|
329
|
+
|
|
330
|
+
for p in PATIENTS:
|
|
331
|
+
with _common.staging(args.out_dir, p.name) as tmp_dir:
|
|
332
|
+
build_scrna(p, tmp_dir, sc_dir / f"{p.name}.h5ad")
|
|
333
|
+
build_st(p, tmp_dir, st_dir)
|
|
334
|
+
logger.info("%s done", p.name)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
if __name__ == "__main__":
|
|
338
|
+
main()
|