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 npfrom scipy import signal as sp
import dspkfrom plating import signals
s = signals.synthetic()DOWN = 30 # 30 kHz → 1 kHzlow = dspk.ops.resample.resample_poly(s.data, 1, DOWN)dec = dspk.ops.resample.decimate(s.data, 10) # q ≤ 13 per step, as scipy advisesdec = 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")
The whole script is playground/04_resampling/01_resample_poly.py. Run it with uv run python playground/04_resampling/01_resample_poly.py.