spatial-cnv
Infer copy number variation programs from spatial transcriptomics data using inferCNVpy or Numbat, with method-aware matrix selection, reference controls, and spatially mappable CNV summaries.
SKILL.mdSkills/spatial/spatial-cnv/SKILL.md
GitHub🧫 Spatial CNV
You are Spatial CNV, the copy-number inference skill for OmicsClaw. Your role is to identify large-scale chromosomal gains and losses from spatial transcriptomics data while preserving the matrix assumptions and reference requirements of each CNV method.
Why This Exists
- Without it: users have to wire gene-position metadata, reference groups, expression matrices, and downstream spatial visualization manually.
- With it: one skill coordinates matrix-aware CNV inference, exports reproducibility commands, and writes spatially interpretable summary tables.
- Why OmicsClaw: it provides a method-specific wrapper layer around inferCNVpy and Numbat, so the user sees the right knobs first and the project can extend methods later without changing the interaction pattern.
Core Capabilities
- inferCNVpy (default): expression-based CNV inference on log-normalized expression with official infercnvpy tuning flags.
- Numbat: haplotype-aware CNV inference via R using raw counts, allele counts, and diploid reference expression profiles.
- Reference-aware runs: supports
reference_key/reference_catbaseline selection for both methods. - Standard Python gallery: emits a recipe-driven CNV gallery with
overview, diagnostic, supporting, and uncertainty panels backed by the
shared
skills/spatial/_lib/vizlayer. - Figure-ready exports: writes
figure_data/CSVs plus a gallery manifest so downstream tools can restyle the same analysis without recomputing CNV. - Compact result tables: writes cell-level CNV scores and method-specific CNV summaries for downstream inspection.
Input Formats
| Format | Extension | Required Fields | Example |
|---|---|---|---|
| AnnData (preprocessed) | .h5ad |
X, obsm["spatial"], var["chromosome"], var["start"], var["end"] |
processed.h5ad |
| Demo | n/a | --demo flag |
Runs spatial-preprocess demo first and injects synthetic gene positions / references |
Input Matrix Convention
The two CNV methods do not consume the same matrix representation:
| Method | Input Matrix | Rationale |
|---|---|---|
infercnvpy |
adata.X (log-normalized) |
infercnvpy.tl.infercnv() models smoothed log-fold-change relative to a baseline and documents layer=None -> X as the main input path |
numbat |
adata.layers["counts"] (raw integer UMI counts) |
run_numbat() expects a gene-by-cell UMI count matrix and combines it with allele evidence |
Core principle: inferCNV-style expression smoothing works on normalized log-expression, while Numbat's joint expression/allelic model works on raw integer counts plus phased SNP evidence.
Additional Numbat Inputs
The current OmicsClaw Numbat wrapper requires:
adata.obsm["allele_counts"]: a table-like object with columnscell/snp_id/CHROM/POS/AD/DP/GT/gene--reference-keyand--reference-cat: labeled diploid reference cells used by OmicsClaw to buildlambdas_ref
If layers["counts"] is missing, OmicsClaw falls back to adata.raw or
adata.X with a warning.
Workflow
- Load: read the preprocessed
.h5adand validate genomic annotations. - Validate: check method-specific matrix requirements and reference metadata.
- Run CNV inference:
infercnvpy: infer CNV matrix, then build CNV-space PCA / neighbors / Leiden clusters before computingcnv_scorenumbat: export a lightweight h5ad + allele-count table and launch the Rrun_numbat()workflow
- Summarize: compute cell-level CNV scores and write method-specific CSV outputs.
- Visualize: render the standard Python CNV gallery from a declarative
recipe built on
plot_cnv()andplot_features(). - Export figure data: write figure-ready CSVs and manifests for optional R-side beautification or custom plotting.
- Report and export: write
report.md,result.json,processed.h5ad, tables, figures,figure_data/, and reproducibility helpers.
CLI Reference
# inferCNVpy default run
oc run spatial-cnv \
--input <processed.h5ad> --output <dir>
# inferCNVpy with explicit reference cells and broader smoothing
oc run spatial-cnv \
--input <processed.h5ad> --method infercnvpy \
--reference-key cell_type --reference-cat Normal Stroma \
--window-size 150 --step 20 \
--infercnv-dynamic-threshold 1.5 \
--infercnv-lfc-clip 3.0 \
--infercnv-exclude-chromosomes chrX chrY \
--infercnv-chunksize 5000 --infercnv-n-jobs 1 \
--output <dir>
# inferCNVpy including sex chromosomes
oc run spatial-cnv \
--input <processed.h5ad> --method infercnvpy \
--reference-key cell_type --reference-cat Normal \
--infercnv-include-sex-chromosomes \
--output <dir>
# Numbat (requires raw counts, allele counts, and diploid references)
oc run spatial-cnv \
--input <processed.h5ad> --method numbat \
--reference-key cell_type --reference-cat Normal \
--numbat-genome hg38 --numbat-max-entropy 0.8 \
--numbat-min-llr 5 --numbat-min-cells 50 --numbat-ncores 4 \
--output <dir>
# Demo mode
oc run spatial-cnv --demo --output /tmp/cnv_demo
# Direct script entrypoint
python skills/spatial/spatial-cnv/spatial_cnv.py \
--input <processed.h5ad> --method infercnvpy --output <dir>
Every successful standard OmicsClaw wrapper run, including oc run and
conversational skill execution, also writes a top-level README.md and
reproducibility/analysis_notebook.ipynb to make the output directory easier
to inspect and rerun.
Example Queries
- "Infer CNV from my spatial transcriptomics data"
- "Run inferCNVpy using stromal spots as the reference baseline"
- "Use Numbat with allele counts to identify tumor clones"
Algorithm / Methodology
inferCNVpy (default)
- Input:
adata.X(log-normalized expression) plusvar["chromosome"],var["start"],var["end"] - Reference baseline:
reference_key/reference_catmap to the official infercnvpy baseline controls; if omitted, infercnvpy uses an all-cells average reference - CNV inference: OmicsClaw runs
infercnvpy.tl.infercnv(...)with official core parameters includinglfc_clip,window_size,step,dynamic_threshold,exclude_chromosomes,chunksize, andn_jobs - CNV-space clustering: after inference, OmicsClaw computes CNV PCA,
CNV-neighbor graph, and CNV Leiden clusters before calling
infercnvpy.tl.cnv_score(...) - Cell-level summary:
cnv_scoreis used as the main scalar anomaly score and exported for visualization / downstream routing
Core tuning flags:
--reference-key/--reference-cat: define the diploid baseline; this is usually the first scientific decision--window-size: larger windows emphasize broad arm-level aberrations, while smaller windows retain finer local structure--step: lower values increase resolution and runtime--infercnv-dynamic-threshold: denoising threshold applied relative to the CNV standard deviation; omit or disable only intentionally--infercnv-lfc-clip: caps extreme log-fold-change values--infercnv-exclude-chromosomes: official chromosome-exclusion control--infercnv-chunksize/--infercnv-n-jobs: scalability knobs
Numbat
- Input: raw integer UMI counts from
layers["counts"]plus allele-count table inadata.obsm["allele_counts"] - Diploid reference construction: the current OmicsClaw wrapper builds
lambdas_reffrom--reference-keyand--reference-cat - Joint CNV inference: OmicsClaw calls the R
run_numbat()workflow withcount_mat,lambdas_ref,df_allele,genome,max_entropy,min_LLR,min_cells, andncores - Clone posterior export: the wrapper exports Numbat joint-posterior and clone-posterior tables back into OmicsClaw outputs
Core tuning flags:
--reference-key/--reference-cat: required in the current wrapper--numbat-max-entropy: allele-ambiguity filter; the official spatial RNA tutorial relaxes this toward0.8on Visium-like data--numbat-min-llr: minimum CNA confidence cutoff--numbat-min-cells: minimum cells per retained CNA-defined clone--numbat-ncores: parallel worker count for the R workflow--numbat-genome: genome build (hg19orhg38)
Output Structure
output_directory/
├── README.md
├── report.md
├── result.json
├── processed.h5ad
├── figures/
│ ├── cnv_heatmap.png
│ ├── cnv_spatial.png
│ ├── cnv_umap.png # when X_umap exists
│ ├── cnv_group_sizes.png # when CNV groups are available
│ ├── cnv_score_distribution.png
│ └── manifest.json
├── figure_data/
│ ├── cnv_scores.csv
│ ├── cnv_run_summary.csv
│ ├── cnv_spatial_points.csv
│ ├── cnv_umap_points.csv # when X_umap exists
│ ├── cnv_group_sizes.csv # when CNV groups are available
│ ├── cnv_bin_summary.csv # inferCNVpy runs
│ ├── numbat_calls.csv # Numbat runs
│ ├── numbat_clone_post.csv # Numbat runs
│ └── manifest.json
├── tables/
│ ├── cnv_scores.csv
│ ├── cnv_run_summary.csv
│ ├── cnv_group_sizes.csv # when CNV groups are available
│ ├── cnv_bin_summary.csv # inferCNVpy runs
│ ├── numbat_calls.csv # Numbat runs
│ └── numbat_clone_post.csv # Numbat runs
└── reproducibility/
├── analysis_notebook.ipynb
├── commands.sh
└── r_visualization.sh
README.md and reproducibility/analysis_notebook.ipynb are generated by the
standard OmicsClaw wrapper. Direct script execution produces the skill-native
outputs plus reproducibility/commands.sh.
Visualization Contract
- Python gallery is canonical:
figures/manifest.jsondescribes the standard OmicsClaw CNV story for routine analysis delivery. figure_data/is the bridge layer: downstream plotting code should read exported CSVs instead of rerunning inferCNVpy or Numbat.- R is an optional customization layer:
skills/spatial/spatial-cnv/r_visualization/contains starter templates that consumefigure_data/and write polished figures underfigures/custom/.
Dependencies
Required (Python):
scanpy
Optional (Python):
infercnvpyfor expression-based CNV inference
Optional (R environment / subprocess):
numbatSingleCellExperimentzellkonverter
Safety
- Local-first: no data upload; all CNV inference remains on the local machine.
- Method-aware matrix usage: do not pass log-normalized matrices to Numbat or raw-count assumptions to inferCNVpy.
- Reference transparency: CNV baselines and reference categories must be stated explicitly before running.
- Interpretation caution: expression-based CNV scores are screening signals, not definitive DNA-level segment calls.
Integration with Orchestrator
Trigger conditions:
- copy number variation
- inferCNV / infercnvpy
- Numbat
- tumor clone / chromosomal aberration
Chaining partners:
spatial-preprocessfor matrix preparation and counts preservationspatial-annotatefor choosing diploid reference categoriesspatial-genesfor linking CNV programs to spatially variable genes
Citations
- inferCNVpy documentation
- Numbat spatial RNA tutorial
- Numbat reference:
run_numbat - Tirosh et al. 2016 — expression-based CNV inference in tumors