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

Create canonical template channel locations

Open cbrnr opened this issue 4 years ago • 92 comments

Currently there are some issues with plotting montages, especially with those consisting of template locations (as opposed to realistic locations), see e.g. #7141 and #7455.

At the moment, MNE ships 24 montage files, and it is not obvious which of these contain template locations and which contain realistic locations. Moreover, among these montage files there are several files containing template locations, which is really confusing.

Ideally, there should be only one template containing all possible locations. This is something we have already discussed in #5269. Unfortunately, the discussion went into a different direction and the issue was closed without solving the original problem.

Therefore, I'd like to bring up this issue again. I suggest that we get rid of the various template location files and unify them in one central place. We could use a simple text file where we could also support multiple labels per location to accommodate different naming schemes. We could compute all locations with the tools provided by @sappelhoff, and we could either include his calculation tools or just the resulting text file in MNE.

cbrnr avatar Mar 18 '20 10:03 cbrnr

disclairmer neither me or @larsoner or @massich with who I did most of the refactoring of DigMontage have strong experience with EEG data requiring a template. The history is that we took files from fieldtrip and aimed at offering the same options with MNE. Ideally we should as well or better than fieldtrip or eeglab with little effort. Now I don't have any strong opinion of how to achieve this. I just have the impression that depending of eeg system it's easier to have a file per EEG cap. my 2c

agramfort avatar Mar 18 '20 10:03 agramfort

In my experience, topomaps are often used to visualize (channel-based) results. In such cases, it is more important that the maps look pretty (symmetrical), because exact locations are usually not available. This is what template locations are mainly used for.

Most caps use some variation of the extended 10-20, 10-10 or 10-05 systems, which are all based on the same underlying subdivision of certain distances on a sphere. However, sometimes they use different names for the same locations. Therefore, I think having only one template with a large number of channels (e.g. 345 as @sappelhoff proposed) would be sufficient to create all kinds of different montages (if we allow for duplicate labels).

Right now the whole montage system is rather messy. It is nice that there are some realistic montages, but there should be only one template montage as opposed to many (partially or completely) overlapping files.

cbrnr avatar Mar 18 '20 11:03 cbrnr

Right now the whole montage system is rather messy. It is nice that there are some realistic montages, but there should be only one template montage as opposed to many (partially or completely) overlapping files.

I agree.

Some manufacturers (e.g., Biosemi) however do use their own system (not a standard), and thus the template positions of the 10-05 system do not apply.

sappelhoff avatar Mar 18 '20 11:03 sappelhoff

Some manufacturers (e.g., Biosemi) however do use their own system (not a standard), and thus the template positions of the 10-05 system do not apply.

True, but in this case we can have more than one template locations file if they are based on different divisions of the (spherical) head. Also, BioSemi does not exclusively use its own non-standard locations - we have a BioSemi system in our lab and our caps are standard 10-20 (basically what MNE already ships with the biosemi64 montage).

Can you create BioSemi custom locations too?

cbrnr avatar Mar 18 '20 11:03 cbrnr

Also, BioSemi does not exclusively use its own non-standard locations - we have a BioSemi system in our lab and our caps are standard 10-20 (basically what MNE already ships with the biosemi64 montage).

Yes, they use 10-20 and what they call ABC (never used it)

Can you create BioSemi custom locations too?

generally yes (but not me personally right now), I don't know how straight forward it would be: you can download a speadsheet on https://www.biosemi.com/headcap.htm ... and in that spreadsheet you see the data for the positions. But you'd have to:

  • reverse engineer the algorithm to compute them OR
  • hope the biosemi customer service is cooperative

:thinking:

sappelhoff avatar Mar 18 '20 11:03 sappelhoff

I'm actually fine with the current state of affairs with respect to channel locations (apart from #7141). As long as these separate files correspond to channel locations shipped by the producer, I'm ok with duplication/overlap/inconsistencies.

mmagnuski avatar Mar 18 '20 12:03 mmagnuski

https://mne.tools/dev/auto_tutorials/intro/plot_40_sensor_locations.html?highlight=montage is our new entry point to document how to work with sensor locations.

we have this https://mne.tools/dev/auto_tutorials/io/plot_20_reading_eeg_data.html?highlight=montage and https://mne.tools/dev/auto_examples/visualization/plot_montage.html?highlight=montage

I don't want to propose to start doing MEP (MNE Enhancement Proposals) but a more detailed plan would help me follow how to progress starting from what we have now.

agramfort avatar Mar 18 '20 12:03 agramfort

I didn't know that there is a separate Layout class. So isn't this already a separation between realistic (Montage) vs. template (Layout) locations? I don't quite understand the distinction, because it seems you can only assign a montage to a raw object but not a layout.

cbrnr avatar Mar 18 '20 13:03 cbrnr

I'm actually fine with the current state of affairs with respect to channel locations (apart from #7141). As long as these separate files correspond to channel locations shipped by the producer, I'm ok with duplication/overlap/inconsistencies.

Many/most people will be needing 10-20/10-10/10-05 locations, so I think it is confusing to have a selection of different manufacturer montages containing basically the same channels.

cbrnr avatar Mar 18 '20 13:03 cbrnr

Layout is really only ever meant to be used with plot_topo, never shown in relationship to a head circle (because in general the geometry is incorrect / inconsistent). This has been discussed a lot over the last 3 years and this is what we settled on.

larsoner avatar Mar 18 '20 13:03 larsoner

we have decided that layout should be removed for topomaps and just used for axes grids as used in evoked.plot_topo

I think...

agramfort avatar Mar 18 '20 13:03 agramfort

OK, so we should basically always use montages.

cbrnr avatar Mar 18 '20 14:03 cbrnr

Yeah that's the TL;DR :)

larsoner avatar Mar 18 '20 14:03 larsoner

@sappelhoff how can I read your 10/10 TSV file? I tried mne.channels.read_custom_montage, but the format (extension) is not supported. I tried renaming to .txt, but then the function complains about missing fiducials.

cbrnr avatar Mar 18 '20 14:03 cbrnr

It's not "MNE-READY", I always read it with pandas and I have my own simple plotting function to display the positions: https://github.com/sappelhoff/eeg_positions/blob/8d91d63c4996a81aabc24ea14dae51e8e1833ca9/eeg_positions/eeg_positions.py

pull requests welcome. The main contribution of my repository is figuring out how manufacturers produce their "template" positions and having that algorithm as a python function: https://github.com/sappelhoff/eeg_positions/blob/8d91d63c4996a81aabc24ea14dae51e8e1833ca9/eeg_positions/utils.py#L10

EDIT: for fiducials, you can check the assumptions I make:

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

Adding these three points as fiducials (they would be duplicated with T9, T10, and Nz then) should be enough for MNE.

sappelhoff avatar Mar 18 '20 14:03 sappelhoff

Many/most people will be needing 10-20/10-10/10-05 locations, so I think it is confusing to have a selection of different manufacturer montages containing basically the same channels.

It might be confusing, I understand that. I never personally found it confusing though. Are you sure there are no location differences between these files?

mmagnuski avatar Mar 18 '20 16:03 mmagnuski

would a hangout meeting work for tomorrow around 3pm Paris time?

agramfort avatar Mar 18 '20 21:03 agramfort

would a hangout meeting work for tomorrow around 3pm Paris time?

Yes, I should be available. I have another meeting at 2pm, so I might be a bit late if we don't finish on time.

cbrnr avatar Mar 19 '20 08:03 cbrnr

sent an cal invitation with hangout link

agramfort avatar Mar 19 '20 09:03 agramfort

@agramfort @cbrnr

Here is code to read my computed standard locations from the eeg_postitions repo into an MNE montage (SEE "DETAILS" BELOW THE PLOT). Note: Scroll down, there is lots of data pasted here for convenience.

Results in this plot:

image

import pandas as pd
import numpy as np
import mne

# NOTE: This is downloaded from https://github.com/sappelhoff/eeg_positions/blob/master/data/standard_1005.tsv
DATA = """
label	x	y	z
Nz	0.0000	1.0000	0.0000
Iz	0.0000	-1.0000	0.0000
Cz	0.0000	0.0000	1.0000
T9	-1.0000	0.0000	0.0000
T10	1.0000	0.0000	0.0000
NFpz	0.0000	0.9877	0.1564
Fpz	0.0000	0.9511	0.3090
AFpz	0.0000	0.8910	0.4540
AFz	0.0000	0.8090	0.5878
AFFz	0.0000	0.7071	0.7071
Fz	0.0000	0.5878	0.8090
FFCz	0.0000	0.4540	0.8910
FCz	0.0000	0.3090	0.9511
FCCz	0.0000	0.1564	0.9877
CCPz	0.0000	-0.1564	0.9877
CPz	0.0000	-0.3090	0.9511
CPPz	0.0000	-0.4540	0.8910
Pz	0.0000	-0.5878	0.8090
PPOz	0.0000	-0.7071	0.7071
POz	0.0000	-0.8090	0.5878
POOz	0.0000	-0.8910	0.4540
Oz	0.0000	-0.9511	0.3090
OIz	0.0000	-0.9877	0.1564
N2h	0.1564	0.9877	0.0000
N2	0.3090	0.9511	0.0000
AFp10	0.4540	0.8910	0.0000
AF10	0.5878	0.8090	0.0000
AFF10	0.7071	0.7071	0.0000
F10	0.8090	0.5878	0.0000
FFT10	0.8910	0.4540	0.0000
FT10	0.9511	0.3090	0.0000
FTT10	0.9877	0.1564	0.0000
TTP10	0.9877	-0.1564	0.0000
TP10	0.9511	-0.3090	0.0000
TPP10	0.8910	-0.4540	0.0000
P10	0.8090	-0.5878	0.0000
PPO10	0.7071	-0.7071	0.0000
PO10	0.5878	-0.8090	0.0000
POO10	0.4540	-0.8910	0.0000
I2	0.3090	-0.9511	0.0000
I2h	0.1564	-0.9877	0.0000
N1h	-0.1564	0.9877	0.0000
N1	-0.3090	0.9511	0.0000
AFp9	-0.4540	0.8910	0.0000
AF9	-0.5878	0.8090	0.0000
AFF9	-0.7071	0.7071	0.0000
F9	-0.8090	0.5878	0.0000
FFT9	-0.8910	0.4540	0.0000
FT9	-0.9511	0.3090	0.0000
FTT9	-0.9877	0.1564	0.0000
TTP9	-0.9877	-0.1564	0.0000
TP9	-0.9511	-0.3090	0.0000
TPP9	-0.8910	-0.4540	0.0000
P9	-0.8090	-0.5878	0.0000
PPO9	-0.7071	-0.7071	0.0000
PO9	-0.5878	-0.8090	0.0000
POO9	-0.4540	-0.8910	0.0000
I1	-0.3090	-0.9511	0.0000
I1h	-0.1564	-0.9877	0.0000
T9h	-0.9877	0.0000	0.1564
T7	-0.9511	0.0000	0.3090
T7h	-0.8910	0.0000	0.4540
C5	-0.8090	0.0000	0.5878
C5h	-0.7071	0.0000	0.7071
C3	-0.5878	0.0000	0.8090
C3h	-0.4540	0.0000	0.8910
C1	-0.3090	0.0000	0.9511
C1h	-0.1564	0.0000	0.9877
C2h	0.1564	0.0000	0.9877
C2	0.3090	0.0000	0.9511
C4h	0.4540	0.0000	0.8910
C4	0.5878	0.0000	0.8090
C6h	0.7071	0.0000	0.7071
C6	0.8090	0.0000	0.5878
T8h	0.8910	0.0000	0.4540
T8	0.9511	0.0000	0.3090
T10h	0.9877	0.0000	0.1564
NFp2h	0.1545	0.9755	0.1564
NFp2	0.3052	0.9394	0.1564
AFp10h	0.4484	0.8800	0.1564
AF10h	0.5806	0.7991	0.1564
AFF10h	0.6984	0.6984	0.1564
F10h	0.7991	0.5806	0.1564
FFT10h	0.8800	0.4484	0.1564
FT10h	0.9394	0.3052	0.1564
FTT10h	0.9755	0.1545	0.1564
TTP10h	0.9755	-0.1545	0.1564
TP10h	0.9394	-0.3052	0.1564
TPP10h	0.8800	-0.4484	0.1564
P10h	0.7991	-0.5806	0.1564
PPO10h	0.6984	-0.6984	0.1564
PO10h	0.5806	-0.7991	0.1564
POO10h	0.4484	-0.8800	0.1564
OI2	0.3052	-0.9394	0.1564
OI2h	0.1545	-0.9755	0.1564
NFp1h	-0.1545	0.9755	0.1564
NFp1	-0.3052	0.9394	0.1564
AFp9h	-0.4484	0.8800	0.1564
AF9h	-0.5806	0.7991	0.1564
AFF9h	-0.6984	0.6984	0.1564
F9h	-0.7991	0.5806	0.1564
FFT9h	-0.8800	0.4484	0.1564
FT9h	-0.9394	0.3052	0.1564
FTT9h	-0.9755	0.1545	0.1564
TTP9h	-0.9755	-0.1545	0.1564
TP9h	-0.9394	-0.3052	0.1564
TPP9h	-0.8800	-0.4484	0.1564
P9h	-0.7991	-0.5806	0.1564
PPO9h	-0.6984	-0.6984	0.1564
PO9h	-0.5806	-0.7991	0.1564
POO9h	-0.4484	-0.8800	0.1564
OI1	-0.3052	-0.9394	0.1564
OI1h	-0.1545	-0.9755	0.1564
Fp2h	0.1488	0.9394	0.3090
Fp2	0.2939	0.9045	0.3090
AFp8	0.4318	0.8474	0.3090
AF8	0.5590	0.7695	0.3090
AFF8	0.6725	0.6725	0.3090
F8	0.7695	0.5590	0.3090
FFT8	0.8474	0.4318	0.3090
FT8	0.9045	0.2939	0.3090
FTT8	0.9394	0.1488	0.3090
TTP8	0.9394	-0.1488	0.3090
TP8	0.9045	-0.2939	0.3090
TPP8	0.8474	-0.4318	0.3090
P8	0.7695	-0.5590	0.3090
PPO8	0.6725	-0.6725	0.3090
PO8	0.5590	-0.7695	0.3090
POO8	0.4318	-0.8474	0.3090
O2	0.2939	-0.9045	0.3090
O2h	0.1488	-0.9394	0.3090
Fp1h	-0.1488	0.9394	0.3090
Fp1	-0.2939	0.9045	0.3090
AFp7	-0.4318	0.8474	0.3090
AF7	-0.5590	0.7695	0.3090
AFF7	-0.6725	0.6725	0.3090
F7	-0.7695	0.5590	0.3090
FFT7	-0.8474	0.4318	0.3090
FT7	-0.9045	0.2939	0.3090
FTT7	-0.9394	0.1488	0.3090
TTP7	-0.9394	-0.1488	0.3090
TP7	-0.9045	-0.2939	0.3090
TPP7	-0.8474	-0.4318	0.3090
P7	-0.7695	-0.5590	0.3090
PPO7	-0.6725	-0.6725	0.3090
PO7	-0.5590	-0.7695	0.3090
POO7	-0.4318	-0.8474	0.3090
O1	-0.2939	-0.9045	0.3090
O1h	-0.1488	-0.9394	0.3090
AFp7h	-0.3848	0.8573	0.3420
AFp5	-0.3350	0.8661	0.3711
AFp5h	-0.2829	0.8736	0.3960
AFp3	-0.2288	0.8798	0.4167
AFp3h	-0.1730	0.8847	0.4329
AFp1	-0.1160	0.8882	0.4446
AFp1h	-0.0582	0.8903	0.4517
AFp2h	0.0582	0.8903	0.4517
AFp2	0.1160	0.8882	0.4446
AFp4h	0.1730	0.8847	0.4329
AFp4	0.2288	0.8798	0.4167
AFp6h	0.2829	0.8736	0.3960
AFp6	0.3350	0.8661	0.3711
AFp8h	0.3848	0.8573	0.3420
AF7h	-0.5070	0.7782	0.3706
AF5	-0.4481	0.7861	0.4259
AF5h	-0.3832	0.7929	0.4740
AF3	-0.3130	0.7986	0.5142
AF3h	-0.2385	0.8031	0.5461
AF1	-0.1608	0.8064	0.5692
AF1h	-0.0810	0.8083	0.5832
AF2h	0.0810	0.8083	0.5832
AF2	0.1608	0.8064	0.5692
AF4h	0.2385	0.8031	0.5461
AF4	0.3130	0.7986	0.5142
AF6h	0.3832	0.7929	0.4740
AF6	0.4481	0.7861	0.4259
AF8h	0.5070	0.7782	0.3706
AFF7h	-0.6175	0.6800	0.3953
AFF5	-0.5515	0.6868	0.4734
AFF5h	-0.4756	0.6928	0.5421
AFF3	-0.3911	0.6978	0.6001
AFF3h	-0.2997	0.7018	0.6463
AFF1	-0.2028	0.7047	0.6799
AFF1h	-0.1023	0.7065	0.7003
AFF2h	0.1023	0.7065	0.7003
AFF2	0.2028	0.7047	0.6799
AFF4h	0.2997	0.7018	0.6463
AFF4	0.3911	0.6978	0.6001
AFF6h	0.4756	0.6928	0.5421
AFF6	0.5515	0.6868	0.4734
AFF8h	0.6175	0.6800	0.3953
F7h	-0.7125	0.5652	0.4159
F5	-0.6408	0.5708	0.5135
F5h	-0.5557	0.5758	0.5998
F3	-0.4591	0.5800	0.6730
F3h	-0.3529	0.5833	0.7316
F1	-0.2394	0.5858	0.7743
F1h	-0.1210	0.5873	0.8003
F2h	0.1210	0.5873	0.8003
F2	0.2394	0.5858	0.7743
F4h	0.3529	0.5833	0.7316
F4	0.4591	0.5800	0.6730
F6h	0.5557	0.5758	0.5998
F6	0.6408	0.5708	0.5135
F8h	0.7125	0.5652	0.4159
FFT7h	-0.7890	0.4365	0.4323
FFC5	-0.7128	0.4408	0.5455
FFC5h	-0.6205	0.4447	0.6460
FFC3	-0.5141	0.4479	0.7315
FFC3h	-0.3961	0.4505	0.8001
FFC1	-0.2692	0.4524	0.8502
FFC1h	-0.1361	0.4536	0.8808
FFC2h	0.1361	0.4536	0.8808
FFC2	0.2692	0.4524	0.8502
FFC4h	0.3961	0.4505	0.8001
FFC4	0.5141	0.4479	0.7315
FFC6h	0.6205	0.4447	0.6460
FFC6	0.7128	0.4408	0.5455
FFT8h	0.7890	0.4365	0.4323
FT7h	-0.8452	0.2971	0.4443
FC5	-0.7658	0.3000	0.5688
FC5h	-0.6682	0.3026	0.6797
FC3	-0.5547	0.3048	0.7742
FC3h	-0.4280	0.3066	0.8502
FC1	-0.2911	0.3079	0.9058
FC1h	-0.1473	0.3087	0.9397
FC2h	0.1473	0.3087	0.9397
FC2	0.2911	0.3079	0.9058
FC4h	0.4280	0.3066	0.8502
FC4	0.5547	0.3048	0.7742
FC6h	0.6682	0.3026	0.6797
FC6	0.7658	0.3000	0.5688
FT8h	0.8452	0.2971	0.4443
FTT7h	-0.8795	0.1504	0.4515
FCC5	-0.7982	0.1519	0.5830
FCC5h	-0.6974	0.1532	0.7002
FCC3	-0.5795	0.1543	0.8003
FCC3h	-0.4475	0.1552	0.8808
FCC1	-0.3045	0.1559	0.9397
FCC1h	-0.1541	0.1563	0.9757
FCC2h	0.1541	0.1563	0.9757
FCC2	0.3045	0.1559	0.9397
FCC4h	0.4475	0.1552	0.8808
FCC4	0.5795	0.1543	0.8003
FCC6h	0.6974	0.1532	0.7002
FCC6	0.7982	0.1519	0.5830
FTT8h	0.8795	0.1504	0.4515
TTP7h	-0.8795	-0.1504	0.4515
CCP5	-0.7982	-0.1519	0.5830
CCP5h	-0.6974	-0.1532	0.7002
CCP3	-0.5795	-0.1543	0.8003
CCP3h	-0.4475	-0.1552	0.8808
CCP1	-0.3045	-0.1559	0.9397
CCP1h	-0.1541	-0.1563	0.9757
CCP2h	0.1541	-0.1563	0.9757
CCP2	0.3045	-0.1559	0.9397
CCP4h	0.4475	-0.1552	0.8808
CCP4	0.5795	-0.1543	0.8003
CCP6h	0.6974	-0.1532	0.7002
CCP6	0.7982	-0.1519	0.5830
TTP8h	0.8795	-0.1504	0.4515
TP7h	-0.8452	-0.2971	0.4443
CP5	-0.7658	-0.3000	0.5688
CP5h	-0.6682	-0.3026	0.6797
CP3	-0.5547	-0.3048	0.7742
CP3h	-0.4280	-0.3066	0.8502
CP1	-0.2911	-0.3079	0.9058
CP1h	-0.1473	-0.3087	0.9397
CP2h	0.1473	-0.3087	0.9397
CP2	0.2911	-0.3079	0.9058
CP4h	0.4280	-0.3066	0.8502
CP4	0.5547	-0.3048	0.7742
CP6h	0.6682	-0.3026	0.6797
CP6	0.7658	-0.3000	0.5688
TP8h	0.8452	-0.2971	0.4443
TPP7h	-0.7890	-0.4365	0.4323
CPP5	-0.7128	-0.4408	0.5455
CPP5h	-0.6205	-0.4447	0.6460
CPP3	-0.5141	-0.4479	0.7315
CPP3h	-0.3961	-0.4505	0.8001
CPP1	-0.2692	-0.4524	0.8502
CPP1h	-0.1361	-0.4536	0.8808
CPP2h	0.1361	-0.4536	0.8808
CPP2	0.2692	-0.4524	0.8502
CPP4h	0.3961	-0.4505	0.8001
CPP4	0.5141	-0.4479	0.7315
CPP6h	0.6205	-0.4447	0.6460
CPP6	0.7128	-0.4408	0.5455
TPP8h	0.7890	-0.4365	0.4323
P7h	-0.7125	-0.5652	0.4159
P5	-0.6408	-0.5708	0.5135
P5h	-0.5557	-0.5758	0.5998
P3	-0.4591	-0.5800	0.6730
P3h	-0.3529	-0.5833	0.7316
P1	-0.2394	-0.5858	0.7743
P1h	-0.1210	-0.5873	0.8003
P2h	0.1210	-0.5873	0.8003
P2	0.2394	-0.5858	0.7743
P4h	0.3529	-0.5833	0.7316
P4	0.4591	-0.5800	0.6730
P6h	0.5557	-0.5758	0.5998
P6	0.6408	-0.5708	0.5135
P8h	0.7125	-0.5652	0.4159
PPO7h	-0.6175	-0.6800	0.3953
PPO5	-0.5515	-0.6868	0.4734
PPO5h	-0.4756	-0.6928	0.5421
PPO3	-0.3911	-0.6978	0.6001
PPO3h	-0.2997	-0.7018	0.6463
PPO1	-0.2028	-0.7047	0.6799
PPO1h	-0.1023	-0.7065	0.7003
PPO2h	0.1023	-0.7065	0.7003
PPO2	0.2028	-0.7047	0.6799
PPO4h	0.2997	-0.7018	0.6463
PPO4	0.3911	-0.6978	0.6001
PPO6h	0.4756	-0.6928	0.5421
PPO6	0.5515	-0.6868	0.4734
PPO8h	0.6175	-0.6800	0.3953
PO7h	-0.5070	-0.7782	0.3706
PO5	-0.4481	-0.7861	0.4259
PO5h	-0.3832	-0.7929	0.4740
PO3	-0.3130	-0.7986	0.5142
PO3h	-0.2385	-0.8031	0.5461
PO1	-0.1608	-0.8064	0.5692
PO1h	-0.0810	-0.8083	0.5832
PO2h	0.0810	-0.8083	0.5832
PO2	0.1608	-0.8064	0.5692
PO4h	0.2385	-0.8031	0.5461
PO4	0.3130	-0.7986	0.5142
PO6h	0.3832	-0.7929	0.4740
PO6	0.4481	-0.7861	0.4259
PO8h	0.5070	-0.7782	0.3706
POO7h	-0.3848	-0.8573	0.3420
POO5	-0.3350	-0.8661	0.3711
POO5h	-0.2829	-0.8736	0.3960
POO3	-0.2288	-0.8798	0.4167
POO3h	-0.1730	-0.8847	0.4329
POO1	-0.1160	-0.8882	0.4446
POO1h	-0.0582	-0.8903	0.4517
POO2h	0.0582	-0.8903	0.4517
POO2	0.1160	-0.8882	0.4446
POO4h	0.1730	-0.8847	0.4329
POO4	0.2288	-0.8798	0.4167
POO6h	0.2829	-0.8736	0.3960
POO6	0.3350	-0.8661	0.3711
POO8h	0.3848	-0.8573	0.3420
"""

# Write data and read as pandas DF
fname = 'data1005.csv'
with open(fname, 'w') as fout:
    fout.write(DATA)

df = pd.read_csv(fname, sep='\t')

# Turn data into digmontage
ch_pos = df.set_index('label').to_dict('index')
for key, val in ch_pos.items():
    ch_pos[key] = np.asarray(list(val.values()))

data = mne.utils.Bunch(
    nasion=ch_pos['Nz'],
    lpa=ch_pos['T9'],
    rpa=ch_pos['T10'],
    ch_pos=ch_pos,
    coord_frame='unknown',
    hsp=None, hpi=None,
)

montage = mne.channels.make_dig_montage(**data)

montage.plot()

sappelhoff avatar Mar 19 '20 15:03 sappelhoff

For fun, I also plotted @robertoostenveld's electrode positions from his blog post using the same Python code as in https://github.com/mne-tools/mne-python/issues/7472#issuecomment-601253011.

(3 adjustments: add column names to Robert's data, and in Robert's data, lpa=LPA and rpa=RPA, instead of for my case lpa=T9, rpa=T10)

Note how both electrode position datasets line up (compare to https://github.com/mne-tools/mne-python/issues/7472#issuecomment-601253011), although in Robert's assumption the equator is going through Fpz, Oz, T7 and T8 ... and mine is one contour line below: Nz, Iz, T9, T10

Interesting to see:

  • Robert does not include the electrode right on the eyes ... I just left them in my dataset, because THEORETICALLY, they are valid ... although in practice it's impossible to put electrodes there (at least in living creatures) :-)
  • In the plot of Robert's data, T9 is overplotted with LPA and T10 is overplotted with RPA --> showing again, how the data line up.

For me this is interesting, because it seems to show that for MNE plotting purposes the assumption of where the equator of the sphere goes DOES NOT MATTER.

image

sappelhoff avatar Mar 19 '20 17:03 sappelhoff

Very nice @sappelhoff! Your montage seems a bit cleaner to me so I'd prefer if we used it as the new default EEG montage. I can integrate this into make_standard_montage if you want. I'll also try this montage with my topomaps and see how it looks like.

Open issues:

  • How do we name the montage? The best name would be standard_1005, but this is already taken. I'd still vote for this name because it is the most intuitive one. The other standard montages should be renamed to something else.
  • Alternatively, we could use the name template_1005, but this is less obvious.
  • We should clearly promote this new montage as the standard EEG template locations and clarify what the other montages really contain.

cbrnr avatar Mar 19 '20 18:03 cbrnr

+1 :

  • to integrate these files in make_standard_montage
  • name it template_1005
  • deprecate standard_1005 and standard_1020 saying to use template_1005
  • update the doc pages accordingly

question :

  • can we use the same file for fsaverage template locations? we do need a realistic_1005 file?

how does this sound? anything else to suggest?

agramfort avatar Mar 19 '20 20:03 agramfort

Hi, sorry I couldn't join your live conversation.

For me this is interesting, because it seems to show that for MNE plotting purposes the assumption of where the equator of the sphere goes DOES NOT MATTER.

It should matter - the channels at the equator should be plotted at the head outline (as long as the sphere center and radius are correct), the channels below equator would be drawn outside of the head circle (the same as in topomaps). Could you check how it works with #7455? Or maybe post a snippet so I could quickly test?

I actually have a preferrence to have the equator where the head circumference approximately is (so I'd say at the level of Fpz, Oz, T7 and T8 ...). It just seems graphically logical given how head circle is drawn (which seems not to work in your case, however). Head circle -> head circumference -> equator.

mmagnuski avatar Mar 20 '20 00:03 mmagnuski

Just to add some background. In FieldTrip we mainly make use of https://github.com/fieldtrip/fieldtrip/blob/master/private/elproj.m to compute projections of 3D electrode positions to a 2D plane. There is always distortion, as in cartography. Furthermore, we tend to keep the 2D layout (for plotting) separate from the 3D electrode positions, since both have different requirements. See http://www.fieldtriptoolbox.org/template/.

The one @sappelhoff made above is identical how I would do it in first instance. However, since you want to improve things, you may want to consider taking it outside the circle. Right now LPA and T9 appear to be above the ear, whereas in reality they are (vertical halfway) just in front of the ears. You could consider something like this http://www.fieldtriptoolbox.org/template/layout/#with-a-more-realistic-display-of-temporal-sensors-1. This is also something that EEGLAB uses, especially for the EGI geodesic sensor nets, which go very far down on the face.

robertoostenveld avatar Mar 20 '20 08:03 robertoostenveld

@mmagnuski the snippet was under the clickable "details" under the first plot. But see here:

import pandas as pd
import numpy as np
import mne

fname = 'XXX'  # set this to either Roberts or my data
df = pd.read_csv(fname, sep='\t')

# Turn data into digmontage
ch_pos = df.set_index('label').to_dict('index')
for key, val in ch_pos.items():
    ch_pos[key] = np.asarray(list(val.values()))

data = mne.utils.Bunch(
    nasion=ch_pos['Nz'],
    lpa=ch_pos['T9'],  # LPA in Robert's data
    rpa=ch_pos['T10'],  # RPA in Robert's data
    ch_pos=ch_pos,
    coord_frame='unknown',
    hsp=None, hpi=None,
)

montage = mne.channels.make_dig_montage(**data)

montage.plot()

I actually have a preferrence to have the equator where the head circumference approximately is (so I'd say at the level of Fpz, Oz, T7 and T8 ...)

~~Okay, but it's actually common practice to measure the head circumference from the nasion to the inion (passing close to T9 and T10) :thinking:~~

Edit: Sorry, I confused this (see Robert's answer below)

sappelhoff avatar Mar 20 '20 09:03 sappelhoff

The head circumference is not measured over Nasion, LPA, Inion and RPA (the palpable anatomical landmarks), but slightly higher. If you were to measure over the landmarks, the measuring tape would be over the eyes and over the ears. Although I personally would not measure precisely where to put the tape to determine the head circumference, I would say that it is approximately 10% above each anatomical landmark, which means it goes over Fpz, T7, Oz and T8. I.e. in https://www.sciencedirect.com/science/article/pii/S1388245700005277#FIG1 https://www.sciencedirect.com/science/article/pii/S1388245700005277#FIG1 it is the innermost circle.

Have a look at this screen capture https://youtu.be/ha-tY69k2ZI https://youtu.be/ha-tY69k2ZI.

On 20 Mar 2020, at 10:19, Stefan Appelhoff [email protected] wrote:

@mmagnuski https://github.com/mmagnuski the snippet was under the clickable "details" under the first plot. But see here:

Robert data (Fpz, Oz, T7, T8 equator) https://robertoostenveld.nl/electrodes/plotting_1005.txt note: you need to add labels to the data first row: label x y z Stefan data (Nz, Iz, T9, T10 equator) https://raw.githubusercontent.com/sappelhoff/eeg_positions/master/data/standard_1005.tsv import pandas as pd import numpy as np import mne

fname = 'XXX' # set this to either Roberts or my data df = pd.read_csv(fname, sep='\t')

Turn data into digmontage

ch_pos = df.set_index('label').to_dict('index') for key, val in ch_pos.items(): ch_pos[key] = np.asarray(list(val.values()))

data = mne.utils.Bunch( nasion=ch_pos['Nz'], # Fpz in Robert's data lpa=ch_pos['T9'], # LPA in Robert's data rpa=ch_pos['T10'], # RPA in Robert's data ch_pos=ch_pos, coord_frame='unknown', hsp=None, hpi=None, )

montage = mne.channels.make_dig_montage(**data)

montage.plot() I actually have a preferrence to have the equator where the head circumference approximately is (so I'd say at the level of Fpz, Oz, T7 and T8 ...)

Okay, but it's actually common practice to measure the head circumference from the nasion to the inion 🤔

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mne-tools/mne-python/issues/7472#issuecomment-601602507, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAG3PY4226ZRV2SWPEERPK3RIMYJZANCNFSM4LOOAYBA.

robertoostenveld avatar Mar 20 '20 09:03 robertoostenveld

People will go crazy if we show electrodes outside the head radius. Maybe we need to show more circles like in your figure?

cbrnr avatar Mar 20 '20 09:03 cbrnr

OK, back to my IC topomaps. Here's how they looked with standard_1020:

ica_components

And here's how they look now with @sappelhoff's 1005 montage:

Screen Shot 2020-03-20 at 11 21 36

The frontmost channel is Fz, whereas the backmost channel is POz. Which of these visualizations do you prefer? Which is more accurate?

cbrnr avatar Mar 20 '20 10:03 cbrnr

Thanks for the tips @robertoostenveld !

@cbrnr

People will go crazy if we show electrodes outside the head radius. Maybe we need to show more circles like in your figure?

But we do show electrodes outside the head radius in topomaps now (as EEGLAB also does) and I didn't notice people going crazy in these situations. :) (plotting montage and plotting topomaps has the same underlying mechanism. As @robertoostenveld mentions - plotting outside the head circle gives a more realistic picture of where the channels are with respect to head circumference, ears etc.)

@cbrnr I think it might be easier to judge using all montage channels and with the sphere radius fix in place (#7455).

@sappelhoff Thanks for the code, I'll try it out!

mmagnuski avatar Mar 20 '20 11:03 mmagnuski