예제 #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_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, "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)
예제 #3
0
def test_r2_term_odf_sharp():
    SNR = None
    S0 = 1
    angle = 75

    _, fbvals, fbvecs = get_data('small_64D')  #get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    sphere = get_sphere('symmetric724')
    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003],
                       [0.0015, 0.0003, 0.0003]))

    S, sticks = multi_tensor(gtab, mevals, S0, angles=[(0, 0), (angle, 0)],
                             fractions=[50, 50], snr=SNR)
    
    
    mevecs = [all_tensor_evecs(sticks[0]).T,
              all_tensor_evecs(sticks[1]).T]

    odf_gt = multi_tensor_odf(sphere.vertices, [0.5, 0.5], mevals, mevecs)
    odfs_sh = sf_to_sh(odf_gt, sphere, sh_order=8, basis_type=None)
    fodf_sh = odf_sh_to_sharp(odfs_sh, sphere, basis=None, ratio=3 / 15.,
                              sh_order=8, lambda_=1., tau=0.1, r2_term=True)
    fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None)

    directions_gt, _, _ = peak_directions(odf_gt, sphere)
    directions, _, _ = peak_directions(fodf, sphere)

    ang_sim = angular_similarity(directions_gt, directions)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions.shape[0], 2)
예제 #4
0
def test_normalization():
    """ Test the normalization routine applied after a convolution"""
    # create kernel
    D33 = 1.0
    D44 = 0.04
    t = 1
    num_orientations = 5
    k = EnhancementKernel(D33,
                          D44,
                          t,
                          orientations=num_orientations,
                          force_recompute=True)

    # create a constant dataset
    numorientations = k.get_orientations().shape[0]
    spike = np.ones((7, 7, 7, numorientations), dtype=np.float64)

    # convert dataset to SH
    spike_sh = sf_to_sh(spike, k.get_sphere(), sh_order=8)

    # convolve kernel with delta spike and apply normalization
    csd_enh = convolve(spike_sh, k, sh_order=8, test_mode=True, normalize=True)

    # convert dataset to DSF
    csd_enh_dsf = sh_to_sf(csd_enh,
                           k.get_sphere(),
                           sh_order=8,
                           basis_type=None)

    # test if the normalization is performed correctly
    npt.assert_almost_equal(np.amax(csd_enh_dsf), np.amax(spike))
예제 #5
0
def test_odf_sh_to_sharp():
    SNR = None
    S0 = 1
    _, fbvals, fbvecs = get_fnames('small_64D')
    bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)
    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))

    S, _ = multi_tensor(gtab,
                        mevals,
                        S0,
                        angles=[(10, 0), (100, 0)],
                        fractions=[50, 50],
                        snr=SNR)

    sphere = default_sphere

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        qb = QballModel(gtab, sh_order=8, assume_normed=True)

    qbfit = qb.fit(S)
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        odf_gt = qbfit.odf(sphere)

    Z = np.linalg.norm(odf_gt)

    odfs_gt = np.zeros((3, 1, 1, odf_gt.shape[0]))
    odfs_gt[:, :, :] = odf_gt[:]

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        odfs_sh = sf_to_sh(odfs_gt, sphere, sh_order=8, basis_type=None)

    odfs_sh /= Z

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        fodf_sh = odf_sh_to_sharp(odfs_sh,
                                  sphere,
                                  basis=None,
                                  ratio=3 / 15.,
                                  sh_order=8,
                                  lambda_=1.,
                                  tau=0.1)

        fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None)

    directions2, _, _ = peak_directions(fodf[0, 0, 0], sphere)

    assert_equal(directions2.shape[0], 2)
예제 #6
0
def create_odf_slicer(sh_fodf, mask, sphere, nb_subdivide, sh_order, sh_basis,
                      full_basis, orientation, scale, radial_scale, norm,
                      colormap):
    """
    Create a ODF slicer actor displaying a fODF slice. The input volume is a
    3-dimensional grid containing the SH coefficients of the fODF for each
    voxel at each voxel, with the grid dimension having a size of 1 along the
    axis corresponding to the selected orientation.
    """
    # Subdivide the spheres if nb_subdivide is provided
    if nb_subdivide is not None:
        sphere = sphere.subdivide(nb_subdivide)

    # Convert SH coefficients to SF coefficients
    fodf = sh_to_sf(sh_fodf, sphere, sh_order, sh_basis, full_basis=full_basis)

    # Get mask if supplied, otherwise create a mask discarding empty voxels
    if mask is None:
        mask = np.linalg.norm(fodf, axis=-1) > 0.

    odf_actor = actor.odf_slicer(fodf,
                                 mask=mask,
                                 norm=norm,
                                 radial_scale=radial_scale,
                                 sphere=sphere,
                                 colormap=colormap,
                                 scale=scale)
    set_display_extent(odf_actor, orientation, fodf.shape)

    return odf_actor
예제 #7
0
파일: test_shm.py 프로젝트: tangwei/dipy
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)
예제 #8
0
def test_mapmri_odf(radial_order=6):
    gtab = get_gtab_taiwan_dsi()

    # load repulsion 724 sphere
    sphere = default_sphere

    # load icosahedron sphere
    l1, l2, l3 = [0.0015, 0.0003, 0.0003]
    data, golden_directions = generate_signal_crossing(gtab,
                                                       l1,
                                                       l2,
                                                       l3,
                                                       angle2=90)
    mapmod = MapmriModel(gtab,
                         radial_order=radial_order,
                         laplacian_regularization=True,
                         laplacian_weighting=0.01)
    # repulsion724
    sphere2 = create_unit_sphere(5)
    mapfit = mapmod.fit(data)
    odf = mapfit.odf(sphere)

    directions, _, _ = peak_directions(odf, sphere, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(angular_similarity(directions, golden_directions), 2,
                        1)

    # 5 subdivisions
    odf = mapfit.odf(sphere2)
    directions, _, _ = peak_directions(odf, sphere2, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(angular_similarity(directions, golden_directions), 2,
                        1)

    sb_dummies = sticks_and_ball_dummies(gtab)
    for sbd in sb_dummies:
        data, golden_directions = sb_dummies[sbd]
        asmfit = mapmod.fit(data)
        odf = asmfit.odf(sphere2)
        directions, _, _ = peak_directions(odf, sphere2, .35, 25)
        if len(directions) <= 3:
            assert_equal(len(directions), len(golden_directions))
        if len(directions) > 3:
            assert_equal(gfa(odf) < 0.1, True)

    # for the isotropic implementation check if the odf spherical harmonics
    # actually represent the discrete sphere function.
    mapmod = MapmriModel(gtab,
                         radial_order=radial_order,
                         laplacian_regularization=True,
                         laplacian_weighting=0.01,
                         anisotropic_scaling=False)
    mapfit = mapmod.fit(data)
    odf = mapfit.odf(sphere)
    odf_sh = mapfit.odf_sh()
    odf_from_sh = sh_to_sf(odf_sh, sphere, radial_order, basis_type=None)
    assert_almost_equal(odf, odf_from_sh, 10)
예제 #9
0
파일: test_shm.py 프로젝트: kerkelae/dipy
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])

    sh_coeffs = sf_to_sh(odf, hemisphere, 8)
    full_sh_coeffs = convert_sh_to_full_basis(sh_coeffs)
    odf_reconst = sh_to_sf(full_sh_coeffs, hemisphere, 8, full_basis=True)

    assert_array_almost_equal(odf, odf_reconst, 2)
예제 #10
0
def test_r2_term_odf_sharp():
    SNR = None
    S0 = 1
    angle = 45  # 45 degrees is a very tight angle to disentangle

    _, fbvals, fbvecs = get_data('small_64D')  # get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    sphere = get_sphere('symmetric724')
    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))

    angles = [(0, 0), (angle, 0)]

    S, sticks = multi_tensor(gtab,
                             mevals,
                             S0,
                             angles=angles,
                             fractions=[50, 50],
                             snr=SNR)

    odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50])
    odfs_sh = sf_to_sh(odf_gt, sphere, sh_order=8, basis_type=None)
    fodf_sh = odf_sh_to_sharp(odfs_sh,
                              sphere,
                              basis=None,
                              ratio=3 / 15.,
                              sh_order=8,
                              lambda_=1.,
                              tau=0.1,
                              r2_term=True)
    fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None)

    directions_gt, _, _ = peak_directions(odf_gt, sphere)
    directions, _, _ = peak_directions(fodf, sphere)

    ang_sim = angular_similarity(directions_gt, directions)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions.shape[0], 2)

    # This should pass as well
    sdt_model = ConstrainedSDTModel(gtab, ratio=3 / 15., sh_order=8)
    sdt_fit = sdt_model.fit(S)
    fodf = sdt_fit.odf(sphere)

    directions_gt, _, _ = peak_directions(odf_gt, sphere)
    directions, _, _ = peak_directions(fodf, sphere)
    ang_sim = angular_similarity(directions_gt, directions)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions.shape[0], 2)
예제 #11
0
def test_shore_odf():
    gtab = get_isbi2013_2shell_gtab()

    # load repulsion 724 sphere
    sphere = default_sphere

    # load icosahedron sphere
    sphere2 = create_unit_sphere(5)
    data, golden_directions = sticks_and_ball(gtab,
                                              d=0.0015,
                                              S0=100,
                                              angles=[(0, 0), (90, 0)],
                                              fractions=[50, 50],
                                              snr=None)
    asm = ShoreModel(gtab,
                     radial_order=6,
                     zeta=700,
                     lambdaN=1e-8,
                     lambdaL=1e-8)
    # repulsion724
    asmfit = asm.fit(data)
    odf = asmfit.odf(sphere)
    odf_sh = asmfit.odf_sh()
    odf_from_sh = sh_to_sf(odf_sh, sphere, 6, basis_type=None, legacy=True)
    npt.assert_almost_equal(odf, odf_from_sh, 10)

    expected_phi = shore_matrix(radial_order=6, zeta=700, gtab=gtab)
    npt.assert_array_almost_equal(np.dot(expected_phi, asmfit.shore_coeff),
                                  asmfit.fitted_signal())

    directions, _, _ = peak_directions(odf, sphere, .35, 25)
    npt.assert_equal(len(directions), 2)
    npt.assert_almost_equal(angular_similarity(directions, golden_directions),
                            2, 1)

    # 5 subdivisions
    odf = asmfit.odf(sphere2)
    directions, _, _ = peak_directions(odf, sphere2, .35, 25)
    npt.assert_equal(len(directions), 2)
    npt.assert_almost_equal(angular_similarity(directions, golden_directions),
                            2, 1)

    sb_dummies = sticks_and_ball_dummies(gtab)
    for sbd in sb_dummies:
        data, golden_directions = sb_dummies[sbd]
        asmfit = asm.fit(data)
        odf = asmfit.odf(sphere2)
        directions, _, _ = peak_directions(odf, sphere2, .35, 25)
        if len(directions) <= 3:
            npt.assert_equal(len(directions), len(golden_directions))
        if len(directions) > 3:
            npt.assert_equal(gfa(odf) < 0.1, True)
예제 #12
0
def test_mapmri_odf(radial_order=6):
    gtab = get_gtab_taiwan_dsi()

    # load symmetric 724 sphere
    sphere = get_sphere('symmetric724')

    # load icosahedron sphere
    l1, l2, l3 = [0.0015, 0.0003, 0.0003]
    data, golden_directions = generate_signal_crossing(gtab, l1, l2, l3,
                                                       angle2=90)
    mapmod = MapmriModel(gtab, radial_order=radial_order,
                         laplacian_regularization=True,
                         laplacian_weighting=0.01)
    # symmetric724
    sphere2 = create_unit_sphere(5)
    mapfit = mapmod.fit(data)
    odf = mapfit.odf(sphere)

    directions, _, _ = peak_directions(odf, sphere, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(
        angular_similarity(directions, golden_directions), 2, 1)

    # 5 subdivisions
    odf = mapfit.odf(sphere2)
    directions, _, _ = peak_directions(odf, sphere2, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(
        angular_similarity(directions, golden_directions), 2, 1)

    sb_dummies = sticks_and_ball_dummies(gtab)
    for sbd in sb_dummies:
        data, golden_directions = sb_dummies[sbd]
        asmfit = mapmod.fit(data)
        odf = asmfit.odf(sphere2)
        directions, _, _ = peak_directions(odf, sphere2, .35, 25)
        if len(directions) <= 3:
            assert_equal(len(directions), len(golden_directions))
        if len(directions) > 3:
            assert_equal(gfa(odf) < 0.1, True)

    # for the isotropic implementation check if the odf spherical harmonics
    # actually represent the discrete sphere function.
    mapmod = MapmriModel(gtab, radial_order=radial_order,
                         laplacian_regularization=True,
                         laplacian_weighting=0.01,
                         anisotropic_scaling=False)
    mapfit = mapmod.fit(data)
    odf = mapfit.odf(sphere)
    odf_sh = mapfit.odf_sh()
    odf_from_sh = sh_to_sf(odf_sh, sphere, radial_order, basis_type=None)
    assert_almost_equal(odf, odf_from_sh, 10)
예제 #13
0
def test_odf_sh_to_sharp():

    SNR = 100
    S0 = 1

    _, fbvals, fbvecs = get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))

    S, sticks = multi_tensor(gtab,
                             mevals,
                             S0,
                             angles=[(10, 0), (100, 0)],
                             fractions=[50, 50],
                             snr=SNR)

    sphere = get_sphere('symmetric724')

    qb = QballModel(gtab, sh_order=8, assume_normed=True)

    qbfit = qb.fit(S)
    odf_gt = qbfit.odf(sphere)

    Z = np.linalg.norm(odf_gt)

    odfs_gt = np.zeros((3, 1, 1, odf_gt.shape[0]))
    odfs_gt[:, :, :] = odf_gt[:]

    odfs_sh = sf_to_sh(odfs_gt, sphere, sh_order=8, basis_type=None)

    odfs_sh /= Z

    fodf_sh = odf_sh_to_sharp(odfs_sh,
                              sphere,
                              basis=None,
                              ratio=3 / 15.,
                              sh_order=8,
                              lambda_=1.,
                              tau=1.)

    fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None)

    directions2, _, _ = peak_directions(fodf[0, 0, 0], sphere)

    assert_equal(directions2.shape[0], 2)
예제 #14
0
def main():
    odf_file = sys.argv[1]
    bvec_file = sys.argv[2]
    basis = sys.argv[3]

    odf = nib.load(odf_file)
    odf_sh = odf.get_fdata()
    bvec = np.loadtxt(bvec_file)
    bvec = bvec[1:, :]

    sph_gtab = Sphere(xyz=np.vstack(bvec))
    print(odf_sh.shape)

    odf_sf = sh_to_sf(odf_sh, sph_gtab, basis_type=basis, sh_order=8)
    visu_odf(bvec, odf_sf)
예제 #15
0
def test_shore_odf():
    gtab = get_isbi2013_2shell_gtab()

    # load symmetric 724 sphere
    sphere = get_sphere('symmetric724')

    # load icosahedron sphere
    sphere2 = create_unit_sphere(5)
    data, golden_directions = SticksAndBall(gtab,
                                            d=0.0015,
                                            S0=100,
                                            angles=[(0, 0), (90, 0)],
                                            fractions=[50, 50],
                                            snr=None)
    asm = ShoreModel(gtab,
                     radial_order=6,
                     zeta=700,
                     lambdaN=1e-8,
                     lambdaL=1e-8)
    # symmetric724
    asmfit = asm.fit(data)
    odf = asmfit.odf(sphere)
    odf_sh = asmfit.odf_sh()
    odf_from_sh = sh_to_sf(odf_sh, sphere, 6, basis_type=None)
    assert_almost_equal(odf, odf_from_sh, 10)

    directions, _, _ = peak_directions(odf, sphere, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(angular_similarity(directions, golden_directions), 2,
                        1)

    # 5 subdivisions
    odf = asmfit.odf(sphere2)
    directions, _, _ = peak_directions(odf, sphere2, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(angular_similarity(directions, golden_directions), 2,
                        1)

    sb_dummies = sticks_and_ball_dummies(gtab)
    for sbd in sb_dummies:
        data, golden_directions = sb_dummies[sbd]
        asmfit = asm.fit(data)
        odf = asmfit.odf(sphere2)
        directions, _, _ = peak_directions(odf, sphere2, .35, 25)
        if len(directions) <= 3:
            assert_equal(len(directions), len(golden_directions))
        if len(directions) > 3:
            assert_equal(gfa(odf) < 0.1, True)
예제 #16
0
def test_shore_odf():
    gtab = get_isbi2013_2shell_gtab()

    # load symmetric 724 sphere
    sphere = get_sphere('symmetric724')

    # load icosahedron sphere
    sphere2 = create_unit_sphere(5)
    data, golden_directions = SticksAndBall(gtab, d=0.0015,
                                            S0=100, angles=[(0, 0), (90, 0)],
                                            fractions=[50, 50], snr=None)
    asm = ShoreModel(gtab, radial_order=6,
                     zeta=700, lambdaN=1e-8, lambdaL=1e-8)
    # symmetric724
    asmfit = asm.fit(data)
    odf = asmfit.odf(sphere)
    odf_sh = asmfit.odf_sh()
    odf_from_sh = sh_to_sf(odf_sh, sphere, 6, basis_type=None)
    assert_almost_equal(odf, odf_from_sh, 10)


    directions, _ , _ = peak_directions(odf, sphere, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(
        angular_similarity(directions, golden_directions), 2, 1)

    # 5 subdivisions
    odf = asmfit.odf(sphere2)
    directions, _ , _ = peak_directions(odf, sphere2, .35, 25)
    assert_equal(len(directions), 2)
    assert_almost_equal(
        angular_similarity(directions, golden_directions), 2, 1)

    sb_dummies = sticks_and_ball_dummies(gtab)
    for sbd in sb_dummies:
        data, golden_directions = sb_dummies[sbd]
        asmfit = asm.fit(data)
        odf = asmfit.odf(sphere2)
        directions, _ , _ = peak_directions(odf, sphere2, .35, 25)
        if len(directions) <= 3:
            assert_equal(len(directions), len(golden_directions))
        if len(directions) > 3:
            assert_equal(gfa(odf) < 0.1, True)
예제 #17
0
def test_r2_term_odf_sharp():
    SNR = None
    S0 = 1
    angle = 45 #45 degrees is a very tight angle to disentangle

    _, fbvals, fbvecs = get_data('small_64D')  #get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    sphere = get_sphere('symmetric724')
    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003],
                       [0.0015, 0.0003, 0.0003]))

    angles = [(0, 0), (angle, 0)]

    S, sticks = multi_tensor(gtab, mevals, S0, angles=angles,
                             fractions=[50, 50], snr=SNR)    

    odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50])
    odfs_sh = sf_to_sh(odf_gt, sphere, sh_order=8, basis_type=None)
    fodf_sh = odf_sh_to_sharp(odfs_sh, sphere, basis=None, ratio=3 / 15.,
                              sh_order=8, lambda_=1., tau=0.1, r2_term=True)
    fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None)

    directions_gt, _, _ = peak_directions(odf_gt, sphere)
    directions, _, _ = peak_directions(fodf, sphere)

    ang_sim = angular_similarity(directions_gt, directions)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions.shape[0], 2)

    # This should pass as well
    sdt_model = ConstrainedSDTModel(gtab, ratio=3/15., sh_order=8)
    sdt_fit = sdt_model.fit(S)
    fodf = sdt_fit.odf(sphere)
    
    directions_gt, _, _ = peak_directions(odf_gt, sphere)
    directions, _, _ = peak_directions(fodf, sphere)
    ang_sim = angular_similarity(directions_gt, directions)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions.shape[0], 2)
def test_spherical_convolution_watson_sh(sh_order=4):
    sphere = get_sphere('symmetric724')

    n = sphere.vertices
    bval = np.tile(1e9, len(n))
    scheme = acquisition_scheme_from_bvalues(bval, n, delta, Delta)
    indices_sphere_orientations = np.arange(sphere.vertices.shape[0])
    np.random.shuffle(indices_sphere_orientations)
    mu_index = indices_sphere_orientations[0]
    mu_watson = sphere.vertices[mu_index]
    mu_watson_sphere = utils.cart2sphere(mu_watson)[1:]

    watson = distributions.SD1Watson(mu=mu_watson_sphere, odi=.3)
    f_sf = watson(n=sphere.vertices)
    f_sh = sf_to_sh(f_sf, sphere, sh_order)

    lambda_par = 2e-9
    stick = cylinder_models.C1Stick(mu=[0, 0], lambda_par=lambda_par)
    k_sf = stick(scheme)
    sh_matrix, m, n = real_sym_sh_mrtrix(sh_order, sphere.theta, sphere.phi)
    sh_matrix_inv = np.linalg.pinv(sh_matrix)
    k_sh = np.dot(sh_matrix_inv, k_sf)
    k_rh = k_sh[m == 0]

    fk_convolved_sh = sh_convolution(f_sh, k_rh)
    fk_convolved_sf = sh_to_sf(fk_convolved_sh, sphere, sh_order)

    # assert if spherical mean is the same between kernel and convolved kernel
    assert_almost_equal(abs(np.mean(k_sf) - np.mean(fk_convolved_sf)), 0., 2)
    # assert if the lowest signal attenuation (E(b,n)) is orientation along
    # the orientation of the watson distribution.
    min_position = np.argmin(fk_convolved_sf)

    if min_position == mu_index:
        assert_equal(min_position, mu_index)
    else:  # then it's the opposite direction
        sphere_positions = np.arange(sphere.vertices.shape[0])
        opposite_index = np.all(
            np.round(sphere.vertices - mu_watson, 2) == 0, axis=1
        )
        min_position_opposite = sphere_positions[opposite_index]
        assert_equal(min_position_opposite, mu_index)
예제 #19
0
def show_odf_sample(filename):

    odf_sh = nib.load(filename).get_data()

    from dipy.data import get_sphere

    sphere = get_sphere('symmetric724')

    odf = sh_to_sf(odf_sh, sphere, 8, 'mrtrix')

    from dipy.viz import fvtk
    r = fvtk.ren()
    #odf = odf[:, :, 25]
    #fvtk.add(r, fvtk.sphere_funcs(odf[:, :, None], sphere, norm=True))
    odf = odf[:, 22, :]
    #odf = odf[14: 23, 22, 34: 43]
    #odf = odf[14:24, 22, 23:33]
    fvtk.add(r, fvtk.sphere_funcs(odf[:, None, :], sphere, norm=True))

    fvtk.show(r)
예제 #20
0
def test_odf_sh_to_sharp():

    SNR = None
    S0 = 1

    _, fbvals, fbvecs = get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)

    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003],
                       [0.0015, 0.0003, 0.0003]))

    S, sticks = multi_tensor(gtab, mevals, S0, angles=[(10, 0), (100, 0)],
                             fractions=[50, 50], snr=SNR)

    sphere = get_sphere('symmetric724')

    qb = QballModel(gtab, sh_order=8, assume_normed=True)

    qbfit = qb.fit(S)
    odf_gt = qbfit.odf(sphere)

    Z = np.linalg.norm(odf_gt)

    odfs_gt = np.zeros((3, 1, 1, odf_gt.shape[0]))
    odfs_gt[:,:,:] = odf_gt[:]

    odfs_sh = sf_to_sh(odfs_gt, sphere, sh_order=8, basis_type=None)

    odfs_sh /= Z

    fodf_sh = odf_sh_to_sharp(odfs_sh, sphere, basis=None, ratio=3 / 15.,
                              sh_order=8, lambda_=1., tau=0.1)

    fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None)

    directions2, _, _ = peak_directions(fodf[0, 0, 0], sphere)

    assert_equal(directions2.shape[0], 2)
예제 #21
0
파일: test_shm.py 프로젝트: arokem/dipy
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)
예제 #22
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)
예제 #23
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)
예제 #24
0
파일: test_kernel.py 프로젝트: MPDean/dipy
def test_normalization():
    """ Test the normalization routine applied after a convolution"""
    # create kernel
    D33 = 1.0
    D44 = 0.04
    t = 1
    num_orientations = 5
    k = EnhancementKernel(D33, D44, t, orientations=num_orientations, force_recompute=True)

    # create a constant dataset
    numorientations = k.get_orientations().shape[0]
    spike = np.ones((7, 7, 7, numorientations), dtype=np.float64)

    # convert dataset to SH
    spike_sh = sf_to_sh(spike, k.get_sphere(), sh_order=8)

    # convolve kernel with delta spike and apply normalization
    csd_enh = convolve(spike_sh, k, sh_order=8, test_mode=True, normalize=True)

    # convert dataset to DSF
    csd_enh_dsf = sh_to_sf(csd_enh, k.get_sphere(), sh_order=8, basis_type=None)

    # test if the normalization is performed correctly
    npt.assert_almost_equal(np.amax(csd_enh_dsf), np.amax(spike))
예제 #25
0
#mask = data[..., 0] > 50

order = 4
csamodel = CsaOdfModel(gtab, order, smooth=0.006)
print 'Computing the CSA odf...'
csafit  = csamodel.fit(data) 
coeff   = csafit._shm_coef

# dipy-dev compatible
#GFA = csafit.gfa
#nib.save(nib.Nifti1Image(GFA.astype('float32'), affine), 'gfa_csa.nii.gz')    
nib.save(nib.Nifti1Image(coeff.astype('float32'), affine), 'csa_odf_sh.nii.gz')


sphere = get_sphere('symmetric724')
odfs = sh_to_sf(coeff[20:50,55:85, 38:39], sphere, order)
if vizu :
    from dipy.viz import fvtk
    r = fvtk.ren()
    fvtk.add(r, fvtk.sphere_funcs(odfs, sphere, colormap='jet'))
    fvtk.show(r)
    fvtk.clear(r)


qballmodel = QballModel(gtab, order, smooth=0.006)
print 'Computing the QBALL odf...'
qballfit  = qballmodel.fit(data) 
coeff   = qballfit._shm_coef

#GFA = qballfit.gfa
# dipy 0.6 compatible
예제 #26
0
Visualize the kernel
"""

from dipy.viz import fvtk
from dipy.data import get_sphere
from dipy.reconst.shm import sf_to_sh, sh_to_sf
ren = fvtk.ren()

# convolve kernel with delta spike
spike = np.zeros((7, 7, 7, k.get_orientations().shape[0]), dtype=np.float64)
spike[3, 3, 3, 0] = 1
spike_shm_conv = convolve(sf_to_sh(spike, k.get_sphere(), sh_order=8), k,
                          sh_order=8, test_mode=True)

sphere = get_sphere('symmetric724')
spike_sf_conv = sh_to_sf(spike_shm_conv, sphere, sh_order=8)
model_kernel = fvtk.sphere_funcs((spike_sf_conv * 6)[3,:,:,:],
                                  sphere,
                                  norm=False,
                                  radial_scale=True)
fvtk.add(ren, model_kernel)
fvtk.camera(ren, pos=(30, 0, 0), focal=(0, 0, 0), viewup=(0, 0, 1), verbose=False)
fvtk.record(ren, out_path='kernel.png', size=(900, 900))

"""
.. figure:: kernel.png
   :align: center

   Visualization of the contour enhancement kernel.
"""
예제 #27
0
Visualize the kernel
"""

from dipy.viz import window, actor
from dipy.reconst.shm import sf_to_sh, sh_to_sf
scene = window.Scene()

# convolve kernel with delta spike
spike = np.zeros((7, 7, 7, k.get_orientations().shape[0]), dtype=np.float64)
spike[3, 3, 3, 0] = 1
spike_shm_conv = convolve(sf_to_sh(spike, k.get_sphere(), sh_order=8),
                          k,
                          sh_order=8,
                          test_mode=True)

spike_sf_conv = sh_to_sf(spike_shm_conv, default_sphere, sh_order=8)
model_kernel = actor.odf_slicer(spike_sf_conv * 6,
                                sphere=default_sphere,
                                norm=False,
                                scale=0.4)
model_kernel.display(x=3)
scene.add(model_kernel)
scene.set_camera(position=(30, 0, 0), focal_point=(0, 0, 0), view_up=(0, 0, 1))
window.record(scene, out_path='kernel.png', size=(900, 900))
if interactive:
    window.show(scene)
"""
.. figure:: kernel.png
   :align: center

   Visualization of the contour enhancement kernel.
예제 #28
0
# Change this value to try other maximum orders
sh_order = 8

sh_coeffs = sf_to_sh(odf, sph, sh_order, sh_basis)
"""
``sh_coeffs`` is an array containing the SH coefficients multiplying the SH
functions of the chosen basis. We can use it as input of ``sh_to_sf`` to
reconstruct our original signal. We will now reproject our signal on a high
resolution sphere using ``sh_to_sf``.
"""

from dipy.data import get_sphere
from dipy.reconst.shm import sh_to_sf

high_res_sph = get_sphere('symmetric724').subdivide(2)
reconst = sh_to_sf(sh_coeffs, high_res_sph, sh_order, sh_basis)

scene.clear()
odf_actor = actor.odf_slicer(reconst[None, None, None, :], sphere=high_res_sph)
odf_actor.RotateX(90)
scene.add(odf_actor)

print('Saving output as symm_reconst.png')
window.record(scene, out_path='symm_reconst.png', size=(300, 300))
if interactive:
    window.show(scene)
"""
.. figure:: symm_reconst.png
   :align: center

   Reconstruction of a symmetric signal on a high resolution sphere using a
def main():
    logging.basicConfig(level=logging.INFO)
    parser = _build_arg_parser()
    args = parser.parse_args()

    required = [args.bundle_filename, args.fod_filename, args.mask_filename]
    assert_inputs_exist(parser, required)

    out_efod = os.path.join(args.output_dir,
                            '{0}efod.nii.gz'.format(args.output_prefix))
    out_priors = os.path.join(args.output_dir,
                              '{0}priors.nii.gz'.format(args.output_prefix))
    out_todi_mask = os.path.join(
        args.output_dir, '{0}todi_mask.nii.gz'.format(args.output_prefix))
    out_endpoints_mask = os.path.join(
        args.output_dir, '{0}endpoints_mask.nii.gz'.format(args.output_prefix))
    required = [out_efod, out_priors, out_todi_mask, out_endpoints_mask]
    assert_outputs_exist(parser, args, required)

    if args.output_dir and not os.path.isdir(args.output_dir):
        os.mkdir(args.output_dir)

    img_sh = nib.load(args.fod_filename)
    sh_shape = img_sh.shape
    sh_order = find_order_from_nb_coeff(sh_shape)
    img_mask = nib.load(args.mask_filename)

    sft = load_tractogram(args.bundle_filename,
                          args.fod_filename,
                          trk_header_check=True)
    sft.to_vox()
    streamlines = sft.streamlines
    if len(streamlines) < 1:
        raise ValueError('The input bundle contains no streamline.')

    # Compute TODI from streamlines
    with TrackOrientationDensityImaging(img_mask.shape,
                                        'repulsion724') as todi_obj:
        todi_obj.compute_todi(streamlines, length_weights=True)
        todi_obj.smooth_todi_dir()
        todi_obj.smooth_todi_spatial(sigma=args.todi_sigma)

        # Fancy masking of 1d indices to limit spatial dilation to WM
        sub_mask_3d = np.logical_and(
            img_mask.get_data(), todi_obj.reshape_to_3d(todi_obj.get_mask()))
        sub_mask_1d = sub_mask_3d.flatten()[todi_obj.get_mask()]
        todi_sf = todi_obj.get_todi()[sub_mask_1d]**2

    # The priors should always be between 0 and 1
    # A minimum threshold is set to prevent misaligned FOD from disappearing
    todi_sf /= np.max(todi_sf, axis=-1, keepdims=True)
    todi_sf[todi_sf < args.sf_threshold] = args.sf_threshold

    # Memory friendly saving, as soon as possible saving then delete
    priors_3d = np.zeros(sh_shape)
    sphere = get_sphere('repulsion724')
    priors_3d[sub_mask_3d] = sf_to_sh(todi_sf,
                                      sphere,
                                      sh_order=sh_order,
                                      basis_type=args.sh_basis)
    nib.save(nib.Nifti1Image(priors_3d, img_mask.affine), out_priors)
    del priors_3d

    input_sh_3d = img_sh.get_data().astype(np.float)
    input_sf_1d = sh_to_sf(input_sh_3d[sub_mask_3d],
                           sphere,
                           sh_order=sh_order,
                           basis_type=args.sh_basis)

    # Creation of the enhanced-FOD (direction-wise multiplication)
    mult_sf_1d = input_sf_1d * todi_sf
    del todi_sf

    input_max_value = np.max(input_sf_1d, axis=-1, keepdims=True)
    mult_max_value = np.max(mult_sf_1d, axis=-1, keepdims=True)
    mult_positive_mask = np.squeeze(mult_max_value) > 0.0
    mult_sf_1d[mult_positive_mask] = mult_sf_1d[mult_positive_mask] * \
        input_max_value[mult_positive_mask] / \
        mult_max_value[mult_positive_mask]

    # Memory friendly saving
    input_sh_3d[sub_mask_3d] = sf_to_sh(mult_sf_1d,
                                        sphere,
                                        sh_order=sh_order,
                                        basis_type=args.sh_basis)
    nib.save(nib.Nifti1Image(input_sh_3d, img_mask.affine), out_efod)
    del input_sh_3d

    nib.save(nib.Nifti1Image(sub_mask_3d.astype(np.int16), img_mask.affine),
             out_todi_mask)

    endpoints_mask = np.zeros(img_mask.shape, dtype=np.int16)
    for streamline in streamlines:
        if img_mask.get_data()[tuple(streamline[0].astype(np.int16))]:
            endpoints_mask[tuple(streamline[0].astype(np.int16))] = 1
            endpoints_mask[tuple(streamline[-1].astype(np.int16))] = 1
    nib.save(nib.Nifti1Image(endpoints_mask, img_mask.affine),
             out_endpoints_mask)
예제 #30
0
def test_r2_term_odf_sharp():
    SNR = None
    S0 = 1
    angle = 45  # 45 degrees is a very tight angle to disentangle

    _, fbvals, fbvecs = get_fnames('small_64D')  # get_fnames('small_64D')

    bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)

    sphere = default_sphere
    gtab = gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))

    angles = [(0, 0), (angle, 0)]

    S, _ = multi_tensor(gtab,
                        mevals,
                        S0,
                        angles=angles,
                        fractions=[50, 50],
                        snr=SNR)

    odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50])
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        odfs_sh = sf_to_sh(odf_gt, sphere, sh_order=8, basis_type=None)
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        fodf_sh = odf_sh_to_sharp(odfs_sh,
                                  sphere,
                                  basis=None,
                                  ratio=3 / 15.,
                                  sh_order=8,
                                  lambda_=1.,
                                  tau=0.1,
                                  r2_term=True)
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        fodf = sh_to_sf(fodf_sh, sphere, sh_order=8, basis_type=None)

    directions_gt, _, _ = peak_directions(odf_gt, sphere)
    directions, _, _ = peak_directions(fodf, sphere)

    ang_sim = angular_similarity(directions_gt, directions)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions.shape[0], 2)

    # This should pass as well
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        sdt_model = ConstrainedSDTModel(gtab, ratio=3 / 15., sh_order=8)
    sdt_fit = sdt_model.fit(S)
    with warnings.catch_warnings():
        warnings.filterwarnings("ignore",
                                message=descoteaux07_legacy_msg,
                                category=PendingDeprecationWarning)
        fodf = sdt_fit.odf(sphere)

    directions_gt, _, _ = peak_directions(odf_gt, sphere)
    directions, _, _ = peak_directions(fodf, sphere)
    ang_sim = angular_similarity(directions_gt, directions)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions.shape[0], 2)