Skip to content

CNMFe — A Conceptual Walkthrough

Written for someone fluent in calcium imaging who would rather not wade through linear algebra. Every step is explained by what it does and why, with the statistical machinery described in words rather than equations. For the actual equations, see algorithm math; for where each step lives in the code, see architecture.


The problem, stated cleanly

You have a one-photon movie: T frames of a field of view containing some unknown number of neurons, K. Each neuron has two things that don't change over the recording and one that does:

  • a spatial footprint — the set of pixels it illuminates and how strongly each pixel belongs to it (essentially its soma profile as seen through the tissue), and
  • a fluorescence trace — its baseline plus the transients it emits when it fires.

What the camera records at a given pixel, over time, is a sum: every neuron whose footprint covers that pixel contributes its trace (scaled by how much that pixel belongs to it), on top of a large diffuse background, plus noise. The neurons are mixed together in the image, and worse, they're mixed into a background that dwarfs them.

CNMFe's job is to invert that mixing — to recover the individual footprints and traces from the blended movie. This is a source-separation (demixing) problem, conceptually identical to recovering individual speakers from a single microphone that recorded a crowded room.


The one idea worth internalizing: the movie is a product of two small things

CNMFe assumes the movie is well explained by a small number of sources, each of which is one fixed spatial pattern multiplied by one time course. Stack the K footprints into a set of images (call it A) and the K traces into a set of time series (call it C); the model says the movie ≈ A combined with C (each pixel's movie = sum over neurons of footprint-weight × trace), plus background and noise.

That "a handful of sources generate the entire movie" claim is the whole trick. Instead of treating every pixel at every frame as an independent number, you commit to the idea that they are all generated by K footprints and K traces. Fitting the model means choosing the footprints and traces whose combination best reproduces what the camera actually saw. In the literature this is a matrix factorization — you're factoring the big movie into two much smaller pieces.

Three assumptions turn this generic idea into something that recovers neurons specifically (this is the "constrained" in CNMFe):

  • Non-negativity. Footprints and fluorescence can't be negative — light only adds. Forcing the factors to be non-negative is what makes them come out looking like real cells and real transients instead of abstract patterns that merely happen to fit.
  • Sparsity and compactness. A neuron occupies a small, connected patch, not the whole frame. The fit actively prefers footprints that are small and local.
  • Calcium dynamics. Each trace should look like calcium — sharp rises, exponential decays — not arbitrary wiggles. This constraint lives on the temporal side (see the deconvolution step).

The rest of the pipeline is machinery for fitting this model on messy 1p data: stabilize the movie → get a rough first guess of the sources → model the background → alternately sharpen the shapes and the traces → tidy up.


Step 1 — Motion correction

The brain and the scope drift, so a pixel in frame 1 isn't the same tissue as that pixel in frame 500. Before you can claim a footprint is fixed, you have to make it actually fixed by registering every frame to a common reference (the average of the first few hundred frames).

The registration uses phase correlation — comparing frames in the frequency domain, which finds the translation between them with sub-pixel accuracy (it can detect and undo a 0.3-pixel shift, not just whole-pixel jumps). Sub-pixel matters here: an uncorrected drift of a pixel or two smears a soma across its neighbours and corrupts every downstream footprint.


Step 2 — A noise yardstick for every pixel

Each pixel flickers a little even when nothing is happening. We measure that per-pixel noise level from the fast fluctuations in its time course (calcium signals are slow; sensor and shot noise are fast, so the high-frequency content is essentially pure noise).

This isn't cosmetic — it becomes the ruler used later to decide whether a candidate is a real cell or just a bright patch of noise. "How big is this signal relative to this pixel's own noise" is a far better question than "how bright is it."


Step 3 — Where are the cells? (summary images)

Two summary images collapse the whole movie into a "where are the neurons" map:

  • CORR (local correlation image). At each pixel, how correlated is its time course with its immediate neighbours? A soma spans several pixels that rise and fall together, so it lights up as a compact correlated patch; uncorrelated noise does not.
  • PNR (peak-to-noise ratio). At each pixel, how tall is its largest transient compared with the noise yardstick from Step 2? Real events tower over noise.

Their product, CORR × PNR, is the seed map: pixels that are both locally correlated and have large transients. Before computing these, the movie is passed through a center-surround filter (a difference-of-Gaussians band-pass tuned to the cell scale) — this suppresses the smooth, low-spatial-frequency background and enhances blobs the size of a soma, so the summary images reflect cells rather than the glow.


Step 4 — A rough first guess, one neuron at a time (greedy initialization)

We build the initial set of sources by peeling neurons off the seed map greedily:

  1. Take the strongest remaining seed pixel.
  2. In a small patch around it, gather the pixels whose time courses co-vary with the seed — that's a first estimate of this neuron's footprint.
  3. Read off its trace (roughly, the average of those pixels over time).
  4. Subtract this neuron's contribution from the movie.
  5. Recompute the seed map on what's left, and repeat.

Removing each neuron before looking for the next is what prevents one bright cell from generating a cluster of false seeds around itself. We stop when nothing left in the residual is bright enough to be a cell. The result is a complete but rough guess — good enough to seed the refinement, not the final answer.

This peel-one-source-at-a-time strategy is the same instinct as un-mixing a band recording by removing the loudest instrument first: once the drums are gone the bass is obvious, and so on.


Step 5 — Modelling the background (the ring — this is the heart of CNMFe)

Even with the cells accounted for, a large, spatially smooth background remains: the diffuse fluorescence from out-of-focus cells, neuropil, and vasculature that drifts slowly across the whole field. Ordinary NMF has no defence against this and ends up describing the background as if it were extra "neurons."

CNMFe's answer: predict each pixel's background from a ring of pixels about one neuron-radius away from it. The logic has two halves. Because the background is spatially smooth, a pixel's neighbours share almost the same background value — so a weighted combination of them is an excellent predictor. And because the ring deliberately skips the pixels immediately around the target (the ones that would belong to the pixel's own neuron), the background estimate captures the shared glow without soaking up genuine neural signal. The ring weights are fit once, as a straightforward best-linear-predictor regression, then used to subtract a background estimate from every frame.

If every window on your street brightens and dims together, you can predict your own window's brightness from your neighbours' — while ignoring your own lamp.


Step 6 — Sharpening shapes and traces by taking turns

You can't solve for the footprints and the traces simultaneously — but if you fix one, solving for the other is a clean regression. So CNMFe alternates: hold the traces fixed and re-estimate every shape, then hold the shapes fixed and re-estimate every trace, and repeat. Each pass fits the movie strictly better than the last; two or three rounds are enough to settle.

Update the shapes (spatial update). With the traces fixed, ask at each pixel: of the neurons whose footprints reach this pixel, how much of this pixel's time course does each one explain? That's a small regression per pixel. Crucially it carries a sparsity penalty (a LASSO) — a pressure that drives weak, uncertain pixel-to-neuron weights all the way to zero rather than leaving a faint smear. That's what keeps footprints tight and stops one cell's footprint from bleeding into its neighbours.

Update the traces (temporal update). With the shapes fixed, re-estimate each neuron's trace: subtract all the other neurons from the movie, project what remains onto this neuron's footprint to read out its time course, then denoise that time course with the calcium-dynamics model (next section).

Merge duplicates (merging). Two seeds sometimes land on the same cell. We merge a pair when their traces are nearly identical and either their footprints overlap or their centroids sit close together.

Why both spatial rules? After footprints are cleaned up (we keep each one's largest connected blob), two duplicates of the same neuron can end up with no pixel overlap at all — each kept only the bright core around its own peak. The centroid rule catches those: the cleaned blobs don't touch, but their centres are still right on top of each other.


Step 7 — Calcium dynamics and deconvolution (the AR model)

You already know the shape of a calcium transient: a fast rise when the cell fires, then an exponential decay as the indicator unbinds. The AR(1) ("autoregressive") model is just the compact way to state that: the fluorescence in each frame equals a fixed fraction g of the previous frame's fluorescence, plus whatever new spiking input arrived this frame. A fraction slightly below 1 (say 0.9) is an exponential decay; the added input is the spike.

Deconvolution runs that model backwards. Given the smooth, noisy trace, it recovers the sparse set of spike times and amplitudes that best explains it — turning a blurry fluorescence curve into an estimate of the underlying activity. The solver is OASIS, which does this exactly and very fast.

If you know a bathtub drains at a fixed 10% per second, then from the water level over time you can reconstruct exactly when, and how much, water was poured in.

Where does the decay rate g come from? You can estimate it from the data, and on clean recordings that's fine. But on 1p data the slow background drift contaminates the estimate and biases it toward "the indicator decays very slowly" even when it doesn't — which over-smooths the traces and blurs spike timing. The robust fix is to tell the pipeline what you used: set decay_time_ms (e.g. ~140 for GCaMP6f, ~180 for jGCaMP8m) and frame_rate_hz. The pipeline converts those into the expected g and uses it as a Bayesian prior — it anchors g at the biologically sensible value and only lets the data pull it away if the recording strongly disagrees. (A "prior" here just means a belief you hold before seeing the data; the fit blends that belief with the evidence instead of trusting a noisy data estimate outright.) The indicator table is in the API reference.


What you get out

  • A — each neuron's spatial footprint (which pixels it covers, and how strongly).
  • C — each neuron's denoised calcium trace: what OASIS believes the fluorescence is, given the AR model. Clean, smooth, ideal for spike-based analyses.
  • S — each neuron's inferred spike train (the deconvolved events).
  • YrA — the residual at each footprint. C + YrA is the noisier but shape-faithful trace: what is actually in the data at that footprint after removing the other neurons.

The whole thing is a cocktail-party un-mixing: who is present (footprints), when each spoke (spike trains), and the actual waveform of each voice (traces).

Two flavours of the trace, and when to use which. C is the model's idealized version — smooth and AR-shaped, best when you care about spike timing and clean event detection. C + YrA is the empirical version — it keeps the real fluctuations in the data at that footprint, so its shape is more faithful to the underlying biology. Prefer it when you're correlating a trace against an external signal (behaviour, LFP, another imaging channel) and don't want the AR smoothing to distort the comparison.


Why 1p imaging makes this hard

In two-photon imaging, only a thin focal plane is excited, so the out-of-focus background is small and standard demixing methods cope.

In one-photon (miniscope) imaging, the whole illuminated volume fluoresces at once — neuropil, axons, vasculature, out-of-focus somata — producing a background that is both huge and spatially correlated. Generic NMF cannot tell that correlated background apart from real cells and folds it into spurious sources. CNMFe's ring-background model is the piece built specifically to strip that correlated background away, leaving the compact, structured neural sources behind — which is exactly why it's the standard tool for miniscope data.