Skip to content

Fewer samples, the same slow signal

LFP analyses do not need 30 000 samples a second. resample_poly(x, up, down) changes the rate by up / down behind an anti-alias low-pass (polyphase FIR, Kaiser window, as scipy’s resample_poly); decimate(x, q) divides it by q behind an IIR low-pass, as scipy’s decimate. Both run on the device.

import numpy as np
from scipy import signal as sp
import dspk
from plating import signals
s = signals.synthetic()
DOWN = 30 # 30 kHz → 1 kHz
low = dspk.ops.resample.resample_poly(s.data, 1, DOWN)
dec = dspk.ops.resample.decimate(s.data, 10) # q ≤ 13 per step, as scipy advises
dec = dspk.ops.resample.decimate(dec, 3)
ref = sp.resample_poly(s.data.astype(np.float64), 1, DOWN, axis=1, window=("kaiser", 5.0))
print(f"{s.samples:,} → {low.shape[1]:,} samples per channel")
print(f"resample_poly vs scipy: max difference {np.max(np.abs(low - ref)) / np.max(np.abs(ref)):.1e} of the peak")

Fewer samples, the same slow signal

The whole script is playground/04_resampling/01_resample_poly.py. Run it with uv run python playground/04_resampling/01_resample_poly.py.