Esempio n. 1
0
def test_Wrotate_single_fiber():

    # Rotate the kurtosis tensor of single fiber simulate to the diffusion
    # tensor diagonal and check that is equal to the kurtosis tensor of the
    # same single fiber simulated directly to the x-axis

    # Define single fiber simulate
    mevals = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
    fie = 0.49
    frac = [fie*100, (1 - fie)*100]

    # simulate single fiber not aligned to the x-axis
    theta = random.uniform(0, 180)
    phi = random.uniform(0, 320)
    angles = [(theta, phi), (theta, phi)]
    signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                      fractions=frac, snr=None)

    evals, evecs = decompose_tensor(from_lower_triangular(dt))

    kt_rotated = dki.Wrotate(kt, evecs)
    # Now coordinate system has the DT diagonal aligned to the x-axis

    # Reference simulation in which DT diagonal is directly aligned to the
    # x-axis
    angles = (90, 0), (90, 0)
    signal, dt_ref, kt_ref = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                              fractions=frac, snr=None)

    assert_array_almost_equal(kt_rotated, kt_ref)
Esempio n. 2
0
def test_Wrotate_crossing_fibers():
    # Test 2 - simulate crossing fibers intersecting at 70 degrees.
    # In this case, diffusion tensor principal eigenvector will be aligned in
    # the middle of the crossing fibers. Thus, after rotating the kurtosis
    # tensor, this will be equal to a kurtosis tensor simulate of crossing
    # fibers both deviating 35 degrees from the x-axis. Moreover, we know that
    # crossing fibers will be aligned to the x-y plane, because the smaller
    # diffusion eigenvalue, perpendicular to both crossings fibers, will be
    # aligned to the z-axis.

    # Simulate the crossing fiber
    angles = [(90, 30), (90, 30), (20, 30), (20, 30)]
    fie = 0.49
    frac = [fie*50, (1-fie) * 50, fie*50, (1-fie) * 50]
    mevals = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                       [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])

    signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                      fractions=frac, snr=None)

    evals, evecs = decompose_tensor(from_lower_triangular(dt))

    kt_rotated = dki.Wrotate(kt, evecs)
    # Now coordinate system has diffusion tensor diagonal aligned to the x-axis

    # Simulate the reference kurtosis tensor
    angles = [(90, 35), (90, 35), (90, -35), (90, -35)]

    signal, dt, kt_ref = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                          fractions=frac, snr=None)

    # Compare rotated with the reference
    assert_array_almost_equal(kt_rotated, kt_ref)
Esempio n. 3
0
def test_Wrotate_crossing_fibers():
    # Test 2 - simulate crossing fibers intersecting at 70 degrees.
    # In this case, diffusion tensor principal eigenvector will be aligned in
    # the middle of the crossing fibers. Thus, after rotating the kurtosis
    # tensor, this will be equal to a kurtosis tensor simulate of crossing
    # fibers both deviating 35 degrees from the x-axis. Moreover, we know that
    # crossing fibers will be aligned to the x-y plane, because the smaller
    # diffusion eigenvalue, perpendicular to both crossings fibers, will be
    # aligned to the z-axis.

    # Simulate the crossing fiber
    angles = [(90, 30), (90, 30), (20, 30), (20, 30)]
    fie = 0.49
    frac = [fie*50, (1-fie) * 50, fie*50, (1-fie) * 50]
    mevals = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                       [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])

    signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                      fractions=frac, snr=None)

    evals, evecs = decompose_tensor(from_lower_triangular(dt))

    kt_rotated = dki.Wrotate(kt, evecs)
    # Now coordinate system has diffusion tensor diagonal aligned to the x-axis

    # Simulate the reference kurtosis tensor
    angles = [(90, 35), (90, 35), (90, -35), (90, -35)]

    signal, dt, kt_ref = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                          fractions=frac, snr=None)

    # Compare rotated with the reference
    assert_array_almost_equal(kt_rotated, kt_ref)
Esempio n. 4
0
def test_Wrotate_single_fiber():

    # Rotate the kurtosis tensor of single fiber simulate to the diffusion
    # tensor diagonal and check that is equal to the kurtosis tensor of the
    # same single fiber simulated directly to the x-axis

    # Define single fiber simulate
    mevals = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
    fie = 0.49
    frac = [fie*100, (1 - fie)*100]

    # simulate single fiber not aligned to the x-axis
    theta = random.uniform(0, 180)
    phi = random.uniform(0, 320)
    angles = [(theta, phi), (theta, phi)]
    signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                      fractions=frac, snr=None)

    evals, evecs = decompose_tensor(from_lower_triangular(dt))

    kt_rotated = dki.Wrotate(kt, evecs)
    # Now coordinate system has the DT diagonal aligned to the x-axis

    # Reference simulation in which DT diagonal is directly aligned to the
    # x-axis
    angles = (90, 0), (90, 0)
    signal, dt_ref, kt_ref = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                              fractions=frac, snr=None)

    assert_array_almost_equal(kt_rotated, kt_ref)
Esempio n. 5
0
def test_kurtosis_fa():
    # KFA = sqrt(4/5) if kurtosis is non-zero only in one direction
    mevals = np.array([[0.002, 0, 0], [0.003, 0, 0]])
    angles = [(45, 0), (45, 0)]
    fie = 0.5
    frac = [fie * 100, (1 - fie) * 100]
    signal, dt, kt = multi_tensor_dki(gtab_2s,
                                      mevals,
                                      S0=100,
                                      angles=angles,
                                      fractions=frac,
                                      snr=None)

    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    dkiF = dkiM.fit(signal)
    dkiF.kfa
    assert_almost_equal(dkiF.kfa, np.sqrt(4 / 5))

    # KFA = sqrt(13/5) for systems of two tensors with same AD and RD values
    # See appendix of Gleen et al., 2015 Quantitative assessment of diffusional
    # kurtosis anisotropy. NMR Biomed 28; 448-459. doi:10.1002/nbm.3271
    mevals = np.array([[0.003, 0.001, 0.001], [0.003, 0.001, 0.001]])
    angles = [(40, -10), (-45, 10)]
    fie = 0.5
    frac = [fie * 100, (1 - fie) * 100]
    signal, dt, kt = multi_tensor_dki(gtab_2s,
                                      mevals,
                                      S0=100,
                                      angles=angles,
                                      fractions=frac,
                                      snr=None)

    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    dkiF = dkiM.fit(signal)
    dkiF.kfa
    assert_almost_equal(dkiF.kfa, np.sqrt(13 / 15))

    # KFA = 0 if MKT = 0
    mevals = np.array([[0.003, 0.001, 0.001], [0.003, 0.001, 0.001]])
    angles = [(40, -10), (40, -10)]
    fie = 0.5
    frac = [fie * 100, (1 - fie) * 100]
    signal, dt, kt = multi_tensor_dki(gtab_2s,
                                      mevals,
                                      S0=100,
                                      angles=angles,
                                      fractions=frac,
                                      snr=None)

    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    dkiF = dkiM.fit(signal)
    dkiF.kfa
    assert_almost_equal(dkiF.kfa, 0)
Esempio n. 6
0
def test_DKI_simulations_aligned_fibers():
    """
    Testing DKI simulations when aligning the same fiber to different axis.

    If biological parameters don't change, kt[0] of a fiber aligned to axis x
    has to be equal to kt[1] of a fiber aligned to the axis y and equal to
    kt[2] of a fiber aligned to axis z. The same is applicable for dt
    """
    # Defining parameters based on Neto Henriques et al., 2015. NeuroImage 111
    mevals = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])  # Intra-cellular  # Extra-cellular
    frac = [49, 51]  # Compartment volume fraction
    # axis x
    angles = [(90, 0), (90, 0)]
    signal_fx, dt_fx, kt_fx = multi_tensor_dki(gtab_2s, mevals, angles=angles, fractions=frac)
    # axis y
    angles = [(90, 90), (90, 90)]
    signal_fy, dt_fy, kt_fy = multi_tensor_dki(gtab_2s, mevals, angles=angles, fractions=frac)
    # axis z
    angles = [(0, 0), (0, 0)]
    signal_fz, dt_fz, kt_fz = multi_tensor_dki(gtab_2s, mevals, angles=angles, fractions=frac)

    assert_array_equal([kt_fx[0], kt_fx[1], kt_fx[2]], [kt_fy[1], kt_fy[0], kt_fy[2]])
    assert_array_equal([kt_fx[0], kt_fx[1], kt_fx[2]], [kt_fz[2], kt_fz[0], kt_fz[1]])

    assert_array_equal([dt_fx[0], dt_fx[2], dt_fx[5]], [dt_fy[2], dt_fy[0], dt_fy[5]])
    assert_array_equal([dt_fx[0], dt_fx[2], dt_fx[5]], [dt_fz[5], dt_fz[0], dt_fz[2]])

    # testing S signal along axis x, y and z
    bvals = np.array([0, 0, 0, 1000, 1000, 1000, 2000, 2000, 2000])
    bvecs = np.asarray(
        [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 0, 1]]
    )
    gtab_axis = gradient_table(bvals, bvecs)
    # axis x
    S_fx = DKI_signal(gtab_axis, dt_fx, kt_fx, S0=100)
    assert_array_almost_equal(S_fx[0:3], [100, 100, 100])  # test S f0r b=0
    # axis y
    S_fy = DKI_signal(gtab_axis, dt_fy, kt_fy, S0=100)
    assert_array_almost_equal(S_fy[0:3], [100, 100, 100])  # test S f0r b=0
    # axis z
    S_fz = DKI_signal(gtab_axis, dt_fz, kt_fz, S0=100)
    assert_array_almost_equal(S_fz[0:3], [100, 100, 100])  # test S f0r b=0

    # test S for b = 1000
    assert_array_almost_equal([S_fx[3], S_fx[4], S_fx[5]], [S_fy[4], S_fy[3], S_fy[5]])
    assert_array_almost_equal([S_fx[3], S_fx[4], S_fx[5]], [S_fz[5], S_fz[3], S_fz[4]])
    # test S for b = 2000
    assert_array_almost_equal([S_fx[6], S_fx[7], S_fx[8]], [S_fy[7], S_fy[6], S_fy[8]])
    assert_array_almost_equal([S_fx[6], S_fx[7], S_fx[8]], [S_fz[8], S_fz[6], S_fz[7]])
Esempio n. 7
0
def test_DKI_crossing_fibers_simulations():
    """ Testing DKI simulations of a crossing fiber
    """
    # two fiber not aligned to planes x = 0, y = 0, or z = 0
    mevals = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                       [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
    angles = [(80, 10), (80, 10), (20, 30), (20, 30)]
    fie = 0.49
    frac = [fie*50, (1 - fie)*50, fie*50, (1 - fie)*50]
    signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                      fractions=frac, snr=None)
    # in this simulations dt and kt cannot have zero elements
    for i in range(len(dt)):
        assert dt[i] != 0
    for i in range(len(kt)):
        assert kt[i] != 0

    # test S, dt and kt relative to the expected values computed from another
    # DKI package - UDKI (Neto Henriques et al., 2015)
    dt_ref = [1.0576161e-3, 0.1292542e-3, 0.4786179e-3,
              0.2667081e-3, 0.1136643e-3, 0.9888660e-3]
    kt_ref = [2.3529944, 0.8226448, 2.3011221, 0.2017312, -0.0437535,
              0.0404011, 0.0355281, 0.2449859, 0.2157668, 0.3495910,
              0.0413366, 0.3461519, -0.0537046, 0.0133414, -0.017441]
    assert_array_almost_equal(dt, dt_ref)
    assert_array_almost_equal(kt, kt_ref)
    assert_array_almost_equal(signal,
                              dki_signal(gtab_2s, dt_ref, kt_ref, S0=1.,
                                         snr=None),
                              decimal=5)
Esempio n. 8
0
def test_DKI_crossing_fibers_simulations():
    """ Testing DKI simulations of a crossing fiber
    """
    # two fiber not aligned to planes x = 0, y = 0, or z = 0
    mevals = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                       [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
    angles = [(80, 10), (80, 10), (20, 30), (20, 30)]
    fie = 0.49
    frac = [fie*50, (1 - fie)*50, fie*50, (1 - fie)*50]
    signal, dt, kt = multi_tensor_dki(gtab_2s, mevals, angles=angles,
                                      fractions=frac, snr=None)
    # in this simulations dt and kt cannot have zero elements
    for i in range(len(dt)):
        assert dt[i] != 0
    for i in range(len(kt)):
        assert kt[i] != 0

    # test S, dt and kt relative to the expected values computed from another
    # DKI package - UDKI (Neto Henriques et al., 2015)
    dt_ref = [1.0576161e-3, 0.1292542e-3, 0.4786179e-3,
              0.2667081e-3, 0.1136643e-3, 0.9888660e-3]
    kt_ref = [2.3529944, 0.8226448, 2.3011221, 0.2017312, -0.0437535,
              0.0404011, 0.0355281, 0.2449859, 0.2157668, 0.3495910,
              0.0413366, 0.3461519, -0.0537046, 0.0133414, -0.017441]
    assert_array_almost_equal(dt, dt_ref)
    assert_array_almost_equal(kt, kt_ref)
    assert_array_almost_equal(signal,
                              DKI_signal(gtab_2s, dt_ref, kt_ref, S0=100,
                                         snr=None),
                              decimal=5)
Esempio n. 9
0
def test_dki_micro_predict_single_voxel():
    # single fiber simulate (which is the assumption of our model)
    fie = 0.49
    ADi = 0.00099
    ADe = 0.00226
    RDi = 0
    RDe = 0.00087

    # prepare simulation:
    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, angles=angles,
                                      fractions=frac, snr=None)
    signal_gt, da = multi_tensor(gtab_2s, mevals, angles=angles,
                                 fractions=frac, snr=None)

    # Defined DKI microstrutural model
    dkiM = dki_micro.KurtosisMicrostructureModel(gtab_2s)

    # Fit single voxel signal
    dkiF = dkiM.fit(signal)

    # Check predict of KurtosisMicrostruturalModel
    pred = dkiM.predict(dkiF.model_params)
    assert_array_almost_equal(pred, signal_gt, decimal=4)

    pred = dkiM.predict(dkiF.model_params, S0=100)
    assert_array_almost_equal(pred, signal_gt * 100, decimal=4)

    # Check predict of KurtosisMicrostruturalFit
    pred = dkiF.predict(gtab_2s, S0=100)
    assert_array_almost_equal(pred, signal_gt * 100, decimal=4)
Esempio n. 10
0
def test_cholesky_functions():
    S, dt, kt = multi_tensor_dki(gtab, mevals, S0=100,
                                 angles=[(45., 45.), (45., 45.)],
                                 fractions=[80, 20])
    R = lower_triangular_to_cholesky(dt)
    tensor = cholesky_to_lower_triangular(R)
    assert_array_almost_equal(dt, tensor)
Esempio n. 11
0
def test_cholesky_functions():
    S, dt, kt = multi_tensor_dki(gtab, mevals, S0=100,
                                 angles=[(45., 45.), (45., 45.)],
                                 fractions=[80, 20])
    R = lower_triangular_to_cholesky(dt)
    tensor = cholesky_to_lower_triangular(R)
    assert_array_almost_equal(dt, tensor)
Esempio n. 12
0
def test_smt2_specific_cases():
    mdkiM = msdki.MeanDiffusionKurtosisModel(gtab_3s)

    # Check smt2 is sepecific cases with knowm g.t:
    # 1) Intrisic diffusion is equal MSD for single Gaussian isotropic
    #     diffusion (i.e. awf=0)
    sig_gaussian = single_tensor(gtab_3s, evals=np.array([2e-3, 2e-3, 2e-3]))
    mdkiF = mdkiM.fit(sig_gaussian)
    assert_almost_equal(mdkiF.msk, 0.0)
    assert_almost_equal(mdkiF.msd, 2.0e-3)
    assert_almost_equal(mdkiF.smt2f, 0)
    assert_almost_equal(mdkiF.smt2di, 2.0e-3)

    # 2) Intrisic diffusion is equal to MSD/3 for single powder-averaged stick
    #    compartment
    Da = 2.0e-3
    mevals = np.zeros((64, 3))
    mevals[:, 0] = Da
    fracs = np.ones(64) * 100 / 64
    signal_pa, dt_sph, kt_sph = multi_tensor_dki(gtab_3s,
                                                 mevals,
                                                 angles=bvecs[1:, :],
                                                 fractions=fracs,
                                                 snr=None)
    mdkiF = mdkiM.fit(signal_pa)
    # decimal is set to 1 because of finite number of directions for powder
    # average calculation
    assert_almost_equal(mdkiF.msk, 2.4, decimal=1)
    assert_almost_equal(mdkiF.msd * 1000, Da / 3 * 1000, decimal=1)
    assert_almost_equal(mdkiF.smt2f, 1, decimal=1)
    assert_almost_equal(mdkiF.smt2di, mdkiF.msd * 3, decimal=1)
Esempio n. 13
0
def test_dki_micro_predict_single_voxel():
    # single fiber simulate (which is the assumption of our model)
    fie = 0.49
    ADi = 0.00099
    ADe = 0.00226
    RDi = 0
    RDe = 0.00087

    # prepare simulation:
    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, angles=angles,
                                      fractions=frac, snr=None)
    signal_gt, da = multi_tensor(gtab_2s, mevals, angles=angles,
                                 fractions=frac, snr=None)

    # Defined DKI microstrutural model
    dkiM = dki_micro.KurtosisMicrostructureModel(gtab_2s)

    # Fit single voxel signal
    dkiF = dkiM.fit(signal)

    # Check predict of KurtosisMicrostruturalModel
    pred = dkiM.predict(dkiF.model_params)
    assert_array_almost_equal(pred, signal_gt, decimal=4)

    pred = dkiM.predict(dkiF.model_params, S0=100)
    assert_array_almost_equal(pred, signal_gt * 100, decimal=4)

    # Check predict of KurtosisMicrostruturalFit
    pred = dkiF.predict(gtab_2s, S0=100)
    assert_array_almost_equal(pred, signal_gt * 100, decimal=4)
Esempio n. 14
0
def test_multi_voxel_kurtosis_maximum():
    # Multi-voxel simulations parameters
    FIE = np.array([[[0.30, 0.32], [0.74, 0.51]], [[0.47, 0.21], [0.80,
                                                                  0.63]]])
    RDI = np.zeros((2, 2, 2))
    ADI = np.array([[[1e-3, 1.3e-3], [0.8e-3, 1e-3]],
                    [[0.9e-3, 0.99e-3], [0.89e-3, 1.1e-3]]])
    ADE = np.array([[[2.2e-3, 2.3e-3], [2.8e-3, 2.1e-3]],
                    [[1.9e-3, 2.5e-3], [1.89e-3, 2.1e-3]]])
    Tor = np.array([[[2.6, 2.4], [2.8, 2.1]], [[2.9, 2.5], [2.7, 2.3]]])
    RDE = ADE / Tor

    # prepare simulation:
    DWIsim = np.zeros((2, 2, 2, gtab_2s.bvals.size))

    for i in range(2):
        for j in range(2):
            for k in range(2):
                ADi = ADI[i, j, k]
                RDi = RDI[i, j, k]
                ADe = ADE[i, j, k]
                RDe = RDE[i, j, k]
                fie = FIE[i, j, k]
                mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]])
                frac = [fie * 100, (1 - fie) * 100]
                theta = random.uniform(0, 180)
                phi = random.uniform(0, 320)
                angles = [(theta, phi), (theta, phi)]
                signal, dt, kt = multi_tensor_dki(gtab_2s,
                                                  mevals,
                                                  angles=angles,
                                                  fractions=frac,
                                                  snr=None)
                DWIsim[i, j, k, :] = signal

    # Ground truth Maximum kurtosis
    RD = FIE * RDI + (1 - FIE) * RDE
    RK = 3 * FIE * (1 - FIE) * ((RDI - RDE) / RD)**2

    # prepare inputs
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(DWIsim)
    sphere = get_sphere('symmetric724')

    # TEST - when no sphere is given
    k_max = dki.kurtosis_maximum(dkiF.model_params)
    assert_almost_equal(k_max, RK, decimal=4)

    # TEST - when sphere is given
    k_max = dki.kurtosis_maximum(dkiF.model_params, sphere)
    assert_almost_equal(k_max, RK, decimal=4)

    # TEST - when mask is given
    mask = np.ones((2, 2, 2), dtype='bool')
    mask[1, 1, 1] = 0
    RK[1, 1, 1] = 0
    k_max = dki.kurtosis_maximum(dkiF.model_params, mask=mask)
    assert_almost_equal(k_max, RK, decimal=4)
Esempio n. 15
0
def test_multi_voxel_kurtosis_maximum():
    # Multi-voxel simulations parameters
    FIE = np.array([[[0.30, 0.32], [0.74, 0.51]],
                    [[0.47, 0.21], [0.80, 0.63]]])
    RDI = np.zeros((2, 2, 2))
    ADI = np.array([[[1e-3, 1.3e-3], [0.8e-3, 1e-3]],
                    [[0.9e-3, 0.99e-3], [0.89e-3, 1.1e-3]]])
    ADE = np.array([[[2.2e-3, 2.3e-3], [2.8e-3, 2.1e-3]],
                    [[1.9e-3, 2.5e-3], [1.89e-3, 2.1e-3]]])
    Tor = np.array([[[2.6, 2.4], [2.8, 2.1]],
                    [[2.9, 2.5], [2.7, 2.3]]])
    RDE = ADE / Tor

    # prepare simulation:
    DWIsim = np.zeros((2, 2, 2, gtab_2s.bvals.size))

    for i in range(2):
        for j in range(2):
            for k in range(2):
                ADi = ADI[i, j, k]
                RDi = RDI[i, j, k]
                ADe = ADE[i, j, k]
                RDe = RDE[i, j, k]
                fie = FIE[i, j, k]
                mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]])
                frac = [fie*100, (1 - fie)*100]
                theta = random.uniform(0, 180)
                phi = random.uniform(0, 320)
                angles = [(theta, phi), (theta, phi)]
                signal, dt, kt = multi_tensor_dki(gtab_2s, mevals,
                                                  angles=angles,
                                                  fractions=frac, snr=None)
                DWIsim[i, j, k, :] = signal

    # Ground truth Maximum kurtosis
    RD = FIE*RDI + (1-FIE)*RDE
    RK = 3 * FIE * (1-FIE) * ((RDI-RDE) / RD) ** 2

    # prepare inputs
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(DWIsim)
    sphere = get_sphere('symmetric724')

    # TEST - when no sphere is given
    k_max = dki.kurtosis_maximum(dkiF.model_params)
    assert_almost_equal(k_max, RK, decimal=4)

    # TEST - when sphere is given
    k_max = dki.kurtosis_maximum(dkiF.model_params, sphere)
    assert_almost_equal(k_max, RK, decimal=4)

    # TEST - when mask is given
    mask = np.ones((2, 2, 2), dtype='bool')
    mask[1, 1, 1] = 0
    RK[1, 1, 1] = 0
    k_max = dki.kurtosis_maximum(dkiF.model_params, mask=mask)
    assert_almost_equal(k_max, RK, decimal=4)
Esempio n. 16
0
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)
Esempio n. 17
0
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)
Esempio n. 18
0
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)
Esempio n. 19
0
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)
Esempio n. 20
0
def make_dki_data(out_fbval, out_fbvec, out_fdata, out_shape=(5, 6, 7)):
    """
    Create a synthetic data-set with a 2-shell acquisition

    out_fbval, out_fbvec, out_fdata : str
        Full paths to generated data and bval/bvec files

    out_shape : tuple
        The 3D shape of the output volum

    """
    # This is one-shell (b=1000) data:
    fimg, fbvals, fbvecs = dpd.get_fnames('small_64D')
    img = nib.load(fimg)
    bvals, bvecs = dio.read_bvals_bvecs(fbvals, fbvecs)
    # So  we create two shells out of it
    bvals_2s = np.concatenate((bvals, bvals * 2), axis=0)
    bvecs_2s = np.concatenate((bvecs, bvecs), axis=0)
    gtab_2s = dpg.gradient_table(bvals_2s, bvecs_2s)

    # Simulate a signal based on the DKI model:
    mevals_cross = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                             [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
    angles_cross = [(80, 10), (80, 10), (20, 30), (20, 30)]
    fie = 0.49
    frac_cross = [fie * 50, (1 - fie) * 50, fie * 50, (1 - fie) * 50]
    # Noise free simulates
    signal_cross, dt_cross, kt_cross = multi_tensor_dki(gtab_2s,
                                                        mevals_cross,
                                                        S0=100,
                                                        angles=angles_cross,
                                                        fractions=frac_cross,
                                                        snr=None)
    DWI = np.zeros(out_shape + (len(gtab_2s.bvals), ))
    DWI[:] = signal_cross
    nib.save(nib.Nifti1Image(DWI, img.affine), out_fdata)
    np.savetxt(out_fbval, bvals_2s)
    np.savetxt(out_fbvec, bvecs_2s)
Esempio n. 21
0
def make_dki_data(out_fbval, out_fbvec, out_fdata, out_shape=(5, 6, 7)):
    """
    Create a synthetic data-set with a 2-shell acquisition

    out_fbval, out_fbvec, out_fdata : str
        Full paths to generated data and bval/bvec files

    out_shape : tuple
        The 3D shape of the output volum

    """
    # This is one-shell (b=1000) data:
    fimg, fbvals, fbvecs = dpd.get_data('small_64D')
    img = nib.load(fimg)
    bvals, bvecs = dio.read_bvals_bvecs(fbvals, fbvecs)
    # So  we create two shells out of it
    bvals_2s = np.concatenate((bvals, bvals * 2), axis=0)
    bvecs_2s = np.concatenate((bvecs, bvecs), axis=0)
    gtab_2s = dpg.gradient_table(bvals_2s, bvecs_2s)

    # Simulate a signal based on the DKI model:
    mevals_cross = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                             [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
    angles_cross = [(80, 10), (80, 10), (20, 30), (20, 30)]
    fie = 0.49
    frac_cross = [fie * 50, (1 - fie) * 50, fie * 50, (1 - fie) * 50]
    # Noise free simulates
    signal_cross, dt_cross, kt_cross = multi_tensor_dki(gtab_2s, mevals_cross,
                                                        S0=100,
                                                        angles=angles_cross,
                                                        fractions=frac_cross,
                                                        snr=None)
    DWI = np.zeros(out_shape + (len(gtab_2s.bvals), ))
    DWI[:] = signal_cross
    nib.save(nib.Nifti1Image(DWI, img.affine), out_fdata)
    np.savetxt(out_fbval, bvals_2s)
    np.savetxt(out_fbvec, bvecs_2s)
Esempio n. 22
0
In ``fractions`` we save the percentage of the contribution of each
compartment, which is computed by multiplying the percentage of contribution
of each fiber population and the water fraction of each different medium
"""

fie = 0.49  # intra axonal water fraction
fractions = [fie*50, (1 - fie)*50, fie*50, (1 - fie)*50]

"""
Having defined the parameters for all tissue compartments, the elements of the
diffusion tensor (DT), the elements of the kurtosis tensor (KT) and the DW
signals simulated from the DKI model can be obtain using the function
``multi_tensor_dki``.
"""

signal_dki, dt, kt = multi_tensor_dki(gtab, mevals, S0=200, angles=angles,
                                      fractions=fractions, snr=None)

"""
We can also add Rician noise with a specific SNR.
"""

signal_noisy, dt, kt = multi_tensor_dki(gtab, mevals, S0=200,
                                        angles=angles, fractions=fractions,
                                        snr=10)

"""
For comparison purposes, we also compute the DW signal if only the diffusion
tensor components are taken into account. For this we use DIPY's function
``single_tensor`` which requires that dt is decomposed into its eigenvalues and
eigenvectors.
"""
Esempio n. 23
0
def test_kurtosis_maximum():
    # TEST 1
    # simulate a crossing fibers interserting at 70 degrees. The first fiber
    # is aligned to the x-axis while the second fiber is aligned to the x-z
    # plane with an angular deviation of 70 degrees from the first one.
    # According to Neto Henriques et al, 2015 (NeuroImage 111: 85-99), the
    # kurtosis tensor of this simulation will have a maxima aligned to axis y
    angles = [(90, 0), (90, 0), (20, 0), (20, 0)]
    signal_70, dt_70, kt_70 = multi_tensor_dki(gtab_2s, mevals_cross, S0=100,
                                               angles=angles,
                                               fractions=frac_cross, snr=None)
    # prepare inputs
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(signal_70)
    MD = dkiF.md
    kt = dkiF.kt
    R = dkiF.evecs
    evals = dkiF.evals
    dt = lower_triangular(np.dot(np.dot(R, np.diag(evals)), R.T))
    sphere = get_sphere('symmetric724')

    # compute maxima
    k_max_cross, max_dir = dki._voxel_kurtosis_maximum(dt, MD, kt, sphere,
                                                       gtol=1e-5)

    yaxis = np.array([0., 1., 0.])
    cos_angle = np.abs(np.dot(max_dir[0], yaxis))
    assert_almost_equal(cos_angle, 1.)

    # TEST 2
    # test the function on cases of well aligned fibers oriented in a random
    # defined direction. According to Neto Henriques et al, 2015 (NeuroImage
    # 111: 85-99), the maxima of kurtosis is any direction perpendicular to the
    # fiber direction. Moreover, according to multicompartmetal simulations,
    # kurtosis in this direction has to be equal to:
    fie = 0.49
    ADi = 0.00099
    ADe = 0.00226
    RDi = 0
    RDe = 0.00087
    RD = fie*RDi + (1-fie)*RDe
    RK = 3 * fie * (1-fie) * ((RDi-RDe) / RD) ** 2

    # prepare simulation:
    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, angles=angles,
                                      fractions=frac, snr=None)

    # prepare inputs
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(signal)
    MD = dkiF.md
    kt = dkiF.kt
    R = dkiF.evecs
    evals = dkiF.evals
    dt = lower_triangular(np.dot(np.dot(R, np.diag(evals)), R.T))

    # compute maxima
    k_max, max_dir = dki._voxel_kurtosis_maximum(dt, MD, kt, sphere, gtol=1e-5)

    # check if max direction is perpendicular to fiber direction
    fdir = np.array([sphere2cart(1., np.deg2rad(theta), np.deg2rad(phi))])
    cos_angle = np.abs(np.dot(max_dir[0], fdir[0]))
    assert_almost_equal(cos_angle, 0., decimal=5)

    # check if max direction is equal to expected value
    assert_almost_equal(k_max, RK)

    # According to Neto Henriques et al., 2015 (NeuroImage 111: 85-99),
    # e.g. see figure 1 of this article, kurtosis maxima for the first test is
    # also equal to the maxima kurtosis value of well-aligned fibers, since
    # simulations parameters (apart from fiber directions) are equal
    assert_almost_equal(k_max_cross, RK)

    # Test 3 - Test performance when kurtosis is spherical - this case, can be
    # problematic since a spherical kurtosis does not have an maximum
    k_max, max_dir = dki._voxel_kurtosis_maximum(dt_sph, np.mean(evals_sph),
                                                 kt_sph, sphere, gtol=1e-2)
    assert_almost_equal(k_max, Kref_sphere)

    # Test 4 - Test performance when kt have all elements zero - this case, can
    # be problematic this case does not have an maximum
    k_max, max_dir = dki._voxel_kurtosis_maximum(dt_sph, np.mean(evals_sph),
                                                 np.zeros(15), sphere,
                                                 gtol=1e-2)
    assert_almost_equal(k_max, 0.0)
Esempio n. 24
0
def test_single_fiber_model():
    # single fiber simulate (which is the assumption of our model)
    fie = 0.49
    ADi = 0.00099
    ADe = 0.00226
    RDi = 0
    RDe = 0.00087

    # prepare simulation:
    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, angles=angles,
                                      fractions=frac, snr=None)
    # DKI fit
    dkiM = dki_micro.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(signal)

    # Axonal Water Fraction
    sphere = get_sphere('symmetric724')
    AWF = dki_micro.axonal_water_fraction(dkiF.model_params, sphere, mask=None,
                                          gtol=1e-5)
    assert_almost_equal(AWF, fie)

    # Extra-cellular and intra-cellular components
    edt, idt = dki_micro.diffusion_components(dkiF.model_params, sphere)
    EDT = eig_from_lo_tri(edt)
    IDT = eig_from_lo_tri(idt)

    # check eigenvalues
    assert_array_almost_equal(EDT[0:3], np.array([ADe, RDe, RDe]))
    assert_array_almost_equal(IDT[0:3], np.array([ADi, RDi, RDi]))
    # first eigenvalue should be the direction of the fibers
    fiber_direction = _check_directions([(theta, phi)])
    f_norm = abs(np.dot(fiber_direction, np.array((EDT[3], EDT[6], EDT[9]))))
    assert_almost_equal(f_norm, 1.)
    f_norm = abs(np.dot(fiber_direction, np.array((IDT[3], IDT[6], IDT[9]))))
    assert_almost_equal(f_norm, 1.)

    # Test model and fit objects
    wmtiM = dki_micro.KurtosisMicrostructureModel(gtab_2s, fit_method="WLS")
    wmtiF = wmtiM.fit(signal)
    assert_almost_equal(wmtiF.awf, AWF)
    assert_array_almost_equal(wmtiF.hindered_evals,
                              np.array([ADe, RDe, RDe]))
    assert_array_almost_equal(wmtiF.restricted_evals,
                              np.array([ADi, RDi, RDi]))
    assert_almost_equal(wmtiF.hindered_ad, ADe)
    assert_almost_equal(wmtiF.hindered_rd, RDe)
    assert_almost_equal(wmtiF.axonal_diffusivity, ADi)
    assert_almost_equal(wmtiF.tortuosity, ADe/RDe, decimal=4)

    # Test diffusion_components when a kurtosis tensors is associated with
    # negative kurtosis values. E.g of this cases is given below:
    dkiparams = np.array([1.67135726e-03, 5.03651205e-04, 9.35365328e-05,
                          -7.11167583e-01, 6.23186820e-01, -3.25390313e-01,
                          -1.75247376e-02, -4.78415563e-01, -8.77958674e-01,
                          7.02804064e-01, 6.18673368e-01, -3.51154825e-01,
                          2.18384153, -2.76378153e-02, 2.22893297,
                          -2.68306546e-01, -1.28411610, -1.56557645e-01,
                          -1.80850619e-01, -8.33152110e-01, -3.62410766e-01,
                          1.57775442e-01, 8.73775381e-01, 2.77188975e-01,
                          -3.67415502e-02, -1.56330984e-01, -1.62295407e-02])
    edt, idt = dki_micro.diffusion_components(dkiparams)
    assert_(np.all(np.isfinite(edt)))
Esempio n. 25
0
# 2 shells for techniques that requires multishell data
bvals_2s = np.concatenate((bvals, bvals * 2), axis=0)
bvecs_2s = np.concatenate((bvecs, bvecs), axis=0)
gtab_2s = gradient_table(bvals_2s, bvecs_2s)

# Simulation 1. signals of two crossing fibers are simulated
mevals_cross = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                         [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
angles_cross = [(80, 10), (80, 10), (20, 30), (20, 30)]
fie = 0.49
frac_cross = [fie*50, (1-fie) * 50, fie*50, (1-fie) * 50]
# Noise free simulates
signal_cross, dt_cross, kt_cross = multi_tensor_dki(gtab_2s, mevals_cross,
                                                    S0=100,
                                                    angles=angles_cross,
                                                    fractions=frac_cross,
                                                    snr=None)
evals_cross, evecs_cross = decompose_tensor(from_lower_triangular(dt_cross))
crossing_ref = np.concatenate((evals_cross, evecs_cross[0], evecs_cross[1],
                               evecs_cross[2], kt_cross), axis=0)

# Simulation 2. Spherical kurtosis tensor.- for white matter, this can be a
# biological implaussible scenario, however this simulation is usefull for
# testing the estimation of directional apparent kurtosis and the mean
# kurtosis, since its directional and mean kurtosis ground truth are a constant
# which can be easly mathematicaly calculated.
Di = 0.00099
De = 0.00226
mevals_sph = np.array([[Di, Di, Di], [De, De, De]])
frac_sph = [50, 50]
Esempio n. 26
0
for i in range(2):
    for j in range(2):
        for k in range(2):
            ADi = ADI[i, j, k]
            RDi = RDI[i, j, k]
            ADe = ADE[i, j, k]
            RDe = RDE[i, j, k]
            fie = FIE[i, j, k]
            mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]])
            frac = [fie * 100, (1 - fie) * 100]
            theta = random.uniform(0, 180)
            phi = random.uniform(0, 320)
            angles = [(theta, phi), (theta, phi)]
            signal, dt, kt = multi_tensor_dki(gtab_2s,
                                              mevals,
                                              angles=angles,
                                              fractions=frac,
                                              snr=None)
            DWIsim[i, j, k, :] = signal
            signal, sticks = multi_tensor(gtab_2s,
                                          mevals,
                                          angles=angles,
                                          fractions=frac,
                                          snr=None)
            DWIsim_all_taylor[i, j, k, :] = signal


def test_single_fiber_model():
    # single fiber simulate (which is the assumption of our model)
    fie = 0.49
    ADi = 0.00099
Esempio n. 27
0
def test_kurtosis_maximum():
    # TEST 1
    # simulate a crossing fibers interserting at 70 degrees. The first fiber
    # is aligned to the x-axis while the second fiber is aligned to the x-z
    # plane with an angular deviation of 70 degrees from the first one.
    # According to Neto Henriques et al, 2015 (NeuroImage 111: 85-99), the
    # kurtosis tensor of this simulation will have a maxima aligned to axis y
    angles = [(90, 0), (90, 0), (20, 0), (20, 0)]
    signal_70, dt_70, kt_70 = multi_tensor_dki(gtab_2s, mevals_cross, S0=100,
                                               angles=angles,
                                               fractions=frac_cross, snr=None)
    # prepare inputs
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(signal_70)
    MD = dkiF.md
    kt = dkiF.kt
    R = dkiF.evecs
    evals = dkiF.evals
    dt = lower_triangular(np.dot(np.dot(R, np.diag(evals)), R.T))
    sphere = get_sphere('symmetric724')

    # compute maxima
    k_max_cross, max_dir = dki._voxel_kurtosis_maximum(dt, MD, kt, sphere,
                                                       gtol=1e-5)

    yaxis = np.array([0., 1., 0.])
    cos_angle = np.abs(np.dot(max_dir[0], yaxis))
    assert_almost_equal(cos_angle, 1.)

    # TEST 2
    # test the function on cases of well aligned fibers oriented in a random
    # defined direction. According to Neto Henriques et al, 2015 (NeuroImage
    # 111: 85-99), the maxima of kurtosis is any direction perpendicular to the
    # fiber direction. Moreover, according to multicompartmetal simulations,
    # kurtosis in this direction has to be equal to:
    fie = 0.49
    ADi = 0.00099
    ADe = 0.00226
    RDi = 0
    RDe = 0.00087
    RD = fie*RDi + (1-fie)*RDe
    RK = 3 * fie * (1-fie) * ((RDi-RDe) / RD) ** 2

    # prepare simulation:
    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, angles=angles,
                                      fractions=frac, snr=None)

    # prepare inputs
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(signal)
    MD = dkiF.md
    kt = dkiF.kt
    R = dkiF.evecs
    evals = dkiF.evals
    dt = lower_triangular(np.dot(np.dot(R, np.diag(evals)), R.T))

    # compute maxima
    k_max, max_dir = dki._voxel_kurtosis_maximum(dt, MD, kt, sphere, gtol=1e-5)

    # check if max direction is perpendicular to fiber direction
    fdir = np.array([sphere2cart(1., np.deg2rad(theta), np.deg2rad(phi))])
    cos_angle = np.abs(np.dot(max_dir[0], fdir[0]))
    assert_almost_equal(cos_angle, 0., decimal=5)

    # check if max direction is equal to expected value
    assert_almost_equal(k_max, RK)

    # According to Neto Henriques et al., 2015 (NeuroImage 111: 85-99),
    # e.g. see figure 1 of this article, kurtosis maxima for the first test is
    # also equal to the maxima kurtosis value of well-aligned fibers, since
    # simulations parameters (apart from fiber directions) are equal
    assert_almost_equal(k_max_cross, RK)

    # Test 3 - Test performance when kurtosis is spherical - this case, can be
    # problematic since a spherical kurtosis does not have an maximum
    k_max, max_dir = dki._voxel_kurtosis_maximum(dt_sph, np.mean(evals_sph),
                                                 kt_sph, sphere, gtol=1e-2)
    assert_almost_equal(k_max, Kref_sphere)

    # Test 4 - Test performance when kt have all elements zero - this case, can
    # be problematic this case does not have an maximum
    k_max, max_dir = dki._voxel_kurtosis_maximum(dt_sph, np.mean(evals_sph),
                                                 np.zeros(15), sphere,
                                                 gtol=1e-2)
    assert_almost_equal(k_max, 0.0)
Esempio n. 28
0
compartment, which is computed by multiplying the percentage of contribution
of each fiber population and the water fraction of each different medium
"""

fie = 0.49  # intra axonal water fraction
fractions = [fie * 50, (1 - fie) * 50, fie * 50, (1 - fie) * 50]
"""
Having defined the parameters for all tissue compartments, the elements of the
diffusion tensor (dt), the elements of the kurtosis tensor (kt) and the DW
signals simulated from the DKI model can be obtain using the function
``multi_tensor_dki``.
"""

signal_dki, dt, kt = multi_tensor_dki(gtab,
                                      mevals,
                                      S0=200,
                                      angles=angles,
                                      fractions=fractions,
                                      snr=None)
"""
We can also add rician noise with a specific SNR.
"""

signal_noisy, dt, kt = multi_tensor_dki(gtab,
                                        mevals,
                                        S0=200,
                                        angles=angles,
                                        fractions=fractions,
                                        snr=10)
"""
For comparison purposes, we also compute the DW signal if only the diffusion
tensor components are taken into account. For this we use Dipy's function
Esempio n. 29
0
# 2 shells for techniques that requires multishell data
bvals_3s = np.concatenate((bvals, bvals*1.5, bvals * 2), axis=0)
bvecs_3s = np.concatenate((bvecs, bvecs, bvecs), axis=0)
gtab_3s = gradient_table(bvals_3s, bvecs_3s)

# Simulation 1. Spherical kurtosis tensor - MSK and MSD from the MSDKI model
# should be equa to the MK and MD of the DKI tensor for cases of
# spherical kurtosis tensors
Di = 0.00099
De = 0.00226
mevals_sph = np.array([[Di, Di, Di], [De, De, De]])
f = 0.5
frac_sph = [f * 100, (1.0 - f) * 100]
signal_sph, dt_sph, kt_sph = multi_tensor_dki(gtab_3s, mevals_sph, S0=100,
                                              fractions=frac_sph,
                                              snr=None)
# Compute ground truth values
MDgt = f * Di + (1 - f) * De
MKgt = 3 * f * (1-f) * ((Di-De) / MDgt) ** 2
params_single = np.array([MDgt, MKgt])
msignal_sph = np.zeros(4)
msignal_sph[0] = signal_sph[0]
msignal_sph[1] = signal_sph[1]
msignal_sph[2] = signal_sph[100]
msignal_sph[3] = signal_sph[180]

# Simulation 2. Multi-voxel simulations
DWI = np.zeros((2, 2, 2, len(gtab_3s.bvals)))
MDWI = np.zeros((2, 2, 2, 4))
MDgt_multi = np.zeros((2, 2, 2))
Esempio n. 30
0
# 2 shells for techniques that requires multishell data
bvals_2s = np.concatenate((bvals, bvals * 2), axis=0)
bvecs_2s = np.concatenate((bvecs, bvecs), axis=0)
gtab_2s = gradient_table(bvals_2s, bvecs_2s)

# Simulation 1. signals of two crossing fibers are simulated
mevals_cross = np.array([[0.00099, 0, 0], [0.00226, 0.00087, 0.00087],
                         [0.00099, 0, 0], [0.00226, 0.00087, 0.00087]])
angles_cross = [(80, 10), (80, 10), (20, 30), (20, 30)]
fie = 0.49
frac_cross = [fie*50, (1-fie) * 50, fie*50, (1-fie) * 50]
# Noise free simulates
signal_cross, dt_cross, kt_cross = multi_tensor_dki(gtab_2s, mevals_cross,
                                                    S0=100,
                                                    angles=angles_cross,
                                                    fractions=frac_cross,
                                                    snr=None)
evals_cross, evecs_cross = decompose_tensor(from_lower_triangular(dt_cross))
crossing_ref = np.concatenate((evals_cross, evecs_cross[0], evecs_cross[1],
                               evecs_cross[2], kt_cross), axis=0)

# Simulation 2. Spherical kurtosis tensor.- for white matter, this can be a
# biological implaussible scenario, however this simulation is usefull for
# testing the estimation of directional apparent kurtosis and the mean
# kurtosis, since its directional and mean kurtosis ground truth are a constant
# which can be easly mathematicaly calculated.
Di = 0.00099
De = 0.00226
mevals_sph = np.array([[Di, Di, Di], [De, De, De]])
frac_sph = [50, 50]
Esempio n. 31
0
def test_single_fiber_model():
    # single fiber simulate (which is the assumption of our model)
    fie = 0.49
    ADi = 0.00099
    ADe = 0.00226
    RDi = 0
    RDe = 0.00087

    # prepare simulation:
    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,
                                      angles=angles,
                                      fractions=frac,
                                      snr=None)
    # DKI fit
    dkiM = dki_micro.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(signal)

    # Axonal Water Fraction
    sphere = get_sphere('symmetric724')
    AWF = dki_micro.axonal_water_fraction(dkiF.model_params,
                                          sphere,
                                          mask=None,
                                          gtol=1e-5)
    assert_almost_equal(AWF, fie)

    # Extra-cellular and intra-cellular components
    edt, idt = dki_micro.diffusion_components(dkiF.model_params, sphere)
    EDT = eig_from_lo_tri(edt)
    IDT = eig_from_lo_tri(idt)

    # check eigenvalues
    assert_array_almost_equal(EDT[0:3], np.array([ADe, RDe, RDe]))
    assert_array_almost_equal(IDT[0:3], np.array([ADi, RDi, RDi]))
    # first eigenvalue should be the direction of the fibers
    fiber_direction = _check_directions([(theta, phi)])
    f_norm = abs(np.dot(fiber_direction, np.array((EDT[3], EDT[6], EDT[9]))))
    assert_almost_equal(f_norm, 1.)
    f_norm = abs(np.dot(fiber_direction, np.array((IDT[3], IDT[6], IDT[9]))))
    assert_almost_equal(f_norm, 1.)

    # Test model and fit objects
    wmtiM = dki_micro.KurtosisMicrostructureModel(gtab_2s, fit_method="WLS")
    wmtiF = wmtiM.fit(signal)
    assert_almost_equal(wmtiF.awf, AWF)
    assert_array_almost_equal(wmtiF.hindered_evals, np.array([ADe, RDe, RDe]))
    assert_array_almost_equal(wmtiF.restricted_evals, np.array([ADi, RDi,
                                                                RDi]))
    assert_almost_equal(wmtiF.hindered_ad, ADe)
    assert_almost_equal(wmtiF.hindered_rd, RDe)
    assert_almost_equal(wmtiF.axonal_diffusivity, ADi)
    assert_almost_equal(wmtiF.tortuosity, ADe / RDe, decimal=4)

    # Test diffusion_components when a kurtosis tensors is associated with
    # negative kurtosis values. E.g of this cases is given below:
    dkiparams = np.array([
        1.67135726e-03, 5.03651205e-04, 9.35365328e-05, -7.11167583e-01,
        6.23186820e-01, -3.25390313e-01, -1.75247376e-02, -4.78415563e-01,
        -8.77958674e-01, 7.02804064e-01, 6.18673368e-01, -3.51154825e-01,
        2.18384153, -2.76378153e-02, 2.22893297, -2.68306546e-01, -1.28411610,
        -1.56557645e-01, -1.80850619e-01, -8.33152110e-01, -3.62410766e-01,
        1.57775442e-01, 8.73775381e-01, 2.77188975e-01, -3.67415502e-02,
        -1.56330984e-01, -1.62295407e-02
    ])
    edt, idt = dki_micro.diffusion_components(dkiparams)
    assert_(np.all(np.isfinite(edt)))
Esempio n. 32
0
# 2 shells for techniques that requires multishell data
bvals_3s = np.concatenate((bvals, bvals * 1.5, bvals * 2), axis=0)
bvecs_3s = np.concatenate((bvecs, bvecs, bvecs), axis=0)
gtab_3s = gradient_table(bvals_3s, bvecs_3s)

# Simulation 1. Spherical kurtosis tensor - MSK and MSD from the MSDKI model
# should be equal to the MK and MD of the DKI tensor for cases of
# spherical kurtosis tensors
Di = 0.00099
De = 0.00226
mevals_sph = np.array([[Di, Di, Di], [De, De, De]])
f = 0.5
frac_sph = [f * 100, (1.0 - f) * 100]
signal_sph, dt_sph, kt_sph = multi_tensor_dki(gtab_3s,
                                              mevals_sph,
                                              S0=100,
                                              fractions=frac_sph,
                                              snr=None)
# Compute ground truth values
MDgt = f * Di + (1 - f) * De
MKgt = 3 * f * (1 - f) * ((Di - De) / MDgt)**2
params_single = np.array([MDgt, MKgt])
msignal_sph = np.zeros(4)
msignal_sph[0] = signal_sph[0]
msignal_sph[1] = signal_sph[1]
msignal_sph[2] = signal_sph[100]
msignal_sph[3] = signal_sph[180]

# Simulation 2. Multi-voxel simulations
DWI = np.zeros((2, 2, 2, len(gtab_3s.bvals)))
MDWI = np.zeros((2, 2, 2, 4))
Esempio n. 33
0
def test_DKI_simulations_aligned_fibers():
    """
    Testing DKI simulations when aligning the same fiber to different axis.

    If biological parameters don't change, kt[0] of a fiber aligned to axis x
    has to be equal to kt[1] of a fiber aligned to the axis y and equal to
    kt[2] of a fiber aligned to axis z. The same is applicable for dt
    """
    # Defining parameters based on Neto Henriques et al., 2015. NeuroImage 111
    mevals = np.array([
        [0.00099, 0, 0],  # Intra-cellular
        [0.00226, 0.00087, 0.00087]
    ])  # Extra-cellular
    frac = [49, 51]  # Compartment volume fraction
    # axis x
    angles = [(90, 0), (90, 0)]
    signal_fx, dt_fx, kt_fx = multi_tensor_dki(gtab_2s,
                                               mevals,
                                               angles=angles,
                                               fractions=frac)
    # axis y
    angles = [(90, 90), (90, 90)]
    signal_fy, dt_fy, kt_fy = multi_tensor_dki(gtab_2s,
                                               mevals,
                                               angles=angles,
                                               fractions=frac)
    # axis z
    angles = [(0, 0), (0, 0)]
    signal_fz, dt_fz, kt_fz = multi_tensor_dki(gtab_2s,
                                               mevals,
                                               angles=angles,
                                               fractions=frac)

    assert_array_equal([kt_fx[0], kt_fx[1], kt_fx[2]],
                       [kt_fy[1], kt_fy[0], kt_fy[2]])
    assert_array_equal([kt_fx[0], kt_fx[1], kt_fx[2]],
                       [kt_fz[2], kt_fz[0], kt_fz[1]])

    assert_array_equal([dt_fx[0], dt_fx[2], dt_fx[5]],
                       [dt_fy[2], dt_fy[0], dt_fy[5]])
    assert_array_equal([dt_fx[0], dt_fx[2], dt_fx[5]],
                       [dt_fz[5], dt_fz[0], dt_fz[2]])

    # testing S signal along axis x, y and z
    bvals = np.array([0, 0, 0, 1000, 1000, 1000, 2000, 2000, 2000])
    bvecs = np.asarray([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0],
                        [0, 0, 1], [1, 0, 0], [0, 1, 0], [0, 0, 1]])
    gtab_axis = gradient_table(bvals, bvecs)
    # axis x
    S_fx = dki_signal(gtab_axis, dt_fx, kt_fx, S0=100)
    assert_array_almost_equal(S_fx[0:3], [100, 100, 100])  # test S f0r b=0
    # axis y
    S_fy = dki_signal(gtab_axis, dt_fy, kt_fy, S0=100)
    assert_array_almost_equal(S_fy[0:3], [100, 100, 100])  # test S f0r b=0
    # axis z
    S_fz = dki_signal(gtab_axis, dt_fz, kt_fz, S0=100)
    assert_array_almost_equal(S_fz[0:3], [100, 100, 100])  # test S f0r b=0

    # test S for b = 1000
    assert_array_almost_equal([S_fx[3], S_fx[4], S_fx[5]],
                              [S_fy[4], S_fy[3], S_fy[5]])
    assert_array_almost_equal([S_fx[3], S_fx[4], S_fx[5]],
                              [S_fz[5], S_fz[3], S_fz[4]])
    # test S for b = 2000
    assert_array_almost_equal([S_fx[6], S_fx[7], S_fx[8]],
                              [S_fy[7], S_fy[6], S_fy[8]])
    assert_array_almost_equal([S_fx[6], S_fx[7], S_fx[8]],
                              [S_fz[8], S_fz[6], S_fz[7]])
Esempio n. 34
0
for i in range(2):
    for j in range(2):
        for k in range(2):
            ADi = ADI[i, j, k]
            RDi = RDI[i, j, k]
            ADe = ADE[i, j, k]
            RDe = RDE[i, j, k]
            fie = FIE[i, j, k]
            mevals = np.array([[ADi, RDi, RDi], [ADe, RDe, RDe]])
            frac = [fie*100, (1 - fie)*100]
            theta = random.uniform(0, 180)
            phi = random.uniform(0, 320)
            angles = [(theta, phi), (theta, phi)]
            signal, dt, kt = multi_tensor_dki(gtab_2s, mevals,
                                              angles=angles,
                                              fractions=frac, snr=None)
            DWIsim[i, j, k, :] = signal
            signal, sticks = multi_tensor(gtab_2s, mevals, angles=angles,
                                          fractions=frac, snr=None)
            DWIsim_all_taylor[i, j, k, :] = signal


def test_single_fiber_model():
    # single fiber simulate (which is the assumption of our model)
    fie = 0.49
    ADi = 0.00099
    ADe = 0.00226
    RDi = 0
    RDe = 0.00087