sc-qc
Review cell quality before filtering. Computes counts, detected genes, mitochondrial percentage, and ribosomal percentage, but does not remove cells.
Files1
View on GitHubSKILL.mdSkills/singlecell/scrna/sc-qc/SKILL.md
GitHub📊 Single-Cell QC
You are SC QC, the OmicsClaw skill for first-pass single-cell RNA-seq quality assessment. Your job is to calculate core QC metrics, render a standard diagnostic gallery, and export figure-ready tables so users can decide filtering thresholds deliberately in a later step.
Why This Exists
- Without it: users jump straight to filtering with vague or tissue-misaligned thresholds
- With it: one run produces a stable QC summary, diagnostic plots, and reusable per-cell metric tables
- Why OmicsClaw: the wrapper keeps a standard output contract across CLI / bot / chat usage and records analysis metadata back into AnnData for downstream reuse
Scope Boundary
Current OmicsClaw sc-qc exposes one implemented analysis path:
qc_metrics.
This skill:
- calculates QC metrics
- visualizes QC distributions
- exports per-cell and summary tables
- saves an AnnData with QC annotations
This skill does not:
- filter cells
- filter genes
- perform doublet detection
- normalize or cluster the data
Use sc-preprocessing or another downstream filtering workflow after reviewing
the QC outputs.
Core Capabilities
- QC metric calculation:
n_genes_by_counts,total_counts,pct_counts_mt, optional log metrics, and ribosomal percentage - Species-aware gene tagging: mitochondrial and ribosomal features are detected from
--species - Standard Python gallery: QC violin, scatter, histogram, and highest-expressed-gene panels
- Structured figure-data contract:
figure_data/exports figure-ready CSVs plus a manifest for downstream plotting or styling - Stable processed AnnData output: a canonical
processed.h5adis produced with standardized scRNA contract fields,layers["counts"],adata.raw, QC metrics in.obs, marker flags in.var, and OmicsClaw metadata in.uns - Notebook-friendly reproducibility: report, structured result JSON, reproducibility shell command, pinned requirements bundle, README, and analysis notebook
Input Formats
The current wrapper uses skills.singlecell._lib.io.smart_load(...).
| Format | Extension / form | Current wrapper support | Notes |
|---|---|---|---|
| AnnData | .h5ad |
yes | preferred path |
| 10x HDF5 | .h5 |
yes | delegated to shared single-cell loader |
| Loom | .loom |
yes | delegated to shared single-cell loader |
| Delimited matrix | .csv, .tsv |
yes | interpreted through the shared count-matrix loader |
| 10x directory | directory | yes | delegated to the shared 10x importer |
| Demo | --demo |
yes | PBMC3k local/example fallback |
Input Expectations
- The most reliable input is a raw-count-like matrix available in
adata.layers["counts"], alignedadata.raw, oradata.X. - If explicit counts are not in
adata.X, the wrapper now auto-selects the best count-like source before QC. - Gene names should follow the selected species convention closely enough for mitochondrial and ribosomal prefix detection to work; when they do not, the run continues with warnings instead of faking precision.
Workflow
- Load: read input data with the shared single-cell loader or demo data.
- Preflight: check whether a count-like matrix exists, recommend
sc-standardize-inputwhen provenance is unclear, and warn honestly about species-dependent gene naming. - Prepare counts and gene IDs: choose the best available count-like source plus the best gene-symbol column for MT / ribosomal tagging.
- Calculate metrics: run Scanpy QC metric calculation and add log-transformed helper columns.
- Render standard gallery: generate the default OmicsClaw QC gallery under
figures/through the sharedskills/singlecell/_lib/vizlayer. - Export figure data and tables: write stable CSV exports under
figure_data/andtables/. - Write outputs: save
processed.h5ad,report.md,result.json, README, notebook, and reproducibility bundle.
CLI Reference
# Basic usage
python skills/singlecell/scrna/sc-qc/sc_qc.py \
--input <data.h5ad> --output <dir>
# Mouse gene naming convention
python skills/singlecell/scrna/sc-qc/sc_qc.py \
--input <data.h5ad> --species mouse --output <dir>
# Demo mode
python skills/singlecell/scrna/sc-qc/sc_qc.py \
--demo --output /tmp/sc_qc_demo
# Via OmicsClaw
oc run sc-qc --input <data.h5ad> --output <dir>
Public Parameters
| Parameter | Default | Type | Role |
|---|---|---|---|
--input |
required unless --demo |
path | input dataset |
--output |
required | path | output directory |
--demo |
false |
flag | run built-in demo data |
--species |
human |
enum | wrapper-level control for MT / ribosomal gene-prefix detection |
Parameter Design Notes
--speciesis the only public extra flag because the current wrapper exposes a single QC path and does not surface thresholding knobs here.calculate_ribo=Trueis fixed in the current implementation and is not a public CLI parameter.- Do not present
sc-qcas if users were choosing among multiple QC algorithms today. The main decision in current OmicsClaw is how to interpret the output, not how to configure many QC backends.
Algorithm / Methodology
Implemented Method: qc_metrics
Current OmicsClaw sc-qc uses Scanpy QC metric calculation with
species-specific feature tagging.
- Species-aware feature tagging
human: mitochondrial genes start withMT-; ribosomal genes match^RP[SL]mouse: mitochondrial genes start withmt-; ribosomal genes match^Rp[sl]
- Metric calculation
scanpy.pp.calculate_qc_metrics(..., qc_vars=["mt", "ribo"], percent_top=None, log1p=False, inplace=True)
- Derived helper metrics
log10_total_countslog10_n_genes_by_counts
- Standard gallery renderers
- QC violin plots
- QC scatter plots
- QC histograms
- highest expressed genes summary
Current Input Robustness Behavior
smart_load(...)is now loader-only: it reads the object and records a minimal input contract.- User-facing standardization advice is emitted by shared
preflight, not by the loader. prepare_count_like_adata(...)then selectslayers["counts"]→ alignedadata.raw→ count-likeadata.Xin that order.- The saved
processed.h5addeclares matrix semantics explicitly inadata.uns["omicsclaw_matrix_contract"]: hereadata.Xis raw count-like,adata.layers["counts"]is the canonical raw layer, andadata.rawis a count-like snapshot. - If no mitochondrial or ribosomal genes match the selected species convention, the run continues with warnings and counts-based QC metrics remain available.
Guaranteed Metric Columns After Success
The saved processed.h5ad is expected to contain at least:
adata.obs["n_genes_by_counts"]
adata.obs["total_counts"]
adata.obs["pct_counts_mt"]
adata.obs["log10_total_counts"]
adata.obs["log10_n_genes_by_counts"]
When ribosomal pattern matching succeeds, the wrapper also writes:
adata.obs["pct_counts_ribo"]
adata.var["ribo"]
The feature-tag columns below are written during QC metric setup:
adata.var["mt"]
adata.var["ribo"]
OmicsClaw analysis metadata is also persisted in:
adata.uns["omicsclaw_analyses"]
Interpretation Guidance
Read These Metrics As Diagnostics, Not Hard Laws
n_genes_by_counts: low values often indicate empty droplets or low-complexity cells; very high values may indicate doubletstotal_counts: very low values may indicate poor capture; very high values may reflect doublets or highly loaded dropletspct_counts_mt: elevated mitochondrial percentage often suggests stressed or dying cells, but acceptable ranges vary by tissuepct_counts_ribo: useful supporting context, especially when translation-heavy cell states dominate
Practical First-Pass Reading
- PBMC-like data often tolerates stricter mitochondrial cutoffs
- solid tissues / tumors often require broader tolerance
- highly metabolic tissues may show biologically elevated mitochondrial fractions
Do not convert these plots directly into filtering without considering tissue, chemistry, ambient RNA burden, and expected cell complexity.
Output Contract
Stable Files
output_dir/
├── README.md
├── report.md
├── result.json
├── processed.h5ad
├── figures/
│ ├── qc_violin.png
│ ├── qc_scatter.png
│ ├── qc_histograms.png
│ ├── highest_expr_genes.png
│ ├── barcode_rank.png
│ ├── qc_correlation_heatmap.png
│ └── manifest.json
├── figure_data/
│ ├── manifest.json
│ ├── qc_run_summary.csv
│ ├── qc_metrics_summary.csv
│ ├── qc_metrics_per_cell.csv
│ ├── highest_expr_genes.csv
│ ├── barcode_rank_curve.csv
│ └── qc_metric_correlations.csv
├── tables/
│ ├── qc_metrics_summary.csv
│ ├── qc_metrics_per_cell.csv
│ ├── highest_expr_genes.csv
│ ├── barcode_rank_curve.csv
│ └── qc_metric_correlations.csv
└── reproducibility/
├── commands.sh
├── requirements.txt
└── analysis_notebook.ipynb
What Users Should Inspect First
report.mdfigures/qc_violin.pngandfigures/qc_scatter.pngtables/qc_metrics_summary.csvtables/qc_metrics_per_cell.csvtables/barcode_rank_curve.csvandtables/qc_metric_correlations.csvfor deeper QC reviewprocessed.h5adfor downstream filtering workflows
Structured Result Contract
result.json includes:
summary.method = "qc_metrics"data.params.speciesdata.effective_params.calculate_ribo = truedata.visualization.recipe_id = "standard-sc-qc-gallery"data.visualization.available_figure_data- top-level summary values such as
n_cells,n_genes,median_genes, andmedian_counts
data.params records replayable public CLI parameters.
data.effective_params records the actual runtime configuration, including
fixed wrapper behavior.
Visualization Contract
sc-qc treats Python plots as the standard analysis gallery. The current
recipe roles are:
overview: QC violin plotsdiagnostic: QC scatter plots and histogramssupporting: highest expressed genes panel
figure_data/ is the stable hand-off layer for downstream custom plotting,
including future R-side visualization or user-authored beautification scripts.
Example Queries
- "Calculate QC metrics for this scRNA-seq dataset"
- "Show me mitochondrial percentage and genes-per-cell distributions"
- "Generate QC violin and scatter plots before filtering"
- "Run single-cell QC and export the per-cell QC table"
Dependencies
Required core packages:
scanpyanndatanumpypandasmatplotlib
Notebook export additionally depends on the standard OmicsClaw notebook helper stack when available.
Safety And Guardrails
- This skill is diagnostic only and does not remove cells or genes.
- Species choice affects mitochondrial / ribosomal pattern matching and should be stated explicitly before the run.
- If gene symbols do not follow expected human or mouse prefixes, explain that percentage estimates may be incomplete.
- For short execution guardrails, see
knowledge_base/knowhows/KH-sc-qc-guardrails.md. - For longer method and interpretation guidance, see
knowledge_base/skill-guides/singlecell/sc-qc.md.
Workflow Position
- Upstream step: Input should come from
sc-count,sc-multi-count, orsc-standardize-input - Usual next step:
sc-filterto remove low-quality cells based on the QC metrics visualized here - Optional: Run
sc-doublet-detectionbefore or after filtering
CLI Parameters
| Flag | Type | Default | Description | Validation |
|---|---|---|---|---|
--input |
path | — | Input AnnData file (.h5ad); required unless --demo |
— |
--output |
path | — | Output directory (required) | — |
--demo |
flag | false |
Run with built-in PBMC3K demo data | — |
--species |
enum | human |
Species for MT/ribosomal gene prefix detection: human, mouse |
— |
--r-enhanced |
flag | false |
Generate R Enhanced figures via ggplot2 renderers | — |
Note: calculate_ribo=True is fixed and not exposed as a CLI parameter.
R Enhanced Plots
| Renderer | Output file | What it shows | R packages |
|---|---|---|---|
plot_embedding_discrete |
r_embedding_discrete.png |
Cell scatter colored by discrete group/cluster label | ggplot2, ggrepel, cowplot |
plot_cell_barplot |
r_cell_barplot.png |
Cell count bar chart per group/sample | ggplot2, cowplot |