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 test_find_ecg(): """Test find ECG peaks.""" # Test if ECG analysis will work on data that is not preloaded raw = read_raw_fif(raw_fname, preload=False) # once with mag-trick # once with characteristic channel for ch_name in ['MEG 1531', None]: events, ch_ECG, average_pulse, ecg = find_ecg_events( raw, event_id=999, ch_name=ch_name, return_ecg=True) assert raw.n_times == ecg.shape[-1] n_events = len(events) _, times = raw[0, :] assert 55 < average_pulse < 60 picks = pick_types( raw.info, meg='grad', eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') # There should be no ECG channels, or else preloading will not be # tested assert 'ecg' not in raw ecg_epochs = create_ecg_epochs(raw, picks=picks, keep_ecg=True) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' in ecg_epochs.ch_names picks = pick_types( ecg_epochs.info, meg=False, eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') assert len(picks) == 1 ecg_epochs = create_ecg_epochs(raw, ch_name='MEG 2641') assert 'MEG 2641' in ecg_epochs.ch_names # test with user provided ecg channel raw.info['projs'] = list() with pytest.warns(RuntimeWarning, match='unit for channel'): raw.set_channel_types({'MEG 2641': 'ecg'}) create_ecg_epochs(raw) raw.load_data().pick_types() # remove ECG ecg_epochs = create_ecg_epochs(raw, keep_ecg=False) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' not in ecg_epochs.ch_names
def run_ica(raw, ica_fname=None, picks=None, n_max_ecg=3, n_max_eog=1): raw_f = raw.copy().filter(1, 45, n_jobs=1, l_trans_bandwidth=0.5, h_trans_bandwidth=0.5, filter_length='10s', phase='zero-double') ica = ICA(method='fastica', random_state=42, n_components=0.98) if picks is None: picks = mne.pick_types(raw_f.info, meg=True, eeg=False, eog=False, stim=False, exclude='bads') ica.fit(raw_f, picks=picks, reject=dict(grad=4000e-13, mag=4e-12), decim=3) ecg_epochs = create_ecg_epochs(raw_f, tmin=-.5, tmax=.5, picks=picks) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds eog_inds, scores = ica.find_bads_eog(raw_f) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds if ica_fname is None: ica_fname = raw_f._filenames[0][:-4] + '-pyimpress-ica.fif' ica.save(ica_fname) return ica, ica_fname
def make_ecg_epochs(*, cfg, raw: mne.io.BaseRaw, subject: str, session: str, run: Optional[str] = None) -> Optional[mne.BaseEpochs]: # ECG either needs an ecg channel, or avg of the mags (i.e. MEG data) if ('ecg' in raw.get_channel_types() or 'meg' in cfg.ch_types or 'mag' in cfg.ch_types): msg = 'Creating ECG epochs …' logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) ecg_epochs = create_ecg_epochs(raw, baseline=(None, -0.2), tmin=-0.5, tmax=0.5) if len(ecg_epochs) == 0: msg = ('No ECG events could be found. Not running ECG artifact ' 'detection.') logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) ecg_epochs = None else: msg = ('No ECG or magnetometer channels are present. Cannot ' 'automate artifact detection for ECG') logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) ecg_epochs = None return ecg_epochs
def detect_ecg_artifacts(ica, raw, subject, session, report): # ECG either needs an ecg channel, or avg of the mags (i.e. MEG data) if ('ecg' in raw.get_channel_types() or 'meg' in config.ch_types or 'mag' in config.ch_types): msg = 'Performing automated ECG artifact detection …' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) # Do not reject epochs based on amplitude. ecg_epochs = create_ecg_epochs(raw, reject=None, baseline=(None, -0.2), tmin=-0.5, tmax=0.5) ecg_evoked = ecg_epochs.average() ecg_inds, scores = ica.find_bads_ecg( ecg_epochs, method='ctps', threshold=config.ica_ctps_ecg_threshold) ica.exclude = ecg_inds msg = (f'Detected {len(ecg_inds)} ECG-related ICs in ' f'{len(ecg_epochs)} ECG epochs.') logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) del ecg_epochs # Plot scores fig = ica.plot_scores(scores, labels='ecg', show=config.interactive) report.add_figs_to_section(figs=fig, captions='Scores - ECG', section=f'sub-{subject}') # Plot source time course fig = ica.plot_sources(ecg_evoked, show=config.interactive) report.add_figs_to_section(figs=fig, captions='Source time course - ECG', section=f'sub-{subject}') # Plot original & corrected data fig = ica.plot_overlay(ecg_evoked, show=config.interactive) report.add_figs_to_section(figs=fig, captions='Corrections - ECG', section=f'sub-{subject}') else: ecg_inds = list() msg = ('No ECG or magnetometer channels are present. Cannot ' 'automate artifact detection for ECG') logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) return ecg_inds
def inscapesMEG_PP(fname, DATA_FOLDER, SAVE_FOLDER): fpath = DATA_FOLDER + fname raw = read_raw_ctf(fpath, preload=True) picks = mne.pick_types(raw.info, meg=True, eog=True, exclude='bads') raw.plot() raw.plot_psd(average=False, picks=picks) ## Filtering high_cutoff = 200 low_cutoff = 0.5 raw.filter(low_cutoff, high_cutoff, fir_design="firwin") raw.notch_filter(np.arange(60, high_cutoff + 1, 60), picks=picks, filter_length='auto', phase='zero', fir_design="firwin") raw.plot_psd(average=False, picks=picks) ## ICA ica = ICA(n_components=20, random_state=0).fit(raw, decim=3) ica.plot_sources(raw) fmax = 40. ## correlation threshold for ICA components (maybe increase to 40. ?) ## FIND ECG COMPONENTS ecg_epochs = create_ecg_epochs(raw, ch_name='EEG059') ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, ch_name='EEG059') ica.plot_scores(ecg_scores, ecg_inds) ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': fmax}, image_args={'sigma': 1.}) ## FIND EOG COMPONENTS eog_epochs = create_eog_epochs(raw, ch_name='EEG057') eog_inds, eog_scores = ica.find_bads_eog(eog_epochs, ch_name='EEG057') ica.plot_scores(eog_scores, eog_inds) ica.plot_properties(eog_epochs, picks=eog_inds, psd_args={'fmax': fmax}, image_args={'sigma': 1.}) ## EXCLUDE COMPONENTS ica.exclude = ecg_inds ica.apply(raw) ica.exclude = eog_inds ica.apply(raw) raw.plot() # Plot the clean signal. ## SAVE PREPROCESSED FILE time.sleep(60) raw.save(SAVE_FOLDER + fname + '_preprocessed.fif.gz', overwrite=True) time.sleep(30) filename = SAVE_FOLDER + fname + '_log.html' #!jupyter nbconvert inscapesMEG_preproc.ipynb --output $filename clear_output()
def fit_ica_and_plot_scores(method, random_state, tol=1e-4): ica = ICA(n_components=0.95, method=method, random_state=random_state, fit_params={'tol': tol}, max_iter=400) t0 = time() ica.fit(raw.copy(), picks=picks, decim=3, reject=dict(mag=4e-12, grad=4000e-13), verbose='warning') fit_time = time() - t0 title = ('Method : %s, init %d. Took %.2g sec.' % (method, random_state + 1, fit_time)) ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=picks) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.plot_scores(scores, exclude=ecg_inds, title=title) ica.plot_components(ecg_inds, colorbar=True)
def 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 make_ecg_epochs(*, cfg, raw_path: BIDSPath, subject: str, session: str, run: Optional[str] = None, n_runs: int) -> Optional[mne.BaseEpochs]: # ECG either needs an ecg channel, or avg of the mags (i.e. MEG data) raw = mne.io.read_raw(raw_path, preload=False) if ('ecg' in raw.get_channel_types() or 'meg' in cfg.ch_types or 'mag' in cfg.ch_types): msg = 'Creating ECG epochs …' logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) # We want to extract a total of 5 min of data for ECG epochs generation # (across all runs) total_ecg_dur = 5 * 60 ecg_dur_per_run = total_ecg_dur / n_runs t_mid = (raw.times[-1] + raw.times[0]) / 2 raw = raw.crop(tmin=max(t_mid - 1 / 2 * ecg_dur_per_run, 0), tmax=min(t_mid + 1 / 2 * ecg_dur_per_run, raw.times[-1])).load_data() ecg_epochs = create_ecg_epochs(raw, baseline=(None, -0.2), tmin=-0.5, tmax=0.5) del raw # Free memory if len(ecg_epochs) == 0: msg = ('No ECG events could be found. Not running ECG artifact ' 'detection.') logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) ecg_epochs = None else: msg = ('No ECG or magnetometer channels are present. Cannot ' 'automate artifact detection for ECG') logger.info(**gen_log_kwargs( message=msg, subject=subject, session=session, run=run)) ecg_epochs = None return ecg_epochs
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')
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) ecg_epochs = create_ecg_epochs(raw_sss, tmin=-.5, tmax=.5) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.apply(raw_sss, exclude=ecg_inds) raw_sss.plot_psd(fmax=100) ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': 35.}) #****************************************************************************# # ERP # #****************************************************************************# tmin, tmax = -0.5, 0.7 event_id = {'Auditory/Left': 1} events = mne.find_events(raw, 'STI 014') picks = mne.pick_types(raw.info, meg=True,
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)) # maximum number of components to reject n_max_ecg, n_max_eog = 3, 1 # here we don't expect horizontal EOG components ############################################################################### # 2) identify bad components by analyzing latent sources. title = 'Sources related to %s artifacts (red)' # generate ECG epochs use detection via phase statistics ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=picks) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.plot_scores(scores, exclude=ecg_inds, title=title % 'ecg', labels='ecg') show_picks = np.abs(scores).argsort()[::-1][:5] ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % 'ecg') ica.plot_components(ecg_inds, title=title % 'ecg', colorbar=True) ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds # detect EOG by correlation eog_inds, scores = ica.find_bads_eog(raw)
picks=picks, decim=3, reject=dict(mag=4e-12, grad=4000e-13), verbose='warning') # low iterations -> does not fully converge # maximum number of components to reject n_max_ecg, n_max_eog = 3, 1 # here we don't expect horizontal EOG components ############################################################################### # 2) identify bad components by analyzing latent sources. title = 'Sources related to %s artifacts (red)' # generate ECG epochs use detection via phase statistics ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=picks) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.plot_scores(scores, exclude=ecg_inds, title=title % 'ecg', labels='ecg') show_picks = np.abs(scores).argsort()[::-1][:5] ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % 'ecg') ica.plot_components(ecg_inds, title=title % 'ecg', colorbar=True) ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds # detect EOG by correlation eog_inds, scores = ica.find_bads_eog(raw)
def preproc(subject): global report from mne.preprocessing import ICA, create_ecg_epochs, create_eog_epochs from mne.io import read_raw_fif import numpy as np raw_path = op.join(rest_dir, subject, 'meg_clean', 'nose-pts-out_raw.fif') clean_raw_path = op.join(rest_dir, subject, 'meg_clean', 'clean_raw.fif') if not os.path.exists( raw_path): # skip subjects that have T1 but do not have MEG data return raw = read_raw_fif(raw_path, preload=True) pick_meg = mne.pick_types(raw.info, meg=True, eeg=False, stim=False, ref_meg=False) pick_eog1 = mne.pick_channels(raw.ch_names, ['EOG061']) pick_eog2 = mne.pick_channels(raw.ch_names, ['EOG062']) pick_ecg = mne.pick_channels(raw.ch_names, ['ECG063']) if pick_eog1.size == 0 or pick_eog2.size == 0 or pick_ecg.size == 0: logFile.write("Subject " + subject + ": EOG and/or ECG channels not found.\n") return ##-- Filtering, PSD --## fig = raw.plot_psd(area_mode='range', average=False, picks=pick_meg) report.add_figs_to_section(fig, captions=subject + ' => PSD before filtering', section='Filtering') raw.notch_filter((50, 100), filter_length='auto', fir_design='firwin', phase='zero', picks=np.append(pick_meg, (pick_ecg, pick_eog1, pick_eog2))) raw.filter(1., None, fir_design='firwin', phase='zero') # high-pass filtering at 1 Hz raw.resample( 200, npad="auto" ) # set sampling frequency to 200Hz (antialiasing filter at 100 Hz) ##-- Artifact removal --## random_state = 23 # we want to have the same decomposition and the same order of components each time it is run for reproducibility ica = ICA(n_components=25, method='fastica', random_state=random_state) reject = dict( mag=5e-12, grad=4000e-13 ) # avoid fitting ICA on large environmental artifacts that would dominate the variance and decomposition try: ica.fit(raw, picks=pick_meg, reject=reject) except: logFile.write("Subject " + subject + ": ICA could not run. Large environmental artifacts.\n") return fig = ica.plot_components(inst=raw) report.add_figs_to_section(fig, captions=[subject + ' => ICA components'] * len(fig), section='Artifact removal') # EOG artifact eog_epochs = create_eog_epochs(raw, reject=reject) if eog_epochs.events.size != 0: eog_inds, scores = ica.find_bads_eog(eog_epochs) if len(eog_inds) != 0: fig = ica.plot_properties(eog_epochs, picks=eog_inds, psd_args={'fmax': 35.}, image_args={'sigma': 1.}) report.add_figs_to_section( fig, captions=[subject + ' => ICA correlated with EOG'] * len(fig), section='Artifact removal') ica.exclude.extend(eog_inds) else: logFile.write("Subject " + subject + ": No ICA component correlated with EOG\n") else: logFile.write("Subject " + subject + ": No EOG events found\n") # ECG artifact ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5) if ecg_epochs.events.size != 0: ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') if len(ecg_inds) != 0: fig = ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': 35.}) report.add_figs_to_section( fig, captions=[subject + ' => ICA correlated with ECG'] * len(fig), section='Artifact removal') ica.exclude.extend(ecg_inds) else: logFile.write("Subject " + subject + ": No ICA component correlated with ECG\n") else: logFile.write("Subject " + subject + ": No ECG events found\n") raw_clean = raw.copy() ica.apply(raw_clean) fig = raw_clean.plot_psd(area_mode='range', picks=pick_meg) report.add_figs_to_section( fig, captions=subject + ' => PSD after filtering and artifact correction', section='Filtering') raw_clean.save(clean_raw_path, overwrite=True)
def 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)
def remove_eyeblinks_and_heartbeat(raw, subject, figdir, events, eventid, rng): """ Find and repair eyeblink and heartbeat artifacts in the data. Data should be filtered. Importantly, ICA is fitted on artificially epoched data with reject criteria estimates via the autoreject package - this is done to reject high- amplitude artifacts to influence the ICA solution. The ICA fit is then applied to the raw data. :param raw: Raw data :param subject: str, subject identifier, e.g., '001' :param figdir: :param rng: random state instance """ # prior to an ICA, it is recommended to high-pass filter the data # as low frequency artifacts can alter the ICA solution. We fit the ICA # to high-pass filtered (1Hz) data, and apply it to non-highpass-filtered # data logging.info("Applying a temporary high-pass filtering prior to ICA") filt_raw = raw.copy() filt_raw.load_data().filter(l_freq=1., h_freq=None) # evoked eyeblinks and heartbeats for diagnostic plots eog_evoked = create_eog_epochs(filt_raw).average() eog_evoked.apply_baseline(baseline=(None, -0.2)) if subject == '008': # subject 008's ECG channel is flat. It will not find any heartbeats by # default. We let it estimate heartbeat from magnetometers. For this, # we'll drop the ECG channel filt_raw.drop_channels('ECG003') ecg_evoked = create_ecg_epochs(filt_raw).average() ecg_evoked.apply_baseline(baseline=(None, -0.2)) # make sure that we actually found sensible artifacts here eog_fig = eog_evoked.plot_joint() for i, fig in enumerate(eog_fig): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"evoked-artifact_eog_sub-{subject}_{i}.png", ]) fig.savefig(fname) ecg_fig = ecg_evoked.plot_joint() for i, fig in enumerate(ecg_fig): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"evoked-artifact_ecg_sub-{subject}_{i}.png", ]) fig.savefig(fname) # Chunk raw data into epochs to fit the ICA # No baseline correction as it would interfere with ICA. logging.info("Epoching filtered data") epochs = mne.Epochs(filt_raw, events, event_id=eventid, tmin=0, tmax=3, picks='meg', baseline=None) ## First, estimate rejection criteria for high-amplitude artifacts. This is ## done via autoreject #logging.info('Estimating bad epochs quick-and-dirty, to improve ICA') #ar = AutoReject(random_state=rng) # fit on first 200 epochs to save (a bit of) time #epochs.load_data() #ar.fit(epochs[:200]) #epochs_ar, reject_log = ar.transform(epochs, return_log=True) # run an ICA to capture heartbeat and eyeblink artifacts. # set a seed for reproducibility. # When left to figure out the component number by itself, it ends up with # about 80. I'm setting n_components to 45 to have a chance at checking them # by hand. # We fit it on a set of epochs excluding the initial bad epochs following # https://github.com/autoreject/autoreject/blob/dfbc64f49eddeda53c5868290a6792b5233843c6/examples/plot_autoreject_workflow.py logging.info('Fitting the ICA') ica = ICA(max_iter='auto', n_components=45, random_state=rng) ica.fit(epochs) #[~reject_log.bad_epochs]) logging.info("Searching for eyeblink and heartbeat artifacts in the data") # get ICA components for the given subject if subject == '008': eog_indices = [10] ecg_indices = [29] #eog_indices = ica_comps[subject]['eog'] #ecg_indices = ica_comps[subject]['ecg'] # An initially manual component detection did not reproduce after a software # update - for now, we have to do the automatic detection for all but sub 8 else: eog_indices, eog_scores = ica.find_bads_eog(filt_raw) ecg_indices, ecg_scores = ica.find_bads_ecg(filt_raw) logging.info(f"Identified the following EOG components: {eog_indices}") logging.info(f"Identified the following ECG components: {ecg_indices}") # visualize the components components = ica.plot_components() for i, fig in enumerate(components): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-components_sub-{subject}_{i}.png", ]) fig.savefig(fname) # visualize the time series of components and save it plt.rcParams['figure.figsize'] = 30, 20 comp_sources = ica.plot_sources(epochs) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-components_sources_sub-{subject}.png", ]) comp_sources.savefig(fname) # reset plotting params plt.rcParams['figure.figsize'] = plt.rcParamsDefault['figure.figsize'] # plot EOG components overlay_eog = ica.plot_overlay(eog_evoked, exclude=ica_comps[subject]['eog']) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-eog-components_over-avg-epochs_sub-{subject}.png", ]) overlay_eog.savefig(fname) # plot ECG components overlay_ecg = ica.plot_overlay(ecg_evoked, exclude=ica_comps[subject]['ecg']) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-ecg-components_over-avg-epochs_sub-{subject}.png", ]) overlay_ecg.savefig(fname) # plot EOG component properties figs = ica.plot_properties(filt_raw, picks=eog_indices) for i, fig in enumerate(figs): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-property{i}_artifact-eog_sub-{subject}.png", ]) fig.savefig(fname) # plot ECG component properties figs = ica.plot_properties(filt_raw, picks=ecg_indices) for i, fig in enumerate(figs): fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-property{i}_artifact-ecg_sub-{subject}.png", ]) fig.savefig(fname) # Set the indices to be excluded ica.exclude = eog_indices ica.exclude.extend(ecg_indices) # plot ICs applied to the averaged EOG epochs, with EOG matches highlighted sources = ica.plot_sources(eog_evoked) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-sources_artifact-eog_sub-{subject}.png", ]) sources.savefig(fname) # plot ICs applied to the averaged ECG epochs, with ECG matches highlighted sources = ica.plot_sources(ecg_evoked) fname = _construct_path([ Path(figdir), f"sub-{subject}", "meg", f"ica-sources_artifact-ecg_sub-{subject}.png", ]) sources.savefig(fname) # apply the ICA to the raw data logging.info('Applying ICA to the raw data.') raw.load_data() ica.apply(raw)
def 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')
# M/EEG signal decomposition using Independent Component Analysis (ICA) ica_fruit = ICA(n_components=n_components, method=method) ica_odour = ICA(n_components=n_components, method=method) ica_milk = ICA(n_components=n_components, method=method) ica_LD = ICA(n_components=n_components, method=method) reject = dict(grad=200e-12, mag=4e-12) # Run the ICA decomposition on raw data ica_fruit.fit(raw_fruit, picks=picks_fruit, decim=decim, reject=reject) ica_odour.fit(raw_odour, picks=picks_odour, decim=decim, reject=reject) ica_milk.fit(raw_milk, picks=picks_milk, decim=decim, reject=reject) ica_LD.fit(raw_LD, picks=picks_LD, decim=decim, reject=reject) # Conveniently generates epochs around EOG artifact events ecg_epochs_fruit = create_ecg_epochs(raw_fruit, reject=reject) ecg_epochs_odour = create_ecg_epochs(raw_odour, reject=reject) ecg_epochs_milk = create_ecg_epochs(raw_milk, reject=reject) ecg_epochs_LD = create_ecg_epochs(raw_LD, reject=reject) # Detecting EOG related components using correlation ecg_inds_fruit, scores_fruit = ica_fruit.find_bads_ecg(ecg_epochs_fruit) ecg_inds_odour, scores_odour = ica_odour.find_bads_ecg(ecg_epochs_odour) ecg_inds_milk, scores_milk = ica_milk.find_bads_ecg(ecg_epochs_milk) ecg_inds_LD, scores_LD = ica_LD.find_bads_ecg(ecg_epochs_LD) ecg_inds_fruit = ecg_inds_fruit[:n_max_ecg] ecg_inds_odour = ecg_inds_odour[:n_max_ecg] ecg_inds_milk = ecg_inds_milk[:n_max_ecg] ecg_inds_LD = ecg_inds_LD[:n_max_ecg]
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 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)
def run_epochs(subject_id, tsss=False): subject = "sub%03d" % subject_id print("Processing subject: %s%s" % (subject, (' (tSSS=%d)' % tsss) if tsss else '')) data_path = op.join(meg_dir, subject) # map to correct subject for bad channels mapping = map_subjects[subject_id] raw_list = list() events_list = list() print(" Loading raw data") for run in range(1, 7): bads = list() bad_name = op.join('bads', mapping, 'run_%02d_raw_tr.fif_bad' % run) if os.path.exists(bad_name): with open(bad_name) as f: for line in f: bads.append(line.strip()) if tsss: run_fname = op.join(data_path, 'run_%02d_filt_tsss_%d_raw.fif' % (run, tsss)) else: run_fname = op.join( data_path, 'run_%02d_filt_sss_' 'highpass-%sHz_raw.fif' % (run, l_freq)) raw = mne.io.read_raw_fif(run_fname, preload=True) delay = int(round(0.0345 * raw.info['sfreq'])) events = mne.read_events(op.join(data_path, 'run_%02d-eve.fif' % run)) events[:, 0] = events[:, 0] + delay events_list.append(events) raw.info['bads'] = bads raw.interpolate_bads() raw_list.append(raw) raw, events = mne.concatenate_raws(raw_list, events_list=events_list) raw.set_eeg_reference(projection=True) del raw_list picks = mne.pick_types(raw.info, meg=True, eeg=True, stim=True, eog=True, exclude=()) # Epoch the data print(' Epoching') epochs = mne.Epochs(raw, events, events_id, tmin, tmax, proj=True, picks=picks, baseline=baseline, preload=False, decim=5, reject=None, reject_tmax=reject_tmax) print(' Interpolating bad channels') # ICA if tsss: ica_name = op.join(meg_dir, subject, 'run_concat-tsss_%d-ica.fif' % (tsss, )) ica_out_name = ica_name else: ica_name = op.join(meg_dir, subject, 'run_concat-ica.fif') ica_out_name = op.join(meg_dir, subject, 'run_concat_highpass-%sHz-ica.fif' % (l_freq, )) print(' Using ICA') ica = read_ica(ica_name) ica.exclude = [] filter_label = '-tsss_%d' % tsss if tsss else '_highpass-%sHz' % l_freq ecg_epochs = create_ecg_epochs(raw, tmin=-.3, tmax=.3, preload=False) eog_epochs = create_eog_epochs(raw, tmin=-.5, tmax=.5, preload=False) del raw n_max_ecg = 3 # use max 3 components ecg_epochs.decimate(5) ecg_epochs.load_data() ecg_epochs.apply_baseline((None, None)) ecg_inds, scores_ecg = ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=0.8) print(' Found %d ECG indices' % (len(ecg_inds), )) ica.exclude.extend(ecg_inds[:n_max_ecg]) ecg_epochs.average().save( op.join(data_path, '%s%s-ecg-ave.fif' % (subject, filter_label))) np.save( op.join(data_path, '%s%s-ecg-scores.npy' % (subject, filter_label)), scores_ecg) del ecg_epochs n_max_eog = 3 # use max 2 components eog_epochs.decimate(5) eog_epochs.load_data() eog_epochs.apply_baseline((None, None)) eog_inds, scores_eog = ica.find_bads_eog(eog_epochs) print(' Found %d EOG indices' % (len(eog_inds), )) ica.exclude.extend(eog_inds[:n_max_eog]) eog_epochs.average().save( op.join(data_path, '%s%s-eog-ave.fif' % (subject, filter_label))) np.save( op.join(data_path, '%s%s-eog-scores.npy' % (subject, filter_label)), scores_eog) del eog_epochs ica.save(ica_out_name) epochs.load_data() ica.apply(epochs) print(' Getting rejection thresholds') reject = get_rejection_threshold(epochs.copy().crop(None, reject_tmax)) epochs.drop_bad(reject=reject) print(' Dropped %0.1f%% of epochs' % (epochs.drop_log_stats(), )) print(' Writing to disk') if tsss: epochs.save(op.join(data_path, '%s-tsss_%d-epo.fif' % (subject, tsss))) else: epochs.save( op.join(data_path, '%s_highpass-%sHz-epo.fif' % (subject, l_freq)))
show_scrollbars=False) ############################################################################### # We can get a summary of how the ocular artifact manifests across each channel # type using `~mne.preprocessing.create_eog_epochs` like we did in the # :ref:`tut-artifact-overview` tutorial: eog_evoked = create_eog_epochs(raw).average() eog_evoked.apply_baseline(baseline=(None, -0.2)) eog_evoked.plot_joint() ############################################################################### # Now we'll do the same for the heartbeat artifacts, using # `~mne.preprocessing.create_ecg_epochs`: ecg_evoked = create_ecg_epochs(raw).average() ecg_evoked.apply_baseline(baseline=(None, -0.2)) ecg_evoked.plot_joint() ############################################################################### # Filtering to remove slow drifts # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Before we run the ICA, an important step is filtering the data to remove # low-frequency drifts, which can negatively affect the quality of the ICA fit. # The slow drifts are problematic because they reduce the independence of the # assumed-to-be-independent sources (e.g., during a slow upward drift, the # neural, heartbeat, blink, and other muscular sources will all tend to have # higher values), making it harder for the algorithm to find an accurate # solution. A high-pass filter with 1 Hz cutoff frequency is recommended. # However, because filtering is a linear operation, the ICA solution found from
def preprocess_ICA_fif_to_ts(fif_file, ECG_ch_name, EoG_ch_name, l_freq, h_freq): # ------------------------ Import stuff ------------------------ # import os import mne import sys from mne.io import Raw from mne.preprocessing import ICA from mne.preprocessing import create_ecg_epochs, create_eog_epochs from nipype.utils.filemanip import split_filename as split_f from reportGen import generateReport import pickle subj_path, basename, ext = split_f(fif_file) # -------------------- Delete later ------------------- # subj_name = subj_path[-5:] results_dir = subj_path[:-6] # results_dir += '2016' subj_path = results_dir + '/' + subj_name if not os.path.exists(subj_path): try: os.makedirs(subj_path) except OSError: sys.stderr.write('ica_preproc: problem creating directory: ' + subj_path) ######################################################## # Read raw # If None the compensation in the data is not modified. If set to n, e.g. 3, apply # gradient compensation of grade n as for CTF systems (compensation=3) print(fif_file) print(EoG_ch_name) # ----------------------------- end Import stuff ----------------- # # EoG_ch_name = "EOG061, EOG062" # ------------- Load raw ------------- # raw = Raw(fif_file, preload=True) # select sensors select_sensors = mne.pick_types(raw.info, meg=True, ref_meg=False, exclude='bads') picks_meeg = mne.pick_types(raw.info, meg=True, eeg=True, exclude='bads') # filtering raw.filter(l_freq=l_freq, h_freq=h_freq, picks=picks_meeg, method='iir', n_jobs=1) # if ECG_ch_name == 'EMG063': if ECG_ch_name in raw.info['ch_names']: raw.set_channel_types({ECG_ch_name: 'ecg'}) # Without this files with ECG_ch_name = 'EMG063' fail # ECG_ch_name = 'ECG063' if EoG_ch_name == 'EMG065,EMG066,EMG067,EMG068': # Because ica.find_bads_eog... can process max 2 EoG channels EoG_ch_name = 'EMG065,EMG067' # it won't fail if I specify 4 channels, but it'll use only first # EMG065 and EMG066 are for vertical eye movements and # EMG067 and EMG068 are for horizontal # print rnk rnk = 'N/A' # 1) Fit ICA model using the FastICA algorithm # Other available choices are `infomax` or `extended-infomax` # We pass a float value between 0 and 1 to select n_components based on the # percentage of variance explained by the PCA components. reject = dict(mag=10e-12, grad=10000e-13) flat = dict(mag=0.1e-12, grad=1e-13) # check if we have an ICA, if yes, we load it ica_filename = os.path.join(subj_path, basename + "-ica.fif") raw_ica_filename = os.path.join(subj_path, basename + "_ica_raw.fif") info_filename = os.path.join(subj_path, basename + "_info.pickle") # if os.path.exists(ica_filename) == False: ica = ICA(n_components=0.99, method='fastica') # , max_iter=500 ica.fit(raw, picks=select_sensors, reject=reject, flat=flat) # decim = 3, # has_ICA = False # else: # has_ICA = True # ica = read_ica(ica_filename) # ica.exclude = [] # ica.labels_ = dict() # to avoid bug; Otherwise it'll throw an exception ica_sources_filename = subj_path + '/' + basename + '_ica_timecourse.fif' # if not os.path.isfile(ica_sources_filename): icaSrc = ica.get_sources(raw, add_channels=None, start=None, stop=None) icaSrc.save(ica_sources_filename, picks=None, tmin=0, tmax=None, buffer_size_sec=10, drop_small_buffer=False, proj=False, fmt='single', overwrite=True, split_size='2GB', verbose=None) icaSrc = None # if has_ICA == False: # ica.save(ica_filename) # return # 2) identify bad components by analyzing latent sources. # generate ECG epochs use detection via phase statistics # check if ECG_ch_name is in the raw channels # import ipdb; ipdb.set_trace() if ECG_ch_name in raw.info['ch_names']: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=ECG_ch_name) # if not a synthetic ECG channel is created from cross channel average else: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors) # ICA for ECG artifact # threshold=0.25 come defualt ecg_inds, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=0.25) # if len(ecg_inds) > 0: ecg_evoked = ecg_epochs.average() ecg_epochs = None # ecg_epochs use too much memory n_max_ecg = 3 ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds n_max_eog = 4 # import pdb; pdb.set_trace() if set(EoG_ch_name.split(',')).issubset(set(raw.info['ch_names'])): eog_inds, eog_scores = ica.find_bads_eog(raw, ch_name=EoG_ch_name) eog_inds = eog_inds[:n_max_eog] eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=EoG_ch_name).average() else: eog_inds = eog_scores = eog_evoked = [] # ------------------------------------------------------ # # This is necessary. Otherwise line # will through an exception if not eog_inds: eog_inds = None # ------------------------------------------------------ # generateReport(raw=raw, ica=ica, subj_name=subj_name, subj_path=subj_path, basename=basename, ecg_evoked=ecg_evoked, ecg_scores=ecg_scores, ecg_inds=ecg_inds, ECG_ch_name=ECG_ch_name, eog_evoked=eog_evoked, eog_scores=eog_scores, eog_inds=eog_inds, EoG_ch_name=EoG_ch_name) sfreq = raw.info['sfreq'] raw = None # To save memory # save ICA solution print ica_filename # ------------------------- Generate log ------------------------ # f = open(subj_path + '/' + basename + '_ica.log', 'w') f.write('Data rank after SSS: ' + str(rnk) + '\n') f.write('Sampling freq: ' + str(sfreq) + '\n') f.write('ECG exclude suggested: ' + str(ecg_inds) + '\n') f.write('EOG exclude suggested: ' + str(eog_inds) + '\n') f.write('\n') f.write('ECG exclude final: ' + str(ecg_inds) + '\n') f.write('EOG exclude final: ' + str(eog_inds) + '\n') f.write('Muscles exclude: []' + '\n') f.close() # ------------------------ end generate log ---------------------- # with open(info_filename, 'wb') as f: pickle.dump(ecg_inds, f) pickle.dump(ecg_scores, f) pickle.dump(eog_inds, f) pickle.dump(eog_scores, f) # -------------------- Save ICA solution ------------------------- # ica.save(ica_filename) return raw_ica_filename, sfreq
def test_find_ecg(): """Test find ECG peaks.""" # Test if ECG analysis will work on data that is not preloaded raw = read_raw_fif(raw_fname, preload=False) # once with mag-trick # once with characteristic channel raw_bad = raw.copy().load_data() ecg_idx = raw.ch_names.index('MEG 1531') raw_bad._data[ecg_idx, :1] = 1e6 # this will break the detector raw_bad.annotations.append(raw.first_samp / raw.info['sfreq'], 1. / raw.info['sfreq'], 'BAD_values') for ch_name in ['MEG 1531', None]: events, ch_ECG, average_pulse, ecg = find_ecg_events( raw, event_id=999, ch_name=ch_name, return_ecg=True) assert raw.n_times == ecg.shape[-1] n_events = len(events) _, times = raw[0, :] assert 55 < average_pulse < 60 # with annotations with pytest.deprecated_call(): average_pulse = find_ecg_events(raw_bad, ch_name=ch_name)[2] assert average_pulse < 1. average_pulse = find_ecg_events(raw_bad, ch_name=ch_name, reject_by_annotation=True)[2] assert 55 < average_pulse < 60 average_pulse = find_ecg_events(raw_bad, ch_name='MEG 2641', reject_by_annotation=False)[2] assert 55 < average_pulse < 65 del raw_bad picks = pick_types( raw.info, meg='grad', eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') # There should be no ECG channels, or else preloading will not be # tested assert 'ecg' not in raw ecg_epochs = create_ecg_epochs(raw, picks=picks, keep_ecg=True) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' in ecg_epochs.ch_names picks = pick_types( ecg_epochs.info, meg=False, eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') assert len(picks) == 1 ecg_epochs = create_ecg_epochs(raw, ch_name='MEG 2641') assert 'MEG 2641' in ecg_epochs.ch_names # test with user provided ecg channel raw.info['projs'] = list() with pytest.warns(RuntimeWarning, match='unit for channel'): raw.set_channel_types({'MEG 2641': 'ecg'}) create_ecg_epochs(raw) raw.load_data().pick_types() # remove ECG ecg_epochs = create_ecg_epochs(raw, keep_ecg=False) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' not in ecg_epochs.ch_names
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 run_epochs(subject_id): subject = "sub%03d" % subject_id print("processing subject: %s" % subject) data_path = op.join(meg_dir, subject) all_epochs = list() # Get all bad channels mapping = map_subjects[subject_id] # map to correct subject all_bads = list() for run in range(1, 7): bads = list() bad_name = op.join('bads', mapping, 'run_%02d_raw_tr.fif_bad' % run) if os.path.exists(bad_name): with open(bad_name) as f: for line in f: bads.append(line.strip()) all_bads += [bad for bad in bads if bad not in all_bads] for run in range(1, 7): print " - Run %s" % run run_fname = op.join(data_path, 'run_%02d_filt_sss_raw.fif' % run) if not os.path.exists(run_fname): continue raw = mne.io.Raw(run_fname, preload=True, add_eeg_ref=False) raw.set_channel_types({'EEG061': 'eog', 'EEG062': 'eog', 'EEG063': 'ecg', 'EEG064': 'misc'}) # EEG064 free floating el. raw.rename_channels({'EEG061': 'EOG061', 'EEG062': 'EOG062', 'EEG063': 'ECG063'}) eog_events = mne.preprocessing.find_eog_events(raw) eog_events[:, 0] -= int(0.25 * raw.info['sfreq']) annotations = mne.Annotations(eog_events[:, 0] / raw.info['sfreq'], np.repeat(0.5, len(eog_events)), 'BAD_blink', raw.info['meas_date']) raw.annotations = annotations # Remove epochs with blinks delay = int(0.0345 * raw.info['sfreq']) events = mne.read_events(op.join(data_path, 'run_%02d_filt_sss-eve.fif' % run)) events[:, 0] = events[:, 0] + delay raw.info['bads'] = all_bads raw.interpolate_bads() raw.set_eeg_reference() picks = mne.pick_types(raw.info, meg=True, eeg=True, stim=True, eog=True) # Read epochs epochs = mne.Epochs(raw, events, events_id, tmin, tmax, proj=True, picks=picks, baseline=baseline, preload=True, decim=2, reject=reject, add_eeg_ref=False) # ICA ica_name = op.join(meg_dir, subject, 'run_%02d-ica.fif' % run) ica = read_ica(ica_name) n_max_ecg = 3 # use max 3 components ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5) ecg_inds, scores_ecg = ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=0.8) ica.exclude += ecg_inds[:n_max_ecg] ica.apply(epochs) all_epochs.append(epochs) epochs = mne.epochs.concatenate_epochs(all_epochs) epochs.save(op.join(data_path, '%s-epo.fif' % subject))
def test_find_ecg(): """Test find ECG peaks.""" # Test if ECG analysis will work on data that is not preloaded raw = read_raw_fif(raw_fname, preload=False) # once with mag-trick # once with characteristic channel for ch_name in ['MEG 1531', None]: events, ch_ECG, average_pulse, ecg = find_ecg_events(raw, event_id=999, ch_name=ch_name, return_ecg=True) assert raw.n_times == ecg.shape[-1] n_events = len(events) _, times = raw[0, :] assert 55 < average_pulse < 60 picks = pick_types(raw.info, meg='grad', eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') # There should be no ECG channels, or else preloading will not be # tested assert 'ecg' not in raw ecg_epochs = create_ecg_epochs(raw, picks=picks, keep_ecg=True) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' in ecg_epochs.ch_names picks = pick_types(ecg_epochs.info, meg=False, eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') assert len(picks) == 1 ecg_epochs = create_ecg_epochs(raw, ch_name='MEG 2641') assert 'MEG 2641' in ecg_epochs.ch_names # test with user provided ecg channel raw.info['projs'] = list() with pytest.warns(RuntimeWarning, match='unit for channel'): raw.set_channel_types({'MEG 2641': 'ecg'}) create_ecg_epochs(raw) raw.load_data().pick_types() # remove ECG ecg_epochs = create_ecg_epochs(raw, keep_ecg=False) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' not in ecg_epochs.ch_names
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)
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)
def test_find_ecg(): """Test find ECG peaks.""" # Test if ECG analysis will work on data that is not preloaded raw = read_raw_fif(raw_fname, preload=False).pick_types(meg=True) raw.pick(raw.ch_names[::10] + ['MEG 2641']) raw.info.normalize_proj() # once with mag-trick # once with characteristic channel raw_bad = raw.copy().load_data() ecg_idx = raw.ch_names.index('MEG 1531') raw_bad._data[ecg_idx, :1] = 1e6 # this will break the detector raw_bad.annotations.append(raw.first_samp / raw.info['sfreq'], 1. / raw.info['sfreq'], 'BAD_values') raw_noload = raw.copy() raw.resample(100) for ch_name, tstart in zip(['MEG 1531', None], [raw.times[-1] / 2, 0]): events, ch_ECG, average_pulse, ecg = find_ecg_events(raw, event_id=999, ch_name=ch_name, tstart=tstart, return_ecg=True) assert raw.n_times == ecg.shape[-1] assert 40 < average_pulse < 60 n_events = len(events) # with annotations average_pulse = find_ecg_events(raw_bad, ch_name=ch_name, tstart=tstart, reject_by_annotation=False)[2] assert average_pulse < 1. average_pulse = find_ecg_events(raw_bad, ch_name=ch_name, tstart=tstart, reject_by_annotation=True)[2] assert 55 < average_pulse < 60 picks = pick_types(raw.info, meg='grad', eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') # There should be no ECG channels, or else preloading will not be # tested assert 'ecg' not in raw ecg_epochs = create_ecg_epochs(raw_noload, picks=picks, keep_ecg=True) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' in ecg_epochs.ch_names assert len(ecg_epochs) == 23 picks = pick_types(ecg_epochs.info, meg=False, eeg=False, stim=False, eog=False, ecg=True, emg=False, ref_meg=False, exclude='bads') assert len(picks) == 1 ecg_epochs = create_ecg_epochs(raw, ch_name='MEG 2641') assert 'MEG 2641' in ecg_epochs.ch_names # test with user provided ecg channel raw.info['projs'] = list() assert 'MEG 2641' in raw.ch_names with pytest.warns(RuntimeWarning, match='unit for channel'): raw.set_channel_types({'MEG 2641': 'ecg'}) create_ecg_epochs(raw) raw.pick_types(meg=True) # remove ECG assert 'MEG 2641' not in raw.ch_names ecg_epochs = create_ecg_epochs(raw, keep_ecg=False) assert len(ecg_epochs.events) == n_events assert 'ECG-SYN' not in raw.ch_names assert 'ECG-SYN' not in ecg_epochs.ch_names
# to definitely register this component as a bad one to be removed # there is the ``ica.exclude`` attribute, a simple Python list ica.exclude.extend(eog_inds) # from now on the ICA will reject this component even if no exclude # parameter is passed, and this information will be stored to disk # on saving # uncomment this for reading and writing # ica.save('my-ica.fif') # ica = read_ica('my-ica.fif') ############################################################################### # Exercise: find and remove ECG artifacts using ICA! ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') ica.plot_properties(ecg_epochs, picks=ecg_inds, psd_args={'fmax': 35.}) ############################################################################### # What if we don't have an EOG channel? # ------------------------------------- # # We could either: # # 1. make a bipolar reference from frontal EEG sensors and use as virtual EOG # channel. This can be tricky though as you can only hope that the frontal # EEG channels only reflect EOG and not brain dynamics in the prefrontal # cortex. # 2. go for a semi-automated approach, using template matching.
def 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
ecg_inds, scores = ica.find_bads_ecg(raw, method='ctps', ch_name='ECG002', threshold=0.25) if len(ecg_inds) > 0: fig = ica.plot_scores(scores, exclude=ecg_inds, title=title % 'ecg') fig.savefig(img_prefix + '_ecg_scores.png') show_picks = np.abs(scores).argsort()[::-1][:n_max_ecg] fig = ica.plot_sources(raw, show_picks, exclude=ecg_inds, start=t_start, stop=t_stop, title=title % 'ecg') fig.savefig(img_prefix + '_ecg_sources.png') fig = ica.plot_components(ecg_inds, title=title % 'ecg', colorbar=True) fig.set_size_inches(9.,6.) fig.savefig(img_prefix + '_ecg_components.png') # estimate average artifact ecg_epochs = create_ecg_epochs(raw, ch_name='ECG002', tmin=-.2, tmax=.5, picks=picks, flat='grad', verbose=False) ecg_evoked = ecg_epochs.average() fig = ica.plot_sources(ecg_evoked, exclude=ecg_inds) # plot ECG sources + selection fig.savefig(img_prefix + '_ecg_evoked_sources.png') fig = ica.plot_overlay(ecg_evoked, exclude=ecg_inds) # plot ECG cleaning fig.savefig(img_prefix + '_ecg_evoked_overlay.png') # detect EOG by correlation # do both together eog_inds, scores = ica.find_bads_eog(raw, ch_name='EOG001,EOG003') allscores = np.vstack((scores[0], scores[1])) mscores = np.max(np.abs(allscores), axis=0) # now scores is show_picks = mscores.argsort()[::-1][:n_max_eog]
def compute_ica(subject): """Function will compute ICA on raw and apply the ICA. params: subject : str the subject id to be loaded """ raw = Raw(save_folder + "%s_filtered_data_mc_raw_tsss.fif" % subject, preload=True) # ICA Part ica = ICA(n_components=0.95, method='fastica', max_iter=256) picks = mne.pick_types(raw.info, meg=True, eeg=True, stim=False, exclude='bads') ica.fit(raw, picks=picks, decim=decim, reject=reject) # maximum number of components to reject n_max_ecg, n_max_eog = 3, 1 ########################################################################## # 2) identify bad components by analyzing latent sources. title = 'Sources related to %s artifacts (red) for sub: %s' # generate ECG epochs use detection via phase statistics ecg_epochs = create_ecg_epochs(raw, ch_name="ECG002", tmin=-.5, tmax=.5, picks=picks) n_ecg_epochs_found = len(ecg_epochs.events) sel_ecg_epochs = np.arange(0, n_ecg_epochs_found, 10) ecg_epochs = ecg_epochs[sel_ecg_epochs] ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') fig = ica.plot_scores(scores, exclude=ecg_inds, title=title % ('ecg', subject)) fig.savefig(save_folder + "pics/%s_ecg_scores.png" % subject) if ecg_inds: show_picks = np.abs(scores).argsort()[::-1][:5] fig = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % ('ecg', subject), show=False) fig.savefig(save_folder + "pics/%s_ecg_sources.png" % subject) fig = ica.plot_components(ecg_inds, title=title % ('ecg', subject), colorbar=True) fig.savefig(save_folder + "pics/%s_ecg_component.png" % subject) ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds # estimate average artifact ecg_evoked = ecg_epochs.average() del ecg_epochs # plot ECG sources + selection fig = ica.plot_sources(ecg_evoked, exclude=ecg_inds) fig.savefig(save_folder + "pics/%s_ecg_sources_ave.png" % subject) # plot ECG cleaning ica.plot_overlay(ecg_evoked, exclude=ecg_inds) fig.savefig(save_folder + "pics/%s_ecg_sources_clean_ave.png" % subject) # DETECT EOG BY CORRELATION # HORIZONTAL EOG eog_epochs = create_eog_epochs(raw, ch_name="EOG001") eog_inds, scores = ica.find_bads_eog(raw) fig = ica.plot_scores(scores, exclude=eog_inds, title=title % ('eog', subject)) fig.savefig(save_folder + "pics/%s_eog_scores.png" % subject) fig = ica.plot_components(eog_inds, title=title % ('eog', subject), colorbar=True) fig.savefig(save_folder + "pics/%s_eog_component.png" % subject) eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds del eog_epochs ########################################################################## # Apply the solution to Raw, Epochs or Evoked like this: raw_ica = ica.apply(raw, copy=False) ica.save(save_folder + "%s-ica.fif" % subject) # save ICA componenets # Save raw with ICA removed raw_ica.save(save_folder + "%s_filtered_ica_mc_raw_tsss.fif" % subject, overwrite=True) plt.close("all")
def preprocess_ICA_fif_to_ts(fif_file, ECG_ch_name, EoG_ch_name, l_freq, h_freq, down_sfreq, variance, is_sensor_space, data_type): import os import numpy as np import mne from mne.io import Raw from mne.preprocessing import ICA, read_ica from mne.preprocessing import create_ecg_epochs, create_eog_epochs from mne.report import Report from nipype.utils.filemanip import split_filename as split_f report = Report() subj_path, basename, ext = split_f(fif_file) (data_path, sbj_name) = os.path.split(subj_path) print data_path # Read raw # If None the compensation in the data is not modified. # If set to n, e.g. 3, apply gradient compensation of grade n as for # CTF systems (compensation=3) raw = Raw(fif_file, preload=True) # select sensors select_sensors = mne.pick_types(raw.info, meg=True, ref_meg=False, exclude='bads') picks_meeg = mne.pick_types(raw.info, meg=True, eeg=True, exclude='bads') # save electrode locations sens_loc = [raw.info['chs'][i]['loc'][:3] for i in select_sensors] sens_loc = np.array(sens_loc) channel_coords_file = os.path.abspath("correct_channel_coords.txt") print '*** ' + channel_coords_file + '***' np.savetxt(channel_coords_file, sens_loc, fmt='%s') # save electrode names sens_names = np.array([raw.ch_names[pos] for pos in select_sensors],dtype = "str") # AP 21032016 # channel_names_file = os.path.join(data_path, "correct_channel_names.txt") channel_names_file = os.path.abspath("correct_channel_names.txt") np.savetxt(channel_names_file,sens_names , fmt = '%s') ### filtering + downsampling raw.filter(l_freq=l_freq, h_freq=h_freq, picks=picks_meeg, method='iir', n_jobs=8) # raw.filter(l_freq = l_freq, h_freq = h_freq, picks = picks_meeg, # method='iir') # raw.resample(sfreq=down_sfreq, npad=0) ### 1) Fit ICA model using the FastICA algorithm # Other available choices are `infomax` or `extended-infomax` # We pass a float value between 0 and 1 to select n_components based on the # percentage of variance explained by the PCA components. ICA_title = 'Sources related to %s artifacts (red)' is_show = False # visualization reject = dict(mag=4e-12, grad=4000e-13) # check if we have an ICA, if yes, we load it ica_filename = os.path.join(subj_path,basename + "-ica.fif") if os.path.exists(ica_filename) is False: ica = ICA(n_components=variance, method='fastica', max_iter=500) # , max_iter=500 ica.fit(raw, picks=select_sensors, reject=reject) # decim = 3, has_ICA = False else: has_ICA = True print ica_filename + ' exists!!!' ica = read_ica(ica_filename) ica.exclude = [] # 2) identify bad components by analyzing latent sources. # generate ECG epochs use detection via phase statistics # if we just have exclude channels we jump these steps # if len(ica.exclude)==0: n_max_ecg = 3 n_max_eog = 2 # check if ECG_ch_name is in the raw channels if ECG_ch_name in raw.info['ch_names']: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=ECG_ch_name) # if not a synthetic ECG channel is created from cross channel average else: ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors) # ICA for ECG artifact # threshold=0.25 come default ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps') print scores print '\n len ecg_inds *** ' + str(len(ecg_inds)) + '***\n' if len(ecg_inds) > 0: ecg_evoked = ecg_epochs.average() fig1 = ica.plot_scores(scores, exclude=ecg_inds, title=ICA_title % 'ecg', show=is_show) show_picks = np.abs(scores).argsort()[::-1][:5] # Pick the five largest scores and plot them # Plot estimated latent sources given the unmixing matrix. #ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=ICA_title % 'ecg', show=is_show) t_start = 0 t_stop = 30 # take the fist 30s fig2 = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=ICA_title % 'ecg' + ' in 30s' ,start = t_start, stop = t_stop, show=is_show) # topoplot of unmixing matrix columns fig3 = ica.plot_components(show_picks, title=ICA_title % 'ecg', colorbar=True, show=is_show) ecg_inds = ecg_inds[:n_max_ecg] ica.exclude += ecg_inds fig4 = ica.plot_sources(ecg_evoked, exclude=ecg_inds, show=is_show) # plot ECG sources + selection fig5 = ica.plot_overlay(ecg_evoked, exclude=ecg_inds, show=is_show) # plot ECG cleaning fig = [fig1, fig2, fig3, fig4, fig5] report.add_figs_to_section(fig, captions=['Scores of ICs related to ECG', 'Time Series plots of ICs (ECG)', 'TopoMap of ICs (ECG)', 'Time-locked ECG sources', 'ECG overlay'], section = 'ICA - ECG') # check if EoG_ch_name is in the raw channels # if EoG_ch_name is empty if data_type is fif, ICA routine automatically looks for EEG61, EEG62 # otherwise if data_type is ds we jump this step if not EoG_ch_name and data_type=='ds': eog_inds = [] else: if EoG_ch_name in raw.info['ch_names']: ### ICA for eye blink artifact - detect EOG by correlation eog_inds, scores = ica.find_bads_eog(raw, ch_name = EoG_ch_name) else: eog_inds, scores = ica.find_bads_eog(raw) if len(eog_inds) > 0: fig6 = ica.plot_scores(scores, exclude=eog_inds, title=ICA_title % 'eog', show=is_show) report.add_figs_to_section(fig6, captions=['Scores of ICs related to EOG'], section = 'ICA - EOG') # check how many EoG ch we have rs = np.shape(scores) if len(rs)>1: rr = rs[0] show_picks = [np.abs(scores[i][:]).argsort()[::-1][:5] for i in range(rr)] for i in range(rr): fig7 = ica.plot_sources(raw, show_picks[i][:], exclude=eog_inds, start = raw.times[0], stop = raw.times[-1], title=ICA_title % 'eog',show=is_show) fig8 = ica.plot_components(show_picks[i][:], title=ICA_title % 'eog', colorbar=True, show=is_show) # ICA nel tempo fig = [fig7, fig8] report.add_figs_to_section(fig, captions=['Scores of ICs related to EOG', 'Time Series plots of ICs (EOG)'], section = 'ICA - EOG') else: show_picks = np.abs(scores).argsort()[::-1][:5] fig7 = ica.plot_sources(raw, show_picks, exclude=eog_inds, title=ICA_title % 'eog', show=is_show) fig8 = ica.plot_components(show_picks, title=ICA_title % 'eog', colorbar=True, show=is_show) fig = [fig7, fig8] report.add_figs_to_section(fig, captions=['Time Series plots of ICs (EOG)', 'TopoMap of ICs (EOG)',], section = 'ICA - EOG') eog_inds = eog_inds[:n_max_eog] ica.exclude += eog_inds if EoG_ch_name in raw.info['ch_names']: eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors, ch_name=EoG_ch_name).average() else: eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=select_sensors).average() fig9 = ica.plot_sources(eog_evoked, exclude=eog_inds, show=is_show) # plot EOG sources + selection fig10 = ica.plot_overlay(eog_evoked, exclude=eog_inds, show=is_show) # plot EOG cleaning fig = [fig9, fig10] report.add_figs_to_section(fig, captions=['Time-locked EOG sources', 'EOG overlay'], section = 'ICA - EOG') fig11 = ica.plot_overlay(raw, show=is_show) report.add_figs_to_section(fig11, captions=['Signal'], section = 'Signal quality') ### plot all topographies and time seris of the ICA components n_ica_components = ica.mixing_matrix_.shape[1] n_topo = 10; n_fig = n_ica_components/n_topo; n_plot = n_ica_components%n_topo; print '*************** n_fig = ' + str(n_fig) + ' n_plot = ' + str(n_plot) + '********************' fig = [] t_start = 0 t_stop = None # 60 if we want to take the fist 60s for n in range(0,n_fig): fig_tmp = ica.plot_components(range(n_topo*n,n_topo*(n+1)),title='ICA components', show=is_show) fig.append(fig_tmp) fig_tmp = ica.plot_sources(raw, range(n_topo*n,n_topo*(n+1)), start = t_start, stop = t_stop, title='ICA components') fig.append(fig_tmp) # if n_plot > 0: # fig_tmp = ica.plot_components(range(n_fig*n_topo,n_ica_components), title='ICA components', show=is_show) # fig.append(fig_tmp) # fig_tmp = ica.plot_sources(raw, range(n_fig*n_topo,n_ica_components), # start = t_start, stop = t_stop, # title='ICA components') # fig.append(fig_tmp) # # for n in range(0, len(fig)): # report.add_figs_to_section(fig[n], captions=['TOPO'], section = 'ICA Topo Maps') if n_plot > 5: n_fig_l = n_plot//5 print '*************************** ' + str(n_fig_l) + ' *********************************' for n in range(0,n_fig_l): print range(n_fig*n_topo+5*n, n_fig*n_topo+5*(n+1)) fig_tmp = ica.plot_components(range(n_fig*n_topo+5*n, n_fig*n_topo+5*(n+1)),title='ICA components') fig.append(fig_tmp) fig_tmp = ica.plot_sources(raw, range(n_fig*n_topo+5*n, n_fig*n_topo+5*(n+1)), start = t_start, stop = t_stop, title='ICA components') fig.append(fig_tmp) print range(n_fig*n_topo+5*(n+1),n_ica_components) fig_tmp = ica.plot_components(range(n_fig*n_topo+5*(n+1),n_ica_components), title='ICA components') fig.append(fig_tmp) fig_tmp = ica.plot_sources(raw, range(n_fig*n_topo+5*(n+1),n_ica_components), start = t_start, stop = t_stop, title='ICA components') fig.append(fig_tmp) for n in range(0, len(fig)): report.add_figs_to_section(fig[n], captions=['TOPO'], section = 'ICA Topo Maps') report_filename = os.path.join(subj_path,basename + "-report.html") print '******* ' + report_filename report.save(report_filename, open_browser=False, overwrite=True) # 3) apply ICA to raw data and save solution and report # check the amplitudes do not change # raw_ica_file = os.path.abspath(basename[:i_raw] + 'ica-raw.fif') raw_ica_file = os.path.join(subj_path, basename + '-preproc-raw.fif') raw_ica = ica.apply(raw) raw_ica.resample(sfreq=down_sfreq, npad=0) raw_ica.save(raw_ica_file, overwrite=True) # save ICA solution print ica_filename if has_ICA is False: ica.save(ica_filename) # 4) save data data_noIca, times = raw[select_sensors, :] data, times = raw_ica[select_sensors, :] print data.shape print raw.info['sfreq'] ts_file = os.path.abspath(basename + "_ica.npy") np.save(ts_file, data) print '***** TS FILE ' + ts_file + '*****' if is_sensor_space: return ts_file, channel_coords_file, channel_names_file, raw.info['sfreq'] else: # return raw_ica, channel_coords_file, channel_names_file, raw.info['sfreq'] return raw_ica_file, channel_coords_file, channel_names_file, raw.info['sfreq']
print('Pre-selected comps: '+str(icacomps.exclude)) print('##################') icacomps.excludeold=icacomps.exclude 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 = '> '
#%% parameters 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)
# To save an ICA solution you can say: ############################################################################### # 2) identify bad components by analyzing latent sources. title = 'Sources related to %s artifacts (red)' # generate ECG epochs use detection via phase statistics picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=True, ecg=True, stim=False, exclude='bads') # create_ecg_epochs is strange: it strips the channels of anything non M/EEG # UNLESS picks=None picks=None ecg_epochs = create_ecg_epochs(raw, ch_name='ECG002', tmin=-.5, tmax=.5, picks=picks, verbose=True) # This will work with the above, but uses MASSIVE RAM # Not sure the ECG quality is good enough for the QRS-detector ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps', ch_name='ECG002') # This creates a synthetic ECG from magnetometers, probably better... ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps', ch_name='ECG002') fig = ica.plot_scores(scores, exclude=ecg_inds, title=title % 'ecg') fig.savefig(img_folder + '/ica_ecg_scores.png') show_picks = np.abs(scores).argsort()[::-1][:5] fig = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=title % 'ecg') fig.savefig(img_folder + '/ica_ecg_sources.png') fig = ica.plot_components(ecg_inds, title=title % 'ecg', colorbar=True)
############################################################################### # On MEG sensors we see narrow frequency peaks at 60, 120, 180, 240 Hz, # related to line noise. # But also some high amplitude signals between 25 and 32 Hz, hinting at other # biological artifacts such as ECG. These can be most easily detected in the # time domain using MNE helper functions # # See :ref:`sphx_glr_auto_tutorials_plot_artifacts_correction_filtering.py`. ############################################################################### # ECG # --- # # finds ECG events, creates epochs, averages and plots 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()
############################################################################### # On MEG sensors we see narrow frequency peaks at 60, 120, 180, 240 Hz, # related to line noise. # But also some high amplitude signals between 25 and 32 Hz, hinting at other # biological artifacts such as ECG. These can be most easily detected in the # time domain using MNE helper functions # # See :ref:`tut_artifacts_filter`. ############################################################################### # ECG # --- # # 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()
# Define the parameters for the ICA. There is a random component to this. # 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)
# pick some channels that clearly show heartbeats and blinks regexp = r'(MEG [12][45][123]1|EEG 00.)' artifact_picks = mne.pick_channels_regexp(raw.ch_names, regexp=regexp) raw.plot(order=artifact_picks, n_channels=len(artifact_picks)) ############################################################################### # Repairing ECG artifacts with SSP # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # MNE-Python provides several functions for detecting and removing heartbeats # from EEG and MEG data. As we saw in :ref:`tut-artifact-overview`, # `~mne.preprocessing.create_ecg_epochs` can be used to both detect and # extract heartbeat artifacts into an `~mne.Epochs` object, which can # be used to visualize how the heartbeat artifacts manifest across the sensors: ecg_evoked = create_ecg_epochs(raw).average() ecg_evoked.plot_joint() ############################################################################### # Looks like the EEG channels are pretty spread out; let's baseline-correct and # plot again: ecg_evoked.apply_baseline((None, None)) ecg_evoked.plot_joint() ############################################################################### # To compute SSP projectors for the heartbeat artifact, you can use # `~mne.preprocessing.compute_proj_ecg`, which 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).
# # License: BSD (3-clause) import mne from mne.io import Raw from mne.preprocessing import ICA, create_ecg_epochs from mne.datasets import sample print(__doc__) ############################################################################### # Fit ICA model using the FastICA algorithm, detect and inspect components data_path = sample.data_path() raw_fname = data_path + "/MEG/sample/sample_audvis_filt-0-40_raw.fif" raw = Raw(raw_fname, preload=True) raw.filter(1, 30, method="iir") raw.pick_types(meg=True, eeg=False, exclude="bads", stim=True) # longer + more epochs for more artifact exposure events = mne.find_events(raw, stim_channel="STI 014") epochs = mne.Epochs(raw, events, event_id=None, tmin=-0.2, tmax=0.5) ica = ICA(n_components=0.95, method="fastica").fit(epochs) ecg_epochs = create_ecg_epochs(raw, tmin=-0.5, tmax=0.5) ecg_inds, scores = ica.find_bads_ecg(ecg_epochs) ica.plot_components(ecg_inds)
def apply_ica(subject, run, session): print("Processing subject: %s" % subject) # Construct the search path for the data file. `sub` is mandatory subject_path = op.join('sub-{}'.format(subject)) # `session` is optional if session is not None: subject_path = op.join(subject_path, 'ses-{}'.format(session)) subject_path = op.join(subject_path, config.kind) bids_basename = make_bids_basename(subject=subject, session=session, task=config.task, acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space ) fpath_deriv = op.join(config.bids_root, 'derivatives', config.PIPELINE_NAME, subject_path) fname_in = \ op.join(fpath_deriv, bids_basename + '-epo.fif') fname_out = \ op.join(fpath_deriv, bids_basename + '_cleaned-epo.fif') # load epochs to reject ICA components epochs = mne.read_epochs(fname_in, preload=True) print("Input: ", fname_in) print("Output: ", fname_out) # load first run of raw data for ecg /eog epochs print(" Loading one run from raw data") bids_basename = make_bids_basename(subject=subject, session=session, task=config.task, acquisition=config.acq, run=config.runs[0], processing=config.proc, recording=config.rec, space=config.space ) if config.use_maxwell_filter: raw_fname_in = \ op.join(fpath_deriv, bids_basename + '_sss_raw.fif') else: raw_fname_in = \ op.join(fpath_deriv, 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 print(ch_type) picks = all_picks[ch_type] # Load ICA fname_ica = \ op.join(fpath_deriv, bids_basename + '_%s-ica.fif' % 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) 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(fpath_deriv, bids_basename + '_%s-reject_ica.html' % ch_type) 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 ECG!') # EOG pick_eog = mne.pick_types(raw.info, meg=False, eeg=False, ecg=False, eog=True) eog_inds = list() 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) if report is not None: 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)
def runICA(raw,saveRoot,name): saveRoot = saveRoot icaList = [] ica = [] n_max_ecg = 3 # max number of ecg components # n_max_eog_1 = 2 # max number of vert eog comps # n_max_eog_2 = 2 # max number of horiz eog comps ecg_source_idx, ecg_scores, ecg_exclude = [], [], [] eog_source_idx, eog_scores, eog_exclude = [], [], [] #horiz = 1 # will later be modified to horiz = 0 if no horizontal EOG components are identified ica = ICA(n_components=0.90,n_pca_components=64,max_pca_components=100,noise_cov=None) ica.fit(raw) #************* eog_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, eog=True, ecg=False, emg=False)[0] ecg_picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, ecg=True, eog=False, emg=False)[0] ica_picks = mne.pick_types(raw.info, meg=True, eeg=False, eog=False, ecg=False, stim=False, exclude='bads') ecg_epochs = create_ecg_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks) ecg_evoked = ecg_epochs.average() eog_evoked = create_eog_epochs(raw, tmin=-.5, tmax=.5, picks=ica_picks).average() ecg_source_idx, ecg_scores = ica.find_bads_ecg(ecg_epochs, method='ctps') eog_source_idx, eog_scores = ica.find_bads_eog(raw,ch_name=raw.ch_names[eog_picks].encode('ascii', 'ignore')) # defining a title-frame for later use title = 'Sources related to %s artifacts (red)' # extracting number of ica-components and plotting their topographies source_idx = range(0, ica.n_components_) ica_plot = ica.plot_components(source_idx, ch_type="mag") # select ICA sources and reconstruct MEG signals, compute clean ERFs # Add detected artefact sources to exclusion list # We now add the eog artefacts to the ica.exclusion list if not ecg_source_idx: print("No ECG components above threshold were identified for subject " + name + " - selecting the component with the highest score under threshold") ecg_exclude = [np.absolute(ecg_scores).argmax()] ecg_source_idx=[np.absolute(ecg_scores).argmax()] elif ecg_source_idx: ecg_exclude += ecg_source_idx[:n_max_ecg] ica.exclude += ecg_exclude if not eog_source_idx: if np.absolute(eog_scores).any>0.3: eog_exclude=[np.absolute(eog_scores).argmax()] eog_source_idx=[np.absolute(eog_scores).argmax()] print("No EOG components above threshold were identified " + name + " - selecting the component with the highest score under threshold above 0.3") elif not np.absolute(eog_scores).any>0.3: eog_exclude=[] print("No EOG components above threshold were identified" + name) elif eog_source_idx: eog_exclude += eog_source_idx ica.exclude += eog_exclude print('########## saving') if len(eog_exclude) == 0: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog_none-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') elif len(eog_exclude) == 1: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') elif len(eog_exclude) == 2: if len(ecg_exclude) == 0: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg_none' + '.pdf', format = 'pdf') elif len(ecg_exclude) == 1: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 2: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '.pdf', format = 'pdf') elif len(ecg_exclude) == 3: ica_plot.savefig(saveRoot + name + '_comps_eog' + map(str, eog_exclude)[0] + '_' + map(str, eog_exclude)[1] + '-ecg' + map(str, ecg_exclude)[0] + '_' + map(str, ecg_exclude)[1] + '_' + map(str, ecg_exclude)[2] + '.pdf', format = 'pdf') # plot the scores for the different components highlighting in red that/those related to ECG scores_plots_ecg=ica.plot_scores(ecg_scores, exclude=ecg_source_idx, title=title % 'ecg') scores_plots_ecg.savefig(saveRoot + name + '_ecg_scores.pdf', format = 'pdf') scores_plots_eog=ica.plot_scores(eog_scores, exclude=eog_source_idx, title=title % 'eog') scores_plots_eog.savefig(saveRoot + name + '_eog_scores.pdf', format = 'pdf') source_source_ecg=ica.plot_sources(ecg_evoked, exclude=ecg_source_idx) source_source_ecg.savefig(saveRoot + name + '_ecg_source.pdf', format = 'pdf') #ax = plt.subplot(2,1,2) source_clean_ecg=ica.plot_overlay(ecg_evoked, exclude=ecg_source_idx) source_clean_ecg.savefig(saveRoot + name + '_ecg_clean.pdf', format = 'pdf') #clean_plot.savefig(saveRoot + name + '_ecg_clean.pdf', format = 'pdf') #if len(eog_exclude) > 0: source_source_eog=ica.plot_sources(eog_evoked, exclude=eog_source_idx) source_source_eog.savefig(saveRoot + name + '_eog_source.pdf', format = 'pdf') source_clean_eog=ica.plot_overlay(eog_evoked, exclude=eog_source_idx) source_clean_eog.savefig(saveRoot + name + '_eog_clean.pdf', format = 'pdf') overl_plot = ica.plot_overlay(raw) overl_plot.savefig(saveRoot + name + '_overl.pdf', format = 'pdf') event_id = 999 ecg_events, _, _ = mne.preprocessing.find_ecg_events(raw, event_id, ch_name=raw.ch_names[ecg_picks].encode('UTF8')) picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, ecg=True) tmin, tmax = -0.1, 0.1 epochs_ecg = mne.Epochs(raw, ecg_events, event_id, tmin, tmax,picks=picks) data_ecg = epochs_ecg.get_data() event_id = 998 eog_events = mne.preprocessing.find_eog_events(raw, event_id, ch_name=raw.ch_names[eog_picks].encode('UTF8')) picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=False, eog=True, exclude='bads') tmin, tmax = -0.5, 0.5 epochs_eog = mne.Epochs(raw, eog_events, event_id, tmin, tmax,picks=[picks[0]])#, data_eog = epochs_eog.get_data() plSize = 1 pltRes = 128 ecg_eogAvg=plt.figure(figsize=(20,10)) ax = plt.subplot(2,3,1) plt.plot(1e3 * epochs_ecg.times, np.squeeze(data_ecg).T) plt.xlabel('Times (ms)') plt.title('ECG') plt.ylabel('ECG') plt.show() ax2 = plt.subplot(2,3,2) plot_evoked_topomap(ecg_evoked, times=0, average=0.02, ch_type='mag',colorbar=False, size=plSize, res=pltRes, axes=ax2) ax3= plt.subplot(2,3,3) plot_evoked_topomap(ecg_evoked, times=0, average=0.02, ch_type='grad',colorbar=False, size=plSize, res=pltRes, axes=ax3) ax = plt.subplot(2,3,4) plt.plot(1e3 * epochs_eog.times, np.squeeze(data_eog).T) plt.xlabel('Times (ms)') plt.title('EOG') plt.ylabel('EOG') ax = plt.subplot(2,3,5) plot_evoked_topomap(eog_evoked, times=0, average=0.05, ch_type='mag',colorbar=False, size=plSize, res=pltRes, axes=ax) ax = plt.subplot(2,3,6) plot_evoked_topomap(eog_evoked, times=0, average=0.05, ch_type='grad',colorbar=False, size=plSize, res=pltRes, show=False, axes=ax) plt.tight_layout() ecg_eogAvg.savefig(saveRoot + name +'_ecg_eog_Avg.pdf',format = 'pdf') plt.close('all') ## restore sensor space data icaList = ica.apply(raw) return(icaList, ica)
def 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 run_evoked(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} if config.eeg: ch_types = ['meg', 'eeg'] else: ch_types = ['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() # XXX I had to lower the threshold for ctps (default 0.25), otherwise it does not # find any components # check how this behaves on other data ecg_inds, scores = ica.find_bads_ecg(ecg_epochs, method='ctps', threshold=0.1) del ecg_epochs report_name = op.join( meg_subject_dir, '{0}_{1}_{2}-reject_ica.html'.format(subject, config.study_name, ch_type)) report = Report(report_name, verbose=False) # Plot r score report.add_figs_to_section(ica.plot_scores(scores, exclude=ecg_inds), captions=ch_type.upper() + ' - ECG - ' + 'R scores') # Plot source time course report.add_figs_to_section(ica.plot_sources(ecg_average, exclude=ecg_inds), 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), captions=ch_type.upper() + ' - ECG - ' + 'Corrections') else: print('no ECG channel!') # 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) del eog_epochs # Plot r score report.add_figs_to_section(ica.plot_scores(scores, exclude=eog_inds), captions=ch_type.upper() + ' - EOG - ' + 'R scores') # Plot source time course report.add_figs_to_section(ica.plot_sources(eog_average, exclude=eog_inds), captions=ch_type.upper() + ' - EOG - ' + 'Sources time course') # Plot source time course report.add_figs_to_section(ica.plot_overlay(eog_average, exclude=eog_inds), captions=ch_type.upper() + ' - EOG - ' + 'Corrections') report.save(report_name, overwrite=True, open_browser=False) else: print('no EOG channel!') ica_reject = (list(ecg_inds) + list(eog_inds) + list(config.rejcomps_man[subject][ch_type])) # now reject the components print('Rejecting from ' + ch_type + ': ' + str(ica_reject)) epochs = ica.apply(epochs, exclude=ica_reject) print('Saving epochs') epochs.save(fname_out) report.add_figs_to_section(ica.plot_overlay(raw.copy(), exclude=ica_reject), captions=ch_type.upper() + ' - ALL(epochs) - ' + 'Corrections') if config.plot: epochs.plot_image(combine='gfp', group_by='type', sigma=2., cmap="YlGnBu_r")