Beispiel #1
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)
Beispiel #2
0
def test_dki_micro_predict_multi_voxel():
    dkiM = dki_micro.KurtosisMicrostructureModel(gtab_2s)
    dkiF = dkiM.fit(DWIsim)

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

    pred = dkiM.predict(dkiF.model_params, S0=100)
    assert_array_almost_equal(pred, DWIsim_all_taylor * 100, decimal=3)

    # Check predict of KurtosisMicrostruturalFit
    pred = dkiF.predict(gtab_2s, S0=100)
    assert_array_almost_equal(pred, DWIsim_all_taylor * 100, decimal=3)
Beispiel #3
0
def test_dki_micro_awf_only():
    dkiM = dki_micro.KurtosisMicrostructureModel(gtab_2s)
    dkiF = dkiM.fit(DWIsim, awf_only=True)
    awf = dkiF.awf
    assert_almost_equal(awf, FIE, decimal=3)

    # assert_raises(dkiF.hindered_evals)
    assert_raises(ValueError, _help_test_awf_only, dkiF,
                  'dkimicrofit.hindered_evals')
    assert_raises(ValueError, _help_test_awf_only, dkiF,
                  'dkimicrofit.restricted_evals')
    assert_raises(ValueError, _help_test_awf_only, dkiF,
                  'dkimicrofit.axonal_diffusivity')
    assert_raises(ValueError, _help_test_awf_only, dkiF,
                  'dkimicrofit.hindered_ad')
    assert_raises(ValueError, _help_test_awf_only, dkiF,
                  'dkimicrofit.hindered_rd')
    assert_raises(ValueError, _help_test_awf_only, dkiF,
                  'dkimicrofit.tortuosity')
Beispiel #4
0
As mentioned above, DKI can also be used to derive concrete biophysical
parameters by applying microstructural models to DT and KT estimated from DKI.
For instance,  Fieremans et al. [Fieremans2011]_ showed that DKI can be used to
estimate the contribution of hindered and restricted diffusion for well-aligned
fibers. These tensors can be also interpreted as the influences of intra- and
extra-cellular compartments and can be used to estimate the axonal volume
fraction and diffusion extra-cellular tortuosity. According to recent studies,
these latter measures can be used to distinguish processes of axonal loss from
processes of myelin degeneration [Fieremans2012]_.

The model proposed by Fieremans and colleagues can be defined in DIPY by
instantiating the 'KurtosisMicrostructureModel' object in the following way:
"""

dki_micro_model = dki_micro.KurtosisMicrostructureModel(gtab)
"""
Before fitting this microstructural model, it is useful to indicate the
regions in which this model provides meaningful information (i.e. voxels of
well-aligned fibers). Following Fieremans et al. [Fieremans2011]_, a simple way
to select this region is to generate a well-aligned fiber mask based on the
values of diffusion sphericity, planarity and linearity. Here we will follow
these selection criteria for a better comparision of our figures with the
original article published by Fieremans et al. [Fieremans2011]_. Nevertheless,
it is important to note that voxels with well-aligned fibers can be selected
based on other approaches such as using predefined regions of interest.
"""

well_aligned_mask = np.ones(data.shape[:-1], dtype='bool')

# Diffusion coefficient of linearity (cl) has to be larger than 0.4, thus
Beispiel #5
0
def fit_dkimicro(data_files,
                 bval_files,
                 bvec_files,
                 mask=None,
                 min_kurtosis=-1,
                 max_kurtosis=3,
                 out_dir=None,
                 b0_threshold=0):
    """
    Fit the DKI model, save files with derived maps

    Parameters
    ----------
    data_files : str or list
        Files containing DWI data. If this is a str, that's the full path to a
        single file. If it's a list, each entry is a full path.
    bval_files : str or list
        Equivalent to `data_files`.
    bvec_files : str or list
        Equivalent to `data_files`.
    mask : ndarray, optional
        Binary mask, set to True or 1 in voxels to be processed.
        Default: Process all voxels.
    min_kurtosis : float, optional
        The minimal plausible value of kurtosis. Default: -1.
    max_kurtosis : float, optional
        The maximal plausible value of kurtosis. Default: 3.
    out_dir : str, optional
        A full path to a directory to store the maps that get computed.
        Default: maps get stored in the same directory as the last DWI file
        in `data_files`.
    b0_threshold : float


    Returns
    -------
    file_paths : a dict with the derived maps that were computed and full-paths
    to the files containing these maps.

    Note
    ----
    Maps that are calculated: FA, MD, AD, RD, MK, AK, RK

    """
    img, data, gtab, mask = ut.prepare_data(data_files,
                                            bval_files,
                                            bvec_files,
                                            mask=mask,
                                            b0_threshold=b0_threshold)

    dkimodel = dki_micro.KurtosisMicrostructureModel(gtab)
    dkifit = dkimodel.fit(data, mask=mask)

    AWF = dkifit.awf
    T = dkifit.tortuosity
    Da = dkifit.axonal_diffusivity
    hRD = dkifit.hindered_rd
    hAD = dkifit.hindered_ad
    evals = dkifit.hindered_evals
    hMD = (evals[..., 0] + evals[..., 1] + evals[..., 2]) / 3.0
    params = dkifit.model_params

    maps = [AWF, T, hAD, hRD, hMD, Da, params]
    names = ['AWF', 'T', 'hAD', 'hRD', 'hMD', 'Da', 'params']

    if out_dir is None:
        if isinstance(data_files, list):
            out_dir = op.join(op.split(data_files[0])[0], 'dki')
        else:
            out_dir = op.join(op.split(data_files)[0], 'dki')

    if not op.exists(out_dir):
        os.makedirs(out_dir)

    aff = img.affine
    file_paths = {}
    for m, n in zip(maps, names):
        file_paths[n] = op.join(out_dir, 'dkimicro_%s.nii.gz' % n)
        nib.save(nib.Nifti1Image(m, aff), file_paths[n])

    return file_paths
def fit_dki_dipy(input_dwi,
                 input_bval,
                 input_bvec,
                 output_dir,
                 fit_method='',
                 mask='',
                 include_micro_fit='FALSE'):

    if fit_method == '':
        fit_method = 'OLS'

    img = nib.load(input_dwi)
    data = img.get_data()
    bvals, bvecs = read_bvals_bvecs(
        input_bval,
        input_bvec,
    )
    gtab = gradient_table(bvals, bvecs)

    if mask != '':
        mask_data = nib.load(mask).get_data()

    values = np.array(bvals)
    ii = np.where(values == bvals.min())[0]
    b0_average = np.mean(data[:, :, :, ii], axis=3)

    #Recommended to smooth data prior to fitting:
    fwhm = 2.00
    gauss_std = fwhm / np.sqrt(
        8 * np.log(2))  # converting fwhm to Gaussian std
    data_smooth = np.zeros(data.shape)
    for v in range(data.shape[-1]):
        data_smooth[..., v] = filters.gaussian_filter(data[..., v],
                                                      sigma=gauss_std)

    dkimodel = dki.DiffusionKurtosisModel(gtab, fit_method)

    if mask != '':
        dkifit = dkimodel.fit(data_smooth, mask_data)
    else:
        dkifit = dkimodel.fit(data_smooth)

    if not os.path.exists(output_dir):
        os.mkdir(output_dir)

    output_evecs = output_dir + '/dki_eigenvectors.nii.gz'
    output_evals = output_dir + '/dki_eigenvalues.nii.gz'

    output_fa = output_dir + '/dki_FA.nii.gz'
    output_md = output_dir + '/dki_MD.nii.gz'
    output_rd = output_dir + '/dki_RD.nii.gz'
    output_ad = output_dir + '/dki_AD.nii.gz'
    output_mk = output_dir + '/dki_MK.nii.gz'
    output_ak = output_dir + '/dki_AK.nii.gz'
    output_rk = output_dir + '/dki_RK.nii.gz'

    #Calculate Parameters for Kurtosis Model
    evals_img = nib.Nifti1Image(dkifit.evals.astype(np.float32),
                                img.get_affine(), img.header)
    nib.save(evals_img, output_evals)

    evecs_img = nib.Nifti1Image(dkifit.evecs.astype(np.float32),
                                img.get_affine(), img.header)
    nib.save(evecs_img, output_evecs)

    dki_fa = dkifit.fa
    dki_fa_img = nib.Nifti1Image(dki_fa.astype(np.float32), img.get_affine(),
                                 img.header)
    nib.save(dki_fa_img, output_fa)

    dki_md = dkifit.md
    dki_md_img = nib.Nifti1Image(dki_md.astype(np.float32), img.get_affine(),
                                 img.header)
    nib.save(dki_md_img, output_md)

    dki_ad = dkifit.ad
    dki_ad_img = nib.Nifti1Image(dki_ad.astype(np.float32), img.get_affine(),
                                 img.header)
    nib.save(dki_ad_img, output_ad)

    dki_rd = dkifit.rd
    dki_rd_img = nib.Nifti1Image(dki_rd.astype(np.float32), img.get_affine(),
                                 img.header)
    nib.save(dki_rd_img, output_rd)

    MK = dkifit.mk(0, 3)
    AK = dkifit.ak(0, 3)
    RK = dkifit.rk(0, 3)

    dki_mk_img = nib.Nifti1Image(MK.astype(np.float32), img.get_affine(),
                                 img.header)
    nib.save(dki_mk_img, output_mk)

    dki_ak_img = nib.Nifti1Image(AK.astype(np.float32), img.get_affine(),
                                 img.header)
    nib.save(dki_ak_img, output_ak)

    dki_rk_img = nib.Nifti1Image(RK.astype(np.float32), img.get_affine(),
                                 img.header)
    nib.save(dki_rk_img, output_rk)

    if include_micro_fit == 'TRUE':

        import dipy.reconst.dki_micro as dki_micro
        well_aligned_mask = np.ones(data.shape[:-1], dtype='bool')

        # Diffusion coefficient of linearity (cl) has to be larger than 0.4, thus
        # we exclude voxels with cl < 0.4.
        cl = dkifit.linearity.copy()
        well_aligned_mask[cl < 0.2] = False

        # Diffusion coefficient of planarity (cp) has to be lower than 0.2, thus
        # we exclude voxels with cp > 0.2.
        cp = dkifit.planarity.copy()
        well_aligned_mask[cp > 0.2] = False

        # Diffusion coefficient of sphericity (cs) has to be lower than 0.35, thus
        # we exclude voxels with cs > 0.35.
        cs = dkifit.sphericity.copy()
        well_aligned_mask[cs > 0.2] = False

        # Removing nan associated with background voxels
        well_aligned_mask[np.isnan(cl)] = False
        well_aligned_mask[np.isnan(cp)] = False
        well_aligned_mask[np.isnan(cs)] = False

        dki_micro_model = dki_micro.KurtosisMicrostructureModel(
            gtab, fit_method)
        dki_micro_fit = dki_micro_model.fit(data_smooth,
                                            mask=well_aligned_mask)

        output_awf = output_dir + '/dki_micro_AWF.nii.gz'
        output_tort = output_dir + '/dki_micro_TORT.nii.gz'
        dki_micro_awf = dki_micro_fit.awf
        dki_micro_tort = dki_micro_fit.tortuosity

        dki_micro_awf_img = nib.Nifti1Image(dki_micro_awf.astype(np.float32),
                                            img.get_affine(), img.header)
        nib.save(dki_micro_awf_img, output_awf)

        dki_micro_tort_img = nib.Nifti1Image(dki_micro_tort.astype(np.float32),
                                             img.get_affine(), img.header)
        nib.save(dki_micro_tort_img, output_tort)
def Kurtosis(dwi, mask):
    import numpy as np
    import dipy.reconst.dki as dki
    import dipy.reconst.dti as dti
    import dipy.reconst.dki_micro as dki_micro
    from dipy.data import fetch_cfin_multib
    from dipy.data import read_cfin_dwi
    from dipy.segment.mask import median_otsu
    from dipy.io.image import load_nifti, save_nifti
    from scipy.ndimage.filters import gaussian_filter
    import nibabel as nib
    from dipy.core.gradients import gradient_table
    from dipy.io import read_bvals_bvecs
    from sklearn import preprocessing
    import dipy.denoise.noise_estimate as ne  # determine the noise needed for RESTORE
    import os

    bval = '/media/amr/HDD/Work/October_Acquistion/bval_multishell'
    bvec = '/media/amr/HDD/Work/October_Acquistion/bvec_multishell'
    protocol = '/media/amr/HDD/Work/October_Acquistion/MDT_multishell_protocol.prtcl'
    data, affine = load_nifti(dwi)
    mask, affine_mask = load_nifti(mask)
    protocol = np.loadtxt(protocol)
    fbval = bval
    fbvec = bvec

    bval, bvec = read_bvals_bvecs(fbval, fbvec)
    gnorm = protocol[:, 3]
    Delta = protocol[:, 4]
    delta = protocol[:, 5]
    TE = protocol[:, 6]
    TR = protocol[:, 8]

    if np.dot(bvec[5, :], bvec[5, :]) == 1.0:
        gtab = gradient_table(bval,
                              bvec,
                              big_delta=Delta,
                              small_delta=delta,
                              b0_threshold=0,
                              atol=1)

    else:
        bvec = preprocessing.normalize(bvec, norm='l2')
        gtab = gradient_table(bval,
                              bvec,
                              big_delta=Delta,
                              small_delta=delta,
                              b0_threshold=0,
                              atol=0.01)

#without disable_background_masking, it does not work with some subjects
    sigma = ne.estimate_sigma(data, disable_background_masking=True)

    # dkimodel = dki.DiffusionKurtosisModel(gtab, fit_method='WLS') the old way also the default
    dkimodel = dki.DiffusionKurtosisModel(gtab,
                                          fit_method='RESTORE',
                                          sigma=sigma)

    #AWF and TORT from microstructure model
    dki_micro_model = dki_micro.KurtosisMicrostructureModel(
        gtab, fit_method='RESTORE')

    # fit the models
    dkifit = dkimodel.fit(data, mask=mask)
    dki_micro_fit = dki_micro_model.fit(data, mask=mask)

    FA = dkifit.fa
    MD = dkifit.md
    AD = dkifit.ad
    RD = dkifit.rd
    KA = dkifit.kfa

    MK = dkifit.mk(0, 3)
    AK = dkifit.ak(0, 3)
    RK = dkifit.rk(0, 3)

    AWF = dki_micro_fit.awf  #Axonal watrer Fraction
    TORT = dki_micro_fit.tortuosity  #Tortouisty

    save_nifti('DKI_FA.nii', FA, affine)
    save_nifti('DKI_MD.nii', MD, affine)
    save_nifti('DKI_AD.nii', AD, affine)
    save_nifti('DKI_RD.nii', RD, affine)
    save_nifti('DKI_KA.nii', KA, affine)

    save_nifti('DKI_MK.nii', MK, affine)
    save_nifti('DKI_AK.nii', AK, affine)
    save_nifti('DKI_RK.nii', RK, affine)

    save_nifti('DKI_AWF.nii', AWF, affine)
    save_nifti('DKI_TORT.nii', TORT, affine)

    DKI_FA = os.path.abspath('DKI_FA.nii')
    DKI_MD = os.path.abspath('DKI_MD.nii')
    DKI_AD = os.path.abspath('DKI_AD.nii')
    DKI_RD = os.path.abspath('DKI_RD.nii')
    DKI_KA = os.path.abspath('DKI_KA.nii')

    DKI_MK = os.path.abspath('DKI_MK.nii')
    DKI_AK = os.path.abspath('DKI_AK.nii')
    DKI_RK = os.path.abspath('DKI_RK.nii')

    DKI_AWF = os.path.abspath('DKI_AWF.nii')
    DKI_TORT = os.path.abspath('DKI_TORT.nii')

    return DKI_FA, DKI_MD, DKI_AD, DKI_RD, DKI_KA, DKI_MK, DKI_AK, DKI_RK, DKI_AWF, DKI_TORT
Beispiel #8
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)))
Beispiel #9
0
def test_wmti_model_multi_voxel():
    # DKI fit
    dkiM = dki_micro.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dkiF = dkiM.fit(DWIsim)

    # Axonal Water Fraction
    sphere = get_sphere()
    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], ADE, decimal=3)
    assert_array_almost_equal(EDT[..., 1], RDE, decimal=3)
    assert_array_almost_equal(EDT[..., 2], RDE, decimal=3)
    assert_array_almost_equal(IDT[..., 0], ADI, decimal=3)
    assert_array_almost_equal(IDT[..., 1], RDI, decimal=3)
    assert_array_almost_equal(IDT[..., 2], RDI, decimal=3)

    # Test methods performance when a signal with all zeros is present
    FIEc = FIE.copy()
    RDIc = RDI.copy()
    ADIc = ADI.copy()
    ADEc = ADE.copy()
    Torc = Tor.copy()
    RDEc = RDE.copy()
    DWIsimc = DWIsim.copy()

    FIEc[0, 0, 0] = 0
    RDIc[0, 0, 0] = 0
    ADIc[0, 0, 0] = 0
    ADEc[0, 0, 0] = 0
    Torc[0, 0, 0] = 0
    RDEc[0, 0, 0] = 0
    DWIsimc[0, 0, 0, :] = 0
    mask = np.ones((2, 2, 2))
    mask[0, 0, 0] = 0

    dkiF = dkiM.fit(DWIsimc)
    awf = dki_micro.axonal_water_fraction(dkiF.model_params, sphere, gtol=1e-5)
    assert_almost_equal(awf, FIEc)

    # Extra-cellular and intra-cellular components
    edt, idt = dki_micro.diffusion_components(dkiF.model_params,
                                              sphere,
                                              awf=awf)
    EDT = eig_from_lo_tri(edt)
    IDT = eig_from_lo_tri(idt)
    assert_array_almost_equal(EDT[..., 0], ADEc, decimal=3)
    assert_array_almost_equal(EDT[..., 1], RDEc, decimal=3)
    assert_array_almost_equal(EDT[..., 2], RDEc, decimal=3)
    assert_array_almost_equal(IDT[..., 0], ADIc, decimal=3)
    assert_array_almost_equal(IDT[..., 1], RDIc, decimal=3)
    assert_array_almost_equal(IDT[..., 2], RDIc, decimal=3)

    # Check when mask is given
    dkiF = dkiM.fit(DWIsim)
    awf = dki_micro.axonal_water_fraction(dkiF.model_params,
                                          sphere,
                                          gtol=1e-5,
                                          mask=mask)
    assert_almost_equal(awf, FIEc, decimal=3)

    # Extra-cellular and intra-cellular components
    edt, idt = dki_micro.diffusion_components(dkiF.model_params,
                                              sphere,
                                              awf=awf,
                                              mask=mask)
    EDT = eig_from_lo_tri(edt)
    IDT = eig_from_lo_tri(idt)
    assert_array_almost_equal(EDT[..., 0], ADEc, decimal=3)
    assert_array_almost_equal(EDT[..., 1], RDEc, decimal=3)
    assert_array_almost_equal(EDT[..., 2], RDEc, decimal=3)
    assert_array_almost_equal(IDT[..., 0], ADIc, decimal=3)
    assert_array_almost_equal(IDT[..., 1], RDIc, decimal=3)
    assert_array_almost_equal(IDT[..., 2], RDIc, decimal=3)

    # Check class object
    wmtiM = dki_micro.KurtosisMicrostructureModel(gtab_2s, fit_method="WLS")
    wmtiF = wmtiM.fit(DWIsim, mask=mask)
    assert_almost_equal(wmtiF.awf, FIEc, decimal=3)
    assert_almost_equal(wmtiF.axonal_diffusivity, ADIc, decimal=3)
    assert_almost_equal(wmtiF.hindered_ad, ADEc, decimal=3)
    assert_almost_equal(wmtiF.hindered_rd, RDEc, decimal=3)
    assert_almost_equal(wmtiF.tortuosity, Torc, decimal=3)
Beispiel #10
0
def dkifit(dwi_file,
           bvec_file,
           bval_file,
           mask_file,
           out,
           min_kurtosis=-0.42,
           max_kurtosis=10,
           micro=False):
    """ The diffusion kurtosis model is an expansion of the diffusion tensor
    model (see Reconstruction of the diffusion signal with the Tensor model).
    In addition to the diffusion tensor (DT), the diffusion kurtosis model
    quantifies the degree to which water diffusion in biological tissues is
    non-Gaussian using the kurtosis tensor (KT) [Jensen2005].

    Measurements of non-Gaussian diffusion from the diffusion kurtosis model
    are of interest because they can be used to charaterize tissue
    microstructural heterogeneity [Jensen2010] and to derive concrete
    biophysical parameters, such as the density of axonal fibres and
    diffusion tortuosity [Fieremans2011].

    Theoretically, computing classical scalar measures from DTI and DKI
    should be analogous. However, according to recent studies, the diffusion
    statistics from the kurtosis model are expected to have better accuracy
    [Veraar2011], [NetoHe2012].

    Kurtosis measures are susceptible to high amplitude outliers. The impact
    of high amplitude kurtosis outliers can be removed by introducing as an
    optional input the extremes of the typical values of kurtosis.
    Here these are assumed to be on the range between -0.42 and 10.

    This code uses dipy.

    Parameters
    ----------
    dwi_file: str (mandatory)
        Diffusion weighted image data file (can be multi-shell).
        A 4D series of data volumes.
    bvec_file: str (mandatory)
        b vectors file.
        Gradient directions.
        An ASCII text file containing a list of gradient directions applied
        during diffusion weighted volumes. The order of entries in this file
        must match the order of volumes in the input data series.
    bval_file: str (mandatory)
        b values file.
        An ASCII text file containing a list of b values applied during each
        volume acquisition. The order of entries in this file must match the
        order of volumes in the input data and entries in the gradient
        directions text file.
    mask_file: str (mandatory)
        Brain binary mask file (i.e. from BET).
        A single binarized volume in diffusion space containing ones inside the
        brain and zeros outside the brain.
    out: str (mandatory)
        User specifies a basename that will be used to name the outputs.
    min_kurtosis: float, default -0.42
        To keep kurtosis values within a plausible biophysical range, mean
        kurtosis values that are smaller than `min_kurtosis` are replaced
        with `min_kurtosis`.
    max_kurtosis: float, default 10
        To keep kurtosis values within a plausible biophysical range, mean
        kurtosis values that are larger than `max_kurtosis` are replaced
        with `max_kurtosis`.
    micro: bool, default False
        If set, estimate yhe DKI based microstructural model.

    Returns
    -------
    fa_file: str
        the fractional anisotropy (FA).
    md_file: str
        the mean diffusivity (MD).
    ad_file: str
        the axial diffusivity (AD).
    rd_file: str
        the radial diffusivity (RD).
    ci_file: str
        the lineraity, planarity and sphericity Westion shapes.
    mk_file: str
        the non-Gaussian measures of mean kurtosis (MK).
    ak_file: str
        the axial kurtosis (AK).
    rk_file: str
        the radial kurtosis (RK)
    dkimask_file: str
        well-aligned fiber mask.
    dkiawf_file: str
        the Axonal water fraction (AWF).
    dkitortuosity_file: str
        the tortuosity.
    """
    # Load the image
    dwi_image = nibabel.load(dwi_file)
    mask_image = nibabel.load(mask_file)

    # Smooth the data
    data = dwi_image.get_data()
    fwhm = 1.25
    gauss_std = fwhm / numpy.sqrt(8 * numpy.log(2))
    data_smooth = numpy.zeros(data.shape)
    for indx in range(data.shape[-1]):
        data_smooth[..., indx] = gaussian_filter(data[..., indx],
                                                 sigma=gauss_std)

    # Load the bvalues and bvectors
    bvals, bvecs = read_bvals_bvecs(bval_file, bvec_file)
    gtab = gradient_table(bvals, bvecs)

    # Create/fit the model
    model = dki.DiffusionKurtosisModel(gtab, fit_method="WLS")
    fit = model.fit(data_smooth, mask=mask_image.get_data())

    # Get the tensor part scalars
    kt_image = nibabel.Nifti1Image(fit.kt, affine=dwi_image.affine)
    dkikt_file = os.path.join(out, "dki_kt.nii.gz")
    nibabel.save(kt_image, dkikt_file)
    fa_image = nibabel.Nifti1Image(fit.fa, affine=dwi_image.affine)
    dkifa_file = os.path.join(out, "dki_fa.nii.gz")
    nibabel.save(fa_image, dkifa_file)
    md_image = nibabel.Nifti1Image(fit.md, affine=dwi_image.affine)
    dkimd_file = os.path.join(out, "dki_md.nii.gz")
    nibabel.save(md_image, dkimd_file)
    ad_image = nibabel.Nifti1Image(fit.ad, affine=dwi_image.affine)
    dkiad_file = os.path.join(out, "dki_ad.nii.gz")
    nibabel.save(ad_image, dkiad_file)
    rd_image = nibabel.Nifti1Image(fit.rd, affine=dwi_image.affine)
    dkird_file = os.path.join(out, "dki_rd.nii.gz")
    nibabel.save(rd_image, dkird_file)
    cl_image = nibabel.Nifti1Image(fit.linearity, affine=dwi_image.affine)
    dkicl_file = os.path.join(out, "dki_cl.nii.gz")
    nibabel.save(cl_image, dkicl_file)
    cp_image = nibabel.Nifti1Image(fit.planarity, affine=dwi_image.affine)
    dkicp_file = os.path.join(out, "dki_cp.nii.gz")
    nibabel.save(cp_image, dkicp_file)
    cs_image = nibabel.Nifti1Image(fit.sphericity, affine=dwi_image.affine)
    dkics_file = os.path.join(out, "dki_cs.nii.gz")
    nibabel.save(cs_image, dkics_file)

    # Get the kutosis part scalars
    mk_image = nibabel.Nifti1Image(fit.mk(min_kurtosis, max_kurtosis),
                                   affine=dwi_image.affine)
    dkimk_file = os.path.join(out, "dki_mk.nii.gz")
    nibabel.save(mk_image, dkimk_file)
    ak_image = nibabel.Nifti1Image(fit.ak(min_kurtosis, max_kurtosis),
                                   affine=dwi_image.affine)
    dkiak_file = os.path.join(out, "dki_ak.nii.gz")
    nibabel.save(ak_image, dkiak_file)
    rk_image = nibabel.Nifti1Image(fit.rk(min_kurtosis, max_kurtosis),
                                   affine=dwi_image.affine)
    dkirk_file = os.path.join(out, "dki_rk.nii.gz")
    nibabel.save(rk_image, dkirk_file)

    # Estimate the microstructural model if requested
    dkimask_file, dkiawf_file, dkitortuosity_file = None, None, None
    if micro:

        # Create a white matter mask based on the westin shapes
        # Fieremans et al. [Fieremans2011]
        well_aligned_mask = numpy.ones(dwi_image.shape[:-1], dtype="bool")
        cl = fit.linearity.copy()
        well_aligned_mask[cl < 0.4] = False
        cp = fit.planarity.copy()
        well_aligned_mask[cp > 0.2] = False
        cs = fit.sphericity.copy()
        well_aligned_mask[cs > 0.35] = False

        # Removing nan associated with background voxels
        well_aligned_mask[numpy.isnan(cl)] = False
        well_aligned_mask[numpy.isnan(cp)] = False
        well_aligned_mask[numpy.isnan(cs)] = False

        # Save mask
        mask_image = nibabel.Nifti1Image(well_aligned_mask.astype(int),
                                         affine=dwi_image.affine)
        dkimask_file = os.path.join(out, "dki_mask.nii.gz")
        nibabel.save(mask_image, dkimask_file)

        # Create/fit the model
        micro_model = dki_micro.KurtosisMicrostructureModel(gtab)
        micro_fit = micro_model.fit(data_smooth, mask=well_aligned_mask)

        # Get scalars
        awf_image = nibabel.Nifti1Image(micro_fit.awf, affine=dwi_image.affine)
        dkiawf_file = os.path.join(out, "dki_awf.nii.gz")
        nibabel.save(awf_image, dkiawf_file)
        tortuosity_image = nibabel.Nifti1Image(micro_fit.tortuosity,
                                               affine=dwi_image.affine)
        dkitortuosity_file = os.path.join(out, "dki_tortuosity.nii.gz")
        nibabel.save(tortuosity_image, dkitortuosity_file)

    return (dkikt_file, dkifa_file, dkimd_file, dkiad_file, dkird_file,
            dkicl_file, dkicp_file, dkics_file, dkimk_file, dkiak_file,
            dkirk_file, dkimask_file, dkiawf_file, dkitortuosity_file)