예제 #1
0
def test_sensors_inside_bem():
    """Test that sensors inside the BEM are problematic."""
    rr = _get_ico_surface(1)['rr']
    rr /= np.linalg.norm(rr, axis=1, keepdims=True)
    rr *= 0.1
    assert len(rr) == 42
    info = create_info(len(rr), 1000., 'mag')
    info['dev_head_t'] = Transform('meg', 'head', np.eye(4))
    for ii, ch in enumerate(info['chs']):
        ch['loc'][:] = np.concatenate((rr[ii], np.eye(3).ravel()))
    trans = Transform('head', 'mri', np.eye(4))
    trans['trans'][2, 3] = 0.03
    sphere_noshell = make_sphere_model((0., 0., 0.), None)
    sphere = make_sphere_model((0., 0., 0.), 1.01)
    with pytest.raises(RuntimeError, match='.* 15 MEG.*inside the scalp.*'):
        make_forward_solution(info, trans, fname_src, fname_bem)
    make_forward_solution(info, trans, fname_src, fname_bem_meg)  # okay
    make_forward_solution(info, trans, fname_src, sphere_noshell)  # okay
    with pytest.raises(RuntimeError, match='.* 42 MEG.*outermost sphere sh.*'):
        make_forward_solution(info, trans, fname_src, sphere)
    sphere = make_sphere_model((0., 0., 2.0), 1.01)  # weird, but okay
    make_forward_solution(info, trans, fname_src, sphere)
    for ch in info['chs']:
        ch['loc'][:3] *= 0.1
    with pytest.raises(RuntimeError, match='.* 42 MEG.*the inner skull.*'):
        make_forward_solution(info, trans, fname_src, fname_bem_meg)
예제 #2
0
def gen_ras_to_head_trans(head_to_mri_t, t1_img):
    # RAS -> VOXEL
    ras_to_vox_t = Transform(fro='ras',
                             to='mri_voxel',
                             trans=np.linalg.inv(t1_img.header.get_vox2ras()))

    # VOXEL -> MRI
    vox_to_mri_t = Transform(fro='mri_voxel',
                             to='mri',
                             trans=t1_img.header.get_vox2ras_tkr())

    # MRI -> HEAD
    mri_to_head_t = invert_transform(head_to_mri_t)

    # Now we have generated all the required transformations
    # to go from RAS to MNE Head coordinates. Let's combine
    # the transforms into a single transform. This requires
    # two calls to `combine_transforms()`.

    # RAS -> MRI
    ras_to_mri_t = combine_transforms(ras_to_vox_t,
                                      vox_to_mri_t,
                                      fro='ras',
                                      to='mri')

    # RAS -> HEAD
    ras_to_head_t = combine_transforms(ras_to_mri_t,
                                       mri_to_head_t,
                                       fro='ras',
                                       to='head')

    return ras_to_head_t
예제 #3
0
def make_static_trans(subj):
    from mne.transforms import Transform
    fro = 4
    to = 5
    trans_mat = np.array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.],
                          [0., 0., 0., 1.]])
    trans = Transform(fro, to, trans_mat)
    fname_trans = op.join(study_path, 'source_stim', subj, 'source_files',
                          'orig', '%s_static-trans.fif' % subj)
    trans.save(fname_trans)
예제 #4
0
def _create_eeg_el(ch, t=None):
    """Create an electrode definition, transform coords if necessary."""
    if ch['kind'] != FIFF.FIFFV_EEG_CH:
        raise RuntimeError('%s is not an EEG channel. Cannot create an '
                           'electrode definition.' % ch['ch_name'])
    if t is None:
        t = Transform('head', 'head')  # identity, no change
    if t.from_str != 'head':
        raise RuntimeError('Inappropriate coordinate transformation')

    r0ex = _loc_to_eeg_loc(ch['loc'])
    if r0ex.shape[1] == 1:  # no reference
        w = np.array([1.])
    else:  # has reference
        w = np.array([1., -1.])

    # Optional coordinate transformation
    r0ex = apply_trans(t['trans'], r0ex.T)

    # The electrode location
    cosmag = r0ex.copy()
    _normalize_vectors(cosmag)
    res = dict(chname=ch['ch_name'],
               coil_class=FIFF.FWD_COILC_EEG,
               w=w,
               accuracy=_accuracy_dict['normal'],
               type=ch['coil_type'],
               coord_frame=t['to'],
               rmag=r0ex,
               cosmag=cosmag)
    return res
예제 #5
0
def map_ch_coords_to_mne(inst):
    """Transform sensors to MNE coordinates

    .. note::
        operates in place

    .. warning::
        For several reasons we do not use the MNE coordinates for the inverse
        modeling. This however won't always play nicely with visualization.

    Parameters
    ----------
    inst :  MNE data containers
        Raw, Epochs, Evoked.
    """
    bti_dev_t = Transform('ctf_meg', 'meg', _get_bti_dev_t())
    dev_ctf_t = inst.info['dev_ctf_t']
    for ch in inst.info['chs']:
        loc = ch['loc'][:]
        if loc is not None:
            logger.debug('converting %s' % ch['ch_name'])
            t = _loc_to_coil_trans(loc)
            t = _convert_coil_trans(t, dev_ctf_t, bti_dev_t)
            loc = _coil_trans_to_loc(t)
            ch['loc'] = loc
예제 #6
0
def test_use_coil_def(tmp_path):
    """Test use_coil_def."""
    info = create_info(1, 1000., 'mag')
    info['chs'][0]['coil_type'] = 9999
    info['chs'][0]['loc'][:] = [0, 0, 0.02, 1, 0, 0, 0, 1, 0, 0, 0, 1]
    sphere = make_sphere_model((0., 0., 0.), 0.01)
    src = setup_volume_source_space(pos=5, sphere=sphere)
    trans = Transform('head', 'mri', None)
    with pytest.raises(RuntimeError, match='coil definition not found'):
        make_forward_solution(info, trans, src, sphere)
    coil_fname = tmp_path / 'coil_def.dat'
    with open(coil_fname, 'w') as fid:
        fid.write("""# custom cube coil def
1   9999    2   8  3e-03  0.000e+00     "Test"
  0.1250 -0.750e-03 -0.750e-03 -0.750e-03  0.000  0.000""")
    with pytest.raises(RuntimeError, match='Could not interpret'):
        with use_coil_def(coil_fname):
            make_forward_solution(info, trans, src, sphere)
    with open(coil_fname, 'w') as fid:
        fid.write("""# custom cube coil def
1   9999    2   8  3e-03  0.000e+00     "Test"
  0.1250 -0.750e-03 -0.750e-03 -0.750e-03  0.000  0.000  1.000
  0.1250 -0.750e-03  0.750e-03 -0.750e-03  0.000  0.000  1.000
  0.1250  0.750e-03 -0.750e-03 -0.750e-03  0.000  0.000  1.000
  0.1250  0.750e-03  0.750e-03 -0.750e-03  0.000  0.000  1.000
  0.1250 -0.750e-03 -0.750e-03  0.750e-03  0.000  0.000  1.000
  0.1250 -0.750e-03  0.750e-03  0.750e-03  0.000  0.000  1.000
  0.1250  0.750e-03 -0.750e-03  0.750e-03  0.000  0.000  1.000
  0.1250  0.750e-03  0.750e-03  0.750e-03  0.000  0.000  1.000""")
    with use_coil_def(coil_fname):
        make_forward_solution(info, trans, src, sphere)
예제 #7
0
def get_aligned_artifacts(info=None, trans=None, subject=None, subjects_dir=None,
                          coord_frame='mri', head_surf=None):
    head_mri_t, _ = _get_trans(trans, 'head', 'mri')
    dev_head_t, _ = _get_trans(info['dev_head_t'], 'meg', 'head')
    head_trans = head_mri_t
    mri_trans = Transform('mri', 'mri')

    mri_fiducials = mne.coreg.get_mni_fiducials(subject, subjects_dir)
    fid_loc = _fiducial_coords(mri_fiducials, FIFF.FIFFV_COORD_MRI)
    fid_loc = apply_trans(mri_trans, fid_loc)
    fid_loc = pd.DataFrame(fid_loc, index=[fid["ident"]._name.split("_")[-1] for fid in mri_fiducials],
                           columns=["x", "y", "z"])

    if head_surf is None:
        subject_dir = Path(get_subjects_dir(subjects_dir, raise_error=True)) / subject
        fname = subject_dir / 'bem' / 'sample-head.fif'
        head_surf = read_bem_surfaces(fname)[0]
        head_surf = transform_surface_to(head_surf, coord_frame, [mri_trans, head_trans], copy=True)

    eeg_picks = mne.pick_types(info, meg=False, eeg=True, ref_meg=False)
    eeg_loc = np.array([info['chs'][k]['loc'][:3] for k in eeg_picks])
    eeg_loc = apply_trans(head_trans, eeg_loc)
    eegp_loc = _project_onto_surface(eeg_loc, head_surf, project_rrs=True, return_nn=True)[2]
    eegp_loc = pd.DataFrame(eegp_loc, index=[ch["ch_name"] for ch in info['chs']], columns=["x", "y", "z"])

    return eegp_loc, fid_loc, head_surf
예제 #8
0
def test_repr():
    """Test Info repr."""
    info = create_info(1, 1000, 'eeg')
    assert '7 non-empty values' in repr(info)

    t = Transform(1, 2, np.ones((4, 4)))
    info['dev_head_t'] = t
    assert 'dev_head_t: MEG device -> isotrak transform' in repr(info)
예제 #9
0
def test_transforms():
    """Test transformations."""
    bti_trans = (0.0, 0.02, 0.11)
    bti_dev_t = Transform('ctf_meg', 'meg', _get_bti_dev_t(0.0, bti_trans))
    for pdf, config, hs, in zip(pdf_fnames, config_fnames, hs_fnames):
        raw = read_raw_bti(pdf, config, hs, preload=False)
        dev_ctf_t = raw.info['dev_ctf_t']
        dev_head_t_old = raw.info['dev_head_t']
        ctf_head_t = raw.info['ctf_head_t']

        # 1) get BTI->Neuromag
        bti_dev_t = Transform('ctf_meg', 'meg', _get_bti_dev_t(0.0, bti_trans))

        # 2) get Neuromag->BTI head
        t = combine_transforms(invert_transform(bti_dev_t), dev_ctf_t, 'meg',
                               'ctf_head')
        # 3) get Neuromag->head
        dev_head_t_new = combine_transforms(t, ctf_head_t, 'meg', 'head')

        assert_array_equal(dev_head_t_new['trans'], dev_head_t_old['trans'])
예제 #10
0
def _prepare_trans(info, trans, coord_frame='head'):
    head_mri_t = _ensure_trans(trans, 'head', 'mri')
    dev_head_t = info['dev_head_t']
    del trans

    # Figure out our transformations
    if coord_frame == 'meg':
        head_trans = invert_transform(dev_head_t)
        meg_trans = Transform('meg', 'meg')
        mri_trans = invert_transform(
            combine_transforms(dev_head_t, head_mri_t, 'meg', 'mri'))
    elif coord_frame == 'mri':
        head_trans = head_mri_t
        meg_trans = combine_transforms(dev_head_t, head_mri_t, 'meg', 'mri')
        mri_trans = Transform('mri', 'mri')
    else:  # coord_frame == 'head'
        head_trans = Transform('head', 'head')
        meg_trans = info['dev_head_t']
        mri_trans = invert_transform(head_mri_t)
    return head_trans, meg_trans, mri_trans
예제 #11
0
def gen_ras_to_head_trans(head_to_mri_t, t1_img):
    mri_to_head_t = invert_transform(head_to_mri_t)

    # RAS <> VOXEL
    ras_to_vox_t = Transform(fro='ras', to='mri_voxel',
                             trans=np.linalg.inv(t1_img.header.get_vox2ras()))
    #  trans=t1_img.header.get_ras2vox())
    vox_to_mri_t = Transform(fro='mri_voxel', to='mri',
                             trans=t1_img.header.get_vox2ras_tkr())

    # RAS <> MRI
    ras_to_mri_t = combine_transforms(ras_to_vox_t,
                                      vox_to_mri_t,
                                      fro='ras', to='mri')

    ras_to_head_t = combine_transforms(ras_to_mri_t,
                                       mri_to_head_t,
                                       fro='ras', to='head')

    return ras_to_head_t
예제 #12
0
def test_nan_trans():
    """Test unlikely case that the device to head transform is empty."""
    for ii, pdf_fname in enumerate(pdf_fnames):
        bti_info = _read_bti_header(pdf_fname,
                                    config_fnames[ii],
                                    sort_by_ch_name=True)

        dev_ctf_t = Transform('ctf_meg', 'ctf_head',
                              _correct_trans(bti_info['bti_transform'][0]))

        # reading params
        convert = True
        rotation_x = 0.
        translation = (0.0, 0.02, 0.11)
        bti_dev_t = _get_bti_dev_t(rotation_x, translation)
        bti_dev_t = Transform('ctf_meg', 'meg', bti_dev_t)
        ecg_ch = 'E31'
        eog_ch = ('E63', 'E64')

        # read parts of info to get trans
        bti_ch_names = list()
        for ch in bti_info['chs']:
            ch_name = ch['name']
            if not ch_name.startswith('A'):
                ch_name = ch.get('chan_label', ch_name)
            bti_ch_names.append(ch_name)

        neuromag_ch_names = _rename_channels(bti_ch_names,
                                             ecg_ch=ecg_ch,
                                             eog_ch=eog_ch)
        ch_mapping = zip(bti_ch_names, neuromag_ch_names)

        # add some nan in some locations!
        dev_ctf_t['trans'][:, 3] = np.nan
        _check_nan_dev_head_t(dev_ctf_t)
        for idx, (chan_4d, chan_neuromag) in enumerate(ch_mapping):
            loc = bti_info['chs'][idx]['loc']
            if loc is not None:
                if convert:
                    t = _loc_to_coil_trans(bti_info['chs'][idx]['loc'])
                    t = _convert_coil_trans(t, dev_ctf_t, bti_dev_t)
예제 #13
0
def transform_sensors_to_mne(inst):
    """ Transform sensors to MNE coordinates

    For several reasons we do not use the MNE coordinates for the inverse
    modeling. This however won't always play nicely with visualization.

    """
    bti_dev_t = Transform('ctf_meg', 'meg', _get_bti_dev_t())
    dev_ctf_t = inst.info['dev_ctf_t']
    for ch in inst.info['chs']:
        loc = ch['loc'][:]
        if loc is not None:
            print('converting %s' % ch['ch_name'])
            t = _loc_to_coil_trans(loc)
            t = _convert_coil_trans(t, dev_ctf_t, bti_dev_t)
            loc = _coil_trans_to_loc(t)
            ch['loc'] = loc
예제 #14
0
def test_info_bad():
    """Test our info sanity checkers."""
    info = create_info(2, 1000., 'eeg')
    info['description'] = 'foo'
    info['experimenter'] = 'bar'
    info['line_freq'] = 50.
    info['bads'] = info['ch_names'][:1]
    info['temp'] = ('whatever', 1.)
    # After 0.24 these should be pytest.raises calls
    check, klass = pytest.raises, RuntimeError
    with check(klass, match=r"info\['temp'\]"):
        info['bad_key'] = 1.
    for (key, match) in ([('sfreq', r'inst\.resample'),
                          ('chs', r'inst\.add_channels')]):
        with check(klass, match=match):
            info[key] = info[key]
    with pytest.raises(ValueError, match='between meg<->head'):
        info['dev_head_t'] = Transform('mri', 'head', np.eye(4))
예제 #15
0
def test_snapshot_brain_montage(renderer):
    """Test snapshot brain montage."""
    info = read_info(evoked_fname)
    fig = plot_alignment(
        info, trans=Transform('head', 'mri'), subject='sample',
        subjects_dir=subjects_dir)

    xyz = np.vstack([ich['loc'][:3] for ich in info['chs']])
    ch_names = [ich['ch_name'] for ich in info['chs']]
    xyz_dict = dict(zip(ch_names, xyz))
    xyz_dict[info['chs'][0]['ch_name']] = [1, 2]  # Set one ch to only 2 vals

    # Make sure wrong types are checked
    pytest.raises(TypeError, snapshot_brain_montage, fig, xyz)

    # All chs must have 3 position values
    pytest.raises(ValueError, snapshot_brain_montage, fig, xyz_dict)

    # Make sure we raise error if the figure has no scene
    pytest.raises(ValueError, snapshot_brain_montage, None, info)
예제 #16
0
def test_coregister_fiducials():
    """Test coreg.coregister_fiducials()"""
    # prepare head and MRI fiducials
    trans = Transform('head', 'mri',
                      rotation(.4, .1, 0).dot(translation(.1, -.1, .1)))
    coords_orig = np.array([[-0.08061612, -0.02908875, -0.04131077],
                            [0.00146763, 0.08506715, -0.03483611],
                            [0.08436285, -0.02850276, -0.04127743]])
    coords_trans = apply_trans(trans, coords_orig)

    def make_dig(coords, cf):
        return ({'coord_frame': cf, 'ident': 1, 'kind': 1, 'r': coords[0]},
                {'coord_frame': cf, 'ident': 2, 'kind': 1, 'r': coords[1]},
                {'coord_frame': cf, 'ident': 3, 'kind': 1, 'r': coords[2]})

    mri_fiducials = make_dig(coords_trans, FIFF.FIFFV_COORD_MRI)
    info = {'dig': make_dig(coords_orig, FIFF.FIFFV_COORD_HEAD)}

    # test coregister_fiducials()
    trans_est = coregister_fiducials(info, mri_fiducials)
    assert_equal(trans_est.from_str, trans.from_str)
    assert_equal(trans_est.to_str, trans.to_str)
    assert_array_almost_equal(trans_est['trans'], trans['trans'])
예제 #17
0
def test_plot_alignment_basic(tmpdir, renderer, mixed_fwd_cov_evoked):
    """Test plotting of -trans.fif files and MEG sensor layouts."""
    # generate fiducials file for testing
    tempdir = str(tmpdir)
    fiducials_path = op.join(tempdir, 'fiducials.fif')
    fid = [{
        'coord_frame': 5,
        'ident': 1,
        'kind': 1,
        'r': [-0.08061612, -0.02908875, -0.04131077]
    }, {
        'coord_frame': 5,
        'ident': 2,
        'kind': 1,
        'r': [0.00146763, 0.08506715, -0.03483611]
    }, {
        'coord_frame': 5,
        'ident': 3,
        'kind': 1,
        'r': [0.08436285, -0.02850276, -0.04127743]
    }]
    write_dig(fiducials_path, fid, 5)
    evoked = read_evokeds(evoked_fname)[0]
    info = evoked.info

    sample_src = read_source_spaces(src_fname)
    pytest.raises(TypeError,
                  plot_alignment,
                  'foo',
                  trans_fname,
                  subject='sample',
                  subjects_dir=subjects_dir)
    pytest.raises(OSError,
                  plot_alignment,
                  info,
                  trans_fname,
                  subject='sample',
                  subjects_dir=subjects_dir,
                  src='foo')
    pytest.raises(ValueError,
                  plot_alignment,
                  info,
                  trans_fname,
                  subject='fsaverage',
                  subjects_dir=subjects_dir,
                  src=sample_src)
    sample_src.plot(subjects_dir=subjects_dir,
                    head=True,
                    skull=True,
                    brain='white')
    # mixed source space
    mixed_src = mixed_fwd_cov_evoked[0]['src']
    assert mixed_src.kind == 'mixed'
    plot_alignment(info,
                   meg=['helmet', 'sensors'],
                   dig=True,
                   coord_frame='head',
                   trans=Path(trans_fname),
                   subject='sample',
                   mri_fiducials=fiducials_path,
                   subjects_dir=subjects_dir,
                   src=mixed_src)
    renderer.backend._close_all()
    # no-head version
    renderer.backend._close_all()
    # trans required
    with pytest.raises(ValueError, match='transformation matrix is required'):
        plot_alignment(info, trans=None, src=src_fname)
    with pytest.raises(ValueError, match='transformation matrix is required'):
        plot_alignment(info, trans=None, mri_fiducials=True)
    with pytest.raises(ValueError, match='transformation matrix is required'):
        plot_alignment(info, trans=None, surfaces=['brain'])
    # all coord frames
    plot_alignment(info)  # works: surfaces='auto' default
    for coord_frame in ('meg', 'head', 'mri'):
        fig = plot_alignment(info,
                             meg=['helmet', 'sensors'],
                             dig=True,
                             coord_frame=coord_frame,
                             trans=Path(trans_fname),
                             subject='sample',
                             mri_fiducials=fiducials_path,
                             subjects_dir=subjects_dir,
                             src=src_fname)
    renderer.backend._close_all()
    # EEG only with strange options
    evoked_eeg_ecog_seeg = evoked.copy().pick_types(meg=False, eeg=True)
    evoked_eeg_ecog_seeg.info['projs'] = []  # "remove" avg proj
    evoked_eeg_ecog_seeg.set_channel_types({
        'EEG 001': 'ecog',
        'EEG 002': 'seeg'
    })
    with catch_logging() as log:
        plot_alignment(evoked_eeg_ecog_seeg.info,
                       subject='sample',
                       trans=trans_fname,
                       subjects_dir=subjects_dir,
                       surfaces=['white', 'outer_skin', 'outer_skull'],
                       meg=['helmet', 'sensors'],
                       eeg=['original', 'projected'],
                       ecog=True,
                       seeg=True,
                       verbose=True)
    log = log.getvalue()
    assert 'ecog: 1' in log
    assert 'seeg: 1' in log
    renderer.backend._close_all()

    sphere = make_sphere_model(info=info, r0='auto', head_radius='auto')
    bem_sol = read_bem_solution(
        op.join(subjects_dir, 'sample', 'bem',
                'sample-1280-1280-1280-bem-sol.fif'))
    bem_surfs = read_bem_surfaces(
        op.join(subjects_dir, 'sample', 'bem',
                'sample-1280-1280-1280-bem.fif'))
    sample_src[0]['coord_frame'] = 4  # hack for coverage
    plot_alignment(
        info,
        trans_fname,
        subject='sample',
        eeg='projected',
        meg='helmet',
        bem=sphere,
        dig=True,
        surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin'])
    plot_alignment(info,
                   subject='sample',
                   meg='helmet',
                   subjects_dir=subjects_dir,
                   eeg='projected',
                   bem=sphere,
                   surfaces=['head', 'brain'],
                   src=sample_src)
    # no trans okay, no mri surfaces
    plot_alignment(info, bem=sphere, surfaces=['brain'])
    with pytest.raises(ValueError, match='A head surface is required'):
        plot_alignment(info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       eeg='projected',
                       surfaces=[])
    with pytest.raises(RuntimeError, match='No brain surface found'):
        plot_alignment(info,
                       trans=trans_fname,
                       subject='foo',
                       subjects_dir=subjects_dir,
                       surfaces=['brain'])
    assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI
               for surf in bem_sol['surfs'])
    plot_alignment(info,
                   trans_fname,
                   subject='sample',
                   meg=[],
                   subjects_dir=subjects_dir,
                   bem=bem_sol,
                   eeg=True,
                   surfaces=['head', 'inflated', 'outer_skull', 'inner_skull'])
    assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI
               for surf in bem_sol['surfs'])
    plot_alignment(info,
                   trans_fname,
                   subject='sample',
                   meg=True,
                   subjects_dir=subjects_dir,
                   surfaces=['head', 'inner_skull'],
                   bem=bem_surfs)
    # single-layer BEM can still plot head surface
    assert bem_surfs[-1]['id'] == FIFF.FIFFV_BEM_SURF_ID_BRAIN
    bem_sol_homog = read_bem_solution(
        op.join(subjects_dir, 'sample', 'bem', 'sample-1280-bem-sol.fif'))
    for use_bem in (bem_surfs[-1:], bem_sol_homog):
        with catch_logging() as log:
            plot_alignment(info,
                           trans_fname,
                           subject='sample',
                           meg=True,
                           subjects_dir=subjects_dir,
                           surfaces=['head', 'inner_skull'],
                           bem=use_bem,
                           verbose=True)
        log = log.getvalue()
        assert 'not find the surface for head in the provided BEM model' in log
    # sphere model
    sphere = make_sphere_model('auto', 'auto', info)
    src = setup_volume_source_space(sphere=sphere)
    plot_alignment(
        info,
        trans=Transform('head', 'mri'),
        eeg='projected',
        meg='helmet',
        bem=sphere,
        src=src,
        dig=True,
        surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin'])
    sphere = make_sphere_model('auto', None, info)  # one layer
    # if you ask for a brain surface with a 1-layer sphere model it's an error
    with pytest.raises(RuntimeError, match='Sphere model does not have'):
        fig = plot_alignment(trans=trans_fname,
                             subject='sample',
                             subjects_dir=subjects_dir,
                             surfaces=['brain'],
                             bem=sphere)
    # but you can ask for a specific brain surface, and
    # no info is permitted
    fig = plot_alignment(trans=trans_fname,
                         subject='sample',
                         meg=False,
                         coord_frame='mri',
                         subjects_dir=subjects_dir,
                         surfaces=['white'],
                         bem=sphere,
                         show_axes=True)
    renderer.backend._close_all()
    if renderer._get_3d_backend() == 'mayavi':
        import mayavi  # noqa: F401 analysis:ignore
        assert isinstance(fig, mayavi.core.scene.Scene)
    # 3D coil with no defined draw (ConvexHull)
    info_cube = pick_info(info, np.arange(6))
    info['dig'] = None
    info_cube['chs'][0]['coil_type'] = 9999
    info_cube['chs'][1]['coil_type'] = 9998
    with pytest.raises(RuntimeError, match='coil definition not found'):
        plot_alignment(info_cube, meg='sensors', surfaces=())
    coil_def_fname = op.join(tempdir, 'temp')
    with open(coil_def_fname, 'w') as fid:
        fid.write(coil_3d)
    # make sure our other OPMs can be plotted, too
    for ii, kind in enumerate(
        ('QUSPIN_ZFOPM_MAG', 'QUSPIN_ZFOPM_MAG2', 'FIELDLINE_OPM_MAG_GEN1',
         'KERNEL_OPM_MAG_GEN1'), 2):
        info_cube['chs'][ii]['coil_type'] = getattr(FIFF, f'FIFFV_COIL_{kind}')
    with use_coil_def(coil_def_fname):
        with catch_logging() as log:
            plot_alignment(info_cube,
                           meg='sensors',
                           surfaces=(),
                           dig=True,
                           verbose='debug')
    log = log.getvalue()
    assert 'planar geometry' in log

    # one layer bem with skull surfaces:
    with pytest.raises(RuntimeError, match='Sphere model does not.*boundary'):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       surfaces=['brain', 'head', 'inner_skull'],
                       bem=sphere)
    # wrong eeg value:
    with pytest.raises(ValueError, match='Invalid value for the .eeg'):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       eeg='foo')
    # wrong meg value:
    with pytest.raises(ValueError, match='Invalid value for the .meg'):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       meg='bar')
    # multiple brain surfaces:
    with pytest.raises(ValueError, match='Only one brain surface can be plot'):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       surfaces=['white', 'pial'])
    with pytest.raises(TypeError, match='surfaces.*must be'):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       surfaces=[1])
    with pytest.raises(ValueError, match='Unknown surface type'):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       surfaces=['foo'])
    with pytest.raises(TypeError, match="must be an instance of "):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       surfaces=dict(brain='super clear'))
    with pytest.raises(ValueError, match="must be between 0 and 1"):
        plot_alignment(info=info,
                       trans=trans_fname,
                       subject='sample',
                       subjects_dir=subjects_dir,
                       surfaces=dict(brain=42))
    fwd_fname = op.join(data_dir, 'MEG', 'sample',
                        'sample_audvis_trunc-meg-eeg-oct-4-fwd.fif')
    fwd = read_forward_solution(fwd_fname)
    plot_alignment(subject='sample',
                   subjects_dir=subjects_dir,
                   trans=trans_fname,
                   fwd=fwd,
                   surfaces='white',
                   coord_frame='head')
    fwd = convert_forward_solution(fwd, force_fixed=True)
    plot_alignment(subject='sample',
                   subjects_dir=subjects_dir,
                   trans=trans_fname,
                   fwd=fwd,
                   surfaces='white',
                   coord_frame='head')
    fwd['coord_frame'] = FIFF.FIFFV_COORD_MRI  # check required to get to MRI
    with pytest.raises(ValueError, match='transformation matrix is required'):
        plot_alignment(info, trans=None, fwd=fwd)
    # surfaces as dict
    plot_alignment(subject='sample',
                   coord_frame='head',
                   trans=trans_fname,
                   subjects_dir=subjects_dir,
                   surfaces={
                       'white': 0.4,
                       'outer_skull': 0.6,
                       'head': None
                   })
예제 #18
0
파일: anatomy.py 프로젝트: RPGOne/mne-hcp
def make_mne_anatomy(subject,
                     subjects_dir,
                     recordings_path=None,
                     hcp_path=op.curdir,
                     outputs=('label', 'mri', 'surf')):
    """Extract relevant anatomy and create MNE friendly directory layout

    The function will create the following outputs by default:

    $subjects_dir/$subject/bem/inner_skull.surf
    $subjects_dir/$subject/label/*
    $subjects_dir/$subject/mri/*
    $subjects_dir/$subject/surf/*
    $recordings_path/$subject/$subject-head_mri-trans.fif

    These can then be set as $SUBJECTS_DIR and as MEG directory, consistent
    with MNE examples.

    Parameters
    ----------
    subject : str
        The subject name.
    subjects_dir : str
        The path corresponding to MNE/freesurfer SUBJECTS_DIR (to be created)
    hcp_path : str
        The path where the HCP files can be found.
    outputs : {'label', 'mri', 'stats', 'surf', 'touch'}
        The outputs of the freesrufer pipeline shipped by HCP. Defaults to
        ('mri', 'surf'), the minimum needed to extract MNE-friendly anatomy
        files and data.
    """
    if hcp_path == op.curdir:
        hcp_path = op.realpath(hcp_path)
    if not op.isabs(subjects_dir):
        subjects_dir = op.realpath(subjects_dir)

    this_subjects_dir = op.join(subjects_dir, subject)
    if not op.isabs(recordings_path):
        recordings_path = op.realpath(recordings_path)

    this_recordings_path = op.join(recordings_path, subject)

    if not op.exists(this_recordings_path):
        os.makedirs(this_recordings_path)

    for output in outputs:
        if not op.exists(op.join(this_subjects_dir, output)):
            os.makedirs(op.join(this_subjects_dir, output))
        if output == 'mri':
            for suboutput in ['orig', 'transforms']:
                if not op.exists(op.join(this_subjects_dir, output,
                                         suboutput)):
                    os.makedirs(op.join(this_subjects_dir, output, suboutput))

        files = get_file_paths(subject=subject,
                               data_type='freesurfer',
                               output=output,
                               hcp_path=hcp_path)
        for source in files:
            match = [match for match in re.finditer(subject, source)][-1]
            split_path = source[:match.span()[1] + 1]
            target = op.join(this_subjects_dir, source.split(split_path)[-1])
            if (not op.isfile(target) and not op.islink(target)
                    and op.exists(source)):  # don't link if it's not there.
                if sys.platform != 'win32':
                    os.symlink(source, target)
                else:
                    shutil.copyfile(source, target)

    logger.info('reading extended structural processing ...')

    # Step 1 #################################################################
    # transform head models to expected coordinate system

    # make hcp trans
    transforms_fname = get_file_paths(subject=subject,
                                      data_type='meg_anatomy',
                                      output='transforms',
                                      hcp_path=hcp_path)
    transforms_fname = [
        k for k in transforms_fname if k.endswith('transform.txt')
    ][0]
    hcp_trans = _read_trans_hcp(fname=transforms_fname, convert_to_meter=False)

    # get RAS freesurfer trans
    c_ras_trans_fname = get_file_paths(subject=subject,
                                       data_type='freesurfer',
                                       output='mri',
                                       hcp_path=hcp_path)
    c_ras_trans_fname = [
        k for k in c_ras_trans_fname if k.endswith('c_ras.mat')
    ][0]
    logger.info('reading RAS freesurfer transform')
    # ceci n'est pas un .mat file ...

    with open(op.join(subjects_dir, c_ras_trans_fname)) as fid:
        ras_trans = np.array([r.split() for r in fid.read().split('\n') if r],
                             dtype=np.float64)

    logger.info('Combining RAS transform and coregistration')
    ras_trans_m = linalg.inv(ras_trans)  # and the inversion

    logger.info('extracting head model')
    head_model_fname = get_file_paths(subject=subject,
                                      data_type='meg_anatomy',
                                      output='head_model',
                                      hcp_path=hcp_path)[0]
    pnts, faces = _get_head_model(head_model_fname=head_model_fname)

    logger.info('coregistring head model to MNE-HCP coordinates')
    pnts = apply_trans(ras_trans_m.dot(hcp_trans['bti2spm']), pnts)

    tri_fname = op.join(this_subjects_dir, 'bem', 'inner_skull.surf')
    if not op.exists(op.dirname(tri_fname)):
        os.makedirs(op.dirname(tri_fname))
    write_surface(tri_fname, pnts, faces)

    # Step 2 #################################################################
    # write corresponding device to MRI transform

    logger.info('extracting coregistration')
    # now convert to everything meter too here
    ras_trans_m[:3, 3] *= 1e-3
    bti2spm = hcp_trans['bti2spm']
    bti2spm[:3, 3] *= 1e-3
    head_mri_t = Transform(  # we're lying here for a good purpose
        'head', 'mri', np.dot(ras_trans_m, bti2spm))  # it should be 'ctf_head'
    write_trans(
        op.join(this_recordings_path, '%s-head_mri-trans.fif' % subject),
        head_mri_t)
예제 #19
0
def select_vertices_in_sensor_range(inst,
                                    dist,
                                    info=None,
                                    picks=None,
                                    trans=None,
                                    indices=False,
                                    verbose=None):
    """Find vertices within given distance to a sensor.

    Parameters
    ----------
    inst : instance of Forward | instance of SourceSpaces
        The object to select vertices from.
    dist : float
        The minimum distance between a vertex and the nearest sensor. All
        vertices for which the distance to the nearest sensor exceeds this
        limit are discarded.
    info : instance of Info | None
        The info structure that contains information about the channels. Only
        needs to be specified if the object to select vertices from does is
        an instance of SourceSpaces.
    picks : array-like of int | None
        Indices of sensors to include in the search for the nearest sensor. If
        ``None``, the default, only MEG channels are used.
    trans : str | instance of Transform | None
        Either the full path to the head<->MRI transform ``*-trans.fif`` file
        produced during coregistration, or the Transformation itself. If trans
        is None, an identity matrix is assumed. Only needed when ``inst`` is a
        source space in MRI coordinates.
    indices: False | True
        If ``True``, return vertex indices instead of vertex numbers. Defaults
        to ``False``.
    verbose : bool | str | int | None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).

    Returns
    -------
    vertices : pair of lists | list of int
        Either a list of vertex numbers for the left and right hemisphere (if
        ``indices==False``) or a single list with vertex indices.

    See Also
    --------
    restrict_forward_to_vertices : restrict Forward to the given vertices
    restrict_src_to_vertices : restrict SourceSpaces to the given vertices
    """

    if isinstance(inst, Forward):
        info = inst['info']
        src = inst['src']
    elif isinstance(inst, SourceSpaces):
        src = inst
        if info is None:
            raise ValueError('You need to specify an Info object with '
                             'information about the channels.')

    # Load the head<->MRI transform if necessary
    if src[0]['coord_frame'] == FIFF.FIFFV_COORD_MRI:
        if trans is None:
            raise ValueError('Source space is in MRI coordinates, but no '
                             'head<->MRI transform was given. Please specify '
                             'the full path to the appropriate *-trans.fif '
                             'file as the "trans" parameter.')
        if isinstance(trans, string_types):
            trans = read_trans(trans, return_all=True)
            for trans in trans:  # we got at least 1
                try:
                    trans = _ensure_trans(trans, 'head', 'mri')
                except Exception as exp:
                    pass
                else:
                    break
            else:
                raise exp

        src_trans = invert_transform(_ensure_trans(trans, 'head', 'mri'))
        print('Transform!')
    else:
        src_trans = Transform('head', 'head')  # Identity transform

    dev_to_head = _ensure_trans(info['dev_head_t'], 'meg', 'head')

    if picks is None:
        picks = pick_types(info, meg=True)
        if len(picks) > 0:
            logger.info('Using MEG channels')
        else:
            logger.info('Using EEG channels')
            picks = pick_types(info, eeg=True)

    src_pos = np.vstack([
        apply_trans(src_trans, s['rr'][s['inuse'].astype(np.bool)])
        for s in src
    ])

    sensor_pos = []
    for ch in picks:
        # MEG channels are in device coordinates, translate them to head
        if channel_type(info, ch) in ['mag', 'grad']:
            sensor_pos.append(
                apply_trans(dev_to_head, info['chs'][ch]['loc'][:3]))
        else:
            sensor_pos.append(info['chs'][ch]['loc'][:3])
    sensor_pos = np.array(sensor_pos)

    # Find vertices that are within range of a sensor. We use a KD-tree for
    # speed.
    logger.info('Finding vertices within sensor range...')
    tree = cKDTree(sensor_pos)
    distances, _ = tree.query(src_pos, distance_upper_bound=dist)

    # Vertices out of range are flagged as np.inf
    src_sel = np.isfinite(distances)
    logger.info('[done]')

    if indices:
        return np.flatnonzero(src_sel)
    else:
        n_lh_verts = src[0]['nuse']
        lh_sel, rh_sel = src_sel[:n_lh_verts], src_sel[n_lh_verts:]
        vert_lh = src[0]['vertno'][lh_sel]
        vert_rh = src[1]['vertno'][rh_sel]
        return [vert_lh, vert_rh]
def get_sensor_pos_from_fwd(inst, info=None, picks=None, trans=None):
    from mne import SourceSpaces, Forward
    from mne.io.constants import FIFF
    from six import string_types
    from mne.transforms import read_trans, _ensure_trans, invert_transform, Transform, apply_trans
    from mne.io.pick import channel_type, pick_types

    if isinstance(inst, Forward):
        info = inst['info']
        src = inst['src']
    elif isinstance(inst, SourceSpaces):
        src = inst
        if info is None:
            raise ValueError('You need to specify an Info object with '
                             'information about the channels.')

    # Load the head<->MRI transform if necessary
    if src[0]['coord_frame'] == FIFF.FIFFV_COORD_MRI:
        if trans is None:
            raise ValueError('Source space is in MRI coordinates, but no '
                             'head<->MRI transform was given. Please specify '
                             'the full path to the appropriate *-trans.fif '
                             'file as the "trans" parameter.')
        if isinstance(trans, string_types):
            trans = read_trans(trans, return_all=True)
            for trans in trans:  # we got at least 1
                try:
                    trans = _ensure_trans(trans, 'head', 'mri')
                except Exception as exp:
                    pass
                else:
                    break
            else:
                raise exp

        src_trans = invert_transform(_ensure_trans(trans, 'head', 'mri'))
        print('Transform!')
    else:
        src_trans = Transform('head', 'head')  # Identity transform

    dev_to_head = _ensure_trans(info['dev_head_t'], 'meg', 'head')

    if picks is None:
        picks = pick_types(info, meg=True)
        if len(picks) > 0:
            print('Using MEG channels')
        else:
            print('Using EEG channels')
            picks = pick_types(info, eeg=True)

    sensor_pos = []
    for ch in picks:
        # MEG channels are in device coordinates, translate them to head
        if channel_type(info, ch) in ['mag', 'grad']:
            sensor_pos.append(
                apply_trans(dev_to_head, info['chs'][ch]['loc'][:3]))
        else:
            sensor_pos.append(info['chs'][ch]['loc'][:3])
    sensor_pos = np.array(sensor_pos)

    return sensor_pos
예제 #21
0
if len(sys.argv) != 3:
    print("usage: {} subject $ds".format(sys.argv[0]))
    sys.exit(1)

subject = sys.argv[1]
dsname = sys.argv[2]

try:
    FShome = os.environ['FREESURFER_HOME']
except KeyError:
    print("You must set the FREESURFER_HOME environment variable!")
    sys.exit(1)

try:
    Subjdir = os.environ['SUBJECTS_DIR']
except KeyError:
    Subjdir = op.join(FShome, "subjects")
    print("Note: Using the default SUBJECTS_DIR:", Subjdir)

name = op.join(Subjdir, subject, "bem", "{}-fiducials.fif".format(subject))
fids = read_fiducials(name)
fidc = _fiducial_coords(fids[0])

raw = read_raw_ctf(dsname, clean_names = True, preload = False)
fidd = _fiducial_coords(raw.info['dig'])

xform = fit_matched_points(fidd, fidc, weights = [1, 10, 1])
t = Transform(FIFF.FIFFV_COORD_HEAD, FIFF.FIFFV_COORD_MRI, xform)
name = op.join(Subjdir, subject, "bem", "{}-trans.fif".format(subject))
write_trans(name, t)
예제 #22
0
def test_scale_mri_xfm(tmp_path, few_surfaces, subjects_dir_tmp_few):
    """Test scale_mri transforms and MRI scaling."""
    # scale fsaverage
    tempdir = str(subjects_dir_tmp_few)
    sample_dir = subjects_dir_tmp_few / 'sample'
    subject_to = 'flachkopf'
    spacing = 'oct2'
    for subject_from in ('fsaverage', 'sample'):
        if subject_from == 'fsaverage':
            scale = 1.  # single dim
        else:
            scale = [0.9, 2, .8]  # separate
        src_from_fname = op.join(tempdir, subject_from, 'bem',
                                 '%s-%s-src.fif' % (subject_from, spacing))
        src_from = mne.setup_source_space(subject_from,
                                          spacing,
                                          subjects_dir=tempdir,
                                          add_dist=False)
        write_source_spaces(src_from_fname, src_from)
        vertices_from = np.concatenate([s['vertno'] for s in src_from])
        assert len(vertices_from) == 36
        hemis = ([0] * len(src_from[0]['vertno']) +
                 [1] * len(src_from[0]['vertno']))
        mni_from = mne.vertex_to_mni(vertices_from,
                                     hemis,
                                     subject_from,
                                     subjects_dir=tempdir)
        if subject_from == 'fsaverage':  # identity transform
            source_rr = np.concatenate(
                [s['rr'][s['vertno']] for s in src_from]) * 1e3
            assert_allclose(mni_from, source_rr)
        if subject_from == 'fsaverage':
            overwrite = skip_fiducials = False
        else:
            with pytest.raises(IOError, match='No fiducials file'):
                scale_mri(subject_from,
                          subject_to,
                          scale,
                          subjects_dir=tempdir)
            skip_fiducials = True
            with pytest.raises(IOError, match='already exists'):
                scale_mri(subject_from,
                          subject_to,
                          scale,
                          subjects_dir=tempdir,
                          skip_fiducials=skip_fiducials)
            overwrite = True
        if subject_from == 'sample':  # support for not needing all surf files
            os.remove(op.join(sample_dir, 'surf', 'lh.curv'))
        scale_mri(subject_from,
                  subject_to,
                  scale,
                  subjects_dir=tempdir,
                  verbose='debug',
                  overwrite=overwrite,
                  skip_fiducials=skip_fiducials)
        if subject_from == 'fsaverage':
            assert _is_mri_subject(subject_to, tempdir), "Scaling failed"
        src_to_fname = op.join(tempdir, subject_to, 'bem',
                               '%s-%s-src.fif' % (subject_to, spacing))
        assert op.exists(src_to_fname), "Source space was not scaled"
        # Check MRI scaling
        fname_mri = op.join(tempdir, subject_to, 'mri', 'T1.mgz')
        assert op.exists(fname_mri), "MRI was not scaled"
        # Check MNI transform
        src = mne.read_source_spaces(src_to_fname)
        vertices = np.concatenate([s['vertno'] for s in src])
        assert_array_equal(vertices, vertices_from)
        mni = mne.vertex_to_mni(vertices,
                                hemis,
                                subject_to,
                                subjects_dir=tempdir)
        assert_allclose(mni, mni_from, atol=1e-3)  # 0.001 mm
        # Check head_to_mni (the `trans` here does not really matter)
        trans = rotation(0.001, 0.002, 0.003) @ translation(0.01, 0.02, 0.03)
        trans = Transform('head', 'mri', trans)
        pos_head_from = np.random.RandomState(0).randn(4, 3)
        pos_mni_from = mne.head_to_mni(pos_head_from, subject_from, trans,
                                       tempdir)
        pos_mri_from = apply_trans(trans, pos_head_from)
        pos_mri = pos_mri_from * scale
        pos_head = apply_trans(invert_transform(trans), pos_mri)
        pos_mni = mne.head_to_mni(pos_head, subject_to, trans, tempdir)
        assert_allclose(pos_mni, pos_mni_from, atol=1e-3)