Exemplo n.º 1
0
def test_msdki_predict():
    dkiM = msdki.MeanDiffusionKurtosisModel(gtab_3s)

    # single voxel
    pred = dkiM.predict(params_single, S0=100)
    assert_array_almost_equal(pred, signal_sph)

    # multi-voxel
    pred = dkiM.predict(params_multi, S0=100)
    assert_array_almost_equal(pred[:, :, 0, :], DWI[:, :, 0, :])

    # check the function predict of the DiffusionKurtosisFit object
    dkiF = dkiM.fit(signal_sph)
    pred_single = dkiF.predict(gtab_3s, S0=100)
    assert_array_almost_equal(pred_single, signal_sph)
    dkiF = dkiM.fit(DWI)
    pred_multi = dkiF.predict(gtab_3s, S0=100)
    assert_array_almost_equal(pred_multi[:, :, 0, :], DWI[:, :, 0, :])

    # No S0
    dkiF = dkiM.fit(signal_sph)
    pred_single = dkiF.predict(gtab_3s)
    assert_array_almost_equal(100 * pred_single, signal_sph)
    dkiF = dkiM.fit(DWI)
    pred_multi = dkiF.predict(gtab_3s)
    assert_array_almost_equal(100 * pred_multi[:, :, 0, :], DWI[:, :, 0, :])

    # SO volume
    dkiF = dkiM.fit(DWI)
    pred_multi = dkiF.predict(gtab_3s, 100 * np.ones(DWI.shape[:-1]))
    assert_array_almost_equal(pred_multi[:, :, 0, :], DWI[:, :, 0, :])
Exemplo n.º 2
0
def test_errors():
    # first error raises if MeanDiffusionKurtosisModel is called for
    # data will only one non-zero b-value
    assert_raises(ValueError, msdki.MeanDiffusionKurtosisModel, gtab)

    # second error raises if negative signal is given to MeanDiffusionKurtosis
    # model
    assert_raises(ValueError,
                  msdki.MeanDiffusionKurtosisModel,
                  gtab_3s,
                  min_signal=-1)

    # third error raises if wrong mask is given to fit
    mask_wrong = np.ones((2, 3, 1))
    msdki_model = msdki.MeanDiffusionKurtosisModel(gtab_3s)
    assert_raises(ValueError, msdki_model.fit, DWI, mask=mask_wrong)

    # fourth error raises if an given index point to more dimensions that data
    # does not contain

    # define auxiliary function for the assert raises
    def aux_test_fun(ob, ind):
        met = ob[ind].msk
        return met

    mdkiF = msdki_model.fit(DWI)
    assert_raises(IndexError, aux_test_fun, mdkiF, (0, 0, 0, 0))
    # checking if aux_test_fun runs fine
    met = aux_test_fun(mdkiF, (0, 0, 0))
    assert_array_almost_equal(MKgt_multi[0, 0, 0], met)
Exemplo n.º 3
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)
Exemplo n.º 4
0
def test_msdki_statistics():
    # tests if MD and MK are equal to expected values of a spherical
    # tensors

    # Multi-tensors
    ub = unique_bvals(bvals_3s)
    design_matrix = msdki.design_matrix(ub)
    msignal, ng = msdki.mean_signal_bvalue(DWI, gtab_3s, bmag=None)
    params = msdki.wls_fit_msdki(design_matrix, msignal, ng)
    assert_array_almost_equal(params[..., 1], MKgt_multi)
    assert_array_almost_equal(params[..., 0], MDgt_multi)

    mdkiM = msdki.MeanDiffusionKurtosisModel(gtab_3s)
    mdkiF = mdkiM.fit(DWI)
    mk = mdkiF.msk
    md = mdkiF.msd
    assert_array_almost_equal(MKgt_multi, mk)
    assert_array_almost_equal(MDgt_multi, md)

    # Single-tensors
    mdkiF = mdkiM.fit(signal_sph)
    mk = mdkiF.msk
    md = mdkiF.msd
    assert_array_almost_equal(MKgt, mk)
    assert_array_almost_equal(MDgt, md)

    # Test with given mask
    mask = np.ones(DWI.shape[:-1])
    v = (0, 0, 0)
    mask[1, 1, 1] = 0
    mdkiF = mdkiM.fit(DWI, mask=mask)
    mk = mdkiF.msk
    md = mdkiF.msd
    assert_array_almost_equal(MKgt_multi, mk)
    assert_array_almost_equal(MDgt_multi, md)
    assert_array_almost_equal(MKgt_multi[v], mdkiF[v].msk)  # tuple case
    assert_array_almost_equal(MDgt_multi[v], mdkiF[v].msd)  # tuple case
    assert_array_almost_equal(MKgt_multi[0], mdkiF[0].msk)  # not tuple case
    assert_array_almost_equal(MDgt_multi[0], mdkiF[0].msd)  # not tuple case

    # Test returned S0
    mdkiM = msdki.MeanDiffusionKurtosisModel(gtab_3s, return_S0_hat=True)
    mdkiF = mdkiM.fit(DWI)
    assert_array_almost_equal(S0gt_multi, mdkiF.S0_hat)
    assert_array_almost_equal(MKgt_multi[v], mdkiF[v].msk)
Exemplo n.º 5
0
def test_smt2_metrics():
    # Just checking if parameters can be retrived from MSDKI's fit class obj

    # Based on the multi-voxel simulations above (computes gt for SMT2 params)
    AWFgt = awf_from_msk(MKgt_multi)
    DIgt = 3 * MDgt_multi / (1 + 2 * (1 - AWFgt)**2)
    # General microscopic anisotropy estimation (Eq 8 Henriques et al MRM 2019)
    RDe = DIgt * (1 - AWFgt)  # tortuosity assumption
    VarD = 2 / 9 * (AWFgt * DIgt**2 + (1 - AWFgt) * (DIgt - RDe)**2)
    MD = (AWFgt * DIgt + (1 - AWFgt) * (DIgt + 2 * RDe)) / 3
    uFAgt = np.sqrt(3 / 2 * VarD[MD > 0] / (VarD[MD > 0] + MD[MD > 0]**2))

    mdkiM = msdki.MeanDiffusionKurtosisModel(gtab_3s)
    mdkiF = mdkiM.fit(DWI)
    assert_array_almost_equal(mdkiF.smt2f, AWFgt)
    assert_array_almost_equal(mdkiF.smt2di, DIgt)
    assert_array_almost_equal(mdkiF.smt2uFA[MD > 0], uFAgt)

    # Check if awf_from_msk when mask is given
    mask = MKgt_multi > 0
    AWF = awf_from_msk(MKgt_multi, mask)
    assert_array_almost_equal(AWF, AWFgt)
Exemplo n.º 6
0
To avoid unnecessary calculations on the background of the image, we also
compute a brain mask.
"""

# Create a brain mask
from dipy.segment.mask import median_otsu

maskdata, mask = median_otsu(data_slices, vol_idx=range(10, 50),
                             median_radius=3, numpass=1, autocrop=False,
                             dilate=1)

# Define mean signal diffusion kurtosis model
import dipy.reconst.msdki as msdki

dki_model = msdki.MeanDiffusionKurtosisModel(gtab)

# Fit the uncorrected data
dki_fit = dki_model.fit(data_slices, mask=mask)
MSKini = dki_fit.msk

# Fit the corrected data
dki_fit = dki_model.fit(data_corrected, mask=mask)
MSKgib = dki_fit.msk

"""
Let's plot the results
"""

fig3, ax = plt.subplots(1, 3, figsize=(12, 12),
                        subplot_kw={'xticks': [], 'yticks': []})
def main():
    logger = logging.getLogger("Compute_DKI_Metrics")
    logger.setLevel(logging.INFO)

    parser = _build_args_parser()
    args = parser.parse_args()

    if not args.not_all:
        args.dki_fa = args.dki_fa or 'dki_fa.nii.gz'
        args.dki_md = args.dki_md or 'dki_md.nii.gz'
        args.dki_ad = args.dki_ad or 'dki_ad.nii.gz'
        args.dki_rd = args.dki_rd or 'dki_rd.nii.gz'
        args.mk = args.mk or 'mk.nii.gz'
        args.rk = args.rk or 'rk.nii.gz'
        args.ak = args.ak or 'ak.nii.gz'
        args.dki_residual = args.dki_residual or 'dki_residual.nii.gz'
        args.msk = args.msk or 'msk.nii.gz'
        args.msd = args.msd or 'msd.nii.gz'

    outputs = [args.dki_fa, args.dki_md, args.dki_ad, args.dki_rd,
               args.mk, args.rk, args.ak, args.dki_residual,
               args.msk, args.msd]

    if args.not_all and not any(outputs):
        parser.error('When using --not_all, you need to specify at least ' +
                     'one metric to output.')

    assert_inputs_exist(
        parser, [args.input, args.bvals, args.bvecs], args.mask)
    assert_outputs_exist(parser, args, outputs)

    img = nib.load(args.input)
    data = img.get_fdata()
    affine = img.affine
    if args.mask is None:
        mask = None
    else:
        mask = nib.load(args.mask).get_fdata().astype(np.bool)

    # Validate bvals and bvecs
    bvals, bvecs = read_bvals_bvecs(args.bvals, args.bvecs)
    if not is_normalized_bvecs(bvecs):
        logging.warning('Your b-vectors do not seem normalized...')
        bvecs = normalize_bvecs(bvecs)

    # Find the volume indices that correspond to the shells to extract.
    tol = args.tolerance
    shells, _ = identify_shells(bvals, tol)
    if not len(shells) >= 3:
        parser.error('Data is not multi-shell. You need at least 2 non-zero' +
                     ' b-values')

    if (shells > 2500).any():
        logging.warning('You seem to be using b > 2500 s/mm2 DWI data. ' +
                        'In theory, this is beyond the optimal range for DKI')

    check_b0_threshold(args, bvals.min())
    gtab = gradient_table(bvals, bvecs, b0_threshold=bvals.min())

    fwhm = args.smooth
    if fwhm > 0:
        # converting fwhm to Gaussian std
        gauss_std = fwhm / np.sqrt(8 * np.log(2))
        data_smooth = np.zeros(data.shape)
        for v in range(data.shape[-1]):
            data_smooth[..., v] = gaussian_filter(data[..., v],
                                                  sigma=gauss_std)
        data = data_smooth

    # Compute DKI
    dkimodel = dki.DiffusionKurtosisModel(gtab)
    dkifit = dkimodel.fit(data, mask=mask)

    min_k = args.min_k
    max_k = args.max_k

    if args.dki_fa:
        FA = dkifit.fa
        FA[np.isnan(FA)] = 0
        FA = np.clip(FA, 0, 1)

        fa_img = nib.Nifti1Image(FA.astype(np.float32), affine)
        nib.save(fa_img, args.dki_fa)

    if args.dki_md:
        MD = dkifit.md
        md_img = nib.Nifti1Image(MD.astype(np.float32), affine)
        nib.save(md_img, args.dki_md)

    if args.dki_ad:
        AD = dkifit.ad
        ad_img = nib.Nifti1Image(AD.astype(np.float32), affine)
        nib.save(ad_img, args.dki_ad)

    if args.dki_rd:
        RD = dkifit.rd
        rd_img = nib.Nifti1Image(RD.astype(np.float32), affine)
        nib.save(rd_img, args.dki_rd)

    if args.mk:
        MK = dkifit.mk(min_k, max_k)
        mk_img = nib.Nifti1Image(MK.astype(np.float32), affine)
        nib.save(mk_img, args.mk)

    if args.ak:
        AK = dkifit.ak(min_k, max_k)
        ak_img = nib.Nifti1Image(AK.astype(np.float32), affine)
        nib.save(ak_img, args.ak)

    if args.rk:
        RK = dkifit.rk(min_k, max_k)
        rk_img = nib.Nifti1Image(RK.astype(np.float32), affine)
        nib.save(rk_img, args.rk)

    if args.msk or args.msd:
        # Compute MSDKI
        msdki_model = msdki.MeanDiffusionKurtosisModel(gtab)
        msdki_fit = msdki_model.fit(data, mask=mask)

        if args.msk:
            MSK = msdki_fit.msk
            MSK[np.isnan(MSK)] = 0
            MSK = np.clip(MSK, min_k, max_k)

            msk_img = nib.Nifti1Image(MSK.astype(np.float32), affine)
            nib.save(msk_img, args.msk)

        if args.msd:
            MSD = msdki_fit.msd
            msd_img = nib.Nifti1Image(MSD.astype(np.float32), affine)
            nib.save(msd_img, args.msd)

    if args.dki_residual:
        S0 = np.mean(data[..., gtab.b0s_mask], axis=-1)
        data_p = dkifit.predict(gtab, S0)
        R = np.mean(np.abs(data_p[..., ~gtab.b0s_mask] -
                           data[..., ~gtab.b0s_mask]), axis=-1)

        norm = np.linalg.norm(R)
        if norm != 0:
            R = R / norm

        if args.mask is not None:
            R *= mask

        R_img = nib.Nifti1Image(R.astype(np.float32), affine)
        nib.save(R_img, args.dki_residual)