API overview
Seven modules, each doing one stage of the pipeline. Everything takes and
returns ordinary objects — a Recording, a SpikeTable, a
Waveforms array, a UnitSet — and nothing holds global state.
This page lists the entry points with their defaults. Argument semantics that are not obvious from the name are explained on the methods page, which is where the reasoning lives.
axonforge.io#
- read(path, *, fs=None, n_channels=None, dtype=None, gain_uv_per_bit=1.0, offset=0, dataset=None, chunk_s=30.0) → Recording
- Dispatches on the suffix. Values from a sidecar are used where an argument is omitted. Returns a lazily mapped recording; nothing is read until a filter or detector asks for it.
- read_spikes(path, *, time_unit="s") → SpikeTable
- Reads spike times from CSV. Accepts
"ms"and"samples"fortime_unit; the last requiresfs. - sanity(rec) → dict
- Cheap checks on the first and last 10 s: saturation fraction per channel, flat channels, a comb-spectrum score that catches a wrong channel count, and the dynamic range in bits actually used.
- concat_spikes(tables, offsets_s) → SpikeTable
- Merges tables from separately processed files, shifting each by its offset. Unit labels are not reconciled across files — that is a sorting decision, not a bookkeeping one.
axonforge.filt#
- bandpass(rec, *, low=300.0, high=6000.0, order=4, zero_phase=True) → Recording
- Butterworth in second-order sections. With
zero_phasethe sections run forwards and backwards, doubling the effective order to eight. - common_median(rec, *, groups=None, exclude_bad=True) → Recording
- Subtracts the per-sample median of each channel group. With
groups=Nonethe grouping from the sidecar is used, and failing that all channels form one group. - noise_sigma(rec, *, estimator="median", span_s=10.0) → ndarray
- Per-channel noise estimate. The default is the median of the absolute value divided by
0.6745; pass
"std"for the plain standard deviation, which is biased upwards by the spikes themselves. - notch(rec, *, freq=50.0, q=30.0, harmonics=3) → Recording
- Mains removal. Rarely needed after bandpassing above 300 Hz, and worth avoiding when it is not: a narrow notch rings, and the ringing looks like a small spike.
axonforge.detect#
- threshold(rec, *, k=4.5, polarity="neg", dead_time_ms=1.0, sigma=None, channels=None) → SpikeTable
- Crossings of
k × sigma, one event per crossing per channel, withdead_time_msenforced afterwards.polaritytakes"neg","pos"or"both"; passingsigmaexplicitly skips re-estimation, which is what you want when comparing sessions. - dual_threshold(rec, *, k_hi=5.0, k_lo=2.5, **kw) → SpikeTable
- Crossing of the high threshold opens an event, return above the low one closes it. Slower, and better behaved on recordings with slow amplitude changes.
axonforge.waveform#
- extract(rec, spikes, *, pre_ms=0.5, post_ms=1.5, channels="group") → Waveforms
- Cuts a window around each event.
channels="group"takes the whole channel group of the detecting channel,"one"takes only it, and an explicit list takes exactly those. - align(wf, *, mode="peak", interp=True, max_shift_samples=4) → Waveforms
modeis"peak","min_slope"or"centre_of_mass". Shifts beyondmax_shift_samplesare left unaligned and flagged inwf.flagsrather than dropped.- templates(wf, labels) → ndarray
- Mean waveform per label with its standard error, for plotting and for reporting.
axonforge.sort#
- features(wf, *, n_components=3, whiten=True, per_channel=False) → Features
- Principal components of the aligned waveforms. With
per_channelthe decomposition is computed separately on each channel of the group and the scores are concatenated. - cluster(feat, *, max_k=8, restarts=20, criterion="bic", covariance="full", seed=0) → UnitSet
- Gaussian mixtures for every k from 1 to
max_k, each fittedrestartstimes from different initialisations; the model order with the best criterion wins.criterionalso accepts"aic". - UnitSet.merge(a, b) / UnitSet.drop(label) → UnitSet
- Curation as explicit operations. Both return a new set and record the action in the provenance, so the container shows what was done by hand.
axonforge.quality#
- isi_violations(st, *, refractory_ms=1.5, censored_ms=0.0) → float
- Fraction of intervals shorter than the refractory period. Report the period you used; 1.5 ms and 2.0 ms give visibly different numbers on the same data.
- l_ratio(feat, labels, unit) → float
- Mahalanobis-based measure of how much of the surrounding cloud leaks into the cluster.
- isolation_distance(feat, labels, unit) → float
- Undefined, and returned as
nan, when the cluster holds more than half of all events — a case that occurs more often than the literature suggests. - presence_ratio(st, *, bin_s=60.0) → float
- Fraction of time bins containing at least one spike. Catches units that vanish halfway through a session, which is usually drift.
axonforge.stats#
- isi(st, *, unit=None, log=False) → ndarray
- Interspike intervals in seconds, optionally log-spaced for histogramming.
- cv(st) / cv2(st) → float
- Coefficient of variation over all intervals, and the local measure averaged over adjacent pairs. The local one is insensitive to slow rate changes, which is why both are reported.
- fano(st, *, window_s=1.0) → float
- Variance over mean of the spike count in fixed windows. The value depends strongly on the window, so the window is part of the result when printed.
- autocorrelogram(st, *, bin_ms=1.0, span_ms=50.0, unit=None) → (counts, edges)
- The zero-lag bin is excluded, not zeroed, so the counts can be used directly.
- bursts(st, *, max_isi_ms=6.0, min_spikes=3) → ndarray
- Interval-threshold burst detection. Deliberately the simple method; surprise-based detection is not implemented, because its result depends on a baseline rate that is itself the thing in question.
Command line#
axonforge detect RAW [options]
--fs HZ sample rate, overrides the sidecar
--channels N channel count, overrides the sidecar
--dtype NAME int16 (default), int32, float32
--bandpass LOW:HIGH default 300:6000, use "none" to skip
--no-cmr skip common median referencing
--k FLOAT threshold in sigma, default 4.5
--polarity neg|pos|both default neg
--dead-time MS default 1.0
--jobs N parallel channel groups, default 1
--out PATH .afz container to write
axonforge sort IN.afz --max-k 8 --components 3 --criterion bic
axonforge report IN.afz --raster --isi --waveforms --out report.pdf
axonforge selftest
axonforge --version
Every flag maps to the keyword argument of the same name, and
axonforge detect --dry-run prints the call it would make in Python. The
intention is that the command line is a convenience, never a separate implementation.