def test_coordinate_transformation(): # test for a vector of size 3 cartesian_vector = np.random.rand(3) spherical_vector = utils.cart2sphere(cartesian_vector) recovered_cartesian_vector = utils.sphere2cart(spherical_vector) assert_almost_equal(cartesian_vector, recovered_cartesian_vector) # test for a vector of size N x 3 cartesian_vector = np.random.rand(10, 3) spherical_vector = utils.cart2sphere(cartesian_vector) recovered_cartesian_vector = utils.sphere2cart(spherical_vector) assert_almost_equal(cartesian_vector, recovered_cartesian_vector)
def test_rotation_on_bingham_tensor(): # test 5: does combined rotation rotate Bingham well? kappa_ = np.random.rand() beta_ = kappa_ / 2. # beta<kappa Bdiag_ = np.diag(np.r_[kappa_, beta_, 0]) theta_ = np.random.rand() * np.pi phi_ = (np.random.rand() - .5) * np.pi psi_ = np.random.rand() * np.pi * 0 R_ = rotation_matrix_100_to_theta_phi_psi(theta_, phi_, psi_) B_ = R_.dot(Bdiag_).dot(R_.T) eigvals, eigvecs = np.linalg.eigh(B_) main_evec = eigvecs[:, np.argmax(eigvals)] _, theta_rec0, phi_rec0 = utils.cart2sphere(main_evec) # checking if the angles are antipodal to each other if abs(theta_ - theta_rec0) > 1e-5: theta_rec = np.pi - theta_rec0 if phi_rec0 > 0: phi_rec = phi_rec0 - np.pi elif phi_rec0 < 0: phi_rec = phi_rec0 + np.pi else: theta_rec = theta_rec0 phi_rec = phi_rec0 assert_almost_equal(theta_, theta_rec) assert_almost_equal(phi_, phi_rec) assert_almost_equal(np.diag(Bdiag_), np.sort(eigvals)[::-1])
def test_rotation_100_to_theta_phi(): # test 1: does R100_to_theta_phi rotate a vector theta_phi? theta_ = np.random.rand() * np.pi phi_ = (np.random.rand() - .5) * np.pi R100_to_theta_pi = rotation_matrix_100_to_theta_phi(theta_, phi_) xyz = np.dot(R100_to_theta_pi, np.r_[1, 0, 0]) _, theta_rec, phi_rec = utils.cart2sphere(xyz) assert_almost_equal(theta_, theta_rec) assert_almost_equal(phi_, phi_rec)
def test_psi_insensitivity_when_doing_psi_theta_phi_rotation(): # test 3: does psi still have no influence on main eigenvector when doing # both rotations? theta_ = np.random.rand() * np.pi phi_ = (np.random.rand() - .5) * np.pi psi_ = np.random.rand() * np.pi R_ = rotation_matrix_100_to_theta_phi_psi(theta_, phi_, psi_) xyz = np.dot(R_, np.r_[1, 0, 0]) _, theta_rec, phi_rec = utils.cart2sphere(xyz) assert_almost_equal(theta_, theta_rec) assert_almost_equal(phi_, phi_rec)
def test_watson_orienting(): # test for orienting the axis of the Watson distribution mu for k>0 # first test to see if Wn is highest along mu sphere = get_sphere('repulsion724') n = sphere.vertices indices = np.array(range(n.shape[0])) np.random.shuffle(indices) mu_index = indices[0] mu_cart = n[mu_index] mu_sphere = utils.cart2sphere(mu_cart)[1:] odi = np.random.rand() watson = distributions.SD1Watson(mu=mu_sphere, odi=odi) Wn_vector = watson(n=n) assert_almost_equal(Wn_vector[mu_index], max(Wn_vector)) # second test to see if Wn is lowest prependicular to mu mu_perp = utils.perpendicular_vector(mu_cart) Wn_perp = watson(n=mu_perp) assert_equal(np.all(Wn_perp < Wn_vector), True)
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)
def __call__(self, n, **kwargs): r"""Returns the sphere function at cartesian orientations n given spherical harmonic coefficients. Parameters ---------- n : array of shape(N x 3), sampled orientations of the Watson distribution. Returns ------- SHn: array of shape(N), Probability density at orientations n, given sh coeffs. """ # calculate SHT matrix _, theta, phi = utils.cart2sphere(n).T SHT = real_sym_sh_mrtrix(self.sh_order, theta, phi)[0] # transform coefficients to sphere values sh_coeff = kwargs.get('sh_coeff', self.sh_coeff) SHn = SHT.dot(sh_coeff) return SHn
from scipy import interpolate from dmipy.core.modeling_framework import ModelProperties from dipy.utils.optpkg import optional_package from dipy.data import get_sphere, HemiSphere sphere = get_sphere('symmetric724') hemisphere = HemiSphere(phi=sphere.phi, theta=sphere.theta) numba, have_numba, _ = optional_package("numba") GRADIENT_TABLES_PATH = pkg_resources.resource_filename('dmipy', 'data/gradient_tables') SIGNAL_MODELS_PATH = pkg_resources.resource_filename('dmipy', 'signal_models') DATA_PATH = pkg_resources.resource_filename('dmipy', 'data') SPHERE_CARTESIAN = np.loadtxt(join(GRADIENT_TABLES_PATH, 'sphere_with_cap.txt')) SPHERE_SPHERICAL = utils.cart2sphere(SPHERE_CARTESIAN) log_bingham_normalization_splinefit = np.load(join( DATA_PATH, "bingham_normalization_splinefit.npz"), encoding='bytes')['arr_0'] inverse_sh_matrix_kernel = { sh_order: np.linalg.pinv( real_sym_sh_mrtrix(sh_order, hemisphere.theta, hemisphere.phi)[0]) for sh_order in np.arange(0, 15, 2) } BETA_SCALING = 1e-6 __all__ = [ 'get_sh_order_from_odi', 'SD1Watson', 'SD2Bingham', 'DD1Gamma', 'odi2kappa', 'kappa2odi' ]