Transient detection#
Why transient detection?#
The indicator brightness rises and falls with whichever underlying biological signal the indicator is engineered to report (intracellular calcium for GCaMP, extracellular dopamine for sensors like dLight, and so on for serotonin, acetylcholine, voltage, and the rest of the indicator catalogue). A brief, large upward deflection in the trace therefore corresponds to a brief, large excursion in that local signal: a bout of population activity, a transmitter release event, or a shift in release-uptake balance, depending on which indicator is in use.
Transient detection (also called peak detection) is the analysis that extracts the times of those deflections. The resulting event list is useful for relating activity to other observables (behavioural timestamps, drug administration, sensory stimuli, signals recorded simultaneously from other regions), for aggregating into a session-level event rate or mean amplitude that compares across conditions, and for cross-correlating event streams between regions to extract timing relationships independent of slow shared drift.
Detecting transients#
The basic detector is conceptually simple. To flag samples that are anomalous relative to the rest of the trace, we characterise that trace by two summary numbers: a typical level and a noise scale (how far a typical sample sits from the typical level). A sample more than K noise scales above the typical level is counted as a transient, where K is a sensitivity multiplier the user chooses (larger K means fewer detections of any kind, real or noise; typical photometry defaults sit around 3). The output is a discrete list of (time, amplitude) events extracted from a continuous recording.
Importantly, the detector runs on the preprocessed fluorescence trace, not on the raw recording. Two upstream cleanup steps are typically applied first: an isosbestic correction that removes optical artifacts shared between the indicator-sensitive and isosbestic channels, and z-score normalization that puts the trace on a noise-relative scale where detection thresholds are interpretable across recordings. What survives is, in principle, a trace whose deflections are predominantly indicator-driven; the detector takes that on faith and operates on whatever comes out of preprocessing.
The following sections cover how to improve this basic approach to deal with complications that arise out of the characteristics of the signal.
Addressing drift#
The mean of the signal is non-stationary across the session. Slow processes that survive preprocessing (residual photobleaching, slow patchcord motion, hemodynamic effects, and genuine biological state changes) create a long-term drift that breaks any single threshold applied across the session. A naive fixed threshold therefore catches events on stretches where the baseline is high and misses events on low-baseline stretches, simply because the threshold doesn’t move with the drift.
One way of addressing the session drift is to split the signal into contiguous chunks of fixed duration and recompute the typical level and noise scale from the samples inside each chunk. The detection threshold within a chunk is then tailored to that chunk’s local conditions. The robust pair to use here is the median for the typical level and MAD (the median absolute deviation) for the noise scale, the same pair introduced in the z-score explainer.
The size of the chunk (the window size) is itself a parameter, and the algorithm behaves very differently across its range. When chunks are too small (panels A and B below, at 1 s), the noise scale is computed from too few samples and is itself noisy: it has high statistical variance just from random sampling, and the threshold derived from it jumps erratically chunk to chunk. Real events are still caught, since they sit well above any plausible noise level, but in chunks where the threshold happens to land low, noise wiggles cross it and register as false positives. When chunks are too large (panels E and F, at 60 s), the slow drift that motivated chunking in the first place lives entirely inside the chunk and inflates its noise scale; the threshold sits at a flat, high value that real events fail to cross. In between sits the working regime (panels C and D, at 15 s), where the threshold adapts smoothly to the wandering baseline. In each row the right column zooms in on the same 5 s slice.
Summarising the above, two failure modes are worth avoiding: (1) chunks so short that the per-chunk noise scale is itself noisy, with high statistical variance from chunk to chunk just from random sampling, and (2) chunks so long that the long-term trends the chunking was meant to localise (residual photobleaching, hemodynamic effects, slow drift) reappear inside each chunk and contaminate the noise scale. Both push the per-chunk threshold away from where the local noise alone would place it. The physical characteristics of the signal suggest a goldilocks range for the window: drift sources span tens of seconds (e.g. hemodynamic effects) to many minutes (e.g. photobleaching), so the window must sit well below that timescale, and at the same time large enough that the per-chunk noise scale is statistically stable across chunks. A chunk in the 10 to 30 second range satisfies both bounds and is a sensible default to start from.
This is the standard bias-variance trade-off applied to a noise estimator parametrised by window size: short windows produce a high-variance estimate (jittery threshold, false positives), long windows produce a biased estimate (inflated by drift, false negatives).
A subtler effect: events that span a chunk boundary slightly bias both adjacent chunks’ noise scales upward. With 15 s windows and ~1 s events the bias is small, but it grows for shorter windows or longer events.
Addressing outlier-induced bias#
Even when the chunk size is in the goldilocks range, the chunk’s typical level and noise scale are still sensitive to what samples happen to land in it. A chunk that catches a large event plus its slow decay tail, two events arriving close together, or an artifact that survived preprocessing sees those high-amplitude samples shift the typical level slightly upward and inflate the noise scale substantially (their distance from the typical level is large, so they enter the spread tally at full distance). Both shifts push the detection threshold upward, and smaller real events in the same chunk fall below it.
A one-sided trim of the per-chunk samples addresses this. Before computing the noise reference for a chunk, blank the upward outliers, presumed to be event-driven rather than noise-driven, and recompute the noise reference on what remains. The trimmed samples still participate in detection (they are not removed from the chunk, only from the noise reference). The remaining samples produce a cleaner estimate of the underlying noise scale, and the threshold set against that estimate catches smaller events that the contaminated single-pass version would miss.
In compact form the procedure is:
Compute the median and MAD of the raw chunk. Form a first threshold at median + K₁ × MAD, where K₁ is the outlier-filter multiplier.
Set aside samples above the first threshold. These are presumed extreme upward outliers. The filter is one-sided: downward excursions (e.g. a brief loss of coupling) are not removed.
Recompute the median and MAD on the remaining samples. Form a second threshold at median′ + K₂ × MAD′, where K₂ is the detection multiplier.
In the original chunk (artifacts included), mark every sample exceeding the second threshold. These are the detected transients.
K₁ is the cutoff above which raw-chunk samples are excluded from the noise reference.
K₂ is the detection threshold itself, applied against the cleaned median and MAD.
Conceptually, K₁ is set so real events and large artifacts reliably exceed the first-pass cutoff (and are excluded from the noise reference) while pure noise samples mostly stay below it. K₂ is the user’s “what counts as a real event” criterion.
Reading the output#
The detector returns a per-event list of (time, amplitude) pairs plus two per-recording summary scalars:
Event rate (events per minute): how often the detector flags a transient. An approximation of the underlying biological event rate, dependent on the noise floor (which sets where the threshold lands) and contaminated by some non-zero rate of noise crossings.
Mean amplitude (in noise-relative units, i.e. multiples of the chunk’s noise scale): the average above-threshold excursion among detected events. An approximation of the average biological event size, expressed in units that are local to the recording’s noise floor.
Rate is the headline statistic in most photometry papers that quantify transients: it is the single number that gets compared across conditions (control versus drug, baseline versus learning, etc.). The two dependencies above (noise floor across recordings; noise-crossing contribution within a recording) are unpacked next.
Mean amplitude is reported in noise-relative units, so cross-recording comparisons silently assume that the recordings have matched noise floors: the same physical event reads as a smaller noise-scale multiple when the noise floor is higher. The z-score explainer covers this fragility at session scale; the same logic applies here at chunk scale, and the same workarounds apply (re-express amplitudes in dF/F, or argue that SNR is matched).
Within a single recording, some fraction of the detected rate is noise rather than biology. Any finite threshold is crossed by chance, so even a recording with no biological transients sits at a non-zero noise floor of detections, and a low rate should be read against that floor rather than as biology.
Limitations#
The threshold + local-maximum approach is one design choice among several. It assumes event shapes are heterogeneous enough that no fixed template applies and that an event-list output is what downstream analyses want. When those assumptions are wrong, other approaches exist: template matching when event shape is well-defined, deconvolution (the calcium-imaging standard for single-cell traces), or working on the continuous trace directly.