def test_multi_tissue_mc_sm_model(): scheme = wu_minn_hcp_acquisition_scheme() ball = gaussian_models.G1Ball() cyl = cylinder_models.C1Stick() models = [ball, cyl] S0_responses = [1., 2.] # generate data mt_mc = modeling_framework.MultiCompartmentModel( models=models, S0_tissue_responses=S0_responses) mt_mc.set_fixed_parameter('C1Stick_1_lambda_par', 1.7e-9) mt_mc.set_fixed_parameter('G1Ball_1_lambda_iso', 3e-9) mt_mc.set_fixed_parameter('C1Stick_1_mu', [0., 0.]) param_dict = {'partial_volume_0': .5, 'partial_volume_1': .5} E = mt_mc.simulate_signal(scheme, param_dict) # do mc-sm multi tissue model. mt_mc_sm = modeling_framework.MultiCompartmentSphericalMeanModel( models=models, S0_tissue_responses=S0_responses) mt_mc_sm.set_fixed_parameter('C1Stick_1_lambda_par', 1.7e-9) mt_mc_sm.set_fixed_parameter('G1Ball_1_lambda_iso', 3e-9) mt_mc_fit = mt_mc_sm.fit(scheme, E) sig_fracts = mt_mc_fit.fitted_parameters vol_fracts = mt_mc_fit.fitted_multi_tissue_fractions vol_fracts_norm = mt_mc_fit.fitted_multi_tissue_fractions_normalized assert_almost_equal( sig_fracts['partial_volume_0'], vol_fracts['partial_volume_0'], 2) assert_almost_equal( sig_fracts['partial_volume_1'], vol_fracts['partial_volume_1'] * 2., 2) assert_almost_equal( vol_fracts_norm['partial_volume_0'], 2 / 3., 2) assert_almost_equal( vol_fracts_norm['partial_volume_1'], 1 / 3., 2)
def test_all_fitted_model_properties(): stick = cylinder_models.C1Stick() watsonstick = distribute_models.SD1WatsonDistributed([stick]) params = {} for parameter, card, in watsonstick.parameter_cardinality.items(): params[parameter] = (np.random.rand(card) * watsonstick.parameter_scales[parameter]) data = np.atleast_2d(watsonstick(scheme, **params)) mcmod = modeling_framework.MultiCompartmentModel([watsonstick]) mcfit = mcmod.fit(scheme, data) vertices = np.random.rand(10, 3) vertices /= np.linalg.norm(vertices, axis=1)[:, None] assert_(isinstance(mcfit.fitted_parameters, dict)) assert_(isinstance(mcfit.fitted_parameters_vector, np.ndarray)) assert_(isinstance(mcfit.fod(vertices), np.ndarray)) assert_(isinstance(mcfit.fod_sh(), np.ndarray)) assert_(isinstance(mcfit.peaks_spherical(), np.ndarray)) assert_(isinstance(mcfit.peaks_cartesian(), np.ndarray)) assert_(isinstance(mcfit.mean_squared_error(data), np.ndarray)) assert_(isinstance(mcfit.R2_coefficient_of_determination(data), np.ndarray)) assert_(isinstance(mcfit.predict(), np.ndarray)) mcmod_sm = modeling_framework.MultiCompartmentSphericalMeanModel([stick]) mcfit_sm = mcmod_sm.fit(scheme, data) assert_(isinstance(mcfit_sm.fitted_parameters, dict)) assert_(isinstance(mcfit_sm.fitted_parameters_vector, np.ndarray)) assert_(isinstance(mcfit.mean_squared_error(data), np.ndarray)) assert_(isinstance(mcfit.R2_coefficient_of_determination(data), np.ndarray)) assert_(isinstance(mcfit.predict(), np.ndarray))
def test_stick_and_tortuous_zeppelin_to_spherical_mean_fit(): """ this is a more complex test to see if we can generate 3D data using a stick and zeppelin model, where we assume the perpendicular diffusivity is linked to the parallel diffusivity and volume fraction using tortuosity. We then use the spherical mean models of stick and zeppelin with the same tortuosity assumption to fit the 3D data (and estimating the spherical mean of each shell). The final check is whether the parallel diffusivity and volume fraction between the 3D and spherical mean models correspond.""" gt_mu = np.clip(np.random.rand(2), .3, np.inf) gt_lambda_par = (np.random.rand() + 1.) * 1e-9 gt_partial_volume = 0.3 stick = cylinder_models.C1Stick() zeppelin = gaussian_models.G2Zeppelin() stick_and_zeppelin = (modeling_framework.MultiCompartmentModel( models=[stick, zeppelin])) stick_and_zeppelin.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'C1Stick_1_lambda_par', 'partial_volume_0', 'partial_volume_1') stick_and_zeppelin.set_equal_parameter('C1Stick_1_mu', 'G2Zeppelin_1_mu') stick_and_zeppelin.set_equal_parameter('C1Stick_1_lambda_par', 'G2Zeppelin_1_lambda_par') gt_parameter_vector = (stick_and_zeppelin.parameters_to_parameter_vector( C1Stick_1_lambda_par=gt_lambda_par, C1Stick_1_mu=gt_mu, partial_volume_0=gt_partial_volume, partial_volume_1=1 - gt_partial_volume)) E = stick_and_zeppelin.simulate_signal(scheme, gt_parameter_vector) # now we make the stick and zeppelin spherical mean model and check if the # same lambda_par and volume fraction result as the 3D generated data. stick_and_tortuous_zeppelin_sm = ( modeling_framework.MultiCompartmentSphericalMeanModel( models=[stick, zeppelin])) stick_and_tortuous_zeppelin_sm.set_tortuous_parameter( 'G2Zeppelin_1_lambda_perp', 'C1Stick_1_lambda_par', 'partial_volume_0', 'partial_volume_1') stick_and_tortuous_zeppelin_sm.set_equal_parameter( 'G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par') res_sm = stick_and_tortuous_zeppelin_sm.fit(scheme, E).fitted_parameters_vector assert_array_almost_equal(np.r_[gt_lambda_par, gt_partial_volume], res_sm.squeeze()[:-1], 2)
def test_raise_mix_with_tortuosity_in_mcsmtmodel(): scheme = wu_minn_hcp_acquisition_scheme() stick = cylinder_models.C1Stick() zeppelin = gaussian_models.G2Zeppelin() mcsmt = modeling_framework.MultiCompartmentSphericalMeanModel( [stick, zeppelin]) mcsmt.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'C1Stick_1_lambda_par', 'partial_volume_0', 'partial_volume_1') data = stick(scheme, lambda_par=1.7e-9, mu=[0., 0.]) assert_raises(ValueError, mcsmt.fit, scheme, data, solver='mix')
def test_parametric_fod_spherical_mean_model(): stick = cylinder_models.C1Stick() watsonstick = distribute_models.SD1WatsonDistributed([stick]) params = {} for parameter, card, in watsonstick.parameter_cardinality.items(): params[parameter] = (np.random.rand(card) * watsonstick.parameter_scales[parameter]) data = np.atleast_2d(watsonstick(scheme, **params)) stick = cylinder_models.C1Stick() zeppelin = gaussian_models.G2Zeppelin() smt = modeling_framework.MultiCompartmentSphericalMeanModel( [stick, zeppelin]) smt.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'C1Stick_1_lambda_par', 'partial_volume_0', 'partial_volume_1') smt.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par') smt_fit = smt.fit(scheme, data) assert_raises(ValueError, smt_fit.return_parametric_fod_model, Ncompartments=1.5) assert_raises(ValueError, smt_fit.return_parametric_fod_model, Ncompartments=0) assert_raises(ValueError, smt_fit.return_parametric_fod_model, distribution='bla') for distribution_name in ['watson', 'bingham']: fod_model = smt_fit.return_parametric_fod_model( distribution=distribution_name, Ncompartments=1) fitted_fod_model = fod_model.fit(scheme, data) assert_(isinstance(fitted_fod_model.fitted_parameters, dict))
def test_spherical_mean_stick_tortuous_zeppelin(): stick = cylinder_models.C1Stick() zeppelin = gaussian_models.G2Zeppelin() mc_mdi = modeling_framework.MultiCompartmentSphericalMeanModel( models=[stick, zeppelin]) mc_mdi.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'C1Stick_1_lambda_par', 'partial_volume_0', 'partial_volume_1') mc_mdi.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par') fitted_params_par = ( mc_mdi.fit( scheme, camino_parallel.signal_attenuation[::20] ).fitted_parameters ) fitted_params_disp = ( mc_mdi.fit( scheme, camino_dispersed.signal_attenuation[::40] ).fitted_parameters ) mean_abs_error_par = np.mean( abs(fitted_params_par['partial_volume_0'].squeeze( ) - camino_parallel.fractions[::20])) mean_abs_error_disp = np.mean( abs(fitted_params_disp['partial_volume_0'].squeeze( ) - camino_dispersed.fractions[::40])) assert_equal(mean_abs_error_par < 0.02, True) assert_equal(mean_abs_error_disp < 0.02, True)
all_bvecs = np.hstack((b1k_bvecs, b2k_bvecs)) all_bvals = np.hstack((b1k_bvals, b2k_bvals)) all_data = np.concatenate((b1k_fdata, b2k_fdata), axis=3) # Prepare Dmipy Acquisition Scheme # This is Dmipy nonsense, that if B-values are in s/mm^2 they need # to be multiplied with 1e6 to be of the scale s/m^2 all_bvals = all_bvals * 1e6 all_bvecs = np.transpose(all_bvecs) # The below line also takes in small delta and big delta. # TODO Big Delta and small delta are not available quite often for the data. acq_scheme = acquisition_scheme_from_bvalues(all_bvals, all_bvecs) # We are ready to fit models # Prepare SMT Model zeppelin = gaussian_models.G2Zeppelin() smt_mod = modeling_framework.MultiCompartmentSphericalMeanModel( models=[zeppelin]) #smt_mod.set_fractional_parameter() # Fit SMT smt_fit_hcp = smt_mod.fit(acq_scheme, all_data, Ns=30, mask=all_data[..., 0] > 0, use_parallel_processing=False) # TODO Use a model name with the dictionary for saving the file name for a specific subject per model. print('Debug here')
def test_multi_voxel_parametric_to_sm_to_sh_fod_watson(): stick = cylinder_models.C1Stick() zeppelin = gaussian_models.G2Zeppelin() watsonstick = distribute_models.SD1WatsonDistributed([stick, zeppelin]) watsonstick.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par') watsonstick.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'G2Zeppelin_1_lambda_par', 'partial_volume_0') mc_mod = modeling_framework.MultiCompartmentModel([watsonstick]) parameter_dict = { 'SD1WatsonDistributed_1_SD1Watson_1_mu': np.random.rand(10, 2), 'SD1WatsonDistributed_1_partial_volume_0': np.linspace(0.1, 0.9, 10), 'SD1WatsonDistributed_1_G2Zeppelin_1_lambda_par': np.linspace(1.5, 2.5, 10) * 1e-9, 'SD1WatsonDistributed_1_SD1Watson_1_odi': np.linspace(0.3, 0.7, 10) } data = mc_mod.simulate_signal(scheme, parameter_dict) sm_mod = modeling_framework.MultiCompartmentSphericalMeanModel( [stick, zeppelin]) sm_mod.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par') sm_mod.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'G2Zeppelin_1_lambda_par', 'partial_volume_0', 'partial_volume_1') sf_watson = [] for mu, odi in zip( parameter_dict['SD1WatsonDistributed_1_SD1Watson_1_mu'], parameter_dict['SD1WatsonDistributed_1_SD1Watson_1_odi']): watson = distributions.SD1Watson(mu=mu, odi=odi) sf_watson.append(watson(sphere.vertices)) sf_watson = np.array(sf_watson) sm_fit = sm_mod.fit(scheme, data) sh_mod = sm_fit.return_spherical_harmonics_fod_model() sh_fit_auto = sh_mod.fit(scheme, data) # will pick tournier fod_tournier = sh_fit_auto.fod(sphere.vertices) assert_array_almost_equal(fod_tournier, sf_watson, 1) sh_fit_tournier = sh_mod.fit(scheme, data, solver='csd_tournier07', unity_constraint=False) fod_tournier = sh_fit_tournier.fod(sphere.vertices) assert_array_almost_equal(fod_tournier, sf_watson, 1) sh_fit_cvxpy = sh_mod.fit(scheme, data, solver='csd_cvxpy', unity_constraint=True, lambda_lb=0.) fod_cvxpy = sh_fit_cvxpy.fod(sphere.vertices) assert_array_almost_equal(fod_cvxpy, sf_watson, 2) sh_fit_cvxpy = sh_mod.fit(scheme, data, solver='csd_cvxpy', unity_constraint=False, lambda_lb=0.) fod_cvxpy = sh_fit_cvxpy.fod(sphere.vertices) assert_array_almost_equal(fod_cvxpy, sf_watson, 2)
from dmipy.core import modeling_framework from dmipy.data import saved_data import matplotlib.pyplot as plt import matplotlib.patches as patches stick = cylinder_models.C1Stick() zeppelin = gaussian_models.G2Zeppelin() ball = gaussian_models.G1Ball() bundle = BundleModel([stick, zeppelin]) bundle.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'C1Stick_1_lambda_par', 'partial_volume_0') bundle.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par') bundle.set_fixed_parameter('G2Zeppelin_1_lambda_par', 1.7e-9) smt_noddi_mod = modeling_framework.MultiCompartmentSphericalMeanModel( models=[bundle, ball]) smt_noddi_mod.parameter_names # then we fix the isotropic diffusivity smt_noddi_mod.set_fixed_parameter('G1Ball_1_lambda_iso', 3e-9) scheme_hcp, data_hcp = saved_data.wu_minn_hcp_coronal_slice() sub_image = data_hcp[70:90, :, 70:90] fig, ax = plt.subplots(1) ax.imshow(data_hcp[:, 0, :, 0].T, origin=True) rect = patches.Rectangle((70, 70), 20, 20, linewidth=1, edgecolor='r',
def main(): # Plot Save Path base_plot_path = r'/nfs/masi/nathv/py_src_code_2020/dmipy_model_pictures' base_plot_path = os.path.normpath(base_plot_path) # Method Saving Paths base_save_path = r'/nfs/masi/nathv/miccai_2020/micro_methods_hcp_mini' base_save_path = os.path.normpath(base_save_path) # Create base saving path for Method # TODO The Method name can be made an argument later on method_name = 'MC_SMT' # Base HCP Data Path base_data_path = r'/nfs/HCP/data' base_data_path = os.path.normpath(base_data_path) # Subject ID's list subj_ID_List = ['115017', '114823', '116726', '118225'] # TODO When needed loop here over the ID list for subj_ID in subj_ID_List: # Subject Save Path subj_save_path = os.path.join(base_save_path, subj_ID) if os.path.exists(subj_save_path) == False: os.mkdir(subj_save_path) # TODO For later the subject data, bval and bvec reading part can be put inside a function subj_data_path = os.path.join(base_data_path, subj_ID, 'T1w', 'Diffusion') # Read the Nifti file, bvals and bvecs subj_bvals = np.loadtxt(os.path.join(subj_data_path, 'bvals')) subj_bvecs = np.loadtxt(os.path.join(subj_data_path, 'bvecs')) all_bvals = subj_bvals * 1e6 all_bvecs = np.transpose(subj_bvecs) subj_Acq_Scheme = acquisition_scheme_from_bvalues(all_bvals, all_bvecs) print(subj_Acq_Scheme.print_acquisition_info) print('Loading the Nifti Data ...') data_start_time = time.time() subj_babel_object = nib.load( os.path.join(subj_data_path, 'data.nii.gz')) subj_data = subj_babel_object.get_fdata() axial_slice_data = subj_data[:, :, 30:32, :] data_end_time = time.time() data_time = np.int(np.round(data_end_time - data_start_time)) print('Data Loaded ... Time Taken: {}'.format(data_end_time - data_start_time)) print('The Data Dimensions are: {}'.format(subj_data.shape)) #### MC-SMT Begin #### stick = cylinder_models.C1Stick() zeppelin = gaussian_models.G2Zeppelin() bundle = BundleModel([stick, zeppelin]) # Model Paramter Constraints bundle.set_tortuous_parameter('G2Zeppelin_1_lambda_perp', 'C1Stick_1_lambda_par', 'partial_volume_0') bundle.set_equal_parameter('G2Zeppelin_1_lambda_par', 'C1Stick_1_lambda_par') mcdmi_mod = modeling_framework.MultiCompartmentSphericalMeanModel( models=[bundle]) # Get List of Estimated Parameter Names para_Names_list = mcdmi_mod.parameter_names print('Fitting the MC-SMT Model ...') fit_start_time = time.time() mcdmi_fit = mcdmi_mod.fit(subj_Acq_Scheme, subj_data, mask=subj_data[..., 0] > 0) fit_end_time = time.time() print('Model Fitting Completed ... Time Taken to fit: {}'.format( fit_end_time - fit_start_time)) fit_time = np.int(np.round(fit_end_time - fit_start_time)) fitted_parameters = mcdmi_fit.fitted_parameters ### Nifti Saving Part # Create a directory per subject subj_method_save_path = os.path.join(subj_save_path, method_name) if os.path.exists(subj_method_save_path) == False: os.mkdir(subj_method_save_path) # Retrieve the affine from already Read Nifti file to form the header affine = subj_babel_object.affine # Loop over fitted parameters name list for each_fitted_parameter in para_Names_list: new_img = nib.Nifti1Image(fitted_parameters[each_fitted_parameter], affine) # Form the file path f_name = each_fitted_parameter + '.nii.gz' param_file_path = os.path.join(subj_method_save_path, f_name) nib.save(new_img, param_file_path) return None