Methods post-mortem  /  single-cell genomics

The envelope that was never there

How a “healthy expression” baseline drawn from too few control cells turned pure sampling noise into a false discovery—the controls that caught it, and the canonical rim signature the same method recovers once the baseline is drawn correctly.

Data GSE180759 · GSE301908 (human MS brain, snRNA-seq) Compartments microglia, astrocytes Outcome mis-drawn, then recovered

Here is a mistake worth publishing, because it is invisible. No number was miscomputed. Every line of code did exactly what it said. And yet the analysis produced a list of “disease genes” that were nothing but the noise floor of single-cell RNA-seq, dressed up by a statistic that had been asked to measure something it could not see.

The specific blunder is not exotic—a skipped detection filter and a per-gene statistic run on three donors, the kind of thing a checklist catches. Owning that plainly matters more than dramatising it. What is worth your time is the mechanism, because it is subtle enough to fool careful people and it generalises well beyond this dataset: a statistic will place whatever boundary you ask for, whether or not it has the data to place it. Undersampling reads as absence; absence reads as departure; a departure reads as a discovery. This is a walk through each link of that chain, on real numbers—ending with what the analysis looks like once it is done correctly.

01 The idea

Don’t ask an atlas to find the lesion. Ask it to define “normal.”

The premise is genuinely good. Instead of comparing diseased tissue to adjacent diseased tissue, you build a healthy envelope—the normal range of expression for each gene, within each cell type—and then flag where the diseased cells fall outside it. Disease becomes a departure from the normal cloud. This is exactly how a clinical reference range works, and it is the correct mental model: expression “normal” is a distribution, never a point.

The healthy envelope here came from the 3 control-donor brains already inside the discovery dataset—non-diseased, and processed on the identical platform as the lesion tissue. That platform-matching is the smart part: it removes the batch and cell-type-matching confounds that would sink an external atlas. Everything about the design was defensible. The failure was entirely in the execution.

02 The seductive result

It returned exactly the shape of answer you hope for

Scored against that healthy envelope, the rim (the chronic-active lesion edge) lit up. In astrocytes, 238 genes fell outside the normal range. In microglia, a tighter 18-gene rim-specific set—confound-subtracted against non-lesion tissue, filtered for stress-response artifacts, and seemingly reproduced in an independent cohort at 17 of 18.

That last check is worth pausing on, because it is a trap inside a trap: it only confirmed the genes were low in healthy tissue—trivially true of almost any rare gene—not that they were elevated in disease. A weak test wearing the costume of a strong one. Yet on the surface the result had everything: a plausible cell-type story, a specificity filter, an independent-dataset check. It survived a first round of controls. Had the pipeline stopped here, those genes would have gone into a figure.

A wrong number screams. A wrong method whispers, and it whispers in exactly the vocabulary you were hoping to hear.

03 The terrain

Most of the transcriptome is noise floor

Before the smoking gun, one fact about single-cell data that the whole mistake rests on. In this discovery matrix—25,476 genes across 66,432 nuclei—detection is astonishingly sparse:

94.2%
of the matrix is zeros
71.5%
of genes detected in <5% of cells
1.4%
of genes robustly expressed (>50% of cells)

Seven in ten genes live at the noise floor: detected in a handful of cells, at one count each, indistinguishable from dropout. This is not a quality problem—it is the normal condition of the technology, driven by ~10–30% capture efficiency stacked on genuinely low transcript counts. It is also the reason every standard pipeline filters genes by detection rate before testing them. The envelope metric did not.

04 The smoking gun

The boundary was drawn on data that didn’t exist

Take CDK4, one of the flagged microglial genes. Here is the raw material the envelope was built from—per-donor pseudobulk expression (log-CPM), control versus rim:

CDK4 — per-donor pseudobulk, the envelope’s raw material
Groupdonor 1donor 2donor 3donor 4meansd
Control “normal”0.000.001.290.430.74
Rim (lesion)1.934.142.372.222.66

Look at the control row: [0.00, 0.00, 1.29]. That is not a distribution. It is two misses and a lucky hit. When your three estimates of “normal” are two zeros and a 1.3, you do not know what normal is—you have not measured it. The metric, however, read mean = 0.43 and treated it as a confident “normal ≈ 0.” It mistook undersampling for absence.

Three execution choices turned that mistake into a large, significant-looking departure:

Why a normal gene landed outside

  1. “Normal” was never measured. A gene detected in ~3% of cells lands in a 137-cell control donor in ~4 cells—or none. The control envelope for such genes is pure sampling luck, biased toward zero.
  2. The two sides weren’t on equal footing. Rim had 2,873 cells; control had 289 (one donor: 10 cells). Ten times the cells means ten times the chances to catch a rare transcript—so rim reads ~2.7 and control reads ~0.4 for the same gene at the same per-cell rate. The gap is a cell-count artifact, not biology.
  3. A variance floor amplified it. Because the control sd was tiny and unstable, a moderated-sd floor shrank the z-score’s denominator—inflating a sampling-noise gap into |z| > 2, “outside the envelope.”

The proof that the gene is normal is in the cells themselves: CDK4 is detected in 1.9% of rim microglia and 4.5% of healthy microglia. If anything it is lower at the lesion. The departure was never in the biology. It was in the boundary.

05 The test that separates signal from noise

A real marker concentrates. Noise stays flat.

The clean way to tell a genuine cell-type gene from noise-floor debris is to ask a single question: does its detection rate jump when you switch the denominator from “all cells” to “its own cell type”? A real microglial gene is globally sparse but locally dense. Noise is sparse everywhere.

% of all cells expressing % of microglia (marker) % of microglia (flagged)

All bars share one scale (full width = 50% of cells). A real marker’s microglia bar leaps above its all-cells bar—8–11×. The flagged genes barely move: they concentrate in no cell type at all, which is the signature of dropout noise, not biology.

This concentration test is not ad hoc; it is what the established specificity metrics all encode. The τ (tau) index (≥ 0.8 for “tissue-specific”), the Human Protein Atlas 4×-enrichment rule, and Seurat’s marker defaults (min.pct = 0.25) are all asking the same thing: is the gene detected, and enriched, within the population that matters? CSF1R clears the min.pct floor at 48%; APOL2 fails it at 2.8%. That one filter—standard, benchmarked, one line of code—would have excluded all 18.

06 What the controls caught

Under scrutiny, one story shrinks and the other collapses

The saving grace was that the analysis kept going—past the seductive result into adversarial controls: subtract the general-disease effect (rim vs. non-lesion tissue), test the whole signature in an independent cohort, and stress-test the flagged genes cell by cell. Here is what was left standing:

The verdict: confound-subtraction + independent aggregate-signature test
Compartment“outside” genesalso in non-lesionindep. signature (aggregate)status
Microglia181MS > ctrl, p=5e−39aggregate real, tiny
Astrocytes238101MS = ctrl, p=1.00collapses

One caveat about that last column, since precision is the whole point: the independent test evaluates the whole signature as one aggregate score, not the 238 or 18 genes individually. It tells you whether the compartment’s overall program replicates—the per-gene fate of the flagged lists is settled separately, in the next section.

Astrocytes evaporated. Of 238 “outside” genes, 101 were already outside in non-lesion diseased tissue—a general disease-brain effect, not a rim signal. And the aggregate astrocyte program flatly refused to replicate: it scored lower in disease than in healthy (p = 1.00). The big, exciting number was also the most confounded.

Microglia survived—but only in aggregate, and only barely. The signature is genuinely elevated in independent disease microglia, yet by a whisker: medians 0.150 vs 0.143. That p-value of 5×10−39 is real and trivial at once—bought entirely by 5,423 cells (significance is not effect size). What replicates is the aggregate; every individual per-gene call, as the next section shows, does not.

07 Done right

Done right, it recovers the actual rim

Two fixes turn the phantom generator back into the method it was meant to be. The first is trivial: the missing detection floor. Apply min.pct ≥ 0.25 and the underpowered version’s lists nearly vanish—0 of 19 microglial phantoms and 236 of 238 astrocyte phantoms are gone. Necessary, but it only removes noise; it adds nothing.

The second fix is the one that matters, and it was the original design all along: draw “normal” from a well-powered healthy reference, not three in-dataset donors. Score the rim cells against an independent healthy cohort of 5,423 microglia (~19× the 289 we misused), with the cross-platform batch handled two ways: a rank-based effect size (immune to scale differences) and a non-lesion subtraction—since the batch offset is shared by all cells from the source dataset, scoring rim and non-lesion tissue against the same reference and differencing cancels it. What survives is small, coherent, and unmistakably real:

Rim-specific departures vs a well-powered healthy reference (rank-based, batch-differenced)
Genein rimAUC rim>healthyrim-specific Δidentity
FTL75%0.720.08ferritin — iron storage
FTH172%0.590.14ferritin — iron storage
SLC11A165%0.690.15NRAMP1 — metal transport
SAT174%0.720.14activated microglia
CEBPD54%0.710.15inflammatory TF
TLR263%0.620.12innate immune
GFAP astro84%0.660.21reactive astrocyte
VIM astro49%0.700.10reactive astrocyte

This is the signature that defines the chronic-active rim. Ferritin (FTL, FTH1) and metal transport (SLC11A1) are the molecular substrate of the iron-laden microglia that give the rim its paramagnetic MRI signal; TLR2, CEBPD and SAT1 are their activation program. In astrocytes, GFAP and VIM—the textbook reactive pair. The non-lesion subtraction is visibly working: ferritin is elevated in all disease microglia (AUC 0.64 in non-lesion tissue) but more at the rim (0.72), and only that rim-specific excess survives. Just 33 of 1,286 tested microglial genes pass—the differencing is removing the common shift, not manufacturing signal.

Same idea, opposite outcome

Underpowered reference (3 in-dataset controls) → APOL2, TEK, obscure ncRNA → artifacts.
Well-powered reference (5,423-cell healthy cohort) → FTL, FTH1, SLC11A1, GFAP, VIM → canonical rim biology.

Honesty about the ceiling: the effect sizes are gradients, not switches (AUC 0.6–0.72), and a rank-plus-subtraction scheme tames cross-platform batch without fully eliminating it—the biological coherence is what certifies the result, not the statistics alone. But the verdict is no longer “a defensible method we couldn’t run.” Run as designed, it works.

The lessons

What to take to your own pipeline

Three avoidable execution errors

  • No detection floor. Testing genes at the noise floor guarantees noise-floor results. Require pct ≥ 0.25 within the target cell type before a gene is eligible.
  • A variance floor on n = 3. Moderating the standard deviation didn’t stabilise the estimate—it manufactured the false departures by shrinking the denominator.
  • Asymmetric sampling. 2,873 vs 289 cells were compared head-to-head. CPM normalisation does not rescue detection-rate asymmetry for rare genes; downsample, or don’t call per-gene.

The checks that mattered — all of them ordinary

  • Run the negative control before interpreting. The rim-vs-non-lesion subtraction and the independent-cohort test are the deliverable—not the flashy positive. If nothing has been run to kill a finding, it is a hypothesis, not a result.
  • A boundary is only as real as its data. When a “normal” thing lands outside the envelope, suspect the envelope. Per-gene boundaries drawn from 3 donors are undrawable for 70% of the transcriptome.
  • Guardrails belong in code, not in prose. A caveat mentioned in a sentence and then not enforced by the pipeline is decoration. The filter has to make the phantom impossible to draw.
  • Trust the aggregate, distrust the list. What replicated was the whole-signature, well-powered, per-cell view. Every seductive per-gene call dissolved on contact with scrutiny.

None of the checks that caught this were clever; that is rather the point. The metric was the sophisticated part, and the metric was wrong. What separated a finding from an artifact was the willingness to run the ordinary control that could kill it—and to not ask a statistic for a boundary the data cannot support. A statistic will always place the boundary you request, whether or not it has the cells to place it. The discipline is in declining to ask when they aren’t there.