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
Example #2
0
def test_helmet():
    """Test loading helmet surfaces."""
    base_dir = op.join(op.dirname(__file__), '..', 'io')
    fname_raw = op.join(base_dir, 'tests', 'data', 'test_raw.fif')
    fname_kit_raw = op.join(base_dir, 'kit', 'tests', 'data',
                            'test_bin_raw.fif')
    fname_bti_raw = op.join(base_dir, 'bti', 'tests', 'data',
                            'exported4D_linux_raw.fif')
    fname_ctf_raw = op.join(base_dir, 'tests', 'data', 'test_ctf_raw.fif')
    fname_trans = op.join(base_dir, 'tests', 'data',
                          'sample-audvis-raw-trans.txt')
    trans = _get_trans(fname_trans)[0]
    new_info = read_info(fname_raw)
    artemis_info = new_info.copy()
    for pick in pick_types(new_info):
        new_info['chs'][pick]['coil_type'] = 9999
        artemis_info['chs'][pick]['coil_type'] = \
            FIFF.FIFFV_COIL_ARTEMIS123_GRAD
    for info, n, name in [(read_info(fname_raw), 304, '306m'),
                          (read_info(fname_kit_raw), 304, 'KIT'),
                          (read_info(fname_bti_raw), 304, 'Magnes'),
                          (read_info(fname_ctf_raw), 342, 'CTF'),
                          (new_info, 102, 'unknown'),
                          (artemis_info, 102, 'ARTEMIS123')
                          ]:
        with catch_logging() as log:
            helmet = get_meg_helmet_surf(info, trans, verbose=True)
        log = log.getvalue()
        assert name in log
        assert_equal(len(helmet['rr']), n)
        assert_equal(len(helmet['rr']), len(helmet['nn']))
Example #3
0
def _compute_coreg_dist(subject, trans_fname, info_fname, subjects_dir):
    """Assess quality of coregistration."""
    trans = mne.read_trans(trans_fname)

    high_res_surf = subjects_dir + "/%s/surf/lh.seghead" % subject
    low_res_surf = subjects_dir + "/%s/bem/%s-outer_skull.surf" % (subject,
                                                                   subject)
    low_res_surf_2 = subjects_dir + "/%s/bem/outer_skull.surf" % subject
    if os.path.exists(high_res_surf):
        pts, _ = mne.read_surface(high_res_surf, verbose=False)
        pts /= 1e3  # convert to mm
    elif os.path.exists(low_res_surf):
        warnings.warn("""Using low resolution head surface,
                         the average distance will be potentially
                         overestimated""")
        pts, _ = mne.read_surface(low_res_surf, verbose=False)
        pts /= 1e3  # convert to mm
    elif os.path.exists(low_res_surf_2):
        warnings.warn("""Using low resolution head surface,
                         the average distance will be potentially
                         overestimated""")
        pts, _ = mne.read_surface(low_res_surf_2, verbose=False)
        pts /= 1e3  # convert to mm
    else:
        raise FileNotFoundError("No MRI surface was found!")
    trans = _get_trans(trans, fro="mri", to="head")[0]
    pts = apply_trans(trans, pts)
    info = mne.io.read_info(info_fname, verbose=False)
    info_dig = np.stack([list(x["r"]) for x in info["dig"]], axis=0)
    M = euclidean_distances(info_dig, pts)
    idx = np.argmin(M, axis=1)
    dist = M[np.arange(len(info_dig)), idx].mean()

    return dist
Example #4
0
def test_nirx_15_2():
    """Test reading NIRX files."""
    raw = read_raw_nirx(fname_nirx_15_2, preload=True)

    # Test data import
    assert raw._data.shape == (64, 67)
    assert raw.info['sfreq'] == 3.90625

    # Test channel naming
    assert raw.info['ch_names'][:4] == [
        "S1_D1 760", "S1_D1 850", "S1_D10 760", "S1_D10 850"
    ]

    # Test info import
    assert raw.info['subject_info'] == dict(sex=1, first_name="TestRecording")

    # Test trigger events
    assert_array_equal(raw.annotations.description, ['4.0', '6.0', '2.0'])

    # Test location of detectors
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D1'
    assert_allclose(mni_locs[0], [-0.0292, 0.0852, -0.0142],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][15][3:5] == 'D4'
    assert_allclose(mni_locs[15], [-0.0739, -0.0756, -0.0075],
                    atol=allowed_dist_error)
Example #5
0
def _find_closest_standard_location(position, reference, *, out='label'):
    """Return closest montage label to coordinates.

    Parameters
    ----------
    position : array, shape (3,)
        Coordinates.
    reference : dataframe
        As generated by _generate_montage_locations.
    trans_pos : str
        Apply a transformation to positions to specified frame.
        Use None for no transformation.
    """
    from scipy.spatial.distance import cdist
    p0 = np.array(position)
    p0.shape = (-1, 3)
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    p0 = apply_trans(head_mri_t, p0)
    dists = cdist(p0, np.asarray(reference[['x', 'y', 'z']], float))

    if out == 'label':
        min_idx = np.argmin(dists)
        return reference["label"][min_idx]
    else:
        assert out == 'dists'
        return dists
Example #6
0
def test_helmet():
    """Test loading helmet surfaces."""
    base_dir = op.join(op.dirname(__file__), '..', 'io')
    fname_raw = op.join(base_dir, 'tests', 'data', 'test_raw.fif')
    fname_kit_raw = op.join(base_dir, 'kit', 'tests', 'data',
                            'test_bin_raw.fif')
    fname_bti_raw = op.join(base_dir, 'bti', 'tests', 'data',
                            'exported4D_linux_raw.fif')
    fname_ctf_raw = op.join(base_dir, 'tests', 'data', 'test_ctf_raw.fif')
    fname_trans = op.join(base_dir, 'tests', 'data',
                          'sample-audvis-raw-trans.txt')
    trans = _get_trans(fname_trans)[0]
    new_info = read_info(fname_raw)
    artemis_info = new_info.copy()
    for pick in pick_types(new_info, meg=True):
        new_info['chs'][pick]['coil_type'] = 9999
        artemis_info['chs'][pick]['coil_type'] = \
            FIFF.FIFFV_COIL_ARTEMIS123_GRAD
    for info, n, name in [(read_info(fname_raw), 304, '306m'),
                          (read_info(fname_kit_raw), 304, 'KIT'),
                          (read_info(fname_bti_raw), 304, 'Magnes'),
                          (read_info(fname_ctf_raw), 342, 'CTF'),
                          (new_info, 102, 'unknown'),
                          (artemis_info, 102, 'ARTEMIS123')]:
        with catch_logging() as log:
            helmet = get_meg_helmet_surf(info, trans, verbose=True)
        log = log.getvalue()
        assert name in log
        assert_equal(len(helmet['rr']), n)
        assert_equal(len(helmet['rr']), len(helmet['nn']))
Example #7
0
def test_get_trans():
    """Test converting '-trans.txt' to '-trans.fif'"""
    trans = read_trans(fname)
    trans = invert_transform(trans)  # starts out as head->MRI, so invert
    trans_2 = _get_trans(fname_trans)[0]
    assert_equal(trans['from'], trans_2['from'])
    assert_equal(trans['to'], trans_2['to'])
    assert_allclose(trans['trans'], trans_2['trans'], rtol=1e-5, atol=1e-5)
def test_get_trans():
    """Test converting '-trans.txt' to '-trans.fif'"""
    trans = read_trans(fname)
    trans = invert_transform(trans)  # starts out as head->MRI, so invert
    trans_2 = _get_trans(fname_trans)[0]
    assert_equal(trans['from'], trans_2['from'])
    assert_equal(trans['to'], trans_2['to'])
    assert_allclose(trans['trans'], trans_2['trans'], rtol=1e-5, atol=1e-5)
Example #9
0
def test_nirx_15_0():
    """Test reading NIRX files."""
    raw = read_raw_nirx(fname_nirx_15_0, preload=True)

    # Test data import
    assert raw._data.shape == (20, 92)
    assert raw.info['sfreq'] == 6.25
    assert raw.info['meas_date'] == dt.datetime(2019,
                                                10,
                                                27,
                                                13,
                                                53,
                                                34,
                                                209000,
                                                tzinfo=dt.timezone.utc)

    # Test channel naming
    assert raw.info['ch_names'][:12] == [
        "S1_D1 760", "S1_D1 850", "S2_D2 760", "S2_D2 850", "S3_D3 760",
        "S3_D3 850", "S4_D4 760", "S4_D4 850", "S5_D5 760", "S5_D5 850",
        "S6_D6 760", "S6_D6 850"
    ]

    # Test info import
    assert raw.info['subject_info'] == {
        'birthday': (2004, 10, 27),
        'first_name': 'NIRX',
        'last_name': 'Test',
        'sex': FIFF.FIFFV_SUBJ_SEX_UNKNOWN,
        'his_id': "NIRX_Test"
    }

    # Test trigger events
    assert_array_equal(raw.annotations.description, ['1.0', '2.0', '2.0'])

    # Test location of detectors
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D1'
    assert_allclose(mni_locs[0], [0.0287, -0.1143, -0.0332],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][15][3:5] == 'D8'
    assert_allclose(mni_locs[15], [-0.0693, -0.0480, 0.0657],
                    atol=allowed_dist_error)

    # Test distance between optodes matches values from
    allowed_distance_error = 0.0002

    assert_allclose(source_detector_distances(
        raw.copy().pick("S1_D1 760").info), [0.0300],
                    atol=allowed_distance_error)
    assert_allclose(source_detector_distances(
        raw.copy().pick("S7_D7 760").info), [0.0392],
                    atol=allowed_distance_error)
Example #10
0
def _compute_depth(dip, fname_bem, fname_trans, subject, subjects_dir):
    """Compute dipole depth."""
    trans = _get_trans(fname_trans)[0]
    bem = read_bem_solution(fname_bem)
    surf = _bem_find_surface(bem, 'inner_skull')
    points = surf['rr']
    points = apply_trans(trans['trans'], points)
    depth = _compute_nearest(points, dip.pos, return_dists=True)[1][0]
    return np.ravel(depth)
Example #11
0
def _compute_depth(dip, fname_bem, fname_trans, subject, subjects_dir):
    """Compute dipole depth."""
    trans = _get_trans(fname_trans)[0]
    bem = read_bem_solution(fname_bem)
    surf = _bem_find_surface(bem, 'inner_skull')
    points = surf['rr']
    points = apply_trans(trans['trans'], points)
    depth = _compute_nearest(points, dip.pos, return_dists=True)[1][0]
    return np.ravel(depth)
Example #12
0
def test_nirx_15_2():
    """Test reading NIRX files."""
    raw = read_raw_nirx(fname_nirx_15_2, preload=True)

    # Test data import
    assert raw._data.shape == (64, 67)
    assert raw.info['sfreq'] == 3.90625
    assert raw.info['meas_date'] == dt.datetime(2019,
                                                10,
                                                2,
                                                9,
                                                8,
                                                47,
                                                511000,
                                                tzinfo=dt.timezone.utc)

    # Test channel naming
    assert raw.info['ch_names'][:4] == [
        "S1_D1 760", "S1_D1 850", "S1_D10 760", "S1_D10 850"
    ]

    # Test info import
    assert raw.info['subject_info'] == dict(sex=1,
                                            first_name="TestRecording",
                                            birthday=(1989, 10, 2))

    # Test trigger events
    assert_array_equal(raw.annotations.description, ['4.0', '6.0', '2.0'])
    print(raw.annotations.onset)

    # Test location of detectors
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D1'
    assert_allclose(mni_locs[0], [-0.0292, 0.0852, -0.0142],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][15][3:5] == 'D4'
    assert_allclose(mni_locs[15], [-0.0739, -0.0756, -0.0075],
                    atol=allowed_dist_error)

    # Old name aliases for backward compat
    assert 'fnirs_cw_amplitude' in raw
    with pytest.deprecated_call():
        assert 'fnirs_raw' in raw
    assert 'fnirs_od' not in raw
    picks = pick_types(raw.info, fnirs='fnirs_cw_amplitude')
    with pytest.deprecated_call():
        picks_alias = pick_types(raw.info, fnirs='fnirs_raw')
    assert_array_equal(picks, picks_alias)
Example #13
0
def test_set_montage_artinis_fsaverage(kind):
    """Test that artinis montages match fsaverage's head<->MRI transform."""
    # Compare OctaMon and Brite23 to fsaverage
    trans_fs, _ = _get_trans('fsaverage')
    montage = make_standard_montage(f'artinis-{kind}')
    trans = compute_native_head_t(montage)
    assert trans['to'] == trans_fs['to']
    assert trans['from'] == trans_fs['from']
    translation = 1000 * np.linalg.norm(trans['trans'][:3, 3] -
                                        trans_fs['trans'][:3, 3])
    assert 0 < translation < 1  # mm
    rotation = np.rad2deg(
        _angle_between_quats(rot_to_quat(trans['trans'][:3, :3]),
                             rot_to_quat(trans_fs['trans'][:3, :3])))
    assert 0 < rotation < 1  # degrees
Example #14
0
def test_helmet():
    """Test loading helmet surfaces."""
    base_dir = op.join(op.dirname(__file__), '..', 'io')
    fname_raw = op.join(base_dir, 'tests', 'data', 'test_raw.fif')
    fname_kit_raw = op.join(base_dir, 'kit', 'tests', 'data',
                            'test_bin_raw.fif')
    fname_bti_raw = op.join(base_dir, 'bti', 'tests', 'data',
                            'exported4D_linux_raw.fif')
    fname_ctf_raw = op.join(base_dir, 'tests', 'data', 'test_ctf_raw.fif')
    fname_trans = op.join(base_dir, 'tests', 'data',
                          'sample-audvis-raw-trans.txt')
    trans = _get_trans(fname_trans)[0]
    for fname in [fname_raw, fname_kit_raw, fname_bti_raw, fname_ctf_raw]:
        helmet = get_meg_helmet_surf(read_info(fname), trans)
        assert_equal(len(helmet['rr']), 304)  # they all have 304 verts
        assert_equal(len(helmet['rr']), len(helmet['nn']))
Example #15
0
def test_helmet():
    """Test loading helmet surfaces."""
    base_dir = op.join(op.dirname(__file__), '..', 'io')
    fname_raw = op.join(base_dir, 'tests', 'data', 'test_raw.fif')
    fname_kit_raw = op.join(base_dir, 'kit', 'tests', 'data',
                            'test_bin_raw.fif')
    fname_bti_raw = op.join(base_dir, 'bti', 'tests', 'data',
                            'exported4D_linux_raw.fif')
    fname_ctf_raw = op.join(base_dir, 'tests', 'data', 'test_ctf_raw.fif')
    fname_trans = op.join(base_dir, 'tests', 'data',
                          'sample-audvis-raw-trans.txt')
    trans = _get_trans(fname_trans)[0]
    for fname in [fname_raw, fname_kit_raw, fname_bti_raw, fname_ctf_raw]:
        helmet = get_meg_helmet_surf(read_info(fname), trans)
        assert_equal(len(helmet['rr']), 304)  # they all have 304 verts
        assert_equal(len(helmet['rr']), len(helmet['nn']))
Example #16
0
def test_nirx_15_0():
    """Test reading NIRX files."""
    raw = read_raw_nirx(fname_nirx_15_0, preload=True)

    # Test data import
    assert raw._data.shape == (20, 92)
    assert raw.info['sfreq'] == 6.25

    # Test channel naming
    assert raw.info['ch_names'][:12] == [
        "S1_D1 760", "S1_D1 850", "S2_D2 760", "S2_D2 850", "S3_D3 760",
        "S3_D3 850", "S4_D4 760", "S4_D4 850", "S5_D5 760", "S5_D5 850",
        "S6_D6 760", "S6_D6 850"
    ]

    # Test info import
    assert raw.info['subject_info'] == {
        'first_name': 'NIRX',
        'last_name': 'Test',
        'sex': '0'
    }

    # Test trigger events
    assert_array_equal(raw.annotations.description, ['1.0', '2.0', '2.0'])

    # Test location of detectors
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D1'
    assert_allclose(mni_locs[0], [0.0287, -0.1143, -0.0332],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][15][3:5] == 'D8'
    assert_allclose(mni_locs[15], [-0.0693, -0.0480, 0.0657],
                    atol=allowed_dist_error)

    # Test distance between optodes matches values from
    allowed_distance_error = 0.0002
    distances = source_detector_distances(raw.info)
    assert_allclose(distances[::2], [
        0.0301, 0.0315, 0.0343, 0.0368, 0.0408, 0.0399, 0.0393, 0.0367, 0.0336,
        0.0447
    ],
                    atol=allowed_distance_error)
Example #17
0
def test_project_sensors_onto_brain(tmp_path):
    """Test projecting sensors onto the brain surface."""
    tempdir = str(tmp_path)
    raw = mne.io.read_raw_fif(fname_raw)
    trans = _get_trans(fname_trans)[0]
    # test informative error for no surface first
    with pytest.raises(RuntimeError, match='requires generating a BEM'):
        project_sensors_onto_brain(raw.info,
                                   trans,
                                   'sample',
                                   subjects_dir=tempdir)
    brain_surf_fname = op.join(tempdir, 'sample', 'bem', 'brain.surf')
    if not op.isdir(op.dirname(brain_surf_fname)):
        os.makedirs(op.dirname(brain_surf_fname))
    if not op.isfile(brain_surf_fname):
        copyfile(op.join(subjects_dir, 'sample', 'bem', 'inner_skull.surf'),
                 brain_surf_fname)
    # now make realistic ECoG grid
    raw.pick_types(meg=False, eeg=True)
    raw.load_data()
    raw.set_eeg_reference([])
    raw.set_channel_types({ch: 'ecog' for ch in raw.ch_names})
    pos = np.zeros((49, 3))
    pos[:, :2] = np.array(
        np.meshgrid(np.linspace(0, 0.02, 7), np.linspace(0, 0.02,
                                                         7))).reshape(2, -1).T
    pos[:, 2] = 0.12
    raw.drop_channels(raw.ch_names[49:])
    raw.set_montage(
        mne.channels.make_dig_montage(ch_pos=dict(zip(raw.ch_names[:49], pos)),
                                      coord_frame='head'))
    raw.info = project_sensors_onto_brain(raw.info,
                                          trans,
                                          'sample',
                                          subjects_dir=tempdir)
    # plot to check, should be projected down onto inner skull
    # brain = mne.viz.Brain('sample', subjects_dir=subjects_dir, alpha=0.5,
    #                       surf='white')
    # brain.add_sensors(raw.info, trans=trans)
    test_locs = [[0.00149, -0.001588, 0.133029],
                 [0.004302, 0.001959, 0.133922], [0.008602, 0.00116, 0.133723]]
    for ch, test_loc in zip(raw.info['chs'][:3], test_locs):
        assert_allclose(ch['loc'][:3], test_loc, rtol=0.01)
Example #18
0
def test_head_to_mni():
    """Test conversion of aseg vertices to MNI coordinates."""
    # obtained using freeview
    coords = np.array([[22.52, 11.24, 17.72], [22.52, 5.46, 21.58],
                       [16.10, 5.46, 22.23], [21.24, 8.36, 22.23]]) / 1000.

    xfm = read_talxfm('sample', subjects_dir)
    coords_MNI = apply_trans(xfm['trans'], coords) * 1000.

    mri_head_t, _ = _get_trans(trans_fname, 'mri', 'head', allow_none=False)

    # obtained from sample_audvis-meg-oct-6-mixed-fwd.fif
    coo_right_amygdala = np.array([[0.01745682, 0.02665809, 0.03281873],
                                   [0.01014125, 0.02496262, 0.04233755],
                                   [0.01713642, 0.02505193, 0.04258181],
                                   [0.01720631, 0.03073877, 0.03850075]])
    coords_MNI_2 = head_to_mni(coo_right_amygdala, 'sample', mri_head_t,
                               subjects_dir)
    # less than 1mm error
    assert_allclose(coords_MNI, coords_MNI_2, atol=10.0)
Example #19
0
def dip_depth(dip, fname_trans, subject, subjects_dir):
    trans = read_trans(fname_trans)
    trans = _get_trans(trans)[0]
    subjects_dir = get_subjects_dir(subjects_dir=subjects_dir)
    fname = os.path.join(subjects_dir, subject, 'bem', 'inner_skull.surf')
    points, faces = read_surface(fname)
    points = apply_trans(trans['trans'], points * 1e-3)

    pos = dip.pos
    ori = dip.ori

    from sklearn.neighbors import NearestNeighbors
    nn = NearestNeighbors()
    nn.fit(points)
    depth, idx = nn.kneighbors(pos, 1, return_distance=True)
    idx = np.ravel(idx)

    direction = pos - points[idx]
    direction /= np.sqrt(np.sum(direction**2, axis=1))[:, None]
    ori /= np.sqrt(np.sum(ori**2, axis=1))[:, None]

    radiality = np.abs(np.sum(ori * direction, axis=1))
    return np.ravel(depth), radiality
def test_get_trans():
    """Test converting '-trans.txt' to '-trans.fif'"""
    trans = read_trans(fname)
    trans = invert_transform(trans)  # starts out as head->MRI, so invert
    trans_2 = _get_trans(fname_trans)[0]
    assert trans.__eq__(trans_2, atol=1e-5)
Example #21
0
def test_snirf_nirsport2_w_positions():
    """Test reading SNIRF files with known positions."""
    raw = read_raw_snirf(nirx_nirsport2_103_2,
                         preload=True,
                         optode_frame="mri")

    # Test data import
    assert raw._data.shape == (40, 128)
    assert_almost_equal(raw.info['sfreq'], 10.2, decimal=1)

    # Test channel naming
    assert raw.info['ch_names'][:4] == [
        'S1_D1 760', 'S1_D1 850', 'S1_D6 760', 'S1_D6 850'
    ]
    assert raw.info['ch_names'][24:26] == ['S6_D4 760', 'S6_D4 850']

    # Test frequency encoding
    assert raw.info['chs'][0]['loc'][9] == 760
    assert raw.info['chs'][1]['loc'][9] == 850

    assert sum(short_channels(raw.info)) == 16

    # Test distance between optodes matches values from
    # nirsite https://github.com/mne-tools/mne-testing-data/pull/86
    # figure 3
    allowed_distance_error = 0.005
    distances = source_detector_distances(raw.info)
    assert_allclose(distances[::2][:14], [
        0.0304, 0.0411, 0.008, 0.0400, 0.008, 0.0310, 0.0411, 0.008, 0.0299,
        0.008, 0.0370, 0.008, 0.0404, 0.008
    ],
                    atol=allowed_distance_error)

    # Test location of detectors
    # The locations of detectors can be seen in the first
    # figure on this page...
    # https://github.com/mne-tools/mne-testing-data/pull/86
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D1'
    assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][2][3:5] == 'D6'
    assert_allclose(mni_locs[2], [-0.0841, -0.0138, 0.0248],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][34][3:5] == 'D5'
    assert_allclose(mni_locs[34], [0.0845, -0.0451, -0.0123],
                    atol=allowed_dist_error)

    # Test location of sensors
    # The locations of sensors can be seen in the second
    # figure on this page...
    # https://github.com/mne-tools/mne-testing-data/pull/86
    allowed_dist_error = 0.0002
    locs = [ch['loc'][3:6] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][:2] == 'S1'
    assert_allclose(mni_locs[0], [-0.0848, -0.0162, -0.0163],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][9][:2] == 'S2'
    assert_allclose(mni_locs[9], [-0.0, -0.1195, 0.0142],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][34][:2] == 'S8'
    assert_allclose(mni_locs[34], [0.0828, -0.046, 0.0285],
                    atol=allowed_dist_error)

    mon = raw.get_montage()
    assert len(mon.dig) == 43
Example #22
0
def write_anat(bids_root, subject, t1w, session=None, acquisition=None,
               raw=None, trans=None, deface=False, overwrite=False,
               verbose=False):
    """Put anatomical MRI data into a BIDS format.

    Given a BIDS directory and a T1 weighted MRI scan for a certain subject,
    format the MRI scan to be in BIDS format and put it into the correct
    location in the bids_dir. If a transformation matrix is supplied, a
    sidecar JSON file will be written for the T1 weighted data.

    Parameters
    ----------
    bids_root : str
        Path to root of the BIDS folder
    subject : str
        Subject label as in 'sub-<label>', for example: '01'
    t1w : str | nibabel image object
        Path to a T1 weighted MRI scan of the subject. Can be in any format
        readable by nibabel. Can also be a nibabel image object of a T1
        weighted MRI scan. Will be written as a .nii.gz file.
    session : str | None
        The session for `t1w`. Corresponds to "ses"
    acquisition: str | None
        The acquisition parameters for `t1w`. Corresponds to "acq"
    raw : instance of Raw | None
        The raw data of `subject` corresponding to `t1w`. If `raw` is None,
        `trans` has to be None as well
    trans : instance of mne.transforms.Transform | str | None
        The transformation matrix from head coordinates to MRI coordinates. Can
        also be a string pointing to a .trans file containing the
        transformation matrix. If None, no sidecar JSON file will be written
        for `t1w`
    deface : bool | dict
        If False, no defacing is performed.
        If True, deface with default parameters.
        `trans` and `raw` must not be `None` if True.
        If dict, accepts the following keys:
            `inset`: how far back in millimeters to start defacing
                     relative to the nasion (default 20)
            `theta`: is the angle of the defacing shear in degrees relative
                     to the normal to the plane passing through the anatomical
                     landmarks (default 35).
    overwrite : bool
        Whether to overwrite existing files or data in files.
        Defaults to False.
        If overwrite is True, any existing files with the same BIDS parameters
        will be overwritten with the exception of the `participants.tsv` and
        `scans.tsv` files. For these files, parts of pre-existing data that
        match the current data will be replaced.
        If overwrite is False, no existing data will be overwritten or
        replaced.
    verbose : bool
        If verbose is True, this will print a snippet of the sidecar files. If
        False, no content will be printed.

    Returns
    -------
    anat_dir : str
        Path to the anatomical scan in the `bids_dir`

    """
    if not has_nibabel():  # pragma: no cover
        raise ImportError('This function requires nibabel.')
    import nibabel as nib

    if deface and (trans is None or raw is None):
        raise ValueError('The raw object, trans and raw must be provided to '
                         'deface the T1')

    # Make directory for anatomical data
    anat_dir = op.join(bids_root, 'sub-{}'.format(subject))
    # Session is optional
    if session is not None:
        anat_dir = op.join(anat_dir, 'ses-{}'.format(session))
    anat_dir = op.join(anat_dir, 'anat')
    if not op.exists(anat_dir):
        os.makedirs(anat_dir)

    # Try to read our T1 file and convert to MGH representation
    if isinstance(t1w, str):
        t1w = nib.load(t1w)
    elif type(t1w) not in nib.all_image_classes:
        raise ValueError('`t1w` must be a path to a T1 weighted MRI data file '
                         ', or a nibabel image object, but it is of type '
                         '"{}"'.format(type(t1w)))

    t1w = nib.Nifti1Image(t1w.dataobj, t1w.affine)
    # XYZT_UNITS = NIFT_UNITS_MM (10 in binary or 2 in decimal)
    # seems to be the default for Nifti files
    # https://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/xyzt_units.html
    if t1w.header['xyzt_units'] == 0:
        t1w.header['xyzt_units'] = np.array(10, dtype='uint8')

    # Now give the NIfTI file a BIDS name and write it to the BIDS location
    t1w_basename = make_bids_basename(subject=subject, session=session,
                                      acquisition=acquisition, prefix=anat_dir,
                                      suffix='T1w.nii.gz')

    # Check if we have necessary conditions for writing a sidecar JSON
    if trans is not None:

        # get trans and ensure it is from head to MRI
        trans, _ = _get_trans(trans, fro='head', to='mri')

        if not isinstance(raw, BaseRaw):
            raise ValueError('`raw` must be specified if `trans` is not None')

        # Prepare to write the sidecar JSON
        # extract MEG landmarks
        coords_dict = _extract_landmarks(raw.info['dig'])
        meg_landmarks = np.asarray((coords_dict['LPA'],
                                    coords_dict['NAS'],
                                    coords_dict['RPA']))

        # Transform MEG landmarks into MRI space, adjust units by * 1e3
        mri_landmarks = apply_trans(trans, meg_landmarks, move=True) * 1e3

        # Get landmarks in voxel space, using the mgh version of our T1 data
        t1_mgh = nib.MGHImage(t1w.dataobj, t1w.affine)
        vox2ras_tkr = t1_mgh.header.get_vox2ras_tkr()
        ras2vox_tkr = np.linalg.inv(vox2ras_tkr)
        mri_landmarks = apply_trans(ras2vox_tkr, mri_landmarks)  # in vox

        # Write sidecar.json
        t1w_json = dict()
        t1w_json['AnatomicalLandmarkCoordinates'] = \
            {'LPA': list(mri_landmarks[0, :]),
             'NAS': list(mri_landmarks[1, :]),
             'RPA': list(mri_landmarks[2, :])}
        fname = t1w_basename.replace('.nii.gz', '.json')
        if op.isfile(fname) and not overwrite:
            raise IOError('Wanted to write a file but it already exists and '
                          '`overwrite` is set to False. File: "{}"'
                          .format(fname))
        _write_json(fname, t1w_json, overwrite, verbose)

        if deface:
            t1w = _deface(t1w, mri_landmarks, deface, trans, raw)

    # Save anatomical data
    if op.exists(t1w_basename):
        if overwrite:
            os.remove(t1w_basename)
        else:
            raise IOError('Wanted to write a file but it already exists and '
                          '`overwrite` is set to False. File: "{}"'
                          .format(t1w_basename))

    nib.save(t1w, t1w_basename)

    return anat_dir
Example #23
0
def test_nirsport_v2():
    """Test NIRSport2 file."""
    raw = read_raw_nirx(nirsport2, preload=True)
    assert raw._data.shape == (40, 128)

    # Test distance between optodes matches values from
    # nirsite https://github.com/mne-tools/mne-testing-data/pull/86
    # figure 3
    allowed_distance_error = 0.005
    distances = source_detector_distances(raw.info)
    assert_allclose(distances[::2][:14], [
        0.0304, 0.0411, 0.008, 0.0400, 0.008, 0.0310, 0.0411, 0.008, 0.0299,
        0.008, 0.0370, 0.008, 0.0404, 0.008
    ],
                    atol=allowed_distance_error)

    # Test location of detectors
    # The locations of detectors can be seen in the first
    # figure on this page...
    # https://github.com/mne-tools/mne-testing-data/pull/86
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D1'
    assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][2][3:5] == 'D6'
    assert_allclose(mni_locs[2], [-0.0841, -0.0138, 0.0248],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][34][3:5] == 'D5'
    assert_allclose(mni_locs[34], [0.0845, -0.0451, -0.0123],
                    atol=allowed_dist_error)

    # Test location of sensors
    # The locations of sensors can be seen in the second
    # figure on this page...
    # https://github.com/mne-tools/mne-testing-data/pull/86
    locs = [ch['loc'][3:6] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][:2] == 'S1'
    assert_allclose(mni_locs[0], [-0.0848, -0.0162, -0.0163],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][9][:2] == 'S2'
    assert_allclose(mni_locs[9], [-0.0, -0.1195, 0.0142],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][34][:2] == 'S8'
    assert_allclose(mni_locs[34], [0.0828, -0.046, 0.0285],
                    atol=allowed_dist_error)

    assert len(raw.annotations) == 3
    assert raw.annotations.description[0] == '1.0'
    assert raw.annotations.description[2] == '6.0'
    # Lose tolerance as I am eyeballing the time differences on screen
    assert_allclose(np.diff(raw.annotations.onset), [2.3, 3.1], atol=0.1)

    mon = raw.get_montage()
    assert len(mon.dig) == 43
Example #24
0
def test_nirx_15_3_short():
    """Test reading NIRX files."""
    raw = read_raw_nirx(fname_nirx_15_3_short, preload=True)

    # Test data import
    assert raw._data.shape == (26, 220)
    assert raw.info['sfreq'] == 12.5

    # Test channel naming
    assert raw.info['ch_names'][:4] == [
        "S1_D2 760", "S1_D2 850", "S1_D9 760", "S1_D9 850"
    ]
    assert raw.info['ch_names'][24:26] == ["S5_D13 760", "S5_D13 850"]

    # Test frequency encoding
    assert raw.info['chs'][0]['loc'][9] == 760
    assert raw.info['chs'][1]['loc'][9] == 850

    # Test info import
    assert raw.info['subject_info'] == dict(birthday=(2020, 8, 18),
                                            sex=0,
                                            first_name="testMontage\\0A"
                                            "TestMontage",
                                            his_id="testMontage\\0A"
                                            "TestMontage")

    # Test distance between optodes matches values from
    # https://github.com/mne-tools/mne-testing-data/pull/72
    allowed_distance_error = 0.001
    distances = source_detector_distances(raw.info)
    assert_allclose(distances[::2], [
        0.0304, 0.0078, 0.0310, 0.0086, 0.0416, 0.0072, 0.0389, 0.0075, 0.0558,
        0.0562, 0.0561, 0.0565, 0.0077
    ],
                    atol=allowed_distance_error)

    # Test which channels are short
    # These are the ones marked as red at
    # https://github.com/mne-tools/mne-testing-data/pull/72
    is_short = short_channels(raw.info)
    assert_array_equal(is_short[:9:2], [False, True, False, True, False])
    is_short = short_channels(raw.info, threshold=0.003)
    assert_array_equal(is_short[:3:2], [False, False])
    is_short = short_channels(raw.info, threshold=50)
    assert_array_equal(is_short[:3:2], [True, True])

    # Test trigger events
    assert_array_equal(raw.annotations.description, ['4.0', '2.0', '1.0'])

    # Test location of detectors
    # The locations of detectors can be seen in the first
    # figure on this page...
    # https://github.com/mne-tools/mne-testing-data/pull/72
    # And have been manually copied below
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D2'
    assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][4][3:5] == 'D1'
    assert_allclose(mni_locs[4], [0.0846, -0.0142, -0.0156],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][8][3:5] == 'D3'
    assert_allclose(mni_locs[8], [0.0207, -0.1062, 0.0484],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][12][3:5] == 'D4'
    assert_allclose(mni_locs[12], [-0.0196, 0.0821, 0.0275],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][16][3:5] == 'D5'
    assert_allclose(mni_locs[16], [-0.0360, 0.0276, 0.0778],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][19][3:5] == 'D6'
    assert_allclose(mni_locs[19], [0.0388, -0.0477, 0.0932],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][21][3:5] == 'D7'
    assert_allclose(mni_locs[21], [-0.0394, -0.0483, 0.0928],
                    atol=allowed_dist_error)
Example #25
0
def test_nirx_15_2_short():
    """Test reading NIRX files."""
    raw = read_raw_nirx(fname_nirx_15_2_short, preload=True)

    # Test data import
    assert raw._data.shape == (26, 145)
    assert raw.info['sfreq'] == 12.5
    assert raw.info['meas_date'] == dt.datetime(2019,
                                                8,
                                                23,
                                                7,
                                                37,
                                                4,
                                                540000,
                                                tzinfo=dt.timezone.utc)

    # Test channel naming
    assert raw.info['ch_names'][:4] == [
        "S1_D1 760", "S1_D1 850", "S1_D9 760", "S1_D9 850"
    ]
    assert raw.info['ch_names'][24:26] == ["S5_D13 760", "S5_D13 850"]

    # Test frequency encoding
    assert raw.info['chs'][0]['loc'][9] == 760
    assert raw.info['chs'][1]['loc'][9] == 850

    # Test info import
    assert raw.info['subject_info'] == dict(sex=1,
                                            first_name="MNE",
                                            middle_name="Test",
                                            last_name="Recording",
                                            birthday=(2014, 8, 23),
                                            his_id="MNE_Test_Recording")

    # Test distance between optodes matches values from
    # nirsite https://github.com/mne-tools/mne-testing-data/pull/51
    # step 4 figure 2
    allowed_distance_error = 0.0002
    distances = source_detector_distances(raw.info)
    assert_allclose(distances[::2], [
        0.0304, 0.0078, 0.0310, 0.0086, 0.0416, 0.0072, 0.0389, 0.0075, 0.0558,
        0.0562, 0.0561, 0.0565, 0.0077
    ],
                    atol=allowed_distance_error)

    # Test which channels are short
    # These are the ones marked as red at
    # https://github.com/mne-tools/mne-testing-data/pull/51 step 4 figure 2
    is_short = short_channels(raw.info)
    assert_array_equal(is_short[:9:2], [False, True, False, True, False])
    is_short = short_channels(raw.info, threshold=0.003)
    assert_array_equal(is_short[:3:2], [False, False])
    is_short = short_channels(raw.info, threshold=50)
    assert_array_equal(is_short[:3:2], [True, True])

    # Test trigger events
    assert_array_equal(raw.annotations.description, ['3.0', '2.0', '1.0'])

    # Test location of detectors
    # The locations of detectors can be seen in the first
    # figure on this page...
    # https://github.com/mne-tools/mne-testing-data/pull/51
    # And have been manually copied below
    # These values were reported in mm, but according to this page...
    # https://mne.tools/stable/auto_tutorials/intro/plot_40_sensor_locations.html
    # 3d locations should be specified in meters, so that's what's tested below
    # Detector locations are stored in the third three loc values
    allowed_dist_error = 0.0002
    locs = [ch['loc'][6:9] for ch in raw.info['chs']]
    head_mri_t, _ = _get_trans('fsaverage', 'head', 'mri')
    mni_locs = apply_trans(head_mri_t, locs)

    assert raw.info['ch_names'][0][3:5] == 'D1'
    assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][4][3:5] == 'D3'
    assert_allclose(mni_locs[4], [0.0846, -0.0142, -0.0156],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][8][3:5] == 'D2'
    assert_allclose(mni_locs[8], [0.0207, -0.1062, 0.0484],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][12][3:5] == 'D4'
    assert_allclose(mni_locs[12], [-0.0196, 0.0821, 0.0275],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][16][3:5] == 'D5'
    assert_allclose(mni_locs[16], [-0.0360, 0.0276, 0.0778],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][19][3:5] == 'D6'
    assert_allclose(mni_locs[19], [0.0352, 0.0283, 0.0780],
                    atol=allowed_dist_error)

    assert raw.info['ch_names'][21][3:5] == 'D7'
    assert_allclose(mni_locs[21], [0.0388, -0.0477, 0.0932],
                    atol=allowed_dist_error)
def make_pert_forward_solution(info,
                               trans,
                               src,
                               bem,
                               perts,
                               meg=True,
                               eeg=True,
                               mindist=0.0,
                               ignore_ref=False,
                               n_jobs=1,
                               verbose=None):
    """Calculate a forward solution for a subject.

    Parameters
    ----------
    info : instance of mne.Info | str
        If str, then it should be a filename to a Raw, Epochs, or Evoked
        file with measurement information. If dict, should be an info
        dict (such as one from Raw, Epochs, or Evoked).
    trans : dict | str | None
        Either a transformation filename (usually made using mne_analyze)
        or an info dict (usually opened using read_trans()).
        If string, an ending of `.fif` or `.fif.gz` will be assumed to
        be in FIF format, any other ending will be assumed to be a text
        file with a 4x4 transformation matrix (like the `--trans` MNE-C
        option). Can be None to use the identity transform.
    src : str | instance of SourceSpaces
        If string, should be a source space filename. Can also be an
        instance of loaded or generated SourceSpaces.
    bem : dict | str
        Filename of the BEM (e.g., "sample-5120-5120-5120-bem-sol.fif") to
        use, or a loaded sphere model (dict).
    meg : bool
        If True (Default), include MEG computations.
    eeg : bool
        If True (Default), include EEG computations.
    mindist : float
        Minimum distance of sources from inner skull surface (in mm).
    ignore_ref : bool
        If True, do not include reference channels in compensation. This
        option should be True for KIT files, since forward computation
        with reference channels is not currently supported.
    n_jobs : int
        Number of jobs to run in parallel.
    perts : dict
        A dictionary containing perturbation parameters for gradiometer
        imbalance, sensor miscalibration, and misalignment
    verbose : bool, str, int, or None
        If not None, override default verbose level (see :func:`mne.verbose`
        and :ref:`Logging documentation <tut_logging>` for more).

    Returns
    -------
    fwd : instance of Forward
        The forward solution.

    See Also
    --------
    convert_forward_solution

    Notes
    -----
    The ``--grad`` option from MNE-C (to compute gradients) is not implemented
    here.

    To create a fixed-orientation forward solution, use this function
    followed by :func:`mne.convert_forward_solution`.
    """
    # Currently not (sup)ported:
    # 1. --grad option (gradients of the field, not used much)
    # 2. --fixed option (can be computed post-hoc)
    # 3. --mricoord option (probably not necessary)

    # read the transformation from MRI to HEAD coordinates
    # (could also be HEAD to MRI)
    mri_head_t, trans = _get_trans(trans)
    if isinstance(bem, ConductorModel):
        bem_extra = 'instance of ConductorModel'
    else:
        bem_extra = bem
    if not isinstance(info, (Info, string_types)):
        raise TypeError('info should be an instance of Info or string')
    if isinstance(info, string_types):
        info_extra = op.split(info)[1]
        info = read_info(info, verbose=False)
    else:
        info_extra = 'instance of Info'
    n_jobs = check_n_jobs(n_jobs)

    # Report the setup
    logger.info('Source space          : %s' % src)
    logger.info('MRI -> head transform : %s' % trans)
    logger.info('Measurement data      : %s' % info_extra)
    if isinstance(bem, ConductorModel) and bem['is_sphere']:
        logger.info('Sphere model      : origin at %s mm' % (bem['r0'], ))
        logger.info('Standard field computations')
    else:
        logger.info('Conductor model   : %s' % bem_extra)
        logger.info('Accurate field computations')
    logger.info('Do computations in %s coordinates',
                _coord_frame_name(FIFF.FIFFV_COORD_HEAD))
    logger.info('Free source orientations')

    megcoils, meg_info, compcoils, megnames, eegels, eegnames, rr, info, \
        update_kwargs, bem = _prepare_for_forward(
            src, mri_head_t, info, bem, mindist, n_jobs, perts, bem_extra, trans,
            info_extra, meg, eeg, ignore_ref)
    del (src, mri_head_t, trans, info_extra, bem_extra, mindist, meg, eeg,
         ignore_ref)

    # Time to do the heavy lifting: MEG first, then EEG
    coil_types = ['meg', 'eeg']
    coils = [megcoils, eegels]
    ccoils = [compcoils, None]
    infos = [meg_info, None]
    megfwd, eegfwd = _compute_forwards(rr, bem, coils, ccoils, infos,
                                       coil_types, n_jobs)

    # merge forwards
    fwd = _merge_meg_eeg_fwds(_to_forward_dict(megfwd, megnames),
                              _to_forward_dict(eegfwd, eegnames),
                              verbose=False)
    logger.info('')

    # Don't transform the source spaces back into MRI coordinates (which is
    # done in the C code) because mne-python assumes forward solution source
    # spaces are in head coords.
    fwd.update(**update_kwargs)
    logger.info('Finished.')
    return fwd
Example #27
0
# House funcs here so PertInv is just scripting
import mne
from _make_perturbed_forward import make_pert_forward_solution, make_pert_forward_dipole
from mne.datasets import sample
import numpy as np  # noqa
from mne.transforms import (_ensure_trans, transform_surface_to, apply_trans,
                          _get_trans, invert_transform, _print_coord_trans, _coord_frame_name,
                          Transform)
# local_data_path = 'C:\MEG\Local_mne_data'
data_path = sample.data_path()  # local copy of mne sample data
raw_fname = data_path + '/MEG/sample/sample_audvis_raw.fif'
cov_fname = data_path + '/MEG/sample/sample_audvis-cov.fif'
subjects_dir = data_path + '/subjects'
subject = 'sample'
trans = data_path + '\MEG\sample/sample_audvis_raw-trans.fif'
mri_head_t, trans = _get_trans(trans)
head_mri_t = invert_transform(mri_head_t)
cov = mne.read_cov(cov_fname)
info = mne.io.read_info(raw_fname)


def fit_dips(min_rad, max_rad, nn, sphere, perts, sourcenorm):
    testsources = dict(rr=[], nn=[])
    nsources = max_rad - min_rad + 1
    vertices = np.zeros((nsources, 1))
    for i in range(min_rad, max_rad + 1):
        ex, ey, ez = sourcenorm[0], sourcenorm[1], sourcenorm[2]
        source = [.001*i*ex, .001*i*ey, .001*i*ez]
        normal = [nn[0], nn[1], nn[2]]
        testsources['rr'].append(source)
        testsources['nn'].append(normal)
Example #28
0
def plot_3d_montage(info,
                    view_map,
                    *,
                    src_det_names='auto',
                    ch_names='numbered',
                    subject='fsaverage',
                    trans='fsaverage',
                    surface='pial',
                    subjects_dir=None,
                    verbose=None):
    """
    Plot a 3D sensor montage.

    Parameters
    ----------
    info : instance of Info
        Measurement info.
    view_map : dict
        Dict of view (key) to channel-pair-numbers (value) to use when
        plotting. Note that, because these get plotted as 1-based channel
        *numbers*, the values should be 1-based rather than 0-based.
        The keys are of the form:

        ``'{side}-{view}'``
            For views like ``'left-lat'`` or ``'right-frontal'`` where the side
            matters.
        ``'{view}'``
            For views like ``'caudal'`` that are along the midline.

        See :meth:`mne.viz.Brain.show_view` for ``view`` options, and the
        Examples section below for usage examples.
    src_det_names : None | dict | str
        Source and detector names to use. "auto" (default) will see if the
        channel locations correspond to standard 10-20 locations and will
        use those if they do (otherwise will act like None). None will use
        S1, S2, ..., D1, D2, ..., etc. Can also be an explicit dict mapping,
        for example::

            src_det_names=dict(S1='Fz', D1='FCz', ...)
    ch_names : str | dict | None
        If ``'numbered'`` (default), use ``['1', '2', ...]`` for the channel
        names, or ``None`` to use ``['S1_D2', 'S2_D1', ...]``. Can also be a
        dict to provide a mapping from the ``'S1_D2'``-style names (keys) to
        other names, e.g., ``defaultdict(lambda: '')`` will prevent showing
        the names altogether.

        .. versionadded:: 0.3
    subject : str
        The subject.
    trans : str | Transform
        The subjects head<->MRI transform.
    surface : str
        The FreeSurfer surface name (e.g., 'pial', 'white').
    subjects_dir : str
        The subjects directory.
    %(verbose)s

    Returns
    -------
    figure : matplotlib.figure.Figure
        The matplotlib figimage.

    Examples
    --------
    For a Hitachi system with two sets of 12 source-detector arrangements,
    one on each side of the head, showing 1-12 on the left and 13-24 on the
    right can be accomplished using the following ``view_map``::

        >>> view_map = {
        ...     'left-lat': np.arange(1, 13),
        ...     'right-lat': np.arange(13, 25),
        ... }

    NIRx typically involves more complicated arrangements. See
    :ref:`the 3D tutorial <tut-fnirs-vis-brain-plot-3d-montage>` for
    an advanced example that incorporates the ``'caudal'`` view as well.
    """  # noqa: E501
    import matplotlib.pyplot as plt
    from scipy.spatial.distance import cdist
    _validate_type(info, Info, 'info')
    _validate_type(view_map, dict, 'views')
    _validate_type(src_det_names, (None, dict, str), 'src_det_names')
    _validate_type(ch_names, (dict, str, None), 'ch_names')
    info = pick_info(info, pick_types(info, fnirs=True, exclude=())[::2])
    if isinstance(ch_names, str):
        _check_option('ch_names', ch_names, ('numbered', ), extra='when str')
        ch_names = {
            name.split()[0]: str(ni)
            for ni, name in enumerate(info['ch_names'], 1)
        }
    info['bads'] = []
    if isinstance(src_det_names, str):
        _check_option('src_det_names',
                      src_det_names, ('auto', ),
                      extra='when str')
        # Decide if we can map to 10-20 locations
        names, pos = zip(
            *transform_to_head(make_standard_montage(
                'standard_1020')).get_positions()['ch_pos'].items())
        pos = np.array(pos, float)
        locs = dict()
        bad = False
        for ch in info['chs']:
            name = ch['ch_name']
            s_name, d_name = name.split()[0].split('_')
            for name, loc in [(s_name, ch['loc'][3:6]),
                              (d_name, ch['loc'][6:9])]:
                if name in locs:
                    continue
                # see if it's close enough
                idx = np.where(cdist(loc[np.newaxis], pos)[0] < 1e-3)[0]
                if len(idx) < 1:
                    bad = True
                    break
                # Some are duplicated (e.g., T7+T3) but we can rely on the
                # first one being the canonical one
                locs[name] = names[idx[0]]
            if bad:
                break
        if bad:
            src_det_names = None
            logger.info('Could not automatically map source/detector names to '
                        '10-20 locations.')
        else:
            src_det_names = locs
            logger.info('Source-detector names automatically mapped to 10-20 '
                        'locations')

    head_mri_t = _get_trans(trans, 'head', 'mri')[0]
    del trans
    views = list()
    for key, num in view_map.items():
        _validate_type(key, str, f'view_map key {repr(key)}')
        _validate_type(num, np.ndarray, f'view_map[{repr(key)}]')
        if '-' in key:
            hemi, v = key.split('-', maxsplit=1)
            hemi = dict(left='lh', right='rh')[hemi]
            views.append((hemi, v, num))
        else:
            views.append(('lh', key, num))
    del view_map
    size = (400 * len(views), 400)
    brain = Brain(subject,
                  'both',
                  surface,
                  views=['lat'] * len(views),
                  size=size,
                  background='w',
                  units='m',
                  view_layout='horizontal',
                  subjects_dir=subjects_dir)
    with _safe_brain_close(brain):
        brain.add_head(dense=False, alpha=0.1)
        brain.add_sensors(info,
                          trans=head_mri_t,
                          fnirs=['channels', 'pairs', 'sources', 'detectors'])
        add_text_kwargs = dict()
        if 'render' in _get_args(brain.plotter.add_text):
            add_text_kwargs['render'] = False
        for col, view in enumerate(views):
            plotted = set()
            brain.show_view(view[1],
                            hemi=view[0],
                            focalpoint=(0, -0.02, 0.02),
                            distance=0.4,
                            row=0,
                            col=col)
            brain.plotter.subplot(0, col)
            vp = brain.plotter.renderer
            for ci in view[2]:  # figure out what we need to plot
                this_ch = info['chs'][ci - 1]
                ch_name = this_ch['ch_name'].split()[0]
                s_name, d_name = ch_name.split('_')
                needed = [
                    (ch_names, 'ch_names', ch_name, this_ch['loc'][:3], 12,
                     'Centered'),
                    (src_det_names, 'src_det_names', s_name,
                     this_ch['loc'][3:6], 8, 'Bottom'),
                    (src_det_names, 'src_det_names', d_name,
                     this_ch['loc'][6:9], 8, 'Bottom'),
                ]
                for lookup, lname, name, ch_pos, font_size, va in needed:
                    if name in plotted:
                        continue
                    plotted.add(name)
                    orig_name = name
                    if lookup is not None:
                        name = lookup[name]
                    _validate_type(name, str, f'{lname}[{repr(orig_name)}]')
                    ch_pos = apply_trans(head_mri_t, ch_pos)
                    vp.SetWorldPoint(np.r_[ch_pos, 1.])
                    vp.WorldToDisplay()
                    ch_pos = (np.array(vp.GetDisplayPoint()[:2]) -
                              np.array(vp.GetOrigin()))
                    actor = brain.plotter.add_text(name,
                                                   ch_pos,
                                                   font_size=font_size,
                                                   color=(0., 0., 0.),
                                                   **add_text_kwargs)
                    prop = actor.GetTextProperty()
                    getattr(prop, f'SetVerticalJustificationTo{va}')()
                    prop.SetJustificationToCentered()
                    actor.SetTextProperty(prop)
                    prop.SetBold(True)
        img = brain.screenshot()
    return plt.figimage(img, resize=True).figure
Example #29
0
def test_get_trans():
    """Test converting '-trans.txt' to '-trans.fif'."""
    trans = read_trans(fname)
    trans = invert_transform(trans)  # starts out as head->MRI, so invert
    trans_2 = _get_trans(fname_trans)[0]
    assert trans.__eq__(trans_2, atol=1e-5)