def shore_convolution_matrix(self, kernel="rank1"): """ Parameters ---------- kernel Returns ------- """ if self.kernel_type != kernel: self.set_kernel(kernel) # Build matrix that maps ODF+volume fractions to signal # in two steps: First, SHORE matrix # Ignore division by zero warning # dipy.core.geometry.cart2sphere -> theta = np.arccos(z / r) with np.errstate(divide='ignore', invalid='ignore'): shore_m = shore_matrix(self.order, self.zeta, self.gtab, self.tau) # then, convolution M_wm = shore.matrix_kernel(self.kernel_wm, self.order) M_gm = shore.matrix_kernel(self.kernel_gm, self.order) M_csf = shore.matrix_kernel(self.kernel_csf, self.order) M = np.hstack((M_wm, M_gm[:, :1], M_csf[:, :1])) # now, multiply them together return np.dot(shore_m, M)
def _fit_helper(self, data, vecs=None, rcond=None, **kwargs): """ Fitting is done here This function is handed to the MultivoxelFitter, to fit deconv for every voxel. Parameters ---------- data : ndarray (n) Data of a single voxel vecs : ndarray (3) First eigenvector of the diffusion tensor for a single voxel rcond : Cut-off ratio for small singular values of the coefficient matrix. For further information read documentation of numpy.linalg.lstsq. kwargs : dict Empty dictionary, not used in this function Returns ------- ShoreFit Object holding the fitted model parameters """ if vecs is not None: with np.errstate(divide='ignore', invalid='ignore'): shore_m = shore_matrix(self.order, self.zeta, gtab_reorient(self.gtab, vecs), self.tau) else: shore_m = self.shore_m coeffs = la.lstsq(shore_m, data, rcond)[0] return ShoreFit(np.array(coeffs))
def __init__(self, gtab, order=4, zeta=700, tau=1 / (4 * np.pi ** 2)): """ Model the diffusion imaging signal using the shore basis Parameters ---------- gtab : dipy.data.GradientTable b-values and b-vectors in a GradientTable object order : int An even integer representing the order of the shore basis zeta : float Radial scaling factor tau : float Diffusion time """ super().__init__(gtab) self.order = order self.zeta = zeta self.tau = tau # These parameters are saved for reinitalization self._params_dict = {'bvals': gtab.bvals, 'bvecs': gtab.bvecs, 'order': order, 'zeta': zeta, 'tau': tau} # Ignore division by zero warning # dipy.core.geometry.cart2sphere -> theta = np.arccos(z / r) with np.errstate(divide='ignore', invalid='ignore'): self.shore_m = shore_matrix(self.order, self.zeta, self.gtab, self.tau)
def return_shore_basis(n,gtab,scale): lambdaN = 1e-8 lambdaL = 1e-8 radial_order = n Lshore = l_shore(radial_order) Nshore = n_shore(radial_order) M = shore_matrix(n, scale, gtab, 1. / (4 * np.pi ** 2)) return M
def get_shore_coeffs(D, n, scale, input_gtab): lambdaN = 1e-8 lambdaL = 1e-8 radial_order = n Lshore = l_shore(radial_order) Nshore = n_shore(radial_order) M = shore_matrix(n, scale, input_gtab, 1. / (4 * np.pi ** 2)) MpseudoInv = np.dot(np.linalg.inv(np.dot(M.T, M) + lambdaN * Nshore + lambdaL * Lshore), M.T) shorecoefs = np.dot(D, MpseudoInv.T) return shorecoefs
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)
def eval_minimized_zeta(D, n, gtab, scale): lambdaN = 1e-8 lambdaL = 1e-8 radial_order = n Lshore = l_shore(radial_order) Nshore = n_shore(radial_order) M = shore_matrix(n, scale, gtab, 1. / (4 * np.pi ** 2)) MpseudoInv = np.dot(np.linalg.inv(np.dot(M.T, M) + lambdaN * Nshore + lambdaL * Lshore), M.T) shorecoefs = np.dot(D, MpseudoInv.T) # shorecoefs = np.dot(D, pinv(Mshore).T) shorepred = np.dot(shorecoefs, M.T) return np.linalg.norm(D - shorepred) ** 2
def eval_shore(D, n, scale, input_gtab): lambdaN = 1e-8 lambdaL = 1e-8 radial_order = n Lshore = l_shore(radial_order) Nshore = n_shore(radial_order) M_1 = shore_matrix(n, scale, input_gtab, 1. / (4 * np.pi ** 2)) #M_2 = shore_matrix(n, scale, prov_gtab_1, 1. / (4 * np.pi ** 2)) MpseudoInv_1 = np.dot(np.linalg.inv(np.dot(M_1.T, M_1) + lambdaN * Nshore + lambdaL * Lshore), M_1.T) #MpseudoInv_2 = np.dot(np.linalg.inv(np.dot(M_2.T, M_2) + lambdaN * Nshore + lambdaL * Lshore), M_2.T) shorecoefs_1 = np.dot(D, MpseudoInv_1.T) #shorecoefs_2 = np.dot(D, MpseudoInv_2.T) # shorecoefs = np.dot(D, pinv(Mshore).T) shorepred_1 = np.dot(shorecoefs_1, M_1.T) #shorepred_2 = np.dot(shorecoefs_2, M_2.T) ''' plt.figure(1, figsize=(12,8)) plt.subplot(2,3,1) plt.plot(D[0, :]) plt.plot(shorepred[0, :]) plt.legend(['Original Signal','SHORE Fitted Signal']) plt.subplot(2,3,2) plt.plot(D[1, :]) plt.plot(shorepred[1, :]) plt.subplot(2,3,3) plt.plot(D[2, :]) plt.plot(shorepred[2, :]) plt.subplot(2,3,4) plt.plot(D[3, :]) plt.plot(shorepred[3, :]) plt.subplot(2,3,5) plt.plot(D[4, :]) plt.plot(shorepred[4, :]) plt.show() ''' return np.linalg.norm(D - shorepred_1) ** 2
def eval_shore(D, n, scale): lambdaN = 1e-8 lambdaL = 1e-8 radial_order = n Lshore = l_shore(radial_order) Nshore = n_shore(radial_order) M = shore_matrix(n, scale, fod_gtab) MpseudoInv = np.dot( np.linalg.inv(np.dot(M.T, M) + lambdaN * Nshore + lambdaL * Lshore), M.T) shorecoefs = np.dot(D, MpseudoInv.T) shorepred = np.dot(shorecoefs, M.T) D = np.exp(D) shorepred = np.exp(shorepred) return np.linalg.norm(D - shorepred)**2
def __init__(self, gtab, order=4, zeta=700, tau=1 / (4 * np.pi ** 2)): """ Parameters ---------- gtab : dipy.data.GradientTable b-values and b-vectors in a GradientTable object order : int An even integer representing the order of the shore basis zeta : float Radial scaling factor tau : float Diffusion time """ self.gtab = gtab self.order = order self.zeta = zeta self.tau = tau # Ignore division by zero warning # dipy.core.geometry.cart2sphere -> theta = np.arccos(z / r) with np.errstate(divide='ignore', invalid='ignore'): self.shore_m = shore_matrix(self.order, self.zeta, self.gtab, self.tau)
def test_shore_metrics(): gtab = get_gtab_taiwan_dsi() mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angl = [(0, 0), (60, 0)] S, sticks = MultiTensor(gtab, mevals, S0=100.0, angles=angl, fractions=[50, 50], snr=None) # test shore_indices n = 7 l = 6 m = -4 radial_order, c = shore_order(n, l, m) n2, l2, m2 = shore_indices(radial_order, c) assert_equal(n, n2) assert_equal(l, l2) assert_equal(m, m2) radial_order = 6 c = 41 n, l, m = shore_indices(radial_order, c) radial_order2, c2 = shore_order(n, l, m) assert_equal(radial_order, radial_order2) assert_equal(c, c2) # since we are testing without noise we can use higher order and lower lambdas, with respect to the default. radial_order = 8 zeta = 700 lambdaN = 1e-12 lambdaL = 1e-12 asm = ShoreModel(gtab, radial_order=radial_order, zeta=zeta, lambdaN=lambdaN, lambdaL=lambdaL) asmfit = asm.fit(S) c_shore = asmfit.shore_coeff cmat = shore_matrix(radial_order, zeta, gtab) S_reconst = np.dot(cmat, c_shore) # test the signal reconstruction S = S / S[0] nmse_signal = np.sqrt(np.sum((S - S_reconst) ** 2)) / (S.sum()) assert_almost_equal(nmse_signal, 0.0, 4) # test if the analytical integral of the pdf is equal to one integral = 0 for n in range(int((radial_order)/2 +1)): integral += c_shore[n] * (np.pi**(-1.5) * zeta **(-1.5) * genlaguerre(n,0.5)(0)) ** 0.5 assert_almost_equal(integral, 1.0, 10) # test if the integral of the pdf calculated on a discrete grid is equal to one pdf_discrete = asmfit.pdf_grid(17, 40e-3) integral = pdf_discrete.sum() assert_almost_equal(integral, 1.0, 1) # compare the shore pdf with the ground truth multi_tensor pdf sphere = get_sphere('symmetric724') v = sphere.vertices radius = 10e-3 pdf_shore = asmfit.pdf(v * radius) pdf_mt = multi_tensor_pdf(v * radius, mevals=mevals, angles=angl, fractions= [50, 50]) nmse_pdf = np.sqrt(np.sum((pdf_mt - pdf_shore) ** 2)) / (pdf_mt.sum()) assert_almost_equal(nmse_pdf, 0.0, 2) # compare the shore rtop with the ground truth multi_tensor rtop rtop_shore_signal = asmfit.rtop_signal() rtop_shore_pdf = asmfit.rtop_pdf() assert_almost_equal(rtop_shore_signal, rtop_shore_pdf, 9) rtop_mt = multi_tensor_rtop([.5, .5], mevals=mevals) assert_equal(rtop_mt / rtop_shore_signal <1.10 and rtop_mt / rtop_shore_signal > 0.95, True) # compare the shore msd with the ground truth multi_tensor msd msd_mt = multi_tensor_msd([.5, .5], mevals=mevals) msd_shore = asmfit.msd() assert_equal(msd_mt / msd_shore < 1.05 and msd_mt / msd_shore > 0.95, True)
def test_shore_metrics(): gtab = get_gtab_taiwan_dsi() mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angl = [(0, 0), (60, 0)] S, _ = multi_tensor(gtab, mevals, S0=100.0, angles=angl, fractions=[50, 50], snr=None) # test shore_indices n = 7 l = 6 m = -4 radial_order, c = shore_order(n, l, m) n2, l2, m2 = shore_indices(radial_order, c) npt.assert_equal(n, n2) npt.assert_equal(l, l2) npt.assert_equal(m, m2) radial_order = 6 c = 41 n, l, m = shore_indices(radial_order, c) radial_order2, c2 = shore_order(n, l, m) npt.assert_equal(radial_order, radial_order2) npt.assert_equal(c, c2) npt.assert_raises(ValueError, shore_indices, 6, 100) npt.assert_raises(ValueError, shore_order, m, n, l) # since we are testing without noise we can use higher order and lower # lambdas, with respect to the default. radial_order = 8 zeta = 700 lambdaN = 1e-12 lambdaL = 1e-12 asm = ShoreModel(gtab, radial_order=radial_order, zeta=zeta, lambdaN=lambdaN, lambdaL=lambdaL) asmfit = asm.fit(S) c_shore = asmfit.shore_coeff cmat = shore_matrix(radial_order, zeta, gtab) S_reconst = np.dot(cmat, c_shore) # test the signal reconstruction S = S / S[0] nmse_signal = np.sqrt(np.sum((S - S_reconst) ** 2)) / (S.sum()) npt.assert_almost_equal(nmse_signal, 0.0, 4) # test if the analytical integral of the pdf is equal to one integral = 0 for n in range(int((radial_order)/2 + 1)): integral += c_shore[n] * (np.pi**(-1.5) * zeta ** (-1.5) * genlaguerre(n, 0.5)(0)) ** 0.5 npt.assert_almost_equal(integral, 1.0, 10) # test if the integral of the pdf calculated on a discrete grid is # equal to one pdf_discrete = asmfit.pdf_grid(17, 40e-3) integral = pdf_discrete.sum() npt.assert_almost_equal(integral, 1.0, 1) # compare the shore pdf with the ground truth multi_tensor pdf sphere = get_sphere('symmetric724') v = sphere.vertices radius = 10e-3 pdf_shore = asmfit.pdf(v * radius) pdf_mt = multi_tensor_pdf(v * radius, mevals=mevals, angles=angl, fractions=[50, 50]) nmse_pdf = np.sqrt(np.sum((pdf_mt - pdf_shore) ** 2)) / (pdf_mt.sum()) npt.assert_almost_equal(nmse_pdf, 0.0, 2) # compare the shore rtop with the ground truth multi_tensor rtop rtop_shore_signal = asmfit.rtop_signal() rtop_shore_pdf = asmfit.rtop_pdf() npt.assert_almost_equal(rtop_shore_signal, rtop_shore_pdf, 9) rtop_mt = multi_tensor_rtop([.5, .5], mevals=mevals) npt.assert_equal(rtop_mt / rtop_shore_signal < 1.10 and rtop_mt / rtop_shore_signal > 0.95, True) # compare the shore msd with the ground truth multi_tensor msd msd_mt = multi_tensor_msd([.5, .5], mevals=mevals) msd_shore = asmfit.msd() npt.assert_equal(msd_mt / msd_shore < 1.05 and msd_mt / msd_shore > 0.95, True)
def main(): # Base Path of all the given files for DDE Part base_path = r'/nfs/masi/nathv/memento_2020/signal_forecast_data/files_project_2927_session_1436088/1-SignalForecast-ProvidedData/PGSE_shells' base_path = os.path.normpath(base_path) save_path = r'/nfs/masi/nathv/memento_2020/pgse_shells_submissions' save_path = os.path.normpath(save_path) # Read files via numpy load txt acq_params_file = np.loadtxt( os.path.join(base_path, 'PGSE_shells_provided_acq_params.txt')) pgse_provided_signals = np.loadtxt( os.path.join(base_path, 'PGSE_shells_provided_signals.txt')) pgse_unprovided_signals = np.loadtxt( os.path.join(base_path, 'PGSE_shells_unprovided_acq_params.txt')) # Transposing the provided signals for fitting to SHORE prov_signals = pgse_provided_signals.transpose() print('All Relevant Files Read ...') # Extract the acquisition parameters from provided and # unprovided to form the two different basis sets for SHORE prov_bvecs = acq_params_file[:, 1:4] prov_bvals = acq_params_file[:, 9] unprov_bvecs = pgse_unprovided_signals[:, 1:4] unprov_bvals = pgse_unprovided_signals[:, 9] print('Removing the B0 signals for signal modelling') # Detect B0 indices # Remove the B0's from the prior modelling non_b0_idxs = np.where(prov_bvals != 0)[0] prov_bvals = prov_bvals[non_b0_idxs] prov_bvecs = prov_bvecs[non_b0_idxs, :] pgse_provided_signals = pgse_provided_signals[non_b0_idxs, :] # Transposing the provided signals for fitting to SHORE prov_signals = pgse_provided_signals.transpose() prov_gtab = gradient_table(prov_bvals, prov_bvecs) unprov_gtab = gradient_table(unprov_bvals, unprov_bvecs) print('Gradient Tables formed ...') # Default SHORE parameters are zeta = 200 lambda_n = 1e-8 lambda_l = 1e-8 radial_order = 6 # SHORE Regularization Matrix Initialization def l_shore(radial_order): "Returns the angular regularisation matrix for SHORE basis" F = radial_order / 2 n_c = int(np.round(1 / 6.0 * (F + 1) * (F + 2) * (4 * F + 3))) diagL = np.zeros(n_c) counter = 0 for l in range(0, radial_order + 1, 2): for n in range(l, int((radial_order + l) / 2) + 1): for m in range(-l, l + 1): diagL[counter] = (l * (l + 1))**2 counter += 1 return np.diag(diagL) def n_shore(radial_order): "Returns the angular regularisation matrix for SHORE basis" F = radial_order / 2 n_c = int(np.round(1 / 6.0 * (F + 1) * (F + 2) * (4 * F + 3))) diagN = np.zeros(n_c) counter = 0 for l in range(0, radial_order + 1, 2): for n in range(l, int((radial_order + l) / 2) + 1): for m in range(-l, l + 1): diagN[counter] = (n * (n + 1))**2 counter += 1 return np.diag(diagN) print('Minimizing the zeta scale Parameter for Input Data ...') def eval_shore(D, n, scale): lambdaN = 1e-8 lambdaL = 1e-8 radial_order = n Lshore = l_shore(radial_order) Nshore = n_shore(radial_order) M = shore_matrix(n, scale, prov_gtab, 1. / (4 * np.pi**2)) MpseudoInv = np.dot( np.linalg.inv( np.dot(M.T, M) + lambdaN * Nshore + lambdaL * Lshore), M.T) shorecoefs = np.dot(D, MpseudoInv.T) # shorecoefs = np.dot(D, pinv(Mshore).T) shorepred = np.dot(shorecoefs, M.T) ''' plt.figure(1, figsize=(12,8)) plt.subplot(2,3,1) plt.plot(D[0, :]) plt.plot(shorepred[0, :]) plt.legend(['Original Signal','SHORE Fitted Signal']) plt.subplot(2,3,2) plt.plot(D[1, :]) plt.plot(shorepred[1, :]) plt.subplot(2,3,3) plt.plot(D[2, :]) plt.plot(shorepred[2, :]) plt.subplot(2,3,4) plt.plot(D[3, :]) plt.plot(shorepred[3, :]) plt.subplot(2,3,5) plt.plot(D[4, :]) plt.plot(shorepred[4, :]) plt.show() ''' return np.linalg.norm(D - shorepred)**2 def get_shore_coeffs(D, n, scale): lambdaN = 1e-8 lambdaL = 1e-8 radial_order = n Lshore = l_shore(radial_order) Nshore = n_shore(radial_order) M = shore_matrix(n, scale, prov_gtab, 1. / (4 * np.pi**2)) MpseudoInv = np.dot( np.linalg.inv( np.dot(M.T, M) + lambdaN * Nshore + lambdaL * Lshore), M.T) shorecoefs = np.dot(D, MpseudoInv.T) return shorecoefs zeta_optimized = minimize( lambda x: eval_shore(prov_signals, radial_order, x), zeta)['x'] print( 'The guess zeta value is: {} and the optimal zeta value is: {}'.format( zeta, zeta_optimized)) guess_prov_mse = eval_shore(prov_signals, radial_order, zeta) optim_prov_mse = eval_shore(prov_signals, radial_order, zeta_optimized) guess_shore_coeffs = get_shore_coeffs(prov_signals, radial_order, zeta) optim_shore_coeffs = get_shore_coeffs(prov_signals, radial_order, zeta_optimized) print( 'MSE for guessed zeta is: {} and MSE for optimized zeta is: {}'.format( guess_prov_mse, optim_prov_mse)) print('Obtaining signal measurements for unprovided data') #M_unprov_zeta = shore_matrix(radial_order, zeta, unprov_gtab, 1. / (4 * np.pi ** 2)) M_unprov_zeta_optim = shore_matrix(radial_order, zeta_optimized, unprov_gtab, 1. / (4 * np.pi**2)) #guess_shore_preds = np.dot(guess_shore_coeffs, M_unprov_zeta.T) optim_shore_preds = np.dot(optim_shore_coeffs, M_unprov_zeta_optim.T) #guess_shore_preds = guess_shore_preds.T optim_shore_preds = optim_shore_preds.T #np.savetxt(os.path.join(save_path, 'sub_1.txt'), guess_shore_preds) np.savetxt(os.path.join(save_path, 'sub_3.txt'), optim_shore_preds) ''' prov_ShoreModel = ShoreModel(gtab=prov_gtab, radial_order=radial_order, zeta=zeta, lambdaN=lambda_n, lambdaL=lambda_l) print('Shore Basis Constructed, Fitting Data ...') prov_ShoreFit = prov_ShoreModel.fit(pgse_provided_signals.transpose()) ''' print('Debug here') return None