DOC: Add epoch quality example#13710
Conversation
|
Hi, I intuitively thought about the reject parameter in the epochs class. Here epochs are being rejected based on maximum peak-to-peak signal amplitude (PTP). From my experience most users play around with this threshold to get a feeling for the amount of epochs being rejected. The function you implemented can inform the user of a threshold for rejecting bad epochs based on PTP etc., but I do think that it won't be useful to inform a threshold for epochs reject or autoreject. It seems to me that it adds a layer of abstraction on rejection of noisy epochs, but maybe I misunderstood the use case you had in mind? |
|
thanks for the feedback @CarinaFo Think of it as answering "which epochs should I look at first?" rather than "what threshold should I use?". Especially handy for large datasets where manual inspection isn't realistic. Happy to make this clearer in the docstring if that helps. And if the general feeling is that this doesn't add enough on top of what's already there, I'm open to that too |
|
I agree with @CarinaFo's comment about the abstraction. Aggregating PTP, variance, and kurtosis like this is something I wouldn't have an intuition for what a good/bad score is. That interpretation's also a bit tricky since these are z-scored values, so if you have a lot of bad epochs in your data, these might not show as being strong outliers in the scoring. This also means having a value for a 'bad score' that would define what epochs are worth inspecting could show you epochs of very different quality for each recording. Is this scoring method coming from a paper? Are there some examples of how common artefacts would impact these scores? E.g., in the |
|
Moreover I think there are a lot of potential statistics/ways of deciding what is good and bad. One option would be to show some of these stats for the |
|
on the paper question:the features aren't arbitrary. Kurtosis and variance z-scored across epochs come from Delorme et al(2007) and FASTER(Nolan et al., 2010), both fairly established in the EEG artifact detection literature. you're both right that the weighting and what counts as a "bad" score is still dataset dependent, which is a real limitation. |
Yeah I think a new example in https://github.com/mne-tools/mne-python/tree/main/examples/preprocessing could make sense. And adding refs to FASTER etc. could be good, too |
|
(you can push commits to this PR to do this and edit the title, no need for a separate PR, but can do it that way instead if you want) |
|
@larsoner i have pushed the example to this PR along with refs to FASTER (Nolan et al., 2010) and Delorme et al. (2007). Let me know if anything needs adjusting!! |
Epochs.score_quality() for epoch outlier scoring with preprocessing example
Ah fair enough, didn't realise that's what they were using. Sorry for the confusion! |
|
I think instead of a |
|
updated the PR @larsoner !! |
Epochs.score_quality() for epoch outlier scoring with preprocessing example|
Very nice example. I think this would be a great starting point for a how-to guide. It is mainly a bit of restructuring of the way the example is introduced to the user. |
|
thanks @CarinaFo that's a helpful distinction. The current example reads more like a tutorial, walking through everything from scratch. A how-to guide should assume the user already knows MNE and just wants to solve a specific problem 'I have epochs, how do I quickly identify the bad ones before rejection?' i can restructure it to be more task oriented, drop the hand-holding, lead with the goal, and let the code speak for itself. Should I keep it in |
| References | ||
| ---------- | ||
| .. [1] Nolan, H., Whelan, R., & Reilly, R. B. (2010). FASTER: Fully Automated | ||
| Statistical Thresholding for EEG artifact Rejection. | ||
| Journal of Neuroscience Methods, 192(1), 152-162. | ||
| .. [2] Delorme, A., Sejnowski, T., & Makeig, S. (2007). Enhanced detection of | ||
| artifacts in EEG data using higher-order statistics and independent | ||
| component analysis. NeuroImage, 34(4), 1443-1449. |
There was a problem hiding this comment.
Small thing, but please add these to the bibliography (doc/references.bib) and cite them in the text with :footcite:. Then at the end of the example, generate the references with:
# References
# ----------
# .. footbibliography::
This example demonstrates the use: https://github.com/mne-tools/mne-python/blob/main/examples/preprocessing/eeg_bridging.py
Reference issue (if any)
Closes #13676
What does this implement/fix?
Adds a
score_quality()method toEpochsthat scores each epoch on a 0 and 1 scale based on how much of an outlier it is relative to the rest of the recording. It uses peak-to-peak amplitude, variance, and kurtosis, z-scored robustly using median absolute deviation, no new dependencies.The idea is to give users a quick, data-driven starting point before calling
drop_bad(), instead of guessing thresholds from scratch. It's not trying to replaceautoreject, just fill the gap for users who want something lightweight and built-in.Additional information
Happy to adjust the API or scoring logic based on feedback. The main open question from the issue whether
suggest_reject=Trueis worth adding, I've left out for now to keep the initial PR focused.