def test_diffusivities(): psphere = get_sphere('symmetric362') bvecs = np.concatenate(([[0, 0, 0]], psphere.vertices)) bvals = np.zeros(len(bvecs)) + 1000 bvals[0] = 0 gtab = grad.gradient_table(bvals, bvecs) mevals = np.array(([0.0015, 0.0003, 0.0001], [0.0015, 0.0003, 0.0003])) mevecs = [np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]), np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]])] S = single_tensor(gtab, 100, mevals[0], mevecs[0], snr=None) dm = dti.TensorModel(gtab, 'LS') dmfit = dm.fit(S) md = mean_diffusivity(dmfit.evals) Trace = trace(dmfit.evals) rd = radial_diffusivity(dmfit.evals) ad = axial_diffusivity(dmfit.evals) lin = linearity(dmfit.evals) plan = planarity(dmfit.evals) spher = sphericity(dmfit.evals) assert_almost_equal(md, (0.0015 + 0.0003 + 0.0001) / 3) assert_almost_equal(Trace, (0.0015 + 0.0003 + 0.0001)) assert_almost_equal(ad, 0.0015) assert_almost_equal(rd, (0.0003 + 0.0001) / 2) assert_almost_equal(lin, (0.0015 - 0.0003)/Trace) assert_almost_equal(plan, 2 * (0.0003 - 0.0001)/Trace) assert_almost_equal(spher, (3 * 0.0001)/Trace)
def test_wls_and_ls_fit(): """ Tests the WLS and LS fitting functions to see if they returns the correct eigenvalues and eigenvectors. Uses data/55dir_grad.bvec as the gradient table and 3by3by56.nii as the data. """ # Defining Test Voxel (avoid nibabel dependency) ### # Recall: D = [Dxx,Dyy,Dzz,Dxy,Dxz,Dyz,log(S_0)] and D ~ 10^-4 mm^2 /s b0 = 1000. bvec, bval = read_bvec_file(get_data('55dir_grad.bvec')) B = bval[1] # Scale the eigenvalues and tensor by the B value so the units match D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B evals = np.array([2., 1., 0.]) / B md = evals.mean() tensor = from_lower_triangular(D) # Design Matrix gtab = grad.gradient_table(bval, bvec) X = dti.design_matrix(gtab) # Signals Y = np.exp(np.dot(X, D)) assert_almost_equal(Y[0], b0) Y.shape = (-1,) + Y.shape # Testing WLS Fit on Single Voxel # If you do something wonky (passing min_signal<0), you should get an # error: npt.assert_raises(ValueError, TensorModel, gtab, fit_method='WLS', min_signal=-1) # Estimate tensor from test signals model = TensorModel(gtab, fit_method='WLS', return_S0_hat=True) tensor_est = model.fit(Y) assert_equal(tensor_est.shape, Y.shape[:-1]) assert_array_almost_equal(tensor_est.evals[0], evals) assert_array_almost_equal(tensor_est.quadratic_form[0], tensor, err_msg="Calculation of tensor from Y does not " "compare to analytical solution") assert_almost_equal(tensor_est.md[0], md) assert_array_almost_equal(tensor_est.S0_hat[0], b0, decimal=3) # Test that we can fit a single voxel's worth of data (a 1d array) y = Y[0] tensor_est = model.fit(y) assert_equal(tensor_est.shape, tuple()) assert_array_almost_equal(tensor_est.evals, evals) assert_array_almost_equal(tensor_est.quadratic_form, tensor) assert_almost_equal(tensor_est.md, md) assert_array_almost_equal(tensor_est.lower_triangular(b0), D) # Test using fit_method='LS' model = TensorModel(gtab, fit_method='LS') tensor_est = model.fit(y) assert_equal(tensor_est.shape, tuple()) assert_array_almost_equal(tensor_est.evals, evals) assert_array_almost_equal(tensor_est.quadratic_form, tensor) assert_almost_equal(tensor_est.md, md) assert_array_almost_equal(tensor_est.lower_triangular(b0), D) assert_array_almost_equal(tensor_est.linearity, linearity(evals)) assert_array_almost_equal(tensor_est.planarity, planarity(evals)) assert_array_almost_equal(tensor_est.sphericity, sphericity(evals))
def fit(self, data, mask=None): tenfit = self.tenmodel.fit(data, mask) evals = tenfit.evals tensor_linearity = dti.linearity(evals) if tensor_linearity > self.tensor_linearity_threshold: R = tenfit.evecs else: R = None # improves robustness of the fitting to include a # lower bound on eigenvalues. evals = np.clip(evals, self.tensor_scale_lower_bound, evals.max()) mu = np.sqrt(evals.mean() * 2 * self.tau) qvals = np.sqrt(self.gtab.bvals / self.tau) / (2 * np.pi) Q_mu_dependent = shore_Q_mu_dependent(self.radial_order, mu, qvals) M = Q_mu_dependent * self.Q_mu_independent if not self.positive_constraint and not self.constraint_e0 and not\ self.laplacian_regularization and not\ self.separated_regularization: coef = np.dot(np.dot(np.linalg.pinv((np.dot(M.T, M))), M.T), data) if self.laplacian_regularization: laplacian_matrix = self.laplacian_matrix * mu if self.laplacian_weighting == 'GCV': lopt = generalized_crossvalidation(data, M, laplacian_matrix) else: lopt = self.laplacian_weighting if self.constraint_e0 or self.positive_constraint: Q = matrix(np.dot(M.T, M) + lopt * laplacian_matrix) else: Mreg = np.dot(M.T, M) + lopt * laplacian_matrix zeros = np.zeros(Mreg.shape[0]) coef = zeros if (data == 0).all(): coef = zeros else: try: MregInv = np.linalg.pinv(Mreg) coef = np.dot(np.dot(MregInv, M.T), data) except np.linalg.linalg.LinAlgError as err: if 'SVD did not converge' in err.message: warnings.warn('SVD did not converge') coef = zeros else: raise else: lopt = 0 if self.separated_regularization: N_mat = self.N_mat L_mat = self.L_mat if self.separated_weighting == 'GCV': loptN, loptL = generalized_crossvalidation2D( data, M, N_mat, L_mat) else: loptN = loptL = self.separated_weighting if self.constraint_e0 or self.positive_constraint: Q = matrix(np.dot(M.T, M) + loptN * N_mat + loptL * L_mat) else: Mreg = np.dot(M.T, M) + loptN * N_mat + loptL * L_mat zeros = np.zeros(Mreg.shape[0]) coef = zeros if (data == 0).all(): coef = zeros else: try: MregInv = np.linalg.pinv(Mreg) coef = np.dot(np.dot(MregInv, M.T), data) except np.linalg.linalg.LinAlgError as err: if 'SVD did not converge' in err.message: warnings.warn('SVD did not converge') coef = zeros else: raise else: loptN = loptL = 0 if self.constraint_e0 or self.positive_constraint: Q = matrix(np.dot(M.T, M)) if self.positive_constraint: constraint_grid = self.constraint_grid K_independent = self.pos_K_independent K_dependent = shore_K_mu_dependent(self.radial_order, mu, constraint_grid) K = K_independent * K_dependent G = matrix(-1 * K) h = matrix(np.zeros((K.shape[0])), (K.shape[0], 1)) else: G = None h = None if self.constraint_e0: data = data / data[self.gtab.b0s_mask].mean() p = matrix(-1 * np.dot(M.T, data)) A = matrix(M[0], (1, M.shape[1])) b = matrix(1.0) else: p = matrix(-1 * np.dot(M.T, data)) A = None b = None solvers.options['show_progress'] = False try: sol = solvers.qp(Q, p, G, h, A, b) coef = np.array(sol['x'])[:, 0] except ValueError: coef = np.zeros(self.ind_mat.shape[0]) if not (self.constraint_e0): coef = coef / sum(coef * self.B_mat) # Apply the mask to the coefficients if mask is not None: mask = np.asarray(mask, dtype=bool) coef *= mask[..., None] return ShoreOzarslanFit(self, coef, mu, R, lopt, loptN, loptL)