← PROJECTS
Scroll move to stir · drag to pan · scroll for story
MERFISH · Mouse-Brain Atlas

Anatomy from RNA alone.

Read the RNA inside an intact mouse brain — one molecule at a time — then rebuild the brain from where those molecules sit.

MOUSE BRAIN · CORONAL / 483 genes / 83,546 cells / ~1.6×10⁸ transcripts / scanpy · squidpy · STalign / CI

MERFISH (multiplexed error-robust fluorescence in situ hybridization) images individual RNA molecules right where they sit in tissue. Hundreds of genes per cell, positions kept — so the anatomy comes from the molecules themselves.

Portfolio repo, not a production pipeline: notebooks and pytest walk a Vizgen coronal cohort through QC, clustering, cell-type mapping, and CCF registration. Synthetic fixtures run offline in CI; live tests hit public downloads when you have network.

METHOD Reading a gene as a barcode

Every gene gets an error-correcting binary code.

MERFISH reads each gene as a binary codeword spread across many imaging rounds — the on/off pattern names the gene. The code self-corrects (16-bit, Hamming-distance-4), so one misread round can't change the answer. That's the "ER" in MERFISH.

PIPELINE Raw imagery to per-cell labels

Six stages, one AnnData object.

Segmentation comes first — it decides what counts as a cell — then QC, clustering, mapping, and atlas registration hand off through the same object.

  1. IngestMERSCOPE mosaics, transcripts, cell-by-gene, boundaries
  2. Segmenttranscript-aware re-assignment (upstream of counts)
  3. QCvs bulk RNAseq + replicate correlation
  4. ClusterScanpy PCA · UMAP · Leiden
  5. Cell typesmarker correlation + bootstrap confidence
  6. Register2D section → Allen CCFv3, per-cell region
VALIDATION Check the counts first

QC before clustering.

MERFISH counts should match bulk RNAseq and reproduce across replicates in the MsBrain_VS38 aging cohort — rendered with seaborn from cohort data.

0.70–0.75
Pearson r · MERFISH vs bulk RNAseq (per gene)
0.98–1.00
replicate ↔ replicate correlation
~1.6×10⁸
transcripts per sample (~74k–87k / FOV)
Four-panel MERSCOPE QC dashboard: total transcript counts, mean counts per FOV, replicate reproducibility heatmap, and MERFISH-versus-bulk-RNAseq correlation
MERSCOPE QC summary. Yield, replicate reproducibility, and the MERFISH↔bulk-RNAseq check, rendered with seaborn from cohort data.
CELL TYPES Mapping with a confidence score

Cell types with a confidence score.

I reimplemented the Allen cell_type_mapper approach on Moffitt 2018 hypothalamus hold-out data: marker-gene matching plus a bootstrap confidence that beats the old cosine heuristic (label only, no score). Fine subtype accuracy within correct classes: 0.82.

0.77
held-out class accuracy (vs 0.71 cosine) · 36,828 cells
0.87
mean per-cell confidence
Four-panel principled cell-type mapping: calibration curve, correct-versus-incorrect confidence histogram, truth-versus-predicted concordance heatmap, and a coronal slice colored by per-cell confidence
Cell-type mapping with a confidence score. Accuracy rises with confidence (top-left); correct calls concentrate at high confidence (top-right); a coronal slice (bottom-right) flags where the 161-gene panel can't resolve a type. The cosine heuristic gives none of this.
Coronal brain slice with the ependymal/glial cluster highlighted along the ventricle lining
Cluster 22 — ependymal / glial. Aqp4, Gfap, Mlc1 lining the ventricles.
Coronal brain slice with an inhibitory-neuron cluster highlighted as two symmetric arcs
Cluster 24 — inhibitory neurons. Gad1, Slc32a1, Cckar, recovered bilaterally.
SEGMENTATION The decision that sits upstream

Segmentation sits upstream.

Draw the cell boundary wrong and everything downstream shifts. On shared ground truth, transcript-aware assignment hits 0.76 accuracy (Voronoi 0.70, nucleus-only 0.17); downstream Leiden ARI reaches 1.00 vs 0.96 baseline. Three methods benchmarked end-to-end (Baysor / proseg / segger-style).

Four-panel segmentation comparison: ground-truth transcripts, transcript-assignment accuracy bars, downstream Leiden ARI bars, and a crop of boundary transcripts the transcript-aware method rescues
Segmentation changes downstream cell types. Transcript-aware assignment (Baysor / proseg / segger-style) rescues the boundary molecules a Voronoi baseline misassigns. A guarded cellpose_sam_segment() hook runs Cellpose-SAM on DAPI mosaics when installed.
REGISTRATION The hardest part of a new scan

Register the section to CCFv3.

Each cell needs a brain-region label — anchor the AP plane, warp with STalign, lift labels from the Allen atlas. The registration core adds per-cell confidence and a QC score that separates good fits from deliberately bad ones (0.14→0.96 on synthetic misalignment). High-confidence calls hit ~98–99% at every ontology depth on that synthetic geometry; 670 leaf regions roll up the ontology tree.

STalign LDDMM, ground-truthed

On a slice cut from a known plane, STalign places it to 46.7 µm — under half a voxel — and gets 0.89 of per-cell labels right, in about two minutes on CPU. A real 2D→3D fit, not a stub.

Three-panel real STalign result: input 2D section with true regions, regions assigned after warping into the CCFv3, and an anterior-posterior position histogram peaking at the true plane
STalign 2D→3D, validated. Input section (left), regions STalign assigns after warping into the CCFv3 (center, near-identical), and the recovered AP position peaking at the true plane (right).

Auto AP-anchor for STalign's init-sensitivity

STalign can misfire on its starting guess — a posterior slice landed 1.44 mm off before the anchor. Sliding the section against every atlas plane fixes depth first: posterior AP error drops 1440→148 µm, thalamus IoU on that scan goes 0.23→0.68, and all three thalamic test sections align (was 1/3). Anchor logic is unit-tested; posterior recovery is live-tested.

Two rows of three coronal scans: top shows ground-truth thalamus in crimson across anterior, mid, and posterior sections; bottom shows the thalamus recovered by STalign in green, including the posterior bilateral clusters
Thalamus across three scans. Truth (crimson, top) vs recovered by STalign→CCFv3 (green, bottom), including the posterior bilateral clusters the bare fit missed. The anchor is unit-tested; the posterior recovery is live-tested.
PROOF Tested on real data

Live test on Moffitt 2018.

Moffitt et al. hypothalamic MERFISH — 73,626 cells, 160 genes. Unsupervised Leiden (27 clusters) vs 16 published classes: ARI 0.28 (random ≈ 0), concordant UMAP, real coronal anatomy.

Four-panel live validation: two UMAPs colored by Leiden clusters and by published cell classes, a coronal spatial slice, and a Leiden-versus-published concordance heatmap
Live validation on real MERFISH. Unsupervised Leiden (27 clusters) vs 16 published classes: concordant UMAP, coronal anatomy, and a near-diagonal concordance heatmap. Generated by the pytest suite (34 offline / 41 total, 7 live); offline tests run in CI on Python 3.12.
CONTEXT Where MERFISH sits in the field

Imaging vs sequencing.

MERFISH is one of three imaging platforms that read single molecules in place. Imaging trades panel size for subcellular precision; sequencing trades precision for whole-transcriptome reach.

PlatformChemistryMax panelResolution
Vizgen MERSCOPEthis project MERFISH — iterative smFISH barcoding ~1,000 genes 100 nm pixel
10x XeniumPrime 5K Padlock-probe ligation + RCA ~5,000 genes XY <30 nm
Bruker CosMxWTX Cyclic FISH, no RT/PCR ~19,000 genes ≤100 nm FOV-scale

The field is standardizing on SpatialData, segmentation is the active research front, and panels keep growing toward whole-transcriptome imaging.

SCOPE What's implemented vs what's wired-in

Repo status.

Light core in CI; heavy atlases and engines plug in behind the same interface.

  • implementedScanpy pipeline, cell-type mapper, segmentation benchmark, and the registration core (geometry, label transfer, uncertainty, QC), all covered by offline pytest.
  • validatedAllen CCFv3 via brainglobe, and the STalign LDDMM deformable backend with a ground-truthed fit, in an isolated NumPy-2 / Python-3.12 environment.
  • wired-inDeepSlice, ANTs, and the Allen cell_type_mapper are stubbed behind the live interfaces with install hints. They need large downloads, not new architecture.

Honest caveat (also in the repo): the calibration and QC numbers use a synthetic registration error on real atlas geometry — so they test the math, not an engine's end-to-end accuracy. The STalign result is a real fit.

NOTES Engineering

A few choices.

Cell-type and region calls both ship calibrated confidence — same pattern, two stages. Every stage has a no-download synthetic path so pytest runs in CI without atlas downloads; real engines slot in behind the same function signatures. STalign upstream still pins numpy==1.23; I install it --no-deps beside NumPy 2.4 in one venv rather than maintaining a separate STalign-only environment.

Python 3.12 scanpy squidpy AnnData STalign LDDMM brainglobe Allen CCFv3 Leiden Cellpose-SAM NumPy 2.x pytest · CI Observable