scRNA Preprocessing And Clustering
Version Compatibility
Reference examples assume:
scanpy 1.10+
anndata 0.10+
pandas 2.2+
matplotlib 3.8+
Before using code patterns, verify installed versions match the environment:
- Python:
python -c "import scanpy, anndata; print(scanpy.__version__, anndata.__version__)"
- If signatures differ, inspect the installed API and adapt the pattern instead of retrying unchanged.
Overview
Use this skill to turn raw or minimally processed scRNA-seq data into an analysis-ready object with:
- QC-filtered cells and genes
- normalized expression values
- highly variable genes
- PCA and UMAP embeddings
- Leiden clusters
- saved
h5ad artifact for annotation, DE, integration, or trajectory analysis
When To Use This Skill
- raw 10x matrices, filtered count matrices, or
h5ad inputs need standard preprocessing
- the user wants UMAP, clustering, or marker discovery
- downstream tasks depend on a stable single-cell object rather than ad hoc plots
Quick Route
- If the input is already a processed
h5ad, inspect adata.raw, embeddings, cluster columns, and QC columns before rerunning preprocessing.
- If the input is raw counts, do QC first and only normalize after filtering obvious low-quality cells.
- If multiple batches are present, preprocess cleanly first, then consider integration instead of hiding batch effects with aggressive filtering.
Progressive Disclosure
- Read technical_reference.md for QC decision rules, assay caveats, and integration branching.
- Read commands_and_thresholds.md for concrete Scanpy code, default thresholds, and output conventions.
Default Rules
- Keep raw counts recoverable. Prefer
adata.raw = adata.copy() before regression or scaling.
- Report thresholds explicitly. Do not silently drop cells or genes.
- Show QC distributions before applying hard filters.
- Use vector outputs such as
.pdf or .svg for final figures when possible.
Expected Inputs
- 10x directory,
.h5, .h5ad, or count matrix
- cell metadata if available
- species context for mitochondrial or ribosomal gene detection
Expected Outputs
results/processed.h5ad
qc/cell_qc_metrics.tsv
qc/gene_qc_metrics.tsv
figures/qc_violin.pdf
figures/pca_variance_ratio.pdf
figures/umap_leiden.pdf
Preferred Tools
scanpy
anndata
pandas
matplotlib
seaborn
Starter Pattern
import scanpy as sc
adata = sc.read_10x_mtx("counts/")
adata.var_names_make_unique()
adata.var["mt"] = adata.var_names.str.upper().str.startswith("MT-")
sc.pp.calculate_qc_metrics(adata, qc_vars=["mt"], inplace=True)
adata = adata[
(adata.obs["n_genes_by_counts"] >= 200)
& (adata.obs["n_genes_by_counts"] <= 6000)
& (adata.obs["pct_counts_mt"] < 15),
:
].copy()
sc.pp.filter_genes(adata, min_cells=3)
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
adata.raw = adata.copy()
sc.pp.highly_variable_genes(adata, n_top_genes=3000, flavor="seurat_v3")
adata = adata[:, adata.var["highly_variable"]].copy()
sc.pp.scale(adata, max_value=10)
sc.tl.pca(adata, svd_solver="arpack")
sc.pp.neighbors(adata, n_neighbors=15, n_pcs=30)
sc.tl.umap(adata)
sc.tl.leiden(adata, resolution=0.5, key_added="leiden_r05")
adata.write("results/processed.h5ad")
Workflow
1. Load and validate the object
- confirm orientation is cells by genes
- make gene names unique
- record sample IDs and batch labels before merging or filtering
2. Compute QC metrics and inspect distributions
n_genes_by_counts
total_counts
pct_counts_mt
- optional ribosomal or hemoglobin fractions
Plot distributions before filtering. Thresholds vary by chemistry, tissue, and nucleus versus whole-cell assay.
3. Filter cells and genes
Use dataset-aware thresholds. Good first-pass defaults:
min_genes >= 200
max_genes <= 5000-8000 to remove likely doublets in many droplet datasets
pct_counts_mt < 10-20 depending on tissue stress
min_cells >= 3 for genes
4. Normalize, log-transform, and select HVGs
- normalize with
target_sum=1e4
log1p
- select
2000-4000 HVGs
- save raw counts before heavy transformations
5. Reduce dimensions and cluster
- PCA on HVGs
- neighbor graph using
10-30 PCs and 10-30 neighbors as a starting range
- UMAP for visualization
- Leiden across a small resolution grid such as
0.2, 0.5, 0.8, 1.0
6. Export analysis-ready artifacts
Always save:
- processed
h5ad
- QC tables
- cluster assignments
- publication-ready QC and UMAP figures
Output Artifacts
results/processed.h5ad: main reusable AnnData object
results/cluster_assignments.tsv: barcode plus cluster labels
qc/filter_summary.tsv: counts before and after filtering
figures/umap_leiden.pdf: main embedding figure
Quality Review
- Median genes per cell should be plausible for the chemistry and tissue.
- Mitochondrial fraction should not dominate retained cells.
- PCA variance should decay smoothly rather than showing obvious technical axes only.
- UMAP should be reviewed together with QC metrics and batch labels, not alone.
- Cluster labels should not be finalized before marker inspection.
Anti-Patterns
- reprocessing an already integrated object as if it were raw counts
- using a single universal mitochondrial threshold for every tissue
- interpreting UMAP separation as biology before checking batch and QC covariates
- discarding raw counts needed later for DE or pseudobulk
Related Skills
- Cell Annotation
- Cell Communication
- Trajectory And Lineage
- Multiome And scATAC
Optional Supplements
1---
2name: scrna-preprocessing-clustering
3description: Standard scRNA-seq preprocessing and clustering with Scanpy. Use for QC, normalization, HVG selection, PCA, neighbor graph construction, UMAP, Leiden clustering, and export of an analysis-ready AnnData object.
4tool_type: python
5primary_tool: scanpy
6---
7
8# scRNA Preprocessing And Clustering
9
10## Version Compatibility
11
12Reference examples assume:
13
14- `scanpy` 1.10+
15- `anndata` 0.10+
16- `pandas` 2.2+
17- `matplotlib` 3.8+
18
19Before using code patterns, verify installed versions match the environment:
20
21- Python: `python -c "import scanpy, anndata; print(scanpy.__version__, anndata.__version__)"`
22- If signatures differ, inspect the installed API and adapt the pattern instead of retrying unchanged.
23
24## Overview
25
26Use this skill to turn raw or minimally processed scRNA-seq data into an analysis-ready object with:
27
28- QC-filtered cells and genes
29- normalized expression values
30- highly variable genes
31- PCA and UMAP embeddings
32- Leiden clusters
33- saved `h5ad` artifact for annotation, DE, integration, or trajectory analysis
34
35## When To Use This Skill
36
37- raw 10x matrices, filtered count matrices, or `h5ad` inputs need standard preprocessing
38- the user wants UMAP, clustering, or marker discovery
39- downstream tasks depend on a stable single-cell object rather than ad hoc plots
40
41## Quick Route
42
43- If the input is already a processed `h5ad`, inspect `adata.raw`, embeddings, cluster columns, and QC columns before rerunning preprocessing.
44- If the input is raw counts, do QC first and only normalize after filtering obvious low-quality cells.
45- If multiple batches are present, preprocess cleanly first, then consider integration instead of hiding batch effects with aggressive filtering.
46
47## Progressive Disclosure
48
49- Read [technical_reference.md](technical_reference.md) for QC decision rules, assay caveats, and integration branching.
50- Read [commands_and_thresholds.md](commands_and_thresholds.md) for concrete Scanpy code, default thresholds, and output conventions.
51
52## Default Rules
53
54- Keep raw counts recoverable. Prefer `adata.raw = adata.copy()` before regression or scaling.
55- Report thresholds explicitly. Do not silently drop cells or genes.
56- Show QC distributions before applying hard filters.
57- Use vector outputs such as `.pdf` or `.svg` for final figures when possible.
58
59## Expected Inputs
60
61- 10x directory, `.h5`, `.h5ad`, or count matrix
62- cell metadata if available
63- species context for mitochondrial or ribosomal gene detection
64
65## Expected Outputs
66
67- `results/processed.h5ad`
68- `qc/cell_qc_metrics.tsv`
69- `qc/gene_qc_metrics.tsv`
70- `figures/qc_violin.pdf`
71- `figures/pca_variance_ratio.pdf`
72- `figures/umap_leiden.pdf`
73
74## Preferred Tools
75
76- `scanpy`
77- `anndata`
78- `pandas`
79- `matplotlib`
80- `seaborn`
81
82## Starter Pattern
83
84```python
85import scanpy as sc
86
87adata = sc.read_10x_mtx("counts/")
88adata.var_names_make_unique()
89adata.var["mt"] = adata.var_names.str.upper().str.startswith("MT-")
90sc.pp.calculate_qc_metrics(adata, qc_vars=["mt"], inplace=True)
91
92adata = adata[
93 (adata.obs["n_genes_by_counts"] >= 200)
94 & (adata.obs["n_genes_by_counts"] <= 6000)
95 & (adata.obs["pct_counts_mt"] < 15),
96 :
97].copy()
98
99sc.pp.filter_genes(adata, min_cells=3)
100sc.pp.normalize_total(adata, target_sum=1e4)
101sc.pp.log1p(adata)
102adata.raw = adata.copy()
103
104sc.pp.highly_variable_genes(adata, n_top_genes=3000, flavor="seurat_v3")
105adata = adata[:, adata.var["highly_variable"]].copy()
106sc.pp.scale(adata, max_value=10)
107sc.tl.pca(adata, svd_solver="arpack")
108sc.pp.neighbors(adata, n_neighbors=15, n_pcs=30)
109sc.tl.umap(adata)
110sc.tl.leiden(adata, resolution=0.5, key_added="leiden_r05")
111adata.write("results/processed.h5ad")
112```
113
114## Workflow
115
116### 1. Load and validate the object
117
118- confirm orientation is cells by genes
119- make gene names unique
120- record sample IDs and batch labels before merging or filtering
121
122### 2. Compute QC metrics and inspect distributions
123
124- `n_genes_by_counts`
125- `total_counts`
126- `pct_counts_mt`
127- optional ribosomal or hemoglobin fractions
128
129Plot distributions before filtering. Thresholds vary by chemistry, tissue, and nucleus versus whole-cell assay.
130
131### 3. Filter cells and genes
132
133Use dataset-aware thresholds. Good first-pass defaults:
134
135- `min_genes >= 200`
136- `max_genes <= 5000-8000` to remove likely doublets in many droplet datasets
137- `pct_counts_mt < 10-20` depending on tissue stress
138- `min_cells >= 3` for genes
139
140### 4. Normalize, log-transform, and select HVGs
141
142- normalize with `target_sum=1e4`
143- `log1p`
144- select `2000-4000` HVGs
145- save raw counts before heavy transformations
146
147### 5. Reduce dimensions and cluster
148
149- PCA on HVGs
150- neighbor graph using `10-30` PCs and `10-30` neighbors as a starting range
151- UMAP for visualization
152- Leiden across a small resolution grid such as `0.2`, `0.5`, `0.8`, `1.0`
153
154### 6. Export analysis-ready artifacts
155
156Always save:
157
158- processed `h5ad`
159- QC tables
160- cluster assignments
161- publication-ready QC and UMAP figures
162
163## Output Artifacts
164
165- `results/processed.h5ad`: main reusable AnnData object
166- `results/cluster_assignments.tsv`: barcode plus cluster labels
167- `qc/filter_summary.tsv`: counts before and after filtering
168- `figures/umap_leiden.pdf`: main embedding figure
169
170## Quality Review
171
172- Median genes per cell should be plausible for the chemistry and tissue.
173- Mitochondrial fraction should not dominate retained cells.
174- PCA variance should decay smoothly rather than showing obvious technical axes only.
175- UMAP should be reviewed together with QC metrics and batch labels, not alone.
176- Cluster labels should not be finalized before marker inspection.
177
178## Anti-Patterns
179
180- reprocessing an already integrated object as if it were raw counts
181- using a single universal mitochondrial threshold for every tissue
182- interpreting UMAP separation as biology before checking batch and QC covariates
183- discarding raw counts needed later for DE or pseudobulk
184
185## Related Skills
186
187- Cell Annotation
188- Cell Communication
189- Trajectory And Lineage
190- Multiome And scATAC
191
192## Optional Supplements
193
194- `anndata`
195- `scanpy`