nstat.extras.metrics.spike_distances — PySpike spike-train distances
Modern, parameter-free spike-train distance and synchrony metrics that have no counterpart in MATLAB nSTAT. Thin wrappers around PySpike, the BSD-2 library that implements the Kreuz / Mulansky family of time-resolved spike-train distances with C/Cython acceleration.
Three metrics ship today:
ISI-distance (Kreuz 2007) — instantaneous dissimilarity in inter-spike intervals.
SPIKE-distance (Kreuz 2013) — instantaneous dissimilarity in spike timing. Bounded in [0, 1].
SPIKE-synchronization (Kreuz 2015) — fraction of “synchronous” spikes; symmetric in [0, 1].
All three are parameter-free — no kernel bandwidth, no binning. That’s their main advantage over rate-based or kernel-density measures.
Install
pip install nstat-toolbox[metrics]
Pulls pyspike>=0.8.
API
Function |
Returns |
Notes |
|---|---|---|
|
|
Kreuz 2007 |
|
|
Kreuz 2013 |
|
|
Kreuz 2015 |
|
|
Symmetric, zero diagonal |
Recipe
import numpy as np
from nstat import nspikeTrain
from nstat.extras.metrics.spike_distances import (
isi_distance, spike_distance, spike_synchronization,
pairwise_spike_distance_matrix,
)
# Two trains sharing a common 1 s window
a = nspikeTrain([0.10, 0.50, 0.90], minTime=0.0, maxTime=1.0)
b = nspikeTrain([0.15, 0.55, 0.95], minTime=0.0, maxTime=1.0)
d_isi = isi_distance(a, b) # ~0.04 (low — similar ISI structure)
d_spike = spike_distance(a, b) # ~0.05 (low — similar timing)
s_sync = spike_synchronization(a, b) # ~1.0 (high — coincident)
# Population-level pairwise matrix
trains = [a, b, nspikeTrain([0.20, 0.60, 1.00], minTime=0, maxTime=1)]
D = pairwise_spike_distance_matrix(trains)
assert D.shape == (3, 3)
assert np.allclose(np.diag(D), 0.0)
assert np.allclose(D, D.T)
Gotchas
Shared time window required. All metrics assume the two (or N) trains share a common recording window. The bridge passes
nst.minTime/nst.maxTimeas PySpike’sedges=— if your trains have divergent windows you should crop them first.Empty trains. Both functions handle empty trains without crashing (PySpike returns ISI-distance and SPIKE-distance of 0.0 or NaN depending on the case). Population-level matrices remain well-defined; check for NaN if you have all-zero rows.
No Victor-Purpura. PySpike doesn’t implement the Victor-Purpura metric (1996, which requires a cost parameter). If you need it, look at
elephant.spike_train_dissimilarity— but Elephant is Neo-typed end-to-end, so use theinterop.neobridge first.
End-to-end demo
examples/extras/metrics_spike_distances_demo.py
generates a 5-train population with shared sinusoidal rate modulation,
then computes pairwise scalars and the full distance matrix.
Upstream references
PySpike: https://github.com/mariomulansky/PySpike
License: BSD-2-Clause (GPL-2 compatible)
Papers: Kreuz 2007 (ISI-distance), Kreuz 2013 (SPIKE-distance), Kreuz 2015 (synchronization)