spatial-aim 1.3.0__tar.gz → 1.3.1__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.3.1}/PKG-INFO +1 -1
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatial_aim.egg-info/PKG-INFO +1 -1
- spatial_aim-1.3.1/src/spatial_aim.egg-info/scm_version.json +8 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/scatter.py +54 -33
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/state_names.py +67 -7
- spatial_aim-1.3.0/src/spatial_aim.egg-info/scm_version.json +0 -8
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/.github/workflows/ci.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/.github/workflows/release.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/.gitignore +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/.pre-commit-config.yaml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/LICENSE +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/README.md +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/docs/aim_gui.gif +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/docs/figure_2_1.png +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/environment.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/pyproject.toml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/renovate.json +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/sample_dataset/ST/index.csv +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/sample_dataset/ST/sample_st.h5ad +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/sample_dataset/pairs.csv +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/sample_dataset/scRNA/index.csv +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/sample_dataset/scRNA/sample_sc.h5ad +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/setup.cfg +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatial_aim.egg-info/SOURCES.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatial_aim.egg-info/dependency_links.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatial_aim.egg-info/entry_points.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatial_aim.egg-info/requires.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatial_aim.egg-info/scm_file_list.json +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatial_aim.egg-info/top_level.txt +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/__main__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/adata_schema.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/aggregation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/coherence.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/compare_ks/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/compare_ks/collect.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/compare_ks/criteria.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/compare_ks/run.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/compare_ks/scoring.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/compare_ks/selection.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/loading.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/reconstruction.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/run.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/shape_consistency.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/analysis/spatial_organization.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/cli.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/clustering.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/config.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/README.md +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/_common.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/_segmentation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_01_mouse_ssp.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_02_colorectal_cancer.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_03_mouse_liver.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_04_mouse_kidney.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_05_mouse_embryo.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_06_mouse_retina.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_07_mouse_mpfc.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_08_mouse_visual_cortex.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_09_human_breast_cancer.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_10_human_mtg.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/dump_retina_counts.R +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/environment_retina_qs.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/common.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/runner.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/validate_pair.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/validate_sc.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/validate_segmentation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/validate_st.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/__main__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/app.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/compute.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/data_access.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/loaders.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/cell_type.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/common.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/headline.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/ksweep.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/markers.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/report.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/render/shape.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/scaffold.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/sidebar.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/texts.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/validation.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/cards.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/cell_type_modal.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/choose_k.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/compare_tab.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/controls.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/mapper_tab.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/reference_tab.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/views/report.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/widgets/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/widgets/headline_plot.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/widgets/linked_plot.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/widgets/plotly_fit.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/gui/widgets/slider.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/io.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/mapping/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/mapping/base.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/mapping/confidence.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/mapping/nearest_centroid.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/mapping/reference.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/mapping/wann.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/metrics/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/metrics/cossim.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/metrics/modularity.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/metrics/shape_consistency.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/metrics/topology.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/__init__.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/environment_dot.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/environment_tacco.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/environment_tangram.yml +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/registry.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/run_dot.R +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/run_dot.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/run_tacco.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/run_tangram.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/sweep.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/tree.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/utils.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/tests/test_cli.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/tests/test_gui_imports.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/tests/test_registry.py +0 -0
- {spatial_aim-1.3.0 → spatial_aim-1.3.1}/tests/test_sweep_sample.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatial-aim
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.1
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spatial-aim
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.1
|
|
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
|
|
@@ -39,6 +39,13 @@ logger = logging.getLogger(__name__)
|
|
|
39
39
|
# Grey (as a CSS rgba string) for spots drawn below the confidence threshold.
|
|
40
40
|
_GREY_RGBA = "rgba(184,184,184,0.9)"
|
|
41
41
|
|
|
42
|
+
# The spatial panel draws each state in up to _MAX_CHUNKS interleaved chunks (see
|
|
43
|
+
# add_spatial_traces), capped at _MAX_STATE_TRACES traces in all: 20 chunks for a
|
|
44
|
+
# handful of states is all but a random order, while a K of 50 still gets 4
|
|
45
|
+
# without the panel turning into thousands of WebGL traces.
|
|
46
|
+
_MAX_CHUNKS = 20
|
|
47
|
+
_MAX_STATE_TRACES = 200
|
|
48
|
+
|
|
42
49
|
# --- EXPERIMENTAL: per-state centroid markers on the UMAP panels --------------
|
|
43
50
|
# Hand-set switch (see the question in the session that added this). When True,
|
|
44
51
|
# each UMAP panel gets one diamond marker per state at the state's *expression
|
|
@@ -373,40 +380,54 @@ def add_spatial_traces(
|
|
|
373
380
|
col=col,
|
|
374
381
|
)
|
|
375
382
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
383
|
+
# Draw order decides which colour wins where spots overlap: one trace per
|
|
384
|
+
# state, stacked by state id, lets the last states cover the others however
|
|
385
|
+
# rare they are. So each state is split into random chunks and the chunks are
|
|
386
|
+
# drawn round-robin (state 0 chunk 0, state 1 chunk 0, ..., state 0 chunk 1,
|
|
387
|
+
# ...), which comes close to a random order spot by spot. Every chunk is still
|
|
388
|
+
# a trace in its state's legendgroup, so the headline widget's toggling,
|
|
389
|
+
# clicks and hover work unchanged; only the first chunk carries the legend
|
|
390
|
+
# entry. The seed is fixed, so a rerun draws the same picture.
|
|
391
|
+
states = sorted(np.unique(hard[keep]).tolist())
|
|
392
|
+
n_chunks = max(1, min(_MAX_CHUNKS, _MAX_STATE_TRACES // max(1, len(states))))
|
|
393
|
+
chunk = np.random.default_rng(0).integers(n_chunks, size=len(hard))
|
|
394
|
+
for c in range(n_chunks):
|
|
395
|
+
for state in states:
|
|
396
|
+
mask = keep & (hard == state) & (chunk == c)
|
|
397
|
+
if not mask.any():
|
|
398
|
+
continue
|
|
399
|
+
show = state not in legend_shown
|
|
400
|
+
legend_shown.add(state)
|
|
401
|
+
genes = top_genes_suffix(top_genes, state)
|
|
402
|
+
head = f"{state_label(state, names)}{genes}"
|
|
403
|
+
if confidence is not None:
|
|
404
|
+
customdata = confidence[mask][:, None]
|
|
405
|
+
hovertemplate = (
|
|
406
|
+
f"{head}<br>"
|
|
407
|
+
"confidence %{customdata[0]:.3f}<br>"
|
|
408
|
+
"x %{x:.1f} y %{y:.1f}<extra></extra>"
|
|
409
|
+
)
|
|
410
|
+
else:
|
|
411
|
+
customdata = None
|
|
412
|
+
hovertemplate = f"{head}<br>x %{{x:.1f}} y %{{y:.1f}}<extra></extra>"
|
|
413
|
+
fig.add_trace(
|
|
414
|
+
go.Scattergl(
|
|
415
|
+
x=coords[mask, 0],
|
|
416
|
+
y=coords[mask, 1],
|
|
417
|
+
mode="markers",
|
|
418
|
+
marker=dict(
|
|
419
|
+
size=dot_size, color=hex_color(palette.get(state)), opacity=1.0
|
|
420
|
+
),
|
|
421
|
+
name=state_label(state, names),
|
|
422
|
+
legendgroup=f"state{state}",
|
|
423
|
+
showlegend=show,
|
|
424
|
+
meta="spatial",
|
|
425
|
+
customdata=customdata,
|
|
426
|
+
hovertemplate=hovertemplate,
|
|
399
427
|
),
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
meta="spatial",
|
|
404
|
-
customdata=customdata,
|
|
405
|
-
hovertemplate=hovertemplate,
|
|
406
|
-
),
|
|
407
|
-
row=row,
|
|
408
|
-
col=col,
|
|
409
|
-
)
|
|
428
|
+
row=row,
|
|
429
|
+
col=col,
|
|
430
|
+
)
|
|
410
431
|
|
|
411
432
|
_pin_spatial_axes(fig, coords, row=row, col=col, equal_aspect=equal_aspect)
|
|
412
433
|
|
|
@@ -9,7 +9,11 @@ the same population whichever mapper placed it there. The names live in
|
|
|
9
9
|
{"7": {"0": "Astrocytes", "3": "L2/3 IT"}, "12": {...}}
|
|
10
10
|
|
|
11
11
|
Only the names actually set are stored; ``label`` falls back to ``Cell type <n>``
|
|
12
|
-
for every other state, so a partly-named K is the normal case.
|
|
12
|
+
for every other state, so a partly-named K is the normal case. A run started
|
|
13
|
+
from an annotation (``--start_from_annotation``) is the exception at K = T (T =
|
|
14
|
+
the number of annotated types): there the tree cut is the identity, so every
|
|
15
|
+
state *is* one annotated type and defaults to that type's name
|
|
16
|
+
(``annotation_names``); a name set by hand still wins.
|
|
13
17
|
|
|
14
18
|
This is the GUI's only write path onto disk. Nothing in the sweep or the analysis
|
|
15
19
|
reads the file -- losing it costs the labels and nothing else. Because the key is
|
|
@@ -22,8 +26,15 @@ from __future__ import annotations
|
|
|
22
26
|
|
|
23
27
|
import json
|
|
24
28
|
import logging
|
|
29
|
+
from functools import lru_cache
|
|
25
30
|
from pathlib import Path
|
|
26
31
|
|
|
32
|
+
import pandas as pd
|
|
33
|
+
|
|
34
|
+
from spatialaim.io import START_CLUSTER_TO_STATE_FILENAME, START_CLUSTERING_FILENAME
|
|
35
|
+
|
|
36
|
+
from . import data_access
|
|
37
|
+
|
|
27
38
|
logger = logging.getLogger(__name__)
|
|
28
39
|
|
|
29
40
|
FILENAME = "cell_type_names.json"
|
|
@@ -52,8 +63,48 @@ def load_all(output_dir: Path) -> dict[str, dict[str, str]]:
|
|
|
52
63
|
return data if isinstance(data, dict) else {}
|
|
53
64
|
|
|
54
65
|
|
|
55
|
-
def
|
|
56
|
-
"""``{state:
|
|
66
|
+
def annotation_names(output_dir: Path, k: int) -> dict[int, str]:
|
|
67
|
+
"""``{state: annotated type}`` when this output dir's runs start from an
|
|
68
|
+
annotation and ``k`` is T, the number of annotated types -- the level where
|
|
69
|
+
the tree cut is the identity, so each state is exactly one annotated type.
|
|
70
|
+
Empty for every other K, for Leiden starts, and when no run root has the
|
|
71
|
+
files yet. All mappers cut the same tree, so any run root serves."""
|
|
72
|
+
if data_access.start_from_annotation_from_config(output_dir) is None:
|
|
73
|
+
return {}
|
|
74
|
+
for root in sorted(Path(output_dir).glob("*/")):
|
|
75
|
+
clustering = root / START_CLUSTERING_FILENAME
|
|
76
|
+
cut = data_access.k_dir(root, k) / START_CLUSTER_TO_STATE_FILENAME
|
|
77
|
+
if clustering.exists() and cut.exists():
|
|
78
|
+
# mtimes in the key: a rerun into the same dir invalidates the cache.
|
|
79
|
+
return dict(
|
|
80
|
+
_annotation_names(
|
|
81
|
+
str(clustering),
|
|
82
|
+
str(cut),
|
|
83
|
+
clustering.stat().st_mtime,
|
|
84
|
+
cut.stat().st_mtime,
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
return {}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@lru_cache(maxsize=32)
|
|
91
|
+
def _annotation_names(
|
|
92
|
+
clustering: str, cut: str, _m1: float, _m2: float
|
|
93
|
+
) -> tuple[tuple[int, str], ...]:
|
|
94
|
+
"""``annotation_names`` for one run root's files (cached per file version)."""
|
|
95
|
+
names = data_access.load_start_cluster_names(Path(clustering).parent)
|
|
96
|
+
states = pd.read_csv(cut)["state"].to_numpy(dtype=int)
|
|
97
|
+
if (
|
|
98
|
+
names is None
|
|
99
|
+
or len(states) != len(names)
|
|
100
|
+
or int(states.max()) + 1 != len(names)
|
|
101
|
+
):
|
|
102
|
+
return () # not the identity level: K != T
|
|
103
|
+
return tuple((int(s), n) for s, n in zip(states, names) if n)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _stored(output_dir: Path, k: int) -> dict[int, str]:
|
|
107
|
+
"""``{state: name}`` for the names set by hand at this K.
|
|
57
108
|
|
|
58
109
|
Tolerates hand-edits: entries with a non-numeric state or a blank name are
|
|
59
110
|
skipped rather than surfacing as broken labels.
|
|
@@ -72,19 +123,28 @@ def load(output_dir: Path, k: int) -> dict[int, str]:
|
|
|
72
123
|
return out
|
|
73
124
|
|
|
74
125
|
|
|
126
|
+
def load(output_dir: Path, k: int) -> dict[int, str]:
|
|
127
|
+
"""``{state: name}`` for one K, holding only the states that have a name:
|
|
128
|
+
the annotated type names at K = T of an annotation start
|
|
129
|
+
(``annotation_names``), overridden by any name set by hand."""
|
|
130
|
+
return annotation_names(output_dir, k) | _stored(output_dir, k)
|
|
131
|
+
|
|
132
|
+
|
|
75
133
|
def save(output_dir: Path, k: int, names: dict[int, str]) -> None:
|
|
76
134
|
"""Replace this K's names, leaving every other K in the file untouched.
|
|
77
135
|
|
|
78
|
-
A blank name
|
|
79
|
-
|
|
136
|
+
A blank name -- or one equal to the state's annotated type (see
|
|
137
|
+
``annotation_names``) -- drops that state back to its default label instead
|
|
138
|
+
of being stored, and a K with nothing left set drops out of the file entirely.
|
|
80
139
|
The write goes through a temp file and an atomic replace, so an interrupted
|
|
81
140
|
save cannot leave a half-written file that would read back as no names at all.
|
|
82
141
|
"""
|
|
83
142
|
data = load_all(output_dir)
|
|
143
|
+
defaults = annotation_names(output_dir, k)
|
|
84
144
|
cleaned = {
|
|
85
145
|
str(int(s)): n.strip()
|
|
86
146
|
for s, n in names.items()
|
|
87
|
-
if isinstance(n, str) and n.strip()
|
|
147
|
+
if isinstance(n, str) and n.strip() and n.strip() != defaults.get(int(s))
|
|
88
148
|
}
|
|
89
149
|
if cleaned:
|
|
90
150
|
data[str(int(k))] = cleaned
|
|
@@ -103,7 +163,7 @@ def set_name(output_dir: Path, k: int, state: int, name: str) -> None:
|
|
|
103
163
|
"""Set (or, when blank, clear) one state's name at this K, keeping the
|
|
104
164
|
others -- the cell-type modal's write, through the same ``save`` as the
|
|
105
165
|
all-states naming dialog."""
|
|
106
|
-
names =
|
|
166
|
+
names = _stored(output_dir, k)
|
|
107
167
|
names[int(state)] = name
|
|
108
168
|
save(output_dir, k, names)
|
|
109
169
|
|
|
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
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/_segmentation.py
RENAMED
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_01_mouse_ssp.py
RENAMED
|
File without changes
|
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_03_mouse_liver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_07_mouse_mpfc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/curate_10_human_mtg.py
RENAMED
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/curate_datasets/dump_retina_counts.R
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/data/validate/validate_segmentation.py
RENAMED
|
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
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/environment_dot.yml
RENAMED
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/environment_tacco.yml
RENAMED
|
File without changes
|
{spatial_aim-1.3.0 → spatial_aim-1.3.1}/src/spatialaim/reference_aligners/environment_tangram.yml
RENAMED
|
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
|