Validation on synthetic ground truth

Numbers for the default parameters, measured against data where the answer is known. They are published so that you can decide whether this tool is adequate for your recordings, and they include the levels at which it is not.

How the test data is made#

python -m axonforge.bench --snr 2,3,4,6,8,10 --reps 20 --out bench.csv
# 26 min on 4 cores; writes one row per repetition

Detection#

Default parameters: k = 4.5, negative polarity, 1.0 ms dead time, bandpass 300–6000 Hz. Medians over 20 repetitions; the spread between repetitions was within ±0.02 for every F1 except the ratio of 2, where it was ±0.07.
SNRPrecisionRecallF1Median time error
20.710.410.5295 µs
30.870.690.7761 µs
40.940.860.9042 µs
60.980.950.9628 µs
80.990.970.9823 µs
100.990.980.9819 µs

Read the first row as a warning rather than a result. At a ratio of 2 the detector finds two spikes in five and is wrong about three of every ten it reports; no downstream curation rescues that, and a unit whose amplitude is twice the noise should be reported as undetected rather than as a low-rate cell. The time error at that level, 95 µs, is three samples at 30 kHz, which is enough to blur a cross-correlogram beyond use.

Effect of the threshold multiplier#

All at a signal-to-noise ratio of 6, everything else at defaults.
kPrecisionRecallF1Smallest unit found?
3.50.840.970.90yes
4.00.960.970.96yes
4.50.980.950.96yes
5.00.990.890.94no
5.50.990.780.87no

F1 is identical at 4.0 and 4.5, so the default was not chosen by maximising it. It was chosen because the error it leaves is the recoverable kind: a missed spike lowers a rate estimate, while a false positive at 4.0 — twice as many as at 4.5 — joins a cluster and corrupts both its waveform and its interval statistics. If your question is about rates rather than about shapes, 4.0 is the better default and you should change it.

Sorting#

Six ground-truth units per repetition. «Correct k» counts repetitions where the information criterion selected exactly six components.
SNRUnits found, medianTruth units recoveredMergesSplitsCorrect k
242 of 6213 / 20
364 of 61111 / 20
465 of 61014 / 20
666 of 60017 / 20
866 of 60019 / 20
1066 of 61018 / 20

A unit counts as recovered when a single cluster contains at least 80 % of its spikes and no more than 20 % contamination from others. The one merge at a ratio of 10 is the pair of templates in the pool whose waveforms differ mainly in the second principal component; with three components they separate in eighteen of twenty repetitions, and with four they separate in all twenty at the cost of a split elsewhere.

Overlapping spikes#

Two units were forced to fire at a controlled separation, 2 000 pairs per separation, at a ratio of 6.

Fraction of the second spike of a pair that was detected at all.
SeparationSecond spike detectedOn the same channel
0.1 ms0.00impossible
0.2 ms0.02impossible
0.3 ms0.07impossible
0.5 ms0.58impossible
0.8 ms0.86impossible
1.0 ms0.97possible
1.5 ms1.00possible

The third column explains the shape of the curve. With a 1.0 ms dead time a second crossing on the same channel cannot be recorded at all, so everything recovered below that separation was detected on a different channel of the group. That is why the curve rises gradually from 0.3 ms instead of stepping at 1.0 ms, and why the recovery depends on how far apart the two cells sit relative to the electrode.

Shortening the dead time does not fix this. At dead_time_ms=0.4 overlap recovery at 0.5 ms rises to 0.74, and precision at a ratio of 6 falls from 0.98 to 0.91, because the trailing edge of large spikes starts producing second events. Resolving genuine overlaps needs template subtraction, which axonforge does not implement.

What these numbers do not cover#