Exemplo n.º 1
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)
Exemplo n.º 2
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)
Exemplo n.º 3
0
def run_forward(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_evoked = bids_path.copy().update(suffix='ave')
    fname_trans = bids_path.copy().update(suffix='trans')
    fname_fwd = bids_path.copy().update(suffix='fwd')

    msg = f'Input: {fname_evoked}, Output: {fname_fwd}'
    logger.info(
        gen_log_message(message=msg, step=10, subject=subject,
                        session=session))

    # Retrieve the head -> MRI transformation matrix from the MRI sidecar file
    # in the input data, and save it to an MNE "trans" file in the derivatives
    # folder.
    trans = get_head_mri_trans(bids_path.copy().update(
        run=config.get_runs()[0], 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)
def run_group_average_source(*, cfg, subject='average'):
    """Run group average in source space"""

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

    with config.get_parallel_backend():
        parallel, run_func, _ = parallel_func(morph_stc,
                                              n_jobs=config.get_n_jobs())
        all_morphed_stcs = parallel(
            run_func(cfg=cfg,
                     subject=subject,
                     fs_subject=config.get_fs_subject(subject),
                     session=session)
            for subject, session in itertools.product(config.get_subjects(),
                                                      config.get_sessions()))
        mean_morphed_stcs = np.array(all_morphed_stcs).mean(axis=0)

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

        run_average(cfg=cfg,
                    session=session,
                    mean_morphed_stcs=mean_morphed_stcs)
Exemplo n.º 5
0
def run_recon(root_dir, subject, fs_bids_app) -> None:
    logger.info(f"Running recon-all on subject {subject}. This will take "
                f"a LONG time – it's a good idea to let it run over night.")

    subjects_dir = Path(config.get_fs_subjects_dir())
    subj_dir = subjects_dir / f"sub-{subject}"

    if subj_dir.exists():
        logger.info(f"Subject {subject} is already present. Please delete the "
                    f"directory if you want to recompute.")
        return

    env = os.environ
    if 'FREESURFER_HOME' not in env:
        raise RuntimeError("FreeSurfer is not available.")

    license_file = Path(f"{env['FREESURFER_HOME']}/license.txt")
    if not license_file.exists():
        license_file = Path(f"{env['FREESURFER_HOME']}/.license")
    if not license_file.exists():
        raise RuntimeError("FreeSurfer license file not found.")

    cmd = [
        f"{sys.executable}",
        f"{fs_bids_app}",
        f"{root_dir}",
        f"{subjects_dir}", "participant",
        "--n_cpus=2", "--stages=all", "--skip_bids_validator",
        f"--license_file={license_file}",
        f"--participant_label={subject}"
    ]
    logger.debug("Running: " + " ".join(cmd))
    run_subprocess(cmd, env=env, verbose=logger.level)
def run_group_average_source(*, cfg, subject='average'):
    """Run group average in source space"""
    if not config.run_source_estimation:
        msg = '    … skipping: run_source_estimation is set to False.'
        logger.info(**gen_log_kwargs(message=msg))
        return

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

    parallel, run_func, _ = parallel_func(morph_stc,
                                          n_jobs=config.get_n_jobs())
    all_morphed_stcs = parallel(
        run_func(cfg=cfg,
                 subject=subject,
                 fs_subject=config.get_fs_subject(subject),
                 session=session) for subject, session in itertools.product(
                     config.get_subjects(), config.get_sessions()))
    mean_morphed_stcs = np.array(all_morphed_stcs).mean(axis=0)

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

    run_average(cfg=cfg, session=session, mean_morphed_stcs=mean_morphed_stcs)
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))
def main():
    # Ensure we're also processing fsaverage if present
    subjects = config.get_subjects()
    if (Path(config.get_fs_subjects_dir()) / 'fsaverage').exists():
        subjects.append('fsaverage')

    parallel, run_func, _ = parallel_func(make_coreg_surfaces,
                                          n_jobs=config.get_n_jobs())

    parallel(run_func(get_config(), subject) for subject in subjects)
Exemplo n.º 9
0
def get_config(subject: Optional[str] = None,
               session: Optional[str] = None) -> BunchConst:
    cfg = BunchConst(
        fs_subject=config.get_fs_subject(subject=subject),
        fs_subjects_dir=config.get_fs_subjects_dir(),
        recreate_bem=config.recreate_bem,
        bem_mri_images=config.bem_mri_images,
        recreate_scalp_surface=config.recreate_scalp_surface,
        interactive=config.interactive,
    )
    return cfg
Exemplo n.º 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))
Exemplo n.º 11
0
def get_config(subject: Optional[str] = None,
               session: Optional[str] = None) -> SimpleNamespace:
    # Deal with configurations where `deriv_root` was specified, but not
    # `fs_subjects_dir`. We normally raise an exception in this case in
    # `get_fs_subjects_dir()`. However, in situations where users only run the
    # sensor-space scripts, we never call this function, so everything works
    # totally fine at first (which is expected). Yet, when creating the
    # reports, the pipeline would fail with an exception – which is
    # unjustified, as it would not make sense to force users to provide an
    # `fs_subjects_dir` if they don't care about source analysis anyway! So
    # simply assign a dummy value in such cases.
    # `get_fs_subject()` calls `get_fs_subjects_dir()`, so take care of this
    # too.
    try:
        fs_subjects_dir = config.get_fs_subjects_dir()
    except ValueError:
        fs_subjects_dir = None
        fs_subject = None
    else:
        fs_subject = config.get_fs_subject(subject=subject)

    cfg = SimpleNamespace(
        task=config.get_task(),
        runs=config.get_runs(subject=subject),
        datatype=config.get_datatype(),
        acq=config.acq,
        rec=config.rec,
        space=config.space,
        proc=config.proc,
        analyze_channels=config.analyze_channels,
        process_er=config.process_er,
        find_noisy_channels_meg=config.find_noisy_channels_meg,
        h_freq=config.h_freq,
        spatial_filter=config.spatial_filter,
        ica_reject=config.ica_reject,
        conditions=config.conditions,
        contrasts=config.contrasts,
        time_frequency_conditions=config.time_frequency_conditions,
        decode=config.decode,
        decoding_metric=config.decoding_metric,
        n_boot=config.n_boot,
        inverse_method=config.inverse_method,
        fs_subject=fs_subject,
        fs_subjects_dir=fs_subjects_dir,
        deriv_root=config.get_deriv_root(),
        bids_root=config.get_bids_root(),
        use_template_mri=config.use_template_mri,
        interactive=config.interactive,
        plot_psd_for_runs=config.plot_psd_for_runs,
    )
    return cfg
def get_config() -> BunchConst:
    cfg = BunchConst(
        task=config.get_task(),
        datatype=config.get_datatype(),
        acq=config.acq,
        rec=config.rec,
        space=config.space,
        proc=config.proc,
        conditions=config.conditions,
        inverse_method=config.inverse_method,
        fs_subjects_dir=config.get_fs_subjects_dir(),
        deriv_root=config.get_deriv_root(),
    )
    return cfg
Exemplo n.º 13
0
def main() -> None:
    """Run freesurfer recon-all command on BIDS dataset.

    The script allows to run the freesurfer recon-all
    command on all subjects of your BIDS dataset. It can
    run in parallel with the --n_jobs parameter.

    It is built on top of the FreeSurfer BIDS app:

    https://github.com/BIDS-Apps/freesurfer

    and the MNE BIDS Pipeline

    https://mne.tools/mne-bids-pipeline

    You must have freesurfer available on your system.

    Run via the MNE BIDS Pipeline's `run.py`:

    python run.py --steps=freesurfer --config=your_pipeline_config.py

    """  # noqa

    logger.info('Running FreeSurfer')

    subjects = config.get_subjects()
    root_dir = config.get_bids_root()
    subjects_dir = Path(config.get_fs_subjects_dir())
    subjects_dir.mkdir(parents=True, exist_ok=True)

    with config.get_parallel_backend():
        n_jobs = config.get_n_jobs()
        parallel, run_func, _ = parallel_func(run_recon, n_jobs=n_jobs)
        parallel(run_func(root_dir, subject, fs_bids_app)
                 for subject in subjects)

        # Handle fsaverage
        fsaverage_dir = subjects_dir / 'fsaverage'
        if fsaverage_dir.exists():
            if fsaverage_dir.is_symlink():
                fsaverage_dir.unlink()
            else:
                shutil.rmtree(fsaverage_dir)

        env = os.environ
        shutil.copytree(f"{env['FREESURFER_HOME']}/subjects/fsaverage",
                        subjects_dir / 'fsaverage')
def morph_stc(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,
                         datatype=config.get_datatype(),
                         root=config.deriv_root,
                         check=False)

    fs_subject = config.get_fs_subject(subject)
    fs_subjects_dir = config.get_fs_subjects_dir()

    morphed_stcs = []

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

    for condition in conditions:
        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 = bids_path.copy().update(
            suffix=f'{cond_str}+{inverse_str}+{hemi_str}')
        fname_stc_fsaverage = bids_path.copy().update(
            suffix=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}')

        stc = mne.read_source_estimate(fname_stc)
        morph = mne.compute_source_morph(stc,
                                         subject_from=fs_subject,
                                         subject_to='fsaverage',
                                         subjects_dir=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
def make_bem(subject):
    fs_subject = config.get_fs_subject(subject)
    fs_subjects_dir = config.get_fs_subjects_dir()
    mri_dir = Path(fs_subjects_dir) / fs_subject / 'mri'
    bem_dir = Path(fs_subjects_dir) / fs_subject / 'bem'
    watershed_bem_dir = bem_dir / 'watershed'
    flash_bem_dir = bem_dir / 'flash'
    flash_dir = mri_dir / 'flash' / 'parameter_maps'
    show = True if config.interactive else False

    if config.bem_mri_images == 'FLASH' and not flash_dir.exists():
        raise RuntimeError('Cannot locate FLASH MRI images.')
    elif config.bem_mri_images == 'FLASH':
        mri_images = 'FLASH'
    elif config.bem_mri_images == 'auto' and flash_dir.exists():
        mri_images = 'FLASH'
    else:
        mri_images = 'T1'

    if ((mri_images == 'FLASH' and flash_bem_dir.exists()) or
            (mri_images == 'T1' and watershed_bem_dir.exists())):
        msg = 'Found existing BEM surfaces. '
        if config.recreate_bem:
            msg += 'Overwriting as requested in configuration.'
            logger.info(gen_log_message(step=10, message=msg))
        else:
            msg = 'Skipping surface extraction as requested in configuration.'
            logger.info(gen_log_message(step=10, message=msg))
            return

    if mri_images == 'FLASH':
        msg = 'Creating BEM surfaces from FLASH MRI images'
        bem_func = mne.bem.make_flash_bem
    else:
        msg = ('Creating BEM surfaces from T1-weighted MRI images using '
               'watershed algorithm')
        bem_func = mne.bem.make_watershed_bem

    logger.info(gen_log_message(step=10, message=msg))
    bem_func(subject=fs_subject,
             subjects_dir=fs_subjects_dir,
             copy=True,
             overwrite=True,
             show=show)
Exemplo n.º 16
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))

    deriv_path = config.deriv_root

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

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

        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_avg = op.join(
            deriv_path, '_'.join([
                'average', bids_basename, 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))
Exemplo n.º 17
0
def get_config(subject: Optional[str] = None,
               session: Optional[str] = None) -> SimpleNamespace:
    cfg = SimpleNamespace(
        task=config.get_task(),
        runs=config.get_runs(subject=subject),
        datatype=config.get_datatype(),
        acq=config.acq,
        rec=config.rec,
        space=config.space,
        mindist=config.mindist,
        spacing=config.spacing,
        use_template_mri=config.use_template_mri,
        source_info_path_update=config.source_info_path_update,
        ch_types=config.ch_types,
        fs_subject=config.get_fs_subject(subject=subject),
        fs_subjects_dir=config.get_fs_subjects_dir(),
        deriv_root=config.get_deriv_root(),
        bids_root=config.get_bids_root(),
        n_jobs=config.get_n_jobs())
    return cfg
Exemplo n.º 18
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
Exemplo n.º 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 = 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
def get_config(
    subject: Optional[str] = None,
    session: Optional[str] = None
) -> BunchConst:
    cfg = BunchConst(
        task=config.get_task(),
        runs=config.get_runs(subject=subject),
        datatype=config.get_datatype(),
        acq=config.acq,
        rec=config.rec,
        space=config.space,
        mindist=config.mindist,
        spacing=config.spacing,
        use_template_mri=config.use_template_mri,
        ch_types=config.ch_types,
        fs_subject=config.get_fs_subject(subject=subject),
        fs_subjects_dir=config.get_fs_subjects_dir(),
        deriv_root=config.get_deriv_root(),
        bids_root=config.get_bids_root(),
        n_jobs=config.get_n_jobs()
    )
    return cfg
def get_config() -> BunchConst:
    cfg = BunchConst(subjects_dir=config.get_fs_subjects_dir())
    return cfg
Exemplo n.º 22
0
def run_report(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_trans = bids_path.copy().update(suffix='trans')
    subjects_dir = config.get_fs_subjects_dir()
    params = dict(info_fname=fname_ave, raw_psd=True)

    if op.exists(fname_trans):
        params['subject'] = subject
        params['subjects_dir'] = subjects_dir

    rep = mne.Report(**params)
    rep.parse_folder(fname_ave.fpath.parent, verbose=True)

    # Visualize automated noisy channel detection.
    if config.find_noisy_channels_meg:
        figs, captions = plot_auto_scores(subject=subject, session=session)
        rep.add_figs_to_section(figs=figs,
                                captions=captions,
                                section='Data Quality')

    # Visualize events.
    events_fig = plot_events(subject=subject, session=session)
    rep.add_figs_to_section(figs=events_fig,
                            captions='Events in filtered continuous data',
                            section='Events')

    conditions = config.conditions.copy()
    conditions.extend(config.contrasts)
    evokeds = mne.read_evokeds(fname_ave)

    ###########################################################################
    #
    # Visualize evoked responses.
    #
    for condition, evoked in zip(conditions, evokeds):
        if condition in config.conditions:
            caption = f'Condition: {condition}'
            section = 'Evoked'
        else:  # It's a contrast of two conditions.
            caption = f'Contrast: {condition[0]} – {condition[1]}'
            section = 'Contrast'

        fig = evoked.plot(show=False, gfp=True, spatial_colors=True)
        rep.add_figs_to_section(figs=fig,
                                captions=caption,
                                comments=evoked.comment,
                                section=section)

    ###########################################################################
    #
    # Visualize the coregistration & inverse solutions.
    #
    if op.exists(fname_trans):
        # We can only plot the coregistration if we have a valid 3d backend.
        if mne.viz.get_3d_backend() is not None:
            fig = mne.viz.plot_alignment(evoked.info,
                                         fname_trans,
                                         subject=subject,
                                         subjects_dir=subjects_dir,
                                         meg=True,
                                         dig=True,
                                         eeg=True)
            rep.add_figs_to_section(figs=fig,
                                    captions='Coregistration',
                                    section='Coregistration')
        else:
            msg = ('Cannot render sensor alignment (coregistration) because '
                   'no usable 3d backend was found.')
            logger.warning(
                gen_log_message(message=msg,
                                step=99,
                                subject=subject,
                                session=session))

        for evoked in evokeds:
            msg = f'Rendering inverse solution for {evoked.comment} …'
            logger.info(
                gen_log_message(message=msg,
                                step=99,
                                subject=subject,
                                session=session))

            if condition in config.conditions:
                caption = f'Condition: {condition}'
            else:  # It's a contrast of two conditions.
                # XXX Will change once we process contrasts here too
                continue

            method = config.inverse_method
            cond_str = evoked.comment.replace(op.sep, '').replace('_', '')
            inverse_str = '%s' % 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}')

            if op.exists(str(fname_stc) + "-lh.stc"):
                stc = mne.read_source_estimate(fname_stc, subject)
                _, peak_time = stc.get_peak()

                # Plot using 3d backend if available, and use Matplotlib
                # otherwise.
                if mne.viz.get_3d_backend() is not None:
                    brain = stc.plot(views=['lat'],
                                     hemi='both',
                                     initial_time=peak_time,
                                     backend='mayavi')
                    figs = brain._figures[0]
                    comments = evoked.comment
                    captions = caption
                else:
                    import matplotlib.pyplot as plt
                    fig_lh = plt.figure()
                    fig_rh = plt.figure()

                    brain_lh = stc.plot(views='lat',
                                        hemi='lh',
                                        initial_time=peak_time,
                                        backend='matplotlib',
                                        subjects_dir=subjects_dir,
                                        figure=fig_lh)
                    brain_rh = stc.plot(views='lat',
                                        hemi='rh',
                                        initial_time=peak_time,
                                        subjects_dir=subjects_dir,
                                        backend='matplotlib',
                                        figure=fig_rh)
                    figs = [brain_lh, brain_rh]
                    comments = [
                        f'{evoked.comment} - left hemisphere',
                        f'{evoked.comment} - right hemisphere'
                    ]
                    captions = [f'{caption} - left', f'{caption} - right']

                rep.add_figs_to_section(figs=figs,
                                        captions=captions,
                                        comments=comments,
                                        section='Sources')
                del peak_time

    if config.process_er:
        fig_er_psd = plot_er_psd(subject=subject, session=session)
        rep.add_figs_to_section(figs=fig_er_psd,
                                captions='Empty-Room Power Spectral Density '
                                '(after filtering)',
                                section='Empty-Room')

    fname_report = bids_path.copy().update(suffix='report', extension='.html')
    rep.save(fname=fname_report, open_browser=False, overwrite=True)
Exemplo n.º 23
0
def main():
    """Make reports."""
    msg = 'Running Step 99: Create reports'
    logger.info(gen_log_message(step=99, message=msg))

    parallel, run_func, _ = parallel_func(run_report, n_jobs=config.N_JOBS)
    parallel(
        run_func(subject, session) for subject, session in itertools.product(
            config.get_subjects(), config.get_sessions()))

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

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

    rep = mne.Report(info_fname=evoked_fname,
                     subject='fsaverage',
                     subjects_dir=config.get_fs_subjects_dir())
    evokeds = mne.read_evokeds(evoked_fname)
    subjects_dir = config.get_fs_subjects_dir()

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

    conditions = config.conditions.copy()
    conditions.extend(config.contrasts)

    ###########################################################################
    #
    # Visualize evoked responses.
    #
    for condition, evoked in zip(conditions, evokeds):
        if condition in config.conditions:
            caption = f'Average: {condition}'
            section = 'Evoked'
        else:  # It's a contrast of two conditions.
            caption = f'Average Contrast: {condition[0]} – {condition[1]}'
            section = 'Contrast'

        fig = evoked.plot(show=False, gfp=True, spatial_colors=True)
        fig = evoked.plot(spatial_colors=True, gfp=True, show=False)
        rep.add_figs_to_section(figs=fig,
                                captions=caption,
                                comments=evoked.comment,
                                section=section)

    ###########################################################################
    #
    # Visualize inverse solutions.
    #

    for condition, evoked in zip(conditions, evokeds):
        if condition in config.conditions:
            caption = f'Average: {condition}'
            cond_str = condition.replace(op.sep, '').replace('_', '')
        else:  # It's a contrast of two conditions.
            # XXX Will change once we process contrasts here too
            continue

        section = 'Source'
        fname_stc_avg = evoked_fname.copy().update(
            suffix=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}',
            extension=None)

        if op.exists(str(fname_stc_avg) + "-lh.stc"):
            stc = mne.read_source_estimate(fname_stc_avg, subject='fsaverage')
            _, peak_time = stc.get_peak()

            # Plot using 3d backend if available, and use Matplotlib
            # otherwise.
            if mne.viz.get_3d_backend() is not None:
                brain = stc.plot(views=['lat'],
                                 hemi='both',
                                 initial_time=peak_time,
                                 backend='mayavi',
                                 subjects_dir=subjects_dir)
                figs = brain._figures[0]
                captions = caption
            else:
                import matplotlib.pyplot as plt
                fig_lh = plt.figure()
                fig_rh = plt.figure()

                brain_lh = stc.plot(views='lat',
                                    hemi='lh',
                                    initial_time=peak_time,
                                    backend='matplotlib',
                                    figure=fig_lh,
                                    subjects_dir=subjects_dir)
                brain_rh = stc.plot(views='lat',
                                    hemi='rh',
                                    initial_time=peak_time,
                                    backend='matplotlib',
                                    figure=fig_rh,
                                    subjects_dir=subjects_dir)
                figs = [brain_lh, brain_rh]
                captions = [f'{caption} - left', f'{caption} - right']

            rep.add_figs_to_section(figs=figs,
                                    captions=captions,
                                    section='Sources')

            del peak_time

    fname_report = evoked_fname.copy().update(task=config.get_task(),
                                              suffix='report',
                                              extension='.html')
    rep.save(fname=fname_report, open_browser=False, overwrite=True)

    msg = 'Completed Step 99: Create reports'
    logger.info(gen_log_message(step=99, message=msg))
Exemplo n.º 24
0
def run_report_average(session: str) -> None:
    # Group report
    import matplotlib.pyplot as plt  # nested import to help joblib

    subject = 'average'
    evoked_fname = 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)

    rep = mne.Report(info_fname=evoked_fname,
                     subject='fsaverage',
                     subjects_dir=config.get_fs_subjects_dir())
    evokeds = mne.read_evokeds(evoked_fname)
    if config.analyze_channels:
        for evoked in evokeds:
            evoked.pick(config.analyze_channels)

    fs_subjects_dir = config.get_fs_subjects_dir()

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

    conditions: List[Condition_T] = list(config.conditions)
    conditions.extend(config.contrasts)

    ###########################################################################
    #
    # Add events end epochs drop log stats.
    #
    add_event_counts(report=rep, session=session)

    ###########################################################################
    #
    # Visualize evoked responses.
    #
    for condition, evoked in zip(conditions, evokeds):
        if condition in config.conditions:
            caption = f'Average: {condition}'
            section = 'Evoked'
        else:  # It's a contrast of two conditions.
            caption = f'Average Contrast: {condition[0]} – {condition[1]}'
            section = 'Contrast'

        fig = evoked.plot(spatial_colors=True, gfp=True, show=False)
        rep.add_figs_to_section(figs=fig,
                                captions=caption,
                                comments=evoked.comment,
                                section=section)

    ###########################################################################
    #
    # Visualize decoding results.
    #
    if config.decode:
        for contrast in config.contrasts:
            cond_1, cond_2 = contrast
            a_vs_b = f'{cond_1}-{cond_2}'.replace(op.sep, '')
            processing = f'{a_vs_b}+{config.decoding_metric}'
            processing = processing.replace('_', '-').replace('-', '')
            fname_decoding_ = (evoked_fname.copy().update(
                processing=processing, suffix='decoding', extension='.mat'))
            decoding_data = loadmat(fname_decoding_)
            del fname_decoding_, processing, a_vs_b

            fig = plot_decoding_scores_gavg(decoding_data)
            caption = f'Time-by-time Decoding: {cond_1} ./. {cond_2}'
            comment = (f'Based on N={decoding_data["N"].squeeze()} subjects. '
                       f'Standard error and confidence interval of the mean '
                       f'were bootstrapped with {config.n_boot} resamples.')
            rep.add_figs_to_section(figs=fig,
                                    captions=caption,
                                    comments=comment,
                                    section='Decoding')
            del decoding_data, cond_1, cond_2, caption, comment

    ###########################################################################
    #
    # Visualize inverse solutions.
    #
    for condition, evoked in zip(conditions, evokeds):
        if condition in config.conditions:
            caption = f'Average: {condition}'
            cond_str = config.sanitize_cond_name(condition)
        else:  # It's a contrast of two conditions.
            # XXX Will change once we process contrasts here too
            continue

        section = 'Source'
        fname_stc_avg = evoked_fname.copy().update(
            suffix=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}',
            extension=None)

        if op.exists(str(fname_stc_avg) + "-lh.stc"):
            stc = mne.read_source_estimate(fname_stc_avg, subject='fsaverage')
            _, peak_time = stc.get_peak()

            # Plot using 3d backend if available, and use Matplotlib
            # otherwise.
            if mne.viz.get_3d_backend() is not None:
                brain = stc.plot(views=['lat'],
                                 hemi='both',
                                 initial_time=peak_time,
                                 backend='pyvista',
                                 time_viewer=True,
                                 show_traces=True,
                                 subjects_dir=fs_subjects_dir)
                brain.toggle_interface()
                figs = brain._renderer.figure
                captions = caption
            else:
                fig_lh = plt.figure()
                fig_rh = plt.figure()

                brain_lh = stc.plot(views='lat',
                                    hemi='lh',
                                    initial_time=peak_time,
                                    backend='matplotlib',
                                    figure=fig_lh,
                                    subjects_dir=fs_subjects_dir)
                brain_rh = stc.plot(views='lat',
                                    hemi='rh',
                                    initial_time=peak_time,
                                    backend='matplotlib',
                                    figure=fig_rh,
                                    subjects_dir=fs_subjects_dir)
                figs = [brain_lh, brain_rh]
                captions = [f'{caption} - left', f'{caption} - right']

            rep.add_figs_to_section(figs=figs,
                                    captions=captions,
                                    section='Sources')

            del peak_time

    fname_report = evoked_fname.copy().update(task=config.get_task(),
                                              suffix='report',
                                              extension='.html')
    rep.save(fname=fname_report, open_browser=False, overwrite=True)

    msg = 'Completed Step 99: Create reports'
    logger.info(gen_log_message(step=99, message=msg))
    plt.close('all')  # close all figures to save memory
Exemplo n.º 25
0
def run_report(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_trans = bids_path.copy().update(suffix='trans')
    fname_epo = bids_path.copy().update(suffix='epo')
    fname_trans = bids_path.copy().update(suffix='trans')
    fname_ica = bids_path.copy().update(suffix='ica')
    fname_decoding = fname_epo.copy().update(suffix='decoding',
                                             extension='.mat')

    fs_subject = config.get_fs_subject(subject)
    fs_subjects_dir = config.get_fs_subjects_dir()

    params: Dict[str, Any] = dict(info_fname=fname_ave, raw_psd=True)
    if op.exists(fname_trans):
        params['subject'] = fs_subject
        params['subjects_dir'] = fs_subjects_dir

    rep = mne.Report(**params)
    rep_kwargs: Dict[str, Any] = dict(data_path=fname_ave.fpath.parent,
                                      verbose=False)
    if not op.exists(fname_trans):
        rep_kwargs['render_bem'] = False

    task = config.get_task()
    if task is not None:
        rep_kwargs['pattern'] = f'*_task-{task}*'
    if mne.viz.get_3d_backend() is not None:
        with mne.viz.use_3d_backend('pyvista'):
            rep.parse_folder(**rep_kwargs)
    else:
        rep.parse_folder(**rep_kwargs)

    # Visualize automated noisy channel detection.
    if config.find_noisy_channels_meg:
        figs, captions = plot_auto_scores(subject=subject, session=session)
        rep.add_figs_to_section(figs=figs,
                                captions=captions,
                                section='Data Quality')

    # Visualize events.
    events_fig = plot_events(subject=subject, session=session)
    rep.add_figs_to_section(figs=events_fig,
                            captions='Events in filtered continuous data',
                            section='Events')

    ###########################################################################
    #
    # Visualize effect of ICA artifact rejection.
    #
    if config.use_ica:
        epochs = mne.read_epochs(fname_epo)
        ica = mne.preprocessing.read_ica(fname_ica)
        fig = ica.plot_overlay(epochs.average(), show=False)
        rep.add_figs_to_section(fig,
                                captions='Evoked response (across all epochs) '
                                'before and after ICA',
                                section='ICA')

    ###########################################################################
    #
    # Visualize evoked responses.
    #
    conditions: List[Condition_T] = list(config.conditions)
    conditions.extend(config.contrasts)
    evokeds = mne.read_evokeds(fname_ave)
    if config.analyze_channels:
        for evoked in evokeds:
            evoked.pick(config.analyze_channels)

    for condition, evoked in zip(conditions, evokeds):
        if condition in config.conditions:
            caption = f'Condition: {condition}'
            section = 'Evoked'
        else:  # It's a contrast of two conditions.
            caption = f'Contrast: {condition[0]} – {condition[1]}'
            section = 'Contrast'

        fig = evoked.plot(spatial_colors=True, gfp=True, show=False)
        rep.add_figs_to_section(figs=fig,
                                captions=caption,
                                comments=evoked.comment,
                                section=section)

    ###########################################################################
    #
    # Visualize decoding results.
    #
    if config.decode:
        epochs = mne.read_epochs(fname_epo)

        for contrast in config.contrasts:
            cond_1, cond_2 = contrast
            a_vs_b = f'{cond_1}-{cond_2}'.replace(op.sep, '')
            processing = f'{a_vs_b}+{config.decoding_metric}'
            processing = processing.replace('_', '-').replace('-', '')
            fname_decoding_ = (fname_decoding.copy().update(
                processing=processing))
            decoding_data = loadmat(fname_decoding_)
            del fname_decoding_, processing, a_vs_b

            fig = plot_decoding_scores(
                times=epochs.times,
                cross_val_scores=decoding_data['scores'],
                metric=config.decoding_metric)

            caption = f'Time-by-time Decoding: {cond_1} ./. {cond_2}'
            comment = (f'{len(epochs[cond_1])} × {cond_1} ./. '
                       f'{len(epochs[cond_2])} × {cond_2}')
            rep.add_figs_to_section(figs=fig,
                                    captions=caption,
                                    comments=comment,
                                    section='Decoding')
            del decoding_data, cond_1, cond_2, caption, comment

        del epochs

    ###########################################################################
    #
    # Visualize the coregistration & inverse solutions.
    #
    evokeds = mne.read_evokeds(fname_ave)

    if op.exists(fname_trans):
        # We can only plot the coregistration if we have a valid 3d backend.
        if mne.viz.get_3d_backend() is not None:
            fig = mne.viz.plot_alignment(evoked.info,
                                         fname_trans,
                                         subject=fs_subject,
                                         subjects_dir=fs_subjects_dir,
                                         meg=True,
                                         dig=True,
                                         eeg=True)
            rep.add_figs_to_section(figs=fig,
                                    captions='Coregistration',
                                    section='Coregistration')
        else:
            msg = ('Cannot render sensor alignment (coregistration) because '
                   'no usable 3d backend was found.')
            logger.warning(
                gen_log_message(message=msg,
                                step=99,
                                subject=subject,
                                session=session))

        for condition, evoked in zip(conditions, evokeds):
            msg = f'Rendering inverse solution for {evoked.comment} …'
            logger.info(
                gen_log_message(message=msg,
                                step=99,
                                subject=subject,
                                session=session))

            if condition in config.conditions:
                full_condition = config.sanitize_cond_name(evoked.comment)
                caption = f'Condition: {full_condition}'
                del full_condition
            else:  # It's a contrast of two conditions.
                # XXX Will change once we process contrasts here too
                continue

            method = config.inverse_method
            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 op.exists(str(fname_stc) + "-lh.stc"):
                stc = mne.read_source_estimate(fname_stc, subject=fs_subject)
                _, peak_time = stc.get_peak()

                # Plot using 3d backend if available, and use Matplotlib
                # otherwise.
                import matplotlib.pyplot as plt

                if mne.viz.get_3d_backend() is not None:
                    brain = stc.plot(views=['lat'],
                                     hemi='split',
                                     initial_time=peak_time,
                                     backend='pyvista',
                                     time_viewer=True,
                                     subjects_dir=fs_subjects_dir)
                    brain.toggle_interface()
                    brain._renderer.plotter.reset_camera()
                    brain._renderer.plotter.subplot(0, 0)
                    brain._renderer.plotter.reset_camera()
                    figs, ax = plt.subplots(figsize=(15, 10))
                    ax.imshow(brain.screenshot(time_viewer=True))
                    ax.axis('off')
                    comments = evoked.comment
                    captions = caption
                else:
                    fig_lh = plt.figure()
                    fig_rh = plt.figure()

                    brain_lh = stc.plot(views='lat',
                                        hemi='lh',
                                        initial_time=peak_time,
                                        backend='matplotlib',
                                        subjects_dir=fs_subjects_dir,
                                        figure=fig_lh)
                    brain_rh = stc.plot(views='lat',
                                        hemi='rh',
                                        initial_time=peak_time,
                                        subjects_dir=fs_subjects_dir,
                                        backend='matplotlib',
                                        figure=fig_rh)
                    figs = [brain_lh, brain_rh]
                    comments = [
                        f'{evoked.comment} - left hemisphere',
                        f'{evoked.comment} - right hemisphere'
                    ]
                    captions = [f'{caption} - left', f'{caption} - right']

                rep.add_figs_to_section(figs=figs,
                                        captions=captions,
                                        comments=comments,
                                        section='Sources')
                del peak_time

    if config.process_er:
        fig_er_psd = plot_er_psd(subject=subject, session=session)
        rep.add_figs_to_section(figs=fig_er_psd,
                                captions='Empty-Room Power Spectral Density '
                                '(after filtering)',
                                section='Empty-Room')

    fname_report = bids_path.copy().update(suffix='report', extension='.html')
    rep.save(fname=fname_report, open_browser=False, overwrite=True)
    import matplotlib.pyplot as plt  # nested import to help joblib
    plt.close('all')  # close all figures to save memory
def get_config() -> SimpleNamespace:
    cfg = SimpleNamespace(subjects_dir=config.get_fs_subjects_dir())
    return cfg
Exemplo n.º 27
0
def run_forward(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_evoked = bids_path.copy().update(suffix='ave')
    fname_trans = bids_path.copy().update(suffix='trans')
    fname_fwd = bids_path.copy().update(suffix='fwd')

    # Generate a head ↔ MRI transformation matrix from the
    # electrophysiological and MRI sidecar files, and save it to an MNE
    # "trans" file in the derivatives folder.
    if config.mri_t1_path_generator is None:
        t1_bids_path = None
    else:
        t1_bids_path = BIDSPath(subject=bids_path.subject,
                                session=bids_path.session,
                                root=config.bids_root)
        t1_bids_path = config.mri_t1_path_generator(t1_bids_path.copy())
        if t1_bids_path.suffix is None:
            t1_bids_path.update(suffix='T1w')
        if t1_bids_path.datatype is None:
            t1_bids_path.update(datatype='anat')

    msg = 'Estimating head ↔ MRI transform'
    logger.info(
        gen_log_message(message=msg, step=10, subject=subject,
                        session=session))

    trans = get_head_mri_trans(bids_path.copy().update(
        run=config.get_runs()[0], root=config.bids_root),
                               t1_bids_path=t1_bids_path)
    mne.write_trans(fname_trans, trans)

    fs_subject = config.get_fs_subject(subject)
    fs_subjects_dir = config.get_fs_subjects_dir()

    # Create the source space.
    msg = 'Creating source space'
    logger.info(
        gen_log_message(message=msg, step=10, subject=subject,
                        session=session))
    src = mne.setup_source_space(subject=fs_subject,
                                 subjects_dir=fs_subjects_dir,
                                 spacing=config.spacing,
                                 add_dist=False,
                                 n_jobs=config.N_JOBS)

    # Calculate the BEM solution.
    # Here we only use a 3-layers BEM only if EEG is available.
    msg = 'Calculating BEM solution'
    logger.info(
        gen_log_message(message=msg, step=10, subject=subject,
                        session=session))

    if 'eeg' in config.ch_types:
        conductivity = (0.3, 0.006, 0.3)
    else:
        conductivity = (0.3, )

    bem_model = mne.make_bem_model(subject=fs_subject,
                                   subjects_dir=fs_subjects_dir,
                                   ico=4,
                                   conductivity=conductivity)
    bem_sol = mne.make_bem_solution(bem_model)

    # Finally, calculate and save the forward solution.
    msg = 'Calculating forward solution'
    logger.info(
        gen_log_message(message=msg, step=10, subject=subject,
                        session=session))
    info = mne.io.read_info(fname_evoked)
    fwd = mne.make_forward_solution(info,
                                    trans=trans,
                                    src=src,
                                    bem=bem_sol,
                                    mindist=config.mindist)
    mne.write_forward_solution(fname_fwd, fwd, overwrite=True)