예제 #1
0
def compute_cov_from_empty_room(subject, session):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             check=False)

    raw_er_fname = bids_basename.copy().update(kind=config.get_kind(),
                                               task='noise',
                                               processing='filt',
                                               extension='.fif')
    cov_fname = bids_basename.copy().update(kind='cov', extension='.fif')

    extra_params = dict()
    if not config.use_maxwell_filter and config.allow_maxshield:
        extra_params['allow_maxshield'] = config.allow_maxshield

    msg = (f'Computing regularized covariance based on empty-room recording. '
           f'Input: {raw_er_fname}, Output: {cov_fname}')
    logger.info(
        gen_log_message(message=msg, step=11, subject=subject,
                        session=session))

    raw_er = mne.io.read_raw_fif(raw_er_fname, preload=True, **extra_params)
    cov = mne.compute_raw_covariance(raw_er, method='shrunk', rank='info')
    cov.save(cov_fname)
예제 #2
0
def plot_er_psd(subject, session):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             acquisition=config.acq,
                             run=None,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             kind=config.get_kind(),
                             task='noise',
                             processing='filt',
                             extension='.fif')

    extra_params = dict()
    if not config.use_maxwell_filter and config.allow_maxshield:
        extra_params['allow_maxshield'] = config.allow_maxshield

    raw_er_filtered = mne.io.read_raw_fif(bids_basename, preload=True,
                                          **extra_params)

    fmax = 1.5 * config.h_freq if config.h_freq is not None else np.inf
    fig = raw_er_filtered.plot_psd(fmax=fmax, show=False)
    return fig
예제 #3
0
def compute_cov_from_epochs(subject, session, tmin, tmax):
    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)

    if config.use_ica or config.use_ssp:
        extension = '_cleaned-epo'
    else:
        extension = '-epo'

    epo_fname = op.join(deriv_path, bids_basename + '%s.fif' % extension)
    cov_fname = op.join(deriv_path, bids_basename + '-cov.fif')

    msg = (f"Computing regularized covariance based on epochs' baseline "
           f"periods. Input: {epo_fname}, Output: {cov_fname}")
    logger.info(
        gen_log_message(message=msg, step=11, subject=subject,
                        session=session))

    epochs = mne.read_epochs(epo_fname, preload=True)
    cov = mne.compute_covariance(epochs,
                                 tmin=tmin,
                                 tmax=tmax,
                                 method='shrunk',
                                 rank='info')
    cov.save(cov_fname)
예제 #4
0
def plot_events(subject, session, deriv_path):
    raws_filt = []
    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             kind=config.get_kind(),
                             processing='filt',
                             extension='.fif')

    for run in config.get_runs():
        fname = bids_basename.copy().update(run=run)
        raw_filt = mne.io.read_raw_fif(fname)
        raws_filt.append(raw_filt)
        del fname

    # Concatenate the filtered raws and extract the events.
    raw_filt_concat = mne.concatenate_raws(raws_filt)
    events, event_id = mne.events_from_annotations(raw=raw_filt_concat)
    fig = mne.viz.plot_events(events=events, event_id=event_id,
                              first_samp=raw_filt_concat.first_samp,
                              sfreq=raw_filt_concat.info['sfreq'],
                              show=False)
    return fig
예제 #5
0
def load_data(bids_basename):
    # read_raw_bids automatically
    # - populates bad channels using the BIDS channels.tsv
    # - sets channels types according to BIDS channels.tsv `type` column
    # - sets raw.annotations using the BIDS events.tsv

    params = get_entities_from_fname(bids_basename)
    subject = params['subject']
    session = params['session']

    extra_params = dict()
    if config.allow_maxshield:
        extra_params['allow_maxshield'] = config.allow_maxshield

    raw = read_raw_bids(bids_basename=bids_basename,
                        bids_root=config.bids_root,
                        extra_params=extra_params,
                        kind=config.get_kind())

    if config.daysback is not None:
        raw.anonymize(daysback=config.daysback)

    if subject != 'emptyroom':
        # Crop the data.
        if config.crop is not None:
            raw.crop(*config.crop)

        # Rename events.
        if config.rename_events:
            rename_events(raw=raw, subject=subject, session=session)

    raw.load_data()
    if hasattr(raw, 'fix_mag_coil_types'):
        raw.fix_mag_coil_types()

    montage_name = config.eeg_template_montage
    if config.get_kind() == 'eeg' and montage_name:
        msg = (f'Setting EEG channel locatiions to template montage: '
               f'{montage_name}.')
        logger.info(gen_log_message(message=msg, step=1, subject=subject,
                                    session=session))
        montage = mne.channels.make_standard_montage(montage_name)
        raw.set_montage(montage, on_missing='warn')

    return raw
예제 #6
0
def run_ssp(subject, session=None):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    # compute SSP on first run of raw
    run = config.get_runs()[0]
    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=run,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path)

    # Prepare a name to save the data
    raw_fname_in = bids_basename.copy().update(processing='filt',
                                               kind=config.get_kind(),
                                               extension='.fif')

    # when saving proj, use run=None
    proj_fname_out = bids_basename.copy().update(run=None,
                                                 kind='proj',
                                                 extension='.fif',
                                                 check=False)

    msg = f'Input: {raw_fname_in}, Output: {proj_fname_out}'
    logger.info(
        gen_log_message(message=msg, step=4, subject=subject, session=session))

    raw = mne.io.read_raw_fif(raw_fname_in)
    # XXX : n_xxx should be options in config
    msg = 'Computing SSPs for ECG'
    logger.debug(
        gen_log_message(message=msg, step=4, subject=subject, session=session))
    ecg_projs, ecg_events = \
        compute_proj_ecg(raw, n_grad=1, n_mag=1, n_eeg=0, average=True)
    msg = 'Computing SSPs for EOG'
    logger.debug(
        gen_log_message(message=msg, step=4, subject=subject, session=session))
    eog_projs, eog_events = \
        compute_proj_eog(raw, n_grad=1, n_mag=1, n_eeg=1, average=True)

    mne.write_proj(proj_fname_out, eog_projs + ecg_projs)
예제 #7
0
def run_evoked(subject, session=None):
    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)

    if config.use_ica or config.use_ssp:
        extension = '_cleaned-epo'
    else:
        extension = '-epo'

    fname_in = op.join(deriv_path, bids_basename + '%s.fif' % extension)
    fname_out = op.join(deriv_path, bids_basename + '-ave.fif')

    msg = f'Input: {fname_in}, Output: {fname_out}'
    logger.info(
        gen_log_message(message=msg, step=6, subject=subject, session=session))

    epochs = mne.read_epochs(fname_in, preload=True)

    msg = 'Creating evoked data based on experimental conditions …'
    logger.info(
        gen_log_message(message=msg, step=6, subject=subject, session=session))
    evokeds = []
    for condition in config.conditions:
        evoked = epochs[condition].average()
        evokeds.append(evoked)

    if config.contrasts:
        msg = 'Contrasting evoked responses …'
        logger.info(
            gen_log_message(message=msg,
                            step=6,
                            subject=subject,
                            session=session))

        for contrast in config.contrasts:
            cond_1, cond_2 = contrast
            evoked_1 = epochs[cond_1].average()
            evoked_2 = epochs[cond_2].average()
            evoked_diff = mne.combine_evoked([evoked_1, evoked_2],
                                             weights=[1, -1])
            evokeds.append(evoked_diff)

    mne.evoked.write_evokeds(fname_out, evokeds)

    if config.interactive:
        for evoked in evokeds:
            evoked.plot()
예제 #8
0
def run_forward(subject, session=None):
    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_evoked = op.join(deriv_path, bids_basename + '-ave.fif')
    fname_trans = op.join(deriv_path, 'sub-{}'.format(subject) + '-trans.fif')
    fname_fwd = op.join(deriv_path, bids_basename + '-fwd.fif')

    msg = f'Input: {fname_evoked}, Output: {fname_fwd}'
    logger.info(gen_log_message(message=msg, step=10, subject=subject,
                                session=session))
    # Find the raw data file
    # XXX : maybe simplify
    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)

    trans = get_head_mri_trans(bids_basename=bids_basename,
                               bids_root=config.bids_root)

    mne.write_trans(fname_trans, trans)

    src = mne.setup_source_space(subject, spacing=config.spacing,
                                 subjects_dir=config.get_fs_subjects_dir(),
                                 add_dist=False)

    evoked = mne.read_evokeds(fname_evoked, condition=0)

    # Here we only use 3-layers BEM only if EEG is available.
    if 'eeg' in config.ch_types:
        model = mne.make_bem_model(subject, ico=4,
                                   conductivity=(0.3, 0.006, 0.3),
                                   subjects_dir=config.get_fs_subjects_dir())
    else:
        model = mne.make_bem_model(subject, ico=4, conductivity=(0.3,),
                                   subjects_dir=config.get_fs_subjects_dir())

    bem = mne.make_bem_solution(model)
    fwd = mne.make_forward_solution(evoked.info, trans, src, bem,
                                    mindist=config.mindist)
    mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
예제 #9
0
def run_forward(subject, session=None):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             check=False)

    fname_evoked = bids_basename.copy().update(kind='ave', extension='.fif')
    fname_trans = bids_basename.copy().update(kind='trans', extension='.fif')
    fname_fwd = bids_basename.copy().update(kind='fwd', extension='.fif')

    msg = f'Input: {fname_evoked}, Output: {fname_fwd}'
    logger.info(
        gen_log_message(message=msg, step=10, subject=subject,
                        session=session))
    # Find the raw data file
    trans = get_head_mri_trans(bids_basename=(bids_basename.copy().update(
        run=config.get_runs()[0], prefix=None)),
                               bids_root=config.bids_root)

    mne.write_trans(fname_trans, trans)

    src = mne.setup_source_space(subject,
                                 spacing=config.spacing,
                                 subjects_dir=config.get_fs_subjects_dir(),
                                 add_dist=False)

    evoked = mne.read_evokeds(fname_evoked, condition=0)

    # Here we only use 3-layers BEM only if EEG is available.
    if 'eeg' in config.ch_types:
        model = mne.make_bem_model(subject,
                                   ico=4,
                                   conductivity=(0.3, 0.006, 0.3),
                                   subjects_dir=config.get_fs_subjects_dir())
    else:
        model = mne.make_bem_model(subject,
                                   ico=4,
                                   conductivity=(0.3, ),
                                   subjects_dir=config.get_fs_subjects_dir())

    bem = mne.make_bem_solution(model)
    fwd = mne.make_forward_solution(evoked.info,
                                    trans,
                                    src,
                                    bem,
                                    mindist=config.mindist)
    mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
예제 #10
0
def main():
    """Run grp ave."""
    msg = 'Running Step 13: Grand-average source estimates'
    logger.info(gen_log_message(step=13, message=msg))

    mne.datasets.fetch_fsaverage(subjects_dir=config.get_fs_subjects_dir())

    parallel, run_func, _ = parallel_func(morph_stc, n_jobs=config.N_JOBS)
    all_morphed_stcs = parallel(run_func(subject, session)
                                for subject, session in
                                itertools.product(config.get_subjects(),
                                                  config.get_sessions()))
    all_morphed_stcs = [morphed_stcs for morphed_stcs, subject in
                        zip(all_morphed_stcs, config.get_subjects())]
    mean_morphed_stcs = map(sum, zip(*all_morphed_stcs))

    subject = 'average'
    # XXX to fix
    if config.get_sessions():
        session = config.get_sessions()[0]
    else:
        session = None

    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             processing=config.proc,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             check=False)

    for condition, this_stc in zip(config.conditions, mean_morphed_stcs):
        this_stc /= len(all_morphed_stcs)

        method = config.inverse_method
        cond_str = condition.replace(op.sep, '').replace('_', '')
        inverse_str = method
        hemi_str = 'hemi'  # MNE will auto-append '-lh' and '-rh'.
        morph_str = 'morph2fsaverage'

        fname_stc_avg = bids_basename.copy().update(
            kind=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}')
        this_stc.save(fname_stc_avg)

    msg = 'Completed Step 13: Grand-average source estimates'
    logger.info(gen_log_message(step=13, message=msg))
예제 #11
0
def run_inverse(subject, session=None):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             extension='.fif',
                             check=False)

    fname_ave = bids_basename.copy().update(kind='ave')
    fname_fwd = bids_basename.copy().update(kind='fwd')
    fname_cov = bids_basename.copy().update(kind='cov')
    fname_inv = bids_basename.copy().update(kind='inv')

    evokeds = mne.read_evokeds(fname_ave)
    cov = mne.read_cov(fname_cov)
    forward = mne.read_forward_solution(fname_fwd)
    info = evokeds[0].info
    inverse_operator = make_inverse_operator(info,
                                             forward,
                                             cov,
                                             loose=0.2,
                                             depth=0.8,
                                             rank='info')
    write_inverse_operator(fname_inv, inverse_operator)

    # Apply inverse
    snr = 3.0
    lambda2 = 1.0 / snr**2

    for condition, evoked in zip(config.conditions, evokeds):
        method = config.inverse_method
        pick_ori = None

        cond_str = condition.replace(op.sep, '').replace('_', '')
        inverse_str = method
        hemi_str = 'hemi'  # MNE will auto-append '-lh' and '-rh'.
        fname_stc = bids_basename.copy().update(
            kind=f'{cond_str}+{inverse_str}+{hemi_str}', extension=None)

        stc = apply_inverse(evoked=evoked,
                            inverse_operator=inverse_operator,
                            lambda2=lambda2,
                            method=method,
                            pick_ori=pick_ori)
        stc.save(fname_stc)
예제 #12
0
def run_inverse(subject, session=None):
    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_ave = op.join(deriv_path, bids_basename + '-ave.fif')
    fname_fwd = op.join(deriv_path, bids_basename + '-fwd.fif')
    fname_cov = op.join(deriv_path, bids_basename + '-cov.fif')
    fname_inv = op.join(deriv_path, bids_basename + '-inv.fif')

    evokeds = mne.read_evokeds(fname_ave)
    cov = mne.read_cov(fname_cov)
    forward = mne.read_forward_solution(fname_fwd)
    info = evokeds[0].info
    inverse_operator = make_inverse_operator(info,
                                             forward,
                                             cov,
                                             loose=0.2,
                                             depth=0.8,
                                             rank='info')
    write_inverse_operator(fname_inv, inverse_operator)

    # Apply inverse
    snr = 3.0
    lambda2 = 1.0 / snr**2

    for condition, evoked in zip(config.conditions, evokeds):
        method = config.inverse_method
        pick_ori = None

        cond_str = 'cond-%s' % condition.replace(op.sep, '')
        inverse_str = 'inverse-%s' % method
        hemi_str = 'hemi'  # MNE will auto-append '-lh' and '-rh'.
        fname_stc = op.join(
            deriv_path,
            '_'.join([bids_basename, cond_str, inverse_str, hemi_str]))

        stc = apply_inverse(evoked=evoked,
                            inverse_operator=inverse_operator,
                            lambda2=lambda2,
                            method=method,
                            pick_ori=pick_ori)
        stc.save(fname_stc)
예제 #13
0
def run_ssp(subject, session=None):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    # compute SSP on first run of raw
    run = config.get_runs()[0]

    bids_basename = make_bids_basename(subject=subject,
                                       session=session,
                                       task=config.get_task(),
                                       acquisition=config.acq,
                                       run=run,
                                       processing=config.proc,
                                       recording=config.rec,
                                       space=config.space)

    # Prepare a name to save the data
    raw_fname_in = op.join(deriv_path, bids_basename + '_filt_raw.fif')

    # when saving proj, use bids_basename=None
    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)

    proj_fname_out = op.join(deriv_path, bids_basename + '_ssp-proj.fif')

    msg = f'Input: {raw_fname_in}, Output: {proj_fname_out}'
    logger.info(
        gen_log_message(message=msg, step=4, subject=subject, session=session))

    raw = mne.io.read_raw_fif(raw_fname_in)
    # XXX : n_xxx should be options in config
    msg = 'Computing SSPs for ECG'
    logger.debug(
        gen_log_message(message=msg, step=4, subject=subject, session=session))
    ecg_projs, ecg_events = \
        compute_proj_ecg(raw, n_grad=1, n_mag=1, n_eeg=0, average=True)
    msg = 'Computing SSPs for EOG'
    logger.debug(
        gen_log_message(message=msg, step=4, subject=subject, session=session))
    eog_projs, eog_events = \
        compute_proj_eog(raw, n_grad=1, n_mag=1, n_eeg=1, average=True)

    mne.write_proj(proj_fname_out, eog_projs + ecg_projs)
def run_time_decoding(subject, condition1, condition2, session=None):
    msg = f'Contrasting conditions: {condition1} – {condition2}'
    logger.info(
        gen_log_message(message=msg, step=8, subject=subject, session=session))

    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    fname_in = BIDSPath(subject=subject,
                        session=session,
                        task=config.get_task(),
                        acquisition=config.acq,
                        run=None,
                        recording=config.rec,
                        space=config.space,
                        prefix=deriv_path,
                        kind='epo',
                        extension='.fif',
                        check=False)

    epochs = mne.read_epochs(fname_in)

    # We define the epochs and the labels
    epochs = mne.concatenate_epochs([epochs[condition1], epochs[condition2]])
    epochs.apply_baseline()

    # Get the data and labels
    X = epochs.get_data()
    n_cond1 = len(epochs[condition1])
    n_cond2 = len(epochs[condition2])
    y = np.r_[np.ones(n_cond1), np.zeros(n_cond2)]

    se = SlidingEstimator(make_pipeline(
        StandardScaler(),
        LogisticRegression(solver='liblinear',
                           random_state=config.random_state)),
                          scoring=config.decoding_metric,
                          n_jobs=config.N_JOBS)
    scores = cross_val_multiscore(se, X=X, y=y, cv=config.decoding_n_splits)

    # let's save the scores now
    a_vs_b = f'{condition1}-{condition2}'.replace(op.sep, '')
    processing = f'{a_vs_b}+{config.decoding_metric}'
    processing = processing.replace('_', '-').replace('-', '')
    fname_td = fname_in.copy().update(kind='decoding',
                                      processing=processing,
                                      extension='.mat')
    savemat(fname_td, {'scores': scores, 'times': epochs.times})
예제 #15
0
def run_time_decoding(subject, condition1, condition2, session=None):
    msg = f'Contrasting conditions: {condition1} – {condition2}'
    logger.info(
        gen_log_message(message=msg, step=8, subject=subject, session=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')
    epochs = mne.read_epochs(fname_in)

    # We define the epochs and the labels
    epochs = mne.concatenate_epochs([epochs[condition1], epochs[condition2]])
    epochs.apply_baseline()

    # Get the data and labels
    X = epochs.get_data()
    n_cond1 = len(epochs[condition1])
    n_cond2 = len(epochs[condition2])
    y = np.r_[np.ones(n_cond1), np.zeros(n_cond2)]

    # Use AUC because chance level is same regardless of the class balance
    se = SlidingEstimator(make_pipeline(
        StandardScaler(),
        LogisticRegression(solver='liblinear',
                           random_state=config.random_state)),
                          scoring=config.decoding_metric,
                          n_jobs=config.N_JOBS)
    scores = cross_val_multiscore(se, X=X, y=y, cv=config.decoding_n_splits)

    # let's save the scores now
    a_vs_b = '%s_vs_%s' % (condition1, condition2)
    a_vs_b = a_vs_b.replace(op.sep, '')
    fname_td = op.join(
        config.bids_root, 'derivatives', config.PIPELINE_NAME,
        '%s_%s_%s_%s.mat' %
        (subject, config.study_name, a_vs_b, config.decoding_metric))
    savemat(fname_td, {'scores': scores, 'times': epochs.times})
예제 #16
0
def apply_ssp(subject, session=None):
    # load epochs to reject ICA components
    # compute SSP on first run of raw

    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path)

    fname_in = bids_basename.copy().update(kind='epo',
                                           extension='.fif',
                                           check=False)
    fname_out = bids_basename.copy().update(kind='epo',
                                            processing='clean',
                                            extension='.fif',
                                            check=False)

    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))

    proj_fname_in = bids_basename.copy().update(kind='proj',
                                                extension='.fif',
                                                check=False)

    msg = f'Reading SSP projections from : {proj_fname_in}'
    logger.info(
        gen_log_message(message=msg, step=5, subject=subject, session=session))

    projs = mne.read_proj(proj_fname_in)
    epochs.add_proj(projs).apply_proj()

    msg = 'Saving epochs'
    logger.info(
        gen_log_message(message=msg, step=5, subject=subject, session=session))
    epochs.save(fname_out, overwrite=True)
예제 #17
0
def run_time_frequency(subject, session=None):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())
    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             check=False)

    processing = None
    if config.use_ica or config.use_ssp:
        processing = 'clean'

    fname_in = bids_basename.copy().update(kind='epo',
                                           processing=processing,
                                           extension='.fif')

    msg = f'Input: {fname_in}'
    logger.info(
        gen_log_message(message=msg, step=9, subject=subject, session=session))

    epochs = mne.read_epochs(fname_in)

    for condition in config.time_frequency_conditions:
        this_epochs = epochs[condition]
        power, itc = mne.time_frequency.tfr_morlet(this_epochs,
                                                   freqs=freqs,
                                                   return_itc=True,
                                                   n_cycles=n_cycles)

        condition_str = condition.replace(op.sep, '').replace('_', '')
        power_fname_out = bids_basename.copy().update(
            kind=f'power+{condition_str}+tfr', extension='.h5')
        itc_fname_out = bids_basename.copy().update(
            kind=f'itc+{condition_str}+tfr', extension='.h5')

        power.save(power_fname_out, overwrite=True)
        itc.save(itc_fname_out, overwrite=True)
예제 #18
0
def run_time_frequency(subject, session=None):
    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)

    if config.use_ica or config.use_ssp:
        extension = '_cleaned-epo'
    else:
        extension = '-epo'

    fname_in = op.join(deriv_path, bids_basename + '%s.fif' % extension)

    msg = f'Input: {fname_in}'
    logger.info(
        gen_log_message(message=msg, step=9, subject=subject, session=session))

    epochs = mne.read_epochs(fname_in)

    for condition in config.time_frequency_conditions:
        this_epochs = epochs[condition]
        power, itc = mne.time_frequency.tfr_morlet(this_epochs,
                                                   freqs=freqs,
                                                   return_itc=True,
                                                   n_cycles=n_cycles)

        power_fname_out = \
            op.join(deriv_path, bids_basename + '_power_%s-tfr.h5'
                    % (condition.replace(op.sep, '')))

        itc_fname_out = \
            op.join(deriv_path, bids_basename + '_itc_%s-tfr.h5'
                    % (condition.replace(op.sep, '')))

        power.save(power_fname_out, overwrite=True)
        itc.save(itc_fname_out, overwrite=True)
예제 #19
0
def morph_stc(subject, session=None):
    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)

    morphed_stcs = []
    for condition in config.conditions:
        method = config.inverse_method
        cond_str = 'cond-%s' % condition.replace(op.sep, '')
        inverse_str = 'inverse-%s' % method
        hemi_str = 'hemi'  # MNE will auto-append '-lh' and '-rh'.
        morph_str = 'morph-fsaverage'
        fname_stc = op.join(
            deriv_path,
            '_'.join([bids_basename, cond_str, inverse_str, hemi_str]))
        fname_stc_fsaverage = op.join(
            deriv_path, '_'.join(
                [bids_basename, cond_str, inverse_str, morph_str, hemi_str]))

        stc = mne.read_source_estimate(fname_stc)
        morph = mne.compute_source_morph(
            stc,
            subject_from=subject,
            subject_to='fsaverage',
            subjects_dir=config.get_fs_subjects_dir())
        stc_fsaverage = morph.apply(stc)
        stc_fsaverage.save(fname_stc_fsaverage)
        morphed_stcs.append(stc_fsaverage)

        del fname_stc, fname_stc_fsaverage

    return morphed_stcs
예제 #20
0
def apply_ssp(subject, session=None):
    # load epochs to reject ICA components
    # compute SSP on first run of raw

    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')

    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))

    proj_fname_in = op.join(deriv_path, bids_basename + '_ssp-proj.fif')

    msg = f'Reading SSP projections from : {proj_fname_in}'
    logger.info(
        gen_log_message(message=msg, step=5, subject=subject, session=session))

    projs = mne.read_proj(proj_fname_in)
    epochs.add_proj(projs).apply_proj()

    msg = 'Saving epochs'
    logger.info(
        gen_log_message(message=msg, step=5, subject=subject, session=session))
    epochs.save(fname_out, overwrite=True)
예제 #21
0
def morph_stc(subject, session=None):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             check=False)

    morphed_stcs = []
    for condition in config.conditions:
        method = config.inverse_method
        cond_str = condition.replace(op.sep, '').replace('_', '')
        inverse_str = method
        hemi_str = 'hemi'  # MNE will auto-append '-lh' and '-rh'.
        morph_str = 'morph2fsaverage'

        fname_stc = bids_basename.copy().update(
            kind=f'{cond_str}+{inverse_str}+{hemi_str}')
        fname_stc_fsaverage = bids_basename.copy().update(
            kind=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}')

        stc = mne.read_source_estimate(fname_stc)
        morph = mne.compute_source_morph(
            stc, subject_from=subject, subject_to='fsaverage',
            subjects_dir=config.get_fs_subjects_dir())
        stc_fsaverage = morph.apply(stc)
        stc_fsaverage.save(fname_stc_fsaverage)
        morphed_stcs.append(stc_fsaverage)

        del fname_stc, fname_stc_fsaverage

    return morphed_stcs
예제 #22
0
def compute_cov_from_epochs(subject, session, tmin, tmax):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             run=None,
                             processing=config.proc,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             check=False)

    processing = None
    if config.use_ica or config.use_ssp:
        processing = 'clean'

    epo_fname = bids_basename.copy().update(kind='epo',
                                            processing=processing,
                                            extension='.fif')
    cov_fname = bids_basename.copy().update(kind='cov', extension='.fif')

    msg = (f"Computing regularized covariance based on epochs' baseline "
           f"periods. Input: {epo_fname}, Output: {cov_fname}")
    logger.info(
        gen_log_message(message=msg, step=11, subject=subject,
                        session=session))

    epochs = mne.read_epochs(epo_fname, preload=True)
    cov = mne.compute_covariance(epochs,
                                 tmin=tmin,
                                 tmax=tmax,
                                 method='shrunk',
                                 rank='info')
    cov.save(cov_fname)
def load_data(bids_basename):
    # read_raw_bids automatically
    # - populates bad channels using the BIDS channels.tsv
    # - sets channels types according to BIDS channels.tsv `type` column
    # - sets raw.annotations using the BIDS events.tsv

    params = _parse_bids_filename(bids_basename, verbose=False)
    subject = params['sub']
    session = params['ses']

    extra_params = dict()
    if config.allow_maxshield:
        extra_params['allow_maxshield'] = config.allow_maxshield

    raw = read_raw_bids(bids_basename=bids_basename,
                        bids_root=config.bids_root,
                        extra_params=extra_params,
                        kind=config.get_kind())

    # XXX hack to deal with dates that fif files cannot handle
    if config.daysback is not None:
        raw.anonymize(daysback=config.daysback)

    if subject != 'emptyroom':
        # Crop the data.
        if config.crop is not None:
            raw.crop(*config.crop)

        # Rename events.
        if config.rename_events:
            rename_events(raw=raw, subject=subject, session=session)

    raw.load_data()

    if hasattr(raw, 'fix_mag_coil_types'):
        raw.fix_mag_coil_types()

    return raw
예제 #24
0
def plot_auto_scores(subject, session):
    """Plot automated bad channel detection scores.
    """
    import json_tricks

    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    fname_scores = BIDSPath(subject=subject,
                            session=session,
                            task=config.get_task(),
                            acquisition=config.acq,
                            run=None,
                            processing=config.proc,
                            recording=config.rec,
                            space=config.space,
                            kind='scores',
                            extension='.json',
                            prefix=deriv_path,
                            check=False)

    all_figs = []
    all_captions = []
    for run in config.get_runs():
        with open(fname_scores.update(run=run), 'r') as f:
            auto_scores = json_tricks.load(f)

        figs = config.plot_auto_scores(auto_scores)
        all_figs.extend(figs)

        # Could be more than 1 fig, e.g. "grad" and "mag"
        captions = [f'Run {run}'] * len(figs)
        all_captions.extend(captions)

    return all_figs, all_captions
예제 #25
0
def run_ica(subject, session=None):
    """Run ICA."""

    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())
    bids_basename = BIDSPath(subject=subject,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path)

    raw_list = list()
    msg = 'Loading filtered raw data'
    logger.info(
        gen_log_message(message=msg, step=4, subject=subject, session=session))

    for run in config.get_runs():
        raw_fname_in = bids_basename.copy().update(run=run,
                                                   processing='filt',
                                                   kind=config.get_kind(),
                                                   extension='.fif')
        raw = mne.io.read_raw_fif(raw_fname_in, preload=True)
        raw_list.append(raw)

    msg = 'Concatenating runs'
    logger.info(
        gen_log_message(message=msg, step=4, subject=subject, session=session))
    raw = mne.concatenate_raws(raw_list)

    events, event_id = mne.events_from_annotations(raw)

    if config.get_kind() == 'eeg':
        raw.set_eeg_reference(projection=True)
    del raw_list

    # don't reject based on EOG to keep blink artifacts
    # in the ICA computation.
    reject_ica = config.get_reject()
    if reject_ica and 'eog' in reject_ica:
        reject_ica = dict(reject_ica)
        del reject_ica['eog']

    # produce high-pass filtered version of the data for ICA
    raw_ica = raw.copy().filter(l_freq=1., h_freq=None)
    epochs_for_ica = mne.Epochs(raw_ica,
                                events,
                                event_id,
                                config.tmin,
                                config.tmax,
                                proj=True,
                                baseline=config.baseline,
                                preload=True,
                                decim=config.decim,
                                reject=reject_ica)

    # get number of components for ICA
    # compute_rank requires 0.18
    # n_components_meg = (mne.compute_rank(epochs_for_ica.copy()
    #                        .pick_types(meg=True)))['meg']

    n_components_meg = 0.999

    n_components = {'meg': n_components_meg, 'eeg': 0.999}

    kind = config.get_kind()
    msg = f'Running ICA for {kind}'
    logger.info(
        gen_log_message(message=msg, step=4, subject=subject, session=session))

    if config.ica_algorithm == 'picard':
        fit_params = dict(fastica_it=5)
    elif config.ica_algorithm == 'extended_infomax':
        fit_params = dict(extended=True)
    elif config.ica_algorithm == 'fastica':
        fit_params = None

    ica = ICA(method=config.ica_algorithm,
              random_state=config.random_state,
              n_components=n_components[kind],
              fit_params=fit_params,
              max_iter=config.ica_max_iterations)

    ica.fit(epochs_for_ica, decim=config.ica_decim)

    msg = (f'Fit {ica.n_components_} components (explaining at least '
           f'{100*n_components[kind]:.1f}% of the variance)')
    logger.info(
        gen_log_message(message=msg, step=4, subject=subject, session=session))

    # Save ICA
    ica_fname = bids_basename.copy().update(run=None,
                                            kind=f'{kind}-ica',
                                            extension='.fif')
    ica.save(ica_fname)

    if config.interactive:
        # plot ICA components to html report
        report_fname = bids_basename.copy().update(run=None,
                                                   kind=f'{kind}-ica',
                                                   extension='.html')
        report = Report(report_fname, verbose=False)

        for idx in range(0, ica.n_components_):
            figure = ica.plot_properties(epochs_for_ica,
                                         picks=idx,
                                         psd_args={'fmax': 60},
                                         show=False)

            report.add_figs_to_section(figure,
                                       section=subject,
                                       captions=(kind.upper() +
                                                 ' - ICA Components'))

        report.save(report_fname, overwrite=True, open_browser=False)
def run_maxwell_filter(subject, session=None):
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())
    os.makedirs(deriv_path, exist_ok=True)

    for run_idx, run in enumerate(config.get_runs()):
        bids_basename = make_bids_basename(subject=subject,
                                           session=session,
                                           task=config.get_task(),
                                           acquisition=config.acq,
                                           run=run,
                                           processing=config.proc,
                                           recording=config.rec,
                                           space=config.space)

        raw = load_data(bids_basename)
        if run_idx == 0:
            dev_head_t = raw.info['dev_head_t']  # Re-use in all runs.

        # Auto-detect bad channels.
        if config.find_flat_channels_meg or config.find_noisy_channels_meg:
            find_bad_channels(raw=raw,
                              subject=subject,
                              session=session,
                              task=config.get_task(),
                              run=run)

        # Maxwell-filter experimental data.
        if config.use_maxwell_filter:
            msg = 'Applying Maxwell filter to experimental data.'
            logger.info(
                gen_log_message(message=msg,
                                step=1,
                                subject=subject,
                                session=session))

            # Warn if no bad channels are set before Maxwell filter
            if not raw.info['bads']:
                msg = '\nFound no bad channels. \n '
                logger.warn(
                    gen_log_message(message=msg,
                                    subject=subject,
                                    step=1,
                                    session=session))

            if config.mf_st_duration:
                msg = '    st_duration=%d' % (config.mf_st_duration)
                logger.info(
                    gen_log_message(message=msg,
                                    step=1,
                                    subject=subject,
                                    session=session))

            # Keyword arguments shared between Maxwell filtering of the
            # experimental and the empty-room data.
            common_mf_kws = dict(calibration=config.mf_cal_fname,
                                 cross_talk=config.mf_ctc_fname,
                                 st_duration=config.mf_st_duration,
                                 origin=config.mf_head_origin,
                                 coord_frame='head',
                                 destination=dev_head_t)

            raw_sss = mne.preprocessing.maxwell_filter(raw, **common_mf_kws)
            raw_out = raw_sss
            raw_fname_out = op.join(deriv_path, f'{bids_basename}_sss_raw.fif')
        else:
            msg = ('Not applying Maxwell filter.\nIf you wish to apply it, '
                   'set use_maxwell_filter=True in your configuration.')
            logger.info(
                gen_log_message(message=msg,
                                step=1,
                                subject=subject,
                                session=session))
            raw_out = raw
            raw_fname_out = op.join(deriv_path,
                                    f'{bids_basename}_nosss_raw.fif')
        raw_out.save(raw_fname_out, overwrite=True)
        if config.interactive:
            raw_out.plot(n_channels=50, butterfly=True)

        # Empty-room processing.
        #
        # We pick the empty-room recording closest in time to the first run
        # of the experimental session.
        if run_idx == 0 and config.noise_cov == 'emptyroom':
            msg = 'Processing empty-room recording …'
            logger.info(
                gen_log_message(step=1,
                                subject=subject,
                                session=session,
                                message=msg))

            bids_basename_er_in = get_matched_empty_room(
                bids_basename=bids_basename, bids_root=config.bids_root)
            raw_er = load_data(bids_basename_er_in)
            raw_er.info['bads'] = [
                ch for ch in raw.info['bads'] if ch.startswith('MEG')
            ]

            # Maxwell-filter empty-room data.
            if config.use_maxwell_filter:
                msg = 'Applying Maxwell filter to empty-room recording'
                logger.info(
                    gen_log_message(message=msg,
                                    step=1,
                                    subject=subject,
                                    session=session))

                # We want to ensure we use the same coordinate frame origin in
                # empty-room and experimental data processing. To do this, we
                # inject the sensor locations and the head <> device transform
                # into the empty-room recording's info, and leave all other
                # parameters the same as for the experimental data. This is not
                # very clean, as we normally should not alter info manually,
                # except for info['bads']. Will need improvement upstream in
                # MNE-Python.
                raw_er.info['dig'] = raw.info['dig']
                raw_er.info['dev_head_t'] = dev_head_t
                raw_er_sss = mne.preprocessing.maxwell_filter(
                    raw_er, **common_mf_kws)

                # Perform a sanity check: empty-room rank should match the
                # experimental data rank after Maxwell filtering.
                rank_exp = mne.compute_rank(raw, rank='info')['meg']
                rank_er = mne.compute_rank(raw_er, rank='info')['meg']
                if not np.isclose(rank_exp, rank_er):
                    msg = (f'Experimental data rank {rank_exp:.1f} does not '
                           f'match empty-room data rank {rank_er:.1f} after '
                           f'Maxwell filtering. This indicates that the data '
                           f'were processed  differenlty.')
                    raise RuntimeError(msg)

                raw_er_out = raw_er_sss
                raw_er_fname_out = op.join(
                    deriv_path, f'{bids_basename}_emptyroom_sss_raw.fif')
            else:
                raw_er_out = raw_er
                raw_er_fname_out = op.join(
                    deriv_path, f'{bids_basename}_emptyroom_nosss_raw.fif')

            raw_er_out.save(raw_er_fname_out, overwrite=True)
def find_bad_channels(raw, subject, session, task, run):
    if (config.find_flat_channels_meg and not config.find_noisy_channels_meg):
        msg = 'Finding flat channels.'
    elif (config.find_noisy_channels_meg
          and not config.find_flat_channels_meg):
        msg = 'Finding noisy channels using Maxwell filtering.'
    else:
        msg = ('Finding flat channels, and noisy channels using '
               'Maxwell filtering.')

    logger.info(
        gen_log_message(message=msg, step=1, subject=subject, session=session))
    raw_lp_filtered_for_maxwell = (raw.copy().filter(l_freq=None, h_freq=40))
    auto_noisy_chs, auto_flat_chs = find_bad_channels_maxwell(
        raw=raw_lp_filtered_for_maxwell,
        calibration=config.mf_cal_fname,
        cross_talk=config.mf_ctc_fname)
    del raw_lp_filtered_for_maxwell

    preexisting_bads = raw.info['bads'].copy()
    bads = preexisting_bads.copy()
    if config.find_flat_channels_meg:
        msg = f'Found {len(auto_flat_chs)} flat channels.'
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        bads.extend(auto_flat_chs)
    if config.find_noisy_channels_meg:
        msg = f'Found {len(auto_noisy_chs)} noisy channels.'
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        bads.extend(auto_noisy_chs)

    bads = sorted(set(bads))
    raw.info['bads'] = bads
    msg = f'Marked {len(raw.info["bads"])} channels as bad.'
    logger.info(
        gen_log_message(message=msg, step=1, subject=subject, session=session))

    # Write the bad channels to disk.
    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=run,
                                       processing=config.proc,
                                       recording=config.rec,
                                       space=config.space)

    bads_tsv_fname = op.join(deriv_path, f'{bids_basename}_bad_channels.tsv')
    bads_for_tsv = []
    reasons = []

    if config.find_flat_channels_meg:
        bads_for_tsv.extend(auto_flat_chs)
        reasons.extend(['auto-flat'] * len(auto_flat_chs))
        preexisting_bads = set(preexisting_bads) - set(auto_flat_chs)

    if config.find_noisy_channels_meg:
        bads_for_tsv.extend(auto_noisy_chs)
        reasons.extend(['auto-noisy'] * len(auto_noisy_chs))
        preexisting_bads = set(preexisting_bads) - set(auto_noisy_chs)

    preexisting_bads = list(preexisting_bads)
    if preexisting_bads:
        bads_for_tsv.extend(preexisting_bads)
        reasons.extend(['pre-existing (before mne-study-template was run)'] *
                       len(preexisting_bads))

    tsv_data = pd.DataFrame(dict(name=bads_for_tsv, reason=reasons))
    tsv_data = tsv_data.sort_values(by='name')
    tsv_data.to_csv(bads_tsv_fname, sep='\t', index=False)
예제 #28
0
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)
예제 #29
0
def run_filter(subject, run=None, session=None):
    """Filter data from a single subject."""
    kind = config.get_kind()
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=kind)

    # Construct the basenames of the files we wish to load, and of the empty-
    # room recording we wish to save.
    # The basenames of the empty-room recording output file does not contain
    # the "run" entity.
    bids_basename = BIDSPath(subject=subject,
                             run=run,
                             session=session,
                             task=config.get_task(),
                             acquisition=config.acq,
                             processing=config.proc,
                             recording=config.rec,
                             space=config.space,
                             prefix=deriv_path,
                             kind=kind)

    bids_er_out_basename = bids_basename.copy().update(run=None)

    # Prepare a name to save the data
    raw_fname_in = bids_basename.copy().update(extension='.fif')
    raw_er_fname_in = bids_basename.copy().update(
        task='noise', run=None, extension='.fif')

    if config.use_maxwell_filter:
        raw_fname_in = raw_fname_in.update(processing='sss')
        raw_er_fname_in = raw_er_fname_in.update(processing='sss')

    raw_fname_out = bids_basename.copy().update(
        processing='filt', extension='.fif')
    raw_er_fname_out = bids_er_out_basename.copy().update(
        processing='filt', task='noise', extension='.fif')

    msg = f'Input: {raw_fname_in}, Output: {raw_fname_out}'
    logger.info(gen_log_message(message=msg, step=2, subject=subject,
                                session=session, run=run,))

    raw = mne.io.read_raw_fif(raw_fname_in)
    raw.load_data()

    # Band-pass the data channels (MEG and EEG)
    msg = (f'Filtering experimental data between {config.l_freq} and '
           f'{config.h_freq} Hz')
    logger.info(gen_log_message(message=msg, step=2, subject=subject,
                                session=session, run=run))

    filter_kws = dict(l_freq=config.l_freq, h_freq=config.h_freq,
                      l_trans_bandwidth=config.l_trans_bandwidth,
                      h_trans_bandwidth=config.h_trans_bandwidth,
                      filter_length='auto', phase='zero', fir_window='hamming',
                      fir_design='firwin')
    raw.filter(**filter_kws)

    if config.process_er:
        msg = 'Filtering empty-room recording.'
        logger.info(gen_log_message(message=msg, step=2, subject=subject,
                                    session=session, run=run,))
        raw_er = mne.io.read_raw_fif(raw_er_fname_in)
        raw_er.load_data()
        raw_er.filter(**filter_kws)

    if config.resample_sfreq:
        msg = f'Resampling experimental data to {config.resample_sfreq:.1f} Hz'
        logger.info(gen_log_message(message=msg, step=2, subject=subject,
                                    session=session, run=run,))
        raw.resample(config.resample_sfreq, npad='auto')

        if config.process_er:
            msg = 'Resampling empty-room recording.'
            logger.info(gen_log_message(message=msg, step=2, subject=subject,
                                        session=session, run=run,))
            raw_er.resample(config.resample_sfreq, npad='auto')

    raw.save(raw_fname_out, overwrite=True)
    if config.process_er:
        raw_er.save(raw_er_fname_out, overwrite=True)

    if config.interactive:
        # Plot raw data and power spectral density.
        raw.plot(n_channels=50, butterfly=True)
        fmax = 1.5 * config.h_freq if config.h_freq is not None else np.inf
        raw.plot_psd(fmax=fmax)

        if config.process_er:
            raw_er.plot(n_channels=50, butterfly=True)
            raw_er.plot_psd(fmax=fmax)
msg = 'Running Step 7: Grand-average sensor data'
logger.info(gen_log_message(step=7, message=msg))

# Container for all conditions:
all_evokeds = defaultdict(list)

# XXX to fix
if config.get_sessions():
    session = config.get_sessions()[0]
else:
    session = None

for subject in config.get_subjects():
    deriv_path = config.get_subject_deriv_path(subject=subject,
                                               session=session,
                                               kind=config.get_kind())

    fname_in = BIDSPath(subject=subject,
                        session=session,
                        task=config.get_task(),
                        acquisition=config.acq,
                        run=None,
                        recording=config.rec,
                        space=config.space,
                        prefix=deriv_path,
                        kind='ave',
                        extension='.fif',
                        check=False)

    msg = f'Input: {fname_in}'
    logger.info(gen_log_message(message=msg, step=7, subject=subject,