mne-python icon indicating copy to clipboard operation
mne-python copied to clipboard

Default standard_1020 montage contains realistic, not template positions

Open hekolk opened this issue 4 years ago • 36 comments

Describe the bug

On the current master (i.e., after #7066) frontal EEG channels are drawn outside of the head in topoplots.

Steps to reproduce

The simplest variant is probably mne.viz.plot_montage(mne.channels.make_standard_montage('standard_1020')) Naturally it also occurs in plot_topomap and is particularly suboptimal for outline='head' and extrapolate='head'.

Expected results

I would expect the head circumference to intersect the positions of the outer AF, F, FT, ... PO, O electrodes. This would match previous behavior and common plots (e.g., the 10-05 paper http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.116.7379&rep=rep1&type=pdf or https://github.com/sappelhoff/eeg_positions).

Actual results

image

Hence, the head seems to be shifted vertically (T9 and T10 are also not vertically centered with respect to the ears).

Additionally, the comment in the extrapolation snippet https://mne.tools/dev/auto_examples/visualization/plot_evoked_topomap.html suggests that changing the sphere diameter has an influence, but it didn't result in any changes for me.

hekolk avatar Dec 13 '19 17:12 hekolk

for @larsoner

agramfort avatar Dec 13 '19 18:12 agramfort

This is because we plot in head coordinates now, and when we change to head coords it shifts the positions. In theory if you shift the sphere center to the opposite of this shift, it should fix the problem.

It looks like T9/T10/ are not the same as LPA/RPA. And looking at the file:

https://github.com/mne-tools/mne-python/blob/master/mne/channels/data/montages/standard_1020.elc

The LPA is at -86.0761 -19.9897 -47.9860 and T9 is at -85.8941 -15.8287 -48.2830. This contradicts what @sappelhoff's site says:

The left preauricular point = (-1, 0, 0) ... coincides with T9 The right preauricular point = (1, 0, 0) ... coincides with T10

So this does not agree with our standard_1020.elc. Not sure if our elc is wrong, or what.

Additionally, the comment in the extrapolation snippet

Yes this is wrong, it should say that changing the head center will influence things.

larsoner avatar Dec 13 '19 19:12 larsoner

So the values in standard_1020.elc seem to be identical to the "realistic" ones in Robert Oostenveld's blog (https://robertoostenveld.nl/electrode/) :

I have also made a computation of all the electrode locations on a reallistical head surface, based on the distances along the (triangulated) surface of the head. The head surface used was constructed from the canonical MRI that is included in the SPM2 package, and locations are expressed in MNI coordinates.

The coordinates can be found at: https://robertoostenveld.nl/electrodes/realistic_1005.txt For the y coordinates, the absolute values of the maximum (0.0845, Nz) and minimum (-0.113, Iz) differ which might cause the problem if some normalization/centering is performed in the code.

There are also spherical versions The first version (“sphere1”) assumes Fpz, Oz, T7 and T9 to be on the poles of the sphere. The location of Nz, Iz, LPA and RPA is subsequently determined according to the following: Oz is at the equator, Cz is at the north-pole. The difference between them is 90 degrees or pi/2 along the surface of the unit sphere. The distance between each of Cz-CPz-Pz-POz-Oz is equal and is 22.5 degree (note that Pz is at 45 degrees from the north-pole). The distance between Iz and Oz is equal to the other distances, therefore Iz is at 22.5 below the equator. Using this, the coordinates of Iz can be computed using the sin() and cos() of 22.5 degrees. The other “fiducial” points have similar coordinates. The Z value for the whole fiducial points contour is -sin(22.5)=-0.3827.

In the second version (“sphere2”) I have tried to mimic the electrode locations that are used in BESA as close as possible. Compared to the “sphere1” version described above, the electrodes are all shifted to slightly lower locations.

For a spherical head description, LPA and T9 are identical and the absolute values of the y coordinate are the same for Nz and Iz: https://robertoostenveld.nl/electrodes/plotting_1005.txt and https://robertoostenveld.nl/electrodes/sphere_1005.txt

I would say that when using a standard EEG layout, people are fine with a spherical head model and this is especially the case when having topomaps with a circular head shape. Although I haven't tried it, a simple solution might be to use the spherical version for the standard_10xx layouts.

hekolk avatar Dec 16 '19 13:12 hekolk

how would you implement this and expose this to users?

agramfort avatar Dec 17 '19 07:12 agramfort

I only see this now, but let me add some explanation (no solution, only information):

@robertoostenveld's computations versus my own computations are slightly different in their assumptions.

  • Robert says the equator goes through Fpz and Oz (and T7 and T9 ... I think the T9 is actually a typo and meant to be T8)

The first version (“sphere1”) assumes Fpz, Oz, T7 and T9 to be on the poles of the sphere.

  • I say the equator goes through Nz and Iz (and T9 and T10, which I say coincide with LPA/RPA for the sake of the model coordinate system, which is defined by Nasion, Inion, and the preauricular points)

so "my" equator is one contour line below that of Robert's computation, hence the positions do not match up absolutely (only in terms of relative distance).

I am of the impression that the choice through which electrodes the equator of the spherical head model passes is rather arbitrary. My choice was inspired by the Brain Products cap, where on the outermost circle, you would find the Nz, Iz, T9 and T10 electrodes.

image

sappelhoff avatar Feb 04 '20 10:02 sappelhoff

correct, T9 should be T8. I have corrected it on https://robertoostenveld.nl/electrode/

My motivation for the circles is based on https://pdfs.semanticscholar.org/53a7/cf6bf8568c660240c080125e55836d507098.pdf figure 6 and 7 and Jasper 1958 (could not find a PDF so quickly).

The contour through Fpz/T7/Oz/T8 is one that is reasonably easy to follow due to the regularity of the head. If you go further down, you get the nose, eye sockets, and ears in the way. So estimating 10% (or 20%) distances along the lower (Nz/Iz) contour is hard, and not for the Fpz/Oz contour. In https://github.com/fieldtrip/fieldtrip/blob/master/ft_electrodeplacement.m with method=1020 I am using this contour following procedure to place electrodes on a scalp surface, following the contours that follow from the plane intersections with the triangulated surface.

But this is all for source modeling, whereas the original question is about visualization of 3D data on a 2D plane: I don't think spheres reflect the head very well, even though we also use them for http://www.fieldtriptoolbox.org/template/layout/. I like the "helmet" layouts (see under CTF, Neuromag and 4D) more than the sphere ones. I think it would be good (for the wider EEG field) to also use better 2D layouts than "spheres with a triangle for the nose".

Wrt the schematic EEG layout with a circle, I would get rid of the ears. They are not at the right location relative to the electrodes.

PS the 1020 algorithm that is also in ft_electrodeplacement was actually used to create the electrode positions I am sharing on my blog, even though at that time FT did not exist yet. I think I used it both for the spherical model and for the realistic model.

robertoostenveld avatar Feb 04 '20 11:02 robertoostenveld

I think the problem is not that some locations are now outside the head (e.g. AF9, AF10, ...), but that too few locations are outside the head as compared to the previous behavior. Previously, Fz was pretty close to the head circumference (close to the nose), whereas now it is way closer to the center (see before and after plots in #7430).

I don't know which configuration is more correct, but the old behavior definitely looked much better.

cbrnr avatar Mar 13 '20 16:03 cbrnr

@cbrnr I agree, I will take a look at this. Your problem in #7430 may be related to #7341. What I also find weird is that the center of the head indicated by channel scatter does not match the center of head circle. If I move the sphere center to have Cz closer to the head circle center the channel scatter has a straight horizontal line at FCz level. mne.viz.plot_montage(mntg, sphere=(0, 0.016, 0, 0.1)) image

After checking: this issue comes from channel positions, see the first panel on the left (scatter size indicates channel distance in the ignored dimension): ch pos the channels positions seem to be digitized/realistic, not schematic/spherical. This is what @hekolk mentioned earlier. I think the schematic positions would be better if we project to the sphere anyway.

mmagnuski avatar Mar 15 '20 17:03 mmagnuski

Shouldn't channels T9 - T7 - C5 - C3 - C1 - Cz - ... form a horizontal line (according to the cartoon posted by @sappelhoff)?

cbrnr avatar Mar 15 '20 19:03 cbrnr

I think they should, take a look at the previous comment by @hekolk.

mmagnuski avatar Mar 16 '20 01:03 mmagnuski

I'm still not sure what the problem is. Do we already know? What's the plan to fix it? I'd really like this to be fixed for 0.20 so I'm adding this to the milestone.

cbrnr avatar Mar 16 '20 10:03 cbrnr

@cbrnr The 10-20 channel positions 'standard_1020' shipped with mne are the "realistic channel positions" (https://robertoostenveld.nl/electrodes/realistic_1005.txt) but there are also less realistic spherical coordinates (https://robertoostenveld.nl/electrodes/plotting_1005.txt and https://robertoostenveld.nl/electrodes/sphere_1005.txt). The realistic positions are better for coregistering with MRI and source localization (if one does not have digitized channel positions) but for plotting the plotting/spherical positions should be better.

@agramfort @larsoner I think we should default make_standard_montage('standard_1020') to spherical 10-20 coords and allow for make_standard_montage('realistic_1020') (or 'standard_1020_realistic') for the current 10-20 default.

Fixing the usage of sphere in topomap code does help a little (PR soon, more details there) but introduces other issues (that could be avoided but will require some decision).

mmagnuski avatar Mar 16 '20 11:03 mmagnuski

👍 for changing standard_1020 to spherical coords and renaming the existing realistic ones to realistic_1020. Which of the two spherical would you use? Also, which function reads these kinds of files?

cbrnr avatar Mar 16 '20 12:03 cbrnr

no objection as long as it's well documented

agramfort avatar Mar 16 '20 12:03 agramfort

I think we should default make_standard_montage('standard_1020') to spherical 10-20 coords and allow for make_standard_montage('realistic_1020') (or 'standard_1020_realistic') for the current 10-20 default.

Usually we want to deprecate things if the existing option is mostly wrong and we want to give people time to adapt gracefully.

Our current behavior can be summarized as: good source loc, bad sphere head plots. Making the proposed deprecation would lead to: bad source loc, good sphere head plots. This is not a 100% clear gain to me, so I'm not sure if deprecation is justified. I'd lean toward making a standard_1020_sphere and documenting the differences rather than force a "fix" on people that will break otherwise reasonable/working code.

However, I am no a "template EEG" expert, so if having the 10-20 electrode locations land where people expect in topomaps -- and it has come up a few times obviously -- is substantially more important than having good source loc by default, and important/common enough to justify breaking existing code for people, I can live with it. But if we do so we should probably just get rid of standard_1020 altogether and have standard_1020_sphere and standard_1020_realistic as the new options to force people to be explicit about their choice.

larsoner avatar Mar 16 '20 13:03 larsoner

Also, which function reads these kinds of files?

https://mne.tools/dev/generated/mne.channels.make_standard_montage.html

larsoner avatar Mar 16 '20 13:03 larsoner

I really liked the old topomaps much better. In my EEG-related work I never had real electrode locations, but there are use cases where real locations improve e.g. source localization. Just creating a nice looking topomap serves a different purpose, so I think it would be good to have both options. As long as we plot to a spherical topomap (is there an option to use a realistic head, especially in 2D?) I think realistic locations are not appropriate and I'd prefer the theoretical locations.

How can I read non-built-in montage files with this function?

cbrnr avatar Mar 16 '20 14:03 cbrnr

As long as we plot to a spherical topomap (is there an option to use a realistic head, especially in 2D?) I think realistic locations are not appropriate and I'd prefer the theoretical locations.

The central idea that the big refactoring took care of was that we have one code path for all electrode locations (digitized or from a template / "theoretical") to go to the flattened 2D plot for topomaps. I'd prefer not to compromise this or the better-for-source localization (i.e., switch to theoretical rather than realistic locations) to make the 2D flattening projection look a bit better. So I think we just have differences in the weights we assign these things...

How can I read non-built-in montage files with this function?

I am not an expert here (or in the file formats), but the Notes seems to list a bunch of function names. Did you look there and/or in our docs to see if what you want to do is covered?

larsoner avatar Mar 16 '20 14:03 larsoner

The central idea that the big refactoring took care of was that we have one code path for all electrode locations (digitized or from a template / "theoretical") to go to the flattened 2D plot for topomaps. I'd prefer not to compromise this or the better-for-source localization (i.e., switch to theoretical rather than realistic locations) to make the 2D flattening projection look a bit better. So I think we just have differences in the weights we assign these things...

Having one code path is a good thing, but the new behavior is clearly a regression for the use case of plotting template locations on a 2D sphere. If you think this can be solved by tweaking some weights this is fine with me (as long as the result looks like it used to). Is this what #7455 solves?

I am not an expert here (or in the file formats), but the Notes seems to list a bunch of function names. Did you look there and/or in our docs to see if what you want to do is covered?

Me neither, but I saw the function names and thought mne.channels.read_custom_montage would do the job. It does read the file, but I can't plot the montage because ValueError: Some fiducial points are missing (got dict_keys(['nasion', 'lpa', 'rpa'])). So maybe this is not the correct reader function.

cbrnr avatar Mar 16 '20 14:03 cbrnr

@cbrnr

I really liked the old topomaps much better.

I think you are referring to two (or more) issues here actually. The channel positions for 1020 were like this (meaning: realistic) before topomap plotting changes IIRC, so they are not responsible for your preferrence of the old topomaps. What you experience in #7430 is thus more related to the new topo plotting: (1) the channels are not stretched to the whole head as previously irrespective of their actual position (this is a definitive improvement), (2) the sphere argument did not work exactly as expected (#7455, #7341) and as I suggest in #7455 could have a better default. It would be best to disccuss topomap (2) in #7455 and focus on standard_1020 realistic vs spherical here.

@larsoner

I'd lean toward making a standard_1020_sphere and documenting the differences rather than force a "fix" on people that will break otherwise reasonable/working code.

I'm fine with this too. Although I think that 2d topomap plotting is much more popular in EEG world than source localization using template chan locs. There seems to be only one example in mne docs on how to do source localization with channel and brain template so it might be worth stressing the usage of standard_1020_realistic there (probably most users trying to do that use this example as a starting point). Other channel positions like biosemi for example are spherical by default - so it would be worthwhile to add such a warning to the docs anyway (by default mne coreg tries to rescale the head model to match the channel positions, while with spherical EEG chanlocs we would actually prefer to do the opposite). Informing the users about standard_1020_spherical might be more difficult ( a warning when reading standard_1020 in the next two mne versions? that might be effective but also irritating :) ). But I don't have a strong opinion here, I just slightly prefer (+0.25) a deprecation (with standard_1020 transitioning from standard_1020_realistic to standard_1020_spherical).

mmagnuski avatar Mar 16 '20 16:03 mmagnuski

if we do so we should probably just get rid of standard_1020 altogether and have standard_1020_sphere and standard_1020_realistic as the new options to force people to be explicit about their choice.

:+1: for this suggestion. It's disruptive, but IMO that's better than silently having old code make plots look different enough to cause people to get annoyed.

drammock avatar Mar 16 '20 19:03 drammock

@drammock @larsoner Oh, I might have missed this part - I also like this idea.

mmagnuski avatar Mar 16 '20 19:03 mmagnuski

FWIW, the biosemi64 montage contains 10-20 labels and seems to have template locations (as opposed to realistic ones):

Figure_2

This looks OK. Here's what this montage looks with 0.19.2:

Figure_current

IMO the new plot looks better (in terms of where I'd expect template locations to be). So whatever will be changed regarding the suboptimal visualization of realistic montages (e.g. #7455), please make sure that template montages are not affected.

cbrnr avatar Mar 18 '20 09:03 cbrnr

@cbrnr All topomap/montage plotting will be affected in a way (but not the montages themselves), because plotting with respect to a sphere has to work the same way irrespective of used montage. But don't worry, if channel positions don't look good we may consider changing the default sphere radius. But most of all - you will be able to control the exact channel placement by changing sphere center and radius, to adjust channel placement to your liking.

mmagnuski avatar Mar 18 '20 11:03 mmagnuski

That's part of the problem. I'd expect a template montage to look good by default when plotted on a sphere. I don't want to tweak parameters until the locations are right.

cbrnr avatar Mar 18 '20 14:03 cbrnr

Based on the discussions, this issue seems sufficiently complex that I think we should move the milestone to 0.21. Otherwise I fear we'll end up delaying release for weeks or months as we sort everything out.

larsoner avatar Mar 18 '20 14:03 larsoner

shall we plan a quick live discussion on hangout ?

agramfort avatar Mar 18 '20 15:03 agramfort

Moving the milestone to 0.21 under the assumption that #7455 is good enough for release and/or we can backport any fix to 0.20.1

larsoner avatar Mar 25 '20 19:03 larsoner

Has this been superseded by #7472?

If not, I'd like to chime in and say:

👍 for changing standard_1020 to spherical coords and renaming the existing realistic ones to realistic_1020.

Yes please!!

I was also just running into this issue:

m = mne.channels.make_standard_montage('standard_1005')
print(m.dig[m.ch_names.index('Cz')])

gives:

<DigPoint |    EEG #39 : (-78.6, -13.5, 28.6) mm   : unknown frame>

which is really not what it should be…

hoechenberger avatar Jan 20 '21 16:01 hoechenberger

@hoechenberger That is because len(mntg.ch_names) < len(mntg.dig), first three dig points are fiducials. But I agree this is inconvenient - maybe fiducials should be at the end, not front of the list?

mmagnuski avatar Jan 20 '21 19:01 mmagnuski