Methods post-mortem / single-cell genomics
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.
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
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
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
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:
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
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:
| Group | donor 1 | donor 2 | donor 3 | donor 4 | mean | sd |
|---|---|---|---|---|---|---|
| Control “normal” | 0.00 | 0.00 | 1.29 | — | 0.43 | 0.74 |
| Rim (lesion) | 1.93 | 4.14 | 2.37 | 2.22 | 2.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
|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
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.
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
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:
| Compartment | “outside” genes | also in non-lesion | indep. signature (aggregate) | status |
|---|---|---|---|---|
| Microglia | 18 | 1 | MS > ctrl, p=5e−39 | aggregate real, tiny |
| Astrocytes | 238 | 101 | MS = ctrl, p=1.00 | collapses |
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
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:
| Gene | in rim | AUC rim>healthy | rim-specific Δ | identity |
|---|---|---|---|---|
| FTL | 75% | 0.72 | 0.08 | ferritin — iron storage |
| FTH1 | 72% | 0.59 | 0.14 | ferritin — iron storage |
| SLC11A1 | 65% | 0.69 | 0.15 | NRAMP1 — metal transport |
| SAT1 | 74% | 0.72 | 0.14 | activated microglia |
| CEBPD | 54% | 0.71 | 0.15 | inflammatory TF |
| TLR2 | 63% | 0.62 | 0.12 | innate immune |
| GFAP astro | 84% | 0.66 | 0.21 | reactive astrocyte |
| VIM astro | 49% | 0.70 | 0.10 | reactive 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
Three avoidable execution errors
pct ≥ 0.25 within the target cell type before a gene is eligible.The checks that mattered — all of them ordinary
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.