Beispiel #1
0
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
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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,
Beispiel #6
0
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)
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
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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]
Beispiel #13
0
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)