Beispiel #1
0
def test_update_fail_check_no_change():
    bids_path = BIDSPath(subject='test')
    try:
        bids_path.update(suffix='ave')
    except Exception:
        pass
    assert bids_path.suffix is None
def run_average(cfg, session, mean_morphed_stcs):
    subject = 'average'
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=cfg.task,
                         acquisition=cfg.acq,
                         run=None,
                         processing=cfg.proc,
                         recording=cfg.rec,
                         space=cfg.space,
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)

    if isinstance(cfg.conditions, dict):
        conditions = list(cfg.conditions.keys())
    else:
        conditions = cfg.conditions

    for condition, stc in zip(conditions, mean_morphed_stcs):
        method = cfg.inverse_method
        cond_str = sanitize_cond_name(condition)
        inverse_str = method
        hemi_str = 'hemi'  # MNE will auto-append '-lh' and '-rh'.
        morph_str = 'morph2fsaverage'

        fname_stc_avg = bids_path.copy().update(
            suffix=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}')
        stc.save(fname_stc_avg)
Beispiel #3
0
def test_bids_path_inference(return_bids_test_dir):
    """Test usage of BIDSPath object and fpath."""
    bids_root = return_bids_test_dir

    # without providing all the entities, ambiguous when trying
    # to use fpath
    bids_path = BIDSPath(
        subject=subject_id, session=session_id, acquisition=acq,
        task=task, root=bids_root)
    with pytest.raises(RuntimeError, match='Found more than one'):
        bids_path.fpath

    # shouldn't error out when there is no uncertainty
    channels_fname = BIDSPath(subject=subject_id, session=session_id,
                              run=run, acquisition=acq, task=task,
                              root=bids_root, suffix='channels')
    channels_fname.fpath

    # create an extra file under 'eeg'
    extra_file = op.join(bids_root, f'sub-{subject_id}',
                         f'ses-{session_id}', 'eeg',
                         channels_fname.basename + '.tsv')
    Path(extra_file).parent.mkdir(exist_ok=True, parents=True)
    # Creates a new file and because of this new file, there is now
    # ambiguity
    with open(extra_file, 'w', encoding='utf-8'):
        pass
    with pytest.raises(RuntimeError, match='Found data of more than one'):
        channels_fname.fpath

    # if you set datatype, now there is no ambiguity
    channels_fname.update(datatype='eeg')
    assert str(channels_fname.fpath) == extra_file
    # set state back to original
    shutil.rmtree(Path(extra_file).parent)
def run_evoked(subject, session=None):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=None,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root)

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

    fname_in = bids_path.copy().update(processing=processing, suffix='epo',
                                       check=False)
    fname_out = bids_path.copy().update(suffix='ave', check=False)

    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))
    all_evoked = dict()

    if isinstance(config.conditions, dict):
        for new_cond_name, orig_cond_name in config.conditions.items():
            evoked = epochs[orig_cond_name].average()
            evoked.comment = evoked.comment.replace(orig_cond_name,
                                                    new_cond_name)
            all_evoked[new_cond_name] = evoked
    else:
        for condition in config.conditions:
            evoked = epochs[condition].average()
            all_evoked[condition] = 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_diff = mne.combine_evoked([all_evoked[cond_1],
                                              all_evoked[cond_2]],
                                             weights=[1, -1])
            all_evoked[contrast] = evoked_diff

    evokeds = list(all_evoked.values())
    mne.write_evokeds(fname_out, evokeds)

    if config.interactive:
        for evoked in evokeds:
            evoked.plot()
Beispiel #5
0
def test_find_emptyroom_ties(tmpdir):
    """Test that we receive a warning on a date tie."""
    data_path = testing.data_path()
    raw_fname = op.join(data_path, 'MEG', 'sample',
                        'sample_audvis_trunc_raw.fif')

    bids_root = str(tmpdir)
    bids_path.update(root=bids_root)
    session = '20010101'
    er_dir_path = BIDSPath(subject='emptyroom', session=session,
                           datatype='meg', root=bids_root)
    er_dir = er_dir_path.mkdir().directory

    meas_date = (datetime
                 .strptime(session, '%Y%m%d')
                 .replace(tzinfo=timezone.utc))

    raw = _read_raw_fif(raw_fname)

    er_raw_fname = op.join(data_path, 'MEG', 'sample', 'ernoise_raw.fif')
    raw.copy().crop(0, 10).save(er_raw_fname, overwrite=True)
    er_raw = _read_raw_fif(er_raw_fname)
    raw.set_meas_date(meas_date)
    er_raw.set_meas_date(meas_date)

    write_raw_bids(raw, bids_path, overwrite=True)
    er_bids_path = BIDSPath(subject='emptyroom', session=session)
    er_basename_1 = er_bids_path.basename
    er_basename_2 = BIDSPath(subject='emptyroom', session=session,
                             task='noise').basename
    er_raw.save(op.join(er_dir, f'{er_basename_1}_meg.fif'))
    er_raw.save(op.join(er_dir, f'{er_basename_2}_meg.fif'))

    with pytest.warns(RuntimeWarning, match='Found more than one'):
        bids_path.find_empty_room()
Beispiel #6
0
def run_report(
    *,
    cfg: SimpleNamespace,
    subject: str,
    session: Optional[str] = None,
):
    report = _gen_empty_report(cfg=cfg, subject=subject, session=session)
    kwargs = dict(cfg=cfg, subject=subject, session=session, report=report)
    report = run_report_preprocessing(**kwargs)
    report = run_report_sensor(**kwargs)
    report = run_report_source(**kwargs)

    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=cfg.task,
                         acquisition=cfg.acq,
                         run=None,
                         recording=cfg.rec,
                         space=cfg.space,
                         extension='.fif',
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)
    fname_report = bids_path.copy().update(suffix='report', extension='.html')
    report.save(fname=fname_report,
                open_browser=cfg.interactive,
                overwrite=True)
Beispiel #7
0
def run_forward(*, 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,
                         extension='.fif',
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)

    fname_info = bids_path.copy().update(**cfg.source_info_path_update)
    fname_trans = bids_path.copy().update(suffix='trans')
    fname_fwd = bids_path.copy().update(suffix='fwd')

    if cfg.use_template_mri:
        src, trans, bem_sol = _prepare_forward_fsaverage(cfg)
    else:
        src, trans, bem_sol = _prepare_forward(cfg, bids_path, fname_trans)

    # Finally, calculate and save the forward solution.
    msg = 'Calculating forward solution'
    logger.info(
        **gen_log_kwargs(message=msg, subject=subject, session=session))
    info = mne.io.read_info(fname_info)
    fwd = mne.make_forward_solution(info,
                                    trans=trans,
                                    src=src,
                                    bem=bem_sol,
                                    mindist=cfg.mindist)

    mne.write_trans(fname_trans, fwd['mri_head_t'], overwrite=True)
    mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
Beispiel #8
0
def plot_events(cfg, subject, session):
    raws_filt = []
    raw_fname = BIDSPath(subject=subject,
                         session=session,
                         task=cfg.task,
                         acquisition=cfg.acq,
                         recording=cfg.rec,
                         space=cfg.space,
                         processing='filt',
                         suffix='raw',
                         extension='.fif',
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)

    for run in cfg.runs:
        this_raw_fname = raw_fname.copy().update(run=run)

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

        raw_filt = mne.io.read_raw_fif(this_raw_fname)
        raws_filt.append(raw_filt)
        del this_raw_fname

    # Concatenate the filtered raws and extract the events.
    raw_filt_concat = mne.concatenate_raws(raws_filt, on_mismatch='warn')
    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
Beispiel #9
0
def plot_er_psd(subject, session):
    raw_fname = BIDSPath(subject=subject,
                         session=session,
                         acquisition=config.acq,
                         run=None,
                         recording=config.rec,
                         space=config.space,
                         task='noise',
                         processing='filt',
                         suffix='raw',
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

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

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

    raw_er_filtered = mne.io.read_raw_fif(raw_fname,
                                          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
Beispiel #10
0
def plot_auto_scores(cfg, subject, session):
    """Plot automated bad channel detection scores.
    """
    import json_tricks

    fname_scores = BIDSPath(subject=subject,
                            session=session,
                            task=cfg.task,
                            acquisition=cfg.acq,
                            run=None,
                            processing=cfg.proc,
                            recording=cfg.rec,
                            space=cfg.space,
                            suffix='scores',
                            extension='.json',
                            datatype=cfg.datatype,
                            root=cfg.deriv_root,
                            check=False)

    all_figs = []
    all_captions = []
    for run in cfg.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
Beispiel #11
0
def test_handle_chpi_reading(tmp_path):
    """Test reading of cHPI information."""
    raw = _read_raw_fif(raw_fname_chpi, allow_maxshield=True)
    root = tmp_path / 'chpi'
    root.mkdir()
    bids_path = BIDSPath(subject='01', session='01',
                         task='audiovisual', run='01',
                         root=root, datatype='meg')
    bids_path = write_raw_bids(raw, bids_path)

    raw_read = read_raw_bids(bids_path)
    assert raw_read.info['hpi_subsystem'] is not None

    # cause conflicts between cHPI info in sidecar and raw data
    meg_json_path = bids_path.copy().update(suffix='meg', extension='.json')
    with open(meg_json_path, 'r', encoding='utf-8') as f:
        meg_json_data = json.load(f)

    # cHPI frequency mismatch
    meg_json_data_freq_mismatch = meg_json_data.copy()
    meg_json_data_freq_mismatch['HeadCoilFrequency'][0] = 123
    _write_json(meg_json_path, meg_json_data_freq_mismatch, overwrite=True)

    with pytest.warns(RuntimeWarning, match='Defaulting to .* mne.Raw object'):
        raw_read = read_raw_bids(bids_path)

    # cHPI "off" according to sidecar, but present in the data
    meg_json_data_chpi_mismatch = meg_json_data.copy()
    meg_json_data_chpi_mismatch['ContinuousHeadLocalization'] = False
    _write_json(meg_json_path, meg_json_data_chpi_mismatch, overwrite=True)

    raw_read = read_raw_bids(bids_path)
    assert raw_read.info['hpi_subsystem'] is None
    assert raw_read.info['hpi_meas'] == []
def compute_cov_from_empty_room(cfg, subject, session):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=cfg.task,
                         acquisition=cfg.acq,
                         run=None,
                         recording=cfg.rec,
                         space=cfg.space,
                         extension='.fif',
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)

    raw_er_fname = bids_path.copy().update(processing='filt',
                                           task='noise',
                                           suffix='raw')
    cov_fname = bids_path.copy().update(suffix='cov')

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

    raw_er = mne.io.read_raw_fif(raw_er_fname, preload=True)
    cov = mne.compute_raw_covariance(raw_er, method='shrunk', rank='info')
    cov.save(cov_fname)
def compute_cov_from_epochs(subject, session, tmin, tmax):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=None,
                         processing=config.proc,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

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

    epo_fname = bids_path.copy().update(processing=processing, suffix='epo')
    cov_fname = bids_path.copy().update(suffix='cov')

    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 compute_cov_from_empty_room(subject, session):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=None,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

    raw_er_fname = bids_path.copy().update(processing='filt',
                                           task='noise',
                                           suffix='raw')
    cov_fname = bids_path.copy().update(suffix='cov')

    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)
def plot_events(subject, session):
    raws_filt = []
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         recording=config.rec,
                         space=config.space,
                         processing='filt',
                         suffix='raw',
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

    for run in config.get_runs():
        fname = bids_path.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
Beispiel #16
0
def compute_cov_from_epochs(cfg, subject, session, tmin, tmax):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=cfg.task,
                         acquisition=cfg.acq,
                         run=None,
                         processing=cfg.proc,
                         recording=cfg.rec,
                         space=cfg.space,
                         extension='.fif',
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)

    processing = None
    if cfg.spatial_filter is not None:
        processing = 'clean'

    epo_fname = bids_path.copy().update(processing=processing, suffix='epo')
    cov_fname = bids_path.copy().update(suffix='cov')

    msg = (f"Computing regularized covariance based on epochs' baseline "
           f"periods. Input: {epo_fname}, Output: {cov_fname}")
    logger.info(
        **gen_log_kwargs(message=msg, 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, overwrite=True)
Beispiel #17
0
def test_find_emptyroom_no_meas_date(tmpdir):
    """Test that we warn if measurement date can be read or inferred."""
    data_path = testing.data_path()
    raw_fname = op.join(data_path, 'MEG', 'sample',
                        'sample_audvis_trunc_raw.fif')

    bids_root = str(tmpdir)
    bids_path.update(root=bids_root)
    er_session = 'mysession'
    er_meas_date = None

    er_dir_path = BIDSPath(subject='emptyroom', session=er_session,
                           datatype='meg', root=bids_root)
    er_dir = er_dir_path.mkdir().directory

    er_bids_path = BIDSPath(subject='emptyroom', session=er_session,
                            task='noise', check=False)
    er_basename = er_bids_path.basename
    raw = _read_raw_fif(raw_fname)

    er_raw_fname = op.join(data_path, 'MEG', 'sample', 'ernoise_raw.fif')
    raw.copy().crop(0, 10).save(er_raw_fname, overwrite=True)
    er_raw = _read_raw_fif(er_raw_fname)
    er_raw.set_meas_date(er_meas_date)
    er_raw.save(op.join(er_dir, f'{er_basename}_meg.fif'), overwrite=True)

    # Write raw file data using mne-bids, and remove participants.tsv
    # as it's incomplete (doesn't contain the emptyroom subject we wrote
    # manually using MNE's Raw.save() above)
    raw = _read_raw_fif(raw_fname)
    write_raw_bids(raw, bids_path, overwrite=True)
    os.remove(op.join(bids_root, 'participants.tsv'))

    with pytest.warns(RuntimeWarning, match='Could not retrieve .* date'):
        bids_path.find_empty_room()
def main():
    """Run group average in source space"""
    msg = 'Running Step 13: Grand-average source estimates'
    logger.info(gen_log_message(step=13, message=msg))

    if not config.run_source_estimation:
        msg = '    … skipping: run_source_estimation is set to False.'
        logger.info(gen_log_message(step=13, message=msg))
        return

    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

    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=None,
                         processing=config.proc,
                         recording=config.rec,
                         space=config.space,
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

    if isinstance(config.conditions, dict):
        conditions = list(config.conditions.keys())
    else:
        conditions = config.conditions

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

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

        fname_stc_avg = bids_path.copy().update(
            suffix=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))
Beispiel #19
0
def run_ssp(subject, session=None):
    # compute SSP on first run of raw
    run = config.get_runs()[0]
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=run,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root)

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

    # when saving proj, use run=None
    proj_fname_out = bids_path.copy().update(run=None,
                                             suffix='proj',
                                             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))

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

    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))
    if config.eog_channels:
        assert all(
            [ch_name in raw.ch_names for ch_name in config.eog_channels])
        ch_name = ','.join(config.eog_channels)
    else:
        ch_name = None

    eog_projs, eog_events = compute_proj_eog(raw,
                                             ch_name=ch_name,
                                             n_grad=1,
                                             n_mag=1,
                                             n_eeg=1,
                                             average=True)

    mne.write_proj(proj_fname_out, eog_projs + ecg_projs)
def run_inverse(subject, session=None):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=None,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

    fname_ave = bids_path.copy().update(suffix='ave')
    fname_fwd = bids_path.copy().update(suffix='fwd')
    fname_cov = bids_path.copy().update(suffix='cov')
    fname_inv = bids_path.copy().update(suffix='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

    if isinstance(config.conditions, dict):
        conditions = list(config.conditions.keys())
    else:
        conditions = config.conditions

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

        cond_str = config.sanitize_cond_name(condition)
        inverse_str = method
        hemi_str = 'hemi'  # MNE will auto-append '-lh' and '-rh'.
        fname_stc = bids_path.copy().update(
            suffix=f'{cond_str}+{inverse_str}+{hemi_str}', extension=None)

        if "eeg" in config.ch_types:
            evoked.set_eeg_reference('average', projection=True)

        stc = apply_inverse(evoked=evoked,
                            inverse_operator=inverse_operator,
                            lambda2=lambda2,
                            method=method,
                            pick_ori=pick_ori)
        stc.save(fname_stc)
def average_evokeds(session):
    # Container for all conditions:
    all_evokeds = defaultdict(list)

    for subject in config.get_subjects():
        fname_in = BIDSPath(subject=subject,
                            session=session,
                            task=config.get_task(),
                            acquisition=config.acq,
                            run=None,
                            recording=config.rec,
                            space=config.space,
                            suffix='ave',
                            extension='.fif',
                            datatype=config.get_datatype(),
                            root=config.deriv_root,
                            check=False)

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

        evokeds = mne.read_evokeds(fname_in)
        for idx, evoked in enumerate(evokeds):
            all_evokeds[idx].append(evoked)  # Insert into the container

    for idx, evokeds in all_evokeds.items():
        all_evokeds[idx] = mne.grand_average(
            evokeds, interpolate_bads=config.interpolate_bads_grand_average
        )  # Combine subjects

    subject = 'average'
    fname_out = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=None,
                         processing=config.proc,
                         recording=config.rec,
                         space=config.space,
                         suffix='ave',
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

    if not fname_out.fpath.parent.exists():
        os.makedirs(fname_out.fpath.parent)

    msg = f'Saving grand-averaged evoked sensor data: {fname_out}'
    logger.info(
        gen_log_message(message=msg, step=9, subject=subject, session=session))
    mne.write_evokeds(fname_out, list(all_evokeds.values()))
    return list(all_evokeds.values())
Beispiel #22
0
def test_bids_path_label_vs_index_entity():
    match = "subject must be an instance of None or str"
    with pytest.raises(TypeError, match=match):
        BIDSPath(subject=1)
    match = "root must be an instance of path-like or None"
    with pytest.raises(TypeError, match=match):
        BIDSPath(root=1, subject='01')
    BIDSPath(subject='01', run=1)  # ok as <index> entity
    BIDSPath(subject='01', split=1)  # ok as <index> entity
Beispiel #23
0
def run_evoked(subject, session=None):
    bids_path = BIDSPath(subject=subject,
                         session=session,
                         task=config.get_task(),
                         acquisition=config.acq,
                         run=None,
                         recording=config.rec,
                         space=config.space,
                         extension='.fif',
                         datatype=config.get_datatype(),
                         root=config.deriv_root)

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

    fname_in = bids_path.copy().update(processing=processing,
                                       suffix='epo',
                                       check=False)
    fname_out = bids_path.copy().update(suffix='ave', check=False)

    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.write_evokeds(fname_out, evokeds)

    if config.interactive:
        for evoked in evokeds:
            evoked.plot()
def run_time_decoding(subject, condition1, condition2, session=None):
    msg = f'Contrasting conditions: {condition1} – {condition2}'
    logger.info(
        gen_log_message(message=msg, step=7, subject=subject, session=session))

    fname_epochs = BIDSPath(subject=subject,
                            session=session,
                            task=config.get_task(),
                            acquisition=config.acq,
                            run=None,
                            recording=config.rec,
                            space=config.space,
                            suffix='epo',
                            extension='.fif',
                            datatype=config.get_datatype(),
                            root=config.deriv_root,
                            check=False)

    epochs = mne.read_epochs(fname_epochs)

    # We define the epochs and the labels
    epochs = mne.concatenate_epochs([epochs[condition1], epochs[condition2]])
    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)]

    clf = make_pipeline(
        StandardScaler(),
        LogisticRegression(solver='liblinear',
                           random_state=config.random_state))

    se = SlidingEstimator(clf,
                          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_mat = fname_epochs.copy().update(suffix='decoding',
                                           processing=processing,
                                           extension='.mat')
    savemat(fname_mat, {'scores': scores, 'times': epochs.times})

    fname_tsv = fname_mat.copy().update(extension='.tsv')
    tabular_data = pd.DataFrame(
        dict(cond_1=[condition1] * len(epochs.times),
             cond_2=[condition2] * len(epochs.times),
             time=epochs.times,
             mean_crossval_score=scores.mean(axis=0),
             metric=[config.decoding_metric] * len(epochs.times)))
    tabular_data.to_csv(fname_tsv, sep='\t', index=False)
Beispiel #25
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))
Beispiel #26
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)
Beispiel #27
0
def test_handle_info_reading():
    """Test reading information from a BIDS sidecar.json file."""
    bids_root = _TempDir()

    # read in USA dataset, so it should find 50 Hz
    raw = _read_raw_fif(raw_fname)

    # write copy of raw with line freq of 60
    # bids basename and fname
    bids_path = BIDSPath(subject='01',
                         session='01',
                         task='audiovisual',
                         run='01',
                         root=bids_root)
    suffix = "meg"
    bids_fname = bids_path.copy().update(suffix=suffix, extension='.fif')
    write_raw_bids(raw, bids_path, overwrite=True)

    # find sidecar JSON fname
    bids_fname.update(datatype=suffix)
    sidecar_fname = _find_matching_sidecar(bids_fname,
                                           suffix=suffix,
                                           extension='.json')

    # assert that we get the same line frequency set
    raw = read_raw_bids(bids_path=bids_path)
    assert raw.info['line_freq'] == 60

    # 2. if line frequency is not set in raw file, then ValueError
    raw.info['line_freq'] = None
    with pytest.raises(ValueError, match="PowerLineFrequency .* required"):
        write_raw_bids(raw, bids_path, overwrite=True)

    # make a copy of the sidecar in "derivatives/"
    # to check that we make sure we always get the right sidecar
    # in addition, it should not break the sidecar reading
    # in `read_raw_bids`
    deriv_dir = op.join(bids_root, "derivatives")
    sidecar_copy = op.join(deriv_dir, op.basename(sidecar_fname))
    os.mkdir(deriv_dir)
    with open(sidecar_fname, "r", encoding='utf-8') as fin:
        sidecar_json = json.load(fin)
        sidecar_json["PowerLineFrequency"] = 45
    _write_json(sidecar_copy, sidecar_json)
    raw = read_raw_bids(bids_path=bids_path)
    assert raw.info['line_freq'] == 60

    # 3. assert that we get an error when sidecar json doesn't match
    _update_sidecar(sidecar_fname, "PowerLineFrequency", 55)
    with pytest.raises(ValueError, match="Line frequency in sidecar json"):
        raw = read_raw_bids(bids_path=bids_path)
        assert raw.info['line_freq'] == 55
Beispiel #28
0
def run_time_frequency(*, 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,
                         datatype=cfg.datatype,
                         root=cfg.deriv_root,
                         check=False)

    processing = None
    if cfg.spatial_filter is not None:
        processing = 'clean'

    fname_in = bids_path.copy().update(suffix='epo',
                                       processing=processing,
                                       extension='.fif')

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

    epochs = mne.read_epochs(fname_in)
    if cfg.analyze_channels:
        # We special-case the average reference here.
        # See 02-sliding_estimator.py for more info.
        if 'eeg' in cfg.ch_types and cfg.eeg_reference == 'average':
            epochs.set_eeg_reference('average')
        else:
            epochs.apply_proj()
        epochs.pick(cfg.analyze_channels)

    freqs = np.arange(cfg.time_frequency_freq_min, cfg.time_frequency_freq_max)
    n_cycles = freqs / 3.

    for condition in cfg.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 = sanitize_cond_name(condition)
        power_fname_out = bids_path.copy().update(
            suffix=f'power+{condition_str}+tfr', extension='.h5')
        itc_fname_out = bids_path.copy().update(
            suffix=f'itc+{condition_str}+tfr', extension='.h5')

        power.save(power_fname_out, overwrite=True)
        itc.save(itc_fname_out, overwrite=True)
Beispiel #29
0
def test_count_events_bids_path(tmpdir):
    """Test the event counts passing a BIDSPath."""
    root, events, event_id = \
        _make_dataset(tmpdir, subjects=['01', '02'], tasks=['task1'])

    with pytest.raises(ValueError, match='datatype .*anat.* is not supported'):
        bids_path = BIDSPath(root=root, subject='01', datatype='anat')
        count_events(bids_path)

    bids_path = BIDSPath(root=root, subject='01', datatype='meg')
    counts = count_events(bids_path)

    _check_counts(counts, events, event_id, subjects=['01'], tasks=['task1'])
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})