Beispiel #1
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_epochs(subject, session=None):
    """Extract epochs for one subject."""
    raw_list = list()
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root)

    for run in config.get_runs():
        # Prepare a name to save the data
        raw_fname_in = bids_path.copy().update(run=run,
                                               processing='filt',
                                               suffix='raw',
                                               check=False)

        if raw_fname_in.copy().update(split='01').fpath.exists():
            raw_fname_in.update(split='01')

        msg = f'Loading filtered raw data from {raw_fname_in}'
        logger.info(
            gen_log_message(message=msg,
                            step=3,
                            subject=subject,
                            session=session,
                            run=run))

        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=3, subject=subject, session=session))

    if len(raw_list) == 1:  # avoid extra memory usage
        raw = raw_list[0]
    else:
        raw = mne.concatenate_raws(raw_list)

    events, event_id = mne.events_from_annotations(raw)
    if "eeg" in config.ch_types:
        projection = True if config.eeg_reference == 'average' else False
        raw.set_eeg_reference(config.eeg_reference, projection=projection)

    del raw_list

    # Construct metadata from the epochs
    # Add here if you need to attach a pandas dataframe as metadata
    # to your epochs object:
    # https://martinos.org/mne/dev/auto_tutorials/plot_metadata_epochs.html

    # Epoch the data
    msg = 'Epoching'
    logger.info(
        gen_log_message(message=msg, step=3, subject=subject, session=session))
    epochs = mne.Epochs(raw,
                        events=events,
                        event_id=event_id,
                        tmin=config.epochs_tmin,
                        tmax=config.epochs_tmax,
                        proj=True,
                        baseline=config.baseline,
                        preload=False,
                        decim=config.decim,
                        reject=config.get_reject(),
                        reject_tmin=config.reject_tmin,
                        reject_tmax=config.reject_tmax)

    msg = 'Writing epochs to disk'
    logger.info(
        gen_log_message(message=msg, step=3, subject=subject, session=session))
    epochs_fname = bids_path.copy().update(suffix='epo', check=False)
    epochs.save(epochs_fname, overwrite=True)

    if config.interactive:
        epochs.plot()
        epochs.plot_image(combine='gfp', sigma=2., cmap='YlGnBu_r')
Beispiel #3
0
def run_epochs(subject, session=None):
    """Extract epochs for one subject."""
    raw_list = list()

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

    for run in 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)
        # Prepare a name to save the data
        raw_fname_in = \
            op.join(deriv_path, bids_basename + '_filt_raw.fif')

        msg = f'Loading filtered raw data from {raw_fname_in}'
        logger.info(
            gen_log_message(message=msg,
                            step=3,
                            subject=subject,
                            session=session,
                            run=run))

        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=3, subject=subject, session=session))
    raw = mne.concatenate_raws(raw_list)

    events, event_id = mne.events_from_annotations(raw)
    if "eeg" in config.ch_types:
        raw.set_eeg_reference(projection=True)

    del raw_list

    meg = False
    if 'meg' in config.ch_types:
        meg = True
    elif 'grad' in config.ch_types:
        meg = 'grad'
    elif 'mag' in config.ch_types:
        meg = 'mag'

    eeg = config.get_kind() == 'eeg'

    picks = mne.pick_types(raw.info,
                           meg=meg,
                           eeg=eeg,
                           stim=True,
                           eog=True,
                           exclude=())

    # Construct metadata from the epochs
    # Add here if you need to attach a pandas dataframe as metadata
    # to your epochs object:
    # https://martinos.org/mne/dev/auto_tutorials/plot_metadata_epochs.html

    # Epoch the data
    msg = 'Epoching'
    logger.info(
        gen_log_message(message=msg, step=3, subject=subject, session=session))
    epochs = mne.Epochs(raw,
                        events,
                        event_id,
                        config.tmin,
                        config.tmax,
                        proj=True,
                        picks=picks,
                        baseline=config.baseline,
                        preload=False,
                        decim=config.decim,
                        reject=config.get_reject())

    msg = 'Writing epochs to disk'
    logger.info(
        gen_log_message(message=msg, step=3, subject=subject, session=session))
    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)

    epochs_fname = \
        op.join(deriv_path, bids_basename + '-epo.fif')
    epochs.save(epochs_fname, overwrite=True)

    if config.interactive:
        epochs.plot()
        epochs.plot_image(combine='gfp',
                          picks=config.ch_types,
                          sigma=2.,
                          cmap='YlGnBu_r')
def run_epochs(subject, session=None):
    """Extract epochs for one subject."""
    raw_list = list()
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root)

    for run in config.get_runs():
        # Prepare a name to save the data
        raw_fname_in = bids_path.copy().update(run=run,
                                               processing='filt',
                                               suffix='raw',
                                               check=False)

        if raw_fname_in.copy().update(split='01').fpath.exists():
            raw_fname_in.update(split='01')

        msg = f'Loading filtered raw data from {raw_fname_in}'
        logger.info(
            gen_log_message(message=msg,
                            step=3,
                            subject=subject,
                            session=session,
                            run=run))

        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=3, subject=subject, session=session))

    if len(raw_list) == 1:  # avoid extra memory usage
        raw = raw_list[0]
    else:
        raw = mne.concatenate_raws(raw_list)

    events, event_id = mne.events_from_annotations(raw)
    if "eeg" in config.ch_types:
        projection = True if config.eeg_reference == 'average' else False
        raw.set_eeg_reference(config.eeg_reference, projection=projection)

    del raw_list

    # Construct metadata from the epochs
    if config.epochs_metadata_tmin is None:
        epochs_metadata_tmin = config.epochs_tmin
    else:
        epochs_metadata_tmin = config.epochs_metadata_tmin

    if config.epochs_metadata_tmax is None:
        epochs_metadata_tmax = config.epochs_tmax
    else:
        epochs_metadata_tmax = config.epochs_metadata_tmax

    metadata, _, _ = mne.epochs.make_metadata(
        events=events,
        event_id=event_id,
        tmin=epochs_metadata_tmin,
        tmax=epochs_metadata_tmax,
        keep_first=config.epochs_metadata_keep_first,
        keep_last=config.epochs_metadata_keep_last,
        sfreq=raw.info['sfreq'])

    # Epoch the data
    msg = (f'Creating epochs with duration: '
           f'[{config.epochs_tmin}, {config.epochs_tmin}] sec')
    logger.info(
        gen_log_message(message=msg, step=3, subject=subject, session=session))
    epochs = mne.Epochs(raw,
                        events=events,
                        event_id=event_id,
                        tmin=config.epochs_tmin,
                        tmax=config.epochs_tmax,
                        proj=True,
                        baseline=None,
                        preload=False,
                        decim=config.decim,
                        reject=config.get_reject(),
                        reject_tmin=config.reject_tmin,
                        reject_tmax=config.reject_tmax,
                        metadata=metadata,
                        event_repeated=config.event_repeated)

    msg = 'Writing epochs to disk'
    logger.info(
        gen_log_message(message=msg, step=3, subject=subject, session=session))
    epochs_fname = bids_path.copy().update(suffix='epo', check=False)
    epochs.save(epochs_fname, overwrite=True)

    if config.interactive:
        epochs.plot()
        epochs.plot_image(combine='gfp', sigma=2., cmap='YlGnBu_r')
def drop_ptp(*, cfg, subject, session=None):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=cfg.task,
                         acquisition=cfg.acq,
                         run=None,
                         recording=cfg.rec,
                         space=cfg.space,
                         suffix='epo',
                         extension='.fif',
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)

    infile_processing = cfg.spatial_filter
    fname_in = bids_path.copy().update(processing=infile_processing)
    fname_out = bids_path.copy().update(processing='clean')

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

    # Get rejection parameters and drop bad epochs
    epochs = mne.read_epochs(fname_in, preload=True)
    reject = config.get_reject(epochs=epochs)

    if cfg.ica_reject is not None:
        for ch_type, threshold in cfg.ica_reject.items():
            if (ch_type in reject and threshold < reject[ch_type]):
                # This can only ever happen in case of
                # reject = 'autoreject_global'
                msg = (f'Adjusting PTP rejection threshold proposed by '
                       f'autoreject, as it is greater than ica_reject: '
                       f'{ch_type}: {reject[ch_type]} -> {threshold}')
                logger.info(**gen_log_kwargs(
                    message=msg, subject=subject, session=session))
                reject[ch_type] = threshold

    msg = f'Using PTP rejection thresholds: {reject}'
    logger.info(
        **gen_log_kwargs(message=msg, subject=subject, session=session))

    n_epochs_before_reject = len(epochs)
    epochs.reject_tmin = cfg.reject_tmin
    epochs.reject_tmax = cfg.reject_tmax
    epochs.drop_bad(reject=reject)
    n_epochs_after_reject = len(epochs)

    if 0 < n_epochs_after_reject < 0.5 * n_epochs_before_reject:
        msg = ('More than 50% of all epochs rejected. Please check the '
               'rejection thresholds.')
        logger.warning(
            **gen_log_kwargs(message=msg, subject=subject, session=session))
    elif n_epochs_after_reject == 0:
        raise RuntimeError('No epochs remaining after peak-to-peak-based '
                           'rejection. Cannot continue.')

    msg = 'Saving cleaned, baseline-corrected epochs …'

    epochs.apply_baseline(cfg.baseline)
    epochs.save(fname_out, overwrite=True)