Some of my sEEG channels have unusually high variance but similar patterns of activity as the other lower-variance channels.
An obvious normalization is to Z-score the entire time-course across time to ensure zero mean and unit variance: and this does make the channels’ activity look more normal/comparable, which is nice.
- I can’t do this baselining either on the
mne.io.Rawor themne.Epochsobjects automatically, because they only supportmode="mean". So I ended up using the.apply_function()method to Z-score each channel:
def normalize_raw_data(
raw: mne.io.BaseRaw,
*,
mode: Literal["zscore", "mean"] | None = "zscore",
) -> mne.io.BaseRaw:
match mode:
case "zscore":
return raw.load_data().apply_function(
lambda x: (
(x - x.mean(axis=-1, keepdims=True)) / x.std(axis=-1, keepdims=True)
if ~np.any(x.std(axis=-1, keepdims=True) == 0)
else x
),
channel_wise=True,
)
case "mean":
return raw.load_data().apply_function(
lambda x: x - x.mean(axis=-1, keepdims=True),
channel_wise=True,
)
case None:
return raw
case _:
raise ValueError
- But this approach messes up the expected units of these classes: they are now dimensionless but I can’t specify that in either
mne.io.Rawormne.Epochs—they assume that the data is stored in volts.
Is there any recommended way to proceed?
I’m not particularly upset about this—I just need to adjust scalings manually when plotting and ignore the “V” units that are assumed and thrown in in several places.
But I imagine this should be a common normalization? Is there a particular reason this use-case isn’t supported beyond making the code more complicated (which is totally valid lol, no shade)?
I’m relatively new to EEG data analysis, but coming from a signal processing/ML/fMRI background, I’m used to early transformations/normalizations of the data before downstream analyses.