예제 #1
0
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))
예제 #3
0
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))
예제 #6
0
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')
예제 #8
0
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)
예제 #9
0
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',
예제 #10
0
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