Пример #1
0
def test_sf_to_sh():
    # Subdividing a hemi_icosahedron twice produces 81 unique points, which
    # is more than enough to fit a order 8 (45 coefficients) spherical harmonic
    sphere = hemi_icosahedron.subdivide(2)

    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))
    mevecs = [np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
              np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])]

    odf = multi_tensor_odf(sphere.vertices, [0.5, 0.5], mevals, mevecs)

    # 1D case with the 3 bases functions
    odf_sh = sf_to_sh(odf, sphere, 8)
    odf2 = sh_to_sf(odf_sh, sphere, 8)
    assert_array_almost_equal(odf, odf2, 2)

    odf_sh = sf_to_sh(odf, sphere, 8, "mrtrix")
    odf2 = sh_to_sf(odf_sh, sphere, 8, "mrtrix")
    assert_array_almost_equal(odf, odf2, 2)

    odf_sh = sf_to_sh(odf, sphere, 8, "fibernav")
    odf2 = sh_to_sf(odf_sh, sphere, 8, "fibernav")
    assert_array_almost_equal(odf, odf2, 2)

    # 2D case
    odf2d = np.vstack((odf2, odf))
    odf2d_sh = sf_to_sh(odf2d, sphere, 8)
    odf2d_sf = sh_to_sf(odf2d_sh, sphere, 8)
    assert_array_almost_equal(odf2d, odf2d_sf, 2)
Пример #2
0
    def test_single_voxel_fit(self):
        signal, gtab, expected = make_fake_signal()
        sphere = hemi_icosahedron.subdivide(4)

        model = self.model(gtab, sh_order=4, min_signal=1e-5,
                           assume_normed=True)
        fit = model.fit(signal)
        odf = fit.odf(sphere)
        assert_equal(odf.shape, sphere.phi.shape)
        directions, _, _ = peak_directions(odf, sphere)
        # Check the same number of directions
        n = len(expected)
        assert_equal(len(directions), n)
        # Check directions are unit vectors
        cos_similarity = (directions * directions).sum(-1)
        assert_array_almost_equal(cos_similarity, np.ones(n))
        # Check the directions == expected or -expected
        cos_similarity = (directions * expected).sum(-1)
        assert_array_almost_equal(abs(cos_similarity), np.ones(n))

        # Test normalize data
        model = self.model(gtab, sh_order=4, min_signal=1e-5,
                           assume_normed=False)
        fit = model.fit(signal * 5)
        odf_with_norm = fit.odf(sphere)
        assert_array_almost_equal(odf, odf_with_norm)
Пример #3
0
def test_hemisphere_find_closest():
    hemisphere1 = hemi_icosahedron.subdivide(4)
    for ii in range(hemisphere1.vertices.shape[0]):
        nt.assert_equal(hemisphere1.find_closest(hemisphere1.vertices[ii]), ii)
        nt.assert_equal(hemisphere1.find_closest(-hemisphere1.vertices[ii]), ii)
        nt.assert_equal(hemisphere1.find_closest(hemisphere1.vertices[ii] * 2),
                        ii)
Пример #4
0
 def test_gfa(self):
     signal, gtab, expected = make_fake_signal()
     signal = np.ones((2, 3, 4, 1)) * signal
     sphere = hemi_icosahedron.subdivide(3)
     model = self.model(gtab, 6, min_signal=1e-5)
     fit = model.fit(signal)
     gfa_shm = fit.gfa
     gfa_odf = odf.gfa(fit.odf(sphere))
     assert_array_almost_equal(gfa_shm, gfa_odf, 3)
Пример #5
0
def test_real_sph_harm_fibernav():
    # This test should do for now
    # The mrtrix basis should be the same as re-ordering and re-scaling the
    # fibernav basis
    new_order = [0, 5, 4, 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, 7, 6]
    sphere = hemi_icosahedron.subdivide(2)
    basis, m, n = real_sph_harm_mrtrix(4, sphere.theta, sphere.phi)
    expected = basis[:, new_order]
    expected *= np.where(m == 0, 1., np.sqrt(2))

    fibernav_basis, m, n = real_sph_harm_fibernav(4, sphere.theta, sphere.phi)
    assert_array_almost_equal(fibernav_basis, expected)
Пример #6
0
def test_real_sym_sh_basis():
    # This test should do for now
    # The tournier07 basis should be the same as re-ordering and re-scaling the
    # descoteaux07 basis
    new_order = [0, 5, 4, 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, 7, 6]
    sphere = hemi_icosahedron.subdivide(2)
    basis, m, n = real_sym_sh_mrtrix(4, sphere.theta, sphere.phi)
    expected = basis[:, new_order]
    expected *= np.where(m == 0, 1., np.sqrt(2))

    descoteaux07_basis, m, n = real_sym_sh_basis(4, sphere.theta, sphere.phi)
    assert_array_almost_equal(descoteaux07_basis, expected)
Пример #7
0
def test_real_sym_sh_basis():
    # This test should do for now
    # The tournier07 basis should be the same as re-ordering and re-scaling the
    # descoteaux07 basis
    new_order = [0, 5, 4, 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, 7, 6]
    sphere = hemi_icosahedron.subdivide(2)
    basis, m, n = real_sym_sh_mrtrix(4, sphere.theta, sphere.phi)
    expected = basis[:, new_order]
    expected *= np.where(m == 0, 1., np.sqrt(2))

    descoteaux07_basis, m, n = real_sym_sh_basis(4, sphere.theta, sphere.phi)
    assert_array_almost_equal(descoteaux07_basis, expected)
Пример #8
0
    def test_gfa(self):
        signal, gtab, expected = make_fake_signal()
        signal = np.ones((2, 3, 4, 1)) * signal
        sphere = hemi_icosahedron.subdivide(3)
        model = self.model(gtab, 6, min_signal=1e-5)
        fit = model.fit(signal)
        gfa_shm = fit.gfa
        gfa_odf = odf.gfa(fit.odf(sphere))
        assert_array_almost_equal(gfa_shm, gfa_odf, 3)

        # gfa should be 0 if all coefficients are 0 (masked areas)
        mask = np.zeros(signal.shape[:-1])
        fit = model.fit(signal, mask)
        assert_array_equal(fit.gfa, 0)
Пример #9
0
    def test_gfa(self):
        signal, gtab, expected = make_fake_signal()
        signal = np.ones((2, 3, 4, 1)) * signal
        sphere = hemi_icosahedron.subdivide(3)
        model = self.model(gtab, 6, min_signal=1e-5)
        fit = model.fit(signal)
        gfa_shm = fit.gfa
        gfa_odf = odf.gfa(fit.odf(sphere))
        assert_array_almost_equal(gfa_shm, gfa_odf, 3)

        # gfa should be 0 if all coefficients are 0 (masked areas)
        mask = np.zeros(signal.shape[:-1])
        fit = model.fit(signal, mask)
        assert_array_equal(fit.gfa, 0)
Пример #10
0
def make_fake_signal():
    hemisphere = hemi_icosahedron.subdivide(2)
    bvecs = np.concatenate(([[0, 0, 0]], hemisphere.vertices))
    bvals = np.zeros(len(bvecs)) + 2000
    bvals[0] = 0
    gtab = gradient_table(bvals, bvecs)

    evals = np.array([[2.1, .2, .2], [.2, 2.1, .2]]) * 10 ** -3
    evecs0 = np.eye(3)
    evecs1 = evecs0
    a = evecs0[0]
    b = evecs1[1]
    S1 = single_tensor(gtab, .55, evals[0], evecs0)
    S2 = single_tensor(gtab, .45, evals[1], evecs1)
    return S1 + S2, gtab, np.vstack([a, b])
Пример #11
0
def make_fake_signal():
    hemisphere = hemi_icosahedron.subdivide(2)
    bvecs = np.concatenate(([[0, 0, 0]], hemisphere.vertices))
    bvals = np.zeros(len(bvecs)) + 2000
    bvals[0] = 0
    gtab = gradient_table(bvals, bvecs)

    evals = np.array([[2.1, .2, .2], [.2, 2.1, .2]]) * 10**-3
    evecs0 = np.eye(3)
    evecs1 = evecs0
    a = evecs0[0]
    b = evecs1[1]
    S1 = single_tensor(gtab, .55, evals[0], evecs0)
    S2 = single_tensor(gtab, .45, evals[1], evecs1)
    return S1 + S2, gtab, np.vstack([a, b])
Пример #12
0
def test_sf_to_sh():
    # Subdividing a hemi_icosahedron twice produces 81 unique points, which
    # is more than enough to fit a order 8 (45 coefficients) spherical harmonic
    sphere = hemi_icosahedron.subdivide(2)

    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))
    angles = [(0, 0), (90, 0)]

    odf = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50])

    # 1D case with the 3 bases functions
    odf_sh = sf_to_sh(odf, sphere, 8)
    odf2 = sh_to_sf(odf_sh, sphere, 8)
    assert_array_almost_equal(odf, odf2, 2)

    odf_sh = sf_to_sh(odf, sphere, 8, "tournier07")
    odf2 = sh_to_sf(odf_sh, sphere, 8, "tournier07")
    assert_array_almost_equal(odf, odf2, 2)

    # Test the basis naming deprecation
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always", DeprecationWarning)
        odf_sh_mrtrix = sf_to_sh(odf, sphere, 8, "mrtrix")
        odf2_mrtrix = sh_to_sf(odf_sh_mrtrix, sphere, 8, "mrtrix")
        assert_array_almost_equal(odf, odf2_mrtrix, 2)
        assert len(w) != 0
        assert issubclass(w[-1].category, DeprecationWarning)
        warnings.simplefilter("default", DeprecationWarning)

    odf_sh = sf_to_sh(odf, sphere, 8, "descoteaux07")
    odf2 = sh_to_sf(odf_sh, sphere, 8, "descoteaux07")
    assert_array_almost_equal(odf, odf2, 2)

    # Test the basis naming deprecation
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always", DeprecationWarning)
        odf_sh_fibernav = sf_to_sh(odf, sphere, 8, "fibernav")
        odf2_fibernav = sh_to_sf(odf_sh_fibernav, sphere, 8, "fibernav")
        assert_array_almost_equal(odf, odf2_fibernav, 2)
        assert len(w) != 0
        assert issubclass(w[-1].category, DeprecationWarning)
        warnings.simplefilter("default", DeprecationWarning)

    # 2D case
    odf2d = np.vstack((odf2, odf))
    odf2d_sh = sf_to_sh(odf2d, sphere, 8)
    odf2d_sf = sh_to_sf(odf2d_sh, sphere, 8)
    assert_array_almost_equal(odf2d, odf2d_sf, 2)
Пример #13
0
def test_sf_to_sh():
    # Subdividing a hemi_icosahedron twice produces 81 unique points, which
    # is more than enough to fit a order 8 (45 coefficients) spherical harmonic
    sphere = hemi_icosahedron.subdivide(2)

    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))
    angles = [(0, 0), (90, 0)]

    odf = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50])

    # 1D case with the 3 bases functions
    odf_sh = sf_to_sh(odf, sphere, 8)
    odf2 = sh_to_sf(odf_sh, sphere, 8)
    assert_array_almost_equal(odf, odf2, 2)

    odf_sh = sf_to_sh(odf, sphere, 8, "tournier07")
    odf2 = sh_to_sf(odf_sh, sphere, 8, "tournier07")
    assert_array_almost_equal(odf, odf2, 2)

    # Test the basis naming deprecation
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always", DeprecationWarning)
        odf_sh_mrtrix = sf_to_sh(odf, sphere, 8, "mrtrix")
        odf2_mrtrix = sh_to_sf(odf_sh_mrtrix, sphere, 8, "mrtrix")
        assert_array_almost_equal(odf, odf2_mrtrix, 2)
        assert len(w) != 0
        assert issubclass(w[-1].category, DeprecationWarning)
        warnings.simplefilter("default", DeprecationWarning)

    odf_sh = sf_to_sh(odf, sphere, 8, "descoteaux07")
    odf2 = sh_to_sf(odf_sh, sphere, 8, "descoteaux07")
    assert_array_almost_equal(odf, odf2, 2)

    # Test the basis naming deprecation
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always", DeprecationWarning)
        odf_sh_fibernav = sf_to_sh(odf, sphere, 8, "fibernav")
        odf2_fibernav = sh_to_sf(odf_sh_fibernav, sphere, 8, "fibernav")
        assert_array_almost_equal(odf, odf2_fibernav, 2)
        assert len(w) != 0
        assert issubclass(w[-1].category, DeprecationWarning)
        warnings.simplefilter("default", DeprecationWarning)

    # 2D case
    odf2d = np.vstack((odf2, odf))
    odf2d_sh = sf_to_sh(odf2d, sphere, 8)
    odf2d_sf = sh_to_sf(odf2d_sh, sphere, 8)
    assert_array_almost_equal(odf2d, odf2d_sf, 2)
Пример #14
0
def test_sf_to_sh():
    # Subdividing a hemi_icosahedron twice produces 81 unique points, which
    # is more than enough to fit a order 8 (45 coefficients) spherical harmonic
    hemisphere = hemi_icosahedron.subdivide(2)
    mevals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]])
    angles = [(0, 0), (60, 0)]
    odf = multi_tensor_odf(hemisphere.vertices, mevals, angles, [50, 50])

    # 1D case with the 2 symmetric bases functions
    odf_sh = sf_to_sh(odf, hemisphere, 8, "tournier07")
    odf_reconst = sh_to_sf(odf_sh, hemisphere, 8, "tournier07")
    assert_array_almost_equal(odf, odf_reconst, 2)

    odf_sh = sf_to_sh(odf, hemisphere, 8, "descoteaux07")
    odf_reconst = sh_to_sf(odf_sh, hemisphere, 8, "descoteaux07")
    assert_array_almost_equal(odf, odf_reconst, 2)

    # We now create an asymmetric signal
    # to try out our full SH basis
    mevals = np.array([[0.0015, 0.0003, 0.0003]])
    angles = [(0, 0)]
    odf2 = multi_tensor_odf(hemisphere.vertices, mevals, angles, [100])

    # We simulate our asymmetric signal by using a different ODF
    # per hemisphere. The sphere used is a concatenation of the
    # vertices of our hemisphere, for a total of 162 vertices.
    sphere = Sphere(xyz=np.vstack((hemisphere.vertices, -hemisphere.vertices)))
    asym_odf = np.append(odf, odf2)

    # Try out full bases with order 10 (121 coefficients)
    odf_sh = sf_to_sh(asym_odf, sphere, 10, "tournier07_full")
    odf_reconst = sh_to_sf(odf_sh, sphere, 10, "tournier07_full")
    assert_array_almost_equal(odf_reconst, asym_odf, 2)

    odf_sh = sf_to_sh(asym_odf, sphere, 10, "descoteaux07_full")
    odf_reconst = sh_to_sf(odf_sh, sphere, 10, "descoteaux07_full")
    assert_array_almost_equal(odf_reconst, asym_odf, 2)

    # An invalid basis name should raise an error
    assert_raises(ValueError, sh_to_sf, odf, hemisphere, basis_type="")
    assert_raises(ValueError, sf_to_sh, odf_sh, hemisphere, basis_type="")

    # 2D case
    odf2d = np.vstack((odf, odf))
    odf2d_sh = sf_to_sh(odf2d, hemisphere, 8)
    odf2d_sf = sh_to_sf(odf2d_sh, hemisphere, 8)
    assert_array_almost_equal(odf2d, odf2d_sf, 2)
Пример #15
0
def test_convert_sh_to_legacy():
    hemisphere = hemi_icosahedron.subdivide(2)
    mevals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]])
    angles = [(0, 0), (60, 0)]
    odf = multi_tensor_odf(hemisphere.vertices, mevals, angles, [50, 50])

    sh_coeffs = sf_to_sh(odf, hemisphere, 8, legacy=False)
    converted_coeffs = convert_sh_to_legacy(sh_coeffs, 'descoteaux07')
    expected_coeffs = sf_to_sh(odf, hemisphere, 8, legacy=True)

    assert_array_almost_equal(converted_coeffs, expected_coeffs, 2)

    sh_coeffs = sf_to_sh(odf,
                         hemisphere,
                         8,
                         basis_type='tournier07',
                         legacy=False)
    converted_coeffs = convert_sh_to_legacy(sh_coeffs, 'tournier07')
    expected_coeffs = sf_to_sh(odf,
                               hemisphere,
                               8,
                               basis_type='tournier07',
                               legacy=True)

    assert_array_almost_equal(converted_coeffs, expected_coeffs, 2)

    # 2D case
    odfs = np.array([odf, odf])
    sh_coeffs = sf_to_sh(odfs,
                         hemisphere,
                         8,
                         basis_type='tournier07',
                         full_basis=True,
                         legacy=False)
    converted_coeffs = convert_sh_to_legacy(sh_coeffs,
                                            'tournier07',
                                            full_basis=True)
    expected_coeffs = sf_to_sh(odfs,
                               hemisphere,
                               8,
                               basis_type='tournier07',
                               legacy=True,
                               full_basis=True)

    assert_array_almost_equal(converted_coeffs, expected_coeffs, 2)
    assert_raises(ValueError, convert_sh_to_legacy, sh_coeffs, '', True)
Пример #16
0
def test_hat_and_lcr():
    hemi = hemi_icosahedron.subdivide(3)
    m, n = sph_harm_ind_list(8)
    B = real_sph_harm(m, n, hemi.theta[:, None], hemi.phi[:, None])
    H = hat(B)
    B_hat = np.dot(H, B)
    assert_array_almost_equal(B, B_hat)

    R = lcr_matrix(H)
    d = np.arange(len(hemi.theta))
    r = d - np.dot(H, d)
    lev = np.sqrt(1 - H.diagonal())
    r /= lev
    r -= r.mean()

    r2 = np.dot(R, d)
    assert_array_almost_equal(r, r2)

    r3 = np.dot(d, R.T)
    assert_array_almost_equal(r, r3)
Пример #17
0
def test_hat_and_lcr():
    hemi = hemi_icosahedron.subdivide(3)
    m, n = sph_harm_ind_list(8)
    B = real_sph_harm(m, n, hemi.theta[:, None], hemi.phi[:, None])
    H = hat(B)
    B_hat = np.dot(H, B)
    assert_array_almost_equal(B, B_hat)

    R = lcr_matrix(H)
    d = np.arange(len(hemi.theta))
    r = d - np.dot(H, d)
    lev = np.sqrt(1 - H.diagonal())
    r /= lev
    r -= r.mean()

    r2 = np.dot(R, d)
    assert_array_almost_equal(r, r2)

    r3 = np.dot(d, R.T)
    assert_array_almost_equal(r, r3)
Пример #18
0
def test_real_full_sh_basis():
    vertices = hemi_icosahedron.subdivide(2).vertices
    mevals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]])
    angles = [(0, 0), (60, 0)]
    odf = multi_tensor_odf(vertices, mevals, angles, [50, 50])

    mevals = np.array([[0.0015, 0.0003, 0.0003]])
    angles = [(0, 0)]
    odf2 = multi_tensor_odf(-vertices, mevals, angles, [100])

    sphere = Sphere(xyz=np.vstack((vertices, -vertices)))
    # Asymmetric spherical function with 162 coefficients
    sf = np.append(odf, odf2)

    # In order for our approximation to be precise enough, we
    # will use a SH basis of orders up to 10 (121 coefficients)
    B, m, n = real_full_sh_basis(10, sphere.theta, sphere.phi)
    invB = smooth_pinv(B, L=np.zeros_like(n))
    sh_coefs = np.dot(invB, sf)
    sf_approx = np.dot(B, sh_coefs)

    assert_array_almost_equal(sf_approx, sf, 2)
Пример #19
0
def test_convert_sh_to_full_basis():
    hemisphere = hemi_icosahedron.subdivide(2)
    mevals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]])
    angles = [(0, 0), (60, 0)]
    odf = multi_tensor_odf(hemisphere.vertices, mevals, angles, [50, 50])

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        sh_coeffs = sf_to_sh(odf, hemisphere, 8)

    full_sh_coeffs = convert_sh_to_full_basis(sh_coeffs)

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)

        odf_reconst = sh_to_sf(full_sh_coeffs, hemisphere, 8, full_basis=True)

    assert_array_almost_equal(odf, odf_reconst, 2)
Пример #20
0
def test_smooth_pinv():
    hemi = hemi_icosahedron.subdivide(2)
    m, n = sph_harm_ind_list(4)
    B = real_sph_harm(m, n, hemi.theta[:, None], hemi.phi[:, None])

    L = np.zeros(len(m))
    C = smooth_pinv(B, L)
    D = np.dot(npl.inv(np.dot(B.T, B)), B.T)
    assert_array_almost_equal(C, D)

    L = n * (n + 1) * .05
    C = smooth_pinv(B, L)
    L = np.diag(L)
    D = np.dot(npl.inv(np.dot(B.T, B) + L * L), B.T)

    assert_array_almost_equal(C, D)

    L = np.arange(len(n)) * .05
    C = smooth_pinv(B, L)
    L = np.diag(L)
    D = np.dot(npl.inv(np.dot(B.T, B) + L * L), B.T)
    assert_array_almost_equal(C, D)
Пример #21
0
def test_smooth_pinv():
    hemi = hemi_icosahedron.subdivide(2)
    m, n = sph_harm_ind_list(4)
    B = real_sph_harm(m, n, hemi.theta[:, None], hemi.phi[:, None])

    L = np.zeros(len(m))
    C = smooth_pinv(B, L)
    D = np.dot(npl.inv(np.dot(B.T, B)), B.T)
    assert_array_almost_equal(C, D)

    L = n * (n + 1) * .05
    C = smooth_pinv(B, L)
    L = np.diag(L)
    D = np.dot(npl.inv(np.dot(B.T, B) + L * L), B.T)

    assert_array_almost_equal(C, D)

    L = np.arange(len(n)) * .05
    C = smooth_pinv(B, L)
    L = np.diag(L)
    D = np.dot(npl.inv(np.dot(B.T, B) + L * L), B.T)
    assert_array_almost_equal(C, D)
Пример #22
0
def test_real_sh_descoteaux1():
    # This test should do for now
    # The tournier07 basis should be the same as re-ordering and re-scaling the
    # descoteaux07 basis
    new_order = [0, 5, 4, 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, 7, 6]
    sphere = hemi_icosahedron.subdivide(2)

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore")
        basis, m, n = real_sym_sh_mrtrix(4, sphere.theta, sphere.phi)

    expected = basis[:, new_order]
    expected *= np.where(m == 0, 1., np.sqrt(2))

    with warnings.catch_warnings(record=True) as w:
        descoteaux07_basis, m, n = real_sh_descoteaux(4, sphere.theta,
                                                      sphere.phi)

    npt.assert_equal(len(w), 1)
    npt.assert_(issubclass(w[0].category, PendingDeprecationWarning))
    npt.assert_(descoteaux07_legacy_msg in str(w[0].message))

    assert_array_almost_equal(descoteaux07_basis, expected)
Пример #23
0
def test_convert_sh_to_legacy():
    hemisphere = hemi_icosahedron.subdivide(2)
    mevals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]])
    angles = [(0, 0), (60, 0)]
    odf = multi_tensor_odf(hemisphere.vertices, mevals, angles, [50, 50])

    sh_coeffs = sf_to_sh(odf, hemisphere, 8, legacy=False)
    converted_coeffs = convert_sh_to_legacy(sh_coeffs, 'descoteaux07')

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)

        expected_coeffs = sf_to_sh(odf, hemisphere, 8, legacy=True)

    assert_array_almost_equal(converted_coeffs, expected_coeffs, 2)

    sh_coeffs = sf_to_sh(odf,
                         hemisphere,
                         8,
                         basis_type='tournier07',
                         legacy=False)
    converted_coeffs = convert_sh_to_legacy(sh_coeffs, 'tournier07')

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=tournier07_legacy_msg,
                                category=PendingDeprecationWarning)

        expected_coeffs = sf_to_sh(odf,
                                   hemisphere,
                                   8,
                                   basis_type='tournier07',
                                   legacy=True)

    assert_array_almost_equal(converted_coeffs, expected_coeffs, 2)

    # 2D case
    odfs = np.array([odf, odf])
    sh_coeffs = sf_to_sh(odfs,
                         hemisphere,
                         8,
                         basis_type='tournier07',
                         full_basis=True,
                         legacy=False)
    converted_coeffs = convert_sh_to_legacy(sh_coeffs,
                                            'tournier07',
                                            full_basis=True)
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=tournier07_legacy_msg,
                                category=PendingDeprecationWarning)

        expected_coeffs = sf_to_sh(odfs,
                                   hemisphere,
                                   8,
                                   basis_type='tournier07',
                                   legacy=True,
                                   full_basis=True)

    assert_array_almost_equal(converted_coeffs, expected_coeffs, 2)
    assert_raises(ValueError, convert_sh_to_legacy, sh_coeffs, '', True)