def find_eog_artifacts(self): self._eog_average = create_eog_epochs(self.filtered, picks=self._picks_eeg).average() self._eog_epochs = create_eog_epochs( self.filtered) # get single EOG trials self._eog_inds, self._eog_scores = self._ica.find_bads_eog( self._eog_epochs) # find via correlation
def perform_ICA(raw, eeg_reject=50.): picks_eeg = mne.pick_types(raw.info, meg=False, eeg=True, eog=False, stim=False, exclude='bads') ica = ICA(n_components=25, random_state=1) # using default method 'fastica' reject = dict(eeg=eeg_reject) ica.fit(raw, picks=picks_eeg, reject=reject) eog_average = create_eog_epochs(raw, reject=reject, picks=picks_eeg).average() eog_epochs = create_eog_epochs(raw, reject=reject) # get single EOG trials eog_inds, scores = ica.find_bads_eog(eog_epochs) # find via correlation ica.exclude.extend(eog_inds) ica.apply(raw) return ica
def ica_correction(raw, picks): # ## Function "ica_correction" will correct artifacts in eeg data # (eg. blink) using ICA and return an ICA array under "my-ica.fif" ## Will also plot ICA components from mne.preprocessing import ICA from mne.preprocessing import create_eog_epochs #ICA parameters n_components = 25 # if float, select n_components by explained variance of PCA method = 'fastica' # for comparison with EEGLAB try "extended-infomax" here decim = 3 # we need sufficient statistics, not all time points -> saves time # we will also set state of the random number generator - ICA is a # non-deterministic algorithm, but we want to have the same decomposition # and the same order of components each time this tutorial is run random_state = 23 ica = ICA(n_components=n_components, method=method, random_state=random_state) ica.fit(raw, picks=picks, decim=decim, reject=dict(eeg=200e-6)) ica.plot_components() eog_average = create_eog_epochs(raw, reject=dict(eeg=200e-6), picks=picks).average() n_max_eog = 1 # here we bet on finding the vertical EOG components eog_epochs = create_eog_epochs(raw, reject=dict(eeg=200e-6), picks=picks) # get single EOG trials eog_inds, scores = ica.find_bads_eog(eog_epochs) # find via correlation ica.plot_scores(scores, exclude=eog_inds) # look at r scores of components # we can see that only one component is highly correlated and that this # component got detected by our correlation analysis (red). ica.plot_sources(eog_average, exclude=eog_inds) # look at source time course ica.plot_properties(eog_epochs, picks=eog_inds, psd_args={'fmax': 35.}, image_args={'sigma': 1.}) print(ica.labels_) ica.plot_overlay(eog_average, exclude=eog_inds, show=False) ica.exclude.extend(eog_inds)
def filter_with_ica(raw_data, event_id, thresh): """Use ICA to filter data for artifacts. Args: raw_data: Raw array of data events: Event Array event_id: A Dictionary of events thresh: A float that indicates a threshold Resturns: raw: ICA and bandpass filtered data """ raw = raw_data.copy().crop(2, raw_data.times.max()) #raw = raw_data.copy() raw.filter(3, 42, n_jobs=1, fir_design='firwin') # Run ICA method = 'fastica' # Choose other parameters n_components, decim, random_state = 25, 3, 42 # if float, select n_components by explained variance of PCA ica = ICA(n_components=n_components, method=method, random_state=random_state) ica.fit(raw, picks=pick_types(raw.info, eeg=True, misc=False, stim=False, eog=False), decim=decim) eog_epochs = create_eog_epochs(raw) # get single EOG trials eog_inds, scores = ica.find_bads_eog( eog_epochs, threshold=thresh) # find via correlation ica.exclude.extend(eog_inds) ica.apply(raw) return raw
def test_plot_ica_overlay(): """Test plotting of ICA cleaning.""" import matplotlib.pyplot as plt raw = _get_raw(preload=True) picks = _get_picks(raw) ica = ICA(noise_cov=read_cov(cov_fname), n_components=2, max_pca_components=3, n_pca_components=3) # can't use info.normalize_proj here because of how and when ICA and Epochs # objects do picking of Raw data with pytest.warns(RuntimeWarning, match='projection'): ica.fit(raw, picks=picks) # don't test raw, needs preload ... with pytest.warns(RuntimeWarning, match='projection'): ecg_epochs = create_ecg_epochs(raw, picks=picks) ica.plot_overlay(ecg_epochs.average()) with pytest.warns(RuntimeWarning, match='projection'): eog_epochs = create_eog_epochs(raw, picks=picks) ica.plot_overlay(eog_epochs.average()) pytest.raises(TypeError, ica.plot_overlay, raw[:2, :3][0]) ica.plot_overlay(raw) plt.close('all') # smoke test for CTF raw = read_raw_fif(raw_ctf_fname) raw.apply_gradient_compensation(3) picks = pick_types(raw.info, meg=True, ref_meg=False) ica = ICA(n_components=2, max_pca_components=3, n_pca_components=3) ica.fit(raw, picks=picks) with pytest.warns(RuntimeWarning, match='longer than'): ecg_epochs = create_ecg_epochs(raw) ica.plot_overlay(ecg_epochs.average()) plt.close('all')
def test_plot_ica_overlay(): """Test plotting of ICA cleaning.""" import matplotlib.pyplot as plt raw = _get_raw(preload=True) picks = _get_picks(raw) ica = ICA(noise_cov=read_cov(cov_fname), n_components=2, max_pca_components=3, n_pca_components=3) # can't use info.normalize_proj here because of how and when ICA and Epochs # objects do picking of Raw data with warnings.catch_warnings(record=True): # bad proj ica.fit(raw, picks=picks) # don't test raw, needs preload ... with warnings.catch_warnings(record=True): # bad proj ecg_epochs = create_ecg_epochs(raw, picks=picks) ica.plot_overlay(ecg_epochs.average()) with warnings.catch_warnings(record=True): # bad proj eog_epochs = create_eog_epochs(raw, picks=picks) ica.plot_overlay(eog_epochs.average()) assert_raises(TypeError, ica.plot_overlay, raw[:2, :3][0]) ica.plot_overlay(raw) plt.close('all') # smoke test for CTF raw = read_raw_fif(raw_ctf_fname) raw.apply_gradient_compensation(3) picks = pick_types(raw.info, meg=True, ref_meg=False) ica = ICA(n_components=2, max_pca_components=3, n_pca_components=3) ica.fit(raw, picks=picks) ecg_epochs = create_ecg_epochs(raw) ica.plot_overlay(ecg_epochs.average()) plt.close('all')
def test_plot_ica_overlay(): """Test plotting of ICA cleaning.""" raw = _get_raw(preload=True) picks = _get_picks(raw) ica = ICA(noise_cov=read_cov(cov_fname), n_components=2, max_pca_components=3, n_pca_components=3) # can't use info.normalize_proj here because of how and when ICA and Epochs # objects do picking of Raw data with pytest.warns(RuntimeWarning, match='projection'): ica.fit(raw, picks=picks) # don't test raw, needs preload ... with pytest.warns(RuntimeWarning, match='projection'): ecg_epochs = create_ecg_epochs(raw, picks=picks) ica.plot_overlay(ecg_epochs.average()) with pytest.warns(RuntimeWarning, match='projection'): eog_epochs = create_eog_epochs(raw, picks=picks) ica.plot_overlay(eog_epochs.average()) pytest.raises(TypeError, ica.plot_overlay, raw[:2, :3][0]) pytest.raises(TypeError, ica.plot_overlay, raw, exclude=2) ica.plot_overlay(raw) plt.close('all') # smoke test for CTF raw = read_raw_fif(raw_ctf_fname) raw.apply_gradient_compensation(3) picks = pick_types(raw.info, meg=True, ref_meg=False) ica = ICA(n_components=2, max_pca_components=3, n_pca_components=3) ica.fit(raw, picks=picks) with pytest.warns(RuntimeWarning, match='longer than'): ecg_epochs = create_ecg_epochs(raw) ica.plot_overlay(ecg_epochs.average()) plt.close('all')
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 getPlot(path): with open(path, "r") as f: data = f.read().split('\n')[1:-1] data = np.array([[i.split(';')[j] for j in range(len(i.split(';'))) if j in [2, 4, 10, 12]] for i in data]).T ch_names = ['AF3', 'T8', 'AF4', 'T7'] # TODO: finish this list info = mne.create_info(ch_names, sfreq=128, ch_types='eeg') raw = mne.io.RawArray(data, info) montage = mne.channels.make_standard_montage(kind='standard_1020', head_size=0.095) raw.set_montage(montage, match_case=True) raw.plot_psd(area_mode='range', average=False); raw.info['bads'] = ['AF3'] raw.interpolate_bads(reset_bads=True, mode='accurate') raw.plot(block=True); eog_events = mne.preprocessing.find_eog_events(raw, ch_name='AF3') n_blinks = len(eog_events) onset = eog_events[:, 0] / raw.info['sfreq'] - 0.25 duration = np.repeat(0.5, n_blinks) annot = mne.Annotations(onset, duration, ['bad blink'] * n_blinks, orig_time=raw.info['meas_date']) raw.set_annotations(annot) print(raw.annotations) raw.plot(block=True, events=eog_events); from mne.preprocessing import ICA, create_eog_epochs decim = 3 reject = dict(eeg=40e-6) #raw.filter(1., None, fir_design='firwin'); ica = ICA(n_components=3, method='fastica', random_state=1) ica.fit(raw, decim=3) print(ica) #ica.plot_components(ch_type='eeg'); eog_average = create_eog_epochs(raw, ch_name='AF3', reject_by_annotation=False).average(); eog_epochs = create_eog_epochs(raw, ch_name='AF3', reject_by_annotation=False); # get single EOG trials eog_inds, scores = ica.find_bads_eog(eog_epochs, ch_name='AF3', threshold=2.0, l_freq=1, h_freq=10, reject_by_annotation=True); # In[10]: ica.plot_scores(scores, exclude=eog_inds); ica.plot_sources(eog_average);
def detect_eog_from_info(input_file): raw = raw_mne_from_tdt(input_file) #TODO: this would work if we had some info about eog or meg events in the # raw info file... picks_eog = mne.pick_types(raw.info, meg=false, eeg=false, eog=true, stim=false, exclude='bads') reject = dict(mag=5e-12, grad=4000e-13, eeg=80e-6) # lowpass at 50 raw.filter(None, 50., fir_design='firwin') # 1hz high pass is often helpful for fitting ica raw.filter(1., None, n_jobs=1, fir_design='firwin') eog_average = create_eog_epochs(raw, reject=reject, picks=picks_eog).average() eog_epochs = create_eog_epochs(raw, reject=reject) # get single EOG trials eog_inds, scores = ica.find_bads_eog(eog_epochs) # find via correlation ica.plot_scores(scores, exclude=eog_inds) # look at r scores of components ica.plot_sources(eog_average, exclude=eog_inds) # look at source time course
def test_plot_ica_overlay(): """Test plotting of ICA cleaning """ raw = _get_raw() picks = _get_picks(raw) ica_picks = pick_types(raw.info, meg=True, eeg=False, stim=False, ecg=False, eog=False, exclude="bads") ica = ICA(noise_cov=read_cov(cov_fname), n_components=2, max_pca_components=3, n_pca_components=3) ica.fit(raw, picks=ica_picks) # don't test raw, needs preload ... ecg_epochs = create_ecg_epochs(raw, picks=picks) ica.plot_overlay(ecg_epochs.average()) eog_epochs = create_eog_epochs(raw, picks=picks) ica.plot_overlay(eog_epochs.average()) assert_raises(ValueError, ica.plot_overlay, raw[:2, :3][0]) plt.close("all")
def test_plot_ica_overlay(): """Test plotting of ICA cleaning """ raw = _get_raw() picks = _get_picks(raw) ica = ICA(noise_cov=read_cov(cov_fname), n_components=2, max_pca_components=3, n_pca_components=3) ica.fit(raw, picks=picks) # don't test raw, needs preload ... ecg_epochs = create_ecg_epochs(raw, picks=picks) ica.plot_overlay(ecg_epochs.average()) eog_epochs = create_eog_epochs(raw, picks=picks) ica.plot_overlay(eog_epochs.average()) assert_raises(ValueError, ica.plot_overlay, raw[:2, :3][0]) plt.close('all')
def ica_correction(raw, picks): """Function "ica_correction" will correct artifacts in eeg data (eg. blink) using ICA and return an ICA array under "my-ica.fif" Will also plot ICA components""" from mne.preprocessing import ICA from mne.preprocessing import create_eog_epochs #ICA parameters n_components = 25 # if float, select n_components by explained variance of PCA method = 'fastica' # for comparison with EEGLAB try "extended-infomax" here decim = 3 # we need sufficient statistics, not all time points -> saves time # we will also set state of the random number generator - ICA is a # non-deterministic algorithm, but we want to have the same decomposition # and the same order of components each time this tutorial is run random_state = 23 ica = ICA(n_components=n_components, method=method, random_state=random_state) ica.fit(raw, picks=picks, decim=decim, reject=dict(eeg=200e-6)) ica.plot_components() n_max_eog = 1 #don't expect to find horizontal eog components title = 'Sources related to EOG components (red)' eog_epochs = create_eog_epochs(raw, tmin=-.5, tmax=1, picks=picks) eog_inds, scores = ica.find_bads_eog(eog_epochs) ica.plot_scores(scores, exclude=eog_inds, title=title, labels='eog') show_picks = np.abs(scores).argsort()[::-1][:5] ica.plot_sources(raw, show_picks, exclude=eog_inds, title=title) ica.plot_components(eog_inds, title=title, colorbar=True) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds # uncomment this for reading and writing #ica.save('my-ica.fif') #ica = read_ica('my-ica.fif') #apply to epochs ica.apply(epochs)
def test_regress_artifact(): """Test regressing data.""" raw = read_raw_fif(raw_fname).pick_types(meg=False, eeg=True, eog=True) raw.load_data() epochs = create_eog_epochs(raw) epochs.apply_baseline((None, None)) orig_data = epochs.get_data('eeg') orig_norm = np.linalg.norm(orig_data) epochs_clean, betas = regress_artifact(epochs) regress_artifact(epochs, betas=betas, copy=False) # inplace, and w/betas assert_allclose(epochs_clean.get_data(), epochs.get_data()) clean_data = epochs_clean.get_data('eeg') clean_norm = np.linalg.norm(clean_data) assert orig_norm / 2 > clean_norm > orig_norm / 10 with pytest.raises(ValueError, match=r'Invalid value.*betas\.shape.*'): regress_artifact(epochs, betas=betas[:-1]) with pytest.raises(ValueError, match='cannot be contained in'): regress_artifact(epochs, picks='eog', picks_artifact='eog')
def test_plot_ica_overlay(): """Test plotting of ICA cleaning.""" import matplotlib.pyplot as plt raw = _get_raw(preload=True) picks = _get_picks(raw) ica = ICA(noise_cov=read_cov(cov_fname), n_components=2, max_pca_components=3, n_pca_components=3) # can't use info.normalize_proj here because of how and when ICA and Epochs # objects do picking of Raw data with warnings.catch_warnings(record=True): # bad proj ica.fit(raw, picks=picks) # don't test raw, needs preload ... with warnings.catch_warnings(record=True): # bad proj ecg_epochs = create_ecg_epochs(raw, picks=picks) ica.plot_overlay(ecg_epochs.average()) with warnings.catch_warnings(record=True): # bad proj eog_epochs = create_eog_epochs(raw, picks=picks) ica.plot_overlay(eog_epochs.average()) assert_raises(ValueError, ica.plot_overlay, raw[:2, :3][0]) ica.plot_overlay(raw) plt.close('all')
def make_eog_epochs(*, raw: mne.io.BaseRaw, eog_channels: Optional[Iterable[str]], subject: str, session: str, run: Optional[str] = None) -> Optional[mne.Epochs]: """Create EOG epochs. No rejection thresholds will be applied. """ if eog_channels: ch_names = eog_channels assert all([ch_name in raw.ch_names for ch_name in ch_names]) else: ch_idx = mne.pick_types(raw.info, meg=False, eog=True) ch_names = [raw.ch_names[i] for i in ch_idx] del ch_idx if ch_names: msg = 'Creating EOG epochs …' logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) eog_epochs = create_eog_epochs(raw, ch_name=ch_names, baseline=(None, -0.2)) if len(eog_epochs) == 0: msg = ('No EOG events could be found. Not running EOG artifact ' 'detection.') logger.warning(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) eog_epochs = None else: msg = ('No EOG channel is present. Cannot automate IC detection ' 'for EOG') logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) eog_epochs = None return eog_epochs
def compute_ica(subject, data_folder): """Function will compute ICA on raw and apply the ICA. Parameters ---------- subject : string the subject id to be loaded """ raw = mne.io.Raw(data_folder + "%s_bp-raw.fif" % subject, preload=True) raw.set_montage = montage raw.apply_proj() # raw.resample(512, n_jobs=2) # ICA Part ica = ICA(n_components=None, max_pca_components=40, method='fastica', max_iter=256) picks = mne.pick_types( raw.info, meg=False, eeg=True, stim=False, exclude='bads') ica.fit(raw, picks=picks, decim=decim, reject=reject) # maximum number of components to reject n_max_eog = 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="Ext4", # 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(data_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(data_folder + "pics/%s_ecg_sources.png" % subject) # fig = ica.plot_components(ecg_inds, title=title % ('ecg', subject), # colorbar=True) # fig.savefig(data_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(data_folder + "pics/%s_ecg_sources_ave.png" % subject) # # # plot ECG cleaning # ica.plot_overlay(ecg_evoked, exclude=ecg_inds) # fig.savefig(data_folder + "pics/%s_ecg_sources_clean_ave.png" % subject) # DETECT EOG BY CORRELATION # HORIZONTAL EOG eog_epochs = create_eog_epochs(raw, ch_name="EXG4") eog_indices, scores = ica.find_bads_eog(raw, ch_name="EXG4") fig = ica.plot_scores( scores, exclude=eog_indices, title=title % ('eog', subject)) fig.savefig(data_folder + "pics/%s_eog_scores.png" % subject) fig = ica.plot_components( eog_indices, title=title % ('eog', subject), colorbar=True) fig.savefig(data_folder + "pics/%s_eog_component.png" % subject) eog_indices = eog_indices[:n_max_eog] ica.exclude += eog_indices del eog_epochs ########################################################################## # Apply the solution to Raw, Epochs or Evoked like this: raw_ica = ica.apply(raw) ica.save(data_folder + "%s-ica.fif" % subject) # save ICA componenets # Save raw with ICA removed raw_ica.save(data_folder + "%s_bp_ica-raw.fif" % subject, overwrite=True) plt.close("all")
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)
ica = ICA(n_components=n_components, method=method, random_state=random_state, max_iter=200) print(ica) reject = dict( grad=4000e-13, # T / m (gradiometers) mag=4e-12) # T (magnetometers) ica.fit(raw_sss, picks=picks_meg, decim=decim, reject=reject) print(ica) raw_sss.plot_psd(fmax=100) eog_average = create_eog_epochs(raw_sss, reject=dict(mag=5e-12, grad=4000e-13), picks=picks_meg).average() 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)
def detect_eog_artifacts(ica, raw, subject, session, report): pick_eog = mne.pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True) if pick_eog.any(): msg = 'Performing automated EOG artifact detection …' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) # Do not reject epochs based on amplitude. eog_epochs = create_eog_epochs(raw, reject=None, baseline=(None, -0.2), tmin=-0.5, tmax=0.5) eog_evoked = eog_epochs.average() eog_inds, scores = ica.find_bads_eog( eog_epochs, threshold=config.ica_eog_threshold) ica.exclude = eog_inds msg = (f'Detected {len(eog_inds)} EOG-related ICs in ' f'{len(eog_epochs)} EOG epochs.') logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) del eog_epochs # Plot scores fig = ica.plot_scores(scores, labels='eog', show=config.interactive) report.add_figs_to_section(figs=fig, captions='Scores - EOG', section=f'sub-{subject}') # Plot source time course fig = ica.plot_sources(eog_evoked, show=config.interactive) report.add_figs_to_section(figs=fig, captions='Source time course - EOG', section=f'sub-{subject}') # Plot original & corrected data fig = ica.plot_overlay(eog_evoked, show=config.interactive) report.add_figs_to_section(figs=fig, captions='Corrections - EOG', section=f'sub-{subject}') else: eog_inds = list() msg = ('No EOG channel is present. Cannot automate IC detection ' 'for EOG') logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) return eog_inds
ica.plot_sources(raw, show_picks, exclude=eog_inds, title=title % 'eog') ica.plot_components(eog_inds, title=title % 'eog', colorbar=True) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds ############################################################################### # 3) Assess component selection and unmixing quality # estimate average artifact ecg_evoked = ecg_epochs.average() ica.plot_sources(ecg_evoked, exclude=ecg_inds) # plot ECG sources + selection ica.plot_overlay(ecg_evoked, exclude=ecg_inds) # plot ECG cleaning eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=picks).average() ica.plot_sources(eog_evoked, exclude=eog_inds) # plot EOG sources + selection ica.plot_overlay(eog_evoked, exclude=eog_inds) # plot EOG cleaning # check the amplitudes do not change ica.plot_overlay(raw) # EOG artifacts remain ############################################################################### # To save an ICA solution you can say: # ica.save('my_ica.fif') # You can later load the solution by saying: # from mne.preprocessing import read_ica # read_ica('my_ica.fif')
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
average_ecg = create_ecg_epochs(raw).average() print('We found %i ECG events' % average_ecg.nave) joint_kwargs = dict(ts_args=dict(time_unit='s'), topomap_args=dict(time_unit='s')) average_ecg.plot_joint(**joint_kwargs) ############################################################################### # we can see typical time courses and non dipolar topographies # not the order of magnitude of the average artifact related signal and # compare this to what you observe for brain signals ############################################################################### # EOG # --- average_eog = create_eog_epochs(raw).average() print('We found %i EOG events' % average_eog.nave) average_eog.plot_joint(**joint_kwargs) ############################################################################### # Knowing these artifact patterns is of paramount importance when # judging about the quality of artifact removal techniques such as SSP or ICA. # As a rule of thumb you need artifact amplitudes orders of magnitude higher # than your signal of interest and you need a few of such events in order # to find decompositions that allow you to estimate and remove patterns related # to artifacts. # # Consider the following tutorials for correcting this class of artifacts: # - :ref:`sphx_glr_auto_tutorials_plot_artifacts_correction_filtering.py` # - :ref:`sphx_glr_auto_tutorials_plot_artifacts_correction_ica.py` # - :ref:`sphx_glr_auto_tutorials_plot_artifacts_correction_ssp.py`
fname = argv[1] reject_ica = {'mag': 6e-12, 'grad': 6e-10} #%% read and filter data Raw = read_raw_fif(fname, preload=True) 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:
# get and save events raw, events = import_bdf(data_path, subject) # save events mne.write_events(data_path + subject + '-eve.fif', events) raw.filter(1., 40, fir_window='hamming', fir_design='firwin', n_jobs=6) # plot raw.plot(events=events, duration=10, n_channels=64) raw.save(data_path + raw_fname) decim = 4 # we need sufficient statistics, not all time points -> saves time picks = mne.pick_types(raw.info, eeg=True, eog=True, exclude='bads') eog_average = create_eog_epochs(raw, picks=picks).average() #eog_average = create_eog_epochs(raw, picks=picks).average(picks=picks[:-2]) #eog_average.average() print('We found %i EOG events' % eog_average.nave) eog_average.plot_joint() # Initialize the ICA estimator and fit it on the data ica = mne.preprocessing.ICA(n_components=25, method='extended-infomax') ica.fit(raw, decim=decim) # Find components highy correlated with the eog events n_max_eog = 3 # here we bet on finding the vertical EOG components eog_epochs = create_eog_epochs(raw, picks=picks) # get single EOG trials eog_inds, scores = ica.find_bads_eog(eog_epochs) # find via correlation ica.plot_scores(scores, exclude=eog_inds) # look at r scores of components
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 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']
def plot_artefact_overview(raw_orig, raw_clean, stim_event_ids=[1], stim_ch='STI 014', resp_ch=None, resp_event_ids=None, ecg_ch='EEG 002', eog1_ch='EEG 001', eog2_ch='EEG 003', eog_tmin=-0.5, eog_tmax=0.5, eog_id=998, eog_lfreq=8., eog_hfreq=20., ecg_tmin=-0.5, ecg_tmax=0.5, ecg_id=999, ecg_lfreq=8., ecg_hfreq=20., stim_tmin=-0.2, stim_tmax=0.8, resp_tmin=-0.6, resp_tmax=0.4, eve_output='onset', overview_fname=None): ''' Plot an overview of the artefact rejection with ECG, EOG vertical and EOG horizontal channels. Shows the data before and after cleaning along with a difference plot. raw_orig: instance of mne.io.Raw | str File name of raw object of the uncleaned data. raw_clean: instance of mne.io.Raw | str File name of raw object of the cleaned data. stim_event_ids: list List of stim or resp event ids. Defaults to [1]. resp_event_ids: list List of stim or resp event ids. Defaults to None. eve_output: 'onset' | 'offset' | 'step' Whether to report when events start, when events end, or both. overview_fname: str | None Name to save the plot generated. (considers raw_clean.info['filename']) Notes: Time is always shown in milliseconds (1e3) and the MEG data from mag is always in femtoTesla (fT) (1e15) ''' from mne.preprocessing import create_ecg_epochs, create_eog_epochs raw = check_read_raw(raw_orig, preload=True) raw_clean = check_read_raw(raw_clean, preload=True) if not overview_fname: try: overview_fname = raw_clean.info['filename'].rsplit('-raw.fif')[0] + ',overview-plot.png' except: overview_fname = 'overview-plot.png' # stim related events events = mne.find_events(raw, stim_channel=stim_ch, output='onset') events_clean = mne.find_events(raw_clean, stim_channel=stim_ch, output='onset') epochs = mne.Epochs(raw, events, event_id=stim_event_ids, tmin=stim_tmin, tmax=stim_tmax, picks=mne.pick_types(raw.info, meg=True, exclude='bads')) evoked = epochs.average() epochs_clean = mne.Epochs(raw_clean, events_clean, event_id=stim_event_ids, tmin=stim_tmin, tmax=stim_tmax, picks=mne.pick_types(raw_clean.info, meg=True, exclude='bads')) evoked_clean = epochs_clean.average() stim_diff_signal = mne.combine_evoked([evoked, evoked_clean], weights=[1, -1]) if resp_ch: # stim related events resp_events = mne.find_events(raw, stim_channel=resp_ch, output='onset') resp_events_clean = mne.find_events(raw_clean, stim_channel=resp_ch, output='onset') resp_epochs = mne.Epochs(raw, resp_events, event_id=resp_event_ids, tmin=resp_tmin, tmax=resp_tmax, picks=mne.pick_types(raw.info, meg=True, exclude='bads')) resp_evoked = resp_epochs.average() resp_epochs_clean = mne.Epochs(raw_clean, resp_events_clean, event_id=resp_event_ids, tmin=resp_tmin, tmax=resp_tmax, picks=mne.pick_types(raw_clean.info, meg=True, exclude='bads')) resp_evoked_clean = resp_epochs_clean.average() resp_diff_signal = mne.combine_evoked([resp_evoked, resp_evoked_clean], weights=[1, -1]) # MEG signal around ECG events ecg_epochs = create_ecg_epochs(raw, ch_name=ecg_ch, event_id=ecg_id, picks=mne.pick_types(raw.info, meg=True, ecg=True, exclude=[ecg_ch]), tmin=ecg_tmin, tmax=ecg_tmax, l_freq=ecg_lfreq, h_freq=ecg_hfreq, preload=True, keep_ecg=False, baseline=(None, None)) ecg_clean_epochs = create_ecg_epochs(raw_clean, ch_name=ecg_ch, event_id=ecg_id, picks=mne.pick_types(raw.info, meg=True, ecg=True, exclude=[ecg_ch]), tmin=ecg_tmin, tmax=ecg_tmax, l_freq=ecg_lfreq, h_freq=ecg_hfreq, preload=True, keep_ecg=False, baseline=(None, None)) stim_diff_ecg = mne.combine_evoked([ecg_epochs.average(), ecg_clean_epochs.average()], weights=[1, -1]) # MEG signal around EOG1 events eog1_epochs = create_eog_epochs(raw, ch_name=eog1_ch, event_id=eog_id, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) eog1_clean_epochs = create_eog_epochs(raw_clean, ch_name=eog1_ch, event_id=eog_id, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) stim_diff_eog1 = mne.combine_evoked([eog1_epochs.average(), eog1_clean_epochs.average()], weights=[1, -1]) # MEG signal around EOG2 events eog2_epochs = create_eog_epochs(raw, ch_name=eog2_ch, event_id=998, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) eog2_clean_epochs = create_eog_epochs(raw_clean, ch_name=eog2_ch, event_id=eog_id, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) stim_diff_eog2 = mne.combine_evoked([eog2_epochs.average(), eog2_clean_epochs.average()], weights=[1, -1]) # plot the overview if resp_ch: nrows, ncols = 5, 2 fig = pl.figure('Overview', figsize=(10, 20)) else: nrows, ncols = 4, 2 fig = pl.figure('Overview', figsize=(10, 16)) ax1 = pl.subplot(nrows, ncols, 1) ax1.set_title('ECG - before (b) / after (r). %d events.' % len(ecg_epochs), fontdict=dict(fontsize='medium')) ecg_evoked = ecg_epochs.average() ecg_evoked_clean = ecg_clean_epochs.average() for i in range(len(ecg_evoked.data)): ax1.plot(ecg_evoked.times * 1e3, ecg_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(ecg_evoked_clean.data)): ax1.plot(ecg_evoked_clean.times * 1e3, ecg_evoked_clean.data[j] * 1e15, color='r', label='after') ylim_ecg = dict(mag=ax1.get_ylim()) ax1.set_xlim(ecg_tmin * 1e3, ecg_tmax * 1e3) ax2 = pl.subplot(nrows, ncols, 2) stim_diff_ecg.plot(axes=ax2, ylim=ylim_ecg, titles=dict(mag='Difference')) ax3 = pl.subplot(nrows, ncols, 3) ax3.set_title('EOG (h) - before (b) / after (r). %d events.' % len(eog1_epochs), fontdict=dict(fontsize='medium')) eog1_evoked = eog1_epochs.average() eog1_evoked_clean = eog1_clean_epochs.average() for i in range(len(eog1_evoked.data)): ax3.plot(eog1_evoked.times * 1e3, eog1_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(eog1_evoked_clean.data)): ax3.plot(eog1_evoked_clean.times * 1e3, eog1_evoked_clean.data[j] * 1e15, color='r', label='after') ylim_eog = dict(mag=ax3.get_ylim()) ax3.set_xlim(eog_tmin * 1e3, eog_tmax * 1e3) ax4 = pl.subplot(nrows, ncols, 4) stim_diff_eog1.plot(axes=ax4, ylim=ylim_eog, titles=dict(mag='Difference')) ax5 = pl.subplot(nrows, ncols, 5) ax5.set_title('EOG (v) - before (b) / after (r). %d events.' % len(eog2_epochs), fontdict=dict(fontsize='medium')) eog2_evoked = eog2_epochs.average() eog2_evoked_clean = eog2_clean_epochs.average() for i in range(len(eog2_evoked.data)): ax5.plot(eog2_evoked.times * 1e3, eog2_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(eog2_evoked_clean.data)): ax5.plot(eog2_evoked_clean.times * 1e3, eog2_evoked_clean.data[j] * 1e15, color='r', label='after') ylim_eog = dict(mag=ax5.get_ylim()) ax5.set_xlim(eog_tmin * 1e3, eog_tmax * 1e3) ax6 = pl.subplot(nrows, ncols, 6) stim_diff_eog2.plot(axes=ax6, ylim=ylim_eog, titles=dict(mag='Difference')) # plot the signal + diff ax7 = pl.subplot(nrows, ncols, 7) ax7.set_title('MEG Signal around stim. %d events.' % len(epochs.events), fontdict=dict(fontsize='medium')) for i in range(len(evoked.data)): ax7.plot(evoked.times * 1e3, evoked.data[i] * 1e15, color='k', label='before') for j in range(len(evoked_clean.data)): ax7.plot(evoked_clean.times * 1e3, evoked_clean.data[j] * 1e15, color='r', label='after') ax7.set_xlim(stim_tmin * 1e3, stim_tmax * 1e3) ylim_diff = dict(mag=ax7.get_ylim()) ax8 = pl.subplot(nrows, ncols, 8) stim_diff_signal.plot(axes=ax8, ylim=ylim_diff, titles=dict(mag='Difference')) if resp_ch: # plot the signal + diff ax9 = pl.subplot(nrows, ncols, 9) ax9.set_title('MEG Signal around resp. %d events.' % len(resp_epochs.events), fontdict=dict(fontsize='medium')) for i in range(len(resp_evoked.data)): ax9.plot(resp_evoked.times * 1e3, resp_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(resp_evoked_clean.data)): ax9.plot(resp_evoked_clean.times * 1e3, resp_evoked_clean.data[j] * 1e15, color='r', label='after') ax9.set_xlim(resp_tmin * 1e3, resp_tmax * 1e3) ylim_diff = dict(mag=ax9.get_ylim()) ax10 = pl.subplot(nrows, ncols, 10) resp_diff_signal.plot(axes=ax10, ylim=ylim_diff, titles=dict(mag='Difference')) pl.tight_layout() pl.savefig(overview_fname) pl.close('all')
def apply_ica(subject, run, session): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space) fname_in = op.join(deriv_path, bids_basename + '-epo.fif') fname_out = op.join(deriv_path, bids_basename + '_cleaned-epo.fif') # load epochs to reject ICA components epochs = mne.read_epochs(fname_in, preload=True) msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) # load first run of raw data for ecg / eog epochs msg = 'Loading first run from raw data' logger.debug( gen_log_message(message=msg, step=5, subject=subject, session=session)) bids_basename = make_bids_basename(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=config.get_runs()[0], processing=config.proc, recording=config.rec, space=config.space) if config.use_maxwell_filter: raw_fname_in = op.join(deriv_path, bids_basename + '_sss_raw.fif') else: raw_fname_in = \ op.join(deriv_path, bids_basename + '_filt_raw.fif') raw = mne.io.read_raw_fif(raw_fname_in, preload=True) # run ICA on MEG and EEG picks_meg = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') picks_eeg = mne.pick_types(raw.info, meg=False, eeg=True, eog=False, stim=False, exclude='bads') all_picks = {'meg': picks_meg, 'eeg': picks_eeg} for ch_type in config.ch_types: report = None picks = all_picks[ch_type] # Load ICA fname_ica = op.join(deriv_path, f'bids_basename_{ch_type}-ica.fif') msg = f'Reading ICA: {fname_ica}' logger.debug( gen_log_message(message=msg, step=5, subject=subject, session=session)) ica = read_ica(fname=fname_ica) pick_ecg = mne.pick_types(raw.info, meg=False, eeg=False, ecg=True, eog=False) # ECG # either needs an ecg channel, or avg of the mags (i.e. MEG data) ecg_inds = list() if pick_ecg or ch_type == 'meg': picks_ecg = np.concatenate([picks, pick_ecg]) # Create ecg epochs if ch_type == 'meg': reject = { 'mag': config.reject['mag'], 'grad': config.reject['grad'] } elif ch_type == 'eeg': reject = {'eeg': config.reject['eeg']} ecg_epochs = create_ecg_epochs(raw, picks=picks_ecg, reject=reject, baseline=(None, 0), tmin=-0.5, tmax=0.5) ecg_average = ecg_epochs.average() ecg_inds, scores = \ ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=config.ica_ctps_ecg_threshold) del ecg_epochs report_fname = \ op.join(deriv_path, bids_basename + f'_{ch_type}-reject_ica.html') report = Report(report_fname, verbose=False) # Plot r score report.add_figs_to_section( ica.plot_scores(scores, exclude=ecg_inds, show=config.interactive), captions=ch_type.upper() + ' - ECG - R scores') # Plot source time course report.add_figs_to_section( ica.plot_sources(ecg_average, exclude=ecg_inds, show=config.interactive), captions=ch_type.upper() + ' - ECG - Sources time course') # Plot source time course report.add_figs_to_section( ica.plot_overlay(ecg_average, exclude=ecg_inds, show=config.interactive), captions=ch_type.upper() + ' - ECG - Corrections') else: # XXX : to check when EEG only is processed msg = ('No ECG channel is present. Cannot automate IC detection ' 'for ECG') logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) # EOG pick_eog = mne.pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True) eog_inds = list() if pick_eog.any(): msg = 'Using EOG channel' logger.debug( gen_log_message(message=msg, step=5, subject=subject, session=session)) picks_eog = np.concatenate([picks, pick_eog]) # Create eog epochs eog_epochs = create_eog_epochs(raw, picks=picks_eog, reject=None, baseline=(None, 0), tmin=-0.5, tmax=0.5) eog_average = eog_epochs.average() eog_inds, scores = ica.find_bads_eog(eog_epochs, threshold=3.0) del eog_epochs params = dict(exclude=eog_inds, show=config.interactive) # Plot r score report.add_figs_to_section(ica.plot_scores(scores, **params), captions=ch_type.upper() + ' - EOG - ' + 'R scores') # Plot source time course report.add_figs_to_section(ica.plot_sources(eog_average, **params), captions=ch_type.upper() + ' - EOG - ' + 'Sources time course') # Plot source time course report.add_figs_to_section(ica.plot_overlay(eog_average, **params), captions=ch_type.upper() + ' - EOG - ' + 'Corrections') report.save(report_fname, overwrite=True, open_browser=False) else: msg = ('No EOG channel is present. Cannot automate IC detection ' 'for EOG') logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) ica_reject = (list(ecg_inds) + list(eog_inds) + list(config.rejcomps_man[subject][ch_type])) # now reject the components msg = f'Rejecting from {ch_type}: {ica_reject}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) epochs = ica.apply(epochs, exclude=ica_reject) msg = 'Saving cleaned epochs' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) epochs.save(fname_out) if report is not None: fig = ica.plot_overlay(raw, exclude=ica_reject, show=config.interactive) report.add_figs_to_section(fig, captions=ch_type.upper() + ' - ALL(epochs) - Corrections') if config.interactive: epochs.plot_image(combine='gfp', group_by='type', sigma=2., cmap="YlGnBu_r", show=config.interactive)
mne.viz.plot_events(events, raw.info['sfreq']) event_ids = {"faces": 1, "scrambled": 2} tmin, tmax = -0.2, 0.6 baseline = None # no baseline as high-pass is applied reject = dict(mag=5e-12) epochs = mne.Epochs(raw, events, event_ids, tmin, tmax, picks=picks, baseline=baseline, preload=True, reject=reject) # Fit ICA, find and remove major artifacts ica = ICA(n_components=0.95, random_state=0).fit(raw, decim=1, reject=reject) # compute correlation scores, get bad indices sorted by score eog_epochs = create_eog_epochs(raw, ch_name='MRT31-2908', reject=reject) eog_inds, eog_scores = ica.find_bads_eog(eog_epochs, ch_name='MRT31-2908') ica.plot_scores(eog_scores, eog_inds) # see scores the selection is based on ica.plot_components(eog_inds) # view topographic sensitivity of components ica.exclude += eog_inds[:1] # we saw the 2nd ECG component looked too dipolar ica.plot_overlay(eog_epochs.average()) # inspect artifact removal ica.apply(epochs) # clean data, default in place evoked = [epochs[k].average() for k in event_ids] contrast = combine_evoked(evoked, weights=[-1, 1]) # Faces - scrambled evoked.append(contrast) for e in evoked: e.plot(ylim=dict(mag=[-400, 400]))
# We set a specific seed for the random state, so this script produces exactly # the same results every time. print('Fitting ICA') ica = ICA(method='fastica', random_state=42, n_components=n_components) # To compute the ICA, we don't need all data. We just need enough data to # perform the statistics to a reasonable degree. Here, we use every 11th # sample. We also apply some rejection limits to discard epochs with overly # large signals that are likely due to the subject moving about. ica.fit(raw, reject=dict(grad=4000e-13, mag=4e-12), decim=11) print('Fit %d components (explaining at least %0.1f%% of the variance)' % (ica.n_components_, 100 * n_components)) # Find onsets of heart beats and blinks. Create epochs around them ecg_epochs = create_ecg_epochs(raw, tmin=-.3, tmax=.3, preload=False) eog_epochs = create_eog_epochs(raw, tmin=-.5, tmax=.5, preload=False) # Find ICA components that correlate with heart beats. ecg_epochs.decimate(5) ecg_epochs.load_data() ecg_epochs.apply_baseline((None, None)) ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ecg_scores = np.abs(ecg_scores) rank = np.argsort(ecg_scores)[::-1] rank = [r for r in rank if ecg_scores[r] > 0.05] ica.exclude = rank[:n_ecg_components] print(' Found %d ECG indices' % (len(ecg_inds),)) # Find ICA components that correlate with eye blinks eog_epochs.decimate(5) eog_epochs.load_data()
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)
# Instead of opening individual figures with component properties, we can # also pass an instance of Raw or Epochs in ``inst`` arument to # ``ica.plot_components``. This would allow us to open component properties # interactively by clicking on individual component topomaps. In the notebook # this woks only when running matplotlib in interactive mode (``%matplotlib``). # uncomment the code below to test the inteactive mode of plot_components: # ica.plot_components(picks=range(10), inst=raw) ############################################################################### # Advanced artifact detection # --------------------------- # # Let's use a more efficient way to find artefacts eog_average = create_eog_epochs(raw, reject=dict(mag=5e-12, grad=4000e-13), picks=picks_meg).average() # We simplify things by setting the maximum number of components to reject n_max_eog = 1 # here we bet on finding the vertical EOG components eog_epochs = create_eog_epochs(raw, reject=reject) # get single EOG trials eog_inds, scores = ica.find_bads_eog(eog_epochs) # find via correlation ica.plot_scores(scores, exclude=eog_inds) # look at r scores of components # we can see that only one component is highly correlated and that this # component got detected by our correlation analysis (red). ica.plot_sources(eog_average, exclude=eog_inds) # look at source time course ############################################################################### # We can take a look at the properties of that component, now using the # data epoched with respect to EOG events.
ica.plot_sources(raw, show_picks, exclude=eog_inds, title=title % 'eog') ica.plot_components(eog_inds, title=title % 'eog', colorbar=True) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds ############################################################################### # 3) Assess component selection and unmixing quality. # estimate average artifact ecg_evoked = ecg_epochs.average() ica.plot_sources(ecg_evoked, exclude=ecg_inds) # plot ECG sources + selection ica.plot_overlay(ecg_evoked, exclude=ecg_inds) # plot ECG cleaning eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=picks).average() ica.plot_sources(eog_evoked, exclude=eog_inds) # plot EOG sources + selection ica.plot_overlay(eog_evoked, exclude=eog_inds) # plot EOG cleaning # check the amplitudes do not change ica.plot_overlay(raw) # EOG artifacts remain ############################################################################### # To save an ICA solution you can say: # ica.save('my_ica.fif') # You can later load the solution by saying: # from mne.preprocessing import read_ica # read_ica('my_ica.fif')
exclude='bads') ica.fit(raw, picks=picks, decim=decim, reject=reject_params) # maximum number of components to reject n_max_eog = 1 n_max_ecg = 3 ########################################################################## # 2) identify bad components by analyzing latent sources. # DETECT EOG BY CORRELATION # HORIZONTAL EOG title = "ICA: %s for %s" eog_epochs = create_eog_epochs(raw, ch_name="EOG002") # TODO: check EOG eog_average = eog_epochs.average() # channel name eog_inds, scores = ica.find_bads_eog(raw) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds if eog_inds: fig = ica.plot_scores( scores, exclude=eog_inds, title=title % ('eog', subject)) fig.savefig(ica_folder + "plots/%s_%s_eog_scores_2.png" % (subject, condition)) fig = ica.plot_sources(eog_average, exclude=eog_inds) fig.savefig(ica_folder + "plots/%s_%s_eog_source_2.png" % (subject, condition))
icacomps.exclude=[] if not icacomps.exclude: print('Old components copied. Exclude field cleared') raw = mne.io.Raw(rawRoot+name+'.fif', preload=True) ecg_picks = mne.pick_types(raw.info, meg=False, eeg=False, eog=False, ecg=True, stim=False, exclude='bads')[0] eog_picks = mne.pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True, stim=False, exclude='bads')[0] meg_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=meg_picks, verbose=False) #ch_name=raw.ch_names[ecg_picks].encode('UTF8')) ecg_evoked = ecg_epochs.average() eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5,picks=meg_picks, ch_name=raw.ch_names[eog_picks].encode('UTF8'), verbose=False).average() # ica topos source_idx = range(0, icacomps.n_components_) ica_plot = icacomps.plot_components(source_idx, ch_type="mag") plt.waitforbuttonpress(1) title = 'Sources related to %s artifacts (red)' #ask for comps ECG prompt = '> ' ecg_done = 'N' eog_done = 'N' while ecg_done.strip() != 'Y' and ecg_done.strip() != 'y':
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)
epochs = mne.Epochs(raw, events, event_ids, tmin, tmax, picks=picks, baseline=baseline, preload=True, reject=reject) # Fit ICA, find and remove major artifacts ica = ICA(n_components=0.95, random_state=0).fit(raw, decim=1, reject=reject) # compute correlation scores, get bad indices sorted by score eog_epochs = create_eog_epochs(raw, ch_name='MRT31-2908', reject=reject) eog_inds, eog_scores = ica.find_bads_eog(eog_epochs, ch_name='MRT31-2908') ica.plot_scores(eog_scores, eog_inds) # see scores the selection is based on ica.plot_components(eog_inds) # view topographic sensitivity of components ica.exclude += eog_inds[:1] # we saw the 2nd ECG component looked too dipolar ica.plot_overlay(eog_epochs.average()) # inspect artifact removal ica.apply(epochs) # clean data, default in place evoked = [epochs[k].average() for k in event_ids] contrast = combine_evoked(evoked, weights=[-1, 1]) # Faces - scrambled evoked.append(contrast) for e in evoked: e.plot(ylim=dict(mag=[-400, 400]))
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")
# estimate average artifact ecg_evoked = ecg_epochs.average() fig = ica.plot_sources(ecg_evoked, exclude=ecg_inds) # plot ECG sources + selection fig.savefig(img_folder + '/ica_ecg_evoked_sources.png') fig = ica.plot_overlay(ecg_evoked, exclude=ecg_inds) # plot ECG cleaning fig.savefig(img_folder + '/ica_ecg_evoked_overlay.png') #eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=picks).average() #fig = ica.plot_sources(eog_evoked, exclude=eog_inds) # plot EOG sources + selection #fig.savefig(img_folder + '/ica_eog_evoked_sources.png') #fig = ica.plot_overlay(eog_evoked, exclude=eog_inds) # plot EOG cleaning #fig.savefig(img_folder + '/ica_eog_evoked_overlay.png') tmp=ica.exclude ica.exclude = [] veog_evoked = create_eog_epochs(raw, ch_name='EOG001', tmin=-.5, tmax=.5, picks=picks).average() fig = ica.plot_sources(veog_evoked, exclude=veog_inds) # plot EOG sources + selection fig.savefig(img_folder + '/ica_veog_evoked_sources_veog_inds.png') fig = ica.plot_overlay(veog_evoked, exclude=veog_inds) # plot EOG cleaning fig.savefig(img_folder + '/ica_veog_evoked_overlay_veog_inds.png') fig = ica.plot_sources(veog_evoked, exclude=heog_inds) # plot EOG sources + selection fig.savefig(img_folder + '/ica_veog_evoked_sources_heog_inds.png') fig = ica.plot_overlay(veog_evoked, exclude=heog_inds) # plot EOG cleaning fig.savefig(img_folder + '/ica_veog_evoked_overlay_heog_inds.png') fig = ica.plot_sources(veog_evoked, exclude=eog_inds) # plot EOG sources + selection fig.savefig(img_folder + '/ica_veog_evoked_sources_eog_inds.png') fig = ica.plot_overlay(veog_evoked, exclude=eog_inds) # plot EOG cleaning fig.savefig(img_folder + '/ica_veog_evoked_overlay_eog_inds.png') heog_evoked = create_eog_epochs(raw, ch_name='EOG003', tmin=-.5, tmax=.5, picks=picks).average() fig = ica.plot_sources(heog_evoked, exclude=veog_inds) # plot EOG sources + selection
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)
# finds ECG events, creates epochs, averages and plots average_ecg = create_ecg_epochs(raw).average() print('We found %i ECG events' % average_ecg.nave) average_ecg.plot_joint() ############################################################################### # we can see typical time courses and non dipolar topographies # not the order of magnitude of the average artifact related signal and # compare this to what you observe for brain signals ############################################################################### # EOG # --- average_eog = create_eog_epochs(raw).average() print('We found %i EOG events' % average_eog.nave) average_eog.plot_joint() ############################################################################### # Knowing these artifact patterns is of paramount importance when # judging about the quality of artifact removal techniques such as SSP or ICA. # As a rule of thumb you need artifact amplitudes orders of magnitude higher # than your signal of interest and you need a few of such events in order # to find decompositions that allow you to estimate and remove patterns related # to artifacts. # # Consider the following tutorials for correcting this class of artifacts: # - :ref:`tut_artifacts_filter` # - :ref:`tut_artifacts_correct_ica` # - :ref:`tut_artifacts_correct_ssp`
def apply_ica(subject): print("Processing subject: %s" % subject) meg_subject_dir = op.join(config.meg_dir, subject) # load epochs to reject ICA components extension = '-epo' fname_in = op.join(meg_subject_dir, config.base_fname.format(**locals())) epochs = mne.read_epochs(fname_in, preload=True) extension = '_cleaned-epo' fname_out = op.join(meg_subject_dir, config.base_fname.format(**locals())) print("Input: ", fname_in) print("Output: ", fname_out) # load first run of raw data for ecg /eog epochs raw_list = list() print(" Loading one run from raw data") extension = config.runs[0] + '_sss_raw' raw_fname_in = op.join(meg_subject_dir, config.base_fname.format(**locals())) raw = mne.io.read_raw_fif(raw_fname_in, preload=True) # run ICA on MEG and EEG picks_meg = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') picks_eeg = mne.pick_types(raw.info, meg=False, eeg=True, eog=False, stim=False, exclude='bads') all_picks = {'meg': picks_meg, 'eeg': picks_eeg} ch_types = [] if 'eeg' in config.ch_types: ch_types.append('eeg') if set(config.ch_types).intersection(('meg', 'grad', 'mag')): ch_types.append('meg') for ch_type in ch_types: print(ch_type) picks = all_picks[ch_type] # Load ICA fname_ica = op.join( meg_subject_dir, '{0}_{1}_{2}-ica.fif'.format(subject, config.study_name, ch_type)) print('Reading ICA: ' + fname_ica) ica = read_ica(fname=fname_ica) pick_ecg = mne.pick_types(raw.info, meg=False, eeg=False, ecg=True, eog=False) # ECG # either needs an ecg channel, or avg of the mags (i.e. MEG data) if pick_ecg or ch_type == 'meg': picks_ecg = np.concatenate([picks, pick_ecg]) # Create ecg epochs if ch_type == 'meg': reject = { 'mag': config.reject['mag'], 'grad': config.reject['grad'] } elif ch_type == 'eeg': reject = {'eeg': config.reject['eeg']} ecg_epochs = create_ecg_epochs(raw, picks=picks_ecg, reject=reject, baseline=(None, 0), tmin=-0.5, tmax=0.5) ecg_average = ecg_epochs.average() ecg_inds, scores = \ ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=config.ica_ctps_ecg_threshold) del ecg_epochs report_fname = \ '{0}_{1}_{2}-reject_ica.html'.format(subject, config.study_name, ch_type) report_fname = op.join(meg_subject_dir, report_fname) report = Report(report_fname, verbose=False) # Plot r score report.add_figs_to_section(ica.plot_scores(scores, exclude=ecg_inds, show=config.plot), captions=ch_type.upper() + ' - ECG - ' + 'R scores') # Plot source time course report.add_figs_to_section(ica.plot_sources(ecg_average, exclude=ecg_inds, show=config.plot), captions=ch_type.upper() + ' - ECG - ' + 'Sources time course') # Plot source time course report.add_figs_to_section(ica.plot_overlay(ecg_average, exclude=ecg_inds, show=config.plot), captions=ch_type.upper() + ' - ECG - ' + 'Corrections') else: # XXX : to check when EEG only is processed print('no ECG channel is present. Cannot automate ICAs component ' 'detection for EOG!') # EOG pick_eog = mne.pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True) if pick_eog.any(): print('using EOG channel') picks_eog = np.concatenate([picks, pick_eog]) # Create eog epochs eog_epochs = create_eog_epochs(raw, picks=picks_eog, reject=None, baseline=(None, 0), tmin=-0.5, tmax=0.5) eog_average = eog_epochs.average() eog_inds, scores = ica.find_bads_eog(eog_epochs, threshold=3.0) del eog_epochs params = dict(exclude=eog_inds, show=config.plot) # Plot r score report.add_figs_to_section(ica.plot_scores(scores, **params), captions=ch_type.upper() + ' - EOG - ' + 'R scores') # Plot source time course report.add_figs_to_section(ica.plot_sources(eog_average, **params), captions=ch_type.upper() + ' - EOG - ' + 'Sources time course') # Plot source time course report.add_figs_to_section(ica.plot_overlay(eog_average, **params), captions=ch_type.upper() + ' - EOG - ' + 'Corrections') report.save(report_fname, overwrite=True, open_browser=False) else: print('no EOG channel is present. Cannot automate ICAs component ' 'detection for EOG!') ica_reject = (list(ecg_inds) + list(eog_inds) + list(config.rejcomps_man[subject][ch_type])) # now reject the components print('Rejecting from %s: %s' % (ch_type, ica_reject)) epochs = ica.apply(epochs, exclude=ica_reject) print('Saving cleaned epochs') epochs.save(fname_out) fig = ica.plot_overlay(raw, exclude=ica_reject, show=config.plot) report.add_figs_to_section(fig, captions=ch_type.upper() + ' - ALL(epochs) - Corrections') if config.plot: epochs.plot_image(combine='gfp', group_by='type', sigma=2., cmap="YlGnBu_r", show=config.plot)
# `~mne.io.Raw` object and returning an `~mne.Epochs` object # # - `mne.compute_proj_epochs` for creating projector(s) from any # `~mne.Epochs` object # # See the documentation of each function for further details. # # # Repairing EOG artifacts with SSP # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Once again let's visualize our artifact before trying to repair it. We've # seen above the large deflections in frontal EEG channels in the raw data; # here is how the ocular artifacts manifests across all the sensors: eog_evoked = create_eog_epochs(raw).average() eog_evoked.apply_baseline((None, None)) eog_evoked.plot_joint() ############################################################################### # Just like we did with the heartbeat artifact, we can compute SSP projectors # for the ocular artifact using `~mne.preprocessing.compute_proj_eog`, # which again takes a `~mne.io.Raw` object as input and returns the # requested number of projectors for magnetometers, gradiometers, and EEG # channels (default is two projectors for each channel type). This time, we'll # pass ``no_proj`` parameter (so we get back only the new EOG projectors, not # also the existing projectors in the `~mne.io.Raw` object), and we'll # ignore the events array by assigning it to ``_`` (the conventional way of # handling unwanted return elements in Python). eog_projs, _ = compute_proj_eog(raw,
# 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 = ICA(n_components=0.90, max_pca_components=None) ############################################################################### # 1) Fit ICA model and identify bad sources picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') ica.fit(raw, picks=picks, decim=3, reject=dict(mag=4e-12, grad=4000e-13)) # create EOG epochs to improve detection by correlation picks = mne.pick_types(raw.info, meg=True, eog=True) eog_epochs = create_eog_epochs(raw, picks=picks) eog_inds, scores = ica.find_bads_eog(eog_epochs) # inds sorted! ica.plot_scores(scores, exclude=eog_inds) # inspect metrics used show_picks = np.abs(scores).argsort()[::-1][:5] # indices of top five scores # detected artifacts drawn in red (via exclude) ica.plot_sources(raw, show_picks, exclude=eog_inds, start=0., stop=3.0) ica.plot_components(eog_inds, colorbar=False) # show component sensitivites ica.exclude += eog_inds[:1] # mark first for exclusion ############################################################################### # 3) check detection and visualize artifact rejection
bio=False, stim=False, exclude='bads') ica.fit(raw, picks=picks, decim=decim, reject=reject_params) # maximum number of components to reject n_max_eog = 1 ########################################################################## # 2) identify bad components by analyzing latent sources. # DETECT EOG BY CORRELATION # HORIZONTAL EOG title = "ICA: %s for %s" picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, emg=False, bio=True, stim=False, exclude='bads') eog_epochs = create_eog_epochs(raw, ch_name="EOG001") eog_average = eog_epochs.average() # channel name eog_inds, scores = ica.find_bads_eog(raw) # ica.plot_components() ica.plot_sources(raw) # %% # eog_inds = [10] # ica.exclude += eog_inds fig = ica.plot_scores(scores, exclude=eog_inds, title=title % ('eog', subject)) fig.savefig(save_folder + "pics/%s_%s_eog_scores.png" % (subject, condition))
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 plot_artefact_overview(raw_orig, raw_clean, stim_event_ids=[1], stim_ch='STI 014', resp_ch=None, resp_event_ids=None, ecg_ch='EEG 002', eog1_ch='EEG 001', eog2_ch='EEG 003', eog_tmin=-0.5, eog_tmax=0.5, eog_id=998, eog_lfreq=8., eog_hfreq=20., ecg_tmin=-0.5, ecg_tmax=0.5, ecg_id=999, ecg_lfreq=8., ecg_hfreq=20., stim_tmin=-0.2, stim_tmax=0.8, resp_tmin=-0.6, resp_tmax=0.4, eve_output='onset', overview_fname=None): ''' Plot an overview of the artefact rejection with ECG, EOG vertical and EOG horizontal channels. Shows the data before and after cleaning along with a difference plot. raw_orig: instance of mne.io.Raw | str File name of raw object of the uncleaned data. raw_clean: instance of mne.io.Raw | str File name of raw object of the cleaned data. stim_event_ids: list List of stim or resp event ids. Defaults to [1]. resp_event_ids: list List of stim or resp event ids. Defaults to None. eve_output: 'onset' | 'offset' | 'step' Whether to report when events start, when events end, or both. overview_fname: str | None Name to save the plot generated. (considers raw_clean.filenames[0]) Notes: Time is always shown in milliseconds (1e3) and the MEG data from mag is always in femtoTesla (fT) (1e15) ''' import matplotlib.pyplot as pl from mne.preprocessing import create_ecg_epochs, create_eog_epochs raw = check_read_raw(raw_orig, preload=True) raw_clean = check_read_raw(raw_clean, preload=True) if not overview_fname: try: overview_fname = raw_clean.filenames[0].rsplit('-raw.fif')[0] + ',overview-plot.png' except: overview_fname = 'overview-plot.png' # stim related events events = mne.find_events(raw, stim_channel=stim_ch, output='onset') events_clean = mne.find_events(raw_clean, stim_channel=stim_ch, output='onset') epochs = mne.Epochs(raw, events, event_id=stim_event_ids, tmin=stim_tmin, tmax=stim_tmax, picks=mne.pick_types(raw.info, meg=True, exclude='bads')) evoked = epochs.average() epochs_clean = mne.Epochs(raw_clean, events_clean, event_id=stim_event_ids, tmin=stim_tmin, tmax=stim_tmax, picks=mne.pick_types(raw_clean.info, meg=True, exclude='bads')) evoked_clean = epochs_clean.average() stim_diff_signal = mne.combine_evoked([evoked, evoked_clean], weights=[1, -1]) if resp_ch: # stim related events resp_events = mne.find_events(raw, stim_channel=resp_ch, output='onset') resp_events_clean = mne.find_events(raw_clean, stim_channel=resp_ch, output='onset') resp_epochs = mne.Epochs(raw, resp_events, event_id=resp_event_ids, tmin=resp_tmin, tmax=resp_tmax, picks=mne.pick_types(raw.info, meg=True, exclude='bads')) resp_evoked = resp_epochs.average() resp_epochs_clean = mne.Epochs(raw_clean, resp_events_clean, event_id=resp_event_ids, tmin=resp_tmin, tmax=resp_tmax, picks=mne.pick_types(raw_clean.info, meg=True, exclude='bads')) resp_evoked_clean = resp_epochs_clean.average() resp_diff_signal = mne.combine_evoked([resp_evoked, resp_evoked_clean], weights=[1, -1]) # MEG signal around ECG events ecg_epochs = create_ecg_epochs(raw, ch_name=ecg_ch, event_id=ecg_id, picks=mne.pick_types(raw.info, meg=True, ecg=True, exclude=[ecg_ch]), tmin=ecg_tmin, tmax=ecg_tmax, l_freq=ecg_lfreq, h_freq=ecg_hfreq, preload=True, keep_ecg=False, baseline=(None, None)) ecg_clean_epochs = create_ecg_epochs(raw_clean, ch_name=ecg_ch, event_id=ecg_id, picks=mne.pick_types(raw.info, meg=True, ecg=True, exclude=[ecg_ch]), tmin=ecg_tmin, tmax=ecg_tmax, l_freq=ecg_lfreq, h_freq=ecg_hfreq, preload=True, keep_ecg=False, baseline=(None, None)) stim_diff_ecg = mne.combine_evoked([ecg_epochs.average(), ecg_clean_epochs.average()], weights=[1, -1]) # MEG signal around EOG1 events eog1_epochs = create_eog_epochs(raw, ch_name=eog1_ch, event_id=eog_id, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) eog1_clean_epochs = create_eog_epochs(raw_clean, ch_name=eog1_ch, event_id=eog_id, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) stim_diff_eog1 = mne.combine_evoked([eog1_epochs.average(), eog1_clean_epochs.average()], weights=[1, -1]) # MEG signal around EOG2 events eog2_epochs = create_eog_epochs(raw, ch_name=eog2_ch, event_id=998, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) eog2_clean_epochs = create_eog_epochs(raw_clean, ch_name=eog2_ch, event_id=eog_id, picks=mne.pick_types(raw.info, meg=True, exclude='bads'), tmin=eog_tmin, tmax=eog_tmax, l_freq=eog_lfreq, h_freq=eog_hfreq, preload=True, baseline=(None, None)) stim_diff_eog2 = mne.combine_evoked([eog2_epochs.average(), eog2_clean_epochs.average()], weights=[1, -1]) # plot the overview if resp_ch: nrows, ncols = 5, 2 fig = pl.figure('Overview', figsize=(10, 20)) else: nrows, ncols = 4, 2 fig = pl.figure('Overview', figsize=(10, 16)) ax1 = pl.subplot(nrows, ncols, 1) ax1.set_title('ECG - before (b) / after (r). %d events.' % len(ecg_epochs), fontdict=dict(fontsize='medium')) ecg_evoked = ecg_epochs.average() ecg_evoked_clean = ecg_clean_epochs.average() for i in range(len(ecg_evoked.data)): ax1.plot(ecg_evoked.times * 1e3, ecg_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(ecg_evoked_clean.data)): ax1.plot(ecg_evoked_clean.times * 1e3, ecg_evoked_clean.data[j] * 1e15, color='r', label='after') ylim_ecg = dict(mag=ax1.get_ylim()) ax1.set_xlim(ecg_tmin * 1e3, ecg_tmax * 1e3) ax2 = pl.subplot(nrows, ncols, 2) stim_diff_ecg.plot(axes=ax2, ylim=ylim_ecg, titles=dict(mag='Difference')) ax3 = pl.subplot(nrows, ncols, 3) ax3.set_title('EOG (h) - before (b) / after (r). %d events.' % len(eog1_epochs), fontdict=dict(fontsize='medium')) eog1_evoked = eog1_epochs.average() eog1_evoked_clean = eog1_clean_epochs.average() for i in range(len(eog1_evoked.data)): ax3.plot(eog1_evoked.times * 1e3, eog1_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(eog1_evoked_clean.data)): ax3.plot(eog1_evoked_clean.times * 1e3, eog1_evoked_clean.data[j] * 1e15, color='r', label='after') ylim_eog = dict(mag=ax3.get_ylim()) ax3.set_xlim(eog_tmin * 1e3, eog_tmax * 1e3) ax4 = pl.subplot(nrows, ncols, 4) stim_diff_eog1.plot(axes=ax4, ylim=ylim_eog, titles=dict(mag='Difference')) ax5 = pl.subplot(nrows, ncols, 5) ax5.set_title('EOG (v) - before (b) / after (r). %d events.' % len(eog2_epochs), fontdict=dict(fontsize='medium')) eog2_evoked = eog2_epochs.average() eog2_evoked_clean = eog2_clean_epochs.average() for i in range(len(eog2_evoked.data)): ax5.plot(eog2_evoked.times * 1e3, eog2_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(eog2_evoked_clean.data)): ax5.plot(eog2_evoked_clean.times * 1e3, eog2_evoked_clean.data[j] * 1e15, color='r', label='after') ylim_eog = dict(mag=ax5.get_ylim()) ax5.set_xlim(eog_tmin * 1e3, eog_tmax * 1e3) ax6 = pl.subplot(nrows, ncols, 6) stim_diff_eog2.plot(axes=ax6, ylim=ylim_eog, titles=dict(mag='Difference')) # plot the signal + diff ax7 = pl.subplot(nrows, ncols, 7) ax7.set_title('MEG Signal around stim. %d events.' % len(epochs.events), fontdict=dict(fontsize='medium')) for i in range(len(evoked.data)): ax7.plot(evoked.times * 1e3, evoked.data[i] * 1e15, color='k', label='before') for j in range(len(evoked_clean.data)): ax7.plot(evoked_clean.times * 1e3, evoked_clean.data[j] * 1e15, color='r', label='after') ax7.set_xlim(stim_tmin * 1e3, stim_tmax * 1e3) ylim_diff = dict(mag=ax7.get_ylim()) ax8 = pl.subplot(nrows, ncols, 8) stim_diff_signal.plot(axes=ax8, ylim=ylim_diff, titles=dict(mag='Difference')) if resp_ch: # plot the signal + diff ax9 = pl.subplot(nrows, ncols, 9) ax9.set_title('MEG Signal around resp. %d events.' % len(resp_epochs.events), fontdict=dict(fontsize='medium')) for i in range(len(resp_evoked.data)): ax9.plot(resp_evoked.times * 1e3, resp_evoked.data[i] * 1e15, color='k', label='before') for j in range(len(resp_evoked_clean.data)): ax9.plot(resp_evoked_clean.times * 1e3, resp_evoked_clean.data[j] * 1e15, color='r', label='after') ax9.set_xlim(resp_tmin * 1e3, resp_tmax * 1e3) ylim_diff = dict(mag=ax9.get_ylim()) ax10 = pl.subplot(nrows, ncols, 10) resp_diff_signal.plot(axes=ax10, ylim=ylim_diff, titles=dict(mag='Difference')) pl.tight_layout() pl.savefig(overview_fname) pl.close('all')
def ica_method(raw, picks, plot='n', save ='n'): ############################################################################### # 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 = ICA(n_components=0.95, method='fastica') picks = mne.pick_types(raw.info, meg=False, eeg=True, eog=False, stim=False, exclude='bads') ica.fit(raw, picks=picks, decim=3) # maximum number of components to reject n_max_eog = 1 # here we don't expect horizontal EOG components ############################################################################### # 2) identify bad components by analyzing latent sources. # detect EOG by correlation eog_inds, scores = ica.find_bads_eog(raw, threshold=2.5) show_picks = np.abs(scores).argsort()[::-1][:5] eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds ############################################################################### # 3) Assess component selection and unmixing quality eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=picks).average() if plot=='y': title = 'Sources related to %s artifacts (red)' ica.plot_scores(scores, exclude=eog_inds, title=title % 'eog', labels='eog') if save=='y': pylab.savefig('2.png') ica.plot_sources(raw, show_picks, exclude=eog_inds, title=title % 'eog') if save=='y': pylab.savefig('3.png') ica.plot_components(eog_inds, title=title % 'eog', colorbar=True) if save=='y': pylab.savefig('4.png') ica.plot_overlay(raw) # EOG artifacts remain if save=='y': pylab.savefig('5.png') ica.plot_sources(eog_evoked, exclude=eog_inds) # plot EOG sources + selection if save=='y': pylab.savefig('6.png') ica.plot_overlay(eog_evoked, exclude=eog_inds) # plot EOG cleaning if save=='y': pylab.savefig('7.png') ica.apply(raw, exclude=eog_inds) eeg_only_after=raw.pick_types(meg=False, eeg=True) return eeg_only_after