mne-tools / mne-python

MNE: Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python
https://mne.tools
BSD 3-Clause "New" or "Revised" License
2.7k stars 1.31k forks source link

Error Electrode positions must be Unique #2653

Closed ImmanuelSamuel closed 8 years ago

ImmanuelSamuel commented 8 years ago
montage = mne.channels.read_montage('standard_1020', ch_names=None, unit='mm', transform=False)
chanNames= montage.ch_names

info = mne.create_info(chanNames, 200, ch_types='eeg', montage=montage)

layout = mne.channels.make_eeg_layout(info)
ImmanuelSamuel commented 8 years ago

I checked for duplicates. Seems there are none

jasmainak commented 8 years ago

you should investigate more carefully:

In [60]: montage.pos[90]
Out[60]: array([-0.0724343, -0.0734527, -0.002487 ])

In [61]: montage.pos[62]
Out[61]: array([-0.0724343, -0.0734527, -0.002487 ])

I see four offending channel pairs

ImmanuelSamuel commented 8 years ago

Great! You found it. I thought I was doing something wrong.

ImmanuelSamuel commented 8 years ago

Is this supposed to happen?

The four channels with same locations are: T7 T3 T8 T4 P7 T5 P8 T6 for i in range(97): for j in range(97): if i < j: if (montage.pos[i] == montage.pos[j]).all(): print(montage.ch_names[i], montage.ch_names[j])

Also after selecting a subset of montage for creating 'info' info = mne.create_info(chanNames, 200, ch_types='eeg', montage=montage)

where

 'Fpz',
 'Fp2',
 'Nz',
 'AF9',
 'AF7',
 'AF3',
 'AFz',
 'AF4',
 'AF8',
 'AF10',
 'F9',
 'F7',
 'F5',
 'F3',
 'F1',
 'Fz',
 'F2',
 'F4',
 'F6',
 'F8',
 'F10',
 'FT9',
 'FT7',
 'FC5',
 'FC3',
 'FC1',
 'FCz',
 'FC2',
 'FC4',
 'FC6',
 'FT8',
 'FT10',
 'T9',
 'T7',
 'C5',
 'C3',
 'C1',
 'Cz',
 'C2',
 'C4',
 'C6',
 'T8',
 'T10',
 'TP9',
 'TP7',
 'CP5',
 'CP3',
 'CP1',
 'CPz',
 'CP2',
 'CP4',
 'CP6',
 'TP8',
 'TP10',
 'P9',
 'P7',
 'P5',
 'P3',
 'P1',
 'Pz',
 'P2',
 'P4',
 'P6',
 'P8',
 'P10',
 'PO9',
 'PO7',
 'PO3',
 'POz',
 'PO4',
 'PO8',
 'PO10',
 'O1',
 'Oz',
 'O2',
 'OI1h',
 'OI2h',
 'I1h',
 'I2h',
 'OIz']

The following are the same now OI1h OI2h OI1h I1h OI1h I2h OI1h OIz OI2h I1h OI2h I2h OI2h OIz I1h I2h I1h OIz I2h OIz

for i in range(81): for j in range(81): if i < j: if (info['chs'][i]['loc'] == info['chs'][j]['loc']).all(): print(info['chs'][i]['ch_name'],info['chs'][j]['ch_name'])

agramfort commented 8 years ago

hum. We use the same file as everyone else.

https://www.google.fr/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=standard_1020.elc

for example if you look at:

https://github.com/sccn/BCILAB/blob/master/resources/standard_BEM/elec/standard_1020.elc

you'll see that there is 2 lines then are equal to "-72.4343 -73.4527 -2.4870"

I have no idea why it is like this...

ImmanuelSamuel commented 8 years ago

Yeah I checked too. Seems like its the same everywhere. Interestingly the 10-20 images online also seem to be inconsistent with each other. For now I have an sfp file for standard 10-20 81 channels that seems to work. If anyone has problems with this I can send it to them.

jasmainak commented 8 years ago

Maybe @mbillingr might have some insight

mbillingr commented 8 years ago

Hi, There are a few EEG locations that have different names in older/newer literature. To be more precise:

The original 10-20 system included only 19 electrodes (see panel B of the figure). Later on, extensions were proposed so that now you can place over 70 electrodes in standard positions (see panel C of the figure). This extension also renamed four electrodes (marked in black in the figure); the original names were: T3, T5, T4, and T6 for T7, P7, T8, and P8, respectively.

from http://www.bci2000.org/wiki/index.php/User_Tutorial:EEG_Measurement_Setup#The_10-20_International_System

I guess the file includes both names for these electrodes so that it works regardless of the name one is using.

Btw, the file seems to contain 10-10 locations (there exist only 19 10-20 locations), so the name is a bit misleading.

jasmainak commented 8 years ago

Great! Thanks @mbillingr . Can we close the issue now @ImmanuelSamuel @agramfort ?

jona-sassenhagen commented 8 years ago

I think it would be convenient if the error message could also tell you which channels are duplicate. Not very important though of course.

ImmanuelSamuel commented 8 years ago

@jasmainak Ok I know more about the standard 10-20 history now. You can close this if you want. The second part of my questions is still unresolved. I don't have an issue with it currently because I am using my own locations. But I think this being very fundamental in EEG others might want this resolved. When I choose certain channels, the duplicates are occurring at other channels. Like O1 and Oz. The code to replicate error should be above (5th comment).

jasmainak commented 8 years ago

@ImmanuelSamuel can you put a full block of code from start to end? the 5th comment looks a bit confusing to me. When I try it, I don't see any duplicate channels

ImmanuelSamuel commented 8 years ago
chanNames = ['Fp1',
 'Fpz',
 'Fp2',
 'Nz',
 'AF9',
 'AF7',
 'AF3',
 'AFz',
 'AF4',
 'AF8',
 'AF10',
 'F9',
 'F7',
 'F5',
 'F3',
 'F1',
 'Fz',
 'F2',
 'F4',
 'F6',
 'F8',
 'F10',
 'FT9',
 'FT7',
 'FC5',
 'FC3',
 'FC1',
 'FCz',
 'FC2',
 'FC4',
 'FC6',
 'FT8',
 'FT10',
 'T9',
 'T7',
 'C5',
 'C3',
 'C1',
 'Cz',
 'C2',
 'C4',
 'C6',
 'T8',
 'T10',
 'TP9',
 'TP7',
 'CP5',
 'CP3',
 'CP1',
 'CPz',
 'CP2',
 'CP4',
 'CP6',
 'TP8',
 'TP10',
 'P9',
 'P7',
 'P5',
 'P3',
 'P1',
 'Pz',
 'P2',
 'P4',
 'P6',
 'P8',
 'P10',
 'PO9',
 'PO7',
 'PO3',
 'POz',
 'PO4',
 'PO8',
 'PO10',
 'O1',
 'Oz',
 'O2',
 'OI1h',
 'OI2h',
 'I1h',
 'I2h',
 'OIz']
montage = mne.channels.read_montage('standard_1020')
info = mne.create_info(chanNames, 200, ch_types='eeg', montage=montage)
layout = mne.channels.make_eeg_layout(info)```
agramfort commented 8 years ago

I can replicate but I don't know what's the good fix.

@mbillingr @alexandrebarachant any idea?

mbillingr commented 8 years ago

I can't try this piece of code at the moment because I don't have MNE here at work.

What are the positions of the offending duplicates? For orientation - what are the positions of some promiment locations (Fpz, Cz, Oz, T8, T7)? Maybe locations are assigned wrongly to names.

What happens inside the create_info function? Are the locations transformed somehow?

agramfort commented 8 years ago

@wmvanvliet any thought on this?

wmvanvliet commented 8 years ago

I guess I can modify the error message to list all the duplicate channels. What is the remaining problem?

mbillingr commented 8 years ago

When I run the code above, this is what I get in info['chs'] (condensed):

{'ch_name': 'O2',
 'loc': array([  29.843, -112.156,    8.8  ,    0.   ,    0.   ,    0.   ,    0.   ,    0.   ,    0.   ,    0.   ,    0.   ,    0.   ]),
 ....
{'ch_name': 'OI1h',
 'loc': array([ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.], dtype=float32),
 ...}
{'ch_name': 'OI2h',
 'loc': array([ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.], dtype=float32),
 ...}
{'ch_name': 'I1h',
 'loc': array([ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.], dtype=float32),
 ....
{'ch_name': 'I2h',
 'loc': array([ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.], dtype=float32),
 ...
{'ch_name': 'OIz',
 'loc': array([ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  1.], dtype=float32),
 ...}]

The locations of channel O2 and others (not shown) seem fine, but there is something wrong with the channels ending on 'h' or 'z'.

wmvanvliet commented 8 years ago

that's because locations for those positions are not specified in the standard_1020 file. Try the standard_1005 file instead.

mbillingr commented 8 years ago

Okay. So undefined locations are set to some sentinel value, and make_eeg_layout thinks they are duplicate - right?

The actual problem seems to be the error message. It points the user to look for duplicate channels when really they should use another layout file.

agramfort commented 8 years ago

can you make a PR to limit the probability of seeing this issue coming back? doc improvements and/or warnings.

thx

wmvanvliet commented 8 years ago

See #2707