def _read_evoked(fname, sensor_mode, info): """ helper to read evokeds """ data = scio.loadmat(fname, squeeze_me=True)['data'] ch_names = [ch for ch in data['label'].tolist()] times = data['time'].tolist() sfreq = 1. / np.diff(times)[0] if info is None: info = create_info( ch_names, ch_types=[sensor_mode] * len(ch_names), sfreq=sfreq) else: info = _hcp_pick_info(info, ch_names) info['sfreq'] = sfreq orig_labels = list(data['grad'].tolist()['label'].tolist()) sel = [orig_labels.index(ch) for ch in ch_names] pos = data['grad'].tolist()['chanpos'].tolist()[sel] out = list() comment = ('_'.join(fname.split('/')[-1].split('_')[2:]) .replace('.mat', '') .replace('_eravg_', '_') .replace('[', '') .replace(']', '')) for key, kind in (('var', 'standard_error'), ('avg', 'average')): evoked = EvokedArray( data=data[key].tolist(), info=info, tmin=min(times), kind=kind, comment=comment) evoked._set_channel_positions(pos, ch_names) out.append(evoked) return out
def test_montage(): """Test making montages""" tempdir = _TempDir() # no pep8 input_str = [ 'FidNz 0.00000 10.56381 -2.05108\nFidT9 -7.82694 0.45386 -3.76056\n' 'very_very_very_long_name 7.82694 0.45386 -3.76056', '// MatLab Sphere coordinates [degrees] Cartesian coordinates\n' # noqa '// Label Theta Phi Radius X Y Z off sphere surface\n' # noqa 'E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011\n' # noqa 'E2 44.600 -0.880 1.000 0.7119 0.7021 -0.0154 0.00000000000000000\n' # noqa 'E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000', # noqa '# ASA electrode file\nReferenceLabel avg\nUnitPosition mm\n' 'NumberPositions= 68\nPositions\n-86.0761 -19.9897 -47.9860\n' '85.7939 -20.0093 -48.0310\n0.0083 86.8110 -39.9830\n' 'Labels\nLPA\nRPA\nNz\n', '# ASA electrode file\nReferenceLabel avg\nUnitPosition m\n' 'NumberPositions= 68\nPositions\n-.0860761 -.0199897 -.0479860\n' '.0857939 -.0200093 -.0480310\n.0000083 .00868110 -.0399830\n' 'Labels\nLPA\nRPA\nNz\n', 'Site Theta Phi\nFp1 -92 -72\nFp2 92 72\n' 'very_very_very_long_name -60 -51\n', '346\n' 'EEG\t F3\t -62.027\t -50.053\t 85\n' 'EEG\t Fz\t 45.608\t 90\t 85\n' 'EEG\t F4\t 62.01\t 50.103\t 85\n', 'eeg Fp1 -95.0 -31.0 -3.0\neeg AF7 -81 -59 -3\neeg AF3 -87 -41 28\n' ] kinds = ['test.sfp', 'test.csd', 'test_mm.elc', 'test_m.elc', 'test.txt', 'test.elp', 'test.hpts'] for kind, text in zip(kinds, input_str): fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(text) montage = read_montage(fname) if ".sfp" in kind or ".txt" in kind: assert_true('very_very_very_long_name' in montage.ch_names) assert_equal(len(montage.ch_names), 3) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (3, 3)) assert_equal(montage.kind, op.splitext(kind)[0]) if kind.endswith('csd'): dtype = [('label', 'S4'), ('theta', 'f8'), ('phi', 'f8'), ('radius', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('off_sph', 'f8')] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) pos2 = np.c_[table['x'], table['y'], table['z']] assert_array_almost_equal(pos2, montage.pos, 4) if kind.endswith('elc'): # Make sure points are reasonable distance from geometric centroid centroid = np.sum(montage.pos, axis=0) / montage.pos.shape[0] distance_from_centroid = np.apply_along_axis( np.linalg.norm, 1, montage.pos - centroid) assert_array_less(distance_from_centroid, 0.2) assert_array_less(0.01, distance_from_centroid) # test transform input_str = """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """ kind = 'test_fid.hpts' fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, 'test_fid.hpts'), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) idx = montage.ch_names.index('2') assert_array_equal(montage.pos[idx, [0, 2]], [0, 0]) idx = montage.ch_names.index('1') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) idx = montage.ch_names.index('3') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, 'test_fid.hpts') montage = read_montage(montage_fname, unit='mm') assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c['loc'][:3] for c in info['chs']]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info['ch_names']) info = create_info( montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) evoked = EvokedArray( data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) evoked.set_montage(montage) pos3 = np.array([c['loc'][:3] for c in evoked.info['chs']]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info['ch_names']) # Warning should be raised when some EEG are not specified in the montage with warnings.catch_warnings(record=True) as w: info = create_info(montage.ch_names + ['foo', 'bar'], 1e3, ['eeg'] * (len(montage.ch_names) + 2)) _set_montage(info, montage) assert_true(len(w) == 1)
continue raw_fname = paths('sss', subject=meg_subject, block=1) inv_fname = paths('inv', subject=meg_subject) cov = load('cov', subject=meg_subject) fwd = load('fwd', subject=meg_subject) info = read_info(raw_fname) inv = make_inverse_operator(info, fwd, cov, loose=0.2, depth=0.8) save(inv, 'inv', subject=meg_subject, overwrite=True) # Morph anatomy into common model --------------------------------------------- from mne import EvokedArray from mne import compute_morph_matrix from mne.minimum_norm import apply_inverse if True: for meg_subject, subject in zip(range(1, 21), subjects_id): if subject in bad_mri: continue raw_fname = paths('sss', subject=meg_subject, block=1) info = read_info(raw_fname) # precompute morphing matrix for faster processing inv = load('inv', subject=meg_subject) evoked = EvokedArray(np.zeros((len(info['chs']), 2)), info, 0) evoked.pick_types(eeg=False, meg=True) stc = apply_inverse(evoked, inv, lambda2=1.0 / (2 ** 3.0), method='dSPM', pick_ori=None) morph = compute_morph_matrix(subject, 'fsaverage', stc.vertices, vertices_to=[np.arange(10242)] * 2, subjects_dir=subjects_dir) save(morph, 'morph', subject=meg_subject)
def test_montage(): """Test making montages.""" tempdir = _TempDir() inputs = dict( sfp='FidNz 0 9.071585155 -2.359754454\n' 'FidT9 -6.711765 0.040402876 -3.251600355\n' 'very_very_very_long_name -5.831241498 -4.494821698 4.955347697\n' 'Cz 0 0 8.899186843', csd='// MatLab Sphere coordinates [degrees] Cartesian coordinates\n' # noqa: E501 '// Label Theta Phi Radius X Y Z off sphere surface\n' # noqa: E501 'E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011\n' # noqa: E501 'E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000\n' # noqa: E501 'E31 90.000 -11.000 1.000 0.0000 0.9816 -0.1908 0.00000000000000000\n' # noqa: E501 'E61 158.000 -17.200 1.000 -0.8857 0.3579 -0.2957 -0.00000000000000022', # noqa: E501 mm_elc='# ASA electrode file\nReferenceLabel avg\nUnitPosition mm\n' # noqa:E501 'NumberPositions= 68\n' 'Positions\n' '-86.0761 -19.9897 -47.9860\n' '85.7939 -20.0093 -48.0310\n' '0.0083 86.8110 -39.9830\n' '-86.0761 -24.9897 -67.9860\n' 'Labels\nLPA\nRPA\nNz\nDummy\n', m_elc='# ASA electrode file\nReferenceLabel avg\nUnitPosition m\n' 'NumberPositions= 68\nPositions\n-.0860761 -.0199897 -.0479860\n' # noqa:E501 '.0857939 -.0200093 -.0480310\n.0000083 .00868110 -.0399830\n' '.08 -.02 -.04\n' 'Labels\nLPA\nRPA\nNz\nDummy\n', txt='Site Theta Phi\n' 'Fp1 -92 -72\n' 'Fp2 92 72\n' 'very_very_very_long_name -92 72\n' 'O2 92 -90\n', elp='346\n' 'EEG\t F3\t -62.027\t -50.053\t 85\n' 'EEG\t Fz\t 45.608\t 90\t 85\n' 'EEG\t F4\t 62.01\t 50.103\t 85\n' 'EEG\t FCz\t 68.01\t 58.103\t 85\n', hpts='eeg Fp1 -95.0 -3. -3.\n' 'eeg AF7 -1 -1 -3\n' 'eeg A3 -2 -2 2\n' 'eeg A 0 0 0', ) # Get actual positions and save them for checking # csd comes from the string above, all others come from commit 2fa35d4 poss = dict( sfp=[[0.0, 9.07159, -2.35975], [-6.71176, 0.0404, -3.2516], [-5.83124, -4.49482, 4.95535], [0.0, 0.0, 8.89919]], mm_elc=[[-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.08681, -0.03998], [-0.08608, -0.02499, -0.06799]], m_elc=[[-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.00868, -0.03998], [0.08, -0.02, -0.04]], txt=[[-26.25044, 80.79056, -2.96646], [26.25044, 80.79056, -2.96646], [-26.25044, -80.79056, -2.96646], [0.0, -84.94822, -2.96646]], elp=[[-48.20043, 57.55106, 39.86971], [0.0, 60.73848, 59.4629], [48.1426, 57.58403, 39.89198], [41.64599, 66.91489, 31.8278]], hpts=[[-95, -3, -3], [-1, -1., -3.], [-2, -2, 2.], [0, 0, 0]], ) for key, text in inputs.items(): kind = key.split('_')[-1] fname = op.join(tempdir, 'test.' + kind) with open(fname, 'w') as fid: fid.write(text) montage = read_montage(fname) if kind in ('sfp', 'txt'): assert_true('very_very_very_long_name' in montage.ch_names) assert_equal(len(montage.ch_names), 4) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (4, 3)) assert_equal(montage.kind, 'test') if kind == 'csd': dtype = [('label', 'S4'), ('theta', 'f8'), ('phi', 'f8'), ('radius', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('off_sph', 'f8')] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) poss['csd'] = np.c_[table['x'], table['y'], table['z']] if kind == 'elc': # Make sure points are reasonable distance from geometric centroid centroid = np.sum(montage.pos, axis=0) / montage.pos.shape[0] distance_from_centroid = np.apply_along_axis( np.linalg.norm, 1, montage.pos - centroid) assert_array_less(distance_from_centroid, 0.2) assert_array_less(0.01, distance_from_centroid) assert_array_almost_equal(poss[key], montage.pos, 4, err_msg=key) # Test reading in different letter case. ch_names = ["F3", "FZ", "F4", "FC3", "FCz", "FC4", "C3", "CZ", "C4", "CP3", "CPZ", "CP4", "P3", "PZ", "P4", "O1", "OZ", "O2"] montage = read_montage('standard_1020', ch_names=ch_names) assert_array_equal(ch_names, montage.ch_names) # test transform input_strs = [""" eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """, """ Fp1 -95.0 -31.0 -3.0 AF7 -81 -59 -3 AF3 -87 -41 28 nasion -91 0 -42 lpa 0 -91 -42 rpa 0 91 -42 """] all_fiducials = [['2', '1', '3'], ['nasion', 'lpa', 'rpa']] kinds = ['test_fid.hpts', 'test_fid.sfp'] for kind, fiducials, input_str in zip(kinds, all_fiducials, input_strs): fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, kind), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) idx = montage.ch_names.index(fiducials[0]) assert_array_equal(montage.pos[idx, [0, 2]], [0, 0]) idx = montage.ch_names.index(fiducials[1]) assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) idx = montage.ch_names.index(fiducials[2]) assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, kind) montage = read_montage(montage_fname, unit='mm') assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c['loc'][:3] for c in info['chs']]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info['ch_names']) info = create_info( montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) evoked = EvokedArray( data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) evoked.set_montage(montage) pos3 = np.array([c['loc'][:3] for c in evoked.info['chs']]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info['ch_names']) # Warning should be raised when some EEG are not specified in montage with warnings.catch_warnings(record=True) as w: info = create_info(montage.ch_names + ['foo', 'bar'], 1e3, ['eeg'] * (len(montage.ch_names) + 2)) _set_montage(info, montage) assert_true(len(w) == 1) # Channel names can be treated case insensitive with warnings.catch_warnings(record=True) as w: info = create_info(['FP1', 'af7', 'AF3'], 1e3, ['eeg'] * 3) _set_montage(info, montage) assert_true(len(w) == 0) # Unless there is a collision in names with warnings.catch_warnings(record=True) as w: info = create_info(['FP1', 'Fp1', 'AF3'], 1e3, ['eeg'] * 3) _set_montage(info, montage) assert_true(len(w) == 1) with warnings.catch_warnings(record=True) as w: montage.ch_names = ['FP1', 'Fp1', 'AF3'] info = create_info(['fp1', 'AF3'], 1e3, ['eeg', 'eeg']) _set_montage(info, montage) assert_true(len(w) == 1)
aspect='auto', extent=[epochs.times[0], epochs.times[-1], 1, len(X_transform)], cmap='RdBu_r') plt.xlabel('Time (ms)') plt.ylabel('Trials (reordered by condition)') # Plot average response plt.figure() plt.title('Average EMS signal') mappings = [(key, value) for key, value in event_ids.items()] for key, value in mappings: ems_ave = X_transform[y == value] plt.plot(epochs.times, ems_ave.mean(0), label=key) plt.xlabel('Time (ms)') plt.ylabel('a.u.') plt.legend(loc='best') plt.show() # Visualize spatial filters across time evoked = EvokedArray(filters, epochs.info, tmin=epochs.tmin) evoked.plot_topomap() ############################################################################# # Note that a similar transformation can be applied with `compute_ems` # However, this function replicates Schurger et al's original paper, and thus # applies the normalization outside a leave-one-out cross-validation, which we # recommend not to do. epochs.equalize_event_counts(event_ids) X_transform, filters, classes = compute_ems(epochs)
plt.title('single trial surrogates') plt.imshow(X_transform[y.argsort()], origin='lower', aspect='auto', extent=[epochs.times[0], epochs.times[-1], 1, len(X_transform)], cmap='RdBu_r') plt.xlabel('Time (ms)') plt.ylabel('Trials (reordered by condition)') # Plot average response plt.figure() plt.title('Average EMS signal') mappings = [(key, value) for key, value in event_ids.items()] for key, value in mappings: ems_ave = X_transform[y == value] plt.plot(epochs.times, ems_ave.mean(0), label=key) plt.xlabel('Time (ms)') plt.ylabel('a.u.') plt.legend(loc='best') plt.show() # Visualize spatial filters across time evoked = EvokedArray(filters, epochs.info, tmin=epochs.tmin) evoked.plot_topomap(time_unit='s') ############################################################################# # Note that a similar transformation can be applied with `compute_ems` # However, this function replicates Schurger et al's original paper, and thus # applies the normalization outside a leave-one-out cross-validation, which we # recommend not to do. epochs.equalize_event_counts(event_ids) X_transform, filters, classes = compute_ems(epochs)
# fit the classifier on MEG data X = scaler.fit_transform(meg_data) model.fit(X, labels) # Extract and plot spatial filters and spatial patterns for name, coef in (('patterns', model.patterns_), ('filters', model.filters_)): # We fitted the linear model onto Z-scored data. To make the filters # interpretable, we must reverse this normalization step coef = scaler.inverse_transform([coef])[0] # The data was vectorized to fit a single model across all time points and # all channels. We thus reshape it: coef = coef.reshape(len(meg_epochs.ch_names), -1) # Plot evoked = EvokedArray(coef, meg_epochs.info, tmin=epochs.tmin) evoked.plot_topomap(title='MEG %s' % name) ############################################################################### # Let's do the same on EEG data using a scikit-learn pipeline X = epochs.pick_types(meg=False, eeg=True) y = epochs.events[:, 2] # Define a unique pipeline to sequentially: clf = make_pipeline( Vectorizer(), # 1) vectorize across time and channels StandardScaler(), # 2) normalize features across trials LinearModel(LogisticRegression())) # 3) fits a logistic regression clf.fit(X, y)
def test_montage(): """Test making montages.""" tempdir = _TempDir() inputs = dict( sfp="FidNz 0 9.071585155 -2.359754454\n" "FidT9 -6.711765 0.040402876 -3.251600355\n" "very_very_very_long_name -5.831241498 -4.494821698 4.955347697\n" "Cz 0 0 8.899186843", csd="// MatLab Sphere coordinates [degrees] Cartesian coordinates\n" # noqa: E501 "// Label Theta Phi Radius X Y Z off sphere surface\n" # noqa: E501 "E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011\n" # noqa: E501 "E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000\n" # noqa: E501 "E31 90.000 -11.000 1.000 0.0000 0.9816 -0.1908 0.00000000000000000\n" # noqa: E501 "E61 158.000 -17.200 1.000 -0.8857 0.3579 -0.2957 -0.00000000000000022", # noqa: E501 mm_elc="# ASA electrode file\nReferenceLabel avg\nUnitPosition mm\n" # noqa:E501 "NumberPositions= 68\n" "Positions\n" "-86.0761 -19.9897 -47.9860\n" "85.7939 -20.0093 -48.0310\n" "0.0083 86.8110 -39.9830\n" "-86.0761 -24.9897 -67.9860\n" "Labels\nLPA\nRPA\nNz\nDummy\n", m_elc="# ASA electrode file\nReferenceLabel avg\nUnitPosition m\n" "NumberPositions= 68\nPositions\n-.0860761 -.0199897 -.0479860\n" # noqa:E501 ".0857939 -.0200093 -.0480310\n.0000083 .00868110 -.0399830\n" ".08 -.02 -.04\n" "Labels\nLPA\nRPA\nNz\nDummy\n", txt="Site Theta Phi\n" "Fp1 -92 -72\n" "Fp2 92 72\n" "very_very_very_long_name -92 72\n" "O2 92 -90\n", elp="346\n" "EEG\t F3\t -62.027\t -50.053\t 85\n" "EEG\t Fz\t 45.608\t 90\t 85\n" "EEG\t F4\t 62.01\t 50.103\t 85\n" "EEG\t FCz\t 68.01\t 58.103\t 85\n", hpts="eeg Fp1 -95.0 -3. -3.\n" "eeg AF7 -1 -1 -3\n" "eeg A3 -2 -2 2\n" "eeg A 0 0 0", ) # Get actual positions and save them for checking # csd comes from the string above, all others come from commit 2fa35d4 poss = dict( sfp=[[0.0, 9.07159, -2.35975], [-6.71176, 0.0404, -3.2516], [-5.83124, -4.49482, 4.95535], [0.0, 0.0, 8.89919]], mm_elc=[ [-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.08681, -0.03998], [-0.08608, -0.02499, -0.06799], ], m_elc=[ [-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.00868, -0.03998], [0.08, -0.02, -0.04], ], txt=[ [-26.25044, 80.79056, -2.96646], [26.25044, 80.79056, -2.96646], [-26.25044, -80.79056, -2.96646], [0.0, -84.94822, -2.96646], ], elp=[ [-48.20043, 57.55106, 39.86971], [0.0, 60.73848, 59.4629], [48.1426, 57.58403, 39.89198], [41.64599, 66.91489, 31.8278], ], hpts=[[-95, -3, -3], [-1, -1.0, -3.0], [-2, -2, 2.0], [0, 0, 0]], ) for key, text in inputs.items(): kind = key.split("_")[-1] fname = op.join(tempdir, "test." + kind) with open(fname, "w") as fid: fid.write(text) montage = read_montage(fname) if kind in ("sfp", "txt"): assert_true("very_very_very_long_name" in montage.ch_names) assert_equal(len(montage.ch_names), 4) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (4, 3)) assert_equal(montage.kind, "test") if kind == "csd": dtype = [ ("label", "S4"), ("theta", "f8"), ("phi", "f8"), ("radius", "f8"), ("x", "f8"), ("y", "f8"), ("z", "f8"), ("off_sph", "f8"), ] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) poss["csd"] = np.c_[table["x"], table["y"], table["z"]] if kind == "elc": # Make sure points are reasonable distance from geometric centroid centroid = np.sum(montage.pos, axis=0) / montage.pos.shape[0] distance_from_centroid = np.apply_along_axis(np.linalg.norm, 1, montage.pos - centroid) assert_array_less(distance_from_centroid, 0.2) assert_array_less(0.01, distance_from_centroid) assert_array_almost_equal(poss[key], montage.pos, 4, err_msg=key) # Test reading in different letter case. ch_names = [ "F3", "FZ", "F4", "FC3", "FCz", "FC4", "C3", "CZ", "C4", "CP3", "CPZ", "CP4", "P3", "PZ", "P4", "O1", "OZ", "O2", ] montage = read_montage("standard_1020", ch_names=ch_names) assert_array_equal(ch_names, montage.ch_names) # test transform input_str = """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """ fname = op.join(tempdir, "test_fid.hpts") with open(fname, "w") as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, "test_fid.hpts"), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) idx = montage.ch_names.index("2") assert_array_equal(montage.pos[idx, [0, 2]], [0, 0]) idx = montage.ch_names.index("1") assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) idx = montage.ch_names.index("3") assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, "test_fid.hpts") montage = read_montage(montage_fname, unit="mm") assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ["eeg"] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c["loc"][:3] for c in info["chs"]]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info["ch_names"]) info = create_info(montage.ch_names, 1e3, ["eeg"] * len(montage.ch_names)) evoked = EvokedArray(data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) evoked.set_montage(montage) pos3 = np.array([c["loc"][:3] for c in evoked.info["chs"]]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info["ch_names"]) # Warning should be raised when some EEG are not specified in the montage with warnings.catch_warnings(record=True) as w: info = create_info(montage.ch_names + ["foo", "bar"], 1e3, ["eeg"] * (len(montage.ch_names) + 2)) _set_montage(info, montage) assert_true(len(w) == 1)
# fit the classifier on MEG data X = scaler.fit_transform(meg_data) model.fit(X, labels) # Extract and plot spatial filters and spatial patterns for name, coef in (('patterns', model.patterns_), ('filters', model.filters_)): # We fitted the linear model onto Z-scored data. To make the filters # interpretable, we must reverse this normalization step coef = scaler.inverse_transform([coef])[0] # The data was vectorized to fit a single model across all time points and # all channels. We thus reshape it: coef = coef.reshape(len(meg_epochs.ch_names), -1) # Plot evoked = EvokedArray(coef, meg_epochs.info, tmin=epochs.tmin) evoked.plot_topomap(title='MEG %s' % name, time_unit='s') ############################################################################### # Let's do the same on EEG data using a scikit-learn pipeline X = epochs.pick_types(meg=False, eeg=True) y = epochs.events[:, 2] # Define a unique pipeline to sequentially: clf = make_pipeline( Vectorizer(), # 1) vectorize across time and channels StandardScaler(), # 2) normalize features across trials LinearModel( LogisticRegression(solver='lbfgs'))) # 3) fits a logistic regression clf.fit(X, y)
def test_montage(): """Test making montages.""" tempdir = _TempDir() inputs = dict( sfp='FidNz 0 9.071585155 -2.359754454\n' 'FidT9 -6.711765 0.040402876 -3.251600355\n' 'very_very_very_long_name -5.831241498 -4.494821698 4.955347697\n' 'Cz 0 0 8.899186843', csd= '// MatLab Sphere coordinates [degrees] Cartesian coordinates\n' # noqa: E501 '// Label Theta Phi Radius X Y Z off sphere surface\n' # noqa: E501 'E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011\n' # noqa: E501 'E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000\n' # noqa: E501 'E31 90.000 -11.000 1.000 0.0000 0.9816 -0.1908 0.00000000000000000\n' # noqa: E501 'E61 158.000 -17.200 1.000 -0.8857 0.3579 -0.2957 -0.00000000000000022', # noqa: E501 mm_elc= '# ASA electrode file\nReferenceLabel avg\nUnitPosition mm\n' # noqa:E501 'NumberPositions= 68\n' 'Positions\n' '-86.0761 -19.9897 -47.9860\n' '85.7939 -20.0093 -48.0310\n' '0.0083 86.8110 -39.9830\n' '-86.0761 -24.9897 -67.9860\n' 'Labels\nLPA\nRPA\nNz\nDummy\n', m_elc='# ASA electrode file\nReferenceLabel avg\nUnitPosition m\n' 'NumberPositions= 68\nPositions\n-.0860761 -.0199897 -.0479860\n' # noqa:E501 '.0857939 -.0200093 -.0480310\n.0000083 .00868110 -.0399830\n' '.08 -.02 -.04\n' 'Labels\nLPA\nRPA\nNz\nDummy\n', txt='Site Theta Phi\n' 'Fp1 -92 -72\n' 'Fp2 92 72\n' 'very_very_very_long_name -92 72\n' 'O2 92 -90\n', elp='346\n' 'EEG\t F3\t -62.027\t -50.053\t 85\n' 'EEG\t Fz\t 45.608\t 90\t 85\n' 'EEG\t F4\t 62.01\t 50.103\t 85\n' 'EEG\t FCz\t 68.01\t 58.103\t 85\n', hpts='eeg Fp1 -95.0 -3. -3.\n' 'eeg AF7 -1 -1 -3\n' 'eeg A3 -2 -2 2\n' 'eeg A 0 0 0', bvef='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n' '<!-- Generated by EasyCap Configurator 19.05.2014 -->\n' '<Electrodes defaults="false">\n' ' <Electrode>\n' ' <Name>Fp1</Name>\n' ' <Theta>-90</Theta>\n' ' <Phi>-72</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>1</Number>\n' ' </Electrode>\n' ' <Electrode>\n' ' <Name>Fz</Name>\n' ' <Theta>45</Theta>\n' ' <Phi>90</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>2</Number>\n' ' </Electrode>\n' ' <Electrode>\n' ' <Name>F3</Name>\n' ' <Theta>-60</Theta>\n' ' <Phi>-51</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>3</Number>\n' ' </Electrode>\n' ' <Electrode>\n' ' <Name>F7</Name>\n' ' <Theta>-90</Theta>\n' ' <Phi>-36</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>4</Number>\n' ' </Electrode>\n' '</Electrodes>', ) # Get actual positions and save them for checking # csd comes from the string above, all others come from commit 2fa35d4 poss = dict( sfp=[[0.0, 9.07159, -2.35975], [-6.71176, 0.0404, -3.2516], [-5.83124, -4.49482, 4.95535], [0.0, 0.0, 8.89919]], mm_elc=[[-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.08681, -0.03998], [-0.08608, -0.02499, -0.06799]], m_elc=[[-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.00868, -0.03998], [0.08, -0.02, -0.04]], txt=[[-26.25044, 80.79056, -2.96646], [26.25044, 80.79056, -2.96646], [-26.25044, -80.79056, -2.96646], [0.0, -84.94822, -2.96646]], elp=[[-48.20043, 57.55106, 39.86971], [0.0, 60.73848, 59.4629], [48.1426, 57.58403, 39.89198], [41.64599, 66.91489, 31.8278]], hpts=[[-95, -3, -3], [-1, -1., -3.], [-2, -2, 2.], [0, 0, 0]], bvef=[[-26.266444, 80.839803, 5.204748e-15], [3.680313e-15, 60.104076, 60.104076], [-46.325632, 57.207392, 42.500000], [-68.766444, 49.961746, 5.204748e-15]], ) for key, text in inputs.items(): kind = key.split('_')[-1] fname = op.join(tempdir, 'test.' + kind) with open(fname, 'w') as fid: fid.write(text) montage = read_montage(fname) if kind in ('sfp', 'txt'): assert ('very_very_very_long_name' in montage.ch_names) assert_equal(len(montage.ch_names), 4) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (4, 3)) assert_equal(montage.kind, 'test') if kind == 'csd': dtype = [('label', 'S4'), ('theta', 'f8'), ('phi', 'f8'), ('radius', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('off_sph', 'f8')] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) poss['csd'] = np.c_[table['x'], table['y'], table['z']] if kind == 'elc': # Make sure points are reasonable distance from geometric centroid centroid = np.sum(montage.pos, axis=0) / montage.pos.shape[0] distance_from_centroid = np.apply_along_axis( np.linalg.norm, 1, montage.pos - centroid) assert_array_less(distance_from_centroid, 0.2) assert_array_less(0.01, distance_from_centroid) assert_array_almost_equal(poss[key], montage.pos, 4, err_msg=key) # Test reading in different letter case. ch_names = [ "F3", "FZ", "F4", "FC3", "FCz", "FC4", "C3", "CZ", "C4", "CP3", "CPZ", "CP4", "P3", "PZ", "P4", "O1", "OZ", "O2" ] montage = read_montage('standard_1020', ch_names=ch_names) assert_array_equal(ch_names, montage.ch_names) # test transform input_strs = [ """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """, """ Fp1 -95.0 -31.0 -3.0 AF7 -81 -59 -3 AF3 -87 -41 28 FidNz -91 0 -42 FidT9 0 -91 -42 FidT10 0 91 -42 """ ] # sfp files seem to have Nz, T9, and T10 as fiducials: # https://github.com/mne-tools/mne-python/pull/4482#issuecomment-321980611 kinds = ['test_fid.hpts', 'test_fid.sfp'] for kind, input_str in zip(kinds, input_strs): fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, kind), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) assert_array_equal(montage.nasion[[0, 2]], [0, 0]) assert_array_equal(montage.lpa[[1, 2]], [0, 0]) assert_array_equal(montage.rpa[[1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, kind) montage = read_montage(montage_fname, unit='mm') assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c['loc'][:3] for c in info['chs']]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info['ch_names']) info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) evoked = EvokedArray(data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) # test return type as well as set montage assert (isinstance(evoked.set_montage(montage), type(evoked))) pos3 = np.array([c['loc'][:3] for c in evoked.info['chs']]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info['ch_names']) # Warning should be raised when some EEG are not specified in montage info = create_info(montage.ch_names + ['foo', 'bar'], 1e3, ['eeg'] * (len(montage.ch_names) + 2)) with pytest.warns(RuntimeWarning, match='position specified'): _set_montage(info, montage) # Channel names can be treated case insensitive info = create_info(['FP1', 'af7', 'AF3'], 1e3, ['eeg'] * 3) _set_montage(info, montage) # Unless there is a collision in names info = create_info(['FP1', 'Fp1', 'AF3'], 1e3, ['eeg'] * 3) assert (info['dig'] is None) with pytest.warns(RuntimeWarning, match='position specified'): _set_montage(info, montage) assert len(info['dig']) == 5 # 2 EEG w/pos, 3 fiducials montage.ch_names = ['FP1', 'Fp1', 'AF3'] info = create_info(['fp1', 'AF3'], 1e3, ['eeg', 'eeg']) assert (info['dig'] is None) with pytest.warns(RuntimeWarning, match='position specified'): _set_montage(info, montage, set_dig=False) assert (info['dig'] is None) # test get_pos2d method montage = read_montage("standard_1020") c3 = montage.get_pos2d()[montage.ch_names.index("C3")] c4 = montage.get_pos2d()[montage.ch_names.index("C4")] fz = montage.get_pos2d()[montage.ch_names.index("Fz")] oz = montage.get_pos2d()[montage.ch_names.index("Oz")] f1 = montage.get_pos2d()[montage.ch_names.index("F1")] assert (c3[0] < 0) # left hemisphere assert (c4[0] > 0) # right hemisphere assert (fz[1] > 0) # frontal assert (oz[1] < 0) # occipital assert_allclose(fz[0], 0, atol=1e-2) # midline assert_allclose(oz[0], 0, atol=1e-2) # midline assert (f1[0] < 0 and f1[1] > 0) # left frontal # test get_builtin_montages function montages = get_builtin_montages() assert (len(montages) > 0) # MNE should always ship with montages assert ("standard_1020" in montages) # 10/20 montage assert ("standard_1005" in montages) # 10/05 montage
plt.yticks(tick_marks, target_names) fig.tight_layout() ax.set(ylabel='True label', xlabel='Predicted label') # %% # The ``patterns_`` attribute of a fitted Xdawn instance (here from the last # cross-validation fold) can be used for visualization. fig, axes = plt.subplots(nrows=len(event_id), ncols=n_filter, figsize=(n_filter, len(event_id) * 2)) fitted_xdawn = clf.steps[0][1] tmp_info = epochs.info.copy() tmp_info['sfreq'] = 1. for ii, cur_class in enumerate(sorted(event_id)): cur_patterns = fitted_xdawn.patterns_[cur_class] pattern_evoked = EvokedArray(cur_patterns[:n_filter].T, tmp_info, tmin=0) pattern_evoked.plot_topomap(times=np.arange(n_filter), time_format='Component %d' if ii == 0 else '', colorbar=False, show_names=False, axes=axes[ii], show=False) axes[ii, 0].set(ylabel=cur_class) fig.tight_layout(h_pad=1.0, w_pad=1.0, pad=0.1) # %% # References # ---------- # .. footbibliography::
def plot_filters(self, info, components=None, fband=None, ch_type=None, layout=None, vmin=None, vmax=None, cmap='RdBu_r', sensors=True, colorbar=True, scalings=None, units='a.u.', res=64, size=1, cbar_fmt='%3.1f', name_format='CSP%01d', show=True, show_names=False, title=None, mask=None, mask_params=None, outlines='head', contours=6, image_interp='bilinear', average=None, head_pos=None, axes=None): if components is None: components = np.arange(self.n_compo) filters = self.filters_[self.fbands.index(fband)] # set sampling frequency to have 1 component per time point info = cp.deepcopy(info) info['sfreq'] = 1. filters = EvokedArray(filters, info, tmin=0) return filters.plot_topomap(times=components, ch_type=ch_type, layout=layout, vmin=vmin, vmax=vmax, cmap=cmap, colorbar=colorbar, res=res, cbar_fmt=cbar_fmt, sensors=sensors, scalings=scalings, units=units, time_unit='s', time_format=name_format, size=size, show_names=show_names, title=title, mask_params=mask_params, mask=mask, outlines=outlines, contours=contours, image_interp=image_interp, show=show, average=average, head_pos=head_pos, axes=axes)
plt.title('single trial surrogates') plt.imshow(X_transform[y.argsort()], origin='lower', aspect='auto', extent=[epochs.times[0], epochs.times[-1], 1, len(X_transform)], cmap='RdBu_r') plt.xlabel('Time (ms)') plt.ylabel('Trials (reordered by condition)') # Plot average response plt.figure() plt.title('Average EMS signal') mappings = [(key, value) for key, value in event_ids.items()] for key, value in mappings: ems_ave = X_transform[y == value] plt.plot(epochs.times, ems_ave.mean(0), label=key) plt.xlabel('Time (ms)') plt.ylabel('a.u.') plt.legend(loc='best') plt.show() # Visualize spatial filters across time evoked = EvokedArray(filters, epochs.info, tmin=epochs.tmin) evoked.plot_topomap(time_unit='s', scalings=1) ############################################################################# # Note that a similar transformation can be applied with `compute_ems` # However, this function replicates Schurger et al's original paper, and thus # applies the normalization outside a leave-one-out cross-validation, which we # recommend not to do. epochs.equalize_event_counts(event_ids) X_transform, filters, classes = compute_ems(epochs)
t_stL = np.c_[t_th_stL,t_a_stL,t_b1_stL, t_b2_stL] t_sinR = np.c_[t_th_sinR,t_a_sinR,t_b1_sinR, t_b2_sinR] t_sinL = np.c_[t_th_sinL,t_a_sinL,t_b1_sinL, t_b2_sinL] t_rest = np.c_[t_th_rest,t_a_rest,t_b1_rest, t_b2_rest] for p in range(4): _, p_corr = fdrcorrection(p_stR[:,p]) p_stR[:,p] = p_corr _, p_corr = fdrcorrection(p_stL[:,p]) p_stL[:,p] = p_corr _, p_corr = fdrcorrection(p_sinR[:,p]) p_sinR[:,p] = p_corr _, p_corr = fdrcorrection(p_sinL[:,p]) p_sinL[:,p] = p_corr _, p_corr = fdrcorrection(p_rest[:,p]) p_rest[:,p] = p_corr t_stR = EvokedArray(t_stR, info, tmin=0) t_stL = EvokedArray(t_stL, info, tmin=0) t_sinR = EvokedArray(t_sinR, info, tmin=0) t_sinL = EvokedArray(t_sinL, info, tmin=0) t_rest = EvokedArray(t_rest, info, tmin=0) mask_stR = p_stR <= 0.05 mask_stL = p_stL <=0.05 mask_sinR = p_sinR <= 0.05 mask_sinL = p_sinL <=0.05 mask_rest = p_rest <= 0.05 fig1 = t_stR.plot_topomap(ch_type='eeg', scalings=1, time_format=' ', vmin=-4.5, vmax=4.5, units='t_values', mask=mask_stR, size=3, time_unit='s', title = None, nrows = 4, res = 1000)
def _get_matrix_from_inverse_operator(inverse_operator, forward, method='dSPM', lambda2=1. / 9.): """Get inverse matrix from an inverse operator. Currently works only for fixed/loose orientation constraints For loose orientation constraint, the CTFs are computed for the normal component (pick_ori='normal'). Parameters ---------- inverse_operator : instance of InverseOperator The inverse operator. forward : instance of Forward The forward operator. method : 'MNE' | 'dSPM' | 'sLORETA' Inverse methods (for apply_inverse). lambda2 : float The regularization parameter (for apply_inverse). Returns ------- invmat : array, shape (n_dipoles, n_channels) Inverse matrix associated with inverse operator and specified parameters. """ # make sure forward and inverse operators match with respect to # surface orientation _convert_forward_match_inv(forward, inverse_operator) info_inv = _prepare_info(inverse_operator) # only use channels that are good for inverse operator and forward sol ch_names_inv = info_inv['ch_names'] n_chs_inv = len(ch_names_inv) bads_inv = inverse_operator['info']['bads'] # indices of bad channels ch_idx_bads = [ch_names_inv.index(ch) for ch in bads_inv] # create identity matrix as input for inverse operator # set elements to zero for non-selected channels id_mat = np.eye(n_chs_inv) # convert identity matrix to evoked data type (pretending it's an epoch) ev_id = EvokedArray(id_mat, info=info_inv, tmin=0.) # apply inverse operator to identity matrix in order to get inverse matrix # free orientation constraint not possible because apply_inverse would # combine components # check if inverse operator uses fixed source orientations is_fixed_inv = _check_fixed_ori(inverse_operator) # choose pick_ori according to inverse operator if is_fixed_inv: pick_ori = None else: pick_ori = 'vector' # columns for bad channels will be zero invmat_op = apply_inverse(ev_id, inverse_operator, lambda2=lambda2, method=method, pick_ori=pick_ori) # turn source estimate into numpy array invmat = invmat_op.data # remove columns for bad channels # take into account it may be 3D array invmat = np.delete(invmat, ch_idx_bads, axis=invmat.ndim - 1) # if 3D array, i.e. multiple values per location (fixed and loose), # reshape into 2D array if invmat.ndim == 3: v0o1 = invmat[0, 1].copy() v3o2 = invmat[3, 2].copy() shape = invmat.shape invmat = invmat.reshape(shape[0] * shape[1], shape[2]) # make sure that reshaping worked assert np.array_equal(v0o1, invmat[1]) assert np.array_equal(v3o2, invmat[11]) logger.info("Dimension of Inverse Matrix: %s" % str(invmat.shape)) return invmat
def test_montage(): """Test making montages""" tempdir = _TempDir() # no pep8 input_str = ["""FidNz 0.00000 10.56381 -2.05108 FidT9 -7.82694 0.45386 -3.76056 FidT10 7.82694 0.45386 -3.76056""", """// MatLab Sphere coordinates [degrees] Cartesian coordinates // Label Theta Phi Radius X Y Z off sphere surface E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011 E2 44.600 -0.880 1.000 0.7119 0.7021 -0.0154 0.00000000000000000 E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000""", # noqa """# ASA electrode file ReferenceLabel avg UnitPosition mm NumberPositions= 68 Positions -86.0761 -19.9897 -47.9860 85.7939 -20.0093 -48.0310 0.0083 86.8110 -39.9830 Labels LPA RPA Nz """, """Site Theta Phi Fp1 -92 -72 Fp2 92 72 F3 -60 -51 """, """346 EEG F3 -62.027 -50.053 85 EEG Fz 45.608 90 85 EEG F4 62.01 50.103 85 """, """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 """] kinds = ['test.sfp', 'test.csd', 'test.elc', 'test.txt', 'test.elp', 'test.hpts'] for kind, text in zip(kinds, input_str): fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(text) montage = read_montage(fname) assert_equal(len(montage.ch_names), 3) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (3, 3)) assert_equal(montage.kind, op.splitext(kind)[0]) if kind.endswith('csd'): dtype = [('label', 'S4'), ('theta', 'f8'), ('phi', 'f8'), ('radius', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('off_sph', 'f8')] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) pos2 = np.c_[table['x'], table['y'], table['z']] assert_array_almost_equal(pos2, montage.pos, 4) # test transform input_str = """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """ kind = 'test_fid.hpts' fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, 'test_fid.hpts'), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) idx = montage.ch_names.index('2') assert_array_equal(montage.pos[idx, [0, 2]], [0, 0]) idx = montage.ch_names.index('1') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) idx = montage.ch_names.index('3') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, 'test_fid.hpts') montage = read_montage(montage_fname, unit='mm') assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c['loc'][:3] for c in info['chs']]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info['ch_names']) info = create_info( montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) evoked = EvokedArray( data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) evoked.set_montage(montage) pos3 = np.array([c['loc'][:3] for c in evoked.info['chs']]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info['ch_names']) # Warning should be raised when some EEG are not specified in the montage with warnings.catch_warnings(record=True) as w: info = create_info(montage.ch_names + ['foo', 'bar'], 1e3, ['eeg'] * (len(montage.ch_names) + 2)) _set_montage(info, montage) assert_true(len(w) == 1)
def test_montage(): """Test making montages.""" tempdir = _TempDir() # no pep8 input_str = [ 'FidNz 0.00000 10.56381 -2.05108\nFidT9 -7.82694 0.45386 -3.76056\n' 'very_very_very_long_name 7.82694 0.45386 -3.76056', '// MatLab Sphere coordinates [degrees] Cartesian coordinates\n' # noqa: E501 '// Label Theta Phi Radius X Y Z off sphere surface\n' # noqa: E501 'E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011\n' # noqa: E501 'E2 44.600 -0.880 1.000 0.7119 0.7021 -0.0154 0.00000000000000000\n' # noqa: E501 'E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000', # noqa: E501 '# ASA electrode file\nReferenceLabel avg\nUnitPosition mm\n' 'NumberPositions= 68\nPositions\n-86.0761 -19.9897 -47.9860\n' '85.7939 -20.0093 -48.0310\n0.0083 86.8110 -39.9830\n' 'Labels\nLPA\nRPA\nNz\n', '# ASA electrode file\nReferenceLabel avg\nUnitPosition m\n' 'NumberPositions= 68\nPositions\n-.0860761 -.0199897 -.0479860\n' '.0857939 -.0200093 -.0480310\n.0000083 .00868110 -.0399830\n' 'Labels\nLPA\nRPA\nNz\n', 'Site Theta Phi\nFp1 -92 -72\nFp2 92 72\n' 'very_very_very_long_name -60 -51\n', '346\n' 'EEG\t F3\t -62.027\t -50.053\t 85\n' 'EEG\t Fz\t 45.608\t 90\t 85\n' 'EEG\t F4\t 62.01\t 50.103\t 85\n', 'eeg Fp1 -95.0 -31.0 -3.0\neeg AF7 -81 -59 -3\neeg AF3 -87 -41 28\n' ] kinds = ['test.sfp', 'test.csd', 'test_mm.elc', 'test_m.elc', 'test.txt', 'test.elp', 'test.hpts'] for kind, text in zip(kinds, input_str): fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(text) montage = read_montage(fname) if ".sfp" in kind or ".txt" in kind: assert_true('very_very_very_long_name' in montage.ch_names) assert_equal(len(montage.ch_names), 3) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (3, 3)) assert_equal(montage.kind, op.splitext(kind)[0]) if kind.endswith('csd'): dtype = [('label', 'S4'), ('theta', 'f8'), ('phi', 'f8'), ('radius', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('off_sph', 'f8')] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) pos2 = np.c_[table['x'], table['y'], table['z']] assert_array_almost_equal(pos2, montage.pos, 4) if kind.endswith('elc'): # Make sure points are reasonable distance from geometric centroid centroid = np.sum(montage.pos, axis=0) / montage.pos.shape[0] distance_from_centroid = np.apply_along_axis( np.linalg.norm, 1, montage.pos - centroid) assert_array_less(distance_from_centroid, 0.2) assert_array_less(0.01, distance_from_centroid) # test transform input_str = """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """ kind = 'test_fid.hpts' fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, 'test_fid.hpts'), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) idx = montage.ch_names.index('2') assert_array_equal(montage.pos[idx, [0, 2]], [0, 0]) idx = montage.ch_names.index('1') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) idx = montage.ch_names.index('3') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, 'test_fid.hpts') montage = read_montage(montage_fname, unit='mm') assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c['loc'][:3] for c in info['chs']]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info['ch_names']) info = create_info( montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) evoked = EvokedArray( data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) evoked.set_montage(montage) pos3 = np.array([c['loc'][:3] for c in evoked.info['chs']]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info['ch_names']) # Warning should be raised when some EEG are not specified in the montage with warnings.catch_warnings(record=True) as w: info = create_info(montage.ch_names + ['foo', 'bar'], 1e3, ['eeg'] * (len(montage.ch_names) + 2)) _set_montage(info, montage) assert_true(len(w) == 1)
def _compare_inverses_approx(inv_1, inv_2, evoked, rtol, atol, depth_atol=1e-6, ctol=0.999999, check_nn=True, check_K=True): """Compare inverses.""" # depth prior if inv_1['depth_prior'] is not None: assert_allclose(inv_1['depth_prior']['data'], inv_2['depth_prior']['data'], atol=depth_atol) else: assert (inv_2['depth_prior'] is None) # orient prior if inv_1['orient_prior'] is not None: assert_allclose(inv_1['orient_prior']['data'], inv_2['orient_prior']['data'], atol=1e-7) else: assert (inv_2['orient_prior'] is None) # source cov assert_allclose(inv_1['source_cov']['data'], inv_2['source_cov']['data'], atol=1e-7) for key in ('units', 'eigen_leads_weighted', 'nsource', 'coord_frame'): assert_equal(inv_1[key], inv_2[key], err_msg=key) assert_equal(inv_1['eigen_leads']['ncol'], inv_2['eigen_leads']['ncol']) K_1 = np.dot(inv_1['eigen_leads']['data'] * inv_1['sing'].astype(float), inv_1['eigen_fields']['data']) K_2 = np.dot(inv_2['eigen_leads']['data'] * inv_2['sing'].astype(float), inv_2['eigen_fields']['data']) # for free + surf ori, we only care about the ::2 # (the other two dimensions have arbitrary direction) if inv_1['nsource'] * 3 == inv_1['source_nn'].shape[0]: # Technically this undersamples the free-orientation, non-surf-ori # inverse, but it's probably okay sl = slice(2, None, 3) else: sl = slice(None) if check_nn: assert_allclose(inv_1['source_nn'][sl], inv_2['source_nn'][sl], atol=1e-4) if check_K: assert_allclose(np.abs(K_1[sl]), np.abs(K_2[sl]), rtol=rtol, atol=atol) # Now let's do some practical tests, too evoked = EvokedArray(np.eye(len(evoked.ch_names)), evoked.info) for method in ('MNE', 'dSPM'): stc_1 = apply_inverse(evoked, inv_1, lambda2, method) stc_2 = apply_inverse(evoked, inv_2, lambda2, method) assert_equal(stc_1.subject, stc_2.subject) assert_equal(stc_1.times, stc_2.times) stc_1 = stc_1.data stc_2 = stc_2.data norms = np.max(stc_1, axis=-1, keepdims=True) stc_1 /= norms stc_2 /= norms corr = np.corrcoef(stc_1.ravel(), stc_2.ravel())[0, 1] assert corr > ctol assert_allclose(stc_1, stc_2, rtol=rtol, atol=atol, err_msg='%s: %s' % (method, corr))
def test_localization_bias(): """Test inverse localization bias for minimum-norm solvers.""" # Identity input evoked = _get_evoked() evoked.pick_types(meg=True, eeg=True, exclude=()) evoked = EvokedArray(np.eye(len(evoked.data)), evoked.info) noise_cov = read_cov(fname_cov) # restrict to limited set of verts (small src here) and one hemi for speed fwd_orig = read_forward_solution(fname_fwd) vertices = [fwd_orig['src'][0]['vertno'].copy(), []] stc = SourceEstimate(np.zeros((sum(len(v) for v in vertices), 1)), vertices, 0., 1.) fwd_orig = restrict_forward_to_stc(fwd_orig, stc) # # Fixed orientation (not very different) # fwd = fwd_orig.copy() inv_fixed = make_inverse_operator(evoked.info, fwd, noise_cov, loose=0., depth=0.8) fwd = convert_forward_solution(fwd, force_fixed=True, surf_ori=True) fwd = fwd['sol']['data'] want = np.arange(fwd.shape[1]) for method, lower, upper in (('MNE', 83, 87), ('dSPM', 96, 98), ('sLORETA', 100, 100), ('eLORETA', 100, 100)): inv_op = apply_inverse(evoked, inv_fixed, lambda2, method).data loc = np.abs(np.dot(inv_op, fwd)) # Compute the percentage of sources for which there is no localization # bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method # # Loose orientation # fwd = fwd_orig.copy() inv_free = make_inverse_operator(evoked.info, fwd, noise_cov, loose=0.2, depth=0.8) fwd = fwd['sol']['data'] want = np.arange(fwd.shape[1]) // 3 for method, lower, upper in (('MNE', 25, 35), ('dSPM', 25, 35), ('sLORETA', 35, 40), ('eLORETA', 40, 45)): inv_op = apply_inverse(evoked, inv_free, lambda2, method, pick_ori='vector').data loc = np.linalg.norm(np.einsum('vos,sx->vxo', inv_op, fwd), axis=-1) # Compute the percentage of sources for which there is no localization # bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method # # Free orientation # fwd = fwd_orig.copy() inv_free = make_inverse_operator(evoked.info, fwd, noise_cov, loose=1., depth=0.8) fwd = fwd['sol']['data'] want = np.arange(fwd.shape[1]) // 3 force_kwargs = dict(method_params=dict(force_equal=True)) for method, lower, upper, kwargs in ( ('MNE', 45, 55, {}), ('dSPM', 40, 45, {}), ('sLORETA', 90, 95, {}), ('eLORETA', 90, 95, force_kwargs), ('eLORETA', 100, 100, {}), ): inv_op = apply_inverse(evoked, inv_free, lambda2, method, pick_ori='vector', **kwargs).data loc = np.linalg.norm(np.einsum('vos,sx->vxo', inv_op, fwd), axis=-1) # Compute the percentage of sources for which there is no localization # bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method
def test_montage(): """Test making montages.""" tempdir = _TempDir() inputs = dict( sfp='FidNz 0 9.071585155 -2.359754454\n' 'FidT9 -6.711765 0.040402876 -3.251600355\n' 'very_very_very_long_name -5.831241498 -4.494821698 4.955347697\n' 'Cz 0 0 8.899186843', csd='// MatLab Sphere coordinates [degrees] Cartesian coordinates\n' # noqa: E501 '// Label Theta Phi Radius X Y Z off sphere surface\n' # noqa: E501 'E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011\n' # noqa: E501 'E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000\n' # noqa: E501 'E31 90.000 -11.000 1.000 0.0000 0.9816 -0.1908 0.00000000000000000\n' # noqa: E501 'E61 158.000 -17.200 1.000 -0.8857 0.3579 -0.2957 -0.00000000000000022', # noqa: E501 mm_elc='# ASA electrode file\nReferenceLabel avg\nUnitPosition mm\n' # noqa:E501 'NumberPositions= 68\n' 'Positions\n' '-86.0761 -19.9897 -47.9860\n' '85.7939 -20.0093 -48.0310\n' '0.0083 86.8110 -39.9830\n' '-86.0761 -24.9897 -67.9860\n' 'Labels\nLPA\nRPA\nNz\nDummy\n', m_elc='# ASA electrode file\nReferenceLabel avg\nUnitPosition m\n' 'NumberPositions= 68\nPositions\n-.0860761 -.0199897 -.0479860\n' # noqa:E501 '.0857939 -.0200093 -.0480310\n.0000083 .00868110 -.0399830\n' '.08 -.02 -.04\n' 'Labels\nLPA\nRPA\nNz\nDummy\n', txt='Site Theta Phi\n' 'Fp1 -92 -72\n' 'Fp2 92 72\n' 'very_very_very_long_name -92 72\n' 'O2 92 -90\n', elp='346\n' 'EEG\t F3\t -62.027\t -50.053\t 85\n' 'EEG\t Fz\t 45.608\t 90\t 85\n' 'EEG\t F4\t 62.01\t 50.103\t 85\n' 'EEG\t FCz\t 68.01\t 58.103\t 85\n', hpts='eeg Fp1 -95.0 -3. -3.\n' 'eeg AF7 -1 -1 -3\n' 'eeg A3 -2 -2 2\n' 'eeg A 0 0 0', bvef='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n' '<!-- Generated by EasyCap Configurator 19.05.2014 -->\n' '<Electrodes defaults="false">\n' ' <Electrode>\n' ' <Name>Fp1</Name>\n' ' <Theta>-90</Theta>\n' ' <Phi>-72</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>1</Number>\n' ' </Electrode>\n' ' <Electrode>\n' ' <Name>Fz</Name>\n' ' <Theta>45</Theta>\n' ' <Phi>90</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>2</Number>\n' ' </Electrode>\n' ' <Electrode>\n' ' <Name>F3</Name>\n' ' <Theta>-60</Theta>\n' ' <Phi>-51</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>3</Number>\n' ' </Electrode>\n' ' <Electrode>\n' ' <Name>F7</Name>\n' ' <Theta>-90</Theta>\n' ' <Phi>-36</Phi>\n' ' <Radius>1</Radius>\n' ' <Number>4</Number>\n' ' </Electrode>\n' '</Electrodes>', ) # Get actual positions and save them for checking # csd comes from the string above, all others come from commit 2fa35d4 poss = dict( sfp=[[0.0, 9.07159, -2.35975], [-6.71176, 0.0404, -3.2516], [-5.83124, -4.49482, 4.95535], [0.0, 0.0, 8.89919]], mm_elc=[[-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.08681, -0.03998], [-0.08608, -0.02499, -0.06799]], m_elc=[[-0.08608, -0.01999, -0.04799], [0.08579, -0.02001, -0.04803], [1e-05, 0.00868, -0.03998], [0.08, -0.02, -0.04]], txt=[[-26.25044, 80.79056, -2.96646], [26.25044, 80.79056, -2.96646], [-26.25044, -80.79056, -2.96646], [0.0, -84.94822, -2.96646]], elp=[[-48.20043, 57.55106, 39.86971], [0.0, 60.73848, 59.4629], [48.1426, 57.58403, 39.89198], [41.64599, 66.91489, 31.8278]], hpts=[[-95, -3, -3], [-1, -1., -3.], [-2, -2, 2.], [0, 0, 0]], bvef=[[-26.266444, 80.839803, 5.204748e-15], [3.680313e-15, 60.104076, 60.104076], [-46.325632, 57.207392, 42.500000], [-68.766444, 49.961746, 5.204748e-15]], ) for key, text in inputs.items(): kind = key.split('_')[-1] fname = op.join(tempdir, 'test.' + kind) with open(fname, 'w') as fid: fid.write(text) montage = read_montage(fname) if kind in ('sfp', 'txt'): assert ('very_very_very_long_name' in montage.ch_names) assert_equal(len(montage.ch_names), 4) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (4, 3)) assert_equal(montage.kind, 'test') if kind == 'csd': dtype = [('label', 'S4'), ('theta', 'f8'), ('phi', 'f8'), ('radius', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('off_sph', 'f8')] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) poss['csd'] = np.c_[table['x'], table['y'], table['z']] if kind == 'elc': # Make sure points are reasonable distance from geometric centroid centroid = np.sum(montage.pos, axis=0) / montage.pos.shape[0] distance_from_centroid = np.apply_along_axis( np.linalg.norm, 1, montage.pos - centroid) assert_array_less(distance_from_centroid, 0.2) assert_array_less(0.01, distance_from_centroid) assert_array_almost_equal(poss[key], montage.pos, 4, err_msg=key) # Test reading in different letter case. ch_names = ["F3", "FZ", "F4", "FC3", "FCz", "FC4", "C3", "CZ", "C4", "CP3", "CPZ", "CP4", "P3", "PZ", "P4", "O1", "OZ", "O2"] montage = read_montage('standard_1020', ch_names=ch_names) assert_array_equal(ch_names, montage.ch_names) # test transform input_strs = [""" eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """, """ Fp1 -95.0 -31.0 -3.0 AF7 -81 -59 -3 AF3 -87 -41 28 FidNz -91 0 -42 FidT9 0 -91 -42 FidT10 0 91 -42 """] # sfp files seem to have Nz, T9, and T10 as fiducials: # https://github.com/mne-tools/mne-python/pull/4482#issuecomment-321980611 kinds = ['test_fid.hpts', 'test_fid.sfp'] for kind, input_str in zip(kinds, input_strs): fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, kind), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) assert_array_equal(montage.nasion[[0, 2]], [0, 0]) assert_array_equal(montage.lpa[[1, 2]], [0, 0]) assert_array_equal(montage.rpa[[1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, kind) montage = read_montage(montage_fname, unit='mm') assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c['loc'][:3] for c in info['chs']]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info['ch_names']) info = create_info( montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) evoked = EvokedArray( data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) # test return type as well as set montage assert (isinstance(evoked.set_montage(montage), type(evoked))) pos3 = np.array([c['loc'][:3] for c in evoked.info['chs']]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info['ch_names']) # Warning should be raised when some EEG are not specified in montage info = create_info(montage.ch_names + ['foo', 'bar'], 1e3, ['eeg'] * (len(montage.ch_names) + 2)) with pytest.warns(RuntimeWarning, match='position specified'): _set_montage(info, montage) # Channel names can be treated case insensitive info = create_info(['FP1', 'af7', 'AF3'], 1e3, ['eeg'] * 3) _set_montage(info, montage) # Unless there is a collision in names info = create_info(['FP1', 'Fp1', 'AF3'], 1e3, ['eeg'] * 3) assert (info['dig'] is None) with pytest.warns(RuntimeWarning, match='position specified'): _set_montage(info, montage) assert len(info['dig']) == 5 # 2 EEG w/pos, 3 fiducials montage.ch_names = ['FP1', 'Fp1', 'AF3'] info = create_info(['fp1', 'AF3'], 1e3, ['eeg', 'eeg']) assert (info['dig'] is None) with pytest.warns(RuntimeWarning, match='position specified'): _set_montage(info, montage, set_dig=False) assert (info['dig'] is None) # test get_pos2d method montage = read_montage("standard_1020") c3 = montage.get_pos2d()[montage.ch_names.index("C3")] c4 = montage.get_pos2d()[montage.ch_names.index("C4")] fz = montage.get_pos2d()[montage.ch_names.index("Fz")] oz = montage.get_pos2d()[montage.ch_names.index("Oz")] f1 = montage.get_pos2d()[montage.ch_names.index("F1")] assert (c3[0] < 0) # left hemisphere assert (c4[0] > 0) # right hemisphere assert (fz[1] > 0) # frontal assert (oz[1] < 0) # occipital assert_allclose(fz[0], 0, atol=1e-2) # midline assert_allclose(oz[0], 0, atol=1e-2) # midline assert (f1[0] < 0 and f1[1] > 0) # left frontal # test get_builtin_montages function montages = get_builtin_montages() assert (len(montages) > 0) # MNE should always ship with montages assert ("standard_1020" in montages) # 10/20 montage assert ("standard_1005" in montages) # 10/05 montage
def test_ica_additional(method): """Test additional ICA functionality.""" _skip_check_picard(method) tempdir = _TempDir() stop2 = 500 raw = read_raw_fif(raw_fname).crop(1.5, stop).load_data() raw.del_proj() # avoid warnings raw.set_annotations(Annotations([0.5], [0.5], ['BAD'])) # XXX This breaks the tests :( # raw.info['bads'] = [raw.ch_names[1]] test_cov = read_cov(test_cov_name) events = read_events(event_name) picks = pick_types(raw.info, meg=True, stim=False, ecg=False, eog=False, exclude='bads')[1::2] epochs = Epochs(raw, events, None, tmin, tmax, picks=picks, baseline=(None, 0), preload=True, proj=False) epochs.decimate(3, verbose='error') assert len(epochs) == 4 # test if n_components=None works ica = ICA(n_components=None, max_pca_components=None, n_pca_components=None, random_state=0, method=method, max_iter=1) with pytest.warns(UserWarning, match='did not converge'): ica.fit(epochs) # for testing eog functionality picks2 = np.concatenate([picks, pick_types(raw.info, False, eog=True)]) epochs_eog = Epochs(raw, events[:4], event_id, tmin, tmax, picks=picks2, baseline=(None, 0), preload=True) del picks2 test_cov2 = test_cov.copy() ica = ICA(noise_cov=test_cov2, n_components=3, max_pca_components=4, n_pca_components=4, method=method) assert (ica.info is None) with pytest.warns(RuntimeWarning, match='normalize_proj'): ica.fit(raw, picks[:5]) assert (isinstance(ica.info, Info)) assert (ica.n_components_ < 5) ica = ICA(n_components=3, max_pca_components=4, method=method, n_pca_components=4, random_state=0) pytest.raises(RuntimeError, ica.save, '') ica.fit(raw, picks=[1, 2, 3, 4, 5], start=start, stop=stop2) # check passing a ch_name to find_bads_ecg with pytest.warns(RuntimeWarning, match='longer'): _, scores_1 = ica.find_bads_ecg(raw) _, scores_2 = ica.find_bads_ecg(raw, raw.ch_names[1]) assert scores_1[0] != scores_2[0] # test corrmap ica2 = ica.copy() ica3 = ica.copy() corrmap([ica, ica2], (0, 0), threshold='auto', label='blinks', plot=True, ch_type="mag") corrmap([ica, ica2], (0, 0), threshold=2, plot=False, show=False) assert (ica.labels_["blinks"] == ica2.labels_["blinks"]) assert (0 in ica.labels_["blinks"]) # test retrieval of component maps as arrays components = ica.get_components() template = components[:, 0] EvokedArray(components, ica.info, tmin=0.).plot_topomap([0], time_unit='s') corrmap([ica, ica3], template, threshold='auto', label='blinks', plot=True, ch_type="mag") assert (ica2.labels_["blinks"] == ica3.labels_["blinks"]) plt.close('all') # test warnings on bad filenames ica_badname = op.join(op.dirname(tempdir), 'test-bad-name.fif.gz') with pytest.warns(RuntimeWarning, match='-ica.fif'): ica.save(ica_badname) with pytest.warns(RuntimeWarning, match='-ica.fif'): read_ica(ica_badname) # test decim ica = ICA(n_components=3, max_pca_components=4, n_pca_components=4, method=method, max_iter=1) raw_ = raw.copy() for _ in range(3): raw_.append(raw_) n_samples = raw_._data.shape[1] with pytest.warns(UserWarning, match='did not converge'): ica.fit(raw, picks=picks[:5], decim=3) assert raw_._data.shape[1] == n_samples # test expl var ica = ICA(n_components=1.0, max_pca_components=4, n_pca_components=4, method=method, max_iter=1) with pytest.warns(UserWarning, match='did not converge'): ica.fit(raw, picks=None, decim=3) assert (ica.n_components_ == 4) ica_var = _ica_explained_variance(ica, raw, normalize=True) assert (np.all(ica_var[:-1] >= ica_var[1:])) # test ica sorting ica.exclude = [0] ica.labels_ = dict(blink=[0], think=[1]) ica_sorted = _sort_components(ica, [3, 2, 1, 0], copy=True) assert_equal(ica_sorted.exclude, [3]) assert_equal(ica_sorted.labels_, dict(blink=[3], think=[2])) # epochs extraction from raw fit pytest.raises(RuntimeError, ica.get_sources, epochs) # test reading and writing test_ica_fname = op.join(op.dirname(tempdir), 'test-ica.fif') for cov in (None, test_cov): ica = ICA(noise_cov=cov, n_components=2, max_pca_components=4, n_pca_components=4, method=method, max_iter=1) with pytest.warns(None): # ICA does not converge ica.fit(raw, picks=picks[:10], start=start, stop=stop2) sources = ica.get_sources(epochs).get_data() assert (ica.mixing_matrix_.shape == (2, 2)) assert (ica.unmixing_matrix_.shape == (2, 2)) assert (ica.pca_components_.shape == (4, 10)) assert (sources.shape[1] == ica.n_components_) for exclude in [[], [0], np.array([1, 2, 3])]: ica.exclude = exclude ica.labels_ = {'foo': [0]} ica.save(test_ica_fname) ica_read = read_ica(test_ica_fname) assert (list(ica.exclude) == ica_read.exclude) assert_equal(ica.labels_, ica_read.labels_) ica.apply(raw) ica.exclude = [] ica.apply(raw, exclude=[1]) assert (ica.exclude == []) ica.exclude = [0, 1] ica.apply(raw, exclude=[1]) assert (ica.exclude == [0, 1]) ica_raw = ica.get_sources(raw) assert (ica.exclude == [ ica_raw.ch_names.index(e) for e in ica_raw.info['bads'] ]) # test filtering d1 = ica_raw._data[0].copy() ica_raw.filter(4, 20, fir_design='firwin2') assert_equal(ica_raw.info['lowpass'], 20.) assert_equal(ica_raw.info['highpass'], 4.) assert ((d1 != ica_raw._data[0]).any()) d1 = ica_raw._data[0].copy() ica_raw.notch_filter([10], trans_bandwidth=10, fir_design='firwin') assert ((d1 != ica_raw._data[0]).any()) ica.n_pca_components = 2 ica.method = 'fake' ica.save(test_ica_fname) ica_read = read_ica(test_ica_fname) assert (ica.n_pca_components == ica_read.n_pca_components) assert_equal(ica.method, ica_read.method) assert_equal(ica.labels_, ica_read.labels_) # check type consistency attrs = ('mixing_matrix_ unmixing_matrix_ pca_components_ ' 'pca_explained_variance_ pre_whitener_') def f(x, y): return getattr(x, y).dtype for attr in attrs.split(): assert_equal(f(ica_read, attr), f(ica, attr)) ica.n_pca_components = 4 ica_read.n_pca_components = 4 ica.exclude = [] ica.save(test_ica_fname) ica_read = read_ica(test_ica_fname) for attr in [ 'mixing_matrix_', 'unmixing_matrix_', 'pca_components_', 'pca_mean_', 'pca_explained_variance_', 'pre_whitener_' ]: assert_array_almost_equal(getattr(ica, attr), getattr(ica_read, attr)) assert (ica.ch_names == ica_read.ch_names) assert (isinstance(ica_read.info, Info)) sources = ica.get_sources(raw)[:, :][0] sources2 = ica_read.get_sources(raw)[:, :][0] assert_array_almost_equal(sources, sources2) _raw1 = ica.apply(raw, exclude=[1]) _raw2 = ica_read.apply(raw, exclude=[1]) assert_array_almost_equal(_raw1[:, :][0], _raw2[:, :][0]) os.remove(test_ica_fname) # check score funcs for name, func in get_score_funcs().items(): if name in score_funcs_unsuited: continue scores = ica.score_sources(raw, target='EOG 061', score_func=func, start=0, stop=10) assert (ica.n_components_ == len(scores)) # check univariate stats scores = ica.score_sources(raw, score_func=stats.skew) # check exception handling pytest.raises(ValueError, ica.score_sources, raw, target=np.arange(1)) params = [] params += [(None, -1, slice(2), [0, 1])] # variance, kurtosis params params += [(None, 'MEG 1531')] # ECG / EOG channel params for idx, ch_name in product(*params): ica.detect_artifacts(raw, start_find=0, stop_find=50, ecg_ch=ch_name, eog_ch=ch_name, skew_criterion=idx, var_criterion=idx, kurt_criterion=idx) evoked = epochs.average() evoked_data = evoked.data.copy() raw_data = raw[:][0].copy() epochs_data = epochs.get_data().copy() with pytest.warns(RuntimeWarning, match='longer'): idx, scores = ica.find_bads_ecg(raw, method='ctps') assert_equal(len(scores), ica.n_components_) with pytest.warns(RuntimeWarning, match='longer'): idx, scores = ica.find_bads_ecg(raw, method='correlation') assert_equal(len(scores), ica.n_components_) with pytest.warns(RuntimeWarning, match='longer'): idx, scores = ica.find_bads_eog(raw) assert_equal(len(scores), ica.n_components_) idx, scores = ica.find_bads_ecg(epochs, method='ctps') assert_equal(len(scores), ica.n_components_) pytest.raises(ValueError, ica.find_bads_ecg, epochs.average(), method='ctps') pytest.raises(ValueError, ica.find_bads_ecg, raw, method='crazy-coupling') with pytest.warns(RuntimeWarning, match='longer'): idx, scores = ica.find_bads_eog(raw) assert_equal(len(scores), ica.n_components_) raw.info['chs'][raw.ch_names.index('EOG 061') - 1]['kind'] = 202 with pytest.warns(RuntimeWarning, match='longer'): idx, scores = ica.find_bads_eog(raw) assert (isinstance(scores, list)) assert_equal(len(scores[0]), ica.n_components_) idx, scores = ica.find_bads_eog(evoked, ch_name='MEG 1441') assert_equal(len(scores), ica.n_components_) idx, scores = ica.find_bads_ecg(evoked, method='correlation') assert_equal(len(scores), ica.n_components_) assert_array_equal(raw_data, raw[:][0]) assert_array_equal(epochs_data, epochs.get_data()) assert_array_equal(evoked_data, evoked.data) # check score funcs for name, func in get_score_funcs().items(): if name in score_funcs_unsuited: continue scores = ica.score_sources(epochs_eog, target='EOG 061', score_func=func) assert (ica.n_components_ == len(scores)) # check univariate stats scores = ica.score_sources(epochs, score_func=stats.skew) # check exception handling pytest.raises(ValueError, ica.score_sources, epochs, target=np.arange(1)) # ecg functionality ecg_scores = ica.score_sources(raw, target='MEG 1531', score_func='pearsonr') with pytest.warns(RuntimeWarning, match='longer'): ecg_events = ica_find_ecg_events(raw, sources[np.abs(ecg_scores).argmax()]) assert (ecg_events.ndim == 2) # eog functionality eog_scores = ica.score_sources(raw, target='EOG 061', score_func='pearsonr') with pytest.warns(RuntimeWarning, match='longer'): eog_events = ica_find_eog_events(raw, sources[np.abs(eog_scores).argmax()]) assert (eog_events.ndim == 2) # Test ica fiff export ica_raw = ica.get_sources(raw, start=0, stop=100) assert (ica_raw.last_samp - ica_raw.first_samp == 100) assert_equal(len(ica_raw._filenames), 1) # API consistency ica_chans = [ch for ch in ica_raw.ch_names if 'ICA' in ch] assert (ica.n_components_ == len(ica_chans)) test_ica_fname = op.join(op.abspath(op.curdir), 'test-ica_raw.fif') ica.n_components = np.int32(ica.n_components) ica_raw.save(test_ica_fname, overwrite=True) ica_raw2 = read_raw_fif(test_ica_fname, preload=True) assert_allclose(ica_raw._data, ica_raw2._data, rtol=1e-5, atol=1e-4) ica_raw2.close() os.remove(test_ica_fname) # Test ica epochs export ica_epochs = ica.get_sources(epochs) assert (ica_epochs.events.shape == epochs.events.shape) ica_chans = [ch for ch in ica_epochs.ch_names if 'ICA' in ch] assert (ica.n_components_ == len(ica_chans)) assert (ica.n_components_ == ica_epochs.get_data().shape[1]) assert (ica_epochs._raw is None) assert (ica_epochs.preload is True) # test float n pca components ica.pca_explained_variance_ = np.array([0.2] * 5) ica.n_components_ = 0 for ncomps, expected in [[0.3, 1], [0.9, 4], [1, 1]]: ncomps_ = ica._check_n_pca_components(ncomps) assert (ncomps_ == expected) ica = ICA(method=method) with pytest.warns(None): # sometimes does not converge ica.fit(raw, picks=picks[:5]) with pytest.warns(RuntimeWarning, match='longer'): ica.find_bads_ecg(raw) ica.find_bads_eog(epochs, ch_name='MEG 0121') assert_array_equal(raw_data, raw[:][0]) raw.drop_channels(['MEG 0122']) pytest.raises(RuntimeError, ica.find_bads_eog, raw) with pytest.warns(RuntimeWarning, match='longer'): pytest.raises(RuntimeError, ica.find_bads_ecg, raw)
plt.title('single trial surrogates') plt.imshow(X_transform[y.argsort()], origin='lower', aspect='auto', extent=[epochs.times[0], epochs.times[-1], 1, len(X_transform)], cmap='RdBu_r') plt.xlabel('Time (ms)') plt.ylabel('Trials (reordered by condition)') # Plot average response plt.figure() plt.title('Average EMS signal') mappings = [(key, value) for key, value in event_ids.items()] for key, value in mappings: ems_ave = X_transform[y == value] plt.plot(epochs.times, ems_ave.mean(0), label=key) plt.xlabel('Time (ms)') plt.ylabel('a.u.') plt.legend(loc='best') plt.show() # Visualize spatial filters across time evoked = EvokedArray(filters, epochs.info, tmin=epochs.tmin) evoked.plot_topomap() ############################################################################# # Note that a similar transformation can be applied with `compute_ems` # However, this function replicates Schurger et al's original paper, and thus # applies the normalization outside a leave-one-out cross-validation, which we # recommend not to do. epochs.equalize_event_counts(event_ids) X_transform, filters, classes = compute_ems(epochs)
def test_montage(): """Test making montages""" tempdir = _TempDir() # no pep8 input_str = [ """FidNz 0.00000 10.56381 -2.05108 FidT9 -7.82694 0.45386 -3.76056 FidT10 7.82694 0.45386 -3.76056""", """// MatLab Sphere coordinates [degrees] Cartesian coordinates // Label Theta Phi Radius X Y Z off sphere surface E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011 E2 44.600 -0.880 1.000 0.7119 0.7021 -0.0154 0.00000000000000000 E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000""", # noqa """# ASA electrode file ReferenceLabel avg UnitPosition mm NumberPositions= 68 Positions -86.0761 -19.9897 -47.9860 85.7939 -20.0093 -48.0310 0.0083 86.8110 -39.9830 Labels LPA RPA Nz """, """Site Theta Phi Fp1 -92 -72 Fp2 92 72 F3 -60 -51 """, """346 EEG F3 -62.027 -50.053 85 EEG Fz 45.608 90 85 EEG F4 62.01 50.103 85 """, """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 """ ] kinds = [ 'test.sfp', 'test.csd', 'test.elc', 'test.txt', 'test.elp', 'test.hpts' ] for kind, text in zip(kinds, input_str): fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(text) montage = read_montage(fname) assert_equal(len(montage.ch_names), 3) assert_equal(len(montage.ch_names), len(montage.pos)) assert_equal(montage.pos.shape, (3, 3)) assert_equal(montage.kind, op.splitext(kind)[0]) if kind.endswith('csd'): dtype = [('label', 'S4'), ('theta', 'f8'), ('phi', 'f8'), ('radius', 'f8'), ('x', 'f8'), ('y', 'f8'), ('z', 'f8'), ('off_sph', 'f8')] try: table = np.loadtxt(fname, skip_header=2, dtype=dtype) except TypeError: table = np.loadtxt(fname, skiprows=2, dtype=dtype) pos2 = np.c_[table['x'], table['y'], table['z']] assert_array_almost_equal(pos2, montage.pos, 4) # test transform input_str = """ eeg Fp1 -95.0 -31.0 -3.0 eeg AF7 -81 -59 -3 eeg AF3 -87 -41 28 cardinal 2 -91 0 -42 cardinal 1 0 -91 -42 cardinal 3 0 91 -42 """ kind = 'test_fid.hpts' fname = op.join(tempdir, kind) with open(fname, 'w') as fid: fid.write(input_str) montage = read_montage(op.join(tempdir, 'test_fid.hpts'), transform=True) # check coordinate transformation pos = np.array([-95.0, -31.0, -3.0]) nasion = np.array([-91, 0, -42]) lpa = np.array([0, -91, -42]) rpa = np.array([0, 91, -42]) fids = np.vstack((nasion, lpa, rpa)) trans = get_ras_to_neuromag_trans(fids[0], fids[1], fids[2]) pos = apply_trans(trans, pos) assert_array_equal(montage.pos[0], pos) idx = montage.ch_names.index('2') assert_array_equal(montage.pos[idx, [0, 2]], [0, 0]) idx = montage.ch_names.index('1') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) idx = montage.ch_names.index('3') assert_array_equal(montage.pos[idx, [1, 2]], [0, 0]) pos = np.array([-95.0, -31.0, -3.0]) montage_fname = op.join(tempdir, 'test_fid.hpts') montage = read_montage(montage_fname, unit='mm') assert_array_equal(montage.pos[0], pos * 1e-3) # test with last info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) _set_montage(info, montage) pos2 = np.array([c['loc'][:3] for c in info['chs']]) assert_array_equal(pos2, montage.pos) assert_equal(montage.ch_names, info['ch_names']) info = create_info(montage.ch_names, 1e3, ['eeg'] * len(montage.ch_names)) evoked = EvokedArray(data=np.zeros((len(montage.ch_names), 1)), info=info, tmin=0) evoked.set_montage(montage) pos3 = np.array([c['loc'][:3] for c in evoked.info['chs']]) assert_array_equal(pos3, montage.pos) assert_equal(montage.ch_names, evoked.info['ch_names']) # Warning should be raised when some EEG are not specified in the montage with warnings.catch_warnings(record=True) as w: info = create_info(montage.ch_names + ['foo', 'bar'], 1e3, ['eeg'] * (len(montage.ch_names) + 2)) _set_montage(info, montage) assert_true(len(w) == 1)