Load when assigning per-spot cell-type labels on a spatial AnnData via marker-gene scoring
Scanned 9/6/2026
Install to Claude Code
npx -y skills add lilinji/GeneTind-Life-Skills --skill spatial-annotate --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Spatial Annotate?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lilinji-spatial-annotate)More formats (shields.io, HTML) on the badges page.
---
# AUTO-GENERATED header from skill.yaml — do not edit by hand.
# Edit skill.yaml, then run: python scripts/generate_skill_md.py <skill_dir>
name: spatial-annotate
description: Load when assigning per-spot cell-type labels on a spatial AnnData via marker-gene scoring
or scRNA-reference mapping (Tangram / scANVI / CellAssign). Skip when computing spot-level cell-type
proportions for multi-cell-per-spot platforms (use spatial-deconv); tissue-domain detection (use spatial-domains).
version: 0.5.0
author: OmicsClaw
license: MIT
emoji: 🏷️
tags:
- spatial
- annotation
- cell-type
- marker-based
- tangram
- scanvi
- cellassign
requires:
- anndata
- matplotlib
- numpy
- pandas
- scanpy
- scipy
- scvi-tools
- seaborn
- tangram-sc
- torch
---
# spatial-annotate
## When to use
The user has a single-cell-per-spot spatial AnnData (Xenium / MERFISH /
Slide-seq) OR wants a discrete per-spot label even for Visium and has
either marker genes or a labelled scRNA reference. Four methods:
- `marker_based` (default) — built-in marker dictionaries (`--species`,
`--marker-n-genes`, `--marker-padj-cutoff`); optional custom marker
model via `--model`. No reference needed.
- `tangram` — gradient mapping from a labelled scRNA reference
(`--tangram-num-epochs`, `--tangram-train-genes`, `--tangram-device`).
Requires `tangram` + `torch`.
- `scanvi` — scvi-tools scANVI semi-supervised classifier
(`--scanvi-n-hidden` / `--scanvi-n-latent` / `--scanvi-n-layers`,
`--scanvi-max-epochs`). Requires `scvi-tools` + `torch`.
- `cellassign` — Bayesian probabilistic assignment with marker
matrix (`--cellassign-max-epochs`).
For *proportion* deconvolution on Visium-style multi-cell spots use
`spatial-deconv`. For tissue domains use `spatial-domains`.
## Inputs & Outputs
<!-- AUTO-GENERATED from skill.yaml (interface) — do not edit by hand. Regenerate: python scripts/generate_skill_md.py <skill_dir> -->
**Inputs**
- File types: `.h5ad`
- Requires a preprocessed AnnData (`X` normalised, PCA/neighbours present)
- Expects `obsm`: `spatial`
**Outputs**
- `tables/annotation_cell_type_counts.csv`
- `tables/annotation_probabilities.csv`
- `tables/annotation_spatial_points.csv`
- `tables/annotation_summary.csv`
- `tables/annotation_umap_points.csv`
- `tables/cell_type_assignments.csv`
- `tables/cluster_annotations.csv`
- `tables/marker_overlap_scores.csv`
- `figures/annotation_confidence_histogram.png`
- `figures/annotation_confidence_spatial.png`
- `figures/annotation_probability_heatmap.png`
- `figures/cell_type_barplot.png`
- `figures/cell_type_spatial.png`
- `figures/cell_type_umap.png`
- `figures/marker_overlap_heatmap.png`
- `processed.h5ad`
- `report.md`
- `result.json`
- Processed AnnData (`saves_h5ad`) — adds `obs`: `cell_type`; `obsm`: `tangram_ct_pred`, `scanvi_probabilities`, `cellassign_probabilities`
## Flow
1. Load AnnData (`--input`) or chain through `spatial-preprocess --demo`.
2. `parser.error` validates per-method numeric flags (lines `:730-746`); `:748` raises if `--reference` is missing for tangram / scanvi; `:750` for missing reference path; `:752` for missing `--model` path.
3. Dispatch to method:
- `marker_based`: run `sc.tl.rank_genes_groups` (or use `--model`), score against species marker DB.
- `tangram`: train Tangram mapping from scRNA → spatial, project labels.
- `scanvi`: train scANVI on reference + spatial, predict labels.
- `cellassign`: solve probabilistic assignment given marker matrix.
4. Write `obs["cell_type"]` (Categorical); per-method extras (probabilities, marker overlap).
5. Save `processed.h5ad`, tables, figures, `report.md`, `result.json`.
## Gotchas
- **`--reference` is required for `tangram` / `scanvi`.** `spatial_annotate.py:748` raises `parser.error(f"--reference is required for {args.method}")`. `marker_based` and `cellassign` can run reference-free (using marker DB or marker matrix).
- **All numeric / file-path validation goes through `parser.error` (exit 2).** `spatial_annotate.py:730-746` for numeric ranges; `:748-752` for required-file paths.
- **`--input` missing → `sys.exit(1)` via `print` (NOT `parser.error`).** Same pattern as spatial-domains. Caller wrappers expecting exit-2 get exit-1.
- **`marker_based` species default is `human`.** `spatial_annotate.py:866` defaults `--species human`. For mouse data pass `--species mouse` so the built-in markers match HGNC vs MGI symbols.
- **Probabilities matrix is method-conditional.** Only `tangram` / `scanvi` / `cellassign` produce a per-spot × celltype probability matrix. `spatial_annotate.py:441` writes it to `figure_data/annotation_probabilities.csv` (note: figure_data, not tables; filename is `annotation_probabilities.csv`). `marker_based` writes only the discrete `obs["cell_type"]`. Downstream tools reading probabilities must guard for absence.
- **`obsm["spatial"]` ↔ `obsm["X_spatial"]` sync at `:102-104`.** Same dual-key pattern as spatial-domains / spatial-deconv.
- **Demo chains through `spatial-preprocess --demo` via subprocess.** `spatial_annotate.py:723` raises `RuntimeError(f"spatial-preprocess --demo failed: {result.stderr}")` on chained-run failure.
- **Tangram requires `tangram-sc` (PyPI name) but imports as `tangram`.** `spatial_annotate.py:699` records this naming wart; pip install `tangram-sc`, not `tangram`.
## Key CLI
```bash
# Demo (chained from spatial-preprocess --demo, marker_based)
python omicsclaw.py run spatial-annotate --demo --output /tmp/spatial_annot_demo
# Marker-based on a Visium with built-in human markers
python omicsclaw.py run spatial-annotate \
--input clustered.h5ad --output results/ \
--method marker_based --species human --marker-n-genes 50
# Tangram reference mapping
python omicsclaw.py run spatial-annotate \
--input clustered.h5ad --output results/ \
--method tangram --reference scrna_atlas.h5ad \
--tangram-num-epochs 1000 --tangram-train-genes 1000
# scANVI semi-supervised
python omicsclaw.py run spatial-annotate \
--input clustered.h5ad --output results/ \
--method scanvi --reference scrna_atlas.h5ad \
--scanvi-n-latent 30 --scanvi-max-epochs 400 --batch-key sample
# CellAssign with marker matrix
python omicsclaw.py run spatial-annotate \
--input clustered.h5ad --output results/ \
--method cellassign --cellassign-max-epochs 200
```
## See also
- `references/parameters.md` — every CLI flag, per-method tunables
- `references/methodology.md` — when each backend wins; reference vs marker-based
- `references/output_contract.md` — `obs["cell_type"]` / `obsm["cell_type_probabilities"]` schema
- Adjacent skills: `spatial-preprocess` (upstream — produces clustered spatial input), `sc-cell-annotation` (upstream — labels the scRNA reference for `--reference`), `spatial-deconv` (parallel — proportion-based for multi-cell-per-spot Visium, NOT discrete labels), `spatial-domains` (parallel — label-free tissue regions; complementary to cell-type labels), `spatial-de` (downstream — DE between cell-types from this skill)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!