Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH, MRG] Add Automatic Muscle Artifact ICA Component Detection #10534

Merged
merged 8 commits into from
Apr 21, 2022

Conversation

alexrockhill
Copy link
Contributor

Fixes #10514. The topomaps are still magnetometers and you can't toggle but I'll write a followup PR for that.

Will link to the example that shows how it works when Circle builds.

@alexrockhill
Copy link
Contributor Author

Looks pretty good to me! Great that someone has already published on it and it wasn't too hard to implement. https://output.circle-artifacts.com/output/job/a105e6c5-2ecf-41c2-b56f-a20761376a3d/artifacts/0/dev/auto_examples/preprocessing/muscle_ica.html?highlight=bad%20muscle

Copy link
Member

@agramfort agramfort left a comment

Choose a reason for hiding this comment

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

Could you run this code in a few EEG subjects from the eegbci dataset to see how it behaves? I would be curious to see how robust is the default threshold.

🙏 🙏 🙏

mne/preprocessing/ica.py Outdated Show resolved Hide resolved
assert pos.shape[0] == components.shape[0] # pos for each component
dists = np.linalg.norm(pos, axis=1)
dists /= dists.max()
focus_dists = np.dot(dists, components_norm)
Copy link
Member

Choose a reason for hiding this comment

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

if you have multiple channel types in inst what do you expect this code to do?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be fine, it's by component normalized so it's not in channel units

Copy link
Member

Choose a reason for hiding this comment

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

agreed but the notion of distance across channel types is weird no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's just distance of the focus for the topomap, whether it's MEG or EEG if the red and blue blobs are far from the vertex that's a high score, it doesn't matter what channel type they are

@alexrockhill
Copy link
Contributor Author

Okay @agramfort, I checked on EEGBCI and just going through the code, I was accidentally using the intercepts instead of the slopes and I failed to normalize the smoothness properly which is why it wasn't working. Now it works awesome, feel free to remove the eegbci part if you want to reduce computation @agramfort but those work great as well. I tried on subject 3 and got rather odd ICA components but I don't think that was really an issue with the algorithm so I didn't include it and stopped there.

Copy link
Member

@agramfort agramfort left a comment

Choose a reason for hiding this comment

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

I would suggest to only keep the eegbci dataset in the example.

examples/decoding/decoding_csp_eeg.py Show resolved Hide resolved
assert pos.shape[0] == components.shape[0] # pos for each component
dists = np.linalg.norm(pos, axis=1)
dists /= dists.max()
focus_dists = np.dot(dists, components_norm)
Copy link
Member

Choose a reason for hiding this comment

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

agreed but the notion of distance across channel types is weird no?

@alexrockhill
Copy link
Contributor Author

agreed but the notion of distance across channel types is weird no?

For the focus distance it doesn't matter but good point for the smoothness, it should be by channel type

@agramfort
Copy link
Member

agramfort commented Apr 18, 2022 via email

@alexrockhill
Copy link
Contributor Author

Ok sounds good, it's complicated because you'd have to append distance matrices and pad them with nans to have one position matrix to multiply with the component matrix. This version right now doesn't divide out by channel types which actually I guess isn't so bad because non-smooth muscle component should be non-smooth in MEG as well (if they show up at all). I think it's good to start.

@alexrockhill
Copy link
Contributor Author

alexrockhill commented Apr 18, 2022

There was just a small docstring error so everything should pass now. I left in the EEGBCI as well as the MNE sample data in the example. The execution time is less than 20 seconds so I think it would be nice to leave everything in because it shows the variability in muscle components based on setup; if the subject is in a relaxed state (probably with a comfortable chair and a task that isn't too demanding/motoric) there might only be one small eigenvalue component but if they have to use more head and neck muscles, half of the components might be from all around the head. I think this example as is covers that diversity really nicely but if you prefer @agramfort or others, I don't feel that strongly and I'm happy to take them out.

EDIT: The two additional EEGBCI calls add about 2 seconds of computation time each so doesn't seem so bad but again not minimal necessary.

examples/preprocessing/muscle_ica.py Outdated Show resolved Hide resolved
examples/preprocessing/muscle_ica.py Show resolved Hide resolved
examples/preprocessing/muscle_ica.py Outdated Show resolved Hide resolved
examples/preprocessing/muscle_ica.py Outdated Show resolved Hide resolved
examples/preprocessing/muscle_ica.py Outdated Show resolved Hide resolved
saved version with smoothness from paper, implementing KL divergence

save kl version

working version [skip ci]

revert

versionadded must be in notes

two more small typos

add test for scores

empty push, Qt segfault

fixed several errors, checked with eegbci

add ref in tutorial, fix tests

fix docstring

alex review
@alexrockhill
Copy link
Contributor Author

Thanks for the review, I incorporated your suggestions :)

@agramfort
Copy link
Member

can you share the new rendered doc when you have it? thx

@alexrockhill
Copy link
Contributor Author

Did someone change the artifact uploading recently? I'm not able to access the circle artifact.

* upstream/main:
  Correct documented default number of CV splits [skip azp][skip actions] (mne-tools#10548)
  MRG: Add error checking to prevent the creation of montage with invalid [x, y, z] (mne-tools#10547)
@larsoner
Copy link
Member

Did someone change the artifact uploading recently? I'm not able to access the circle artifact.

No, and it seems to work on other PRs like:

#10464

Assuming you didn't enable CircleCI on your fork or anything like that, it's hopefully just a temporary glitch. I did a merge with upstream/main then pushed a commit to just build the doc, let's see what happens...

Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
@alexrockhill
Copy link
Contributor Author

Thanks @larsoner, the CIs are running now so maybe it's just a glitch

@alexrockhill
Copy link
Contributor Author

Copy link
Member

@agramfort agramfort left a comment

Choose a reason for hiding this comment

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

thx @alexrockhill

I let you merge after fixing conflict with latest.inc and provided CIs are green.

🙏 🙏 🙏

* upstream/main:
  MAINT: Extra test for coreg (mne-tools#10549)
  BUG: Fix annot meas_date / crop (mne-tools#10491)
  Update latest.inc
  Use liblinear solver instead of lbgfs in all decodung examples [skip azp][skip actions] (mne-tools#10552)
  STY: Hotfix for HTML [ci skip]
  Allow making inverse solutions from fixed-orientation discrete forward models, enabling multi-dipole modeling (mne-tools#10464)
@larsoner larsoner merged commit 5adb552 into mne-tools:main Apr 21, 2022
@larsoner
Copy link
Member

Thanks @alexrockhill !

@alexrockhill alexrockhill deleted the muscle branch April 21, 2022 17:14
larsoner added a commit to hoechenberger/mne-python that referenced this pull request Apr 21, 2022
…10520

* upstream/main:
  MAINT: Respect activation (mne-tools#10546)
  [ENH, MRG] Add Automatic Muscle Artifact ICA Component Detection  (mne-tools#10534)
larsoner added a commit to hoechenberger/mne-python that referenced this pull request Apr 21, 2022
…10533

* upstream/main:
  MAINT: Respect activation (mne-tools#10546)
  [ENH, MRG] Add Automatic Muscle Artifact ICA Component Detection  (mne-tools#10534)
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.

[ENH] Reject ICA components based on muscle artifact
3 participants