mne-python icon indicating copy to clipboard operation
mne-python copied to clipboard

Addition of a non-projection-based method of removing EOG and ECG artifacts.

Open wmvanvliet opened this issue 1 year ago • 14 comments

Describe the new feature or enhancement

The current SSP and ICA methods of removing EOG and ECG artifacts are really effective, but they do completely zap out 2 or even 3 ranks of data. With many-channel MEG and EEG recordings, that's usually fine, but since MNE-Python is getting used more and more for EEG analysis, also low channel count EEG analysis, perhaps it would be nice to provide an alternative method that is more conservative.

In the past, I've played around with regression-based approaches (regress out the EOG channels from the data), which do work pretty well, but recently @rkobler developed the SGEYESUB algorithm that may be superior.

Do others agree this is worth adding to MNE-Python?

Describe your proposed implementation

Implement mne.preprocessing.sgeyesub following the reference implementation. It needs epochs of blinks and saccades, which are usually recorded in a dedicated segment of the experiment where the participant is following on-screen directions for blinking and moving their eyes. If you don't have such a segment in your experiment, mne.preprocessing.make_eog_epochs could be a decent substitute.

Describe possible alternatives

We could decide SSP/ICA is good enough and if people want other algorithms, they can make their own extension packages. Alternatively, we could merge in mne_sandbox.preprocessing.eog_regression instead.

wmvanvliet avatar Aug 11 '22 13:08 wmvanvliet

I'd add the "standard" regression approach first, because that's widely used (and often requested). I have implemented one of the first regression-based approached described in Hillyard & Galambos (1970) here. Can you explain what's different in the approach you implemented in mne-sandbox (Croft & Barry, 2000)? I've never seen SGEYESUB used before, so it seems rather niche and I would probably not add it right away (at least not before the standard regression approach is available).

cbrnr avatar Aug 11 '22 13:08 cbrnr

Croft & Barry first extract blink and saccade epochs and create ERPs. Then they compute the regression weights on those ERPs. The idea being that the ERPs contain a pretty pure blink without other ongoing EEG, so the weights will be more accurate. Once you have the weights, you apply them on the raw data like in your approach.

wmvanvliet avatar Aug 11 '22 13:08 wmvanvliet

Perhaps it's time then to move the EOG regression out of the sandbox into MNE-Python proper ;)

wmvanvliet avatar Aug 11 '22 13:08 wmvanvliet

I think so too! It would be nice if that function had a parameter to choose from Croft & Barry and Hillyard & Galambos (since the latter is very often still used today).

cbrnr avatar Aug 11 '22 14:08 cbrnr

Describe your proposed implementation

Implement mne.preprocessing.sgeyesub following the reference implementation.

reference implementation is GPL-3, which IIUC carries a "same license for the library" requirement. We'd need to request permission to relicense as BSD-3 if the plan is to simply translate the MATLAB implementation into Python.

drammock avatar Aug 11 '22 14:08 drammock

A bonus provided by @rkobler's paper is a nice set of validation datasets we can use to test our implementation: https://osf.io/2qgrd

wmvanvliet avatar Aug 12 '22 06:08 wmvanvliet

reference implementation is GPL-3

I'll keep that in mind if we do end up implementing SGEYESUB.

wmvanvliet avatar Aug 12 '22 07:08 wmvanvliet

A bit OT, but I find it a bit sad that both the paper by Kobler et al. (2020) as well as the cited Schlögl et al. (2007) completely ignore relevant prior literature. The regression approach dates back to Hillyard and Galambos (1970), and a useful implementation (using the same data and separate coefficients for blinks and movements) was presented by Gratton, Coles and Donchin (1983). The latter is the "reference" implementation which I think we should provide before anything else (maybe even in simplified form with just one set of coefficients for both blinks and movements).

cbrnr avatar Aug 12 '22 07:08 cbrnr

among the variants is their one you would consider the go to method for this task? I would like to avoid implement/maintain/test many small variants that lead to comparable results.

Message ID: @.***>

agramfort avatar Aug 12 '22 11:08 agramfort

I'd prefer the one from Gratton et al. (1984), this is the most used one IMO. All of them are pretty similar anyway and also comparable in terms of performance. So it's basically about how to estimate the regression coefficients. I think the code that's already available in the sandbox is a good starting point.

cbrnr avatar Aug 12 '22 11:08 cbrnr

If I look at the spectrum of variants, it occurs to me that most of them have to do with deciding on what type of data to fit the regression weights. If we go for a .fit()/.apply() style API, it would leave the user a lot of flexibility on which methodology to use. What I don't like about that approach though is that it makes it less straightforward to "just apply the method". Perhaps being opinionated on an approach is more desirable. :thinking:

wmvanvliet avatar Aug 12 '22 12:08 wmvanvliet

I'd prefer the one from Gratton et al. (1984)

This one? https://www.sciencedirect.com/science/article/abs/pii/0013469483901359?via%3Dihub

wmvanvliet avatar Aug 12 '22 12:08 wmvanvliet

Perhaps being opinionated on an approach is more desirable. 🤔

+1

Message ID: @.***>

agramfort avatar Aug 12 '22 12:08 agramfort

Yes, this one! And yes, the differences between the various regression methods is which data to fit the coefficients on, so a fit/apply API would be perfect! To make it easier to apply, we could then provide a wrapper function for e.g. the Gratton et al. approach.

cbrnr avatar Aug 12 '22 12:08 cbrnr

https://mne.tools/stable/generated/mne.preprocessing.regress_artifact.html 😅

wmvanvliet avatar Aug 22 '22 15:08 wmvanvliet