Annotating raw data based on amplitude thresholds

[MNE version 0.24.1, macOS)

Hello,

Is there a method to annotate continuous data according to certain periods where the trace is outside (or within) of a specified range of amplitudes?

The context: I have an EEG recording where the signal is occasionally interrupted (drops to an extremely low voltage), and I want to annotate these artifacts as ā€˜badā€™ prior to plotting the PSD with raw.plot_psd(reject_by_annotation=True) . The artifacts look like signal dropouts but arenā€™t completely flat, so attempting to label them with mne.preprocessing.annotate_flat() does not work.

Ideally, I would like to annotate these periods as ā€˜badā€™ and remove them from the data similar to the solution provided here under ā€œRejecting Epochs based on channel amplitudeā€: Rejecting bad data spans and breaks ā€” MNE 0.24.1 documentation. However, my data contains no events or epochs, so instead of rejecting epochs I am aiming to just annotate the artifacts and remove them from the continuous data.

Perhaps there is an alternative solution?

Thanks in advance,
Jack

I donā€™t think there is any convenience function that will do this out of the box in MNE.

You could use the interactive annotation in the 2D browser displayed with raw.plot() and mark bad segments manually.
Or you could mark them programmatically by defining an Annotation object.

The related tutorial is: Annotating continuous data ā€” MNE 0.24.1 documentation
Note that for interactive annotation, you could use the new 2D browser by calling mne.viz.set_browser_backend('pyqtgraph') before raw.plot().


Programatically, you would have to scan (loop on) your data and figure out the onset and duration of each bad. e.g. you could define a small window size, slide it on your data; and each time all points in the window are below the threshold, retrieve the onset (left-edge of the window) and the duration.

3 Likes

agreed, and this could be simplified by creating epochs and iterating over the epochs, see this function: make_fixed_length_epochs

1 Like

I actually think that we should enhance annotate_flat such that one can specify a flatness threshold, similarly to what we offer when creating epochs. Currently we only check whether the data is actually absolutely flat, i.e., the difference between samples is zero. It should be easy to allow for an absolute non-zero threshold here instead.

4 Likes

Thanks all for the very helpful responses!

For those who might encounter this problem in the future, I managed to fix it based on the feedback given above. Itā€™s certainly not a permanent solution as it requires you to manually inspect the data first. The basic code is below:

#create equally spaced events in raw data, with the duration > the longest bad data segment (here, that was 4 s)
events = make_fixed_length_events(raw, duration=4) 

#convert the raw data to an epoch object using events and reject epochs where data is over a certain amplitude threshold (here, that was 0.6 mV or 6e-5 V)
reject = dict(eeg=6e-5)
epochs = Epochs(raw, events, picks=picks, reject=reject, preload=True)

#do subsequent analysis
1 Like