Skip to content

Let users run find_bads_muscle also when no sensor positions are available#12862

Merged
larsoner merged 9 commits intomne-tools:mainfrom
sappelhoff:muscle
Sep 20, 2024
Merged

Let users run find_bads_muscle also when no sensor positions are available#12862
larsoner merged 9 commits intomne-tools:mainfrom
sappelhoff:muscle

Conversation

@sappelhoff
Copy link
Copy Markdown
Member

@sappelhoff sappelhoff commented Sep 18, 2024

This is an "issue as PR", that also contains some commits from #12860 that can be ignored.

The main point that I would like to discuss is, that find_bads_muscle is using three criteria to flag components as bad by muscle activity. However, two of these criteria require sensor positions to work.

I have a dataset without sensor positions available (and no option to add standard positions), and I would still like to run this function, using only the first criterion to flag channels.

In the diff below, I show that this is easily accomplished in principle. In practice I would much rather have some guidance in what components may be muscle related, than none at all.

What are your thoughts on this?

Comment on lines +2015 to +2016
try:
# compute metric #2: distance from the vertex of focus
Copy link
Copy Markdown
Member

@mscheltienne mscheltienne Sep 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of a big try/except block, you could reduce the diff by a check for existence of channel positions and if it's absent exit early?

slope_score = ...
if not has_dig(...):
    warn(...)
    return slope_score
[...]
return

Otherwise, +1 to add this.

Copy link
Copy Markdown
Member Author

@sappelhoff sappelhoff Sep 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the feedback

Yes, that'd be a cleaner solution, and maybe wrap the scoring (currently after the try/except) into a small private function that then gets called either early (after 1st criterion is computed), or later (after all criteria are computed).

are you aware of a simple check whether an object has sensor positions?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inst.get_montage() is None or inst.info["dig"] is None should do it? I remember other utilities exist, but I can't remember where at the moment..

Copy link
Copy Markdown
Member

@mscheltienne mscheltienne Sep 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found it: mne.utils.check.py: _check_ch_locs(info, picks=None, ch_type=None)

@sappelhoff
Copy link
Copy Markdown
Member Author

@mscheltienne would you mind reviewing this?

@mscheltienne
Copy link
Copy Markdown
Member

I'm away until Monday, I can review then if it's still needed.

Copy link
Copy Markdown
Member

@larsoner larsoner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise looks good -- FYI I merged in main to get the CI feedback but feel free to push over it

Comment on lines +2021 to +2024
logger.warning(
"No sensor positions found. Scores for bad muscle components are only "
"based on the 'slope' criterion."
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this you should use warn from mne.utils, it does some nice stuff based on the logging level etc.

Comment on lines +1525 to +1528
with catch_logging() as log:
labels, scores = ica.find_bads_muscle(raw, threshold=0.35)
log = log.getvalue()
assert "based on the 'slope' criterion" in log
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then

Suggested change
with catch_logging() as log:
labels, scores = ica.find_bads_muscle(raw, threshold=0.35)
log = log.getvalue()
assert "based on the 'slope' criterion" in log
with pytest.warns(RuntimeWarning, match="based on the 'slope'"):
labels, scores = ica.find_bads_muscle(raw, threshold=0.35)

@larsoner larsoner enabled auto-merge (squash) September 20, 2024 18:24
@larsoner
Copy link
Copy Markdown
Member

Pushed my suggested fix and marked for merge-when-green, thanks in advance @sappelhoff !

@larsoner larsoner merged commit b9cdca8 into mne-tools:main Sep 20, 2024
@sappelhoff sappelhoff deleted the muscle branch September 20, 2024 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants