Common average and common median
Whatever every channel picks up alike (mains hum, movement, the reference electrode’s own activity) can be estimated from the channels themselves and subtracted, at every sample: CAR subtracts the mean over channels, CMR the median. They agree on clean data; they part when one channel goes bad: the mean drags that channel’s artefact onto all the others, the median ignores it.
import numpy as np
import dspkfrom plating import signals
s = signals.synthetic(channels=16)data = s.data.copy()
# One bad channel: a large, brief artefact on channel 3 (a loose contact)BAD, AT, WIDTH, SIZE = 3, int(0.25 * s.sample_rate), int(0.02 * s.sample_rate), 2_000.0data[BAD, AT : AT + WIDTH] += SIZE * np.hanning(WIDTH)
car = dspk.ops.spatial.car(data)cmr = dspk.ops.spatial.cmr(data)
# What the bad channel did to a good one: referenced with it minus referenced without itgood = 0for name, op, out in (("CAR", dspk.ops.spatial.car, car), ("CMR", dspk.ops.spatial.cmr, cmr)): leak = np.max(np.abs(out[good] - op(s.data)[good])) print(f"{name}: the bad channel's artefact reaches channel {good} with {leak:.0f} µV (it is {SIZE:,.0f} µV)")
The whole script is playground/03_referencing/01_car_and_cmr.py. Run it with uv run python playground/03_referencing/01_car_and_cmr.py.