-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Topo plots for EEG data, even when no digitization points are present #1619
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
Conversation
|
@dengemann's montage branch #1390 also doesn't add any digitization points, so we're going to need this in order to have a smooth workflow. |
|
looks clean to me. Thanks @wmvanvliet @dengemann please review |
mne/preprocessing/maxfilter.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not a good idea. funky things can and will happen with mutable default parameters (google python mutable defaults). The pattern we're using in such cases is default to None and substitute for the value. Also in this case there does not seem to be a reason to use a list. A tuple would be more appropriate. A tuple with one value will howeve not look that nice in a default parameter. So None as default and the tuple for substitution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tuples are immutable, so this could just be dig_kinds=(FIFF.FIFFV_POINT_CARDINAL,).
However, this is an API change. I think the default needs to be (FIFFV.FIFFV_POINT_CARDINAL, FIFFV_FIFFV_POINT_EXTRA).
|
@wmvanvliet besided my comments LGTM! |
mne/preprocessing/maxfilter.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need this check
|
Since I'm changing things in @agramfort you are mentioned as one of the authors of this function. I've taken the liberty of modifying it to detect this case and handle it gracefully. It forces the center of the sphere to be in the same plane as the other points in this case. Is this acceptable? Will it horribly brake everyone's maxfilter results? |
|
I mentioned these two points already, but it must have been missed:
Make sense? |
|
@Eric89GXL that makes perfect sense, you are right. If EXTRA points are the default, the case that only nasion/auricular points are taken should hardly ever occur. This makes my patch to |
|
Ok, the PR should now be in a usable state. What do you think? |
mne/layouts/layout.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW maxfilter assumes an origin of [0, 0, 40] (in mm) by default, not sure if we want to adopt the same here for layout generation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general use case for not having any digitization points is to use the electrode positions specified by the cap manufacturer, which place the head center at (0, 0, 0).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, makes sense. I wonder if it would be better to have center=None be a kwarg. If None, then estimate, throwing error if it doesn't exist. If not None, should be a 3-element array-like specifying the position. It would add a little bit of overhead for people without digitization, but it has the nice effect of forcing them to explicitly choose the head center. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is a very good idea. That nicely avoids having to spit out an ugly warning too.
|
Other than my comments, looks reasonable to me. |
|
@wmvanvliet I feel we have some redundant code paths here. Already on master for the use case you describe topomaps can be generated when passing the ch_type ... We should investigate and think about unifying the different code paths if they are really redundant. |
|
@dengemann yes we should |
mne/layouts/tests/test_layout.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should still check the RuntimeError is properly raised.
|
besides LGTM |
|
@dengemann as far as I can tell, there is a duplication in code when no layout can be found for the data. both Maybe we should rely on the code in |
|
good catch... I remember opening an issue on this a while ago... |
|
I think I've added the code that does it without fitting a sphere. It more or less follows fieldtrip I think. Would be good to merge both the way you propose.
|
|
There we go! The codepaths are now merged, tests are added and are passing. There is a small API issue I would like your opinion on. When no digitization points are present in the data, I like the idea of manually having to specify the head origin (for example to (0, 0, 0)) and raising an error if no origin was specified. For
|
|
now that I read this back, option 2 should be a clear winner. |
|
@wmvanvliet I would prefer option 2. It kepps things compatible but exposes the issue. Nice work! |
|
let me know when to review |
|
I've rebased, but Travis is still not happy. Some error in a test that exports a source estimate to a Pandas dataset. A test that succeeds on my machine. |
|
you have a rebase issue as it contains commits already in master. travis will fail due to pandas update. Don't bother about it if it's just a pandas failure. |
8684639 to
5354c02
Compare
|
OK, this PR is ready for review. |
|
@dengemann better? |
|
@t3on thanks for the review |
|
I think I've addressed everything now |
|
@wmvanvliet can you rebase on master? |
cf42a26 to
a8d3c2d
Compare
|
Here you go, I squashed everything up to now into a single commit to keep it manageable. |
|
hrm, the imports are failing. What's going on here? |
|
circular import? try using nested imports at some location to see if it fixes the pb. |
mne/channels/layout.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this import could need a nested import
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does! Had the same issue. It seems like your rebasing un-did some of my changes we just merged. Actually in layuot this import has been removed by myself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wmvanvliet ping defaults are still missing. Add: "Defaults to XXX." everywhere where XXX is the default
|
besides LGTM @christianbrodbeck last chance to take a look :) |
|
Thanks @agramfort I trust that it's fine :) , doesn't touch any code that I've been recently working with |
|
@dengemann could you take a look at the documentation for the |
|
Hold on. Removing the fitting of a head sphere and omitting transforming the eeg_loc into head coordinates may have broken things. Where and when exactly are EEG digitization points transformed into head coordinates? What's the difference between |
|
when reading the file from disk loc and eeg_loc contain the same info: I don't know for the rest. |
|
never mind, it's my data that has weird digitization points. |
|
this PR is ready for yet another evaluation round :) |
|
+1 for merge. |
|
@wmvanvliet nice work! Thanks a lot! Merging. |
Topo plots for EEG data, even when no digitization points are present
Many EEG-only labs (including mine) don't bother with source localization and so don't mark EEG electrode locations. When plotting, relying on the approximate electrode positions reported by the cap manufacturer is good enough. In practice, this means ch['eeg_loc'] and ch['loc'] are specified, but no digitization points are present in the data. This breaks
make_eeg_layout, which is currently very picky about which digitization points should be present. This PR makes the function a lot less picky:fit_sphere_to_headshape. This defaults to onlyFIFF.FIFFV_POINT_CARDINAL, which was the defaultbefore I started messing with it in Fix EEG electrode positions in EDF/BDF import. #1541. When calling the function from
make_eeg_layout, more pointsare considered. I've noticed that Neuromag data adds
FIFF.FIFFV_POINT_EEG, while the EDF loader addsFIFF.FIFFV_POINT_EXTRA, so it looks at both in addition toFIFF.FIFFV_POINT_CARDINALlandmarks.make_eeg_layoutstill work even if no digitization points are present. Generate a warning though.