Bioinfo, bench to analysis · an interactive tutorial
⭑ Try OmicOne
Chapter 6Analysis

Quality control: which cells to keep

Not every barcode Cell Ranger calls a cell is a good cell: some are broken cells, some are empty droplets that slipped through, some are doublets. Quality control finds them with three numbers per cell: total UMIs, genes detected and mitochondrial fraction. Each number traces back to a bench step.

Three metrics, three bench sources

Metric Low suggests High suggests Bench source
nCount_RNA Broken cell, empty droplet Doublet, or a naturally large cell Dissociation damage (ch. 1), loading (ch. 2), depth (ch. 4)
nFeature_RNA Same; few genes despite normal UMIs means a few genes dominate Doublet Same, plus library complexity (ch. 3)
percent.mt — Damaged or dying cell Dissociation, freeze–thaw, waiting (ch. 1)

In Seurat the mitochondrial fraction is computed like this (human genes start with MT-, mouse with mt-):

obj[["percent.mt"]] <- PercentageFeatureSet(obj, pattern = "^MT-")

Read the three together. The classic broken cell has few UMIs and a high mitochondrial fraction; a cell with a raised mitochondrial fraction but normal UMIs may be a real, metabolically active cell type. The ribosomal protein fraction, the haemoglobin fraction and the doublet score from chapter 2 add further evidence.

Drag the thresholds on pbmc3k

Drag the QC thresholds on pbmc3kReal data
Loading data…

The widget holds all 2,700 cells of pbmc3k. The left plot shows UMI count against mitochondrial fraction, the right one genes against UMIs, with the current thresholds as dashed lines. Start with the “Seurat tutorial thresholds” button: it keeps cells with 200–2,500 genes and less than 5% mitochondrial reads, leaving 2,638. Look at where the removed cells sit on the scatter plot.

obj <- subset(obj, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)

Fixed thresholds are simple, but they were chosen for this one dataset. The alternative is an adaptive MAD threshold: take the median on the log scale and flag cells more than a few MADs (median absolute deviations) away from it. It adjusts to the data, which suits samples from different tissues and depths. OmicOne’s defaults are 5 MADs for UMI and gene counts (log scale) and 3 MADs, upper side only, for the mitochondrial fraction. Switch between the two modes in the widget and compare which cells each removes.

Common pitfalls

  • Copying 200–2,500 and 5% to other data. pbmc3k is v1 chemistry with few genes per cell; on data from newer chemistries an upper limit of 2,500 removes many healthy cells.
  • Setting the lower bound too high. RNA-poor cells such as platelets and resting lymphocytes naturally have few UMIs; a hard floor deletes the whole type.
  • Checking the threshold but not who was removed. After clustering, look back: are removed or borderline cells concentrated in one cluster?
  • Expecting QC to remove ambient RNA. Filtering removes bad cells; the background on the cells you keep needs SoupX, CellBender or similar.