示例#1
0
def test_dki_errors():

    # first error of DKI module is if a unknown fit method is given
    assert_raises(ValueError, dki.DiffusionKurtosisModel, gtab_2s,
                  fit_method="JOANA")

    # second error of DKI module is if a min_signal is defined as negative
    assert_raises(ValueError, dki.DiffusionKurtosisModel, gtab_2s,
                  min_signal=-1)
    # try case with correct min_signal
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, min_signal=1)
    dkiF = dkiM.fit(DWI)
    assert_array_almost_equal(dkiF.model_params, multi_params)

    # third error is if a given mask do not have same shape as data
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)

    # test a correct mask
    dkiF = dkiM.fit(DWI)
    mask_correct = dkiF.fa > 0
    mask_correct[1, 1] = False
    multi_params[1, 1] = np.zeros(27)
    mask_not_correct = np.array([[True, True, False], [True, False, False]])
    dkiF = dkiM.fit(DWI, mask=mask_correct)
    assert_array_almost_equal(dkiF.model_params, multi_params)
    # test a incorrect mask
    assert_raises(ValueError, dkiM.fit, DWI, mask=mask_not_correct)

    # error if data with only one non zero b-value is given
    assert_raises(ValueError, dki.DiffusionKurtosisModel, gtab)
示例#2
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)
示例#3
0
    def fit(self):
        """
        Fits a dki model to the data
            Standard DTI measures (FA,MD,RD,AD) are calculated from the DKI model, accounting for additional variance.
            DKI measures of MK,RK,AK are computed from the DKI model.
            Residual image has the same dimensions as the original input image. Calculated as |Avg(B0_volumes)-predicted_image|
            Noise is equal to the stdev across volumes of the residual image, and SNR is Avg(B0_volumes)/Noise, removing NaNs.
        """
        data = self.data.get_data()

        #Generate the dk model
        print("Generating the models.")
        dkimodel = dki.DiffusionKurtosisModel(self.gradient_table)
        print("Fitting the data.")
        self.dki_fitted = dkimodel.fit(data)

        #Generate the lower-triangular dataset
        print("Generating the kurtosis tensor data.")
        self.out_dti = nib.nifti1.Nifti1Image(self.dki_fitted.lower_triangular(), self.data.get_affine())
        self.out_dki = nib.nifti1.Nifti1Image(self.dki_fitted.kt, self.data.get_affine())

        #Generate the residuals
        if self.out_residual_path != None or self.out_noise_path != None or self.out_snr_path != None:
            print("Estimating input data.")
            estimate_data = self.dki_fitted.predict(self.gradient_table, S0=self.b0_average)
            print("Calculating residuals.")
            residuals = np.absolute(data - estimate_data)
            noise = np.std(residuals, axis=3)
            snr = np.nan_to_num(self.b0_average / noise)
            self.out_residual = nib.nifti1.Nifti1Image(residuals.astype(np.float32), self.data.get_affine())
            self.out_noise = nib.nifti1.Nifti1Image(noise.astype(np.float32), self.data.get_affine())
            self.out_snr = nib.nifti1.Nifti1Image(snr.astype(np.float32), self.data.get_affine())
示例#4
0
def DKE_by_slice(data, gtab, slices='all'):
    """
    Fits the DKE model by slice to decrease memory requirements
    Do all slices, or array subset thereof
    """
    import dipy.reconst.dki as dki
    import numpy as np

    print('Creating diffusion kurtosis model')
    dkimodel = dki.DiffusionKurtosisModel(gtab)
    n_contrasts = 3  #number of contrasts that we are going to have output from the dki model

    out_data = np.zeros(
        list(np.shape(data)[0:3]) +
        [n_contrasts])  #replace the diff dir axis with our own for the results
    if slices is 'all':
        slices = np.arange(0, np.shape(data)[2])
    print("Performing diffusion kurtosis estimation by slice: "),
    #lets loop across the z dimension - index 2
    for zslice in slices:
        print(zslice),
        slice_d = data[:, :, zslice, :]

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

        #assign to our out_data
        out_data[:, :, zslice, 0] = MK
        out_data[:, :, zslice, 1] = AK
        out_data[:, :, zslice, 2] = RK
    print("")
    return out_data
def fit_dki(dwi, blur=False):
    """Fit a DKI model to a DWI, applying a mask if provided.

    Parameters
    ---------
    dwi : DiffusionWeightedImage 
        DWI data to fit to the model.
    blur : bool, optional
        True if the image should be blurred before the model fit.

    Returns
    -------
    dwifit : DiffusionKurtosisFit
        A fit from which parameter maps can be generated
    """

    dkimodel = dki.DiffusionKurtosisModel(dwi.gtab)

    data = dwi.get_image()

    if blur:
        data = ndi.gaussian_filter(data, [0.5, 0.5, 0, 0])

    try:
        mask = dwi.mask
    except AttributeError:
        mask = np.ones(data.shape[:3])

    return dkimodel.fit(data, mask)
示例#6
0
def test_dki_predict():
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    pred = dkiM.predict(crossing_ref, S0=100)

    assert_array_almost_equal(pred, signal_cross)

    # just to check that it works with more than one voxel:
    pred_multi = dkiM.predict(multi_params, S0=100)
    assert_array_almost_equal(pred_multi, DWI)

    # Check that it works with more than one voxel, and with a different S0
    # in each voxel:
    pred_multi = dkiM.predict(multi_params,
                              S0=100*np.ones(pred_multi.shape[:3]))
    assert_array_almost_equal(pred_multi, DWI)

    # check the function predict of the DiffusionKurtosisFit object
    dkiF = dkiM.fit(DWI)
    pred_multi = dkiF.predict(gtab_2s, S0=100)
    assert_array_almost_equal(pred_multi, DWI)

    dkiF = dkiM.fit(pred_multi)
    pred_from_fit = dkiF.predict(dkiM.gtab, S0=100)
    assert_array_almost_equal(pred_from_fit, DWI)

    # Test the module function:
    pred = dki.dki_prediction(crossing_ref, gtab_2s, S0=100)
    assert_array_almost_equal(pred, signal_cross)

    # Test the module function with S0 volume:
    pred = dki.dki_prediction(multi_params, gtab_2s,
                              S0=100 * np.ones(multi_params.shape[:3]))
    assert_array_almost_equal(pred, DWI)
示例#7
0
def test_split_dki_param():
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="OLS")
    dkiF = dkiM.fit(DWI)
    evals, evecs, kt = dki.split_dki_param(dkiF.model_params)

    assert_array_almost_equal(evals, dkiF.evals)
    assert_array_almost_equal(evecs, dkiF.evecs)
    assert_array_almost_equal(kt, dkiF.kt)
示例#8
0
文件: test_dki.py 项目: davhunt/dipy
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)
示例#9
0
def test_dki_predict():
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    pred = dkiM.predict(crossing_ref, S0=100)

    assert_array_almost_equal(pred, signal_cross)

    # just to check that it works with more than one voxel:
    pred_multi = dkiM.predict(multi_params, S0=100)
    assert_array_almost_equal(pred_multi, DWI)
示例#10
0
def test_dki_fits():
    """ DKI fits are tested on noise free crossing fiber simulates """

    # OLS fitting
    dkiM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="OLS")
    dkiF = dkiM.fit(signal_cross)

    assert_array_almost_equal(dkiF.model_params, crossing_ref)

    # WLS fitting
    dki_wlsM = dki.DiffusionKurtosisModel(gtab_2s, fit_method="WLS")
    dki_wlsF = dki_wlsM.fit(signal_cross)

    assert_array_almost_equal(dki_wlsF.model_params, crossing_ref)

    # testing multi-voxels
    dkiF_multi = dkiM.fit(DWI)
    assert_array_almost_equal(dkiF_multi.model_params, multi_params)

    dkiF_multi = dki_wlsM.fit(DWI)
    assert_array_almost_equal(dkiF_multi.model_params, multi_params)
示例#11
0
def test_dki_predict():
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    pred = dkiM.predict(crossing_ref, S0=100)

    assert_array_almost_equal(pred, signal_cross)

    # just to check that it works with more than one voxel:
    pred_multi = dkiM.predict(multi_params, S0=100)
    assert_array_almost_equal(pred_multi, DWI)

    # check the function predict of the DiffusionKurtosisFit object
    dkiF = dkiM.fit(DWI)
    pred_multi = dkiF.predict(gtab, S0=100)
    assert_array_almost_equal(pred_multi, DWI[:, :, :, :65])
示例#12
0
文件: test_dki.py 项目: koendc/dipy
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)
示例#13
0
文件: test_dki.py 项目: koendc/dipy
def test_compare_MK_method():
    # tests if analytical solution of MK is equal to the average of directional
    # kurtosis sampled from a sphere

    # DKI Model fitting
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    dkiF = dkiM.fit(signal_cross)

    # MK analytical solution
    MK_as = dkiF.mk(None, None, analytical=True)

    # MK numerical method
    MK_nm = dkiF.mk(None, None, analytical=False)

    assert_array_almost_equal(MK_as, MK_nm, decimal=3)
示例#14
0
文件: test_dki.py 项目: koendc/dipy
def test_compare_RK_methods():
    # tests if analytical solution of RK is equal to the perpendicular kurtosis
    # relative to the first diffusion axis

    # DKI Model fitting
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    dkiF = dkiM.fit(signal_cross)

    # RK analytical solution
    RK_as = dkiF.rk(analytical=True)

    # RK numerical method
    RK_nm = dkiF.rk(analytical=False)

    assert_array_almost_equal(RK_as, RK_nm)
示例#15
0
文件: test_dki.py 项目: davhunt/dipy
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)
示例#16
0
def test_compare_MK_method():
    # tests if analytical solution of MK is equal to the average of directional
    # kurtosis sampled from a sphere

    # DKI Model fitting
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    dkiF = dkiM.fit(signal_cross)

    # MK analytical solution
    MK_as = dkiF.mk()

    # MK numerical method
    sph = Sphere(xyz=gtab.bvecs[gtab.bvals > 0])
    MK_nm = np.mean(dki.apparent_kurtosis_coef(dkiF.model_params, sph),
                    axis=-1)

    assert_array_almost_equal(MK_as, MK_nm, decimal=1)
示例#17
0
def test_compare_RK_methods():
    # tests if analytical solution of RK is equal to the perpendicular kurtosis
    # relative to the first diffusion axis

    # DKI Model fitting
    dkiM = dki.DiffusionKurtosisModel(gtab_2s)
    dkiF = dkiM.fit(signal_cross)

    # MK analytical solution
    RK_as = dkiF.rk()

    # MK numerical method
    evecs = dkiF.evecs
    p_dir = perpendicular_directions(evecs[:, 0], num=30, half=True)
    ver = Sphere(xyz=p_dir)
    RK_nm = np.mean(dki.apparent_kurtosis_coef(dkiF.model_params, ver),
                    axis=-1)

    assert_array_almost_equal(RK_as, RK_nm)
示例#18
0
def fit_dki(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.DiffusionKurtosisModel(gtab)
    dkifit = dkimodel.fit(data, mask=mask)

    FA = dkifit.fa
    MD = dkifit.md
    AD = dkifit.ad
    RD = dkifit.rd
    MK = dkifit.mk(min_kurtosis, max_kurtosis)
    AK = dkifit.ak(min_kurtosis, max_kurtosis)
    RK = dkifit.rk(min_kurtosis, max_kurtosis)
    params = dkifit.model_params

    maps = [FA, MD, AD, RD, MK, AK, RK, params]
    names = ['FA', 'MD', 'AD', 'RD', 'MK', 'AK', 'RK', '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, 'dki_%s.nii.gz' % n)
        nib.save(nib.Nifti1Image(m, aff), file_paths[n])

    return file_paths
示例#19
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)
示例#20
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)
示例#21
0
def calc_cod1000(subject):
    s3 = boto3.resource('s3')
    boto3.setup_default_session(profile_name='cirrus')
    bucket = s3.Bucket('hcp-dki')
    path_dti = '%s/%s_cod_dti_1000.nii.gz' % (subject, subject)
    path_dki = '%s/%s_cod_dki_1000.nii.gz' % (subject, subject)
    if not (exists(path_dti, bucket.name) and exists(path_dki, bucket.name)):
        print("File doesn't exist - going ahead")
        with tempfile.TemporaryDirectory() as tempdir:
            try:
                bucket = setup_boto()
                dwi_file = op.join(tempdir, 'data.nii.gz')
                bvec_file = op.join(tempdir, 'data.bvec')
                bval_file = op.join(tempdir, 'data.bval')

                data_files = {}

                data_files[dwi_file] = \
                    'HCP_900/%s/T1w/Diffusion/data.nii.gz' % subject
                data_files[bvec_file] = \
                    'HCP_900/%s/T1w/Diffusion/bvecs' % subject
                data_files[bval_file] = \
                    'HCP_900/%s/T1w/Diffusion/bvals' % subject
                for k in data_files.keys():
                    if not op.exists(k):
                        bucket.download_file(data_files[k], k)

                wm_file = op.join(tempdir, 'wm.nii.gz')
                boto3.setup_default_session(profile_name='cirrus')
                s3 = boto3.resource('s3')
                bucket = s3.Bucket('hcp-dki')

                s3.meta.client.download_file(
                    'hcp-dki',
                    '%s/%s_white_matter_mask.nii.gz' % (subject, subject),
                    wm_file)
                wm_mask = nib.load(wm_file).get_data().astype(bool)
                dwi_img = nib.load(dwi_file)
                data = dwi_img.get_data()
                bvals = np.loadtxt(bval_file)
                bvecs = np.loadtxt(bvec_file)
                idx = bvals < 1985

                if not exists(path_dki, bucket.name):
                    gtab = dpg.gradient_table(bvals, bvecs, b0_threshold=10)
                    dki_model = dki.DiffusionKurtosisModel(gtab)
                    # Use all the data to calculate the mode
                    pred = xval.kfold_xval(dki_model, data, 5, mask=wm_mask)
                    # But compare only on the b=1000 shell (same as DTI):
                    cod = xval.coeff_of_determination(pred[..., idx],
                                                      data[..., idx])
                    cod_file = op.join(tempdir, 'cod_dki_1000.nii.gz')
                    nib.save(nib.Nifti1Image(cod, dwi_img.affine), cod_file)
                    s3.meta.client.upload_file(cod_file, 'hcp-dki', path_dki)

                if not exists(path_dti, bucket.name):
                    data = data[..., idx]
                    gtab = dpg.gradient_table(bvals[idx],
                                              bvecs[:, idx].squeeze(),
                                              b0_threshold=10)

                    model = dti.TensorModel(gtab)
                    pred = xval.kfold_xval(model, data, 5, mask=wm_mask)
                    cod = xval.coeff_of_determination(pred, data)
                    cod_file = op.join(tempdir, 'cod_dti_1000.nii.gz')
                    nib.save(nib.Nifti1Image(cod, dwi_img.affine), cod_file)
                    s3.meta.client.upload_file(cod_file, 'hcp-dki', path_dti)

                return subject, True
            except Exception as err:
                return subject, err.args
    else:
        return subject, True
示例#22
0
def make_maps(subject):

    s3 = boto3.resource('s3')
    boto3.setup_default_session(profile_name='cirrus')
    bucket = s3.Bucket('hcp-dki')
    path = '%s/%s_dki_1000_3000_MK.nii.gz' % (subject, subject)
    if not exists(path, bucket.name):

        with tempfile.TemporaryDirectory() as tempdir:
            try:
                bucket = setup_boto()
                dwi_file = op.join(tempdir, 'data.nii.gz')
                bvec_file = op.join(tempdir, 'data.bvec')
                bval_file = op.join(tempdir, 'data.bval')

                data_files = {}

                data_files[dwi_file] = \
                    'HCP_900/%s/T1w/Diffusion/data.nii.gz' % subject
                data_files[bvec_file] = \
                    'HCP_900/%s/T1w/Diffusion/bvecs' % subject
                data_files[bval_file] = \
                    'HCP_900/%s/T1w/Diffusion/bvals' % subject
                for k in data_files.keys():
                    if not op.exists(k):
                        bucket.download_file(data_files[k], k)

                wm_file = op.join(tempdir, 'wm.nii.gz')
                boto3.setup_default_session(profile_name='cirrus')
                s3 = boto3.resource('s3')
                bucket = s3.Bucket('hcp-dki')

                s3.meta.client.download_file(
                    'hcp-dki',
                    '%s/%s_white_matter_mask.nii.gz' % (subject, subject),
                    wm_file)
                wm_mask = nib.load(wm_file).get_data().astype(bool)
                dwi_img = nib.load(dwi_file)
                data = dwi_img.get_data()
                bvals = np.loadtxt(bval_file)
                bvecs = np.loadtxt(bvec_file)
                gtab = dpg.gradient_table(bvals, bvecs)
                idx1000 = ((gtab.bvals < 1100) | (gtab.bvals <= 5))
                idx2000 = (((gtab.bvals > 1100) & (gtab.bvals < 2100)) |
                           (gtab.bvals <= 5))
                idx3000 = ((gtab.bvals > 2100) | (gtab.bvals <= 5))
                data1000 = data[..., idx1000]
                data2000 = data[..., idx2000]
                data3000 = data[..., idx3000]
                data1000_2000 = data[..., idx1000 + idx2000]
                data1000_3000 = data[..., idx1000 + idx3000]
                data2000_3000 = data[..., idx2000 + idx3000]
                gtab1000 = dpg.gradient_table(gtab.bvals[idx1000],
                                              gtab.bvecs[idx1000],
                                              b0_threshold=10)
                gtab2000 = dpg.gradient_table(gtab.bvals[idx1000],
                                              gtab.bvecs[idx1000],
                                              b0_threshold=10)
                gtab3000 = dpg.gradient_table(gtab.bvals[idx1000],
                                              gtab.bvecs[idx1000],
                                              b0_threshold=10)
                gtab1000_2000 = dpg.gradient_table(
                    gtab.bvals[idx1000 + idx2000],
                    gtab.bvecs[idx1000 + idx2000],
                    b0_threshold=10)
                gtab1000_3000 = dpg.gradient_table(
                    gtab.bvals[idx1000 + idx3000],
                    gtab.bvecs[idx1000 + idx3000],
                    b0_threshold=10)
                gtab2000_3000 = dpg.gradient_table(
                    gtab.bvals[idx2000 + idx3000],
                    gtab.bvecs[idx2000 + idx3000],
                    b0_threshold=10)

                dti_model1000 = dti.TensorModel(gtab1000)
                dti_model2000 = dti.TensorModel(gtab2000)
                dti_model3000 = dti.TensorModel(gtab3000)
                dti_model1000_2000 = dti.TensorModel(gtab1000_2000)
                dti_model1000_3000 = dti.TensorModel(gtab1000_3000)
                dti_model2000_3000 = dti.TensorModel(gtab2000_3000)
                dti_fit1000 = dti_model1000.fit(data1000, mask=wm_mask)
                dti_fit2000 = dti_model2000.fit(data2000, mask=wm_mask)
                dti_fit3000 = dti_model3000.fit(data3000, mask=wm_mask)
                dti_fit1000_2000 = dti_model1000_2000.fit(data1000_2000,
                                                          mask=wm_mask)
                dti_fit1000_3000 = dti_model1000_3000.fit(data1000_3000,
                                                          mask=wm_mask)
                dti_fit2000_3000 = dti_model2000_3000.fit(data2000_3000,
                                                          mask=wm_mask)
                for FA, fa_file in zip([
                        dti_fit1000.fa, dti_fit2000.fa, dti_fit3000.fa,
                        dti_fit1000_2000.fa, dti_fit2000_3000.fa,
                        dti_fit1000_3000.fa
                ], [
                        '%s_dti_1000_FA.nii.gz' % subject,
                        '%s_dti_2000_FA.nii.gz' % subject,
                        '%s_dti_3000_FA.nii.gz' % subject,
                        '%s_dti_1000_2000_FA.nii.gz' % subject,
                        '%s_dti_2000_3000_FA.nii.gz' % subject,
                        '%s_dti_1000_3000_FA.nii.gz' % subject,
                ]):
                    nib.save(nib.Nifti1Image(FA, dwi_img.affine),
                             op.join(tempdir, fa_file))
                    s3.meta.client.upload_file(op.join(tempdir,
                                                       fa_file), 'hcp-dki',
                                               '%s/%s' % (subject, fa_file))

                for MD, md_file in zip([
                        dti_fit1000.md, dti_fit2000.md, dti_fit3000.md,
                        dti_fit1000_2000.md, dti_fit2000_3000.md,
                        dti_fit1000_3000.md
                ], [
                        '%s_dti_1000_MD.nii.gz' % subject,
                        '%s_dti_2000_MD.nii.gz' % subject,
                        '%s_dti_3000_MD.nii.gz' % subject,
                        '%s_dti_1000_2000_MD.nii.gz' % subject,
                        '%s_dti_2000_3000_MD.nii.gz' % subject,
                        '%s_dti_1000_3000_MD.nii.gz' % subject,
                ]):
                    nib.save(nib.Nifti1Image(MD, dwi_img.affine),
                             op.join(tempdir, md_file))
                    s3.meta.client.upload_file(op.join(tempdir,
                                                       md_file), 'hcp-dki',
                                               '%s/%s' % (subject, md_file))

                dki_model1000_2000 = dki.DiffusionKurtosisModel(gtab1000_2000)
                dki_model1000_3000 = dki.DiffusionKurtosisModel(gtab1000_3000)
                dki_model2000_3000 = dki.DiffusionKurtosisModel(gtab2000_3000)
                dki_fit1000_2000 = dki_model1000_2000.fit(data1000_2000)
                dki_fit1000_3000 = dki_model1000_3000.fit(data1000_3000)
                dki_fit2000_3000 = dki_model2000_3000.fit(data2000_3000)

                for FA, fa_file in zip([
                        dki_fit1000_2000.fa, dki_fit2000_3000.fa,
                        dki_fit1000_3000.fa
                ], [
                        '%s_dki_1000_2000_FA.nii.gz' % subject,
                        '%s_dki_2000_3000_FA.nii.gz' % subject,
                        '%s_dki_1000_3000_FA.nii.gz' % subject,
                ]):
                    nib.save(nib.Nifti1Image(FA, dwi_img.affine),
                             op.join(tempdir, fa_file))
                    s3.meta.client.upload_file(op.join(tempdir,
                                                       fa_file), 'hcp-dki',
                                               '%s/%s' % (subject, fa_file))

                for MD, md_file in zip([
                        dki_fit1000_2000.md, dki_fit2000_3000.md,
                        dki_fit1000_3000.md
                ], [
                        '%s_dki_1000_2000_MD.nii.gz' % subject,
                        '%s_dki_2000_3000_MD.nii.gz' % subject,
                        '%s_dki_1000_3000_MD.nii.gz' % subject,
                ]):
                    nib.save(nib.Nifti1Image(MD, dwi_img.affine),
                             op.join(tempdir, md_file))
                    s3.meta.client.upload_file(op.join(tempdir,
                                                       md_file), 'hcp-dki',
                                               '%s/%s' % (subject, md_file))

                for MK, mk_file in zip([
                        dki_fit1000_2000.mk(),
                        dki_fit2000_3000.mk(),
                        dki_fit1000_3000.mk()
                ], [
                        '%s_dki_1000_2000_MK.nii.gz' % subject,
                        '%s_dki_2000_3000_MK.nii.gz' % subject,
                        '%s_dki_1000_3000_MK.nii.gz' % subject,
                ]):
                    nib.save(nib.Nifti1Image(MK, dwi_img.affine),
                             op.join(tempdir, mk_file))
                    s3.meta.client.upload_file(op.join(tempdir,
                                                       mk_file), 'hcp-dki',
                                               '%s/%s' % (subject, mk_file))
                return subject, True
            except Exception as err:
                return subject, err.args
    else:
        return subject, True
示例#23
0
    def main(self):

        self.imgFile = str(self.imgFile)
        self.maskFile = str(self.maskFile)

        self.mk_low_high = [
            float(x) for x in self.mk_low_high[1:-1].split(',')
        ]
        self.mk_low_high.sort()
        self.fa_low_high = [
            float(x) for x in self.fa_low_high[1:-1].split(',')
        ]
        self.fa_low_high.sort()
        self.md_low_high = [
            float(x) for x in self.md_low_high[1:-1].split(',')
        ]
        self.md_low_high.sort()
        hdr = None
        affine = None

        if not self.out_dir:
            self.out_dir = os.path.dirname(self.imgFile)

        outPrefix = os.path.join(self.out_dir,
                                 os.path.basename(self.imgFile).split('.')[0])

        if self.imgFile.endswith('.nii.gz') or self.imgFile.endswith('.nii'):
            bvals, bvecs = read_bvals_bvecs(self.bvalFile, self.bvecFile)
            outFormat = '.nii.gz'

            img = nib.load(self.imgFile)
            data = img.get_data()

            affine = img.affine
            grad_axis = 3
            if len(data.shape) != 4:
                raise AttributeError('Not a valid dwi, check dimension')

        elif self.imgFile.endswith('.nrrd') or self.imgFile.endswith('.nhdr'):

            img = nrrd.read(self.imgFile)
            data = img[0]
            hdr = img[1]

            outFormat = '.nrrd'

            bvals, bvecs, b_max, grad_axis, N = nrrd_bvals_bvecs(hdr)

            # put the gradients along last axis
            if grad_axis != 3:
                data = np.moveaxis(data, grad_axis, 3)

        # provide the user a liberty to specify different file formats for dwi and mask
        if self.maskFile.endswith('.nii.gz') or self.maskFile.endswith('.nii'):
            mask_data = nib.load(self.maskFile).get_data()

        elif self.maskFile.endswith('.nrrd') or self.maskFile.endswith(
                '.nhdr'):
            mask_data = nrrd.read(self.maskFile)[0]

        data = applymask(data, mask_data)

        gtab = gradient_table(bvals, bvecs)

        dtimodel = dti.TensorModel(gtab)
        dtifit = dtimodel.fit(data, mask_data)
        evals = dtifit.evals
        fa = dtifit.fa
        md = dtifit.md
        ad = dtifit.ad
        rd = dtifit.rd
        evals_zero = evals < 0.
        evals_zero_mask = (evals_zero[..., 0] | evals_zero[..., 1]
                           | evals_zero[..., 2]) * 1

        mkFlag = check_multi_b(gtab, n_bvals=3)
        if mkFlag:
            dkimodel = dki.DiffusionKurtosisModel(gtab)
            dkifit = dkimodel.fit(data, mask_data)
            mk = dkifit.mk(
                0, 3)  # http://nipy.org/dipy/examples_built/reconst_dki.html

        else:
            warnings.warn(
                "DIPY DKI requires at least 3 b-shells (which can include b=0), "
                "kurtosis quality cannot be computed.")

        fa_mask = mask_calc(fa, self.fa_low_high)
        md_mask = mask_calc(md, self.md_low_high)

        where_b0s = np.where(bvals == 0)[0]
        where_dwi = np.where(bvals != 0)[0]
        bse_data = data[..., where_b0s].mean(-1)
        b0File = outPrefix + '_b0' + outFormat
        save_map(b0File, bse_data, affine, hdr)

        # prevent division by zero during normalization
        bse_data[bse_data < 1] = 1.
        extend_bse = np.expand_dims(bse_data, grad_axis)
        extend_bse = np.repeat(extend_bse, len(where_dwi), grad_axis)
        curtail_dwi = np.take(data, where_dwi, axis=grad_axis)

        # 1 / b0 * min(b0 - Gi)
        minOverGrads = np.min(extend_bse - curtail_dwi,
                              axis=grad_axis) / bse_data

        # another way to prevent division by zero: 1/b0 * min(b0-Gi) with condition at b0~eps
        # minOverGrads = np.min(extend_bse - curtail_dwi, axis=grad_axis) / (bse_data + eps)
        # minOverGrads[(bse_data < eps) & (minOverGrads < 5 * eps)] = 0.
        # minOverGrads[(bse_data < eps) & (minOverGrads > 5 * eps)] = 10.

        minOverGradsNegativeMask = (minOverGrads < 0) * 1

        # compute histograms
        print('\nminOverGrads (b0-Gi)/b0 histogram')
        bins = [-inf, 0, inf]
        negative, _ = hist_calc(minOverGrads, bins)

        print('\nevals<0 histogram')
        bins = [-inf, 0, inf]
        hist_calc(evals, bins)

        print('\nfractional anisotropy histogram')
        bins = form_bins(self.fa_low_high)
        hist_calc(fa, bins)

        print('\nmean diffusivity histogram')
        bins = form_bins(self.md_low_high)
        hist_calc(md, bins)

        if mkFlag:
            print('\nmean kurtosis mask')
            bins = form_bins(self.mk_low_high)
            hist_calc(mk, bins)

        # save histograms
        print('\nCreating minOverGrads image ...')
        save_map(outPrefix + '_minOverGrads' + outFormat, minOverGrads, affine,
                 hdr)
        print('\nCreating minOverGrads<0 mask ...')
        save_map(outPrefix + '_minOverGradsMask' + outFormat,
                 minOverGradsNegativeMask.astype('short'), affine, hdr)

        print('\nCreating evals<0 mask ...')
        save_map(outPrefix + '_evalsZeroMask' + outFormat,
                 evals_zero_mask.astype('short'), affine, hdr)

        if mkFlag:
            mk_mask = mask_calc(mk, self.mk_low_high)
            print('\nCreating mk image ...')
            save_map(outPrefix + '_MK' + outFormat, mk, affine, hdr)
            print('Creating mk out of range mask ...')
            save_map(outPrefix + '_MK_mask' + outFormat,
                     mk_mask.astype('short'), affine, hdr)
        else:
            mk = np.zeros(fa.shape)

        print('\nCreating fa image ...')
        save_map(outPrefix + '_FA' + outFormat, fa, affine, hdr)
        print('Creating fa out of range mask ...')
        save_map(outPrefix + '_FA_mask' + outFormat, fa_mask.astype('short'),
                 affine, hdr)

        print('\nCreating md image ....')
        save_map(outPrefix + '_MD' + outFormat, md, affine, hdr)
        print('Creating md out of range mask ...')
        save_map(outPrefix + '_MD_mask' + outFormat, md_mask.astype('short'),
                 affine, hdr)

        # conclusion
        N_mask = mask_data.size
        print('\n\nConclusion: ')
        print('The masked dwi has %.5f%% voxels with values less than b0' %
              (negative * 100))
        print('The masked dwi has %.5f%% voxels with negative eigen value' %
              (evals_zero_mask.sum() / N_mask * 100))
        print('The masked dwi has %.5f%% voxels with FA out of [%f,%f]' %
              (fa_mask.sum() / N_mask * 100, self.fa_low_high[0],
               self.fa_low_high[1]))
        print('The masked dwi has %.5f%% voxels with MD out of [%f,%f]' %
              (md_mask.sum() / N_mask * 100, self.md_low_high[0],
               self.md_low_high[1]))
        if mkFlag:
            print('The masked dwi has %.5f%% voxels with MK out of [%f,%f]' %
                  (mk_mask.sum() / N_mask * 100, self.mk_low_high[0],
                   self.mk_low_high[1]))

        # perform roi based analysis
        if self.template and self.labelMap:
            antsReg(b0File, self.maskFile, self.template, outPrefix)
            warp = outPrefix + '1Warp.nii.gz'
            trans = outPrefix + '0GenericAffine.mat'
            outLabelMapFile = outPrefix + '_labelMap.nii.gz'
            applyXform(self.labelMap,
                       b0File,
                       warp,
                       trans,
                       outLabelMapFile,
                       interp='NearestNeighbor')
            rm = local['rm']
            rm(warp, trans, outPrefix + 'Warped.nii.gz',
               outPrefix + '1InverseWarp.nii.gz',
               outPrefix + 'InverseWarped.nii.gz')

            outLabelMap = nib.load(outLabelMapFile).get_data()
            labels = np.unique(outLabelMap)[1:]
            label2name = parse_labels(labels,
                                      self.lut._path if self.lut else None)

            print('Creating ROI based statistics ...')
            stat_file = outPrefix + f'_{self.name}_stat.csv'

            df = pd.DataFrame(columns=[
                'region',
                'FA_mean',
                'FA_std',
                'MD_mean',
                'MD_std',
                'AD_mean',
                'AD_std',
                'RD_mean',
                'RD_std',
                'total_{min_i(b0-Gi)<0}',
                'total_evals<0',
                'MK_mean',
                'MK_std',
            ])

            for i, label in enumerate(label2name.keys()):
                roi = outLabelMap == int(label)

                properties = [
                    num2str(x) for x in [
                        fa[roi > 0].mean(), fa[roi > 0].std(), md[roi > 0].
                        mean(), md[roi > 0].std(), ad[roi > 0].mean(), ad[
                            roi > 0].std(), rd[roi > 0].mean(),
                        rd[roi > 0].std(), minOverGradsNegativeMask[
                            roi > 0].sum(), evals_zero_mask[roi > 0].sum(), mk[
                                roi > 0].mean(), mk[roi > 0].std()
                    ]
                ]

                df.loc[i] = [label2name[label]] + properties

            df = df.set_index('region')
            # print(df)
            df.to_csv(stat_file)
            print('See ', os.path.abspath(stat_file))
示例#24
0
文件: dki.py 项目: richford/pyAFQ
def _fit(gtab, data, mask=None):
    dkimodel = dki.DiffusionKurtosisModel(gtab)
    return dkimodel.fit(data, mask=mask)
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
示例#27
0
def hcp_dki(subject, aws_access_key, aws_secret_key, hcp_aws_access_key,
            hcp_aws_secret_key, outbucket):

    fs = s3fs.S3FileSystem(key=aws_access_key, secret=aws_secret_key)
    remote_p2s_path =\
        "%s/derivatives/patch2self" % (outbucket)

    remote_dti_path =\
        "%s/derivatives/dti" % (outbucket)

    remote_dti1000_path =\
        "%s/derivatives/dti1000" % (outbucket)

    remote_dki_path =\
        "%s/derivatives/dki" % (outbucket)

    remote_sst_path =\
        "%s/derivatives/sst" % (outbucket)

    logging.basicConfig(level=logging.INFO)
    log = logging.getLogger(__name__)  # noqa

    log.info(f"Getting data for subject {subject}")
    # get HCP data for the given subject / session
    _, hcp_bids = fetch_hcp([subject],
                            profile_name=False,
                            aws_access_key_id=hcp_aws_access_key,
                            aws_secret_access_key=hcp_aws_secret_key)

    dwi_path = op.join(afd.afq_home, 'HCP_1200', 'derivatives', 'dmriprep',
                       f'sub-{subject}', 'ses-01', 'dwi')

    dwi_img = nib.load(op.join(dwi_path, f'sub-{subject}_dwi.nii.gz'))
    dwi_data = dwi_img.get_fdata()
    b0_threshold = 50

    gtab = gradient_table(op.join(dwi_path, f'sub-{subject}_dwi.bval'),
                          op.join(dwi_path, f'sub-{subject}_dwi.bvec'),
                          b0_threshold=b0_threshold)

    rpath = op.join(remote_p2s_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_desc-denoised_dwi.nii.gz')
    lpath = "./denoised_data.nii.gz"

    if not fs.exists(rpath):
        log.info("Denoising with patch2self")
        t1 = time.time()
        den_data = patch2self(dwi_data,
                              gtab.bvals,
                              b0_threshold=b0_threshold,
                              clip_negative_vals=False,
                              shift_intensity=True)
        log.info(f"That took {time.time() - t1} seconds")
        den_img = nib.Nifti1Image(den_data, dwi_img.affine)
        nib.save(den_img, lpath)
        fs.upload(lpath, rpath)
    else:
        log.info("Looks like I've already denoised this subject")
        log.info("Downloading data from S3")
        fs.download(rpath, lpath)
        den_data = nib.load(lpath).get_fdata()

    log.info("Calculating SST")
    data_dwi = den_data[..., ~gtab.b0s_mask]
    mean_dwi = np.mean(den_data[..., ~gtab.b0s_mask], -1)
    sst = np.sum((data_dwi - mean_dwi[..., None])**2, -1)
    lpath = "data_sst.nii.gz"
    nib.save(nib.Nifti1Image(sst, dwi_img.affine), lpath)
    rpath = op.join(remote_sst_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_desc-sst.nii.gz')
    fs.upload(lpath, rpath)

    lpath = "dti_params.nii.gz"
    rpath = op.join(remote_dti_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_model-DTI_diffmodel.nii.gz')

    if not fs.exists(rpath):
        log.info("Fitting DTI")
        t1 = time.time()
        dtim = dti.TensorModel(gtab)
        dtif = dtim.fit(den_data, mask=np.ones(den_data.shape[:3]))
        nib.save(nib.Nifti1Image(dtif.model_params, dwi_img.affine), lpath)
        fs.upload(lpath, rpath)
        log.info(f"That took {time.time() - t1} seconds")
    else:
        log.info("Looks like I've already fit DTI")
        log.info("Downloading DTI params from S3")
        fs.download(rpath, lpath)
        dtim = dti.TensorModel(gtab)

    dti_params = nib.load("dti_params.nii.gz")
    S0 = np.mean(den_data[..., gtab.b0s_mask], -1)
    pred = dtim.predict(dti_params.get_fdata(), S0=S0)

    lpath = "dti_pred.nii.gz"
    rpath = op.join(remote_dti_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_prediction-DTI_diffmodel.nii.gz')

    nib.save(nib.Nifti1Image(pred, dwi_img.affine), lpath)
    fs.upload(lpath, rpath)

    # We calculate SSE only over diffusion-weighted volumes
    sse = np.sum(
        (pred[..., ~gtab.b0s_mask] - den_data[..., ~gtab.b0s_mask])**2, -1)
    lpath = "dti_sse.nii.gz"
    rpath = op.join(remote_dti_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_SSE-DTI_diffmodel.nii.gz')
    nib.save(nib.Nifti1Image(sse, dwi_img.affine), lpath)
    fs.upload(lpath, rpath)

    ### DTI 1000
    lpath = "dti1000_params.nii.gz"
    rpath = op.join(remote_dti1000_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_model-DTI_diffmodel.nii.gz')

    dwi1000 = den_data[..., gtab.bvals < 1100]
    gtab1000 = gradient_table(gtab.bvals[gtab.bvals < 1100],
                              gtab.bvecs[gtab.bvals < 1100])
    if not fs.exists(rpath):
        log.info("Fitting DTI")
        t1 = time.time()
        dtim = dti.TensorModel(gtab1000)
        dtif = dtim.fit(dwi1000, mask=np.ones(den_data.shape[:3]))
        nib.save(nib.Nifti1Image(dtif.model_params, dwi_img.affine), lpath)
        fs.upload(lpath, rpath)
        log.info(f"That took {time.time() - t1} seconds")
    else:
        log.info("Looks like I've already fit DTI with b=1000")
        log.info("Downloading DTI params from S3")
        fs.download(rpath, lpath)
        dtim = dti.TensorModel(gtab1000)

    dti_params = nib.load("dti_params.nii.gz")
    S0 = np.mean(dwi1000[..., gtab1000.b0s_mask], -1)
    pred = dtim.predict(dti_params.get_fdata(), S0=S0)

    lpath = "dti1000_pred.nii.gz"
    rpath = op.join(remote_dti1000_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_prediction-DTI_diffmodel.nii.gz')

    nib.save(nib.Nifti1Image(pred, dwi_img.affine), lpath)
    fs.upload(lpath, rpath)

    # We calculate SSE only over diffusion-weighted volumes
    sse = np.sum(
        (pred[..., ~gtab1000.b0s_mask] - dwi1000[..., ~gtab1000.b0s_mask])**2,
        -1)
    lpath = "dti1000_sse.nii.gz"
    rpath = op.join(remote_dti1000_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_SSE-DTI_diffmodel.nii.gz')
    nib.save(nib.Nifti1Image(sse, dwi_img.affine), lpath)
    fs.upload(lpath, rpath)

    ### DKI
    lpath = "dki_params.nii.gz"
    rpath = op.join(remote_dki_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_model-DKI_diffmodel.nii.gz')

    if not fs.exists(rpath):
        log.info("Fitting DKI")
        t1 = time.time()
        dkim = dki.DiffusionKurtosisModel(gtab)
        dkif = dkim.fit(den_data)
        log.info(f"That took {time.time() - t1} seconds")
        nib.save(nib.Nifti1Image(dkif.model_params, dwi_img.affine), lpath)
        fs.upload(lpath, rpath)
    else:
        log.info("Looks like I've already fit DKI")
        log.info("Downloading DKI params from S3")
        fs.download(rpath, lpath)
        dkim = dki.DiffusionKurtosisModel(gtab)

    dki_params = nib.load("dki_params.nii.gz")
    pred = dkim.predict(dki_params.get_fdata(), S0=S0)
    lpath = "dki_pred.nii.gz"
    rpath = op.join(remote_dki_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_prediction-DKI_diffmodel.nii.gz')

    nib.save(nib.Nifti1Image(pred, dwi_img.affine), lpath)
    fs.upload(lpath, rpath)

    # We calculate SSE only over diffusion-weighted volumes
    sse = np.sum(
        (pred[..., ~gtab.b0s_mask] - den_data[..., ~gtab.b0s_mask])**2, -1)
    lpath = "dki_sse.nii.gz"
    rpath = op.join(remote_dki_path, f'sub-{subject}', 'ses-01', 'dwi',
                    f'sub-{subject}_dwi_SSE-DKI_diffmodel.nii.gz')

    nib.save(nib.Nifti1Image(sse, dwi_img.affine), lpath)
    fs.upload(lpath, rpath)
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)
示例#29
0
the data's structural information is preserved by the PCA denoising algorithm
(right panel).

Below we show how the denoised data can be saved.
"""

nib.save(nib.Nifti1Image(denoised_arr, affine), 'denoised_mppca.nii.gz')

print("Entire denoised data saved in denoised_mppca.nii.gz")
"""
Additionally, we show how the PCA denoising algorithm affects different
diffusion measurements. For this, we run the diffusion kurtosis model
below on both original and denoised versions of the data:
"""

dkimodel = dki.DiffusionKurtosisModel(gtab)

maskdata, mask = median_otsu(data,
                             vol_idx=[0, 1],
                             median_radius=4,
                             numpass=2,
                             autocrop=False,
                             dilate=1)

dki_orig = dkimodel.fit(data, mask=mask)
dki_den = dkimodel.fit(denoised_arr, mask=mask)
"""
We use the following code to plot the MD, FA and MK estimates from the two data
fits:
"""
def hcp_dki(subject, aws_access_key, aws_secret_key, hcp_aws_access_key,
            hcp_aws_secret_key, outbucket):

    fs = s3fs.S3FileSystem(key=aws_access_key, secret=aws_secret_key)

    remote_dti1000_path =\
        "%s/derivatives/dti1000" % (outbucket)

    remote_dti1000_2000_path =\
        "%s/derivatives/dti1000_2000" % (outbucket)

    remote_dki1000_2000_path =\
        "%s/derivatives/dki1000_2000" % (outbucket)

    remote_dki2000_3000_path =\
        "%s/derivatives/dki2000_3000" % (outbucket)

    remote_dki1000_3000_path =\
        "%s/derivatives/dki1000_3000" % (outbucket)


    logging.basicConfig(level=logging.INFO)
    log = logging.getLogger(__name__) # noqa

    log.info(f"Getting data for subject {subject}")
    # get HCP data for the given subject / session
    _, hcp_bids = fetch_hcp(
        [subject],
        profile_name=False,
        aws_access_key_id=hcp_aws_access_key,
        aws_secret_access_key=hcp_aws_secret_key)

    dwi_path = op.join(afd.afq_home, 'HCP_1200', 'derivatives', 'dmriprep',
                       f'sub-{subject}', 'ses-01', 'dwi')

    dwi_img = nib.load(op.join(dwi_path, f'sub-{subject}_dwi.nii.gz'))
    dwi_data = dwi_img.get_fdata()
    b0_threshold = 50

    gtab = gradient_table(
        op.join(dwi_path, f'sub-{subject}_dwi.bval'),
        op.join(dwi_path, f'sub-{subject}_dwi.bvec'),
        b0_threshold=b0_threshold)

    ### DTI 1000
    last_result = op.join(
        remote_dti1000_path, f'sub-{subject}', 'ses-01', 'dwi',
        f'sub-{subject}_dwi_model-DTI_MD.nii.gz')
    if not fs.exists(last_result):
        lpath = "dti1000_params.nii.gz"
        rpath = op.join(remote_dti1000_path, f'sub-{subject}', 'ses-01', 'dwi',
                        f'sub-{subject}_dwi_model-DTI_diffmodel.nii.gz')

        dwi1000 = dwi_data[..., gtab.bvals < 1100]
        gtab1000 = gradient_table(gtab.bvals[gtab.bvals < 1100],
                                gtab.bvecs[gtab.bvals < 1100])
        if not fs.exists(rpath):
            log.info("Fitting DTI")
            t1 = time.time()
            dtim = dti.TensorModel(gtab1000)
            dtif = dtim.fit(dwi1000, mask=np.ones(dwi_data.shape[:3]))
            nib.save(nib.Nifti1Image(dtif.model_params, dwi_img.affine), lpath)
            fs.upload(lpath, rpath)
            log.info(f"That took {time.time() - t1} seconds")
        else:
            log.info("Looks like I've already fit DTI with b=1000")
            log.info("Downloading DTI params from S3")
            fs.download(rpath, lpath)
            dtim = dti.TensorModel(gtab1000)
            dti_params = nib.load(lpath).get_fdata()
            dtif = dti.TensorFit(dtim, dti_params)

        lpath = "dti1000_fa.nii.gz"
        nib.save(nib.Nifti1Image(dtif.fa, dwi_img.affine), lpath)
        rpath = op.join(remote_dti1000_path, f'sub-{subject}', 'ses-01', 'dwi',
                        f'sub-{subject}_dwi_model-DTI_FA.nii.gz')
        fs.upload(lpath, rpath)

        lpath = "dti1000_md.nii.gz"
        nib.save(nib.Nifti1Image(dtif.md, dwi_img.affine), lpath)
        rpath = op.join(remote_dti1000_path, f'sub-{subject}', 'ses-01', 'dwi',
                        f'sub-{subject}_dwi_model-DTI_MD.nii.gz')
        fs.upload(lpath, rpath)


    ### DTI 1000 + 2000
    last_result = op.join(
        remote_dti1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
        f'sub-{subject}_dwi_model-DTI_MD.nii.gz')
    if not fs.exists(last_result):
        lpath = "dti1000_2000_params.nii.gz"
        rpath = op.join(
            remote_dti1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DTI_diffmodel.nii.gz')

        dwi1000_2000 = dwi_data[..., gtab.bvals < 2100]
        gtab1000_2000 = gradient_table(
            gtab.bvals[gtab.bvals < 2100],
            gtab.bvecs[gtab.bvals < 2100])
        if not fs.exists(rpath):
            log.info("Fitting DTI with b=1000 and 2000")
            t1 = time.time()
            dtim = dti.TensorModel(gtab1000_2000)
            dtif = dtim.fit(dwi1000_2000, mask=np.ones(dwi_data.shape[:3]))
            nib.save(nib.Nifti1Image(dtif.model_params, dwi_img.affine), lpath)
            fs.upload(lpath, rpath)
            log.info(f"That took {time.time() - t1} seconds")
        else:
            log.info("Looks like I've already fit DTI with b=1000 and b=2000")
            log.info("Downloading DTI params from S3")
            fs.download(rpath, lpath)
            dtim = dti.TensorModel(gtab1000_2000)
            dti_params = nib.load(lpath).get_fdata()
            dtif = dti.TensorFit(dtim, dti_params)

        lpath = "dti1000_2000_fa.nii.gz"
        nib.save(nib.Nifti1Image(dtif.fa, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dti1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DTI_FA.nii.gz')
        fs.upload(lpath, rpath)

        lpath = "dti1000_2000_md.nii.gz"
        nib.save(nib.Nifti1Image(dtif.md, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dti1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DTI_MD.nii.gz')
        fs.upload(lpath, rpath)


    ### DKI 1000 + 2000
    last_result = op.join(
        remote_dki1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
        f'sub-{subject}_dwi_model-DKI_MD.nii.gz')

    if not fs.exists(last_result):
        lpath = "dki1000_2000_params.nii.gz"
        rpath = op.join(
            remote_dki1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_diffmodel.nii.gz')

        dwi1000_2000 = dwi_data[..., gtab.bvals < 2100]
        gtab1000_2000 = gradient_table(gtab.bvals[gtab.bvals < 2100],
                                       gtab.bvecs[gtab.bvals < 2100])
        if not fs.exists(rpath):
            log.info("Fitting DKI with b=1000 + 2000")
            t1 = time.time()
            dkim = dki.DiffusionKurtosisModel(gtab1000_2000)
            dkif = dkim.fit(dwi1000_2000, mask=np.ones(dwi_data.shape[:3]))
            nib.save(nib.Nifti1Image(dkif.model_params, dwi_img.affine), lpath)
            fs.upload(lpath, rpath)
            log.info(f"That took {time.time() - t1} seconds")
        else:
            log.info("Looks like I've already fit DKI with b=1000 and b=2000")
            log.info("Downloading DKI params from S3")
            fs.download(rpath, lpath)
            dkim = dki.DiffusionKurtosisModel(gtab1000_2000)
            dki_params = nib.load(lpath).get_fdata()
            dkif = dki.DiffusionKurtosisFit(dkim, dki_params)

        lpath = "dki1000_2000_fa.nii.gz"
        nib.save(nib.Nifti1Image(dkif.fa, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dki1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_FA.nii.gz')
        fs.upload(lpath, rpath)

        lpath = "dki1000_2000_md.nii.gz"
        nib.save(nib.Nifti1Image(dkif.md, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dki1000_2000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_MD.nii.gz')
        fs.upload(lpath, rpath)

    ### DKI 2000 + 3000
    last_result = op.join(
        remote_dki2000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
        f'sub-{subject}_dwi_model-DKI_MD.nii.gz')
    if not fs.exists(last_result):
        lpath = "dki2000_3000_params.nii.gz"
        rpath = op.join(
            remote_dki2000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_diffmodel.nii.gz')

        dwi2000_3000 = dwi_data[..., (gtab.bvals > 1985) | (gtab.bvals < 50)]
        gtab2000_3000 = gradient_table(
            gtab.bvals[(gtab.bvals > 1985) | (gtab.bvals < 50)],
            gtab.bvecs[(gtab.bvals > 1985) | (gtab.bvals < 50)])

        if not fs.exists(rpath):
            log.info("Fitting DKI with b=2000 + 3000")
            t1 = time.time()
            dkim = dki.DiffusionKurtosisModel(gtab2000_3000)
            dkif = dkim.fit(dwi2000_3000, mask=np.ones(dwi_data.shape[:3]))
            nib.save(nib.Nifti1Image(dkif.model_params, dwi_img.affine), lpath)
            fs.upload(lpath, rpath)
            log.info(f"That took {time.time() - t1} seconds")
        else:
            log.info("Looks like I've already fit DKI with b=2000 and b=3000")
            log.info("Downloading DKI params from S3")
            fs.download(rpath, lpath)
            dkim = dki.DiffusionKurtosisModel(gtab2000_3000)
            dki_params = nib.load(lpath).get_fdata()
            dkif = dki.DiffusionKurtosisFit(dkim, dki_params)

        lpath = "dki2000_3000_fa.nii.gz"
        nib.save(nib.Nifti1Image(dkif.fa, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dki2000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_FA.nii.gz')
        fs.upload(lpath, rpath)

        lpath = "dki2000_3000_md.nii.gz"
        nib.save(nib.Nifti1Image(dkif.md, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dki2000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_MD.nii.gz')
        fs.upload(lpath, rpath)

    ### DKI 1000 + 3000
    last_result = op.join(
        remote_dki1000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
        f'sub-{subject}_dwi_model-DKI_MD.nii.gz')
    if not fs.exists(last_result):
        lpath = "dki1000_3000_params.nii.gz"
        rpath = op.join(
            remote_dki1000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_diffmodel.nii.gz')

        dwi1000_3000 = dwi_data[..., (gtab.bvals > 2500) | (gtab.bvals < 1500)]
        gtab1000_3000 = gradient_table(
            gtab.bvals[(gtab.bvals > 2500) | (gtab.bvals < 1500)],
            gtab.bvecs[(gtab.bvals > 2500) | (gtab.bvals < 1500)])

        if not fs.exists(rpath):
            log.info("Fitting DKI with b=1000 + 3000")
            t1 = time.time()
            dkim = dki.DiffusionKurtosisModel(gtab1000_3000)
            dkif = dkim.fit(dwi1000_3000, mask=np.ones(dwi_data.shape[:3]))
            nib.save(nib.Nifti1Image(dkif.model_params, dwi_img.affine), lpath)
            fs.upload(lpath, rpath)
            log.info(f"That took {time.time() - t1} seconds")
        else:
            log.info("Looks like I've already fit DKI with b=1000 and b=3000")
            log.info("Downloading DKI params from S3")
            fs.download(rpath, lpath)
            dkim = dki.DiffusionKurtosisModel(gtab1000_3000)
            dki_params = nib.load(lpath).get_fdata()
            dkif = dki.DiffusionKurtosisFit(dkim, dki_params)

        lpath = "dki1000_3000_fa.nii.gz"
        nib.save(nib.Nifti1Image(dkif.fa, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dki1000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_FA.nii.gz')
        fs.upload(lpath, rpath)

        lpath = "dki1000_3000_md.nii.gz"
        nib.save(nib.Nifti1Image(dkif.md, dwi_img.affine), lpath)
        rpath = op.join(
            remote_dki1000_3000_path, f'sub-{subject}', 'ses-01', 'dwi',
            f'sub-{subject}_dwi_model-DKI_MD.nii.gz')
        fs.upload(lpath, rpath)