Skip to content

A real probe: every spike, where it came from, and how the probe moved

Kilosort4’s test recording: 45 s of a Neuropixels 1.0 probe (384 sites over 3.8 mm, plus a sync channel), 30 kHz, int16. First run 00_fetch_kilosort_data.py.

  1. Detect over the whole file, streaming on the device (detect_recording: band-pass, common median reference, threshold, merging across sites) — what dspk detect does.
  2. Locate each spike as it is detected: the centre of mass of its snippet’s peak-to-peak heights over its nearest sites (µm on the probe), computed on the device with the snippets.
  3. Drift: spikes’ depths over time show the probe moving in the brain (bands of activity bend); spatial.drift estimates that motion — what sorters correct before clustering.
from pathlib import Path
import numpy as np
import dspk
from dspk.synapse import detection, io, spatial
DATA = Path(__file__).resolve().parents[1] / "datasets" / "kilosort4" / "ZFM-02370_mini.imec0.ap.short.bin"
if not DATA.exists():
raise SystemExit(f"{DATA} is missing: run playground/09_sorting/00_fetch_kilosort_data.py first")
rec = dspk.io.open(DATA)
probe = io.Probe.preset("neuropixels1") # 384 sites; the file's channel 385 is the sync line
fs, total = rec.sample_rate, rec.samples
print(rec)
# 1–2. Detection over the whole recording (streamed in batches on the device), each spike located
# from its 8 nearest sites
sorting, summary = detection.detect_recording(rec, probe, car=True, k_neighbors=8)
spikes = sorting.spikes()
positions = spikes["locations"]
print(f"{summary['spikes']} spikes after merging ({summary['raw_crossings']} threshold crossings)")
ok = ~np.isnan(positions[:, 1])
print(f"located {ok.mean():.0%} of the spikes")
# 3. Drift from the located spikes (rigid: one displacement for the whole probe per time bin)
t, depth, amp = spikes["samples"][ok], positions[ok, 1], np.abs(spikes["amplitudes"][ok])
drift = spatial.drift(t, depth, amp, total, fs, depth_min_um=float(depth.min()), depth_max_um=float(depth.max()))
print(f"drift over the recording: {np.ptp(drift['drift_um']):.1f} µm peak to peak")

A real probe: every spike, where it came from, and how the probe moved

The whole script is playground/09_sorting/01_detect_and_locate.py. Run it with uv run python playground/09_sorting/01_detect_and_locate.py.