Apply ICA before or after epoching/cleaning?

  • MNE-Python version: 0.23.0
  • operating system: Windows 10

Dear MNE users and maintainers,

I have read conflicting information about whether to perform ICA on cleaned/epoched data or directly to the raw data. I get the impression that it is highly depended on a number of factors including the data type, artifacts, and goal of the project.

Some discussion on this:

Is it better to apply ICA on whole EEG data or on epoched data in order to detect and correct existing artifacts?
ica.apply for MEG and EEG

I do not know what the best approach is for my data (EEG only). I’ve been focusing on fitting ICA to cleaned/epoched dataset and assumed that this was fine, but (out of curiosity) I just fitted ICA to some of my raw data and it seems that it might perform better.

My case is a little different as I am not just looking at removing eye blinks or other common artifacts, but I have short (~500ms) external electrical stimulation events (tES) that I want to remove. I am using the FastICA algorithm with the default parameters.

  1. I was wondering if anyone had experience with applying ICA to remove short tES artifacts (or something similar), could give me some feedback based on their experience particularly regarding the workflow for preprocessing.

  2. Also, more generally, if someone could recommend a good method for comparing or evaluating the efficacy of different ICA fittings on the same dataset (or comparing raw vs epoched versions of the same dataset), I would be very interested and grateful for your input.

  3. Finally, I’ve been a little confused about the baseline correction and filtering warning that mne generates when I apply ICA to my datasets. Do these warning suggest that there is a specific order of operations that I should always follow regardless of raw/epoched dataset prior to fitting to ICA?

Thank you all for your assistance,
J

Hello @Jbb and welcome to the forum!

Typically the ICA “sees” more data when you feed it the raw compared to the epoched signal. It may benefit from this (and sometimes the opposite will be true). Whether that is the case depends on the specific type of data you’re looking at.

For the MNE-BIDS-Pipeline, we decided to run ICA on epoched data only. Also keep in mind that fitting on epochs can often be substantially faster than fitting on continuous data.

Speaking of performance, MNE has support for Picard, which essentially performs the same decomposition as FastICA, but converges faster. See Comparing Picard and FastICA for the task of detecting ECG artifacts in MEG — picard 0.7.dev documentation for an example.

Until now I wasn’t even aware that this was an option! Former co-workers of mine would simply live with the fact that the EEG signal during the stimulation event was irretrievably lost. Did you actually manage to recover it successfully?

Only thing I can suggest here is to do a careful visual inspection of the topographies and PSD plots for each component. Oh, and measure how long ICA takes – might be worth considering this too.

Yes so this is a new warning, because we observed unexpected behavior otherwise (alright, a mathematician would probably say: it was expected! but users got confused).

The data you feed into ICA should be high-pass-filtered (e.g., 1.0 Hz) to remove slow drifts. Epochs should not be baseline-corrected. When using epochs, you should also specify peak-to-peak rejection thresholds via the reject parameter of Epochs(). When using raw data, ICA.fit() accepts a similar reject parameter too (which is currently silently ignored if you run ICA.fit() on Epochs!)

I hope this helps a little!

Richard

Hello @Jbb and welcome to the forum!

Thanks Richard. This is a really great resource and the feedback that I’ve gotten so far has been very timely and helpful; glad to have found it.

Well, for the limited comparisons I’ve done so far, I’ve noticed that for raw data it takes longer than for epoched data.

To check, I’ve run consecutive ICA fittings in both situations to see if any more relevant ICA components are available. For the raw data, the relevant components (2-3) are in the first round of ICA alone, while for the epoched data each ICA fitting has a larger number of “relevant” ICA components (5-6) and I can do 2-3 fittings and still see components.

My concern is that while the ICA is faster for the epoched version, the components that it shows are removing more than the artifact signals. And faster just means instead of taking ~10 seconds, it only takes ~3 seconds. For data that lasts longer than that, in my case, it means that it will not converge which has only happened for one or two epoched datasets. In these cases, I’ve raised the iterations to 30000-50000 and it still doesn’t converge.

Until now I wasn’t even aware that this was an option! Former co-workers of mine would simply live with the fact that the EEG signal during the stimulation event was irretrievably lost. Did you actually manage to recover it successfully?

It is one of the aspects of the research project that I am working on. There are some studies that compare ICA and other methods for removing tES. For example, here’s a 2019 paper discussing this: Removal of tACS artefact: a simulation study for algorithm comparison | IEEE Conference Publication | IEEE Xplore

Once we publish our data, I will send an update on the forums and share our results.

The data you feed into ICA should be high-pass-filtered (e.g., 1.0 Hz) to remove slow drifts. Epochs should not be baseline-corrected. When using epochs, you should also specify peak-to-peak rejection thresholds via the reject parameter of Epochs() . When using raw data, ICA.fit() accepts a similar reject parameter too (which is currently silently ignored if you run ICA.fit() on Epochs !)

If you run multiple ICA fittings, as is more commonly done with removal of TMS artifacts, would you recommend performing baseline corrections in between ICA fittings to correct for dc shifts?

Yesterday I added the reject parameter in ICA.fit() using the default reject dict example. I adjusted the values of the ‘eeg’ key to see how it affected the output. So far, the fitting seems to provide better components without the reject parameter added. But this is just based off a few attempts, visual inspection, and with just one data set. Not sure if it will improve, but I can write an update here if I get some better results.

Thanks!