def mesh_to_sphere(mesh): vertices = np.array(mesh.vertex()).astype(np.float64) faces = np.array(mesh.polygon()).astype(np.uint16) sphere = Sphere(xyz=vertices, faces=faces) #step not necessary but just to be sure edges = sphere.edges.astype(np.uint16) sphere = Sphere(xyz=vertices, faces=faces, edges=edges) return sphere
def test_sphere_subdivide(): sphere1 = unit_octahedron.subdivide(4) sphere2 = Sphere(xyz=sphere1.vertices) nt.assert_equal(sphere1.faces.shape, sphere2.faces.shape) nt.assert_equal(array_to_set(sphere1.faces), array_to_set(sphere2.faces)) sphere1 = unit_icosahedron.subdivide(4) sphere2 = Sphere(xyz=sphere1.vertices) nt.assert_equal(sphere1.faces.shape, sphere2.faces.shape) nt.assert_equal(array_to_set(sphere1.faces), array_to_set(sphere2.faces))
def test_sphere_edges_faces(): nt.assert_raises(ValueError, Sphere, xyz=1, edges=1, faces=None) Sphere(xyz=[0, 0, 1], faces=[0, 0, 0]) Sphere(xyz=[[0, 0, 1], [1, 0, 0], [0, 1, 0]], edges=[[0, 1], [1, 2], [2, 0]], faces=[0, 1, 2])
def test_sphere_construct(): s0 = Sphere(xyz=verts) s1 = Sphere(theta=theta, phi=phi) s2 = Sphere(*verts.T) nt.assert_array_almost_equal(s0.theta, s1.theta) nt.assert_array_almost_equal(s0.theta, s2.theta) nt.assert_array_almost_equal(s0.theta, theta) nt.assert_array_almost_equal(s0.phi, s1.phi) nt.assert_array_almost_equal(s0.phi, s2.phi) nt.assert_array_almost_equal(s0.phi, phi)
def test_edges_faces(): s = Sphere(xyz=verts) faces = oct_faces nt.assert_equal(array_to_set(s.faces), array_to_set(faces)) nt.assert_equal(array_to_set(s.edges), array_to_set(edges)) s = Sphere(xyz=verts, faces=[[0, 1, 2]]) nt.assert_equal(array_to_set(s.faces), array_to_set([[0, 1, 2]])) nt.assert_equal(array_to_set(s.edges), array_to_set([[0, 1], [1, 2], [0, 2]])) s = Sphere(xyz=verts, faces=[[0, 1, 2]], edges=[[0, 1]]) nt.assert_equal(array_to_set(s.faces), array_to_set([[0, 1, 2]])) nt.assert_equal(array_to_set(s.edges), array_to_set([[0, 1]]))
def dir_compute_peaks(output_dir, relative_peak_threshold=.5, peak_normalize=1, min_separation_angle=45, max_peak_number=5): peaks_file = os.path.join(output_dir, 'peaks.npz') result_file = os.path.join(output_dir, 'result_raw.pickle') result = pickle.load(open(result_file, 'rb'))[0] try: u_RECON = result['u'] except KeyError: u_RECON = result['u1'] b_sph = load_b_sph(output_dir) sphere = Sphere(xyz=b_sph.v.T) f_noisy = reconst_f(output_dir, b_sph)[0] l_labels = u_RECON.shape[0] imagedims = u_RECON.shape[1:] num_peak_coeffs = max_peak_number * 3 computed_peaks = [] for odfs in [u_RECON, f_noisy]: peaks = compute_peaks(odfs, sphere, relative_peak_threshold=.5, peak_normalize=1, min_separation_angle=45, max_peak_number=5) computed_peaks.append(peaks.reshape(imagedims + (peaks.shape[-1], ))) np.savez_compressed(peaks_file, computed_peaks) return computed_peaks
def test_fbc(): """Test the FBC measures on a set of fibers""" # Generate two fibers of 10 points streamlines = [] for i in range(2): fiber = np.zeros((10, 3)) for j in range(10): fiber[j, 0] = j fiber[j, 1] = i*0.2 fiber[j, 2] = 0 streamlines.append(fiber) # Create lookup table. # A fixed set of orientations is used to guarantee deterministic results D33 = 1.0 D44 = 0.04 t = 1 sphere = Sphere(xyz=np.array([[0.82819078, 0.51050355, 0.23127074], [-0.10761926, -0.95554309, 0.27450957], [0.4101745, -0.07154038, 0.90919682], [-0.75573448, 0.64854889, 0.09082809], [-0.56874549, 0.01377562, 0.8223982]])) k = EnhancementKernel(D33, D44, t, orientations=sphere, force_recompute=True) # run FBC fbc = FBCMeasures(streamlines, k, verbose=True) # get FBC values fbc_sl_orig, clrs_orig, rfbc_orig = \ fbc.get_points_rfbc_thresholded(0, emphasis=0.01) # check mean RFBC against tested value npt.assert_almost_equal(np.mean(rfbc_orig), 1.0500466494329224)
def correct_sphere(sphere): faces = sphere.faces.copy() vertices = sphere.vertices o = check_face_orientation(faces, vertices) faces[o, :] = faces[o, ::-1] new_sphere = Sphere(xyz=vertices, faces=faces) return new_sphere
def get_2D_sphere(no_phis=None, no_thetas=None): """Retrieve evenly distributed 2D sphere out of phi and theta count. Parameters ---------- no_phis : int, optional The numbers of phis in the sphere, by default as in config file / 16 no_thetas : int, optional The numbers of thetas in the sphere, by default as in config file / 16 Returns ------- Sphere The 2D sphere requested """ if no_thetas is None: no_thetas = Config.get_config().getint("2DSphereOptions", "noThetas", fallback="16") if no_phis is None: no_phis = Config.get_config().getint("2DSphereOptions", "noPhis", fallback="16") xi = np.arange(0, np.pi, (np.pi) / no_thetas) # theta yi = np.arange(-np.pi, np.pi, 2 * (np.pi) / no_phis) # phi basis = np.array(np.meshgrid(yi, xi)) sphere = Sphere(theta=basis[0, :], phi=basis[1, :]) return sphere
def mrtrix_spherical_functions(): """Spherical functions represented by spherical harmonic coefficients and evaluated on a discrete sphere. Returns ------- func_coef : array (2, 3, 4, 45) Functions represented by the coefficients associated with the mxtrix spherical harmonic basis of order 8. func_discrete : array (2, 3, 4, 81) Functions evaluated on `sphere`. sphere : Sphere The discrete sphere, points on the surface of a unit sphere, used to evaluate the functions. Notes ----- These coefficients were obtained by using the dwi2SH command of mrtrix. """ func_discrete = load(pjoin(DATA_DIR, "func_discrete.nii.gz")).get_data() func_coef = load(pjoin(DATA_DIR, "func_coef.nii.gz")).get_data() gradients = np.loadtxt(pjoin(DATA_DIR, "sphere_grad.txt")) # gradients[0] and the first volume of func_discrete, # func_discrete[..., 0], are associated with the b=0 signal. # gradients[:, 3] are the b-values for each gradient/volume. sphere = Sphere(xyz=gradients[1:, :3]) return func_coef, func_discrete[..., 1:], sphere
def test_sh_to_sf_matrix(): sphere = Sphere(xyz=hemi_icosahedron.vertices) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) B1, invB1 = sh_to_sf_matrix(sphere) B2, m, n = real_sh_descoteaux(4, sphere.theta, sphere.phi) invB2 = smooth_pinv(B2, L=np.zeros_like(n)) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=descoteaux07_legacy_msg, category=PendingDeprecationWarning) B3 = sh_to_sf_matrix(sphere, return_inv=False) assert_array_almost_equal(B1, B2.T) assert_array_almost_equal(invB1, invB2.T) assert_array_almost_equal(B3, B1) assert_raises(ValueError, sh_to_sf_matrix, sphere, basis_type="")
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 resample_dwi(self, directions=None, sh_order=8, smooth=0.006): """ Resamples a diffusion signal according to a set of directions using spherical harmonics. Parameters ----------- directions : `dipy.core.sphere.Sphere` object, optional Directions the diffusion signal will be resampled to. Directions are assumed to be on the whole sphere, not the hemisphere like bvecs. If omitted, 100 directions evenly distributed on the sphere will be used. sh_order : int, optional SH order. Default: 8 smooth : float, optional Lambda-regularization in the SH fit. Default: 0.006. """ data_sh = self.get_spherical_harmonics_coefficients(self.dwi, self.bvals, self.bvecs, sh_order=sh_order, smooth=smooth) sphere = get_sphere('repulsion100') if directions is not None: sphere = Sphere(xyz=directions) sph_harm_basis = sph_harm_lookup.get("tournier07") Ba, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi) data_resampled = np.dot(data_sh, Ba.T) return data_resampled
def odf(self, sphere): ## Override the odf method to subclass OdfFit bvec = self.model.bvec[self.model.bval > 0] data = self.data[self.model.bval > 0] origin_sphere = Sphere(xyz=bvec) discrete_odf = 1. / data return interp_rbf(discrete_odf, origin_sphere, sphere)
def create_sphere(n_pts): theta = np.pi * np.random.rand(n_pts) phi = 2 * np.pi * np.random.rand(n_pts) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, _ = disperse_charges(hsph_initial, 5000) sph = Sphere(xyz=np.vstack((hsph_updated.vertices, -hsph_updated.vertices))) return sph
def plot_signal(bvecs, signal, origin=[0, 0, 0], maya=True, cmap='jet', file_name=None, colorbar=False, figure=None, vmin=None, vmax=None, offset=0, azimuth=60, elevation=90, roll=0, non_neg=False): """ Interpolate a measured signal, using RBF interpolation. Parameters ---------- signal: bvecs: array (3,n) the x,y,z locations where the signal was measured offset : float where to place the plotted voxel (on the z axis) """ s0 = Sphere(xyz=bvecs.T) vertices = s0.vertices faces = s0.faces x, y, z = vertices.T r, phi, theta = geo.cart2sphere(x, y, z) x_plot, y_plot, z_plot = geo.sphere2cart(signal, phi, theta) if non_neg: signal[np.where(signal < 0)] = 0 # Call and return straightaway: return _display_maya_voxel(x_plot, y_plot, z_plot, faces, signal, origin, cmap=cmap, colorbar=colorbar, figure=figure, vmin=vmin, vmax=vmax, file_name=file_name, azimuth=azimuth, elevation=elevation)
def resample_dwi(dwi, bvals, bvecs, directions=None, sh_order=8, smooth=0.006, mean_centering=True): """ Resamples a diffusion signal according to a set of directions using spherical harmonics. Parameters ----------- dwi : `nibabel.NiftiImage` object Diffusion signal as weighted images (4D). bvals : ndarray shape (N,) B-values used with each direction. bvecs : ndarray shape (N, 3) Directions of the diffusion signal. Directions are assumed to be only on the hemisphere. directions : `dipy.core.sphere.Sphere` object, optional Directions the diffusion signal will be resampled to. Directions are assumed to be on the whole sphere, not the hemisphere like bvecs. If omitted, 100 directions evenly distributed on the sphere will be used. sh_order : int, optional SH order. Default: 8 smooth : float, optional Lambda-regularization in the SH fit. Default: 0.006. mean_centering : bool If True, signal will have zero mean in each direction for all nonzero voxels Returns ------- ndarray Diffusion weights resampled according to `sphere`. """ data_sh = get_spherical_harmonics_coefficients(dwi, bvals, bvecs, sh_order=sh_order, smooth=smooth, mean_centering=False) sphere = get_sphere('repulsion100') # sphere = get_sphere('repulsion724') if directions is not None: sphere = Sphere(xyz=bvecs[1:]) sph_harm_basis = sph_harm_lookup.get('mrtrix') Ba, m, n = sph_harm_basis(sh_order, sphere.theta, sphere.phi) data_resampled = np.dot(data_sh, Ba.T) if mean_centering: # Normalization in each direction (zero mean) idx = data_resampled.sum(axis=-1).nonzero() means = data_resampled[idx].mean(axis=0) data_resampled[idx] -= means return data_resampled
def sph_peaks_t(power_map, theta_look, phi_look, max_n_peaks=20, audio_length_seconds=None, **kwargs): N_frames = power_map.shape[1] # set up sphere object for peak finding sph = Sphere(theta=phi_look, phi=theta_look) # set up output arrays for DOAs y_t = np.zeros((N_frames, max_n_peaks)) x_t = np.zeros((N_frames, max_n_peaks)) for i in range(N_frames): # peak finding in spherical data _, _, peaks = peak_directions(power_map[:, i], sph, **kwargs) # relative_peak_threshold=.5, # min_separation_angle=5) # save peaks to arrays xdirs = theta_look[peaks] ydirs = phi_look[peaks] # get rid of any extra peaks xdirs = xdirs[:max_n_peaks - 1] ydirs = ydirs[:max_n_peaks - 1] x_t[i, 0] = i y_t[i, 0] = i x_t[i, 1:len(xdirs) + 1] += xdirs y_t[i, 1:len(xdirs) + 1] += ydirs # rearranging data to a useful format for i in range(np.min(x_t.shape) - 1): xyi = np.append(np.append(x_t[:, [0]], x_t[:, [i + 1]], 1), y_t[:, [i + 1]], 1) if 'xy_t' not in locals(): xy_t = xyi else: xy_t = np.append(xy_t, xyi, 0) # remove zeros xy_t = xy_t[np.where(xy_t[:, 2] != 0)] if audio_length_seconds is not None: # replace frame numbers with time in seconds n_frames = len(power_map.T) time_index = np.linspace(0, audio_length_seconds, n_frames) # time_points = time_index[xy_t[:,0].astype(int)] xy_t[:, 0] = time_index[xy_t[:, 0].astype(int)] return xy_t
def process(self, data_container, points, dwi): raw_sphere = Sphere(xyz=data_container.bvecs) real_sh, _, n = real_sym_sh_mrtrix(self.sh_order, raw_sphere.theta, raw_sphere.phi) l = -n * (n + 1) inv_b = smooth_pinv(real_sh, np.sqrt(self.smooth) * l) data_sh = np.dot(dwi, inv_b.T) return data_sh
def test_apparent_kurtosis_coef(): """ Apparent kurtosis coeficients are tested for a spherical kurtosis tensor """ sph = Sphere(xyz=gtab.bvecs[gtab.bvals > 0]) AKC = dki.apparent_kurtosis_coef(params_sph, sph) # check all direction for d in range(len(gtab.bvecs[gtab.bvals > 0])): assert_array_almost_equal(AKC[d], Kref_sphere)
def peak_dist(_, u, b_sph): sphere = Sphere(xyz=b_sph.v.T) peaks = compute_peaks(u, sphere, relative_peak_threshold=.5, peak_normalize=1, min_separation_angle=25, max_peak_number=5) _, _, _, AE = compute_err(peaks, load_gt_img()) return AE
def test_sh_to_sf_matrix(): sphere = Sphere(xyz=hemi_icosahedron.vertices) B1, invB1 = sh_to_sf_matrix(sphere) B2, m, n = real_sym_sh_basis(4, sphere.theta, sphere.phi) invB2 = smooth_pinv(B2, L=np.zeros_like(n)) B3 = sh_to_sf_matrix(sphere, return_inv=False) assert_array_almost_equal(B1, B2.T) assert_array_almost_equal(invB1, invB2.T) assert_array_almost_equal(B3, B1) assert_raises(ValueError, sh_to_sf_matrix, sphere, basis_type="")
def test_basic_cache(): t = DummyModel() s = Sphere(theta=[0], phi=[0]) assert_(t.cache_get("design_matrix", s) is None) m = [[1, 0], [0, 1]] t.cache_set("design_matrix", key=s, value=m) assert_equal(t.cache_get("design_matrix", s), m) t.cache_clear() assert_(t.cache_get("design_matrix", s) is None)
def test_single_voxel_DKI_stats(): # tests if AK and RK are equal to expected values for a single fiber # simulate randomly oriented ADi = 0.00099 ADe = 0.00226 RDi = 0 RDe = 0.00087 # Reference values AD = fie * ADi + (1 - fie) * ADe AK = 3 * fie * (1 - fie) * ((ADi - ADe) / AD)**2 RD = fie * RDi + (1 - fie) * RDe RK = 3 * fie * (1 - fie) * ((RDi - RDe) / RD)**2 ref_vals = np.array([AD, AK, RD, RK]) # simulate fiber randomly oriented theta = random.uniform(0, 180) phi = random.uniform(0, 320) angles = [(theta, phi), (theta, phi)] mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]]) frac = [fie * 100, (1 - fie) * 100] signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, S0=100, angles=angles, fractions=frac, snr=None) evals, evecs = decompose_tensor(from_lower_triangular(dt)) dki_par = np.concatenate((evals, evecs[0], evecs[1], evecs[2], kt), axis=0) # Estimates using dki functions ADe1 = dti.axial_diffusivity(evals) RDe1 = dti.radial_diffusivity(evals) AKe1 = axial_kurtosis(dki_par) RKe1 = radial_kurtosis(dki_par) e1_vals = np.array([ADe1, AKe1, RDe1, RKe1]) assert_array_almost_equal(e1_vals, ref_vals) # Estimates using the kurtosis class object dkiM = dki.DiffusionKurtosisModel(gtab_2s) dkiF = dkiM.fit(signal) e2_vals = np.array([dkiF.ad, dkiF.ak(), dkiF.rd, dkiF.rk()]) assert_array_almost_equal(e2_vals, ref_vals) # test MK (note this test correspond to the MK singularity L2==L3) MK_as = dkiF.mk() sph = Sphere(xyz=gtab.bvecs[gtab.bvals > 0]) MK_nm = np.mean(dkiF.akc(sph)) assert_array_almost_equal(MK_as, MK_nm, decimal=1)
def create_symmetric_repulsion_sphere(n_points, n_iter): """ Create a full Sphere object using electrostatic repulsion. params: npoints: number of points in the electrostatic repulsion n_iter: number of iterations to optimise energy return: Sphere object with 2*npoints vertices """ theta = np.pi * np.random.rand(n_points) phi = 2 * np.pi * np.random.rand(n_points) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, energy = disperse_charges(hsph_initial, iters=n_iter) sph = Sphere(xyz=np.vstack((hsph_updated.vertices, -hsph_updated.vertices))) return sph
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)
def test_MK_singularities(): # To test MK in case that analytical solution was a singularity not covered # by other tests dkiM = dki.DiffusionKurtosisModel(gtab_2s) # test singularity L1 == L2 - this is the case of a prolate diffusion # tensor for crossing fibers at 90 degrees angles_all = np.array([[(90, 0), (90, 0), (0, 0), (0, 0)], [(89.9, 0), (89.9, 0), (0, 0), (0, 0)]]) for angles_90 in angles_all: s_90, dt_90, kt_90 = multi_tensor_dki(gtab_2s, mevals_cross, S0=100, angles=angles_90, fractions=frac_cross, snr=None) dkiF = dkiM.fit(s_90) MK = dkiF.mk() sph = Sphere(xyz=gtab.bvecs[gtab.bvals > 0]) MK_nm = np.mean(dkiF.akc(sph)) assert_almost_equal(MK, MK_nm, decimal=2) # test singularity L1 == L3 and L1 != L2 # since L1 is defined as the larger eigenvalue and L3 the smallest # eigenvalue, this singularity teoretically will never be called, # because for L1 == L3, L2 have also to be = L1 and L2. # Nevertheless, I decided to include this test since this singularity # is revelant for cases that eigenvalues are not ordered # artificially revert the eigenvalue and eigenvector order dki_params = dkiF.model_params.copy() dki_params[1] = dkiF.model_params[2] dki_params[2] = dkiF.model_params[1] dki_params[4] = dkiF.model_params[5] dki_params[5] = dkiF.model_params[4] dki_params[7] = dkiF.model_params[8] dki_params[8] = dkiF.model_params[7] dki_params[10] = dkiF.model_params[11] dki_params[11] = dkiF.model_params[10] MK = dki.mean_kurtosis(dki_params) MK_nm = np.mean(dki.apparent_kurtosis_coef(dki_params, sph)) assert_almost_equal(MK, MK_nm, decimal=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 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_compare_MK_method(): # tests if analytical solution of MK is equal to the average of directional # kurtosis sampled from a sphere # DKI Model fitting dkiM = dki.DiffusionKurtosisModel(gtab_2s) dkiF = dkiM.fit(signal_cross) # MK analytical solution MK_as = dkiF.mk() # MK numerical method sph = Sphere(xyz=gtab.bvecs[gtab.bvals > 0]) MK_nm = np.mean(dki.apparent_kurtosis_coef(dkiF.model_params, sph), axis=-1) assert_array_almost_equal(MK_as, MK_nm, decimal=1)
def test_compare_RK_methods(): # tests if analytical solution of RK is equal to the perpendicular kurtosis # relative to the first diffusion axis # DKI Model fitting dkiM = dki.DiffusionKurtosisModel(gtab_2s) dkiF = dkiM.fit(signal_cross) # MK analytical solution RK_as = dkiF.rk() # MK numerical method evecs = dkiF.evecs p_dir = perpendicular_directions(evecs[:, 0], num=30, half=True) ver = Sphere(xyz=p_dir) RK_nm = np.mean(dki.apparent_kurtosis_coef(dkiF.model_params, ver), axis=-1) assert_array_almost_equal(RK_as, RK_nm)