def test_real_sh_descoteaux2(): 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) with warnings.catch_warnings(record=True) as w: B, m, n = real_sh_descoteaux(10, sphere.theta, sphere.phi, full_basis=True) npt.assert_equal(len(w), 1) npt.assert_(issubclass(w[0].category, PendingDeprecationWarning)) npt.assert_(descoteaux07_legacy_msg in str(w[0].message)) 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)
def test_csd_predict(): """ Test prediction API """ 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])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = small_sphere multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) # Predicting from a fit should give the same result as predicting from a # model, S0 is 1 by default prediction1 = csd_fit.predict() prediction2 = csd.predict(csd_fit.shm_coeff) npt.assert_array_equal(prediction1, prediction2) npt.assert_array_equal(prediction1[..., gtab.b0s_mask], 1.) # Same with a different S0 prediction1 = csd_fit.predict(S0=123.) prediction2 = csd.predict(csd_fit.shm_coeff, S0=123.) npt.assert_array_equal(prediction1, prediction2) npt.assert_array_equal(prediction1[..., gtab.b0s_mask], 123.) # For "well behaved" coefficients, the model should be able to find the # coefficients from the predicted signal. coeff = np.random.random(csd_fit.shm_coeff.shape) - .5 coeff[..., 0] = 10. S = csd.predict(coeff) csd_fit = csd.fit(S) npt.assert_array_almost_equal(coeff, csd_fit.shm_coeff) # Test predict on nd-data set S_nd = np.zeros((2, 3, 4, S.size)) S_nd[:] = S fit = csd.fit(S_nd) predict1 = fit.predict() predict2 = csd.predict(fit.shm_coeff) npt.assert_array_almost_equal(predict1, predict2)
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)
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)
def test_csd_predict(): """ """ 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])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) prediction = csd_predict(csd_fit.shm_coeff, gtab, response=response, S0=S0) npt.assert_equal(prediction.shape[0], S.shape[0]) model_prediction = csd.predict(csd_fit.shm_coeff) assert_array_almost_equal(prediction, model_prediction) # Roundtrip tests (quite inaccurate, because of regularization): assert_array_almost_equal(csd_fit.predict(gtab, S0=S0),S,decimal=1) assert_array_almost_equal(csd.predict(csd_fit.shm_coeff, S0=S0),S,decimal=1)
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)
def test_minmax_normalize(): bvalue = 3000 S0 = 1 SNR = 100 sphere = get_sphere('symmetric362') bvecs = np.concatenate(([[0, 0, 0]], sphere.vertices)) bvals = np.zeros(len(bvecs)) + bvalue bvals[0] = 0 gtab = gradient_table(bvals, bvecs) evals = np.array(([0.0017, 0.0003, 0.0003], [0.0017, 0.0003, 0.0003])) multi_tensor(gtab, evals, S0, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=SNR) odf = multi_tensor_odf(sphere.vertices, evals, angles=[(0, 0), (90, 0)], fractions=[50, 50]) odf2 = minmax_normalize(odf) assert_equal(odf2.max(), 1) assert_equal(odf2.min(), 0) odf3 = np.empty(odf.shape) odf3 = minmax_normalize(odf, odf3) assert_equal(odf3.max(), 1) assert_equal(odf3.min(), 0)
def test_peak_finding(): vertices, faces=get_sphere('symmetric724') odf=np.zeros(len(vertices)) odf = np.abs(vertices.sum(-1)) odf[1] = 10. odf[505] = 505. odf[143] = 143. peaks, inds=peak_finding(odf.astype('f8'), faces.astype('uint16')) print peaks, inds edges = unique_edges(faces) peaks, inds = local_maxima(odf, edges) print peaks, inds vertices_half, edges_half, faces_half = reduce_antipodal(vertices, faces) n = len(vertices_half) peaks, inds = local_maxima(odf[:n], edges_half) print peaks, inds mevals=np.array(([0.0015,0.0003,0.0003], [0.0015,0.0003,0.0003])) e0=np.array([1,0,0.]) e1=np.array([0.,1,0]) mevecs=[all_tensor_evecs(e0),all_tensor_evecs(e1)] odf = multi_tensor_odf(vertices, [0.5,0.5], mevals, mevecs) peaks, inds=peak_finding(odf, faces) print peaks, inds peaks2, inds2 = local_maxima(odf[:n], edges_half) print peaks2, inds2 assert_equal(len(peaks), 2) assert_equal(len(peaks2), 2)
def test_odfdeconv(): 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])) angles = [(0, 0), (90, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) e1 = 15.0 e2 = 3.0 ratio = e2 / e1 csd = ConstrainedSDTModel(gtab, ratio, None) csd_fit = csd.fit(S) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=10) assert_equal(len(w) > 0, True) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=8) assert_equal(len(w) > 0, False) csd_fit = csd.fit(np.zeros_like(S)) fodf = csd_fit.odf(sphere) assert_array_equal(fodf, np.zeros_like(fodf)) odf_sh = np.zeros_like(fodf) odf_sh[1] = np.nan fodf, it = odf_deconv(odf_sh, csd.R, csd.B_reg) assert_array_equal(fodf, np.zeros_like(fodf))
def test_minmax_normalize(): bvalue = 3000 S0 = 1 SNR = 100 sphere = get_sphere("symmetric362") bvecs = np.concatenate(([[0, 0, 0]], sphere.vertices)) bvals = np.zeros(len(bvecs)) + bvalue bvals[0] = 0 gtab = gradient_table(bvals, bvecs) evals = np.array(([0.0017, 0.0003, 0.0003], [0.0017, 0.0003, 0.0003])) S, sticks = multi_tensor(gtab, evals, S0, angles=[(0, 0), (90, 0)], fractions=[50, 50], snr=SNR) odf = multi_tensor_odf(sphere.vertices, evals, angles=[(0, 0), (90, 0)], fractions=[50, 50]) odf2 = minmax_normalize(odf) assert_equal(odf2.max(), 1) assert_equal(odf2.min(), 0) odf3 = np.empty(odf.shape) odf3 = minmax_normalize(odf, odf3) assert_equal(odf3.max(), 1) assert_equal(odf3.min(), 0)
def _create_mt_sim(mevals, angles, fractions, S0, SNR, half_sphere=False): _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs) S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=fractions, snr=SNR) sphere = get_sphere('symmetric724').subdivide(2) if half_sphere: sphere = HemiSphere.from_sphere(sphere) odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles=angles, fractions=fractions) return odf_gt, sticks, sphere
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)
def test_multi_tensor(): vertices, faces = get_sphere('symmetric724') mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) e0 = np.array([1, 0, 0.]) e1 = np.array([0., 1, 0]) mevecs = [all_tensor_evecs(e0), all_tensor_evecs(e1)] odf = multi_tensor_odf(vertices, [0.5, 0.5], mevals, mevecs) assert odf.shape == (len(vertices), ) assert np.all(odf <= 1) & np.all(odf >= 0)
def test_multi_tensor(): vertices, faces = get_sphere('symmetric724') mevals=np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) e0 = np.array([1, 0, 0.]) e1 = np.array([0., 1, 0]) mevecs=[all_tensor_evecs(e0), all_tensor_evecs(e1)] odf = multi_tensor_odf(vertices, [0.5,0.5], mevals, mevecs) assert odf.shape == (len(vertices),) assert np.all(odf <= 1) & np.all(odf >= 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]) 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)
def test_csdeconv(): 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=[(0, 0), (60, 0)], fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric724') 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) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) assert_equal(csd_fit.shm_coeff[0] > 0, True) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: ConstrainedSphericalDeconvModel(gtab, response, sh_order=10) assert_equal(len(w) > 0, True) with warnings.catch_warnings(record=True) as w: ConstrainedSphericalDeconvModel(gtab, response, sh_order=8) assert_equal(len(w) > 0, False)
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_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)
def sim_tensor_2x(gtab, angle=90, sphere=None, S0=1., snr=None): mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) data, sticks = multi_tensor(gtab, mevals, S0, angles=[(90 , 0), (90, angle)], 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) return data, sticks, odf_gt
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)
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)
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 _create_mt_sim(mevals, angles, fractions, S0, SNR, half_sphere=False): _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) gtab = gradient_table(bvals, bvecs) S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=fractions, snr=SNR) sphere = get_sphere('symmetric724').subdivide(2) if half_sphere: sphere = HemiSphere.from_sphere(sphere) odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles=angles, fractions=fractions) return odf_gt, sticks, sphere
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)
def synth_unimodal_odfs(qball_sphere, sphere_vol, directions, cutoff=2 * np.pi, const_width=3, tightness=4.9): verts = qball_sphere.vertices l_labels = verts.shape[0] # `const_width` unimodals for each entry of `directions` val_base = 1e-6 * 290 vals = [tightness * val_base, val_base, val_base] vecs = normalize( np.array( [[np.sin(phi * np.pi / 180.0), np.cos(phi * np.pi / 180.0), 0] for phi in directions]).T).T voxels = [ multi_tensor_odf(verts, np.array((vals, vals)), [v, v], [50, 50]) for v in vecs ] if cutoff < 1.5 * np.pi: # cut off support of distribution functions for v, vox in zip(vecs, voxels): for k in range(l_labels): v_diff1 = verts[k] - v v_diff2 = verts[k] + v if np.einsum('n,n->', v_diff1, v_diff1) > cutoff**2 \ and np.einsum('n,n->', v_diff2, v_diff2) > cutoff**2: vox[k] = 0 fin = np.zeros((l_labels, const_width * len(voxels)), order='C') for i, vox in enumerate(voxels): i1 = i * const_width i2 = (i + 1) * const_width fin[:, i1:i2] = np.tile(vox, (const_width, 1)).T normalize_odf(fin, sphere_vol) return fin
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)
def test_sh(): from dipy.sims.voxel import multi_tensor, multi_tensor_odf, sticks_and_ball from dipy.data import get_sphere, get_fnames from dipy.core.gradients import gradient_table from dipy.io.gradients import read_bvals_bvecs _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs) d = 0.0015 S, sticks = sticks_and_ball(gtab, d=d, S0=1, angles=[(0, 0), (30, 30)], fractions=[60, 40], snr=None) print(S) print(sticks) mevals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]]) angles = [(0, 0), (60, 0)] fractions = [50, 50] sphere = get_sphere('repulsion724') sphere = sphere.subdivide(2) odf = multi_tensor_odf(sphere.vertices, mevals, angles, fractions) print(odf) ren = window.Scene() odf_actor = actor.odf_slicer(odf[None, None, None, :], sphere=sphere, colormap='plasma') # odf_actor.RotateX(90) ren.add(odf_actor) # window.show(ren) odf_test_dec= \ """ // Constants, see here: http://en.wikipedia.org/wiki/Table_of_spherical_harmonics #define k01 0.2820947918 // sqrt( 1/PI)/2 #define k02 0.4886025119 // sqrt( 3/PI)/2 #define k03 1.0925484306 // sqrt( 15/PI)/2 #define k04 0.3153915652 // sqrt( 5/PI)/4 #define k05 0.5462742153 // sqrt( 15/PI)/4 #define k06 0.5900435860 // sqrt( 70/PI)/8 #define k07 2.8906114210 // sqrt(105/PI)/2 #define k08 0.4570214810 // sqrt( 42/PI)/8 #define k09 0.3731763300 // sqrt( 7/PI)/4 #define k10 1.4453057110 // sqrt(105/PI)/4 // unrolled version of the above float SH_0_0( in vec3 s ) { vec3 n = s.zxy; return k01; } float SH_1_0( in vec3 s ) { vec3 n = s.zxy; return -k02*n.y; } float SH_1_1( in vec3 s ) { vec3 n = s.zxy; return k02*n.z; } float SH_1_2( in vec3 s ) { vec3 n = s.zxy; return -k02*n.x; } float SH_2_0( in vec3 s ) { vec3 n = s.zxy; return k03*n.x*n.y; } float SH_2_1( in vec3 s ) { vec3 n = s.zxy; return -k03*n.y*n.z; } float SH_2_2( in vec3 s ) { vec3 n = s.zxy; return k04*(3.0*n.z*n.z-1.0); } float SH_2_3( in vec3 s ) { vec3 n = s.zxy; return -k03*n.x*n.z; } float SH_2_4( in vec3 s ) { vec3 n = s.zxy; return k05*(n.x*n.x-n.y*n.y); } float SH_3_0( in vec3 s ) { vec3 n = s.zxy; return -k06*n.y*(3.0*n.x*n.x-n.y*n.y); } float SH_3_1( in vec3 s ) { vec3 n = s.zxy; return k07*n.z*n.y*n.x; } float SH_3_2( in vec3 s ) { vec3 n = s.zxy; return -k08*n.y*(5.0*n.z*n.z-1.0); } float SH_3_3( in vec3 s ) { vec3 n = s.zxy; return k09*n.z*(5.0*n.z*n.z-3.0); } float SH_3_4( in vec3 s ) { vec3 n = s.zxy; return -k08*n.x*(5.0*n.z*n.z-1.0); } float SH_3_5( in vec3 s ) { vec3 n = s.zxy; return k10*n.z*(n.x*n.x-n.y*n.y); } float SH_3_6( in vec3 s ) { vec3 n = s.zxy; return -k06*n.x*(n.x*n.x-3.0*n.y*n.y); } vec3 map( in vec3 p ) { vec3 p00 = p - vec3( 0.00, 2.5,0.0); vec3 p01 = p - vec3(-1.25, 1.0,0.0); vec3 p02 = p - vec3( 0.00, 1.0,0.0); vec3 p03 = p - vec3( 1.25, 1.0,0.0); vec3 p04 = p - vec3(-2.50,-0.5,0.0); vec3 p05 = p - vec3(-1.25,-0.5,0.0); vec3 p06 = p - vec3( 0.00,-0.5,0.0); vec3 p07 = p - vec3( 1.25,-0.5,0.0); vec3 p08 = p - vec3( 2.50,-0.5,0.0); vec3 p09 = p - vec3(-3.75,-2.0,0.0); vec3 p10 = p - vec3(-2.50,-2.0,0.0); vec3 p11 = p - vec3(-1.25,-2.0,0.0); vec3 p12 = p - vec3( 0.00,-2.0,0.0); vec3 p13 = p - vec3( 1.25,-2.0,0.0); vec3 p14 = p - vec3( 2.50,-2.0,0.0); vec3 p15 = p - vec3( 3.75,-2.0,0.0); float r, d; vec3 n, s, res; #ifdef SHOW_SPHERES #define SHAPE (vec3(d-0.35, -1.0+2.0*clamp(0.5 + 16.0*r,0.0,1.0),d)) #else #define SHAPE (vec3(d-abs(r), sign(r),d)) #endif d=length(p00); n=p00/d; r = SH_0_0( n ); s = SHAPE; res = s; d=length(p01); n=p01/d; r = SH_1_0( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p02); n=p02/d; r = SH_1_1( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p03); n=p03/d; r = SH_1_2( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p04); n=p04/d; r = SH_2_0( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p05); n=p05/d; r = SH_2_1( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p06); n=p06/d; r = SH_2_2( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p07); n=p07/d; r = SH_2_3( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p08); n=p08/d; r = SH_2_4( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p09); n=p09/d; r = SH_3_0( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p10); n=p10/d; r = SH_3_1( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p11); n=p11/d; r = SH_3_2( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p12); n=p12/d; r = SH_3_3( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p13); n=p13/d; r = SH_3_4( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p14); n=p14/d; r = SH_3_5( n ); s = SHAPE; if( s.x<res.x ) res=s; d=length(p15); n=p15/d; r = SH_3_6( n ); s = SHAPE; if( s.x<res.x ) res=s; return vec3( res.x, 0.5+0.5*res.y, res.z ); } vec3 intersect( in vec3 ro, in vec3 rd ) { vec3 res = vec3(1e10,-1.0, 1.0); float maxd = 10.0; float h = 1.0; float t = 0.0; vec2 m = vec2(-1.0); for( int i=0; i<200; i++ ) { if( h<0.001||t>maxd ) break; vec3 res = map( ro+rd*t ); h = res.x; m = res.yz; t += h*0.3; } if( t<maxd && t<res.x ) res=vec3(t,m); return res; } vec3 calcNormal( in vec3 pos ) { vec3 eps = vec3(0.001,0.0,0.0); return normalize( vec3( map(pos+eps.xyy).x - map(pos-eps.xyy).x, map(pos+eps.yxy).x - map(pos-eps.yxy).x, map(pos+eps.yyx).x - map(pos-eps.yyx).x ) ); } """ odf_test_impl = \ """ // camera matrix vec3 ww = vec3(0.0,0.0,0.0); //MCDCMatrix (2); vec3 uu = vec3(0.0,0.0,0.0); //MCDCMatrix (0); vec3 vv = vec3(0.0,0.0,0.0); //MCDCMatrix (1); vec3 tot = vec3(0.0); vec2 p = (-vec2(0.5, 0.5) + (2.0*point,0)) / 0.5; vec3 ro = vec3(0.0,0.0,0.0); // create view ray vec3 rd = normalize( p.x*uu + p.y*vv + 2.0*ww ); // background vec3 col = vec3(0.3) * clamp(1.0-length(point)*0.5,0.0,1.0); // raymarch vec3 tmat = intersect(ro,rd); if( tmat.y>-0.5 ) { // geometry vec3 pos = ro + tmat.x*rd; vec3 nor = calcNormal(pos); vec3 ref = reflect( rd, nor ); // material vec3 mate = 0.5*mix( vec3(1.0,0.6,0.15), vec3(0.2,0.4,0.5), tmat.y ); float occ = clamp( 2.0*tmat.z, 0.0, 1.0 ); float sss = pow( clamp( 1.0 + dot(nor,rd), 0.0, 1.0 ), 1.0 ); // lights vec3 lin = 2.5*occ*vec3(1.0,1.00,1.00)*(0.6+0.4*nor.y); lin += 1.0*sss*vec3(1.0,0.95,0.70)*occ; // surface-light interacion col = mate.xyz * lin; } // gamma col = pow( clamp(col,0.0,1.0), vec3(0.4545) ); tot += col; fragOutput0 = vec4( tot, 1.0 ); """ scene = window.Scene() scene.background((0.8, 0.8, 0.8)) centers = np.array([[2, 0, 0], [0, 0, 0], [-2, 0, 0]]) # np.random.rand(3, 3) * 3 # colors = np.array([[255, 0, 0], [0, 255, 0], [0, 0, 255]]) colors = np.random.rand(3, 3) * 255 scale = 1 # np.random.rand(3) * 5 # https://www.shadertoy.com/view/MstXWS # https://www.shadertoy.com/view/XsX3R4 fs_dec = \ """ uniform mat4 MCDCMatrix; uniform mat4 MCVCMatrix; float sdRoundBox( vec3 p, vec3 b, float r ) { vec3 q = abs(p) - b; return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r; } float sdEllipsoid( vec3 p, vec3 r ) { float k0 = length(p/r); float k1 = length(p/(r*r)); return k0*(k0-1.0)/k1; } float sdCylinder(vec3 p, float h, float r) { vec2 d = abs(vec2(length(p.xz),p.y)) - vec2(h,r); return min(max(d.x,d.y),0.0) + length(max(d,0.0)); } float sdSphere(vec3 pos, float r) { float d = length(pos) - r; return d; } float map( in vec3 pos) { float d = sdSphere(pos-0.5, .2); float d1 = sdCylinder(pos+0.5, 0.05, .5); float d2 = sdEllipsoid(pos + vec3(-0.5,0.5,0), vec3(0.2,0.3,0.5)); float d3 = sdRoundBox(pos + vec3(0.5,-0.5,0), vec3(0.2,0.1,0.3), .05); //.xy return min(min(min(d, d1), d2), d3); } vec3 calcNormal( in vec3 pos ) { vec2 e = vec2(0.0001,0.0); return normalize( vec3(map(pos + e.xyy) - map(pos - e.xyy ), map(pos + e.yxy) - map(pos - e.yxy), map(pos + e.yyx) - map(pos - e.yyx) ) ); } float castRay(in vec3 ro, vec3 rd) { float t = 0.0; for(int i=0; i < 100; i++) { vec3 pos = ro + t * rd; vec3 nor = calcNormal(pos); float h = map(pos); if (h < 0.001) break; t += h; if (t > 20.0) break; } return t; } """ fake_sphere = \ """ vec3 uu = vec3(MCVCMatrix[0][0], MCVCMatrix[1][0], MCVCMatrix[2][0]); // camera right vec3 vv = vec3(MCVCMatrix[0][1], MCVCMatrix[1][1], MCVCMatrix[2][1]); // camera up vec3 ww = vec3(MCVCMatrix[0][2], MCVCMatrix[1][2], MCVCMatrix[2][2]); // camera direction vec3 ro = MCVCMatrix[3].xyz * mat3(MCVCMatrix); // camera position // create view ray vec3 rd = normalize( point.x*-uu + point.y*-vv + 7*ww); vec3 col = vec3(0.0); float t = castRay(ro, rd); if (t < 20.0) { vec3 pos = ro + t * rd; vec3 nor = calcNormal(pos); vec3 sun_dir = vec3(MCVCMatrix[0][2], MCVCMatrix[1][2], MCVCMatrix[2][2]); //normalize() float dif = clamp( dot(nor, sun_dir), 0.0, 1.0); //vec3 sun_dif = normalize() col = color * dot(color,nor); // (color + diffuseColor + ambientColor + specularColor)*nor.zzz;//vec3(1.0); fragOutput0 = vec4(col, 1.0); } else{ //fragOutput0 = vec4(0,1,0, 1.0); discard; } /*float radius = 1.; if(len > radius) {discard;} //err, lightColor0 vertexColorVSOutput normalVCVSOutput, ambientIntensity; diffuseIntensity;specularIntensity;specularColorUniform; float c = len; fragOutput0 = vec4(c,c,c, 1); vec3 normalizedPoint = normalize(vec3(point.xy, sqrt(1. - len))); vec3 direction = normalize(vec3(1., 1., 1.)); float df = max(0, dot(direction, normalizedPoint)); float sf = pow(df, 24); fragOutput0 = vec4(max(df * color, sf * vec3(1)), 1);*/ """ billboard_actor = actor.billboard(centers, colors=colors.astype(np.uint8), scale=scale, fs_dec=fs_dec, fs_impl=fake_sphere) scene.add(billboard_actor) scene.add(actor.axes()) scene.camera_info() matrix = scene.camera().GetViewTransformMatrix() mat = np.zeros((4, 4)) for i in range(4): for j in range(4): mat[i, j] = matrix.GetElement(i, j) print(mat) print(np.dot(-mat[:3, 3], mat[:3, :3])) # camera position window.show(scene)
def test_recursive_response_calibration(): """ Test the recursive response calibration method. """ SNR = 100 S0 = 1 sh_order = 8 _, fbvals, fbvecs = get_data('small_64D') bvals = np.load(fbvals) bvecs = np.load(fbvecs) sphere = get_sphere('symmetric724') gtab = gradient_table(bvals, bvecs) evals = np.array([0.0015, 0.0003, 0.0003]) evecs = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]).T mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (90, 0)] where_dwi = lazy_index(~gtab.b0s_mask) S_cross, sticks_cross = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) S_single = single_tensor(gtab, S0, evals, evecs, snr=SNR) data = np.concatenate((np.tile(S_cross, (8, 1)), np.tile(S_single, (2, 1))), axis=0) odf_gt_cross = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) odf_gt_single = single_tensor_odf(sphere.vertices, evals, evecs) response = recursive_response(gtab, data, mask=None, sh_order=8, peak_thr=0.01, init_fa=0.05, init_trace=0.0021, iter=8, convergence=0.001, parallel=False) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(data) assert_equal(np.all(csd_fit.shm_coeff[:, 0] >= 0), True) fodf = csd_fit.odf(sphere) directions_gt_single, _, _ = peak_directions(odf_gt_single, sphere) directions_gt_cross, _, _ = peak_directions(odf_gt_cross, sphere) directions_single, _, _ = peak_directions(fodf[8, :], sphere) directions_cross, _, _ = peak_directions(fodf[0, :], sphere) ang_sim = angular_similarity(directions_cross, directions_gt_cross) assert_equal(ang_sim > 1.9, True) assert_equal(directions_cross.shape[0], 2) assert_equal(directions_gt_cross.shape[0], 2) ang_sim = angular_similarity(directions_single, directions_gt_single) assert_equal(ang_sim > 0.9, True) assert_equal(directions_single.shape[0], 1) assert_equal(directions_gt_single.shape[0], 1) sphere = Sphere(xyz=gtab.gradients[where_dwi]) sf = response.on_sphere(sphere) S = np.concatenate(([response.S0], sf)) tenmodel = dti.TensorModel(gtab, min_signal=0.001) tenfit = tenmodel.fit(S) FA = fractional_anisotropy(tenfit.evals) FA_gt = fractional_anisotropy(evals) assert_almost_equal(FA, FA_gt, 1)
def test_csdeconv(): SNR = 100 S0 = 1 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) gtab = gradient_table(bvals, bvecs, b0_threshold=0) mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) assert_equal(csd_fit.shm_coeff[0] > 0, True) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", category=UserWarning) _ = ConstrainedSphericalDeconvModel(gtab, response, sh_order=10) assert_greater(len([lw for lw in w if issubclass(lw.category, UserWarning)]), 0) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", category=UserWarning) ConstrainedSphericalDeconvModel(gtab, response, sh_order=8) assert_equal(len([lw for lw in w if issubclass(lw.category, UserWarning)]), 0) mevecs = [] for s in sticks: mevecs += [all_tensor_evecs(s).T] S2 = single_tensor(gtab, 100, mevals[0], mevecs[0], snr=None) big_S = np.zeros((10, 10, 10, len(S2))) big_S[:] = S2 aresponse, aratio = auto_response(gtab, big_S, roi_center=(5, 5, 4), roi_radius=3, fa_thr=0.5) assert_array_almost_equal(aresponse[0], response[0]) assert_almost_equal(aresponse[1], 100) assert_almost_equal(aratio, response[0][1] / response[0][0]) auto_response(gtab, big_S, roi_radius=3, fa_thr=0.5) assert_array_almost_equal(aresponse[0], response[0]) _, _, nvoxels = auto_response(gtab, big_S, roi_center=(5, 5, 4), roi_radius=30, fa_thr=0.5, return_number_of_voxels=True) assert_equal(nvoxels, 1000) _, _, nvoxels = auto_response(gtab, big_S, roi_center=(5, 5, 4), roi_radius=30, fa_thr=1, return_number_of_voxels=True) assert_equal(nvoxels, 0)
Let's create a multi tensor with 2 fiber directions at 60 degrees. """ evals = np.array([[0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]]) directions = [(-30, 0), (30, 0)] fractions = [50, 50] signal, _ = multi_tensor(gtab, evals, 100, angles=directions, fractions=fractions, snr=None) sphere = get_sphere('symmetric724').subdivide(1) odf_gt = multi_tensor_odf(sphere.vertices, evals, angles=directions, fractions=fractions) """ Perform the reconstructions with standard DSI and DSI with deconvolution. """ dsi_model = DiffusionSpectrumModel(gtab) dsi_odf = dsi_model.fit(signal).odf(sphere) dsid_model = DiffusionSpectrumDeconvModel(gtab) dsid_odf = dsid_model.fit(signal).odf(sphere) """ Finally, we can visualize the ground truth ODF, together with the DSI and DSI
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)
def test_recursive_response_calibration(): """ Test the recursive response calibration method. """ SNR = 100 S0 = 1 _, fbvals, fbvecs = get_fnames('small_64D') bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs) sphere = default_sphere gtab = gradient_table(bvals, bvecs) evals = np.array([0.0015, 0.0003, 0.0003]) evecs = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]).T mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angles = [(0, 0), (90, 0)] where_dwi = lazy_index(~gtab.b0s_mask) S_cross, _ = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) S_single = single_tensor(gtab, S0, evals, evecs, snr=SNR) data = np.concatenate((np.tile(S_cross, (8, 1)), np.tile(S_single, (2, 1))), axis=0) odf_gt_cross = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) odf_gt_single = single_tensor_odf(sphere.vertices, evals, evecs) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) response = recursive_response(gtab, data, mask=None, sh_order=8, peak_thr=0.01, init_fa=0.05, init_trace=0.0021, iter=8, convergence=0.001, parallel=False) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(data) assert_equal(np.all(csd_fit.shm_coeff[:, 0] >= 0), True) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) fodf = csd_fit.odf(sphere) directions_gt_single, _, _ = peak_directions(odf_gt_single, sphere) directions_gt_cross, _, _ = peak_directions(odf_gt_cross, sphere) directions_single, _, _ = peak_directions(fodf[8, :], sphere) directions_cross, _, _ = peak_directions(fodf[0, :], sphere) ang_sim = angular_similarity(directions_cross, directions_gt_cross) assert_equal(ang_sim > 1.9, True) assert_equal(directions_cross.shape[0], 2) assert_equal(directions_gt_cross.shape[0], 2) ang_sim = angular_similarity(directions_single, directions_gt_single) assert_equal(ang_sim > 0.9, True) assert_equal(directions_single.shape[0], 1) assert_equal(directions_gt_single.shape[0], 1) with warnings.catch_warnings(record=True) as w: sphere = Sphere(xyz=gtab.gradients[where_dwi]) npt.assert_equal(len(w), 1) npt.assert_(issubclass(w[0].category, UserWarning)) npt.assert_("Vertices are not on the unit sphere" in str(w[0].message)) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) sf = response.on_sphere(sphere) S = np.concatenate(([response.S0], sf)) tenmodel = TensorModel(gtab, min_signal=0.001) tenfit = tenmodel.fit(S) FA = fractional_anisotropy(tenfit.evals) FA_gt = fractional_anisotropy(evals) assert_almost_equal(FA, FA_gt, 1)
def test_odfdeconv(): SNR = 100 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])) angles = [(0, 0), (90, 0)] S, _ = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) e1 = 15.0 e2 = 3.0 ratio = e2 / e1 csd = ConstrainedSDTModel(gtab, ratio, None) csd_fit = csd.fit(S) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=10) w_count = len(w) # A warning is expected from the ConstrainedSDTModel constructor # and additionnal warnings should be raised where legacy SH bases # are used assert_equal(w_count > 1, True) with warnings.catch_warnings(record=True) as w: ConstrainedSDTModel(gtab, ratio, sh_order=8) # Test that the warning from ConstrainedSDTModel # constructor is no more raised assert_equal(len(w) == w_count - 1, True) csd_fit = csd.fit(np.zeros_like(S)) fodf = csd_fit.odf(sphere) assert_array_equal(fodf, np.zeros_like(fodf)) odf_sh = np.zeros_like(fodf) odf_sh[1] = np.nan fodf, _ = odf_deconv(odf_sh, csd.R, csd.B_reg) assert_array_equal(fodf, np.zeros_like(fodf))
'odf_coeffs_*.npz')))): data = sph_io.load(os.path.basename(fn)) print "Dipy model..." odf = m.evaluate_odf(data['signal']) ODFs.append(odf) separation_from_odf(odf) print "Quadrature model..." odf = kernel_reconstruct(coords['odf_theta'], coords['odf_phi'], data['beta'], theta, phi, kernel=even_kernel, N=data['kernel_N']) odf[odf < 0] = 0 ODFs.append(odf) print "Actual angle:", np.rad2deg(data['separation']) separation_from_odf(odf) ODFs.append(multi_tensor_odf(verts, data['weights'], mevals=[[1700e-6, 300e-6, 300e-6]] * len(data['weights']), mevecs=data['mevecs'])) N = 3 ODFs = np.array([[ODFs]]).reshape(len(ODFs) // N, 1, N, -1) from dipy.viz import show_odfs show_odfs(ODFs, (verts, faces), scale=2, radial_scale=True)
.. figure:: simulated_signal.png :align: center **Simulated MultiTensor signal** """ """ For the ODF simulation we will need a sphere. Because we are interested in a simulation of only a single voxel, we can use a sphere with very high resolution. We generate that by subdividing the triangles of one of DIPY_'s cached spheres, which we can read in the following way. """ sphere = get_sphere('symmetric724') sphere = sphere.subdivide(2) odf = multi_tensor_odf(sphere.vertices, mevals, angles, fractions) from dipy.viz import window, actor # Enables/disables interactive visualization interactive = False ren = window.Renderer() odf_actor = actor.odf_slicer(odf[None, None, None, :], sphere=sphere, colormap='plasma') odf_actor.RotateX(90) ren.add(odf_actor)
def test_csdeconv(): 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])) angles = [(0, 0), (60, 0)] S, sticks = multi_tensor(gtab, mevals, S0, angles=angles, fractions=[50, 50], snr=SNR) sphere = get_sphere('symmetric362') odf_gt = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50]) response = (np.array([0.0015, 0.0003, 0.0003]), S0) csd = ConstrainedSphericalDeconvModel(gtab, response) csd_fit = csd.fit(S) assert_equal(csd_fit.shm_coeff[0] > 0, True) fodf = csd_fit.odf(sphere) directions, _, _ = peak_directions(odf_gt, sphere) directions2, _, _ = peak_directions(fodf, sphere) ang_sim = angular_similarity(directions, directions2) assert_equal(ang_sim > 1.9, True) assert_equal(directions.shape[0], 2) assert_equal(directions2.shape[0], 2) with warnings.catch_warnings(record=True) as w: ConstrainedSphericalDeconvModel(gtab, response, sh_order=10) assert_equal(len(w) > 0, True) with warnings.catch_warnings(record=True) as w: ConstrainedSphericalDeconvModel(gtab, response, sh_order=8) assert_equal(len(w) > 0, False) mevecs = [] for s in sticks: mevecs += [all_tensor_evecs(s).T] S2 = single_tensor(gtab, 100, mevals[0], mevecs[0], snr=None) big_S = np.zeros((10, 10, 10, len(S2))) big_S[:] = S2 aresponse, aratio = auto_response(gtab, big_S, roi_center=(5, 5, 4), roi_radius=3, fa_thr=0.5) assert_array_almost_equal(aresponse[0], response[0]) assert_almost_equal(aresponse[1], 100) assert_almost_equal(aratio, response[0][1]/response[0][0]) aresponse2, aratio2 = auto_response(gtab, big_S, roi_radius=3, fa_thr=0.5) assert_array_almost_equal(aresponse[0], response[0])
directions = [(-30, 0), (30, 0)] fractions = [50, 50] signal, _ = multi_tensor(gtab, evals, 100, angles=directions, fractions=fractions, snr=None) sphere = get_sphere('symmetric724').subdivide(1) odf_gt = multi_tensor_odf(sphere.vertices, evals, angles=directions, fractions=fractions) """ Perform the reconstructions with standard DSI and DSI with deconvolution. """ dsi_model = DiffusionSpectrumModel(gtab) dsi_odf = dsi_model.fit(signal).odf(sphere) dsid_model = DiffusionSpectrumDeconvModel(gtab) dsid_odf = dsid_model.fit(signal).odf(sphere) """ Finally, we can visualize the ground truth ODF, together with the DSI and DSI with deconvolution ODFs and observe that with the deconvolved method it is
""" import numpy as np from gradients_spheres import sph """ We now need to create our initial signal. To do so, we will use our sphere's vertices as the sampled points of our spherical function (SF). We will use ``multi_tensor_odf`` to simulate an ODF. For more information on how to use DIPY_ to simulate a signal and ODF, see :ref:`example_simulate_multi_tensor`. """ from dipy.sims.voxel import multi_tensor_odf mevals = np.array([[0.0015, 0.00015, 0.00015], [0.0015, 0.00015, 0.00015]]) angles = [(0, 0), (60, 0)] odf = multi_tensor_odf(sph.vertices, mevals, angles, [50, 50]) from dipy.viz import window, actor # Enables/disables interactive visualization interactive = False scene = window.Scene() scene.SetBackground(1, 1, 1) odf_actor = actor.odf_slicer(odf[None, None, None, :], sphere=sph) odf_actor.RotateX(90) scene.add(odf_actor) print('Saving illustration as symm_signal.png') window.record(scene, out_path='symm_signal.png', size=(300, 300))
:align: center **Simulated MultiTensor signal** """ """ For the ODF simulation we will need a sphere. Because we are interested in a simulation of only a single voxel, we can use a sphere with very high resolution. We generate that by subdividing the triangles of one of dipy_'s cached spheres, which we can read in the following way. """ sphere = get_sphere('symmetric724') sphere = sphere.subdivide(2) odf = multi_tensor_odf(sphere.vertices, mevals, angles, fractions) from dipy.viz import window, actor # Enables/disables interactive visualization interactive = False ren = window.Renderer() odf_actor = actor.odf_slicer(odf[None, None, None, :], sphere=sphere, colormap='plasma') odf_actor.RotateX(90) ren.add(odf_actor) print('Saving illustration as multi_tensor_simulation') window.record(ren, out_path='multi_tensor_simulation.png', size=(300, 300))
def compute_bounds(data, sph): # get noise intervals from background pixels (using mask) # determine background pixels #_, mask = median_otsu(S_data, median_radius=3, numpass=1, dilate=2, # vol_idx=np.where(gtab.bvals > 0)[0]) # for the moment using trivial bounds b_sph = data['sph'] bvals = data['gtab'].bvals S_data = data['S'] logging.debug("Getting bounds on S0 and Si's") c = 0.05 S0_l = S_data[..., bvals == 0].clip(1.0).mean(-1) * (1.0 - c) S0_u = S_data[..., bvals == 0].clip(1.0).mean(-1) * (1.0 + c) S_l = S_data[..., bvals > 0] * (1.0 - c) S_u = S_data[..., bvals > 0] * (1.0 + c) assert ((S_u >= S_l).all()) assert ((S0_u >= S0_l).all()) logging.debug("Bounds for normalized data E = S/S_0 ...") E_l = S_l / S0_u[..., None] E_u = S_u / S0_l[..., None] assert ((E_u >= E_l).all()) # E_l[:] = 0.0 # E_u[:] = 1.0 logging.debug("Bounds for the monotone decreasing log(-log) transform") loglog_E_l = np.log(-np.log(E_u.clip(0.001, 0.999))) loglog_E_u = np.log(-np.log(E_l.clip(0.001, 0.999))) assert ((loglog_E_u >= loglog_E_l).all()) logging.debug("Bounds for the FRT") FRT_op = FRT_linop(b_sph, sph) rhs_l = np.einsum('kl,...l->...k', FRT_op, loglog_E_l) rhs_u = np.einsum('kl,...l->...k', FRT_op, loglog_E_u) assert ((rhs_u >= rhs_l).all()) c_shift = (2 - np.log(2)) / (4 * np.pi) rhs_u, rhs_l = -rhs_l, -rhs_u rhs_l += c_shift rhs_u += c_shift from tools import InverseLaplaceBeltrami, normalize_odf Phi = InverseLaplaceBeltrami(sph, b_sph) u_true = None synthetic = False if synthetic: example = 2 if example == 1: # uniform u = np.ones(b_sph.mdims['l_labels']) elif example == 2: # bimodals from dipy.sims.voxel import multi_tensor_odf verts = b_sph.v.T directions = [30, 90] val_base = 1e-6 * 200 vals = [8.5 * val_base, val_base, val_base] vecs = [ np.array([ np.sin(phi * np.pi / 180.0), np.cos(phi * np.pi / 180.0), 0 ]) for phi in directions ] u = multi_tensor_odf(verts, np.array((vals, vals)), vecs, [50, 50]) normalize_odf(u, b_sph.b) w = np.einsum('jk,k->j', Phi, u) # print (w.mean()) c1 = 0.05 for i in range(rhs_u.shape[0]): rhs_l[i, :] = w[:] * (1.0 - c1) rhs_u[i, :] = w[:] * (1.0 + c1) u_true = np.tile(u, (rhs_u.shape[0], 1)).T assert ((rhs_u >= rhs_l).all()) return rhs_l, rhs_u, u_true