Skip to content

Commit

Permalink
Merge pull request #1 from dengemann/mne_rename_channels
Browse files Browse the repository at this point in the history
cleanup + fix
  • Loading branch information
dgwakeman committed Feb 13, 2014
2 parents fad6de4 + d3cd0bc commit 826dc9e
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 63 deletions.
86 changes: 40 additions & 46 deletions mne/fiff/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def drop_channels(self, ch_names):
self.data = self.data[idx, :]


def rename_channels(info, alias):
def rename_channels(info, mapping):
"""Rename channels and optionally change the sensor type.
Note: This only changes between the following sensor types: eeg, eog,
Expand All @@ -197,60 +197,54 @@ def rename_channels(info, alias):
----------
info : dict
Measurement info.
alias : dict
mapping : dict
a dictionary mapping the old channel to a new channel name {'EEG061' :
'EEG161'}. If changing the sensor type, make the new name a tuple with
the name (str) and the new channel type (str)
{'EEG061',('EOG061','eog')}.
"""
human2fiff = {'eeg': FIFF.FIFFV_EEG_CH,
'eog': FIFF.FIFFV_EOG_CH,
human2fiff = {'eog': FIFF.FIFFV_EOG_CH,
'emg': FIFF.FIFFV_EMG_CH,
'ecg': FIFF.FIFFV_ECG_CH,
'misc': FIFF.FIFFV_MISC_CH}
bads = info['bads']
chs = info['chs']
info['ch_names'] = [ch['ch_name'] for ch in chs] # reset for safety

bads, chs = info['bads'], info['chs']
ch_names = info['ch_names']
for ch_name in alias.keys():
new_names, new_kinds, new_bads = list(), list(), list()

# first check and assemble clean mappings of index and name
for ch_name, new_name in mapping.items():
if ch_name not in ch_names:
raise RuntimeError("This channel name %s doesn't exist in info."
% ch_name)
else:
c_ind = ch_names.index(ch_name)
if type(alias[ch_name]) is str: # just name change
chs[c_ind]['ch_name'] = alias[ch_name]
if ch_name in bads: # check bads
bads[bads.index(ch_name)] = alias[ch_name]
elif type(alias[ch_name]) is tuple: # name and type change
fiff_accept = human2fiff.values()
fiff_accept.append(chs[c_ind]['kind'])
if (len(fiff_accept) > len(set(fiff_accept))):
if alias[ch_name][1] in human2fiff:
chs[c_ind]['ch_name'] = alias[ch_name][0]
if ch_name in bads: # check bads
bads[bads.index(ch_name)] = alias[ch_name][0]
chs[c_ind]['kind'] = human2fiff[alias[ch_name][1]]
if chs[c_ind]['kind'] is human2fiff['eeg']:
raise RuntimeError('This function cannot create '
'eeg channels!')
else:
raise RuntimeError('This function cannot change to '
'this channel type: %s.' %
alias[ch_name][1])
else:
raise RuntimeError('This function will not change from'
' this channel type. Please check'
' that this is the channel you mean.'
)
else:
raise RuntimeError('Your alias is not configured properly. '
'Please see the help: mne.rename_channels?')
raise ValueError("This channel name (%s) doesn't exist in info."
% ch_name)

c_ind = ch_names.index(ch_name)
if not isinstance(new_name, (string_types, tuple)):
raise ValueError('Your mapping is not configured properly. '
'Please see the help: mne.rename_channels?')

elif isinstance(new_name, tuple): # name and type change
new_name, new_type = new_name # unpack
if new_type not in human2fiff:
raise ValueError('This function cannot change to this '
'channel type: %s.' % new_type)
new_kinds.append((c_ind, human2fiff[new_type]))

if new_name in ch_names:
raise ValueError('The new name ({new}) already exists. Choose a '
'unique name'.format(new=new_name))

new_names.append((c_ind, new_name))
if ch_name in bads: # check bads
new_bads.append((bads.index(ch_name), new_name))

# Reset ch_names and Check that all the channel names are unique.
info['chs'] = chs
info['ch_names'] = [ch['ch_name'] for ch in chs]
if (len(info['ch_names']) > len(set(info['ch_names']))):
raise RuntimeError('You have created duplicate channel names. '
'Please check that your not renaming a channel to a'
' name that already exists in ch_names')
for key, collection in [('ch_name', new_names), ('kind', new_kinds)]:
for c_ind, new_name in collection:
chs[c_ind][key] = new_name
for c_ind, new_name in new_bads:
bads[c_ind] = new_name

# reference magic, please don't change (with the local binding
# it doesn't work)
info['ch_names'] = [c['ch_name'] for c in chs]
34 changes: 17 additions & 17 deletions mne/fiff/tests/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,29 @@ def test_rename_channels():
info = fiff.read_info(raw_fname)
# Error Tests
# Test channel name exists in ch_names
alias = {'EEG 160': 'EEG060'}
assert_raises(RuntimeError, rename_channels, info, alias)
mapping = {'EEG 160': 'EEG060'}
assert_raises(ValueError, rename_channels, info, mapping)
# Test change to EEG channel
alias = {'EOG 061': ('EEG 061', 'eeg')}
assert_raises(RuntimeError, rename_channels, info, alias)
mapping = {'EOG 061': ('EEG 061', 'eeg')}
assert_raises(ValueError, rename_channels, info, mapping)
# Test change to illegal channel type
alias = {'EOG 061': ('MEG 061', 'meg')}
assert_raises(RuntimeError, rename_channels, info, alias)
mapping = {'EOG 061': ('MEG 061', 'meg')}
assert_raises(ValueError, rename_channels, info, mapping)
# Test channel type which you are changing from e.g. MEG
alias = {'MEG 2641': ('MEG2641', 'eeg')}
assert_raises(RuntimeError, rename_channels, info, alias)
# Test improper alias configuration
alias = {'MEG 2641': 1.0}
assert_raises(RuntimeError, rename_channels, info, alias)
mapping = {'MEG 2641': ('MEG2641', 'eeg')}
assert_raises(ValueError, rename_channels, info, mapping)
# Test improper mapping configuration
mapping = {'MEG 2641': 1.0}
assert_raises(ValueError, rename_channels, info, mapping)
# Test duplicate named channels
alias = {'EEG 060': 'EOG 061'}
assert_raises(RuntimeError, rename_channels, info, alias)
mapping = {'EEG 060': 'EOG 061'}
assert_raises(ValueError, rename_channels, info, mapping)
# Test successful changes
# Test ch_name and ch_names are changed
info2 = deepcopy(info) # for consistency at the start of each test
info2['bads'] = ['EEG 060', 'EOG 061']
alias = {'EEG 060': 'EEG060', 'EOG 061': 'EOG061'}
rename_channels(info2, alias)
mapping = {'EEG 060': 'EEG060', 'EOG 061': 'EOG061'}
rename_channels(info2, mapping)
assert_true(info2['chs'][374]['ch_name'] == 'EEG060')
assert_true(info2['ch_names'][374] == 'EEG060')
assert_true('EEG060' in info2['bads'])
Expand All @@ -54,8 +54,8 @@ def test_rename_channels():
# Test type change
info2 = deepcopy(info)
info2['bads'] = ['EEG 060', 'EEG 059']
alias = {'EEG 060': ('EOG 060', 'eog'), 'EEG 059': ('EOG 059', 'eog')}
rename_channels(info2, alias)
mapping = {'EEG 060': ('EOG 060', 'eog'), 'EEG 059': ('EOG 059', 'eog')}
rename_channels(info2, mapping)
assert_true(info2['chs'][374]['ch_name'] == 'EOG 060')
assert_true(info2['ch_names'][374] == 'EOG 060')
assert_true('EOG 060' in info2['bads'])
Expand Down

0 comments on commit 826dc9e

Please sign in to comment.