def compute_peaks_from_mne(a, sfreq=1000, ch_types=['mag']): # find peaks in array (not corrected) using mne. See martinos.org/mne/stable/generated/mne.create_info.html for variables raw = mne.io.RawArray([a], mne.create_info(ch_names=['raz'], sfreq=sfreq, ch_types=ch_types)) ecg_events, name_c, _ = mne_prep.find_ecg_events(raw) peak_starts = ecg_events[:, 0] return peak_starts
def get_ics_cardiac(meg_raw, ica, flow=10, fhigh=20, tmin=-0.3, tmax=0.3, name_ecg='ECG 001', use_CTPS=True, proj=False, score_func='pearsonr', thresh=0.3): ''' Identify components with cardiac artefacts ''' from mne.preprocessing import find_ecg_events event_id_ecg = 999 if name_ecg in meg_raw.ch_names: # get and filter ICA signals ica_raw = ica.get_sources(meg_raw) ica_raw.filter(l_freq=flow, h_freq=fhigh, n_jobs=2, method='fft') # get R-peak indices in ECG signal idx_R_peak, _, _ = find_ecg_events(meg_raw, ch_name=name_ecg, event_id=event_id_ecg, l_freq=flow, h_freq=fhigh, verbose=False) # ----------------------------------- # default method: CTPS # else: correlation # ----------------------------------- if use_CTPS: # create epochs picks = np.arange(ica.n_components_) ica_epochs = mne.Epochs(ica_raw, events=idx_R_peak, event_id=event_id_ecg, tmin=tmin, tmax=tmax, baseline=None, proj=False, picks=picks, verbose=False) # compute CTPS _, pk, _ = ctps.ctps(ica_epochs.get_data()) pk_max = np.max(pk, axis=1) idx_ecg = np.where(pk_max >= thresh)[0] else: # use correlation idx_ecg = [meg_raw.ch_names.index(name_ecg)] ecg_filtered = mne.filter.band_pass_filter(meg_raw[idx_ecg, :][0], meg_raw.info['sfreq'], Fp1=flow, Fp2=fhigh) ecg_scores = ica.score_sources(meg_raw, target=ecg_filtered, score_func=score_func) idx_ecg = np.where(np.abs(ecg_scores) >= thresh)[0] else: print ">>>> NOTE: No ECG channel found!" idx_ecg = np.array([0]) return idx_ecg
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 plot_performance_artifact_rejection(meg_raw, ica, fnout_fig, meg_clean=None, show=False, proj=False, verbose=False, name_ecg='ECG 001', name_eog='EOG 002'): ''' Creates a performance image of the data before and after the cleaning process. ''' import matplotlib.pyplot as pl from mne.preprocessing import find_ecg_events, find_eog_events from jumeg import jumeg_math as jmath # name_ecg = 'ECG 001' # name_eog_hor = 'EOG 001' # name_eog_ver = 'EOG 002' event_id_ecg = 999 event_id_eog = 998 tmin_ecg = -0.4 tmax_ecg = 0.4 tmin_eog = -0.4 tmax_eog = 0.4 picks = mne.pick_types(meg_raw.info, meg=True, ref_meg=False, exclude='bads') # as we defined x% of the explained variance as noise (e.g. 5%) # we will remove this noise from the data if meg_clean: meg_clean_given = True else: meg_clean_given = False meg_clean = ica.apply(meg_raw.copy(), exclude=ica.exclude, n_pca_components=ica.n_components_) # plotting parameter props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) # check if ECG and EOG was recorded in addition # to the MEG data ch_names = meg_raw.info['ch_names'] # ECG if name_ecg in ch_names: nstart = 0 nrange = 1 else: nstart = 1 nrange = 1 # EOG if name_eog in ch_names: nrange = 2 y_figsize = 6 * nrange perf_art_rej = np.zeros(2) # ToDo: How can we avoid popping up the window if show=False ? pl.ioff() pl.figure('performance image', figsize=(12, y_figsize)) pl.clf() # ECG, EOG: loop over all artifact events for i in range(nstart, nrange): # get event indices if i == 0: baseline = (None, None) event_id = event_id_ecg idx_event, _, _ = find_ecg_events(meg_raw, event_id, ch_name=name_ecg, verbose=verbose) idx_ref_chan = meg_raw.ch_names.index(name_ecg) tmin = tmin_ecg tmax = tmax_ecg pl1 = nrange * 100 + 21 pl2 = nrange * 100 + 22 text1 = "CA: original data" text2 = "CA: cleaned data" elif i == 1: baseline = (None, None) event_id = event_id_eog idx_event = find_eog_events(meg_raw, event_id, ch_name=name_eog, verbose=verbose) idx_ref_chan = meg_raw.ch_names.index(name_eog) tmin = tmin_eog tmax = tmax_eog pl1 = nrange * 100 + 21 + (nrange - nstart - 1) * 2 pl2 = nrange * 100 + 22 + (nrange - nstart - 1) * 2 text1 = "OA: original data" text2 = "OA: cleaned data" # average the signals raw_epochs = mne.Epochs(meg_raw, idx_event, event_id, tmin, tmax, picks=picks, baseline=baseline, proj=proj, verbose=verbose) cleaned_epochs = mne.Epochs(meg_clean, idx_event, event_id, tmin, tmax, picks=picks, baseline=baseline, proj=proj, verbose=verbose) ref_epochs = mne.Epochs(meg_raw, idx_event, event_id, tmin, tmax, picks=[idx_ref_chan], baseline=baseline, proj=proj, verbose=verbose) raw_epochs_avg = raw_epochs.average() cleaned_epochs_avg = cleaned_epochs.average() ref_epochs_avg = np.average(ref_epochs.get_data(), axis=0).flatten() * -1.0 times = raw_epochs_avg.times * 1e3 if np.max(raw_epochs_avg.data) < 1: factor = 1e15 else: factor = 1 ymin = np.min(raw_epochs_avg.data) * factor ymax = np.max(raw_epochs_avg.data) * factor # plotting data before cleaning pl.subplot(pl1) pl.plot(times, raw_epochs_avg.data.T * factor, 'k') pl.title(text1) # plotting reference signal pl.plot(times, jmath.rescale(ref_epochs_avg, ymin, ymax), 'r') pl.xlim(times[0], times[len(times) - 1]) pl.ylim(1.1 * ymin, 1.1 * ymax) # print some info textstr1 = 'num_events=%d\nEpochs: tmin, tmax = %0.1f, %0.1f' \ % (len(idx_event), tmin, tmax) pl.text(times[10], 1.09 * ymax, textstr1, fontsize=10, verticalalignment='top', bbox=props) # plotting data after cleaning pl.subplot(pl2) pl.plot(times, cleaned_epochs_avg.data.T * factor, 'k') pl.title(text2) # plotting reference signal again pl.plot(times, jmath.rescale(ref_epochs_avg, ymin, ymax), 'r') pl.xlim(times[0], times[len(times) - 1]) pl.ylim(1.1 * ymin, 1.1 * ymax) # print some info perf_art_rej[i] = calc_performance(raw_epochs_avg, cleaned_epochs_avg) # ToDo: would be nice to add info about ica.excluded if meg_clean_given: textstr1 = 'Performance: %d\nFrequency Correlation: %d'\ % (perf_art_rej[i], calc_frequency_correlation(raw_epochs_avg, cleaned_epochs_avg)) else: textstr1 = 'Performance: %d\nFrequency Correlation: %d\n# ICs: %d\nExplained Var.: %d'\ % (perf_art_rej[i], calc_frequency_correlation(raw_epochs_avg, cleaned_epochs_avg), ica.n_components_, ica.n_components * 100) pl.text(times[10], 1.09 * ymax, textstr1, fontsize=10, verticalalignment='top', bbox=props) if show: pl.show() # save image pl.savefig(fnout_fig + '.png', format='png') pl.close('performance image') pl.ion() return perf_art_rej
plt.show() ############################################################################### # Validation: check ECG components extracted # Export ICA as Raw object for subsequent processing steps in ICA space. ica_raw = ica.sources_as_raw(raw, start=100., stop=160., picks=None) from mne.preprocessing import find_ecg_events # find ECG events event_id = 999 events, _, _ = find_ecg_events(raw, ch_name='MEG 1531', event_id=event_id, l_freq=8, h_freq=16) # pick components, create epochs and evoked in ICA space ica_picks = np.arange(ica.n_components_) ica_raw.info['bads'] = [] # selected components are exported as bad channels # create epochs around ECG events ecg_epochs = mne.Epochs(ica_raw, events=events, event_id=event_id, tmin=-0.5, tmax=0.5, baseline=None,
def do_preprocessing_combined(p, subjects, run_indices): """Do preprocessing on all raw files together. Calculates projection vectors to use to clean data. Parameters ---------- p : instance of Parameters Analysis parameters. subjects : list of str Subject names to analyze (e.g., ['Eric_SoP_001', ...]). run_indices : array-like | None Run indices to include. """ drop_logs = list() for si, subj in enumerate(subjects): proj_nums = _proj_nums(p, subj) ecg_channel = _handle_dict(p.ecg_channel, subj) flat = _handle_dict(p.flat, subj) if p.disp_files: print(' Preprocessing subject %g/%g (%s).' % (si + 1, len(subjects), subj)) pca_dir = _get_pca_dir(p, subj) bad_file = get_bad_fname(p, subj, check_exists=False) # Create SSP projection vectors after marking bad channels raw_names = get_raw_fnames(p, subj, 'sss', False, False, run_indices[si]) empty_names = get_raw_fnames(p, subj, 'sss', 'only') for r in raw_names + empty_names: if not op.isfile(r): raise NameError('File not found (' + r + ')') fir_kwargs, old_kwargs = _get_fir_kwargs(p.fir_design) if isinstance(p.auto_bad, float): print(' Creating post SSS bad channel file:\n' ' %s' % bad_file) # do autobad raw = _raw_LRFCP(raw_names, p.proj_sfreq, None, None, p.n_jobs_fir, p.n_jobs_resample, list(), None, p.disp_files, method='fir', filter_length=p.filter_length, apply_proj=False, force_bads=False, l_trans=p.hp_trans, h_trans=p.lp_trans, phase=p.phase, fir_window=p.fir_window, pick=True, skip_by_annotation='edge', **fir_kwargs) events = fixed_len_events(p, raw) rtmin = p.reject_tmin \ if p.reject_tmin is not None else p.tmin rtmax = p.reject_tmax \ if p.reject_tmax is not None else p.tmax # do not mark eog channels bad meg, eeg = 'meg' in raw, 'eeg' in raw picks = pick_types(raw.info, meg=meg, eeg=eeg, eog=False, exclude=[]) assert p.auto_bad_flat is None or isinstance(p.auto_bad_flat, dict) assert p.auto_bad_reject is None or \ isinstance(p.auto_bad_reject, dict) or \ p.auto_bad_reject == 'auto' if p.auto_bad_reject == 'auto': print(' Auto bad channel selection active. ' 'Will try using Autoreject module to ' 'compute rejection criterion.') try: from autoreject import get_rejection_threshold except ImportError: raise ImportError(' Autoreject module not installed.\n' ' Noisy channel detection parameter ' ' not defined. To use autobad ' ' channel selection either define ' ' rejection criteria or install ' ' Autoreject module.\n') print(' Computing thresholds.\n', end='') temp_epochs = Epochs(raw, events, event_id=None, tmin=rtmin, tmax=rtmax, baseline=_get_baseline(p), proj=True, reject=None, flat=None, preload=True, decim=1) kwargs = dict() if 'verbose' in get_args(get_rejection_threshold): kwargs['verbose'] = False reject = get_rejection_threshold(temp_epochs, **kwargs) reject = {kk: vv for kk, vv in reject.items()} elif p.auto_bad_reject is None and p.auto_bad_flat is None: raise RuntimeError('Auto bad channel detection active. Noisy ' 'and flat channel detection ' 'parameters not defined. ' 'At least one criterion must be defined.') else: reject = p.auto_bad_reject if 'eog' in reject.keys(): reject.pop('eog', None) epochs = Epochs(raw, events, None, tmin=rtmin, tmax=rtmax, baseline=_get_baseline(p), picks=picks, reject=reject, flat=p.auto_bad_flat, proj=True, preload=True, decim=1, reject_tmin=rtmin, reject_tmax=rtmax) # channel scores from drop log drops = Counter([ch for d in epochs.drop_log for ch in d]) # get rid of non-channel reasons in drop log scores = { kk: vv for kk, vv in drops.items() if kk in epochs.ch_names } ch_names = np.array(list(scores.keys())) # channel scores expressed as percentile and rank ordered counts = (100 * np.array([scores[ch] for ch in ch_names], float) / len(epochs.drop_log)) order = np.argsort(counts)[::-1] # boolean array masking out channels with <= % epochs dropped mask = counts[order] > p.auto_bad badchs = ch_names[order[mask]] if len(badchs) > 0: # Make sure we didn't get too many bad MEG or EEG channels for m, e, thresh in zip( [True, False], [False, True], [p.auto_bad_meg_thresh, p.auto_bad_eeg_thresh]): picks = pick_types(epochs.info, meg=m, eeg=e, exclude=[]) if len(picks) > 0: ch_names = [epochs.ch_names[pp] for pp in picks] n_bad_type = sum(ch in ch_names for ch in badchs) if n_bad_type > thresh: stype = 'meg' if m else 'eeg' raise RuntimeError('Too many bad %s channels ' 'found: %s > %s' % (stype, n_bad_type, thresh)) print(' The following channels resulted in greater than ' '{:.0f}% trials dropped:\n'.format(p.auto_bad * 100)) print(badchs) with open(bad_file, 'w') as f: f.write('\n'.join(badchs)) if not op.isfile(bad_file): print(' Clearing bad channels (no file %s)' % op.sep.join(bad_file.split(op.sep)[-3:])) bad_file = None ecg_t_lims = _handle_dict(p.ecg_t_lims, subj) ecg_f_lims = p.ecg_f_lims ecg_eve = op.join(pca_dir, 'preproc_ecg-eve.fif') ecg_epo = op.join(pca_dir, 'preproc_ecg-epo.fif') ecg_proj = op.join(pca_dir, 'preproc_ecg-proj.fif') all_proj = op.join(pca_dir, 'preproc_all-proj.fif') get_projs_from = _handle_dict(p.get_projs_from, subj) if get_projs_from is None: get_projs_from = np.arange(len(raw_names)) pre_list = [ r for ri, r in enumerate(raw_names) if ri in get_projs_from ] projs = list() raw_orig = _raw_LRFCP(raw_names=pre_list, sfreq=p.proj_sfreq, l_freq=None, h_freq=None, n_jobs=p.n_jobs_fir, n_jobs_resample=p.n_jobs_resample, projs=projs, bad_file=bad_file, disp_files=p.disp_files, method='fir', filter_length=p.filter_length, force_bads=False, l_trans=p.hp_trans, h_trans=p.lp_trans, phase=p.phase, fir_window=p.fir_window, pick=True, skip_by_annotation='edge', **fir_kwargs) # Apply any user-supplied extra projectors if p.proj_extra is not None: if p.disp_files: print(' Adding extra projectors from "%s".' % p.proj_extra) projs.extend(read_proj(op.join(pca_dir, p.proj_extra))) proj_kwargs, p_sl = _get_proj_kwargs(p) # # Calculate and apply ERM projectors # if not p.cont_as_esss: if any(proj_nums[2]): assert proj_nums[2][2] == 0 # no EEG projectors for ERM if len(empty_names) == 0: raise RuntimeError('Cannot compute empty-room projectors ' 'from continuous raw data') if p.disp_files: print(' Computing continuous projectors using ERM.') # Use empty room(s), but processed the same way projs.extend(_compute_erm_proj(p, subj, projs, 'sss', bad_file)) else: cont_proj = op.join(pca_dir, 'preproc_cont-proj.fif') _safe_remove(cont_proj) # # Calculate and apply the ECG projectors # if any(proj_nums[0]): if p.disp_files: print(' Computing ECG projectors...', end='') raw = raw_orig.copy() raw.filter(ecg_f_lims[0], ecg_f_lims[1], n_jobs=p.n_jobs_fir, method='fir', filter_length=p.filter_length, l_trans_bandwidth=0.5, h_trans_bandwidth=0.5, phase='zero-double', fir_window='hann', skip_by_annotation='edge', **old_kwargs) raw.add_proj(projs) raw.apply_proj() find_kwargs = dict() if 'reject_by_annotation' in get_args(find_ecg_events): find_kwargs['reject_by_annotation'] = True elif len(raw.annotations) > 0: print(' WARNING: ECG event detection will not make use of ' 'annotations, please update MNE-Python') # We've already filtered the data channels above, but this # filters the ECG channel ecg_events = find_ecg_events(raw, 999, ecg_channel, 0., ecg_f_lims[0], ecg_f_lims[1], qrs_threshold='auto', return_ecg=False, **find_kwargs)[0] use_reject, use_flat = _restrict_reject_flat( _handle_dict(p.ssp_ecg_reject, subj), flat, raw) ecg_epochs = Epochs(raw, ecg_events, 999, ecg_t_lims[0], ecg_t_lims[1], baseline=None, reject=use_reject, flat=use_flat, preload=True) print(' obtained %d epochs from %d events.' % (len(ecg_epochs), len(ecg_events))) if len(ecg_epochs) >= 20: write_events(ecg_eve, ecg_epochs.events) ecg_epochs.save(ecg_epo, **_get_epo_kwargs()) desc_prefix = 'ECG-%s-%s' % tuple(ecg_t_lims) pr = compute_proj_wrap(ecg_epochs, p.proj_ave, n_grad=proj_nums[0][0], n_mag=proj_nums[0][1], n_eeg=proj_nums[0][2], desc_prefix=desc_prefix, **proj_kwargs) assert len(pr) == np.sum(proj_nums[0][::p_sl]) write_proj(ecg_proj, pr) projs.extend(pr) else: plot_drop_log(ecg_epochs.drop_log) raw.plot(events=ecg_epochs.events) raise RuntimeError('Only %d/%d good ECG epochs found' % (len(ecg_epochs), len(ecg_events))) del raw, ecg_epochs, ecg_events else: _safe_remove([ecg_proj, ecg_eve, ecg_epo]) # # Next calculate and apply the EOG projectors # for idx, kind in ((1, 'EOG'), (3, 'HEOG'), (4, 'VEOG')): _compute_add_eog(p, subj, raw_orig, projs, proj_nums[idx], kind, pca_dir, flat, proj_kwargs, old_kwargs, p_sl) del proj_nums # save the projectors write_proj(all_proj, projs) # # Look at raw_orig for trial DQs now, it will be quick # raw_orig.filter(p.hp_cut, p.lp_cut, n_jobs=p.n_jobs_fir, method='fir', filter_length=p.filter_length, l_trans_bandwidth=p.hp_trans, phase=p.phase, h_trans_bandwidth=p.lp_trans, fir_window=p.fir_window, skip_by_annotation='edge', **fir_kwargs) raw_orig.add_proj(projs) raw_orig.apply_proj() # now let's epoch with 1-sec windows to look for DQs events = fixed_len_events(p, raw_orig) reject = _handle_dict(p.reject, subj) use_reject, use_flat = _restrict_reject_flat(reject, flat, raw_orig) epochs = Epochs(raw_orig, events, None, p.tmin, p.tmax, preload=False, baseline=_get_baseline(p), reject=use_reject, flat=use_flat, proj=True) try: epochs.drop_bad() except AttributeError: # old way epochs.drop_bad_epochs() drop_logs.append(epochs.drop_log) del raw_orig del epochs if p.plot_drop_logs: for subj, drop_log in zip(subjects, drop_logs): plot_drop_log(drop_log, p.drop_thresh, subject=subj)
plt.xlim(100, 106) plt.show() ############################################################################### # Validation: check ECG components extracted # Export ICA as Raw object for subsequent processing steps in ICA space. ica_raw = ica.sources_as_raw(raw, start=100., stop=160., picks=None) from mne.preprocessing import find_ecg_events # find ECG events event_id = 999 events, _, _ = find_ecg_events(raw, ch_name='MEG 1531', event_id=event_id, l_freq=8, h_freq=16) # pick components, create epochs and evoked in ICA space ica_picks = np.arange(ica.n_components_) ica_raw.info['bads'] = [] # selected components are exported as bad channels # create epochs around ECG events ecg_epochs = mne.Epochs(ica_raw, events=events, event_id=event_id, tmin=-0.5, tmax=0.5, baseline=None, proj=False, picks=ica_picks) ica_ave = ecg_epochs.average(ica_picks) plt.figure() times = ica_ave.times * 1e3
def plot_performance_artifact_rejection(meg_raw, ica, fnout_fig, meg_clean=None, show=False, proj=False, verbose=False, name_ecg='ECG 001', name_eog='EOG 002'): ''' Creates a performance image of the data before and after the cleaning process. ''' from mne.preprocessing import find_ecg_events, find_eog_events from jumeg import jumeg_math as jmath # name_ecg = 'ECG 001' # name_eog_hor = 'EOG 001' # name_eog_ver = 'EOG 002' event_id_ecg = 999 event_id_eog = 998 tmin_ecg = -0.4 tmax_ecg = 0.4 tmin_eog = -0.4 tmax_eog = 0.4 picks = mne.pick_types(meg_raw.info, meg=True, ref_meg=False, exclude='bads') # as we defined x% of the explained variance as noise (e.g. 5%) # we will remove this noise from the data if meg_clean: meg_clean_given = True else: meg_clean_given = False meg_clean = ica.apply(meg_raw.copy(), exclude=ica.exclude, n_pca_components=ica.n_components_) # plotting parameter props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) # check if ECG and EOG was recorded in addition # to the MEG data ch_names = meg_raw.info['ch_names'] # ECG if name_ecg in ch_names: nstart = 0 nrange = 1 else: nstart = 1 nrange = 1 # EOG if name_eog in ch_names: nrange = 2 y_figsize = 6 * nrange perf_art_rej = np.zeros(2) # ToDo: How can we avoid popping up the window if show=False ? pl.ioff() pl.figure('performance image', figsize=(12, y_figsize)) pl.clf() # ECG, EOG: loop over all artifact events for i in range(nstart, nrange): # get event indices if i == 0: baseline = (None, None) event_id = event_id_ecg idx_event, _, _ = find_ecg_events(meg_raw, event_id, ch_name=name_ecg, verbose=verbose) idx_ref_chan = meg_raw.ch_names.index(name_ecg) tmin = tmin_ecg tmax = tmax_ecg pl1 = nrange * 100 + 21 pl2 = nrange * 100 + 22 text1 = "CA: original data" text2 = "CA: cleaned data" elif i == 1: baseline = (None, None) event_id = event_id_eog idx_event = find_eog_events(meg_raw, event_id, ch_name=name_eog, verbose=verbose) idx_ref_chan = meg_raw.ch_names.index(name_eog) tmin = tmin_eog tmax = tmax_eog pl1 = nrange * 100 + 21 + (nrange - nstart - 1) * 2 pl2 = nrange * 100 + 22 + (nrange - nstart - 1) * 2 text1 = "OA: original data" text2 = "OA: cleaned data" # average the signals raw_epochs = mne.Epochs(meg_raw, idx_event, event_id, tmin, tmax, picks=picks, baseline=baseline, proj=proj, verbose=verbose) cleaned_epochs = mne.Epochs(meg_clean, idx_event, event_id, tmin, tmax, picks=picks, baseline=baseline, proj=proj, verbose=verbose) ref_epochs = mne.Epochs(meg_raw, idx_event, event_id, tmin, tmax, picks=[idx_ref_chan], baseline=baseline, proj=proj, verbose=verbose) raw_epochs_avg = raw_epochs.average() cleaned_epochs_avg = cleaned_epochs.average() ref_epochs_avg = np.average(ref_epochs.get_data(), axis=0).flatten() * -1.0 times = raw_epochs_avg.times * 1e3 if np.max(raw_epochs_avg.data) < 1: factor = 1e15 else: factor = 1 ymin = np.min(raw_epochs_avg.data) * factor ymax = np.max(raw_epochs_avg.data) * factor # plotting data before cleaning pl.subplot(pl1) pl.plot(times, raw_epochs_avg.data.T * factor, 'k') pl.title(text1) # plotting reference signal pl.plot(times, jmath.rescale(ref_epochs_avg, ymin, ymax), 'r') pl.xlim(times[0], times[len(times) - 1]) pl.ylim(1.1 * ymin, 1.1 * ymax) # print some info textstr1 = 'num_events=%d\nEpochs: tmin, tmax = %0.1f, %0.1f' \ % (len(idx_event), tmin, tmax) pl.text(times[10], 1.09 * ymax, textstr1, fontsize=10, verticalalignment='top', bbox=props) # plotting data after cleaning pl.subplot(pl2) pl.plot(times, cleaned_epochs_avg.data.T * factor, 'k') pl.title(text2) # plotting reference signal again pl.plot(times, jmath.rescale(ref_epochs_avg, ymin, ymax), 'r') pl.xlim(times[0], times[len(times) - 1]) pl.ylim(1.1 * ymin, 1.1 * ymax) # print some info perf_art_rej[i] = calc_performance(raw_epochs_avg, cleaned_epochs_avg) # ToDo: would be nice to add info about ica.excluded if meg_clean_given: textstr1 = 'Performance: %d\nFrequency Correlation: %d'\ % (perf_art_rej[i], calc_frequency_correlation(raw_epochs_avg, cleaned_epochs_avg)) else: textstr1 = 'Performance: %d\nFrequency Correlation: %d\n# ICs: %d\nExplained Var.: %d'\ % (perf_art_rej[i], calc_frequency_correlation(raw_epochs_avg, cleaned_epochs_avg), ica.n_components_, ica.n_components * 100) pl.text(times[10], 1.09 * ymax, textstr1, fontsize=10, verticalalignment='top', bbox=props) if show: pl.show() # save image pl.savefig(fnout_fig + '.png', format='png') pl.close('performance image') pl.ion() return perf_art_rej
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
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 get_ics_cardiac(meg_raw, ica, flow=8, fhigh=25, tmin=-0.4, tmax=0.4, name_ecg='ECG 001', use_CTPS=True, event_id=999, score_func='pearsonr', thresh=0.25): ''' Identify components with cardiac artefacts ''' from mne.preprocessing import find_ecg_events idx_ecg = [] if name_ecg in meg_raw.ch_names: # get and filter ICA signals ica_raw = ica.get_sources(meg_raw) ica_raw.filter(l_freq=flow, h_freq=fhigh, n_jobs=2, method='fft') # get ECG events events_ecg, _, _ = find_ecg_events(meg_raw, ch_name=name_ecg, event_id=event_id, l_freq=flow, h_freq=fhigh, verbose=False) # CTPS if use_CTPS: # create epochs picks = np.arange(ica.n_components_) ica_epochs = mne.Epochs(ica_raw, events=events_ecg, event_id=event_id, tmin=tmin, tmax=tmax, baseline=None, proj=False, picks=picks, verbose=False) # compute CTPS _, pk, _ = ctps.ctps(ica_epochs.get_data()) pk_max = np.max(pk, axis=1) scores_ecg = pk_max ic_ecg = np.where(pk_max >= thresh)[0] else: # use correlation idx_ecg = [meg_raw.ch_names.index(name_ecg)] ecg_filtered = mne.filter.filter_data(meg_raw[idx_ecg, :][0], meg_raw.info['sfreq'], l_freq=flow, h_freq=fhigh) scores_ecg = ica.score_sources(meg_raw, target=ecg_filtered, score_func=score_func) ic_ecg = np.where(np.abs(scores_ecg) >= thresh)[0] else: logger.warning(">>>> Warning: Could not find ECG channel %s" % name_ecg) events_ecg = [] if len(ic_ecg) == 0: ic_ecg = np.array([-1]) scores_ecg = np.zeros( ica.n_components) #scores_ecg = np.array([-1]) ??? events_ecg = np.array([-1]) else: events_ecg[:, 0] -= meg_raw.first_samp # make sure event samples start from 0 return [ic_ecg, scores_ecg, events_ecg]
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
##################EOG 1st rejection#################################### eog_ch_idx = [raw.ch_names.index(eog_ch_name)] raw.filter(picks=eog_ch_idx, l_freq=1, h_freq=10) eog_scores = ica.find_sources_raw(raw, raw[eog_ch_idx][0]) eog_idx = np.where(np.abs(eog_scores) > 0.1)[0] ica.exclude += list(eog_idx) print '%s has been identified as eog component and excluded' %(eog_idx) #####################ECG Reject######################################### # Filter sources in the ecg range ica_ecg = ica add_ecg_from_raw = mne.fiff.pick_types(raw.info, meg=False, ecg=True, include=ecg_ch_name) sources_ecg = ica_ecg.sources_as_raw(raw, picks=add_ecg_from_raw) ecg_eve, _, _ = find_ecg_events(sources_ecg, 999, ch_name=ecg_ch_name) # drop non-data channels (ICA sources are type misc) picks = mne.fiff.pick_types(sources_ecg.info, meg=False, misc=True) sources_ecg.filter(l_freq=8, h_freq=16, method='iir', n_jobs=4) # Epochs at R peak onset, from ecg_eve. ica_epochs_ecg = mne.Epochs(sources_ecg, ecg_eve, event_id=999, tmin=-0.5, tmax=0.5, picks=picks, preload=True, proj=False) # Compute phase values and statistics (significance values pK) #phase_trial_ecg, pk_dyn_ecg, _ = compute_ctps(ica_epochs_ecg.get_data()) _ , pk_dyn_ecg, _ = compute_ctps(ica_epochs_ecg.get_data()) # Get kuiper maxima pk_max = pk_dyn_ecg.max(axis=1)