Note
Why this matters.
Every downstream geometric step (PCA, clustering, UMAP) treats the post-QC matrix as ground truth.
Garbage in → confidently-wrong clusters out.
There is no “fix the clustering” — you have to fix the QC.
n = cells is the most common mistake in the fieldBulk: nearly every gene is detected in every sample (~5% zeros)
Smart-seq2: ~50–60% zeros — moderate dropout but rich per-cell signal
10x 3’ v3 droplet: ~90–95% zeros — most (cell, gene) pairs are zero
The implication for analysis: every step has to handle counts that are mostly zero.
That’s why we have specialized normalisation (SCTransform), HVG selection, and graph-based clustering instead of the bulk RNA-seq toolkit.
Tip
A 4-step mental compression. From here on out, every chunk of the pipeline (a) cleans something, (b) puts things on a sensible scale, (c) finds structure, (d) names that structure with biology.
A droplet that “looks like a cell” in your matrix may actually be
an empty droplet with ambient soup
a dying cell leaking cytoplasm
two (or more) cells in one droplet
a real cell
QC is how we triage them.
nFeature_RNA: genes detected per cell — proxy for capture qualitynCount_RNA: total UMI counts per cell — proxy for sequencing depth in that cellpercent.mt: % reads mapping to mitochondrial genes — proxy for stress / dying cells (cytoplasmic mRNA leaks before mitochondrial mRNA)Note
Typical “healthy” thresholds for 10x 3’ v3 on dissociated tissue. These are starting points, not rules — always look at the distributions first.
| Metric | Typical lower | Typical upper | Notes |
|---|---|---|---|
nFeature_RNA (genes/cell) |
200–500 | 2,500–6,000 | Upper bound is dataset-specific; doublets push past it |
nCount_RNA (UMIs/cell) |
500–1,000 | ~50,000 | Very high counts often = doublets, very low = empty |
percent.mt |
— | 5–10% (PBMC), 15–20% (tumor / fragile tissue) | Nuclei (snRNA) should be < ~1–2% |
Warning
Watch-outs.
nCount_RNA distribution often means two cell sizes (e.g., lymphocytes + neutrophils), not doublets — don’t gate it away.Ambient RNA — raster reference
EmptyDrops or the Cell Ranger knee-pointSoupX, DecontX, or CellBender| Tool | Ecosystem | Notes |
|---|---|---|
scDblFinder |
R / Bioc | Fast, recommended default |
DoubletFinder |
R | Needs pK sweep |
Scrublet |
Python | Classic choice in scanpy flows |
Warning
Doublet detection runs per sample, not on a merged object.
Note
Seurat v5 note.
merge() in Seurat v5, the RNA assay stores split layers (counts.CTRL, counts.STIM, …).JoinLayers() after merging the per-sample objects so that downstream steps see a single layer.
NormalizeData in Seurat) — fast, simple, the default in most tutorialsSCTransform in Seurat) — models the negative-binomial mean–variance relationship; often better for low-count cells but slowerTip
When to reach for SCTransform: noisy or very low-depth data (~3,000 UMIs/cell median), or when you can see depth artefacts in your UMAP. For typical 10x v3 data, log-normalization is fine.
Warning
Don’t normalize twice. SCTransform replaces NormalizeData + ScaleData. Running both on the same object stacks transforms and breaks downstream assumptions.
.
FindVariableFeatures()sc.pp.highly_variable_genes()Note
Typical settings: nfeatures = 2000 is the Seurat default and a defensible choice for most datasets. Bump to 3,000–5,000 for atlas-scale or highly heterogeneous data; drop to 1,000 only if your dataset is small and unimodal.
Warning
Pitfalls in HVG selection. - Including mitochondrial / ribosomal genes as HVGs lets technical variation drive your PCs — Many pipelines exclude these patterns by default. - If you regress out cell-cycle scores, do it before HVG selection, otherwise cycling genes dominate the variable list.
FindVariableFeatures(seu, selection.method = "vst", nfeatures = 2000) returns the top 2,000 such genes, ranked by standardized residual variance. VariableFeaturePlot() is exactly this picture.LYZ, S100A9, CD74, MS4A1, …) — you should recognise them.ifnb datasetThe workshop dataset — the Kang et al. PBMCs we call “ifnb”
Single-cell RNA-seq data of human peripheral blood mononuclear cells (PBMCs).
Two conditions: resting (CONTROL) and interferon-beta (IFN-β) stimulated (STIM) cells
Loaded via muscData::Kang18_8vs8()
Starts at ~24,500 annotated singlets across CTRL and STIM.
After the QC filters in Tutorial 01 you should retain ~23,000 cells.
Tip
Doublet detection in this tutorial runs per sample (CTRL then STIM separately) with scDblFinder.
merge() and JoinLayers() before the final filter.percent.rb and when to use itTutorial 01 also computes percent.rb (ribosomal-protein fraction). It is not a standard QC filter; rather:
percent.rb (>50%) in a cluster often signals a metabolically active or activated state, not a low-quality cell.percent.rb, check whether library prep differed.percent.rb by default — just note it.Single Cell RNA-seq Workshop · Lecture 01