def test_ica_labels(): """Test ICA labels.""" # The CTF data are uniquely well suited to testing the ICA.find_bads_ # methods raw = read_raw_ctf(ctf_fname, preload=True) # set the appropriate EEG channels to EOG and ECG raw.set_channel_types({'EEG057': 'eog', 'EEG058': 'eog', 'EEG059': 'ecg'}) ica = ICA(n_components=4, random_state=0, max_iter=2, method='fastica', allow_ref_meg=True) with pytest.warns(UserWarning, match='did not converge'): ica.fit(raw) _assert_ica_attributes(ica) ica.find_bads_eog(raw, l_freq=None, h_freq=None) picks = list(pick_types(raw.info, meg=False, eog=True)) for idx, ch in enumerate(picks): assert '{}/{}/{}'.format('eog', idx, raw.ch_names[ch]) in ica.labels_ assert 'eog' in ica.labels_ for key in ('ecg', 'ref_meg', 'ecg/ECG-MAG'): assert key not in ica.labels_ ica.find_bads_ecg(raw, l_freq=None, h_freq=None, method='correlation', threshold='auto') picks = list(pick_types(raw.info, meg=False, ecg=True)) for idx, ch in enumerate(picks): assert '{}/{}/{}'.format('ecg', idx, raw.ch_names[ch]) in ica.labels_ for key in ('ecg', 'eog'): assert key in ica.labels_ for key in ('ref_meg', 'ecg/ECG-MAG'): assert key not in ica.labels_ # derive reference ICA components and append them to raw ica_rf = ICA(n_components=2, random_state=0, max_iter=2, allow_ref_meg=True) with pytest.warns(UserWarning, match='did not converge'): ica_rf.fit(raw.copy().pick_types(meg=False, ref_meg=True)) icacomps = ica_rf.get_sources(raw) # rename components so they are auto-detected by find_bads_ref icacomps.rename_channels({c: 'REF_' + c for c in icacomps.ch_names}) # and add them to raw raw.add_channels([icacomps]) ica.find_bads_ref(raw, l_freq=None, h_freq=None, method="separate") picks = pick_channels_regexp(raw.ch_names, 'REF_ICA*') for idx, ch in enumerate(picks): assert '{}/{}/{}'.format('ref_meg', idx, raw.ch_names[ch]) in ica.labels_ ica.find_bads_ref(raw, l_freq=None, h_freq=None, method="together") assert 'ref_meg' in ica.labels_ for key in ('ecg', 'eog', 'ref_meg'): assert key in ica.labels_ assert 'ecg/ECG-MAG' not in ica.labels_ ica.find_bads_ecg(raw, l_freq=None, h_freq=None, threshold='auto') for key in ('ecg', 'eog', 'ref_meg', 'ecg/ECG-MAG'): assert key in ica.labels_
def test_ica_labels(): """Test ICA labels.""" # The CTF data are uniquely well suited to testing the ICA.find_bads_ # methods raw = read_raw_ctf(ctf_fname, preload=True) # derive reference ICA components and append them to raw icarf = ICA(n_components=2, random_state=0, max_iter=2, allow_ref_meg=True) with pytest.warns(UserWarning, match='did not converge'): icarf.fit(raw.copy().pick_types(meg=False, ref_meg=True)) icacomps = icarf.get_sources(raw) # rename components so they are auto-detected by find_bads_ref icacomps.rename_channels({c: 'REF_' + c for c in icacomps.ch_names}) # and add them to raw raw.add_channels([icacomps]) # set the appropriate EEG channels to EOG and ECG raw.set_channel_types({'EEG057': 'eog', 'EEG058': 'eog', 'EEG059': 'ecg'}) ica = ICA(n_components=4, random_state=0, max_iter=2, method='fastica') with pytest.warns(UserWarning, match='did not converge'): ica.fit(raw) ica.find_bads_eog(raw, l_freq=None, h_freq=None) picks = list(pick_types(raw.info, meg=False, eog=True)) for idx, ch in enumerate(picks): assert '{}/{}/{}'.format('eog', idx, raw.ch_names[ch]) in ica.labels_ assert 'eog' in ica.labels_ for key in ('ecg', 'ref_meg', 'ecg/ECG-MAG'): assert key not in ica.labels_ ica.find_bads_ecg(raw, l_freq=None, h_freq=None, method='correlation') picks = list(pick_types(raw.info, meg=False, ecg=True)) for idx, ch in enumerate(picks): assert '{}/{}/{}'.format('ecg', idx, raw.ch_names[ch]) in ica.labels_ for key in ('ecg', 'eog'): assert key in ica.labels_ for key in ('ref_meg', 'ecg/ECG-MAG'): assert key not in ica.labels_ ica.find_bads_ref(raw, l_freq=None, h_freq=None) picks = pick_channels_regexp(raw.ch_names, 'REF_ICA*') for idx, ch in enumerate(picks): assert '{}/{}/{}'.format('ref_meg', idx, raw.ch_names[ch]) in ica.labels_ for key in ('ecg', 'eog', 'ref_meg'): assert key in ica.labels_ assert 'ecg/ECG-MAG' not in ica.labels_ ica.find_bads_ecg(raw, l_freq=None, h_freq=None) for key in ('ecg', 'eog', 'ref_meg', 'ecg/ECG-MAG'): assert key in ica.labels_
def run_ica(raw, ica_fname=None, picks=None, n_max_ecg=3, n_max_eog=1): raw_f = raw.copy().filter(1, 45, n_jobs=1, l_trans_bandwidth=0.5, h_trans_bandwidth=0.5, filter_length='10s', phase='zero-double') ica = ICA(method='fastica', random_state=42, n_components=0.98) if picks is None: picks = mne.pick_types(raw_f.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') ica.fit(raw_f, picks=picks, reject=dict(grad=4000e-13, mag=4e-12), decim=3) ecg_epochs = create_ecg_epochs(raw_f, tmin=-.5, tmax=.5, picks=picks) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds eog_inds, scores = ica.find_bads_eog(raw_f) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds if ica_fname is None: ica_fname = raw_f._filenames[0][:-4] + '-pyimpress-ica.fif' ica.save(ica_fname) return ica, ica_fname
def inscapesMEG_PP(fname, DATA_FOLDER, SAVE_FOLDER): fpath = DATA_FOLDER + fname raw = read_raw_ctf(fpath, preload=True) picks = mne.pick_types(raw.info, meg=True, eog=True, exclude='bads') raw.plot() raw.plot_psd(average=False, picks=picks) ## Filtering high_cutoff = 200 low_cutoff = 0.5 raw.filter(low_cutoff, high_cutoff, fir_design="firwin") raw.notch_filter(np.arange(60, high_cutoff + 1, 60), picks=picks, filter_length='auto', phase='zero', fir_design="firwin") raw.plot_psd(average=False, picks=picks) ## ICA ica = ICA(n_components=20, random_state=0).fit(raw, decim=3) ica.plot_sources(raw) fmax = 40. ## correlation threshold for ICA components (maybe increase to 40. ?) ## FIND ECG COMPONENTS ecg_epochs = create_ecg_epochs(raw, ch_name='EEG059') ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, ch_name='EEG059') ica.plot_scores(ecg_scores, ecg_inds) ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': fmax}, image_args={'sigma': 1.}) ## FIND EOG COMPONENTS eog_epochs = create_eog_epochs(raw, ch_name='EEG057') eog_inds, eog_scores = ica.find_bads_eog(eog_epochs, ch_name='EEG057') ica.plot_scores(eog_scores, eog_inds) ica.plot_properties(eog_epochs, picks=eog_inds, psd_args={'fmax': fmax}, image_args={'sigma': 1.}) ## EXCLUDE COMPONENTS ica.exclude = ecg_inds ica.apply(raw) ica.exclude = eog_inds ica.apply(raw) raw.plot() # Plot the clean signal. ## SAVE PREPROCESSED FILE time.sleep(60) raw.save(SAVE_FOLDER + fname + '_preprocessed.fif.gz', overwrite=True) time.sleep(30) filename = SAVE_FOLDER + fname + '_log.html' #!jupyter nbconvert inscapesMEG_preproc.ipynb --output $filename clear_output()
def fit_ica_and_plot_scores(method, random_state, tol=1e-4): ica = ICA(n_components=0.95, method=method, random_state=random_state, fit_params={'tol': tol}, max_iter=400) t0 = time() ica.fit(raw.copy(), picks=picks, decim=3, reject=dict(mag=4e-12, grad=4000e-13), verbose='warning') fit_time = time() - t0 title = ('Method : %s, init %d. Took %.2g sec.' % (method, random_state + 1, fit_time)) ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=picks) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.plot_scores(scores, exclude=ecg_inds, title=title) ica.plot_components(ecg_inds, colorbar=True)
def preprocess_ICA_fif_to_ts(fif_file, ECG_ch_name, EoG_ch_name, l_freq, h_freq): # ------------------------ Import stuff ------------------------ # import os import mne import sys from mne.io import Raw from mne.preprocessing import ICA from mne.preprocessing import create_ecg_epochs, create_eog_epochs from nipype.utils.filemanip import split_filename as split_f from reportGen import generateReport import pickle subj_path, basename, ext = split_f(fif_file) # -------------------- Delete later ------------------- # subj_name = subj_path[-5:] results_dir = subj_path[:-6] # results_dir += '2016' subj_path = results_dir + '/' + subj_name if not os.path.exists(subj_path): try: os.makedirs(subj_path) except OSError: sys.stderr.write('ica_preproc: problem creating directory: ' + subj_path) ######################################################## # Read raw # If None the compensation in the data is not modified. If set to n, e.g. 3, apply # gradient compensation of grade n as for CTF systems (compensation=3) print(fif_file) print(EoG_ch_name) # ----------------------------- end Import stuff ----------------- # # EoG_ch_name = "EOG061, EOG062" # ------------- Load raw ------------- # raw = Raw(fif_file, preload=True) # select sensors select_sensors = mne.pick_types(raw.info, meg=True, ref_meg=False, exclude='bads') picks_meeg = mne.pick_types(raw.info, meg=True, eeg=True, exclude='bads') # filtering raw.filter(l_freq=l_freq, h_freq=h_freq, picks=picks_meeg, method='iir', n_jobs=1) # if ECG_ch_name == 'EMG063': if ECG_ch_name in raw.info['ch_names']: raw.set_channel_types({ECG_ch_name: 'ecg'}) # Without this files with ECG_ch_name = 'EMG063' fail # ECG_ch_name = 'ECG063' if EoG_ch_name == 'EMG065,EMG066,EMG067,EMG068': # Because ica.find_bads_eog... can process max 2 EoG channels EoG_ch_name = 'EMG065,EMG067' # it won't fail if I specify 4 channels, but it'll use only first # EMG065 and EMG066 are for vertical eye movements and # EMG067 and EMG068 are for horizontal # print rnk rnk = 'N/A' # 1) Fit ICA model using the FastICA algorithm # Other available choices are `infomax` or `extended-infomax` # We pass a float value between 0 and 1 to select n_components based on the # percentage of variance explained by the PCA components. reject = dict(mag=10e-12, grad=10000e-13) flat = dict(mag=0.1e-12, grad=1e-13) # check if we have an ICA, if yes, we load it ica_filename = os.path.join(subj_path, basename + "-ica.fif") raw_ica_filename = os.path.join(subj_path, basename + "_ica_raw.fif") info_filename = os.path.join(subj_path, basename + "_info.pickle") # if os.path.exists(ica_filename) == False: ica = ICA(n_components=0.99, method='fastica') # , max_iter=500 ica.fit(raw, picks=select_sensors, reject=reject, flat=flat) # decim = 3, # has_ICA = False # else: # has_ICA = True # ica = read_ica(ica_filename) # ica.exclude = [] # ica.labels_ = dict() # to avoid bug; Otherwise it'll throw an exception ica_sources_filename = subj_path + '/' + basename + '_ica_timecourse.fif' # if not os.path.isfile(ica_sources_filename): icaSrc = ica.get_sources(raw, add_channels=None, start=None, stop=None) icaSrc.save(ica_sources_filename, picks=None, tmin=0, tmax=None, buffer_size_sec=10, drop_small_buffer=False, proj=False, fmt='single', overwrite=True, split_size='2GB', verbose=None) icaSrc = None # if has_ICA == False: # ica.save(ica_filename) # return # 2) identify bad components by analyzing latent sources. # generate ECG epochs use detection via phase statistics # check if ECG_ch_name is in the raw channels # import ipdb; ipdb.set_trace() if ECG_ch_name in raw.info['ch_names']: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=ECG_ch_name) # if not a synthetic ECG channel is created from cross channel average else: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors) # ICA for ECG artifact # threshold=0.25 come defualt ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=0.25) # if len(ecg_inds) > 0: ecg_evoked = ecg_epochs.average() ecg_epochs = None # ecg_epochs use too much memory n_max_ecg = 3 ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds n_max_eog = 4 # import pdb; pdb.set_trace() if set(EoG_ch_name.split(',')).issubset(set(raw.info['ch_names'])): eog_inds, eog_scores = ica.find_bads_eog(raw, ch_name=EoG_ch_name) eog_inds = eog_inds[:n_max_eog] eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=EoG_ch_name).average() else: eog_inds = eog_scores = eog_evoked = [] # ------------------------------------------------------ # # This is necessary. Otherwise line # will through an exception if not eog_inds: eog_inds = None # ------------------------------------------------------ # generateReport(raw=raw, ica=ica, subj_name=subj_name, subj_path=subj_path, basename=basename, ecg_evoked=ecg_evoked, ecg_scores=ecg_scores, ecg_inds=ecg_inds, ECG_ch_name=ECG_ch_name, eog_evoked=eog_evoked, eog_scores=eog_scores, eog_inds=eog_inds, EoG_ch_name=EoG_ch_name) sfreq = raw.info['sfreq'] raw = None # To save memory # save ICA solution print ica_filename # ------------------------- Generate log ------------------------ # f = open(subj_path + '/' + basename + '_ica.log', 'w') f.write('Data rank after SSS: ' + str(rnk) + '\n') f.write('Sampling freq: ' + str(sfreq) + '\n') f.write('ECG exclude suggested: ' + str(ecg_inds) + '\n') f.write('EOG exclude suggested: ' + str(eog_inds) + '\n') f.write('\n') f.write('ECG exclude final: ' + str(ecg_inds) + '\n') f.write('EOG exclude final: ' + str(eog_inds) + '\n') f.write('Muscles exclude: []' + '\n') f.close() # ------------------------ end generate log ---------------------- # with open(info_filename, 'wb') as f: pickle.dump(ecg_inds, f) pickle.dump(ecg_scores, f) pickle.dump(eog_inds, f) pickle.dump(eog_scores, f) # -------------------- Save ICA solution ------------------------- # ica.save(ica_filename) return raw_ica_filename, sfreq
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') ica_different_channels = ICA(n_components=2, random_state=0).fit( raw, picks=[2, 3, 4, 5]) pytest.raises(ValueError, corrmap, [ica_different_channels, ica], (0, 0)) # 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, start=0, stop=50, 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) # Make sure detect_artifacts marks the right components. # For int criterion, the doc says "E.g. range(2) would return the two # sources with the highest score". Assert that's what it does. # Only test for skew, since it's always the same code. ica.exclude = [] ica.detect_artifacts(raw, start_find=0, stop_find=50, ecg_ch=None, eog_ch=None, skew_criterion=0, var_criterion=None, kurt_criterion=None) assert np.abs(scores[ica.exclude]) == np.max(np.abs(scores)) 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)
def runICA(raw,saveRoot,name): saveRoot = saveRoot icaList = [] ica = [] n_max_ecg = 3 # max number of ecg components # n_max_eog_1 = 2 # max number of vert eog comps # n_max_eog_2 = 2 # max number of horiz eog comps ecg_source_idx, ecg_scores, ecg_exclude = [], [], [] eog_source_idx, eog_scores, eog_exclude = [], [], [] #horiz = 1 # will later be modified to horiz = 0 if no horizontal EOG components are identified ica = ICA(n_components=0.90,n_pca_components=64,max_pca_components=100,noise_cov=None) fit_picks = mne.pick_types(raw.info, meg=True, eeg=True, eog=False, ecg=False, stim=False, exclude='bads') ica.fit(raw, picks=fit_picks) #ica.fit(raw) #************* eog_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, eog=True, ecg=False, emg=False)[0] ecg_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, ecg=True, eog=False, emg=False)[0] ica_picks = mne.pick_types(raw.info, meg=True, eeg=True, eog=False, ecg=False, stim=False, exclude='bads') ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks) ecg_evoked = ecg_epochs.average() eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks).average() ecg_source_idx, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps') eog_source_idx, eog_scores = ica.find_bads_eog(raw,ch_name=raw.ch_names[eog_picks].encode('ascii', 'ignore')) #eog_source_idx_2, eog_scores_2 = ica.find_bads_eog(raw,ch_name='EOG002') #if not eog_source_idx_2: # horiz = 0 #show_picks = np.abs(scores).argsort()[::-1][:5] #ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % 'ecg') # defining a title-frame for later use title = 'Sources related to %s artifacts (red)' # extracting number of ica-components and plotting their topographies source_idx = range(0, ica.n_components_) #ica_plot = ica.plot_components(source_idx, ch_type="mag") ica_plot = ica.plot_components(source_idx) #ica_plot = ica.plot_components(source_idx) # select ICA sources and reconstruct MEG signals, compute clean ERFs # Add detected artefact sources to exclusion list # We now add the eog artefacts to the ica.exclusion list if not ecg_source_idx: print("No ECG components above threshold were identified for subject " + name + " - selecting the component with the highest score under threshold") ecg_exclude = [np.absolute(ecg_scores).argmax()] ecg_source_idx=[np.absolute(ecg_scores).argmax()] elif ecg_source_idx: ecg_exclude += ecg_source_idx[:n_max_ecg] ica.exclude += ecg_exclude if not eog_source_idx: if np.absolute(eog_scores).any>0.3: eog_exclude=[np.absolute(eog_scores).argmax()] eog_source_idx=[np.absolute(eog_scores).argmax()] print("No EOG components above threshold were identified " + name + " - selecting the component with the highest score under threshold above 0.3") elif not np.absolute(eog_scores).any>0.3: eog_exclude=[] print("No EOG components above threshold were identified" + name) elif eog_source_idx: eog_exclude += eog_source_idx ica.exclude += eog_exclude print('########## saving') if len(eog_exclude) == 0: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') elif len(eog_exclude) == 1: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') elif len(eog_exclude) == 2: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') # plot the scores for the different components highlighting in red that/those related to ECG #scores_plots=plt.figure() #ax = plt.subplot(2,1,1) scores_plots_ecg=ica.plot_scores(ecg_scores, exclude=ecg_source_idx, title=title % 'ecg') scores_plots_ecg.savefig(saveRoot + name + '_ecg_scores.pdf', format = 'pdf') #ax = plt.subplot(2,1,2) scores_plots_eog=ica.plot_scores(eog_scores, exclude=eog_source_idx, title=title % 'eog') scores_plots_eog.savefig(saveRoot + name + '_eog_scores.pdf', format = 'pdf') #if len(ecg_exclude) > 0: # estimate average artifact #source_clean_ecg=plt.figure() #ax = plt.subplot(2,1,1) source_source_ecg=ica.plot_sources(ecg_evoked, exclude=ecg_source_idx) source_source_ecg.savefig(saveRoot + name + '_ecg_source.pdf', format = 'pdf') #ax = plt.subplot(2,1,2) source_clean_ecg=ica.plot_overlay(ecg_evoked, exclude=ecg_source_idx) source_clean_ecg.savefig(saveRoot + name + '_ecg_clean.pdf', format = 'pdf') #clean_plot.savefig(saveRoot + name + '_ecg_clean.pdf', format = 'pdf') #if len(eog_exclude) > 0: source_source_eog=ica.plot_sources(eog_evoked, exclude=eog_source_idx) source_source_eog.savefig(saveRoot + name + '_eog_source.pdf', format = 'pdf') source_clean_eog=ica.plot_overlay(eog_evoked, exclude=eog_source_idx) source_clean_eog.savefig(saveRoot + name + '_eog_clean.pdf', format = 'pdf') overl_plot = ica.plot_overlay(raw) overl_plot.savefig(saveRoot + name + '_overl.pdf', format = 'pdf') plt.close('all') ## restore sensor space data icaList = ica.apply(raw) return(icaList, ica)
def preproc(subject): global report from mne.preprocessing import ICA, create_ecg_epochs, create_eog_epochs from mne.io import read_raw_fif import numpy as np raw_path = op.join(rest_dir, subject, 'meg_clean', 'nose-pts-out_raw.fif') clean_raw_path = op.join(rest_dir, subject, 'meg_clean', 'clean_raw.fif') if not os.path.exists( raw_path): # skip subjects that have T1 but do not have MEG data return raw = read_raw_fif(raw_path, preload=True) pick_meg = mne.pick_types(raw.info, meg=True, eeg=False, stim=False, ref_meg=False) pick_eog1 = mne.pick_channels(raw.ch_names, ['EOG061']) pick_eog2 = mne.pick_channels(raw.ch_names, ['EOG062']) pick_ecg = mne.pick_channels(raw.ch_names, ['ECG063']) if pick_eog1.size == 0 or pick_eog2.size == 0 or pick_ecg.size == 0: logFile.write("Subject " + subject + ": EOG and/or ECG channels not found.\n") return ##-- Filtering, PSD --## fig = raw.plot_psd(area_mode='range', average=False, picks=pick_meg) report.add_figs_to_section(fig, captions=subject + ' => PSD before filtering', section='Filtering') raw.notch_filter((50, 100), filter_length='auto', fir_design='firwin', phase='zero', picks=np.append(pick_meg, (pick_ecg, pick_eog1, pick_eog2))) raw.filter(1., None, fir_design='firwin', phase='zero') # high-pass filtering at 1 Hz raw.resample( 200, npad="auto" ) # set sampling frequency to 200Hz (antialiasing filter at 100 Hz) ##-- Artifact removal --## random_state = 23 # we want to have the same decomposition and the same order of components each time it is run for reproducibility ica = ICA(n_components=25, method='fastica', random_state=random_state) reject = dict( mag=5e-12, grad=4000e-13 ) # avoid fitting ICA on large environmental artifacts that would dominate the variance and decomposition try: ica.fit(raw, picks=pick_meg, reject=reject) except: logFile.write("Subject " + subject + ": ICA could not run. Large environmental artifacts.\n") return fig = ica.plot_components(inst=raw) report.add_figs_to_section(fig, captions=[subject + ' => ICA components'] * len(fig), section='Artifact removal') # EOG artifact eog_epochs = create_eog_epochs(raw, reject=reject) if eog_epochs.events.size != 0: eog_inds, scores = ica.find_bads_eog(eog_epochs) if len(eog_inds) != 0: fig = ica.plot_properties(eog_epochs, picks=eog_inds, psd_args={'fmax': 35.}, image_args={'sigma': 1.}) report.add_figs_to_section( fig, captions=[subject + ' => ICA correlated with EOG'] * len(fig), section='Artifact removal') ica.exclude.extend(eog_inds) else: logFile.write("Subject " + subject + ": No ICA component correlated with EOG\n") else: logFile.write("Subject " + subject + ": No EOG events found\n") # ECG artifact ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5) if ecg_epochs.events.size != 0: ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') if len(ecg_inds) != 0: fig = ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': 35.}) report.add_figs_to_section( fig, captions=[subject + ' => ICA correlated with ECG'] * len(fig), section='Artifact removal') ica.exclude.extend(ecg_inds) else: logFile.write("Subject " + subject + ": No ICA component correlated with ECG\n") else: logFile.write("Subject " + subject + ": No ECG events found\n") raw_clean = raw.copy() ica.apply(raw_clean) fig = raw_clean.plot_psd(area_mode='range', picks=pick_meg) report.add_figs_to_section( fig, captions=subject + ' => PSD after filtering and artifact correction', section='Filtering') raw_clean.save(clean_raw_path, overwrite=True)
def compute_ica(subject): """Function will compute ICA on raw and apply the ICA. params: subject : str the subject id to be loaded """ raw = Raw(save_folder + "%s_filtered_data_mc_raw_tsss.fif" % subject, preload=True) # ICA Part ica = ICA(n_components=0.95, method='fastica', max_iter=256) picks = mne.pick_types(raw.info, meg=True, eeg=True, stim=False, exclude='bads') ica.fit(raw, picks=picks, decim=decim, reject=reject) # maximum number of components to reject n_max_ecg, n_max_eog = 3, 1 ########################################################################## # 2) identify bad components by analyzing latent sources. title = 'Sources related to %s artifacts (red) for sub: %s' # generate ECG epochs use detection via phase statistics ecg_epochs = create_ecg_epochs(raw, ch_name="ECG002", tmin=-.5, tmax=.5, picks=picks) n_ecg_epochs_found = len(ecg_epochs.events) sel_ecg_epochs = np.arange(0, n_ecg_epochs_found, 10) ecg_epochs = ecg_epochs[sel_ecg_epochs] ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') fig = ica.plot_scores(scores, exclude=ecg_inds, title=title % ('ecg', subject)) fig.savefig(save_folder + "pics/%s_ecg_scores.png" % subject) if ecg_inds: show_picks = np.abs(scores).argsort()[::-1][:5] fig = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % ('ecg', subject), show=False) fig.savefig(save_folder + "pics/%s_ecg_sources.png" % subject) fig = ica.plot_components(ecg_inds, title=title % ('ecg', subject), colorbar=True) fig.savefig(save_folder + "pics/%s_ecg_component.png" % subject) ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds # estimate average artifact ecg_evoked = ecg_epochs.average() del ecg_epochs # plot ECG sources + selection fig = ica.plot_sources(ecg_evoked, exclude=ecg_inds) fig.savefig(save_folder + "pics/%s_ecg_sources_ave.png" % subject) # plot ECG cleaning ica.plot_overlay(ecg_evoked, exclude=ecg_inds) fig.savefig(save_folder + "pics/%s_ecg_sources_clean_ave.png" % subject) # DETECT EOG BY CORRELATION # HORIZONTAL EOG eog_epochs = create_eog_epochs(raw, ch_name="EOG001") eog_inds, scores = ica.find_bads_eog(raw) fig = ica.plot_scores(scores, exclude=eog_inds, title=title % ('eog', subject)) fig.savefig(save_folder + "pics/%s_eog_scores.png" % subject) fig = ica.plot_components(eog_inds, title=title % ('eog', subject), colorbar=True) fig.savefig(save_folder + "pics/%s_eog_component.png" % subject) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds del eog_epochs ########################################################################## # Apply the solution to Raw, Epochs or Evoked like this: raw_ica = ica.apply(raw, copy=False) ica.save(save_folder + "%s-ica.fif" % subject) # save ICA componenets # Save raw with ICA removed raw_ica.save(save_folder + "%s_filtered_ica_mc_raw_tsss.fif" % subject, overwrite=True) plt.close("all")
def preprocess_ICA_fif_to_ts(fif_file, ECG_ch_name, EoG_ch_name, l_freq, h_freq, down_sfreq, variance, is_sensor_space, data_type): import os import numpy as np import mne from mne.io import Raw from mne.preprocessing import ICA, read_ica from mne.preprocessing import create_ecg_epochs, create_eog_epochs from mne.report import Report from nipype.utils.filemanip import split_filename as split_f report = Report() subj_path, basename, ext = split_f(fif_file) (data_path, sbj_name) = os.path.split(subj_path) print data_path # Read raw # If None the compensation in the data is not modified. # If set to n, e.g. 3, apply gradient compensation of grade n as for # CTF systems (compensation=3) raw = Raw(fif_file, preload=True) # select sensors select_sensors = mne.pick_types(raw.info, meg=True, ref_meg=False, exclude='bads') picks_meeg = mne.pick_types(raw.info, meg=True, eeg=True, exclude='bads') # save electrode locations sens_loc = [raw.info['chs'][i]['loc'][:3] for i in select_sensors] sens_loc = np.array(sens_loc) channel_coords_file = os.path.abspath("correct_channel_coords.txt") print '*** ' + channel_coords_file + '***' np.savetxt(channel_coords_file, sens_loc, fmt='%s') # save electrode names sens_names = np.array([raw.ch_names[pos] for pos in select_sensors],dtype = "str") # AP 21032016 # channel_names_file = os.path.join(data_path, "correct_channel_names.txt") channel_names_file = os.path.abspath("correct_channel_names.txt") np.savetxt(channel_names_file,sens_names , fmt = '%s') ### filtering + downsampling raw.filter(l_freq=l_freq, h_freq=h_freq, picks=picks_meeg, method='iir', n_jobs=8) # raw.filter(l_freq = l_freq, h_freq = h_freq, picks = picks_meeg, # method='iir') # raw.resample(sfreq=down_sfreq, npad=0) ### 1) Fit ICA model using the FastICA algorithm # Other available choices are `infomax` or `extended-infomax` # We pass a float value between 0 and 1 to select n_components based on the # percentage of variance explained by the PCA components. ICA_title = 'Sources related to %s artifacts (red)' is_show = False # visualization reject = dict(mag=4e-12, grad=4000e-13) # check if we have an ICA, if yes, we load it ica_filename = os.path.join(subj_path,basename + "-ica.fif") if os.path.exists(ica_filename) is False: ica = ICA(n_components=variance, method='fastica', max_iter=500) # , max_iter=500 ica.fit(raw, picks=select_sensors, reject=reject) # decim = 3, has_ICA = False else: has_ICA = True print ica_filename + ' exists!!!' ica = read_ica(ica_filename) ica.exclude = [] # 2) identify bad components by analyzing latent sources. # generate ECG epochs use detection via phase statistics # if we just have exclude channels we jump these steps # if len(ica.exclude)==0: n_max_ecg = 3 n_max_eog = 2 # check if ECG_ch_name is in the raw channels if ECG_ch_name in raw.info['ch_names']: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=ECG_ch_name) # if not a synthetic ECG channel is created from cross channel average else: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors) # ICA for ECG artifact # threshold=0.25 come default ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') print scores print '\n len ecg_inds *** ' + str(len(ecg_inds)) + '***\n' if len(ecg_inds) > 0: ecg_evoked = ecg_epochs.average() fig1 = ica.plot_scores(scores, exclude=ecg_inds, title=ICA_title % 'ecg', show=is_show) show_picks = np.abs(scores).argsort()[::-1][:5] # Pick the five largest scores and plot them # Plot estimated latent sources given the unmixing matrix. #ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=ICA_title % 'ecg', show=is_show) t_start = 0 t_stop = 30 # take the fist 30s fig2 = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=ICA_title % 'ecg' + ' in 30s' ,start = t_start, stop = t_stop, show=is_show) # topoplot of unmixing matrix columns fig3 = ica.plot_components(show_picks, title=ICA_title % 'ecg', colorbar=True, show=is_show) ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds fig4 = ica.plot_sources(ecg_evoked, exclude=ecg_inds, show=is_show) # plot ECG sources + selection fig5 = ica.plot_overlay(ecg_evoked, exclude=ecg_inds, show=is_show) # plot ECG cleaning fig = [fig1, fig2, fig3, fig4, fig5] report.add_figs_to_section(fig, captions=['Scores of ICs related to ECG', 'Time Series plots of ICs (ECG)', 'TopoMap of ICs (ECG)', 'Time-locked ECG sources', 'ECG overlay'], section = 'ICA - ECG') # check if EoG_ch_name is in the raw channels # if EoG_ch_name is empty if data_type is fif, ICA routine automatically looks for EEG61, EEG62 # otherwise if data_type is ds we jump this step if not EoG_ch_name and data_type=='ds': eog_inds = [] else: if EoG_ch_name in raw.info['ch_names']: ### ICA for eye blink artifact - detect EOG by correlation eog_inds, scores = ica.find_bads_eog(raw, ch_name = EoG_ch_name) else: eog_inds, scores = ica.find_bads_eog(raw) if len(eog_inds) > 0: fig6 = ica.plot_scores(scores, exclude=eog_inds, title=ICA_title % 'eog', show=is_show) report.add_figs_to_section(fig6, captions=['Scores of ICs related to EOG'], section = 'ICA - EOG') # check how many EoG ch we have rs = np.shape(scores) if len(rs)>1: rr = rs[0] show_picks = [np.abs(scores[i][:]).argsort()[::-1][:5] for i in range(rr)] for i in range(rr): fig7 = ica.plot_sources(raw, show_picks[i][:], exclude=eog_inds, start = raw.times[0], stop = raw.times[-1], title=ICA_title % 'eog',show=is_show) fig8 = ica.plot_components(show_picks[i][:], title=ICA_title % 'eog', colorbar=True, show=is_show) # ICA nel tempo fig = [fig7, fig8] report.add_figs_to_section(fig, captions=['Scores of ICs related to EOG', 'Time Series plots of ICs (EOG)'], section = 'ICA - EOG') else: show_picks = np.abs(scores).argsort()[::-1][:5] fig7 = ica.plot_sources(raw, show_picks, exclude=eog_inds, title=ICA_title % 'eog', show=is_show) fig8 = ica.plot_components(show_picks, title=ICA_title % 'eog', colorbar=True, show=is_show) fig = [fig7, fig8] report.add_figs_to_section(fig, captions=['Time Series plots of ICs (EOG)', 'TopoMap of ICs (EOG)',], section = 'ICA - EOG') eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds if EoG_ch_name in raw.info['ch_names']: eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=EoG_ch_name).average() else: eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors).average() fig9 = ica.plot_sources(eog_evoked, exclude=eog_inds, show=is_show) # plot EOG sources + selection fig10 = ica.plot_overlay(eog_evoked, exclude=eog_inds, show=is_show) # plot EOG cleaning fig = [fig9, fig10] report.add_figs_to_section(fig, captions=['Time-locked EOG sources', 'EOG overlay'], section = 'ICA - EOG') fig11 = ica.plot_overlay(raw, show=is_show) report.add_figs_to_section(fig11, captions=['Signal'], section = 'Signal quality') ### plot all topographies and time seris of the ICA components n_ica_components = ica.mixing_matrix_.shape[1] n_topo = 10; n_fig = n_ica_components/n_topo; n_plot = n_ica_components%n_topo; print '*************** n_fig = ' + str(n_fig) + ' n_plot = ' + str(n_plot) + '********************' fig = [] t_start = 0 t_stop = None # 60 if we want to take the fist 60s for n in range(0,n_fig): fig_tmp = ica.plot_components(range(n_topo*n,n_topo*(n+1)),title='ICA components', show=is_show) fig.append(fig_tmp) fig_tmp = ica.plot_sources(raw, range(n_topo*n,n_topo*(n+1)), start = t_start, stop = t_stop, title='ICA components') fig.append(fig_tmp) # if n_plot > 0: # fig_tmp = ica.plot_components(range(n_fig*n_topo,n_ica_components), title='ICA components', show=is_show) # fig.append(fig_tmp) # fig_tmp = ica.plot_sources(raw, range(n_fig*n_topo,n_ica_components), # start = t_start, stop = t_stop, # title='ICA components') # fig.append(fig_tmp) # # for n in range(0, len(fig)): # report.add_figs_to_section(fig[n], captions=['TOPO'], section = 'ICA Topo Maps') if n_plot > 5: n_fig_l = n_plot//5 print '*************************** ' + str(n_fig_l) + ' *********************************' for n in range(0,n_fig_l): print range(n_fig*n_topo+5*n, n_fig*n_topo+5*(n+1)) fig_tmp = ica.plot_components(range(n_fig*n_topo+5*n, n_fig*n_topo+5*(n+1)),title='ICA components') fig.append(fig_tmp) fig_tmp = ica.plot_sources(raw, range(n_fig*n_topo+5*n, n_fig*n_topo+5*(n+1)), start = t_start, stop = t_stop, title='ICA components') fig.append(fig_tmp) print range(n_fig*n_topo+5*(n+1),n_ica_components) fig_tmp = ica.plot_components(range(n_fig*n_topo+5*(n+1),n_ica_components), title='ICA components') fig.append(fig_tmp) fig_tmp = ica.plot_sources(raw, range(n_fig*n_topo+5*(n+1),n_ica_components), start = t_start, stop = t_stop, title='ICA components') fig.append(fig_tmp) for n in range(0, len(fig)): report.add_figs_to_section(fig[n], captions=['TOPO'], section = 'ICA Topo Maps') report_filename = os.path.join(subj_path,basename + "-report.html") print '******* ' + report_filename report.save(report_filename, open_browser=False, overwrite=True) # 3) apply ICA to raw data and save solution and report # check the amplitudes do not change # raw_ica_file = os.path.abspath(basename[:i_raw] + 'ica-raw.fif') raw_ica_file = os.path.join(subj_path, basename + '-preproc-raw.fif') raw_ica = ica.apply(raw) raw_ica.resample(sfreq=down_sfreq, npad=0) raw_ica.save(raw_ica_file, overwrite=True) # save ICA solution print ica_filename if has_ICA is False: ica.save(ica_filename) # 4) save data data_noIca, times = raw[select_sensors, :] data, times = raw_ica[select_sensors, :] print data.shape print raw.info['sfreq'] ts_file = os.path.abspath(basename + "_ica.npy") np.save(ts_file, data) print '***** TS FILE ' + ts_file + '*****' if is_sensor_space: return ts_file, channel_coords_file, channel_names_file, raw.info['sfreq'] else: # return raw_ica, channel_coords_file, channel_names_file, raw.info['sfreq'] return raw_ica_file, channel_coords_file, channel_names_file, raw.info['sfreq']
# # License: BSD (3-clause) import mne from mne.io import Raw from mne.preprocessing import ICA, create_ecg_epochs from mne.datasets import sample print(__doc__) ############################################################################### # Fit ICA model using the FastICA algorithm, detect and inspect components data_path = sample.data_path() raw_fname = data_path + "/MEG/sample/sample_audvis_filt-0-40_raw.fif" raw = Raw(raw_fname, preload=True) raw.filter(1, 30, method="iir") raw.pick_types(meg=True, eeg=False, exclude="bads", stim=True) # longer + more epochs for more artifact exposure events = mne.find_events(raw, stim_channel="STI 014") epochs = mne.Epochs(raw, events, event_id=None, tmin=-0.2, tmax=0.5) ica = ICA(n_components=0.95, method="fastica").fit(epochs) ecg_epochs = create_ecg_epochs(raw, tmin=-0.5, tmax=0.5) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs) ica.plot_components(ecg_inds)
random_state=25) #,method='infomax') ica.fit(ep, picks=our_picks) eog_ic = [] for ch in [ 'E25', 'E17', 'E8', 'E21', 'E14', 'E125', 'E126', 'E127', 'E128' ]: #insert EOG channels eog_idx, scores = ica.find_bads_eog(ep, ch_name=ch) eog_ic.append(eog_idx) print(eog_ic) ecg_ic = [] for ch in []: # insert ECG channels ecg_idx, scores = ica.find_bads_ecg(ep, ch_name=ch) ecg_ic.append(ecg_idx) print(ecg_ic) reject_ic = [] for eog_inds in eog_ic: for ele in eog_inds: if (ele not in reject_ic) and (ele < 35): reject_ic.append(ele) for ecg_inds in ecg_ic: for ele in ecg_inds: if (ele not in reject_ic) and (ele < 35): reject_ic.append(ele) print(reject_ic)
def runICA(raw,saveRoot,name): saveRoot = saveRoot icaList = [] ica = [] n_max_ecg = 3 # max number of ecg components # n_max_eog_1 = 2 # max number of vert eog comps # n_max_eog_2 = 2 # max number of horiz eog comps ecg_source_idx, ecg_scores, ecg_exclude = [], [], [] eog_source_idx, eog_scores, eog_exclude = [], [], [] #horiz = 1 # will later be modified to horiz = 0 if no horizontal EOG components are identified ica = ICA(n_components=0.90,n_pca_components=64,max_pca_components=100,noise_cov=None) ica.fit(raw) #************* eog_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, eog=True, ecg=False, emg=False)[0] ecg_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, ecg=True, eog=False, emg=False)[0] ica_picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, ecg=False, stim=False, exclude='bads') ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks) ecg_evoked = ecg_epochs.average() eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks).average() ecg_source_idx, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps') eog_source_idx, eog_scores = ica.find_bads_eog(raw,ch_name=raw.ch_names[eog_picks].encode('ascii', 'ignore')) # defining a title-frame for later use title = 'Sources related to %s artifacts (red)' # extracting number of ica-components and plotting their topographies source_idx = range(0, ica.n_components_) ica_plot = ica.plot_components(source_idx, ch_type="mag") # select ICA sources and reconstruct MEG signals, compute clean ERFs # Add detected artefact sources to exclusion list # We now add the eog artefacts to the ica.exclusion list if not ecg_source_idx: print("No ECG components above threshold were identified for subject " + name + " - selecting the component with the highest score under threshold") ecg_exclude = [np.absolute(ecg_scores).argmax()] ecg_source_idx=[np.absolute(ecg_scores).argmax()] elif ecg_source_idx: ecg_exclude += ecg_source_idx[:n_max_ecg] ica.exclude += ecg_exclude if not eog_source_idx: if np.absolute(eog_scores).any>0.3: eog_exclude=[np.absolute(eog_scores).argmax()] eog_source_idx=[np.absolute(eog_scores).argmax()] print("No EOG components above threshold were identified " + name + " - selecting the component with the highest score under threshold above 0.3") elif not np.absolute(eog_scores).any>0.3: eog_exclude=[] print("No EOG components above threshold were identified" + name) elif eog_source_idx: eog_exclude += eog_source_idx ica.exclude += eog_exclude print('########## saving') if len(eog_exclude) == 0: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') elif len(eog_exclude) == 1: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') elif len(eog_exclude) == 2: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') # plot the scores for the different components highlighting in red that/those related to ECG scores_plots_ecg=ica.plot_scores(ecg_scores, exclude=ecg_source_idx, title=title % 'ecg') scores_plots_ecg.savefig(saveRoot + name + '_ecg_scores.pdf', format = 'pdf') scores_plots_eog=ica.plot_scores(eog_scores, exclude=eog_source_idx, title=title % 'eog') scores_plots_eog.savefig(saveRoot + name + '_eog_scores.pdf', format = 'pdf') source_source_ecg=ica.plot_sources(ecg_evoked, exclude=ecg_source_idx) source_source_ecg.savefig(saveRoot + name + '_ecg_source.pdf', format = 'pdf') #ax = plt.subplot(2,1,2) source_clean_ecg=ica.plot_overlay(ecg_evoked, exclude=ecg_source_idx) source_clean_ecg.savefig(saveRoot + name + '_ecg_clean.pdf', format = 'pdf') #clean_plot.savefig(saveRoot + name + '_ecg_clean.pdf', format = 'pdf') #if len(eog_exclude) > 0: source_source_eog=ica.plot_sources(eog_evoked, exclude=eog_source_idx) source_source_eog.savefig(saveRoot + name + '_eog_source.pdf', format = 'pdf') source_clean_eog=ica.plot_overlay(eog_evoked, exclude=eog_source_idx) source_clean_eog.savefig(saveRoot + name + '_eog_clean.pdf', format = 'pdf') overl_plot = ica.plot_overlay(raw) overl_plot.savefig(saveRoot + name + '_overl.pdf', format = 'pdf') event_id = 999 ecg_events, _, _ = mne.preprocessing.find_ecg_events(raw, event_id, ch_name=raw.ch_names[ecg_picks].encode('UTF8')) picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, ecg=True) tmin, tmax = -0.1, 0.1 epochs_ecg = mne.Epochs(raw, ecg_events, event_id, tmin, tmax,picks=picks) data_ecg = epochs_ecg.get_data() event_id = 998 eog_events = mne.preprocessing.find_eog_events(raw, event_id, ch_name=raw.ch_names[eog_picks].encode('UTF8')) picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, eog=True, exclude='bads') tmin, tmax = -0.5, 0.5 epochs_eog = mne.Epochs(raw, eog_events, event_id, tmin, tmax,picks=[picks[0]])#, data_eog = epochs_eog.get_data() plSize = 1 pltRes = 128 ecg_eogAvg=plt.figure(figsize=(20,10)) ax = plt.subplot(2,3,1) plt.plot(1e3 * epochs_ecg.times, np.squeeze(data_ecg).T) plt.xlabel('Times (ms)') plt.title('ECG') plt.ylabel('ECG') plt.show() ax2 = plt.subplot(2,3,2) plot_evoked_topomap(ecg_evoked, times=0, average=0.02, ch_type='mag',colorbar=False, size=plSize, res=pltRes, axes=ax2) ax3= plt.subplot(2,3,3) plot_evoked_topomap(ecg_evoked, times=0, average=0.02, ch_type='grad',colorbar=False, size=plSize, res=pltRes, axes=ax3) ax = plt.subplot(2,3,4) plt.plot(1e3 * epochs_eog.times, np.squeeze(data_eog).T) plt.xlabel('Times (ms)') plt.title('EOG') plt.ylabel('EOG') ax = plt.subplot(2,3,5) plot_evoked_topomap(eog_evoked, times=0, average=0.05, ch_type='mag',colorbar=False, size=plSize, res=pltRes, axes=ax) ax = plt.subplot(2,3,6) plot_evoked_topomap(eog_evoked, times=0, average=0.05, ch_type='grad',colorbar=False, size=plSize, res=pltRes, show=False, axes=ax) plt.tight_layout() ecg_eogAvg.savefig(saveRoot + name +'_ecg_eog_Avg.pdf',format = 'pdf') plt.close('all') ## restore sensor space data icaList = ica.apply(raw) return(icaList, ica)
def main(fname): from mne import pick_types from sys import argv from mne.io import read_raw_fif from mne.preprocessing import ICA, create_eog_epochs, create_ecg_epochs import numpy as np import matplotlib.pyplot as plt #%% parameters #fname=argv[1] reject_ica = {'mag': 6e-12, 'grad': 6e-10} #ecg_ch='MEG0141' #%% read and filter data Raw = read_raw_fif(fname, preload=True) Raw.filter(1, 40, fir_design='firwin') #Events=find_events(Raw, min_duration=0.003) #%% run ICA for automatic ocular & cardiac rejection (plot the rejected topos) picks_ica = pick_types(Raw.info, meg=True) ica = ICA(n_components=0.98, method='fastica') ica.fit(Raw, picks=picks_ica, reject=reject_ica, decim=4) ecg_epochs = create_ecg_epochs( Raw, reject=reject_ica ) # ch_name='MEG0111') # find the ECG events automagically eog_epochs = create_eog_epochs( Raw, reject=reject_ica) # find the EOG events automagically #ecg_epochs.average().plot_joint(times=0) #eog_epochs.average().plot_joint(times=0) ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps') print(ecg_inds) eog_inds, eog_scores = ica.find_bads_eog(eog_epochs) print(eog_inds) #ica.plot_overlay(ecg_average, exclude=ecg_inds) # does not work? try: ica.plot_components(ch_type='mag', picks=ecg_inds, title=fname, show=False) except IndexError as exc: pass except ValueError as exc: pass try: ica.plot_components(ch_type='mag', picks=eog_inds, title=fname, show=False) except IndexError as exc: pass except ValueError as exc: pass plt.show(block=False) ica.exclude.extend(eog_inds) ica.exclude.extend(ecg_inds) # Save changes to the data: #Raw.copy().crop(10,20).plot() Raw = ica.apply(Raw) #Raw.copy().crop(10,20).plot() #Raw=ica.apply(Raw,exclude=[eog_inds]) # list of the ICA components to exclude!!! return Raw, ica
ica = ICA(n_components=90, random_state=25) ica.fit(eyes_open, picks=our_picks_EO) eog_ic = [] for ch in [ 'E25', 'E17', 'E8', 'E21', 'E14', 'E125', 'E126', 'E127', 'E128' ]: #insert EOG channels eog_idx, scores = ica.find_bads_eog(eyes_open, ch_name=ch) eog_ic.append(eog_idx) print(eog_ic) ecg_ic = [] for ch in []: # insert ECG channels ecg_idx, scores = ica.find_bads_ecg(eyes_open, ch_name=ch) ecg_ic.append(ecg_idx) print(ecg_ic) reject_ic = [] for eog_inds in eog_ic: for ele in eog_inds: if ele not in reject_ic: reject_ic.append(ele) for ecg_inds in ecg_ic: for ele in ecg_inds: if el not in reject_ic: reject_ic.append(el) print(reject_ic)
raw = raw_notch_BPF picks = mne.pick_types(raw.info, meg=True, eeg=True, eog=True, stim=False) ica = ICA(n_components=n_components, method=method) reject = dict(grad=200e-12, mag=4e-12) ica.fit(raw, picks=picks, decim=decim, reject=reject) eog_epochs = create_eog_epochs(raw) ecg_epochs = create_ecg_epochs(raw, reject=reject) eog_inds, scores_eog = ica.find_bads_eog(eog_epochs) ecg_inds, scores_ecg = ica.find_bads_ecg(ecg_epochs) eog_inds = eog_inds[:n_max_eog] ecg_inds = ecg_inds[:n_max_ecg] # eog_inds = [0,40] ica.exclude += eog_inds ica.exclude += ecg_inds ica.apply(inst=raw, exclude=eog_inds) ica.apply(inst=raw, exclude=ecg_inds) #pick_av = np.abs((scores_eog[0]+scores_eog[1])/2).argsort()[::-1][:5] #pick_0 = np.abs(scores_eog[0]).argsort()[::-1][:5] #pick_1 = np.abs(scores_eog[1]).argsort()[::-1][:5]
def camcan_preproc(subject): data_folder = '/Users/work/camcan' data_file = os.path.join(data_folder, subject, '_ses-rest_task-rest_proc-raw.fif') #data_file = os.path.join(data_folder, # 'sub-CC _ses-rest_task-rest_proc-raw_sss.fif') report = mne.Report(verbose=True) report.save('report_basic.html', overwrite=True) # read file raw = mne.io.read_raw_fif(data_file, preload=True) print(raw.info) fig = raw.plot_psd(fmax=50, show=False) report.add_figs_to_section(fig, captions='Raw', section='PSD') meg_channels = mne.pick_types(raw.info, meg=True, stim=False, ref_meg=False) eog1 = mne.pick_channels(raw.ch_names, ['EOG061']) eog2 = mne.pick_channels(raw.ch_names, ['EOG062']) ecg = mne.pick_channels(raw.ch_names, ['ECG063']) mag_channels = mne.pick_types(raw.info, meg='mag') # Bandpass between 1 and 45 Hz, bandstop between 50 and 100 raw.filter(1, 45) freqs = (50, 100) raw.notch_filter(freqs=freqs) fig = raw.plot_psd(fmax=50, show=False) report.add_figs_to_section(fig, captions='After bandpass and notch filters', section='PSD') # 2s epochs events = mne.make_fixed_length_events(raw, start=0, stop=None, duration=2.0, overlap=0) reject = dict(grad=4000e-13, mag=4e-12, eog=250e-6) #from mne tutorial epochs = mne.Epochs(raw, events, baseline=None, preload=True, reject=reject) # Topoplot before ICA fig = epochs.plot_psd_topomap(ch_type='mag', normalize=True, show=False) report.add_figs_to_section(fig, captions='Topoplot before ICA', section='Topoplots') # ICA to remove artefacts from mne.preprocessing import ICA, create_ecg_epochs, create_eog_epochs ica = ICA(n_components=0.95, method='fastica').fit(epochs) fig = ica.plot_components(show=False) ica.exclude = [] report.add_figs_to_section(fig, captions=('ICA components', ' '), section='ICA') # Find ECG artefacts ecg_epochs = create_ecg_epochs(raw) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, threshold='auto') fig = ica.plot_components(ecg_inds, show=False) ica.exclude += ecg_inds report.add_figs_to_section(fig, captions='ECG components', section='ICA') # Find EOG artefacts eog_epochs = create_eog_epochs(raw, tmin=-.5, tmax=.5) eog_inds, scores = ica.find_bads_eog(eog_epochs) fig = ica.plot_components(eog_inds, show=False) ica.exclude += eog_inds report.add_figs_to_section(fig, captions='EOG components', section='ICA') # Apply ICA cleaned = epochs.copy() ica.apply(cleaned) fig = cleaned.plot_psd_topomap(ch_type='mag', normalize=True, show=False) report.add_figs_to_section(fig, captions='Topoplot after artefact rejection', section='Preprocessed') report.save('report.html', overwrite=True) # save fif file clean_file = os.path.join(data_folder, subject, '_cleaned.fif') cleaned.save(clean_file, overwrite=True)
def compute_ica(raw, subject, n_components=0.99, picks=None, decim=None, reject=None, ecg_tmin=-0.5, ecg_tmax=0.5, eog_tmin=-0.5, eog_tmax=0.5, n_max_ecg=3, n_max_eog=1, n_max_ecg_epochs=200, img_scale=1.0, report=None): """Run ICA in raw data Parameters ----------, raw : instance of Raw Raw measurements to be decomposed. subject : str The name of the subject. picks : array-like of int, shape(n_channels, ) | None Channels to be included. This selection remains throughout the initialized ICA solution. If None only good data channels are used. Defaults to None. n_components : int | float | None | 'rank' The number of components used for ICA decomposition. If int, it must be smaller then max_pca_components. If None, all PCA components will be used. If float between 0 and 1 components can will be selected by the cumulative percentage of explained variance. If 'rank', the number of components equals the rank estimate. Defaults to 0.99. decim : int | None Increment for selecting each nth time slice. If None, all samples within ``start`` and ``stop`` are used. Defalts to None. reject : dict | None Rejection parameters based on peak to peak amplitude. Valid keys are 'grad' | 'mag' | 'eeg' | 'eog' | 'ecg'. If reject is None then no rejection is done. You should use such parameters to reject big measurement artifacts and not EOG for example. It only applies if `inst` is of type Raw. Defaults to {'mag': 5e-12} ecg_tmin : float Start time before ECG event. Defaults to -0.5. ecg_tmax : float End time after ECG event. Defaults to 0.5. eog_tmin : float Start time before rog event. Defaults to -0.5. eog_tmax : float End time after rog event. Defaults to 0.5. n_max_ecg : int | None The maximum number of ECG components to exclude. Defaults to 3. n_max_eog : int | None The maximum number of EOG components to exclude. Defaults to 1. n_max_ecg_epochs : int The maximum number of ECG epochs to use for phase-consistency estimation. Defaults to 200. scale_img : float The scaling factor for the report. Defaults to 1.0. report : instance of Report | None The report object. If None, a new report will be generated. Returns ------- ica : isntance of ICA The ICA solution. report : instance of Report The report object. """ if report is None: report = Report(subject=subject, title='ICA preprocessing') if n_components == 'rank': n_components = raw.estimate_rank(picks=picks) ica = ICA(n_components=n_components, max_pca_components=None, max_iter=256) ica.fit(raw, picks=picks, decim=decim, reject=reject) comment = [] for ch in ('mag', 'grad', 'eeg'): if ch in ica: comment += [ch.upper()] if len(comment) > 0: comment = '+'.join(comment) + ' ' else: comment = '' topo_ch_type = 'mag' if 'GRAD' in comment and 'MAG' not in comment: topo_ch_type = 'grad' elif 'EEG' in comment: topo_ch_type = 'eeg' ############################################################################ # 2) identify bad components by analyzing latent sources. title = '%s related to %s artifacts (red) ({})'.format(subject) # generate ECG epochs use detection via phase statistics ecg_epochs = create_ecg_epochs(raw, tmin=ecg_tmin, tmax=ecg_tmax, picks=None, reject={'mag': 5e-12}) n_ecg_epochs_found = len(ecg_epochs.events) n_max_ecg_epochs = min(n_max_ecg_epochs, n_ecg_epochs_found) sel_ecg_epochs = np.arange(n_ecg_epochs_found) rng = np.random.RandomState(42) rng.shuffle(sel_ecg_epochs) ecg_epochs = ecg_epochs[sel_ecg_epochs[:n_max_ecg_epochs]] ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') if len(ecg_inds) > 0: ecg_evoked = ecg_epochs.average(picks=picks) del ecg_epochs fig = ica.plot_scores(scores, exclude=ecg_inds, title=title % ('scores', 'ecg')) report.add_figs_to_section(fig, 'scores ({})'.format(subject), section=comment + 'ECG', scale=img_scale) fig = ica.plot_sources(raw, ecg_inds, exclude=ecg_inds, title=title % ('components', 'ecg')) report.add_figs_to_section(fig, 'sources ({})'.format(subject), section=comment + 'ECG', scale=img_scale) fig = ica.plot_components(ecg_inds, ch_type=topo_ch_type, title='', colorbar=True) report.add_figs_to_section(fig, title % ('sources', 'ecg'), section=comment + 'ECG', scale=img_scale) ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds fig = ica.plot_sources(ecg_evoked, exclude=ecg_inds) report.add_figs_to_section(fig, 'evoked sources ({})'.format(subject), section=comment + 'ECG', scale=img_scale) fig = ica.plot_overlay(ecg_evoked, exclude=ecg_inds) report.add_figs_to_section(fig, 'rejection overlay ({})'.format(subject), section=comment + 'ECG', scale=img_scale) # detect EOG by correlation eog_inds, scores = ica.find_bads_eog(raw) if len(eog_inds) > 0: fig = ica.plot_scores(scores, exclude=eog_inds, title=title % ('scores', 'eog')) report.add_figs_to_section(fig, 'scores ({})'.format(subject), section=comment + 'EOG', scale=img_scale) fig = ica.plot_sources(raw, eog_inds, exclude=ecg_inds, title=title % ('sources', 'eog')) report.add_figs_to_section(fig, 'sources', section=comment + 'EOG', scale=img_scale) fig = ica.plot_components(eog_inds, ch_type=topo_ch_type, title='', colorbar=True) report.add_figs_to_section(fig, title % ('components', 'eog'), section=comment + 'EOG', scale=img_scale) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds # estimate average artifact eog_evoked = create_eog_epochs(raw, tmin=eog_tmin, tmax=eog_tmax, picks=None).average(picks=picks) fig = ica.plot_sources(eog_evoked, exclude=eog_inds) report.add_figs_to_section(fig, 'evoked sources ({})'.format(subject), section=comment + 'EOG', scale=img_scale) fig = ica.plot_overlay(eog_evoked, exclude=eog_inds) report.add_figs_to_section(fig, 'rejection overlay({})'.format(subject), section=comment + 'EOG', scale=img_scale) # check the amplitudes do not change if len(ica.exclude) > 0: fig = ica.plot_overlay(raw) # EOG artifacts remain report.add_figs_to_section(fig, 'rejection overlay({})'.format(subject), section=comment + 'RAW', scale=img_scale) return ica, report
# bipolar reference from frontal EEG sensors and use that as virtual EOG # channel. This carries a risk however: you must hope that the frontal EEG # channels only reflect EOG and not brain dynamics in the prefrontal cortex (or # you must not care about those prefrontal signals). # # For ECG, it is easier: :meth:`~mne.preprocessing.ICA.find_bads_ecg` can use # cross-channel averaging of magnetometer or gradiometer channels to construct # a virtual ECG channel, so if you have MEG channels it is usually not # necessary to pass a specific channel name. # :meth:`~mne.preprocessing.ICA.find_bads_ecg` also has two options for its # ``method`` parameter: ``'ctps'`` (cross-trial phase statistics [3]_) and # ``'correlation'`` (Pearson correlation between data and ECG channel). ica.exclude = [] # find which ICs match the ECG pattern ecg_indices, ecg_scores = ica.find_bads_ecg(raw, method='correlation') ica.exclude = ecg_indices # barplot of ICA component "ECG match" scores ica.plot_scores(ecg_scores) # plot diagnostics ica.plot_properties(raw, picks=ecg_indices) # plot ICs applied to raw data, with ECG matches highlighted ica.plot_sources(raw) # plot ICs applied to the averaged ECG epochs, with ECG matches highlighted ica.plot_sources(ecg_evoked) ###############################################################################
def autodenoise_MEG(subject, run): ############################################################################### import numpy as np import mne import os.path as op import os import matplotlib matplotlib.use('Agg') from mne.report import Report from mne.io import Raw from mne.preprocessing import ICA from mne.preprocessing import create_ecg_epochs, create_eog_epochs data_path = '/neurospin/meg/meg_tmp/MTT_MEG_Baptiste/MEG/' raw_fname = data_path + subject + '/' + run + '_trans_sss.fif' # ICA report = Report(subject) raw = Raw(raw_fname, preload=True) raw.filter(None, 30, n_jobs=4) picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') ica = ICA(n_components=0.95, method='fastica') ica.fit(raw, picks=picks, decim=4) # maximum number of components to reject n_max_ecg, n_max_eogv, n_max_eogh = 3, 3, 3 title = 'Sources related to %s artifacts (red)' # Create the results directory if it doesn't exist results_dir = op.join(data_path, subject, 'artefactICA') if not op.exists(results_dir): os.makedirs(results_dir) #ica_fname = '%s_ica' % (subject) ############################################################################### # generate ECG epochs use detection via phase statistics ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=picks) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') fig1 = ica.plot_scores(scores, exclude=ecg_inds, title=title % 'ecg', labels='ecg') report.add_figs_to_section(fig1, captions='ECGcomp', section='ICA') show_picks = np.abs(scores).argsort()[::-1][:5] fig2 = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % 'ecg') report.add_figs_to_section(fig2, captions='ECGcomptime', section='ICA') fig3 = ica.plot_components(ecg_inds, title=title % 'ecg', colorbar=True) report.add_figs_to_section(fig3, captions='ECGcomptopo', section='ICA') ecg_inds = ecg_inds[:n_max_ecg] report.save((results_dir + '/' + run + '.html'), open_browser=False, overwrite=True) ############################################################################### # detect vertical EOG by correlation eogv_inds = [] eogv_inds, scores = ica.find_bads_eog(raw, ch_name='EOG061') fig4 = ica.plot_scores(scores, exclude=eogv_inds, title=title % 'eogv', labels='ecg') report.add_figs_to_section(fig4, captions='EOGvcomp', section='ICA') show_picks = np.abs(scores).argsort()[::-1][:5] fig5 = ica.plot_sources(raw, show_picks, exclude=eogv_inds, title=title % 'eogv') report.add_figs_to_section(fig5, captions='EOGvcomptime', section='ICA') fig6 = ica.plot_components(eogv_inds, title=title % 'eogv', colorbar=True) report.add_figs_to_section(fig6, captions='EOGvcomptopo', section='ICA') eogv_inds = eogv_inds[:n_max_eogv] report.save((results_dir + '/' + run + '.html'), open_browser=False, overwrite=True) ############################################################################### # detect horizontal EOG by correlation eogh_inds = [] eogh_inds, scores = ica.find_bads_eog(raw, ch_name='EOG062') fig7 = ica.plot_scores(scores, exclude=eogh_inds, title=title % 'eogh', labels='ecg') report.add_figs_to_section(fig7, captions='EOGhcomp', section='ICA') show_picks = np.abs(scores).argsort()[::-1][:5] fig8 = ica.plot_sources(raw, show_picks, exclude=eogh_inds, title=title % 'eogh') report.add_figs_to_section(fig8, captions='EOGhcomptime', section='ICA') fig9 = ica.plot_components(eogh_inds, title=title % 'eogh', colorbar=True) report.add_figs_to_section(fig9, captions='EOGhcomptopo', section='ICA') eogh_inds = eogh_inds[:n_max_eogh] report.save((results_dir + '/' + run + '.html'), open_browser=False, overwrite=True) ############################################################################### # estimate average artifact ecg_evoked = ecg_epochs.average() fig10 = ica.plot_sources(ecg_evoked, exclude=ecg_inds) # plot ECG sources + selection fig11 = ica.plot_overlay(ecg_evoked, exclude=ecg_inds) # plot ECG cleaning report.add_figs_to_section(fig10, captions='ECG sources', section='ICA') report.add_figs_to_section(fig11, captions='ECG clean', section='ICA') eogv_evoked = create_eog_epochs(raw, tmin=-.5, ch_name='EOG061', tmax=.5, picks=picks).average() fig12 = ica.plot_sources(eogv_evoked, exclude=eogv_inds) # plot EOG sources + selection fig13 = ica.plot_overlay(eogv_evoked, exclude=eogv_inds) # plot EOG cleaning report.add_figs_to_section(fig12, captions='EOGv sources', section='ICA') report.add_figs_to_section(fig13, captions='EOGv clean', section='ICA') eogh_evoked = create_eog_epochs(raw, tmin=-.5, ch_name='EOG062', tmax=.5, picks=picks).average() fig14 = ica.plot_sources(eogh_evoked, exclude=eogh_inds) # plot EOG sources + selection fig15 = ica.plot_overlay(eogh_evoked, exclude=eogh_inds) # plot EOG cleaning report.add_figs_to_section(fig14, captions='EOGh sources', section='ICA') report.add_figs_to_section(fig15, captions='EOGh clean', section='ICA') # check the amplitudes do not change fig16 = ica.plot_overlay(raw) # EOG artifacts remain report.add_figs_to_section(fig16, captions='avg', section='ICA') ############################################################################### # Create the results directory if it doesn't exist ica_dir = op.join(data_path, subject, 'mne_python/ICA') if not op.exists(ica_dir): os.makedirs(ica_dir) # mark bad components and save ica artifact_inds = list(np.unique(eogv_inds + eogh_inds + ecg_inds)) ica.exclude = [] ica.exclude = artifact_inds ica.save((ica_dir + '/ICA_MEG' + run))
def runICA(raw, saveRoot, name): saveRoot = saveRoot icaList = [] ica = [] n_max_ecg = 3 # max number of ecg components # n_max_eog_1 = 2 # max number of vert eog comps # n_max_eog_2 = 2 # max number of horiz eog comps ecg_source_idx, ecg_scores, ecg_exclude = [], [], [] eog_source_idx, eog_scores, eog_exclude = [], [], [] #horiz = 1 # will later be modified to horiz = 0 if no horizontal EOG components are identified ica = ICA(n_components=0.90, n_pca_components=64, max_pca_components=100, noise_cov=None) fit_picks = mne.pick_types(raw.info, meg=True, eeg=True, eog=False, ecg=False, stim=False, exclude='bads') ica.fit(raw, picks=fit_picks) #ica.fit(raw) #************* eog_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, eog=True, ecg=False, emg=False)[0] ecg_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, ecg=True, eog=False, emg=False)[0] ica_picks = mne.pick_types(raw.info, meg=True, eeg=True, eog=False, ecg=False, stim=False, exclude='bads') ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks) ecg_evoked = ecg_epochs.average() eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks).average() ecg_source_idx, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps') eog_source_idx, eog_scores = ica.find_bads_eog( raw, ch_name=raw.ch_names[eog_picks].encode('ascii', 'ignore')) #eog_source_idx_2, eog_scores_2 = ica.find_bads_eog(raw,ch_name='EOG002') #if not eog_source_idx_2: # horiz = 0 #show_picks = np.abs(scores).argsort()[::-1][:5] #ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % 'ecg') # defining a title-frame for later use title = 'Sources related to %s artifacts (red)' # extracting number of ica-components and plotting their topographies source_idx = range(0, ica.n_components_) #ica_plot = ica.plot_components(source_idx, ch_type="mag") ica_plot = ica.plot_components(source_idx) #ica_plot = ica.plot_components(source_idx) # select ICA sources and reconstruct MEG signals, compute clean ERFs # Add detected artefact sources to exclusion list # We now add the eog artefacts to the ica.exclusion list if not ecg_source_idx: print( "No ECG components above threshold were identified for subject " + name + " - selecting the component with the highest score under threshold" ) ecg_exclude = [np.absolute(ecg_scores).argmax()] ecg_source_idx = [np.absolute(ecg_scores).argmax()] elif ecg_source_idx: ecg_exclude += ecg_source_idx[:n_max_ecg] ica.exclude += ecg_exclude if not eog_source_idx: if np.absolute(eog_scores).any > 0.3: eog_exclude = [np.absolute(eog_scores).argmax()] eog_source_idx = [np.absolute(eog_scores).argmax()] print( "No EOG components above threshold were identified " + name + " - selecting the component with the highest score under threshold above 0.3" ) elif not np.absolute(eog_scores).any > 0.3: eog_exclude = [] print("No EOG components above threshold were identified" + name) elif eog_source_idx: eog_exclude += eog_source_idx ica.exclude += eog_exclude print('########## saving') if len(eog_exclude) == 0: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg_none' + '.pdf', format='pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '.pdf', format='pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format='pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format='pdf') elif len(eog_exclude) == 1: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg_none' + '.pdf', format='pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format='pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format='pdf') elif len(ecg_exclude) == 3: ica_plot.savefig( saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format='pdf') elif len(eog_exclude) == 2: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg_none' + '.pdf', format='pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format='pdf') elif len(ecg_exclude) == 2: ica_plot.savefig( saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format='pdf') elif len(ecg_exclude) == 3: ica_plot.savefig( saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format='pdf') # plot the scores for the different components highlighting in red that/those related to ECG #scores_plots=plt.figure() #ax = plt.subplot(2,1,1) scores_plots_ecg = ica.plot_scores(ecg_scores, exclude=ecg_source_idx, title=title % 'ecg') scores_plots_ecg.savefig(saveRoot + name + '_ecg_scores.pdf', format='pdf') #ax = plt.subplot(2,1,2) scores_plots_eog = ica.plot_scores(eog_scores, exclude=eog_source_idx, title=title % 'eog') scores_plots_eog.savefig(saveRoot + name + '_eog_scores.pdf', format='pdf') #if len(ecg_exclude) > 0: # estimate average artifact #source_clean_ecg=plt.figure() #ax = plt.subplot(2,1,1) source_source_ecg = ica.plot_sources(ecg_evoked, exclude=ecg_source_idx) source_source_ecg.savefig(saveRoot + name + '_ecg_source.pdf', format='pdf') #ax = plt.subplot(2,1,2) source_clean_ecg = ica.plot_overlay(ecg_evoked, exclude=ecg_source_idx) source_clean_ecg.savefig(saveRoot + name + '_ecg_clean.pdf', format='pdf') #clean_plot.savefig(saveRoot + name + '_ecg_clean.pdf', format = 'pdf') #if len(eog_exclude) > 0: source_source_eog = ica.plot_sources(eog_evoked, exclude=eog_source_idx) source_source_eog.savefig(saveRoot + name + '_eog_source.pdf', format='pdf') source_clean_eog = ica.plot_overlay(eog_evoked, exclude=eog_source_idx) source_clean_eog.savefig(saveRoot + name + '_eog_clean.pdf', format='pdf') overl_plot = ica.plot_overlay(raw) overl_plot.savefig(saveRoot + name + '_overl.pdf', format='pdf') plt.close('all') ## restore sensor space data icaList = ica.apply(raw) return (icaList, ica)
def saflow_preproc(filepath, savepath, reportpath): report = mne.Report(verbose=True) raw = read_raw_ctf(filepath, preload=True) raw_data = raw.copy().apply_gradient_compensation( grade=3) #required for source reconstruction picks = mne.pick_types(raw_data.info, meg=True, eog=True, exclude='bads') fig = raw_data.plot(show=False) report.add_figs_to_section(fig, captions='Time series', section='Raw data') close(fig) fig = raw_data.plot_psd(average=False, picks=picks, show=False) report.add_figs_to_section(fig, captions='PSD', section='Raw data') close(fig) ## Filtering high_cutoff = 200 low_cutoff = 0.5 raw_data.filter(low_cutoff, high_cutoff, fir_design="firwin") raw_data.notch_filter(np.arange(60, high_cutoff + 1, 60), picks=picks, filter_length='auto', phase='zero', fir_design="firwin") fig = raw_data.plot_psd(average=False, picks=picks, fmax=120, show=False) report.add_figs_to_section(fig, captions='PSD', section='Filtered data') close(fig) ## ICA ica = ICA(n_components=20, random_state=0).fit(raw_data, decim=3) fig = ica.plot_sources(raw_data, show=False) report.add_figs_to_section(fig, captions='Independent Components', section='ICA') close(fig) ## FIND ECG COMPONENTS ecg_threshold = 0.50 ecg_epochs = create_ecg_epochs(raw_data, ch_name='EEG059') ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, ch_name='EEG059', method='ctps', threshold=ecg_threshold) fig = ica.plot_scores(ecg_scores, ecg_inds, show=False) report.add_figs_to_section(fig, captions='Correlation with ECG (EEG059)', section='ICA - ECG') close(fig) fig = list() try: fig = ica.plot_properties(ecg_epochs, picks=ecg_inds, image_args={'sigma': 1.}, show=False) for i, figure in enumerate(fig): report.add_figs_to_section(figure, captions='Detected component ' + str(i), section='ICA - ECG') close(figure) except: print('No component to remove') ## FIND EOG COMPONENTS eog_threshold = 4 eog_epochs = create_eog_epochs(raw_data, ch_name='EEG057') eog_inds, eog_scores = ica.find_bads_eog(eog_epochs, ch_name='EEG057', threshold=eog_threshold) fig = ica.plot_scores(eog_scores, eog_inds, show=False) report.add_figs_to_section(fig, captions='Correlation with EOG (EEG057)', section='ICA - EOG') close(fig) fig = list() try: fig = ica.plot_properties(eog_epochs, picks=eog_inds, image_args={'sigma': 1.}, show=False) for i, figure in enumerate(fig): report.add_figs_to_section(figure, captions='Detected component ' + str(i), section='ICA - EOG') close(figure) except: print('No component to remove') ## EXCLUDE COMPONENTS ica.exclude = ecg_inds ica.apply(raw_data) ica.exclude = eog_inds ica.apply(raw_data) fig = raw_data.plot(show=False) # Plot the clean signal. report.add_figs_to_section(fig, captions='After filtering + ICA', section='Raw data') close(fig) ## SAVE PREPROCESSED FILE report.save(reportpath, open_browser=False, overwrite=True) raw_data.save(savepath, overwrite=False) return raw_data
Raw.filter(1, 40, fir_design='firwin') Events = find_events(Raw) #%% run ICA for automatic ocular & cardiac rejection (plot the rejected topos) picks_ica = pick_types(Raw.info, meg=True) ica = ICA(n_components=0.98, method='fastica') ica.fit(Raw, picks=picks_ica, reject=reject_ica, decim=4) ecg_epochs = create_ecg_epochs( Raw, ch_name='MEG0111', reject=reject_ica ) # ch_name='MEG0141') # find the ECG events automagically eog_epochs = create_eog_epochs( Raw, reject=reject_ica) # find the EOG events automagically ecg_epochs.average().plot_joint(times=0) eog_epochs.average().plot_joint(times=0) ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, ch_name='MEG0111', method='ctps', threshold=0.2) print(ecg_inds) eog_inds, eog_scores = ica.find_bads_eog(eog_epochs) print(eog_inds) #ica.plot_overlay(ecg_average, exclude=ecg_inds) # does not work? try: ica.plot_components(ch_type='mag', picks=ecg_inds) except IndexError as exc: pass try: ica.plot_components(ch_type='mag', picks=eog_inds) except IndexError as exc: pass ica.exclude.extend(eog_inds) ica.exclude.extend(ecg_inds)
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') # make sure a single threshold in a list works corrmap([ica, ica3], template, threshold=[0.5], label='blinks', plot=True, ch_type="mag") ica_different_channels = ICA(n_components=2, random_state=0).fit(raw, picks=[2, 3, 4, 5]) pytest.raises(ValueError, corrmap, [ica_different_channels, ica], (0, 0)) # 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, start=0, stop=50, 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) # Make sure detect_artifacts marks the right components. # For int criterion, the doc says "E.g. range(2) would return the two # sources with the highest score". Assert that's what it does. # Only test for skew, since it's always the same code. ica.exclude = [] ica.detect_artifacts(raw, start_find=0, stop_find=50, ecg_ch=None, eog_ch=None, skew_criterion=0, var_criterion=None, kurt_criterion=None) assert np.abs(scores[ica.exclude]) == np.max(np.abs(scores)) 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)
proc_dir = root_dir+"proc/" proclist = listdir(proc_dir) l_freq = 0.3 h_freq = 200 n_jobs = "cuda" max_thresh = 2e-3 for filename in proclist: this_match = re.match("c_EPI_(.*)-raw.fif", filename) if not this_match: continue file_id = this_match.groups(1)[0] raw = mne.io.Raw(proc_dir+filename, preload=True) raw_sel = raw.copy().pick_channels(["Cz", "Fz", "F3", "F4", "C3", "C4", "Pz", "Fp1", "Fp2", "O1", "O2", "VEOG", "HEOG", "ECG1+"]) raw_sel.filter(l_freq=0.3, h_freq=30, n_jobs=4) raw_sel.resample(100, n_jobs="cuda") ica = ICA(method="picard") ica.fit(raw_sel) ica.save("{}sel_c_EPI_{}-ica.fif".format(proc_dir, file_id)) bads_eog, scores = ica.find_bads_eog(raw_sel, ch_name="VEOG", threshold=2.3) bads_ecg ,scores = ica.find_bads_ecg(raw_sel, ch_name="ECG1+") bad_comps = bads_eog + bads_ecg raw_sel = ica.apply(raw_sel, exclude=bad_comps) raw_sel.save("{}csel_{}".format(proc_dir, filename), overwrite=True)
n_max_eog = 1 # here we bet on finding the vertical EOG components eog_epochs = create_eog_epochs(raw_sss, reject=reject) # get single EOG trials eog_inds, scores = ica.find_bads_eog(eog_epochs) # find via correlation print(ica) raw_sss.plot_psd(fmax=100) #ica.plot_scores(scores, exclude=eog_inds) #ica.plot_sources(eog_average, exclude=eog_inds) # look at source time course ica.apply(raw_sss, exclude=eog_inds) print(ica) raw_sss.plot_psd(fmax=100) ecg_epochs = create_ecg_epochs(raw_sss, tmin=-.5, tmax=.5) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.apply(raw_sss, exclude=ecg_inds) raw_sss.plot_psd(fmax=100) ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': 35.}) #****************************************************************************# # ERP # #****************************************************************************# tmin, tmax = -0.5, 0.7 event_id = {'Auditory/Left': 1} events = mne.find_events(raw, 'STI 014') picks = mne.pick_types(raw.info, meg=True, eeg=True,
def compute_ica(fif_file, ecg_ch_name, eog_ch_name, n_components, reject): """Compute ica solution""" import os import mne from mne.io import read_raw_fif from mne.preprocessing import ICA from mne.preprocessing import create_ecg_epochs, create_eog_epochs from nipype.utils.filemanip import split_filename as split_f subj_path, basename, ext = split_f(fif_file) raw = read_raw_fif(fif_file, preload=True) # select sensors select_sensors = mne.pick_types(raw.info, meg=True, ref_meg=False, exclude='bads') # 1) Fit ICA model using the FastICA algorithm # Other available choices are `infomax` or `extended-infomax` # We pass a float value between 0 and 1 to select n_components based on the # percentage of variance explained by the PCA components. # reject = dict(mag=1e-1, grad=1e-9) flat = dict(mag=1e-13, grad=1e-13) ica = ICA(n_components=n_components, method='fastica', max_iter=500) ica.fit(raw, picks=select_sensors, reject=reject, flat=flat) # -------------------- Save ica timeseries ---------------------------- # ica_ts_file = os.path.abspath(basename + "_ica-tseries.fif") ica_src = ica.get_sources(raw) ica_src.save(ica_ts_file) ica_src = None # --------------------------------------------------------------------- # # 2) identify bad components by analyzing latent sources. # generate ECG epochs use detection via phase statistics # if we just have exclude channels we jump these steps n_max_ecg = 3 n_max_eog = 2 # check if ecg_ch_name is in the raw channels if ecg_ch_name in raw.info['ch_names']: raw.set_channel_types({ecg_ch_name: 'ecg'}) else: ecg_ch_name = None ecg_epochs = create_ecg_epochs(raw, tmin=-0.5, tmax=0.5, picks=select_sensors, ch_name=ecg_ch_name) ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ecg_evoked = ecg_epochs.average() ecg_epochs = None ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds eog_ch_name = eog_ch_name.replace(' ', '') if set(eog_ch_name.split(',')).issubset(set(raw.info['ch_names'])): print('*** EOG CHANNELS FOUND ***') eog_inds, eog_scores = ica.find_bads_eog(raw, ch_name=eog_ch_name) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds eog_evoked = create_eog_epochs(raw, tmin=-0.5, tmax=0.5, picks=select_sensors, ch_name=eog_ch_name).average() else: print('*** NO EOG CHANNELS FOUND!!! ***') eog_inds = eog_scores = eog_evoked = None report_file = generate_report(raw=raw, ica=ica, subj_name=fif_file, basename=basename, ecg_evoked=ecg_evoked, ecg_scores=ecg_scores, ecg_inds=ecg_inds, ecg_ch_name=ecg_ch_name, eog_evoked=eog_evoked, eog_scores=eog_scores, eog_inds=eog_inds, eog_ch_name=eog_ch_name) report_file = os.path.abspath(report_file) ica_sol_file = os.path.abspath(basename + '_ica_solution.fif') ica.save(ica_sol_file) raw_ica = ica.apply(raw) raw_ica_file = os.path.abspath(basename + '_ica' + ext) raw_ica.save(raw_ica_file) return raw_ica_file, ica_sol_file, ica_ts_file, report_file
def remove_eyeblinks_and_heartbeat(raw, subject, figdir, events, eventid, rng): """ Find and repair eyeblink and heartbeat artifacts in the data. Data should be filtered. Importantly, ICA is fitted on artificially epoched data with reject criteria estimates via the autoreject package - this is done to reject high- amplitude artifacts to influence the ICA solution. The ICA fit is then applied to the raw data. :param raw: Raw data :param subject: str, subject identifier, e.g., '001' :param figdir: :param rng: random state instance """ # prior to an ICA, it is recommended to high-pass filter the data # as low frequency artifacts can alter the ICA solution. We fit the ICA # to high-pass filtered (1Hz) data, and apply it to non-highpass-filtered # data logging.info("Applying a temporary high-pass filtering prior to ICA") filt_raw = raw.copy() filt_raw.load_data().filter(l_freq=1., h_freq=None) # evoked eyeblinks and heartbeats for diagnostic plots eog_evoked = create_eog_epochs(filt_raw).average() eog_evoked.apply_baseline(baseline=(None, -0.2)) if subject == '008': # subject 008's ECG channel is flat. It will not find any heartbeats by # default. We let it estimate heartbeat from magnetometers. For this, # we'll drop the ECG channel filt_raw.drop_channels('ECG003') ecg_evoked = create_ecg_epochs(filt_raw).average() ecg_evoked.apply_baseline(baseline=(None, -0.2)) # make sure that we actually found sensible artifacts here eog_fig = eog_evoked.plot_joint() for i, fig in enumerate(eog_fig): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"evoked-artifact_eog_sub-{subject}_{i}.png", ]) fig.savefig(fname) ecg_fig = ecg_evoked.plot_joint() for i, fig in enumerate(ecg_fig): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"evoked-artifact_ecg_sub-{subject}_{i}.png", ]) fig.savefig(fname) # Chunk raw data into epochs to fit the ICA # No baseline correction as it would interfere with ICA. logging.info("Epoching filtered data") epochs = mne.Epochs(filt_raw, events, event_id=eventid, tmin=0, tmax=3, picks='meg', baseline=None) ## First, estimate rejection criteria for high-amplitude artifacts. This is ## done via autoreject #logging.info('Estimating bad epochs quick-and-dirty, to improve ICA') #ar = AutoReject(random_state=rng) # fit on first 200 epochs to save (a bit of) time #epochs.load_data() #ar.fit(epochs[:200]) #epochs_ar, reject_log = ar.transform(epochs, return_log=True) # run an ICA to capture heartbeat and eyeblink artifacts. # set a seed for reproducibility. # When left to figure out the component number by itself, it ends up with # about 80. I'm setting n_components to 45 to have a chance at checking them # by hand. # We fit it on a set of epochs excluding the initial bad epochs following # https://github.com/autoreject/autoreject/blob/dfbc64f49eddeda53c5868290a6792b5233843c6/examples/plot_autoreject_workflow.py logging.info('Fitting the ICA') ica = ICA(max_iter='auto', n_components=45, random_state=rng) ica.fit(epochs) #[~reject_log.bad_epochs]) logging.info("Searching for eyeblink and heartbeat artifacts in the data") # get ICA components for the given subject if subject == '008': eog_indices = [10] ecg_indices = [29] #eog_indices = ica_comps[subject]['eog'] #ecg_indices = ica_comps[subject]['ecg'] # An initially manual component detection did not reproduce after a software # update - for now, we have to do the automatic detection for all but sub 8 else: eog_indices, eog_scores = ica.find_bads_eog(filt_raw) ecg_indices, ecg_scores = ica.find_bads_ecg(filt_raw) logging.info(f"Identified the following EOG components: {eog_indices}") logging.info(f"Identified the following ECG components: {ecg_indices}") # visualize the components components = ica.plot_components() for i, fig in enumerate(components): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-components_sub-{subject}_{i}.png", ]) fig.savefig(fname) # visualize the time series of components and save it plt.rcParams['figure.figsize'] = 30, 20 comp_sources = ica.plot_sources(epochs) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-components_sources_sub-{subject}.png", ]) comp_sources.savefig(fname) # reset plotting params plt.rcParams['figure.figsize'] = plt.rcParamsDefault['figure.figsize'] # plot EOG components overlay_eog = ica.plot_overlay(eog_evoked, exclude=ica_comps[subject]['eog']) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-eog-components_over-avg-epochs_sub-{subject}.png", ]) overlay_eog.savefig(fname) # plot ECG components overlay_ecg = ica.plot_overlay(ecg_evoked, exclude=ica_comps[subject]['ecg']) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-ecg-components_over-avg-epochs_sub-{subject}.png", ]) overlay_ecg.savefig(fname) # plot EOG component properties figs = ica.plot_properties(filt_raw, picks=eog_indices) for i, fig in enumerate(figs): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-property{i}_artifact-eog_sub-{subject}.png", ]) fig.savefig(fname) # plot ECG component properties figs = ica.plot_properties(filt_raw, picks=ecg_indices) for i, fig in enumerate(figs): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-property{i}_artifact-ecg_sub-{subject}.png", ]) fig.savefig(fname) # Set the indices to be excluded ica.exclude = eog_indices ica.exclude.extend(ecg_indices) # plot ICs applied to the averaged EOG epochs, with EOG matches highlighted sources = ica.plot_sources(eog_evoked) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-sources_artifact-eog_sub-{subject}.png", ]) sources.savefig(fname) # plot ICs applied to the averaged ECG epochs, with ECG matches highlighted sources = ica.plot_sources(ecg_evoked) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-sources_artifact-ecg_sub-{subject}.png", ]) sources.savefig(fname) # apply the ICA to the raw data logging.info('Applying ICA to the raw data.') raw.load_data() ica.apply(raw)
def test_ica_additional(): """Test additional ICA functionality""" stop2 = 500 raw = io.Raw(raw_fname, preload=True).crop(0, stop, False).crop(1.5) picks = pick_types(raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads") 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") epochs = Epochs(raw, events[:4], event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True) # for testing eog functionality picks2 = pick_types(raw.info, meg=True, stim=False, ecg=False, eog=True, exclude="bads") epochs_eog = Epochs(raw, events[:4], event_id, tmin, tmax, picks=picks2, baseline=(None, 0), preload=True) test_cov2 = deepcopy(test_cov) ica = ICA(noise_cov=test_cov2, n_components=3, max_pca_components=4, n_pca_components=4) assert_true(ica.info is None) with warnings.catch_warnings(record=True): ica.fit(raw, picks[:5]) assert_true(isinstance(ica.info, Info)) assert_true(ica.n_components_ < 5) ica = ICA(n_components=3, max_pca_components=4, n_pca_components=4) assert_raises(RuntimeError, ica.save, "") with warnings.catch_warnings(record=True): ica.fit(raw, picks=None, start=start, stop=stop2) # test warnings on bad filenames with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") ica_badname = op.join(op.dirname(tempdir), "test-bad-name.fif.gz") ica.save(ica_badname) read_ica(ica_badname) assert_true(len(w) == 2) # test decim ica = ICA(n_components=3, max_pca_components=4, n_pca_components=4) raw_ = raw.copy() for _ in range(3): raw_.append(raw_) n_samples = raw_._data.shape[1] with warnings.catch_warnings(record=True): ica.fit(raw, picks=None, decim=3) assert_true(raw_._data.shape[1], n_samples) # test expl var ica = ICA(n_components=1.0, max_pca_components=4, n_pca_components=4) with warnings.catch_warnings(record=True): ica.fit(raw, picks=None, decim=3) assert_true(ica.n_components_ == 4) # epochs extraction from raw fit assert_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) with warnings.catch_warnings(record=True): # ICA does not converge ica.fit(raw, picks=picks, start=start, stop=stop2) sources = ica.get_sources(epochs).get_data() assert_true(ica.mixing_matrix_.shape == (2, 2)) assert_true(ica.unmixing_matrix_.shape == (2, 2)) assert_true(ica.pca_components_.shape == (4, len(picks))) assert_true(sources.shape[1] == ica.n_components_) for exclude in [[], [0]]: ica.exclude = [0] ica.save(test_ica_fname) ica_read = read_ica(test_ica_fname) assert_true(ica.exclude == ica_read.exclude) ica.exclude = [] ica.apply(raw, exclude=[1]) assert_true(ica.exclude == []) ica.exclude = [0, 1] ica.apply(raw, exclude=[1]) assert_true(ica.exclude == [0, 1]) ica_raw = ica.get_sources(raw) assert_true(ica.exclude == [ica_raw.ch_names.index(e) for e in ica_raw.info["bads"]]) # test filtering d1 = ica_raw._data[0].copy() with warnings.catch_warnings(record=True): # dB warning ica_raw.filter(4, 20) assert_true((d1 != ica_raw._data[0]).any()) d1 = ica_raw._data[0].copy() with warnings.catch_warnings(record=True): # dB warning ica_raw.notch_filter([10]) assert_true((d1 != ica_raw._data[0]).any()) ica.n_pca_components = 2 ica.save(test_ica_fname) ica_read = read_ica(test_ica_fname) assert_true(ica.n_pca_components == ica_read.n_pca_components) # check type consistency attrs = "mixing_matrix_ unmixing_matrix_ pca_components_ " "pca_explained_variance_ _pre_whitener" f = lambda x, y: 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_true(ica.ch_names == ica_read.ch_names) assert_true(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 scrore funcs for name, func in 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_true(ica.n_components_ == len(scores)) # check univariate stats scores = ica.score_sources(raw, score_func=stats.skew) # check exception handling assert_raises(ValueError, ica.score_sources, raw, target=np.arange(1)) params = [] params += [(None, -1, slice(2), [0, 1])] # varicance, kurtosis idx 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, ) idx, scores = ica.find_bads_ecg(raw, method="ctps") assert_equal(len(scores), ica.n_components_) idx, scores = ica.find_bads_ecg(raw, method="correlation") assert_equal(len(scores), ica.n_components_) idx, scores = ica.find_bads_ecg(epochs, method="ctps") assert_equal(len(scores), ica.n_components_) assert_raises(ValueError, ica.find_bads_ecg, epochs.average(), method="ctps") assert_raises(ValueError, ica.find_bads_ecg, raw, method="crazy-coupling") 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 idx, scores = ica.find_bads_eog(raw) assert_true(isinstance(scores, list)) assert_equal(len(scores[0]), ica.n_components_) # check score funcs for name, func in score_funcs.items(): if name in score_funcs_unsuited: continue scores = ica.score_sources(epochs_eog, target="EOG 061", score_func=func) assert_true(ica.n_components_ == len(scores)) # check univariate stats scores = ica.score_sources(epochs, score_func=stats.skew) # check exception handling assert_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 warnings.catch_warnings(record=True): # filter attenuation warning ecg_events = ica_find_ecg_events(raw, sources[np.abs(ecg_scores).argmax()]) assert_true(ecg_events.ndim == 2) # eog functionality eog_scores = ica.score_sources(raw, target="EOG 061", score_func="pearsonr") with warnings.catch_warnings(record=True): # filter attenuation warning eog_events = ica_find_eog_events(raw, sources[np.abs(eog_scores).argmax()]) assert_true(eog_events.ndim == 2) # Test ica fiff export ica_raw = ica.get_sources(raw, start=0, stop=100) assert_true(ica_raw.last_samp - ica_raw.first_samp == 100) assert_true(len(ica_raw._filenames) == 0) # API consistency ica_chans = [ch for ch in ica_raw.ch_names if "ICA" in ch] assert_true(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 = io.Raw(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_true(ica_epochs.events.shape == epochs.events.shape) ica_chans = [ch for ch in ica_epochs.ch_names if "ICA" in ch] assert_true(ica.n_components_ == len(ica_chans)) assert_true(ica.n_components_ == ica_epochs.get_data().shape[1]) assert_true(ica_epochs.raw is None) assert_true(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_ = _check_n_pca_components(ica, ncomps) assert_true(ncomps_ == expected)
# to definitely register this component as a bad one to be removed # there is the ``ica.exclude`` attribute, a simple Python list ica.exclude.extend(eog_inds) # from now on the ICA will reject this component even if no exclude # parameter is passed, and this information will be stored to disk # on saving # uncomment this for reading and writing # ica.save('my-ica.fif') # ica = read_ica('my-ica.fif') ############################################################################### # Exercise: find and remove ECG artifacts using ICA! ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': 35.}) ############################################################################### # What if we don't have an EOG channel? # ------------------------------------- # # We could either: # # 1. make a bipolar reference from frontal EEG sensors and use as virtual EOG # channel. This can be tricky though as you can only hope that the frontal # EEG channels only reflect EOG and not brain dynamics in the prefrontal # cortex. # 2. go for a semi-automated approach, using template matching. #
def raw_preprocessing(self, raw, use_ica=True, use_ssp=True): # Filter raw.info['bads'] = self.bad_channels # Remove power-line noise raw.notch_filter(np.arange(60, 241, 60), picks=self.picks, filter_length='auto', phase=self.phase) raw.filter(l_freq=self.l_freq, h_freq=self.h_freq, phase=self.phase, fir_window=self.fir_window, fir_design=self.fir_design) # Add EEG reference raw.set_eeg_reference(projection=True) # TODO: some mechanism to control this if use_ica: # supported ica_channels = ['mag', 'grad', 'eeg', 'seeg', 'ecog', 'hbo', 'hbr', 'eog'] ica_picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') n_components = 25 decim = 3 # maximum number of components to reject n_max_ecg, n_max_eog = 3, 1 # here we don't expect horizontal EOG components # ica = run_ica(raw, n_components=0.95) ica = ICA(n_components=n_components, method='fastica', noise_cov=None) ica.fit(raw, decim=decim, picks=ica_picks, reject=self.reject) # generate ECG epochs use detection via phase statistics ecg_epochs = create_ecg_epochs(raw, reject=self.reject) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds # detect EOG by correlation eog_inds, scores = ica.find_bads_eog(raw) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds ica.apply(raw) if use_ssp: if self.ecg: ecg_projs, _ = compute_proj_ecg(raw) raw.info['projs'] += ecg_projs if self.blink: eog_projs, _ = compute_proj_eog(raw) raw.info['projs'] += eog_projs raw.apply_proj() return raw
def find_ecg_eog_components(raw, apply_lohipass=True, plot=True, save_epochs=True, save_fn=None, ask_user=True): """ Try filtering the raw data file with ICA: identify components suspicious as ECG/EoG components. :type raw: mne.io.fiff.raw.Raw :param apply_lohipass: Whether to apply a low-pass & hi-pass filter :param plot: Whether to plot figures :param save_epochs: Whether to store epochs in the returned value (set to False in order to save space) :param save_fn: Save the returned dict in the specified file :return: dict """ #-- 1Hz high pass is often helpful for fitting ICA print('======== Loading data =========') raw.load_data() if apply_lohipass: print('\n======== Filtering data =========') raw.filter(1, 40, n_jobs=multiprocessing.cpu_count()) picks_meg = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') #-- Create ICA and fit it to the data reject = dict(mag=5e-12, grad=4000e-13) print('\n======== ICA: identifying components =========') ica = ICA(n_components=25, method='fastica', random_state=23) ica.fit(raw, picks=picks_meg, decim=3, reject=reject) #----------- Filter EoG data --------------- print('\n======== Detecting EoG components =========') eog_epochs = create_eog_epochs(raw, reject=reject) # get single EOG trials eog_average = create_eog_epochs(raw, reject=reject, picks=picks_meg).average() #-- Find components that correlate with the EoG data eog_inds, eog_scores = ica.find_bads_eog( eog_epochs) # find via correlation if len(eog_inds) > 0: eog_inds_desc = ",".join([str(i) for i in eog_inds]) print('>>> EoG components: [%s]' % eog_inds_desc) else: print(">>> No EoG components were found.") #----------- Filter ECG data --------------- print('\n======== Detecting ECG components =========') ecg_average = create_ecg_epochs(raw, reject=reject, picks=picks_meg).average() ecg_epochs = create_ecg_epochs(raw, reject=reject) #-- Find components that correlate with the ECG data ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs) if len(ecg_inds) > 0: ecg_inds_desc = ",".join([str(i) for i in ecg_inds]) print('>>> ECG components: [%s]' % ecg_inds_desc) else: print(">>> No ECG components were found.") res = dict(ica=ica, ecg_inds=ecg_inds, eog_inds=eog_inds, ecg_epochs=ecg_epochs, eog_epochs=eog_epochs, ecg_scores=ecg_scores, eog_scores=eog_scores, ecg_average=ecg_average, eog_average=eog_average, bad_components=list(set(eog_inds + ecg_inds)), reject=reject) if plot: plot_ecg_eog_components(res) plt.show() plt.pause(1) if ask_user: print('---------------------------------------- \n') print('Do you want to update the ECG components ?') print('---------------------------------------- \n') ecg_comp = input() if ecg_comp == 'no': print('>>> ECG components: [%s]' % ecg_inds) else: ecg_inds = ecg_comp print('---------------------------------------- \n') print('Do you want to update the EOG components ?') print('---------------------------------------- \n') eog_comp = input() if eog_comp == 'no': print('>>> ECG components: [%s]' % ecg_inds) else: eog_inds = eog_comp ica.exclude.extend(eog_inds) ica.exclude.extend(ecg_inds) res = dict(ica=ica, ecg_inds=ecg_inds, eog_inds=eog_inds, ecg_epochs=ecg_epochs, eog_epochs=eog_epochs, ecg_scores=ecg_scores, eog_scores=eog_scores, ecg_average=ecg_average, eog_average=eog_average, bad_components=list(set(eog_inds + ecg_inds)), reject=reject) if not save_epochs: del res['ecg_epochs'] del res['eog_epochs'] if save_fn is not None: print('Saving results in %s' % save_fn) with open(save_fn, 'wb') as fp: pickle.dump(res, fp) ica.save(save_fn[:-4] + '-ica.fif') print('Saved.') return res
# bipolar reference from frontal EEG sensors and use that as virtual EOG # channel. This carries a risk however: you must hope that the frontal EEG # channels only reflect EOG and not brain dynamics in the prefrontal cortex (or # you must not care about those prefrontal signals). # # For ECG, it is easier: :meth:`~mne.preprocessing.ICA.find_bads_ecg` can use # cross-channel averaging of magnetometer or gradiometer channels to construct # a virtual ECG channel, so if you have MEG channels it is usually not # necessary to pass a specific channel name. # :meth:`~mne.preprocessing.ICA.find_bads_ecg` also has two options for its # ``method`` parameter: ``'ctps'`` (cross-trial phase statistics [3]_) and # ``'correlation'`` (Pearson correlation between data and ECG channel). ica.exclude = [] # find which ICs match the ECG pattern ecg_indices, ecg_scores = ica.find_bads_ecg(raw, method='correlation', threshold='auto') ica.exclude = ecg_indices # barplot of ICA component "ECG match" scores ica.plot_scores(ecg_scores) # plot diagnostics ica.plot_properties(raw, picks=ecg_indices) # plot ICs applied to raw data, with ECG matches highlighted ica.plot_sources(raw, show_scrollbars=False) # plot ICs applied to the averaged ECG epochs, with ECG matches highlighted ica.plot_sources(ecg_evoked) ###############################################################################
def compute_ica(raw, subject, n_components=0.99, picks=None, decim=None, reject=None, ecg_tmin=-0.5, ecg_tmax=0.5, eog_tmin=-0.5, eog_tmax=0.5, n_max_ecg=3, n_max_eog=1, n_max_ecg_epochs=200, show=True, img_scale=1.0, random_state=None, report=None, artifact_stats=None): """Run ICA in raw data Parameters ----------, raw : instance of Raw Raw measurements to be decomposed. subject : str The name of the subject. picks : array-like of int, shape(n_channels, ) | None Channels to be included. This selection remains throughout the initialized ICA solution. If None only good data channels are used. Defaults to None. n_components : int | float | None | 'rank' The number of components used for ICA decomposition. If int, it must be smaller then max_pca_components. If None, all PCA components will be used. If float between 0 and 1 components can will be selected by the cumulative percentage of explained variance. If 'rank', the number of components equals the rank estimate. Defaults to 0.99. decim : int | None Increment for selecting each nth time slice. If None, all samples within ``start`` and ``stop`` are used. Defalts to None. reject : dict | None Rejection parameters based on peak to peak amplitude. Valid keys are 'grad' | 'mag' | 'eeg' | 'eog' | 'ecg'. If reject is None then no rejection is done. You should use such parameters to reject big measurement artifacts and not EOG for example. It only applies if `inst` is of type Raw. Defaults to {'mag': 5e-12} ecg_tmin : float Start time before ECG event. Defaults to -0.5. ecg_tmax : float End time after ECG event. Defaults to 0.5. eog_tmin : float Start time before rog event. Defaults to -0.5. eog_tmax : float End time after rog event. Defaults to 0.5. n_max_ecg : int | None The maximum number of ECG components to exclude. Defaults to 3. n_max_eog : int | None The maximum number of EOG components to exclude. Defaults to 1. n_max_ecg_epochs : int The maximum number of ECG epochs to use for phase-consistency estimation. Defaults to 200. show : bool Show figure if True scale_img : float The scaling factor for the report. Defaults to 1.0. random_state : None | int | instance of np.random.RandomState np.random.RandomState to initialize the FastICA estimation. As the estimation is non-deterministic it can be useful to fix the seed to have reproducible results. Defaults to None. report : instance of Report | None The report object. If None, a new report will be generated. artifact_stats : None | dict A dict that contains info on amplitude ranges of artifacts and numbers of events, etc. by channel type. Returns ------- ica : instance of ICA The ICA solution. report : dict A dict with an html report ('html') and artifact statistics ('stats'). """ if report is None: report = Report(subject=subject, title='ICA preprocessing') if n_components == 'rank': n_components = raw.estimate_rank(picks=picks) ica = ICA(n_components=n_components, max_pca_components=None, random_state=random_state, max_iter=256) ica.fit(raw, picks=picks, decim=decim, reject=reject) comment = [] for ch in ('mag', 'grad', 'eeg'): if ch in ica: comment += [ch.upper()] if len(comment) > 0: comment = '+'.join(comment) + ' ' else: comment = '' topo_ch_type = 'mag' if 'GRAD' in comment and 'MAG' not in comment: topo_ch_type = 'grad' elif 'EEG' in comment: topo_ch_type = 'eeg' ########################################################################### # 2) identify bad components by analyzing latent sources. title = '%s related to %s artifacts (red) ({})'.format(subject) # generate ECG epochs use detection via phase statistics reject_ = {'mag': 5e-12, 'grad': 5000e-13, 'eeg': 300e-6} if reject is not None: reject_.update(reject) for ch_type in ['mag', 'grad', 'eeg']: if ch_type not in ica: reject_.pop(ch_type) picks_ = np.array([raw.ch_names.index(k) for k in ica.ch_names]) if 'eeg' in ica: if 'ecg' in raw: picks_ = np.append(picks_, pick_types(raw.info, meg=False, ecg=True)[0]) else: logger.info('There is no ECG channel, trying to guess ECG from ' 'magnetormeters') if artifact_stats is None: artifact_stats = dict() ecg_epochs = create_ecg_epochs(raw, tmin=ecg_tmin, tmax=ecg_tmax, keep_ecg=True, picks=picks_, reject=reject_) n_ecg_epochs_found = len(ecg_epochs.events) artifact_stats['ecg_n_events'] = n_ecg_epochs_found n_max_ecg_epochs = min(n_max_ecg_epochs, n_ecg_epochs_found) artifact_stats['ecg_n_used'] = n_max_ecg_epochs sel_ecg_epochs = np.arange(n_ecg_epochs_found) rng = np.random.RandomState(42) rng.shuffle(sel_ecg_epochs) ecg_ave = ecg_epochs.average() report.add_figs_to_section(ecg_ave.plot(), 'ECG-full', 'artifacts') ecg_epochs = ecg_epochs[sel_ecg_epochs[:n_max_ecg_epochs]] ecg_ave = ecg_epochs.average() report.add_figs_to_section(ecg_ave.plot(), 'ECG-used', 'artifacts') _put_artifact_range(artifact_stats, ecg_ave, kind='ecg') ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') if len(ecg_inds) > 0: ecg_evoked = ecg_epochs.average() del ecg_epochs fig = ica.plot_scores(scores, exclude=ecg_inds, labels='ecg', title='', show=show) report.add_figs_to_section(fig, 'scores ({})'.format(subject), section=comment + 'ECG', scale=img_scale) current_exclude = [e for e in ica.exclude] # issue #2608 MNE fig = ica.plot_sources(raw, ecg_inds, exclude=ecg_inds, title=title % ('components', 'ecg'), show=show) report.add_figs_to_section(fig, 'sources ({})'.format(subject), section=comment + 'ECG', scale=img_scale) ica.exclude = current_exclude fig = ica.plot_components(ecg_inds, ch_type=topo_ch_type, title='', colorbar=True, show=show) report.add_figs_to_section(fig, title % ('sources', 'ecg'), section=comment + 'ECG', scale=img_scale) ica.exclude = current_exclude ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds fig = ica.plot_sources(ecg_evoked, exclude=ecg_inds, show=show) report.add_figs_to_section(fig, 'evoked sources ({})'.format(subject), section=comment + 'ECG', scale=img_scale) fig = ica.plot_overlay(ecg_evoked, exclude=ecg_inds, show=show) report.add_figs_to_section(fig, 'rejection overlay ({})'.format(subject), section=comment + 'ECG', scale=img_scale) # detect EOG by correlation picks_eog = np.concatenate( [picks_, pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True)]) eog_epochs = create_eog_epochs(raw, tmin=eog_tmin, tmax=eog_tmax, picks=picks_eog, reject=reject_) artifact_stats['eog_n_events'] = len(eog_epochs.events) artifact_stats['eog_n_used'] = artifact_stats['eog_n_events'] eog_ave = eog_epochs.average() report.add_figs_to_section(eog_ave.plot(), 'EOG-used', 'artifacts') _put_artifact_range(artifact_stats, eog_ave, kind='eog') eog_inds = None if len(eog_epochs.events) > 0: eog_inds, scores = ica.find_bads_eog(eog_epochs) if eog_inds is not None and len(eog_epochs.events) > 0: fig = ica.plot_scores(scores, exclude=eog_inds, labels='eog', show=show, title='') report.add_figs_to_section(fig, 'scores ({})'.format(subject), section=comment + 'EOG', scale=img_scale) current_exclude = [e for e in ica.exclude] # issue #2608 MNE fig = ica.plot_sources(raw, eog_inds, exclude=ecg_inds, title=title % ('sources', 'eog'), show=show) report.add_figs_to_section(fig, 'sources', section=comment + 'EOG', scale=img_scale) ica.exclude = current_exclude fig = ica.plot_components(eog_inds, ch_type=topo_ch_type, title='', colorbar=True, show=show) report.add_figs_to_section(fig, title % ('components', 'eog'), section=comment + 'EOG', scale=img_scale) ica.exclude = current_exclude eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds eog_evoked = eog_epochs.average() fig = ica.plot_sources(eog_evoked, exclude=eog_inds, show=show) report.add_figs_to_section( fig, 'evoked sources ({})'.format(subject), section=comment + 'EOG', scale=img_scale) fig = ica.plot_overlay(eog_evoked, exclude=eog_inds, show=show) report.add_figs_to_section( fig, 'rejection overlay({})'.format(subject), section=comment + 'EOG', scale=img_scale) else: del eog_epochs # check the amplitudes do not change if len(ica.exclude) > 0: fig = ica.plot_overlay(raw, show=show) # EOG artifacts remain html = _render_components_table(ica) report.add_htmls_to_section( html, captions='excluded components', section='ICA rejection summary (%s)' % ch_type) report.add_figs_to_section( fig, 'rejection overlay({})'.format(subject), section=comment + 'RAW', scale=img_scale) return ica, dict(html=report, stats=artifact_stats)
title = 'Sources related to %s artifacts (red)' # generate ECG epochs use detection via phase statistics picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=True, ecg=True, stim=False, exclude='bads') # create_ecg_epochs is strange: it strips the channels of anything non M/EEG # UNLESS picks=None picks=None ecg_epochs = create_ecg_epochs(raw, ch_name='ECG002', tmin=-.5, tmax=.5, picks=picks, verbose=True) # This will work with the above, but uses MASSIVE RAM # Not sure the ECG quality is good enough for the QRS-detector ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps', ch_name='ECG002') # This creates a synthetic ECG from magnetometers, probably better... ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps', ch_name='ECG002') fig = ica.plot_scores(scores, exclude=ecg_inds, title=title % 'ecg') fig.savefig(img_folder + '/ica_ecg_scores.png') show_picks = np.abs(scores).argsort()[::-1][:5] fig = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % 'ecg') fig.savefig(img_folder + '/ica_ecg_sources.png') fig = ica.plot_components(ecg_inds, title=title % 'ecg', colorbar=True) fig.set_size_inches(12.,8.) fig.savefig(img_folder + '/ica_ecg_components.png') ecg_inds = ecg_inds[:n_max_ecg]
reject = dict(grad=200e-12, mag=4e-12) # Run the ICA decomposition on raw data ica_fruit.fit(raw_fruit, picks=picks_fruit, decim=decim, reject=reject) ica_odour.fit(raw_odour, picks=picks_odour, decim=decim, reject=reject) ica_milk.fit(raw_milk, picks=picks_milk, decim=decim, reject=reject) ica_LD.fit(raw_LD, picks=picks_LD, decim=decim, reject=reject) # Conveniently generates epochs around EOG artifact events ecg_epochs_fruit = create_ecg_epochs(raw_fruit, reject=reject) ecg_epochs_odour = create_ecg_epochs(raw_odour, reject=reject) ecg_epochs_milk = create_ecg_epochs(raw_milk, reject=reject) ecg_epochs_LD = create_ecg_epochs(raw_LD, reject=reject) # Detecting EOG related components using correlation ecg_inds_fruit, scores_fruit = ica_fruit.find_bads_ecg(ecg_epochs_fruit) ecg_inds_odour, scores_odour = ica_odour.find_bads_ecg(ecg_epochs_odour) ecg_inds_milk, scores_milk = ica_milk.find_bads_ecg(ecg_epochs_milk) ecg_inds_LD, scores_LD = ica_LD.find_bads_ecg(ecg_epochs_LD) ecg_inds_fruit = ecg_inds_fruit[:n_max_ecg] ecg_inds_odour = ecg_inds_odour[:n_max_ecg] ecg_inds_milk = ecg_inds_milk[:n_max_ecg] ecg_inds_LD = ecg_inds_LD[:n_max_ecg] # Excluding the list of sources indices obtained in the previous line ica_fruit.exclude += ecg_inds_fruit ica_odour.exclude += ecg_inds_odour ica_milk.exclude += ecg_inds_milk ica_LD.exclude += ecg_inds_LD
(subject, condition)) fig = ica.plot_components(eog_inds, title=title % ('eog', subject), colorbar=True) fig.savefig(ica_folder + "plots/%s_%s_eog_component.png" % (subject, condition)) fig = ica.plot_overlay(epochs.average(), exclude=eog_inds, show=False) fig.savefig(ica_folder + "plots/%s_%s_eog_excluded.png" % (subject, condition)) fig = ica.plot_properties(epochs, picks=eog_inds) fig[0].savefig(ica_folder + "plots/%s_%s_plot_properties.png" % (subject, condition)) # ECG ecg_inds, scores = ica.find_bads_ecg(epochs) ica.exclude += ecg_inds if ecg_inds: fig = ica.plot_components(ecg_inds, title=title % ('ecg', subject), colorbar=True) fig.savefig(ica_folder + "plots/%s_%s_ecg_component.png" % (subject, condition)) fig = ica.plot_overlay(epochs.average(), exclude=ecg_inds, show=False) fig.savefig(ica_folder + "plots/%s_%s_ecg_excluded.png" % (subject, condition)) fig = ica.plot_properties(epochs, picks=ecg_inds) fig[0].savefig(ica_folder + "plots/%s_%s_plot_properties.png" % (subject, condition))
# peak-to-peak amplitude rejection parameters reject = dict(grad=4000e-13, mag=4e-12) # longer + more epochs for more artifact exposure events = mne.find_events(raw, stim_channel='STI 014') epochs = mne.Epochs(raw, events, event_id=None, tmin=-0.2, tmax=0.5, reject=reject) ############################################################################### # Fit ICA model using the FastICA algorithm, detect and plot components # explaining ECG artifacts. ica = ICA(n_components=0.95, method='fastica').fit(epochs) ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, threshold='auto') ica.plot_components(ecg_inds) ############################################################################### # Plot properties of ECG components: ica.plot_properties(epochs, picks=ecg_inds) ############################################################################### # Plot the estimated source of detected ECG related components ica.plot_sources(raw, picks=ecg_inds)
def test_ica_additional(): """Test additional ICA functionality""" tempdir = _TempDir() stop2 = 500 raw = Raw(raw_fname).crop(1.5, stop, False) raw.load_data() picks = pick_types(raw.info, meg=True, stim=False, ecg=False, eog=False, exclude='bads') 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') epochs = Epochs(raw, events[:4], event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True) # test if n_components=None works with warnings.catch_warnings(record=True): ica = ICA(n_components=None, max_pca_components=None, n_pca_components=None, random_state=0) ica.fit(epochs, picks=picks, decim=3) # for testing eog functionality picks2 = pick_types(raw.info, meg=True, stim=False, ecg=False, eog=True, exclude='bads') epochs_eog = Epochs(raw, events[:4], event_id, tmin, tmax, picks=picks2, baseline=(None, 0), preload=True) test_cov2 = test_cov.copy() ica = ICA(noise_cov=test_cov2, n_components=3, max_pca_components=4, n_pca_components=4) assert_true(ica.info is None) with warnings.catch_warnings(record=True): ica.fit(raw, picks[:5]) assert_true(isinstance(ica.info, Info)) assert_true(ica.n_components_ < 5) ica = ICA(n_components=3, max_pca_components=4, n_pca_components=4) assert_raises(RuntimeError, ica.save, '') with warnings.catch_warnings(record=True): ica.fit(raw, picks=[1, 2, 3, 4, 5], start=start, stop=stop2) # test corrmap ica2 = 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_true(ica.labels_["blinks"] == ica2.labels_["blinks"]) assert_true(0 in ica.labels_["blinks"]) plt.close('all') # test warnings on bad filenames with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') ica_badname = op.join(op.dirname(tempdir), 'test-bad-name.fif.gz') ica.save(ica_badname) read_ica(ica_badname) assert_naming(w, 'test_ica.py', 2) # test decim ica = ICA(n_components=3, max_pca_components=4, n_pca_components=4) raw_ = raw.copy() for _ in range(3): raw_.append(raw_) n_samples = raw_._data.shape[1] with warnings.catch_warnings(record=True): ica.fit(raw, picks=None, decim=3) assert_true(raw_._data.shape[1], n_samples) # test expl var ica = ICA(n_components=1.0, max_pca_components=4, n_pca_components=4) with warnings.catch_warnings(record=True): ica.fit(raw, picks=None, decim=3) assert_true(ica.n_components_ == 4) # epochs extraction from raw fit assert_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) with warnings.catch_warnings(record=True): # ICA does not converge ica.fit(raw, picks=picks, start=start, stop=stop2) sources = ica.get_sources(epochs).get_data() assert_true(ica.mixing_matrix_.shape == (2, 2)) assert_true(ica.unmixing_matrix_.shape == (2, 2)) assert_true(ica.pca_components_.shape == (4, len(picks))) assert_true(sources.shape[1] == ica.n_components_) for exclude in [[], [0]]: ica.exclude = [0] ica.labels_ = {'foo': [0]} ica.save(test_ica_fname) ica_read = read_ica(test_ica_fname) assert_true(ica.exclude == ica_read.exclude) assert_equal(ica.labels_, ica_read.labels_) ica.exclude = [] ica.apply(raw, exclude=[1]) assert_true(ica.exclude == []) ica.exclude = [0, 1] ica.apply(raw, exclude=[1]) assert_true(ica.exclude == [0, 1]) ica_raw = ica.get_sources(raw) assert_true(ica.exclude == [ica_raw.ch_names.index(e) for e in ica_raw.info['bads']]) # test filtering d1 = ica_raw._data[0].copy() with warnings.catch_warnings(record=True): # dB warning ica_raw.filter(4, 20) assert_true((d1 != ica_raw._data[0]).any()) d1 = ica_raw._data[0].copy() with warnings.catch_warnings(record=True): # dB warning ica_raw.notch_filter([10]) assert_true((d1 != ica_raw._data[0]).any()) ica.n_pca_components = 2 ica.save(test_ica_fname) ica_read = read_ica(test_ica_fname) assert_true(ica.n_pca_components == ica_read.n_pca_components) # 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_true(ica.ch_names == ica_read.ch_names) assert_true(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 scrore 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_true(ica.n_components_ == len(scores)) # check univariate stats scores = ica.score_sources(raw, score_func=stats.skew) # check exception handling assert_raises(ValueError, ica.score_sources, raw, target=np.arange(1)) params = [] params += [(None, -1, slice(2), [0, 1])] # varicance, kurtosis idx 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) with warnings.catch_warnings(record=True): idx, scores = ica.find_bads_ecg(raw, method='ctps') assert_equal(len(scores), ica.n_components_) idx, scores = ica.find_bads_ecg(raw, method='correlation') assert_equal(len(scores), ica.n_components_) idx, scores = ica.find_bads_ecg(epochs, method='ctps') assert_equal(len(scores), ica.n_components_) assert_raises(ValueError, ica.find_bads_ecg, epochs.average(), method='ctps') assert_raises(ValueError, ica.find_bads_ecg, raw, method='crazy-coupling') 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 idx, scores = ica.find_bads_eog(raw) assert_true(isinstance(scores, list)) assert_equal(len(scores[0]), ica.n_components_) # 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_true(ica.n_components_ == len(scores)) # check univariate stats scores = ica.score_sources(epochs, score_func=stats.skew) # check exception handling assert_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 warnings.catch_warnings(record=True): # filter attenuation warning ecg_events = ica_find_ecg_events(raw, sources[np.abs(ecg_scores).argmax()]) assert_true(ecg_events.ndim == 2) # eog functionality eog_scores = ica.score_sources(raw, target='EOG 061', score_func='pearsonr') with warnings.catch_warnings(record=True): # filter attenuation warning eog_events = ica_find_eog_events(raw, sources[np.abs(eog_scores).argmax()]) assert_true(eog_events.ndim == 2) # Test ica fiff export ica_raw = ica.get_sources(raw, start=0, stop=100) assert_true(ica_raw.last_samp - ica_raw.first_samp == 100) assert_true(len(ica_raw._filenames) == 0) # API consistency ica_chans = [ch for ch in ica_raw.ch_names if 'ICA' in ch] assert_true(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 = Raw(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_true(ica_epochs.events.shape == epochs.events.shape) ica_chans = [ch for ch in ica_epochs.ch_names if 'ICA' in ch] assert_true(ica.n_components_ == len(ica_chans)) assert_true(ica.n_components_ == ica_epochs.get_data().shape[1]) assert_true(ica_epochs._raw is None) assert_true(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_true(ncomps_ == expected)
def compute_ica(raw, subject, n_components=0.99, picks=None, decim=None, reject=None, ecg_tmin=-0.5, ecg_tmax=0.5, eog_tmin=-0.5, eog_tmax=0.5, n_max_ecg=3, n_max_eog=1, n_max_ecg_epochs=200, show=True, img_scale=1.0, random_state=None, report=None, artifact_stats=None): """Run ICA in raw data Parameters ----------, raw : instance of Raw Raw measurements to be decomposed. subject : str The name of the subject. picks : array-like of int, shape(n_channels, ) | None Channels to be included. This selection remains throughout the initialized ICA solution. If None only good data channels are used. Defaults to None. n_components : int | float | None | 'rank' The number of components used for ICA decomposition. If int, it must be smaller then max_pca_components. If None, all PCA components will be used. If float between 0 and 1 components can will be selected by the cumulative percentage of explained variance. If 'rank', the number of components equals the rank estimate. Defaults to 0.99. decim : int | None Increment for selecting each nth time slice. If None, all samples within ``start`` and ``stop`` are used. Defalts to None. reject : dict | None Rejection parameters based on peak to peak amplitude. Valid keys are 'grad' | 'mag' | 'eeg' | 'eog' | 'ecg'. If reject is None then no rejection is done. You should use such parameters to reject big measurement artifacts and not EOG for example. It only applies if `inst` is of type Raw. Defaults to {'mag': 5e-12} ecg_tmin : float Start time before ECG event. Defaults to -0.5. ecg_tmax : float End time after ECG event. Defaults to 0.5. eog_tmin : float Start time before rog event. Defaults to -0.5. eog_tmax : float End time after rog event. Defaults to 0.5. n_max_ecg : int | None The maximum number of ECG components to exclude. Defaults to 3. n_max_eog : int | None The maximum number of EOG components to exclude. Defaults to 1. n_max_ecg_epochs : int The maximum number of ECG epochs to use for phase-consistency estimation. Defaults to 200. show : bool Show figure if True scale_img : float The scaling factor for the report. Defaults to 1.0. random_state : None | int | instance of np.random.RandomState np.random.RandomState to initialize the FastICA estimation. As the estimation is non-deterministic it can be useful to fix the seed to have reproducible results. Defaults to None. report : instance of Report | None The report object. If None, a new report will be generated. artifact_stats : None | dict A dict that contains info on amplitude ranges of artifacts and numbers of events, etc. by channel type. Returns ------- ica : instance of ICA The ICA solution. report : dict A dict with an html report ('html') and artifact statistics ('stats'). """ if report is None: report = Report(subject=subject, title='ICA preprocessing') if n_components == 'rank': n_components = raw.estimate_rank(picks=picks) ica = ICA(n_components=n_components, max_pca_components=None, random_state=random_state, max_iter=256) ica.fit(raw, picks=picks, decim=decim, reject=reject) comment = [] for ch in ('mag', 'grad', 'eeg'): if ch in ica: comment += [ch.upper()] if len(comment) > 0: comment = '+'.join(comment) + ' ' else: comment = '' topo_ch_type = 'mag' if 'GRAD' in comment and 'MAG' not in comment: topo_ch_type = 'grad' elif 'EEG' in comment: topo_ch_type = 'eeg' ########################################################################### # 2) identify bad components by analyzing latent sources. title = '%s related to %s artifacts (red) ({})'.format(subject) # generate ECG epochs use detection via phase statistics reject_ = {'mag': 5e-12, 'grad': 5000e-13, 'eeg': 300e-6} if reject is not None: reject_.update(reject) for ch_type in ['mag', 'grad', 'eeg']: if ch_type not in ica: reject_.pop(ch_type) picks_ = np.array([raw.ch_names.index(k) for k in ica.ch_names]) if 'eeg' in ica: if 'ecg' in raw: picks_ = np.append(picks_, pick_types(raw.info, meg=False, ecg=True)[0]) else: logger.info('There is no ECG channel, trying to guess ECG from ' 'magnetormeters') if artifact_stats is None: artifact_stats = dict() ecg_epochs = create_ecg_epochs(raw, tmin=ecg_tmin, tmax=ecg_tmax, keep_ecg=True, picks=picks_, reject=reject_) n_ecg_epochs_found = len(ecg_epochs.events) artifact_stats['ecg_n_events'] = n_ecg_epochs_found n_max_ecg_epochs = min(n_max_ecg_epochs, n_ecg_epochs_found) artifact_stats['ecg_n_used'] = n_max_ecg_epochs sel_ecg_epochs = np.arange(n_ecg_epochs_found) rng = np.random.RandomState(42) rng.shuffle(sel_ecg_epochs) ecg_ave = ecg_epochs.average() report.add_figs_to_section(ecg_ave.plot(), 'ECG-full', 'artifacts') ecg_epochs = ecg_epochs[sel_ecg_epochs[:n_max_ecg_epochs]] ecg_ave = ecg_epochs.average() report.add_figs_to_section(ecg_ave.plot(), 'ECG-used', 'artifacts') _put_artifact_range(artifact_stats, ecg_ave, kind='ecg') ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') if len(ecg_inds) > 0: ecg_evoked = ecg_epochs.average() del ecg_epochs fig = ica.plot_scores(scores, exclude=ecg_inds, labels='ecg', title='', show=show) report.add_figs_to_section(fig, 'scores ({})'.format(subject), section=comment + 'ECG', scale=img_scale) current_exclude = [e for e in ica.exclude] # issue #2608 MNE fig = ica.plot_sources(raw, ecg_inds, exclude=ecg_inds, title=title % ('components', 'ecg'), show=show) report.add_figs_to_section(fig, 'sources ({})'.format(subject), section=comment + 'ECG', scale=img_scale) ica.exclude = current_exclude fig = ica.plot_components(ecg_inds, ch_type=topo_ch_type, title='', colorbar=True, show=show) report.add_figs_to_section(fig, title % ('sources', 'ecg'), section=comment + 'ECG', scale=img_scale) ica.exclude = current_exclude ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds fig = ica.plot_sources(ecg_evoked, exclude=ecg_inds, show=show) report.add_figs_to_section(fig, 'evoked sources ({})'.format(subject), section=comment + 'ECG', scale=img_scale) fig = ica.plot_overlay(ecg_evoked, exclude=ecg_inds, show=show) report.add_figs_to_section(fig, 'rejection overlay ({})'.format(subject), section=comment + 'ECG', scale=img_scale) # detect EOG by correlation picks_eog = np.concatenate([ picks_, pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True) ]) eog_epochs = create_eog_epochs(raw, tmin=eog_tmin, tmax=eog_tmax, picks=picks_eog, reject=reject_) artifact_stats['eog_n_events'] = len(eog_epochs.events) artifact_stats['eog_n_used'] = artifact_stats['eog_n_events'] eog_ave = eog_epochs.average() report.add_figs_to_section(eog_ave.plot(), 'EOG-used', 'artifacts') _put_artifact_range(artifact_stats, eog_ave, kind='eog') eog_inds = None if len(eog_epochs.events) > 0: eog_inds, scores = ica.find_bads_eog(eog_epochs) if eog_inds is not None and len(eog_epochs.events) > 0: fig = ica.plot_scores(scores, exclude=eog_inds, labels='eog', show=show, title='') report.add_figs_to_section(fig, 'scores ({})'.format(subject), section=comment + 'EOG', scale=img_scale) current_exclude = [e for e in ica.exclude] # issue #2608 MNE fig = ica.plot_sources(raw, eog_inds, exclude=ecg_inds, title=title % ('sources', 'eog'), show=show) report.add_figs_to_section(fig, 'sources', section=comment + 'EOG', scale=img_scale) ica.exclude = current_exclude fig = ica.plot_components(eog_inds, ch_type=topo_ch_type, title='', colorbar=True, show=show) report.add_figs_to_section(fig, title % ('components', 'eog'), section=comment + 'EOG', scale=img_scale) ica.exclude = current_exclude eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds eog_evoked = eog_epochs.average() fig = ica.plot_sources(eog_evoked, exclude=eog_inds, show=show) report.add_figs_to_section(fig, 'evoked sources ({})'.format(subject), section=comment + 'EOG', scale=img_scale) fig = ica.plot_overlay(eog_evoked, exclude=eog_inds, show=show) report.add_figs_to_section(fig, 'rejection overlay({})'.format(subject), section=comment + 'EOG', scale=img_scale) else: del eog_epochs # check the amplitudes do not change if len(ica.exclude) > 0: fig = ica.plot_overlay(raw, show=show) # EOG artifacts remain html = _render_components_table(ica) report.add_htmls_to_section(html, captions='excluded components', section='ICA rejection summary (%s)' % ch_type) report.add_figs_to_section(fig, 'rejection overlay({})'.format(subject), section=comment + 'RAW', scale=img_scale) return ica, dict(html=report, stats=artifact_stats)