mne-python: BUG:mne.create_info function mismatch channel names with DigMontage

Describe the bug

In 0.19.2, mne.channels.read_montage has been replaced by mne.channels.make_standard_montage, which returns a DigMontage object.

However, mne.create_info with DigMontage can not match channel names in a case insensitive manner.

Steps to reproduce

import mne

montage = mne.channels.make_standard_montage('standard_1005')
info = mne.create_info(
    ['FPz'], 100, 
    ch_types=['eeg'], montage=montage)

Actual results

~/miniconda3/envs/ml/lib/python3.7/site-packages/mne/utils/_logging.py in wrapper(*args, **kwargs)
     88             with use_log_level(verbose_level):
     89                 return function(*args, **kwargs)
---> 90         return function(*args, **kwargs)
     91     return FunctionMaker.create(
     92         function, 'return decfunc(%(signature)s)',

~/miniconda3/envs/ml/lib/python3.7/site-packages/mne/io/meas_info.py in create_info(ch_names, sfreq, ch_types, montage, verbose)
   1798         for montage_ in montage:
   1799             if isinstance(montage_, (str, Montage, DigMontage)):
-> 1800                 _set_montage(info, montage_)
   1801             else:
   1802                 raise TypeError('Montage must be an instance of Montage, '

~/miniconda3/envs/ml/lib/python3.7/site-packages/mne/channels/montage.py in _set_montage(info, montage, update_ch_names, set_dig, raise_if_subset)
   1564             info_names=set([info['ch_names'][ii] for ii in _pick_chs(info)]),
   1565             montage_names=set(ch_pos),
-> 1566             raise_if_subset=_raise,  # XXX: deprecated param to remove in 0.20
   1567         )
   1568 

~/miniconda3/envs/ml/lib/python3.7/site-packages/mne/channels/montage.py in _check_ch_names_are_compatible(info_names, montage_names, raise_if_subset)
     91                 '\nYou can use `raise_if_subset=False` in `set_montage` to'
     92                 ' avoid this ValueError and get a DeprecationWarning instead.'
---> 93             ).format(n_ch=len(not_in_montage), ch_names=not_in_montage))
     94         else:
     95             # XXX: deprecated. to remove in 0.20 (raise_if_subset, too)

ValueError: DigMontage is a only a subset of info. There are 1 channel positions not present it the DigMontage. The required channels are: {'FPz'}.
You can use `raise_if_subset=False` in `set_montage` to avoid this ValueError and get a DeprecationWarning instead.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 31 (15 by maintainers)

Most upvoted comments

Hello there, I’m trying to run set_montage in the BCI200 raw data but I’m still getting errors related to channels name. Raw data channels are: ch_names: Fc5., Fc3., Fc1., Fcz., Fc2., Fc4., Fc6., C5…, C3…, C1…, …

Thus, when I ran

montage = mne.channels.make_standard_montage(‘biosemi64’) print(montage)

<DigMontage | 0 extras (headshape), 0 HPIs, 3 fiducials, 64 channels> <bound method set_channel_types of <RawEDF | S003R03.edf, 64 x 20000 (125.0 s), ~9.8 MB, data loaded>>

raw.set_montage(montage)

I get the following error

ValueError Traceback (most recent call last) <ipython-input-21-fe790fd59c77> in <module>() ----> 1 raw.set_montage(montage)

<decorator-gen-143> in set_montage(self, montage, match_case, match_alias, on_missing, verbose)

2 frames /usr/local/lib/python3.7/dist-packages/mne/utils/check.py in _on_missing(on_missing, msg, name, error_klass) 870 on_missing = ‘warn’ if on_missing == ‘warning’ else on_missing 871 if on_missing == ‘raise’: –> 872 raise error_klass(msg) 873 elif on_missing == ‘warn’: 874 warn(msg)

ValueError: DigMontage is only a subset of info. There are 64 channel positions not present in the DigMontage. The required channels are:

[‘Fc5.’, ‘Fc3.’, ‘Fc1.’, ‘Fcz.’, ‘Fc2.’, ‘Fc4.’, ‘Fc6.’, ‘C5…’, ‘C3…’, ‘C1…’, ‘Cz…’, ‘C2…’, ‘C4…’, ‘C6…’, ‘Cp5.’, ‘Cp3.’, ‘Cp1.’, ‘Cpz.’, ‘Cp2.’, ‘Cp4.’, ‘Cp6.’, ‘Fp1.’, ‘Fpz.’, ‘Fp2.’, ‘Af7.’, ‘Af3.’, ‘Afz.’, ‘Af4.’, ‘Af8.’, ‘F7…’, ‘F5…’, ‘F3…’, ‘F1…’, ‘Fz…’, ‘F2…’, ‘F4…’, ‘F6…’, ‘F8…’, ‘Ft7.’, ‘Ft8.’, ‘T7…’, ‘T8…’, ‘T9…’, ‘T10.’, ‘Tp7.’, ‘Tp8.’, ‘P7…’, ‘P5…’, ‘P3…’, ‘P1…’, ‘Pz…’, ‘P2…’, ‘P4…’, ‘P6…’, ‘P8…’, ‘Po7.’, ‘Po3.’, ‘Poz.’, ‘Po4.’, ‘Po8.’, ‘O1…’, ‘Oz…’, ‘O2…’, ‘Iz…’].

Consider using inst.set_channel_types if these are not EEG channels, or use the on_missing parameter if the channel positions are allowed to be unknown in your analyses.

However, they are EEG channels and positions must be known, thus:

Datasamples I’m using are officially available at https://physionet.org/content/eegmmidb/1.0.0/

Must I rename channels as per indicated in this thread?

@TanTingyi larsoner has already added match_case keyword to _set_montage, which is called by set_montage and create_info. Although we can not directly use match_case in create_info, now we can create raw object as follows:

import numpy as np
import mne

data = np.random.rand(1, 200)
info = mne.create_info(['FPz'], 100, ch_types=['eeg'])

raw = mne.io.RawArray(data, info)

montage =  mne.channels.make_standard_montage('standard_1005')
raw.set_montage(montage, match_case=False)

@larsoner Would you mind adding match_case option to create_info function in your PR?