more bumpy PSD after removing ICA components [EEG analysis]

Data was preprocessed using that setting

fline = 50
h_freq = 40
l_freq = 1

filter_params = {
    "l_freq": l_freq,
    "h_freq": h_freq,
    "h_trans_bandwidth": "auto",
    "fir_window": "hamming",
    "fir_design": "firwin2",
    "phase": "zero",
    "picks": ["ecg", "eeg"],
}

raw = load_data(subject, project_path=project_path)

total_duration = raw.times[-1]

raw_filtered = (
    raw.copy()
    .resample(250, method="polyphase", verbose=True)
    .drop_channels(bad_channels)
    .notch_filter(freqs=[fline], phase="zero", method="iir")
    .filter(**filter_params)
    .crop(tmin=3.0, tmax=total_duration - 3, include_tmax=True)
)

epochs that were bad on more than 40% of channels where rejected using autoreject, and some ICA components were rejected;

The signal before ICA


after ICA (with the same scale)

and the PSD in comparison


(after ICA is at the bottom)

Its seems that the removal of components either removed some “normal” eeg leaving the more bumpy one, or introduce artefacts - what might be the reason of it? Some artfact that propage with reconstructing signal from components?

The data is not open data, I cannot easily share it openly.

To me it doesn’t look too different than before if you consider the Y axis. High-power signals were removed from the frontal region, but artifacts remain within the rest of the data. I would also be suspicious of the channel with the very low lower and the one with the highest power at low frequencies before ICA. Check their data quality before ICA, they might have something weird going on :thinking: Did you apply an average reference?

  1. Previously I did slightly different preprocessing and I was able to get much nicer signal without artifacts (this time I removed first and last 3sec of recording, and used slightly different setting for downsampling), maybe I picked better components
    ; bad channels were automatically found using pyprep implemention of MATLAB library with the same functions (and around 40 channels around neck and ears were dropped at the beginning of analysis to limit artifacts, leaving only slightly over 200 channels from orginal HD EEG set).
  2. The reference in this system was applied while recording (VREF ~ Cz), I didn’t rereferenced data later.
  3. I also tried with automating labelling with ICALabel and the results weren’t so impressive (filtered to 100hz, both with CAR and without), I needed only information up to 40Hz so we decided with colleagues to manually pick ICA components to removed in the subsequent rerun of the pipelin
  4. Here is an automated report that I generated for this subject , I think maybe we removed too many components and 0, 2, and 4 weren’t bad components in the end
    Transfer - Dropbox

On the margin of this specific problem: is there a better way to insert to report scrollable timeseries that are more useful to browse later?
so far I am able to add static plots, but they are can show only up to 20 channels/ICA components, so I need to create many loops/different slicing of epochs in order to be able to check later after running pipeline (I create parametrized notebooks with quarto/papermill for every subject so I have always trace what happened, but mne.report is nicer)

Another general question - If I split signal into epochs, does detrending per epoch (when creating them using mne) can have influence on the quality of ICA ?


def create_epochs(raw: mne.io.Raw, length: float = 5, overlap: float =1.5):
    """Create epochs from raw data"""
    events = mne.make_fixed_length_events(
        raw=raw,
        start=0,
        stop=None,
        duration=length,
        overlap=overlap,
        first_samp=False,
    )
    return mne.Epochs(
        raw=raw,
        events=events,
        tmin=0,
        tmax=length,
        detrend=1,  # from 0 to 1
        baseline=None,
        preload=True,
        reject_by_annotation=True
    )

The bumps are likely due to one or more large(-ish) artifact(s) in your data, which gets aliased to several frequencies that we see as bumps. Regarding the other question, a good high-pass filter is essential, and I’m not sure that firwin2 yields a steep enough rolloff. Is there any reason why you don’t want to use the default firwin, which in my experience creates very good filters? Detrending also removes low frequencies, so it can complement a high-pass filter, but I don’t think it can replace it.

1 Like