Skip to content

Non-linear: median and Teager–Kaiser energy

Not every useful filter is linear. A running median ignores short events: wide enough, it removes the spikes and keeps the background. The Teager–Kaiser energy (x[t]² − x[t−1]·x[t+1]) does the opposite: it grows where the signal is both large and fast, so spikes stand out of the noise; spike detectors use it.

import numpy as np
import dspk
from plating import signals
s = signals.synthetic()
WIDTH = dspk.ops.filter.MAX_MEDIAN_WIDTH # 31 samples, ~1 ms at 30 kHz
spikes_band = dspk.ops.filter.iir(s.data, s.sample_rate, "highpass", 300.0)
median = dspk.ops.filter.median(spikes_band, WIDTH)
energy = dspk.ops.filter.teager_kaiser(spikes_band)
ch = s.loudest_channel
on_ch = s.spike_samples[np.isin(s.spike_units, np.flatnonzero(s.unit_channels == ch))]
print(f"channel {ch}: {on_ch.size} spikes of units peaking there")

Non-linear: median and Teager–Kaiser energy

The whole script is playground/02_filtering/05_median_and_energy.py. Run it with uv run python playground/02_filtering/05_median_and_energy.py.