sc-perturb
Load when classifying perturbed vs non-perturbed cells in a Perturb-seq / CRISPR-screen scRNA AnnData via the pertpy Mixscape workflow. Skip when guide labels are not yet attached to the expression ob
SKILL.mdskills/sc-perturb/SKILL.md
GitHubsc-perturb
When to use
The user has a scRNA AnnData from a CRISPR perturbation screen
(Perturb-seq style) where each cell already carries a perturbation
label in obs[--pert-key] plus a control category. The skill runs
pertpy's Mixscape workflow to:
- Compute a per-cell perturbation signature (subtracts the matched
control profile in
obsm["X_pca"]). - Classify cells as
KO/NT/NP(non-perturbed / escapers). - Report responder vs non-responder structure per perturbation +
--split-bygroup.
Single backend: mixscape (forward-compatible CLI choice). For
attaching guide labels to expression first, use sc-perturb-prep. For
predicting perturbation effects on unperturbed data, use
sc-in-silico-perturbation.
Inputs & Outputs
<!-- AUTO-GENERATED from skill.yaml (interface) — do not edit by hand. Regenerate: python scripts/generate_skill_md.py <skill_dir> -->Inputs
- Modalities: scrna
- File types:
.h5ad
Outputs
tables/cell_metadata.csvtables/cell_type_counts.csvtables/mixscape_cell_classes.csvtables/mixscape_class_counts.csvtables/mixscape_global_class_counts.csvtables/mixscape_global_classes.csvfigures/mixscape_global_classes.pngfigures/r_perturbation_barplot.pnganalysis_summary.txtprocessed.h5adreport.mdresult.json- Processed AnnData (
saves_h5ad) — addsobs:mixscape_class,mixscape_class_global,mixscape_class_p_<lower(perturbation_type)>
Flow
- Load AnnData (
--input) or generate demo Perturb-seq data. - Validate
obs[--pert-key]exists and--controlis a real category in that column. - Warn-and-disable
--split-byif the column is absent (does NOT raise). - Compute
obsm["X_pca"]if missing (auto-runssc.pp.pca). - Run
pertpy.tools.Mixscape(perturbation signature + KO/NT/NP classification). - Detect degenerate output (e.g., everything classified as
NP) and write troubleshooting hints. - Save
processed.h5ad, tables, figure,report.md,result.json.
Gotchas
- All preflight failures
raise SystemExit, notValueError.sc_perturb.py:228raisesSystemExit("Provide --input or use --demo");:235raisesSystemExit("Perturbation column '<key>' not found in adata.obs. ...")with multi-option fix hints;:246raisesSystemExit("Control label '<label>' not found in adata.obs['<key>']. Available labels: <list>"). Wrappers expecting standardValueErrorneed to catchSystemExithere. --split-bymissing is a soft warning, not a fail. When--split-by(defaultreplicate) doesn't exist inobs,sc_perturb.py:255-261logs a warning and silently disables the split. The Mixscape run continues without replicate awareness —result.json["params"]["split_by"]will reflect the disablement.- PCA is computed automatically when missing.
sc_perturb.py:264-266callssc.pp.pca(adata)ifobsm["X_pca"]is absent — no upstreamsc-preprocessingstrictly required, but the implicit PCA uses defaults (no batch correction, no HVG). For real screens prefer runningsc-preprocessingfirst so the PCA reflects HVG-selected normalised data. - Degenerate output (everything
NP) is a soft fail.sc_perturb.py:85defines_detect_degenerate_outputwhich records diagnostics and writes troubleshooting hints toreport.md(seesc_perturb.py:141+); the script does NOT raise. Always inspectresult.json["n_classes"](:382) — if it's 1, Mixscape didn't separate populations and the run is uninformative. --method mixscapeis the only choice.sc_perturb.py:72argparsechoices=["mixscape"].--methodexists for forward-compatibility; today any other value is rejected by argparse before the script runs.
Key CLI
# Demo (synthetic Perturb-seq)
python omicsclaw.py run sc-perturb --demo --output /tmp/sc_perturb_demo
# Default: input has standard column names (perturbation / NT)
python omicsclaw.py run sc-perturb \
--input perturb_prep_output/processed.h5ad --output results/
# Custom column / control names
python omicsclaw.py run sc-perturb \
--input data.h5ad --output results/ \
--pert-key guide_target --control non-targeting --split-by donor
# Tune Mixscape DE thresholds
python omicsclaw.py run sc-perturb \
--input data.h5ad --output results/ \
--logfc-threshold 0.5 --pval-cutoff 0.01 --n-neighbors 30
See also
references/parameters.md— every CLI flag, Mixscape tunablesreferences/methodology.md— Mixscape signature subtraction; KO/NT/NP semanticsreferences/output_contract.md—obs["mixscape_class"]/obs["mixscape_class_global"]schema + table layouts- Adjacent skills:
sc-perturb-prep(upstream — attaches guide labels to the expression object),sc-de(downstream — DE between perturbed and control),sc-in-silico-perturbation(parallel — predicts perturbation effects WITHOUT a real screen),sc-preprocessing(upstream — produces an HVG-aware PCA preferable to the auto-PCA inside this skill)