Example #1
0
def test_standalone_functions():
    # WLS procedure
    params = wls_fit_tensor(gtab_2s, DWI)
    assert_array_almost_equal(params[..., 12], GTF)
    fa = fractional_anisotropy(params[..., :3])
    assert_array_almost_equal(fa, FAref)

    # NLS procedure
    params = nls_fit_tensor(gtab_2s, DWI)
    assert_array_almost_equal(params[..., 12], GTF)
    fa = fractional_anisotropy(params[..., :3])
    assert_array_almost_equal(fa, FAref)
Example #2
0
def test_response_from_mask():
    fdata, fbvals, fbvecs = get_data('small_64D')
    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)
    data = nib.load(fdata).get_data()

    gtab = gradient_table(bvals, bvecs)
    ten = TensorModel(gtab)
    tenfit = ten.fit(data)
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    radius = 3

    for fa_thr in np.arange(0, 1, 0.1):
        response_auto, ratio_auto, nvoxels = auto_response(gtab,
                                                           data,
                                                           roi_center=None,
                                                           roi_radius=radius,
                                                           fa_thr=fa_thr,
                                                           return_number_of_voxels=True)

        ci, cj, ck = np.array(data.shape[:3]) / 2
        mask = np.zeros(data.shape[:3])
        mask[ci - radius: ci + radius,
             cj - radius: cj + radius,
             ck - radius: ck + radius] = 1

        mask[FA <= fa_thr] = 0
        response_mask, ratio_mask = response_from_mask(gtab, data, mask)

        assert_equal(int(np.sum(mask)), nvoxels)
        assert_array_almost_equal(response_mask[0], response_auto[0])
        assert_almost_equal(response_mask[1], response_auto[1])
        assert_almost_equal(ratio_mask, ratio_auto)
Example #3
0
def compute_reconstruction(src_dmri_dir, subj_name):

    src_dmri_file = os.path.join(src_dmri_dir, subj_name + par_iso_suffix)
    src_bval_file = src_dmri_dir +  [each for each in os.listdir(src_dmri_dir) if each.endswith('.bval')][0]
    src_bvec_file = src_dmri_dir +  [each for each in os.listdir(src_dmri_dir) if each.endswith('.bvec')][0]

    img = nib.load(src_dmri_file)
    bvals = np.loadtxt(src_bval_file)
    bvecs = np.loadtxt(src_bvec_file).T
    data = img.get_data()
    affine = img.get_affine()

    gradients = gradient_table(bvals,bvecs)
    tensor_model = dti.TensorModel(gradients)  
    tensors = tensor_model.fit(data)
    FA = dti.fractional_anisotropy(tensors.evals)
    FA[np.isnan(FA)] = 0
    Color_FA = np.array(255*(dti.color_fa(FA, tensors.evecs)),'uint8')
    
    out_evecs_file = os.path.join(src_dmri_dir, subj_name + par_evecs_suffix)
    evecs_img = nib.Nifti1Image(tensors.evecs.astype(np.float32), affine)
    nib.save(evecs_img, out_evecs_file)

    out_fa_file = os.path.join(src_dmri_dir, subj_name + par_fa_suffix)
    fa_img = nib.Nifti1Image(FA.astype(np.float32), affine)
    nib.save(fa_img, out_fa_file)

    out_cfa_file = os.path.join(src_dmri_dir, subj_name + par_cfa_tome_suffix)
    cfa_img = nib.Nifti1Image(Color_FA, affine)
    nib.save(cfa_img, out_cfa_file)

    dt = np.dtype([('R', 'u1'), ('G', 'u1'), ('B', 'u1')])
    out_cfa_file = os.path.join(src_dmri_dir, subj_name + par_cfa_trkvis_suffix)
    cfa_img = nib.Nifti1Image((Color_FA.view((dt)).reshape(Color_FA.shape[:3])), affine)
    nib.save(cfa_img, out_cfa_file)
Example #4
0
def DIPY_nii2streamlines(imgfile, maskfile, bvals, bvecs, output_prefix):
    import numpy as np
    import nibabel as nib
    import os

    from dipy.reconst.dti import TensorModel

    print "nii2streamlines"

    img = nib.load(imgfile)
    bvals = np.genfromtxt(bvals)
    bvecs = np.genfromtxt(bvecs)
    if bvecs.shape[1] != 3:
        bvecs = bvecs.T
    print bvecs.shape

    from nipype.utils.filemanip import split_filename
    _, prefix, _  = split_filename(imgfile)
    from dipy.data import gradient_table
    gtab = gradient_table(bvals, bvecs)
    data = img.get_data()
    affine = img.get_affine()
    zooms = img.get_header().get_zooms()[:3]
    new_zooms = (2., 2., 2.)
    data2, affine2 = data, affine
    mask = nib.load(maskfile).get_data().astype(np.bool)
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data2, mask)

    from dipy.reconst.dti import fractional_anisotropy
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    fa_img = nib.Nifti1Image(FA, img.get_affine())
    nib.save(fa_img, experiment_dir + '/' + ('%s_tensor_fa.nii.gz' % prefix))
    evecs = tenfit.evecs
    evec_img = nib.Nifti1Image(evecs, img.get_affine())
    nib.save(evec_img, experiment_dir + '/' + ('%s_tensor_evec.nii.gz' % prefix))

    from dipy.data import get_sphere
    sphere = get_sphere('symmetric724')
    from dipy.reconst.dti import quantize_evecs

    peak_indices = quantize_evecs(tenfit.evecs, sphere.vertices)

    from dipy.tracking.eudx import EuDX
    eu = EuDX(FA, peak_indices, odf_vertices = sphere.vertices, a_low=0.2, seeds=10**6, ang_thr=35)
    tensor_streamlines = [streamline for streamline in eu]
    hdr = nib.trackvis.empty_header()
    hdr['voxel_size'] = new_zooms
    hdr['voxel_order'] = 'LPS'
    hdr['dim'] = data2.shape[:3]

    import dipy.tracking.metrics as dmetrics
    tensor_streamlines = ((sl, None, None) for sl in tensor_streamlines if dmetrics.length(sl) > 15)
    ten_sl_fname = experiment_dir + '/' + ('%s_streamline.trk' % prefix)
    nib.trackvis.write(ten_sl_fname, tensor_streamlines, hdr, points_space='voxel')
    return ten_sl_fname
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix):
    """
    Compute DTI.
    :param fname_in: input 4d file.
    :param bvals: bvals txt file
    :param bvecs: bvecs txt file
    :param prefix: output prefix. Example: "dti_"
    :return: True/False
    """
    # Open file.
    from msct_image import Image
    nii = Image(fname_in)
    data = nii.data
    print('data.shape (%d, %d, %d, %d)' % data.shape)

    # open bvecs/bvals
    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs)
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs)

    # # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image.
    # from dipy.segment.mask import median_otsu
    # maskdata, mask = median_otsu(data, 3, 1, True, vol_idx=range(10, 50), dilate=2)
    # print('maskdata.shape (%d, %d, %d, %d)' % maskdata.shape)

    # fit tensor model
    import dipy.reconst.dti as dti
    tenmodel = dti.TensorModel(gtab)
    tenfit = tenmodel.fit(data)

    # Compute metrics
    printv('Computing metrics...', param.verbose)
    # FA
    from dipy.reconst.dti import fractional_anisotropy
    nii.data = fractional_anisotropy(tenfit.evals)
    nii.setFileName(prefix+'FA.nii.gz')
    nii.save('float32')
    # MD
    from dipy.reconst.dti import mean_diffusivity
    nii.data = mean_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'MD.nii.gz')
    nii.save('float32')
    # RD
    from dipy.reconst.dti import radial_diffusivity
    nii.data = radial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'RD.nii.gz')
    nii.save('float32')
    # AD
    from dipy.reconst.dti import axial_diffusivity
    nii.data = axial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'AD.nii.gz')
    nii.save('float32')

    return True
Example #6
0
def FA_RGB(data, gtab):
    """
    Input : data, gtab taken from the load_data.py script.
    Return : FA and RGB as two nd numpy array
    """

    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data)
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    FA = np.clip(FA, 0, 1)
    RGB = color_fa(FA, tenfit.evecs)
    return FA, RGB
def estimate_response(gtab, data, affine, mask, fa_thr=0.7):
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data, mask)
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    mask[FA <= 0.1] = 0
    mask[FA > 1.] = 0
    indices = np.where(FA > fa_thr)
    lambdas = tenfit.evals[indices][:, :2]
    S0s = data[indices][:, 0]
    S0 = np.mean(S0s)
    l01 = np.mean(lambdas, axis=0)
    evals = np.array([l01[0], l01[1], l01[1]])
    ratio = evals[1] / evals[0]
    print 'Response evals' , evals, ' ratio: ', ratio, '\tMean S0', S0
    return (evals, S0), ratio
def prepare(training, category, snr, denoised, odeconv, tv, method):

    data, affine, gtab = get_specific_data(training,
                                           category,
                                           snr,
                                           denoised)

    prefix = create_file_prefix(training,
                                category,
                                snr,
                                denoised,
                                odeconv,
                                tv,
                                method)

    if training:
        mask = nib.load('wm_mask_hardi_01.nii.gz').get_data()
    else:
        #mask = np.ones(data.shape[:-1])
        mask = nib.load('test_hardi_30_den=1_fa_0025_dilate2_mask.nii.gz').get_data()

    tenmodel = TensorModel(gtab)

    tenfit = tenmodel.fit(data, mask)

    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0

    mask[FA <= 0.1] = 0
    mask[FA > 1.] = 0

    indices = np.where(FA > 0.7)
    lambdas = tenfit.evals[indices][:, :2]
    S0s = data[indices][:, 0]
    S0 = np.mean(S0s)

    if S0 == 0:
        print 'S0 equals to 0 switching to 1'
        S0 = 1

    l01 = np.mean(lambdas, axis=0)

    evals = np.array([l01[0], l01[1], l01[1]])

    print evals, S0

    return data, affine, gtab, mask, evals, S0, prefix
Example #9
0
def test_color_fa():
    data, gtab = dsi_voxels()
    dm = dti.TensorModel(gtab, 'LS')
    dmfit = dm.fit(data)
    fa = fractional_anisotropy(dmfit.evals)
    cfa = color_fa(fa, dmfit.evecs)

    fa = np.ones((3, 3, 3))
    # evecs should be of shape (fa, 3, 3)
    evecs = np.zeros(fa.shape + (3, 2))
    npt.assert_raises(ValueError, color_fa, fa, evecs)

    evecs = np.zeros(fa.shape + (3, 3))
    evecs[..., :, :] = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])

    assert_equal(fa.shape, evecs[..., 0, 0].shape)
    assert_equal((3, 3), evecs.shape[-2:])

    # 3D test case
    fa = np.ones((3, 3, 3))
    evecs = np.zeros(fa.shape + (3, 3))
    evecs[..., :, :] = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    cfa = color_fa(fa, evecs)
    cfa_truth = np.array([1, 0, 0])
    true_cfa = np.reshape(np.tile(cfa_truth, 27), [3, 3, 3, 3])

    assert_array_equal(cfa, true_cfa)

    # 2D test case
    fa = np.ones((3, 3))
    evecs = np.zeros(fa.shape + (3, 3))
    evecs[..., :, :] = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    cfa = color_fa(fa, evecs)
    cfa_truth = np.array([1, 0, 0])
    true_cfa = np.reshape(np.tile(cfa_truth, 9), [3, 3, 3])

    assert_array_equal(cfa, true_cfa)

    # 1D test case
    fa = np.ones((3))
    evecs = np.zeros(fa.shape + (3, 3))
    evecs[..., :, :] = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    cfa = color_fa(fa, evecs)
    cfa_truth = np.array([1, 0, 0])
    true_cfa = np.reshape(np.tile(cfa_truth, 3), [3, 3])

    assert_array_equal(cfa, true_cfa)
Example #10
0
def segment_from_cfa(tensor_fit, roi, threshold, return_cfa=False):
    """
    Segment the cfa inside roi using the values from threshold as bounds.

    Parameters
    -------------
    tensor_fit : TensorFit object
        TensorFit object

    roi : ndarray
        A binary mask, which contains the bounding box for the segmentation.

    threshold : array-like
        An iterable that defines the min and max values to use for the
        thresholding.
        The values are specified as (R_min, R_max, G_min, G_max, B_min, B_max)

    return_cfa : bool, optional
        If True, the cfa is also returned.

    Returns
    ----------
    mask : ndarray
        Binary mask of the segmentation.

    cfa : ndarray, optional
        Array with shape = (..., 3), where ... is the shape of tensor_fit.
        The color fractional anisotropy, ordered as a nd array with the last
        dimension of size 3 for the R, G and B channels.
    """

    FA = fractional_anisotropy(tensor_fit.evals)
    FA[np.isnan(FA)] = 0
    FA = np.clip(FA, 0, 1)  # Clamp the FA to remove degenerate tensors

    cfa = color_fa(FA, tensor_fit.evecs)
    roi = np.asarray(roi, dtype=bool)

    include = ((cfa >= threshold[0::2]) &
               (cfa <= threshold[1::2]) &
               roi[..., None])
    mask = np.all(include, axis=-1)

    if return_cfa:
        return mask, cfa

    return mask
def tractography_rec(imag, bvals, bvecs, seed, threshold):
    ''' Script to generate tractography. Uses the EuDX function from dipy. Returns tractography and FA.
    
    Parameters
    ----------
    imag: NiftiImage object 
    bvals: bvals array
    bvecs: bvecs array
    seed: int or ndarray (Parameter for the EuDX function)
    threshold : float (Parameter for the EuDX function)
    '''

    print "Retrieving data and affine"
    data = img.get_data()
    affine = img.get_affine()

    #new version of dipy
    print "Computing tensor model"
    gradients = gradient_table(bvals,bvecs)
    tensor_model = dti.TensorModel(gradients)
    tensors = tensor_model.fit(data)

    print "Computing FA"
    FA = dti.fractional_anisotropy(tensors.evals)
    FA[np.isnan(FA)] = 0

    print "Computing evecs"
    evecs_img = nib.Nifti1Image(tensors.evecs.astype(np.float32), affine)
    evecs = evecs_img.get_data()

    sphere = get_sphere('symmetric724')
    peak_indices = dti.quantize_evecs(evecs, sphere.vertices)
    
    print "Computing EuDX reconstruction."
    streamlines = EuDX(FA.astype('f8'),
                        ind=peak_indices,
			seeds=seed,
                        odf_vertices= sphere.vertices,
                        a_low=threshold)

    return streamlines, FA
Example #12
0
def single_fiber_response(diffusionData, mask, gtable, fa_thr = 0.7):
    from dipy.reconst.dti import TensorModel, fractional_anisotropy
    
    ten    = TensorModel(gtable)
    tenfit = ten.fit(diffusionData, mask=mask)
    
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    
    indices = np.where(FA > fa_thr)
    lambdas = tenfit.evals[indices][:, :2]
    
    S0s     = diffusionData[indices][:, np.nonzero(gtable.b0s_mask)[0]]
    S0      = np.mean(S0s)
    l01     = np.mean(lambdas, axis=0)
    evals   = np.array([l01[0], l01[1], l01[1]])
    
    response = (evals, S0)
    ratio    = evals[1]/evals[0]
    
    return response, ratio
Example #13
0
def tensor_model(
    input_filename_data, input_filename_bvecs, input_filename_bvals, output_filename_fa=None, output_filename_evecs=None
):

    # print 'Tensor model ...'

    # print 'Loading data ...'
    img = nib.load(input_filename_data)
    data = img.get_data()
    affine = img.get_affine()

    bvals, bvecs = read_bvals_bvecs(input_filename_bvals, input_filename_bvecs)
    gtab = gradient_table(bvals, bvecs)

    mask = data[..., 0] > 50
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data, mask)

    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0

    if output_filename_fa == None:
        filename_save_fa = input_filename_data.split(".")[0] + "_tensor_fa.nii.gz"
    else:
        filename_save_fa = os.path.abspath(output_filename_fa)

    fa_img = nib.Nifti1Image(FA, img.get_affine())
    nib.save(fa_img, filename_save_fa)
    print "Saving fa to:", filename_save_fa

    if output_filename_evecs == None:
        filename_save_evecs = input_filename_data.split(".")[0] + "_tensor_evecs.nii.gz"
    else:
        filename_save_evecs = os.path.abspath(output_filename_evecs)

    evecs_img = nib.Nifti1Image(tenfit.evecs, img.get_affine())
    nib.save(evecs_img, filename_save_evecs)
    print "Saving evecs to:", filename_save_evecs

    return filename_save_fa, filename_save_evecs
Example #14
0
def tensor2fa(tensors, tensor_name, dwi, derivdir, qcdir):
    '''
    outdir: location of output directory.
    fname: name of output fa map file. default is none (name created based on
    input file)
    '''
    dwi_data = nb.load(dwi)
    affine = dwi_data.get_affine()
    dwi_data = dwi_data.get_data()

    # create FA map
    FA = fractional_anisotropy(tensors.evals)
    FA[np.isnan(FA)] = 0

    # generate the RGB FA map
    FA = np.clip(FA, 0, 1)
    RGB = color_fa(FA, tensors.evecs)

    fname = os.path.split(tensor_name)[1].split(".")[0] + '_fa_rgb.nii.gz'
    fa = nb.Nifti1Image(np.array(255 * RGB, 'uint8'), affine)
    nb.save(fa, derivdir + fname)

    fa_pngs(fa, fname, qcdir)
Example #15
0
def mask_for_response_ssst(gtab,
                           data,
                           roi_center=None,
                           roi_radii=10,
                           fa_thr=0.7):
    """ Computation of mask for single-shell single-tissue (ssst) response
        function using FA.

    Parameters
    ----------
    gtab : GradientTable
    data : ndarray
        diffusion data (4D)
    roi_center : array-like, (3,)
        Center of ROI in data. If center is None, it is assumed that it is
        the center of the volume with shape `data.shape[:3]`.
    roi_radii : int or array-like, (3,)
        radii of cuboid ROI
    fa_thr : float
        FA threshold

    Returns
    -------
    mask : ndarray
        Mask of voxels within the ROI and with FA above the FA threshold.

    Notes
    -----
    In CSD there is an important pre-processing step: the estimation of the
    fiber response function. In order to do this, we look for voxels with very
    anisotropic configurations. This function aims to accomplish that by
    returning a mask of voxels within a ROI, that have a FA value above a
    given threshold. For example we can use a ROI (20x20x20) at
    the center of the volume and store the signal values for the voxels with
    FA values higher than 0.7 (see [1]_).

    References
    ----------
    .. [1] Tournier, J.D., et al. NeuroImage 2004. Direct estimation of the
    fiber orientation density function from diffusion-weighted MRI
    data using spherical deconvolution
    """

    if len(data.shape) < 4:
        msg = """Data must be 4D (3D image + directions). To use a 2D image,
        please reshape it into a (N, N, 1, ndirs) array."""
        raise ValueError(msg)

    if isinstance(roi_radii, numbers.Number):
        roi_radii = (roi_radii, roi_radii, roi_radii)

    if roi_center is None:
        roi_center = np.array(data.shape[:3]) // 2

    roi_radii = _roi_in_volume(data.shape, np.asarray(roi_center),
                               np.asarray(roi_radii))

    roi_mask = _mask_from_roi(data.shape[:3], roi_center, roi_radii)

    ten = TensorModel(gtab)
    tenfit = ten.fit(data, mask=roi_mask)
    fa = fractional_anisotropy(tenfit.evals)
    fa[np.isnan(fa)] = 0

    mask = np.zeros(fa.shape, dtype=np.int64)
    mask[fa > fa_thr] = 1

    if np.sum(mask) == 0:
        msg = """No voxel with a FA higher than {} were found.
        Try a larger roi or a lower threshold.""".format(str(fa_thr))
        warnings.warn(msg, UserWarning)

    return mask
Example #16
0
def main():
    parser = buildArgsParser()
    args = parser.parse_args()

    # Load data
    img = nib.load(args.input)
    data = img.get_data()
    affine = img.get_affine()

    # Setting suffix savename
    if args.savename is None:
        filename = ""
    else:
        filename = args.savename + "_"

    if os.path.exists(filename + 'fa.nii.gz'):
        if not args.overwrite:
            raise ValueError("File " + filename + "fa.nii.gz" 
                             + " already exists. Use -f option to overwrite.")

        print (filename + "fa.nii.gz", " already exists and will be overwritten.")

    if args.mask is not None:
        mask = nib.load(args.mask).get_data()
    else:
        print("No mask specified. Computing mask with median_otsu.")
        data, mask = median_otsu(data)
        mask_img = nib.Nifti1Image(mask.astype(np.float32), affine)
        nib.save(mask_img, filename + 'mask.nii.gz')

    # Get tensors
    print('Tensor estimation...')
    b_vals, b_vecs = read_bvals_bvecs(args.bvals, args.bvecs)
    gtab = gradient_table_from_bvals_bvecs(b_vals, b_vecs)
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data, mask)

    # FA
    print('Computing FA...')
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0

    # RGB
    print('Computing RGB...')
    FA = np.clip(FA, 0, 1)
    RGB = color_fa(FA, tenfit.evecs)

    if args.all :
        print('Computing Diffusivities...')
        # diffusivities
        MD = mean_diffusivity(tenfit.evals)
        AD = axial_diffusivity(tenfit.evals)
        RD = radial_diffusivity(tenfit.evals)

        print('Computing Mode...')
        MODE = mode(tenfit.quadratic_form)

        print('Saving tensor coefficients and metrics...')
        # Get the Tensor values and format them for visualisation in the Fibernavigator.
        tensor_vals = lower_triangular(tenfit.quadratic_form)
        correct_order = [0, 1, 3, 2, 4, 5]
        tensor_vals_reordered = tensor_vals[..., correct_order]
        fiber_tensors = nib.Nifti1Image(tensor_vals_reordered.astype(np.float32), affine)
        nib.save(fiber_tensors, filename + 'tensors.nii.gz')

        # Save - for some reason this is not read properly by the FiberNav
        md_img = nib.Nifti1Image(MD.astype(np.float32), affine)
        nib.save(md_img, filename + 'md.nii.gz')
        ad_img = nib.Nifti1Image(AD.astype(np.float32), affine)
        nib.save(ad_img, filename + 'ad.nii.gz')
        rd_img = nib.Nifti1Image(RD.astype(np.float32), affine)
        nib.save(rd_img, filename + 'rd.nii.gz')
        mode_img = nib.Nifti1Image(MODE.astype(np.float32), affine)
        nib.save(mode_img, filename + 'mode.nii.gz')

    fa_img = nib.Nifti1Image(FA.astype(np.float32), affine)
    nib.save(fa_img, filename + 'fa.nii.gz')
    rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine)
    nib.save(rgb_img, filename + 'rgb.nii.gz')
Example #17
0
def compute_dti(fname_in, fname_bvals, fname_bvecs, prefix, method, file_mask):
    """
    Compute DTI.
    :param fname_in: input 4d file.
    :param bvals: bvals txt file
    :param bvecs: bvecs txt file
    :param prefix: output prefix. Example: "dti_"
    :param method: algo for computing dti
    :return: True/False
    """
    # Open file.
    from msct_image import Image
    nii = Image(fname_in)
    data = nii.data
    print('data.shape (%d, %d, %d, %d)' % data.shape)

    # open bvecs/bvals
    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(fname_bvals, fname_bvecs)
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs)

    # mask and crop the data. This is a quick way to avoid calculating Tensors on the background of the image.
    if not file_mask == '':
        printv('Open mask file...', param.verbose)
        # open mask file
        nii_mask = Image(file_mask)
        mask = nii_mask.data

    # fit tensor model
    printv('Computing tensor using "'+method+'" method...', param.verbose)
    import dipy.reconst.dti as dti
    if method == 'standard':
        tenmodel = dti.TensorModel(gtab)
        if file_mask == '':
            tenfit = tenmodel.fit(data)
        else:
            tenfit = tenmodel.fit(data, mask)
    elif method == 'restore':
        import dipy.denoise.noise_estimate as ne
        sigma = ne.estimate_sigma(data)
        dti_restore = dti.TensorModel(gtab, fit_method='RESTORE', sigma=sigma)
        if file_mask == '':
            tenfit = dti_restore.fit(data)
        else:
            tenfit = dti_restore.fit(data, mask)

    # Compute metrics
    printv('Computing metrics...', param.verbose)
    # FA
    from dipy.reconst.dti import fractional_anisotropy
    nii.data = fractional_anisotropy(tenfit.evals)
    nii.setFileName(prefix+'FA.nii.gz')
    nii.save('float32')
    # MD
    from dipy.reconst.dti import mean_diffusivity
    nii.data = mean_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'MD.nii.gz')
    nii.save('float32')
    # RD
    from dipy.reconst.dti import radial_diffusivity
    nii.data = radial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'RD.nii.gz')
    nii.save('float32')
    # AD
    from dipy.reconst.dti import axial_diffusivity
    nii.data = axial_diffusivity(tenfit.evals)
    nii.setFileName(prefix+'AD.nii.gz')
    nii.save('float32')

    return True
Example #18
0
def auto_response(gtab, data, roi_center=None, roi_radius=10, fa_thr=0.7,
                  fa_callable=fa_superior, return_number_of_voxels=False):
    """ Automatic estimation of response function using FA.

    Parameters
    ----------
    gtab : GradientTable
    data : ndarray
        diffusion data
    roi_center : tuple, (3,)
        Center of ROI in data. If center is None, it is assumed that it is
        the center of the volume with shape `data.shape[:3]`.
    roi_radius : int
        radius of cubic ROI
    fa_thr : float
        FA threshold
    fa_callable : callable
        A callable that defines an operation that compares FA with the fa_thr. The operator
        should have two positional arguments (e.g., `fa_operator(FA, fa_thr)`) and it should
        return a bool array.
    return_number_of_voxels : bool
        If True, returns the number of voxels used for estimating the response
        function.

    Returns
    -------
    response : tuple, (2,)
        (`evals`, `S0`)
    ratio : float
        The ratio between smallest versus largest eigenvalue of the response.
    number of voxels : int (optional)
        The number of voxels used for estimating the response function.

    Notes
    -----
    In CSD there is an important pre-processing step: the estimation of the
    fiber response function. In order to do this we look for voxels with very
    anisotropic configurations. For example we can use an ROI (20x20x20) at
    the center of the volume and store the signal values for the voxels with
    FA values higher than 0.7. Of course, if we haven't precalculated FA we
    need to fit a Tensor model to the datasets. Which is what we do in this
    function.

    For the response we also need to find the average S0 in the ROI. This is
    possible using `gtab.b0s_mask()` we can find all the S0 volumes (which
    correspond to b-values equal 0) in the dataset.

    The `response` consists always of a prolate tensor created by averaging
    the highest and second highest eigenvalues in the ROI with FA higher than
    threshold. We also include the average S0s.

    We also return the `ratio` which is used for the SDT models. If requested,
    the number of voxels used for estimating the response function is also
    returned, which can be used to judge the fidelity of the response function.
    As a rule of thumb, at least 300 voxels should be used to estimate a good
    response function (see [1]_).

    References
    ----------
    .. [1] Tournier, J.D., et al. NeuroImage 2004. Direct estimation of the
    fiber orientation density function from diffusion-weighted MRI
    data using spherical deconvolution
    """

    ten = TensorModel(gtab)
    if roi_center is None:
        ci, cj, ck = np.array(data.shape[:3]) // 2
    else:
        ci, cj, ck = roi_center
    w = roi_radius
    roi = data[int(ci - w): int(ci + w),
               int(cj - w): int(cj + w),
               int(ck - w): int(ck + w)]
    tenfit = ten.fit(roi)
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    indices = np.where(fa_callable(FA, fa_thr))

    if indices[0].size == 0:
        msg = "No voxel with a FA higher than " + str(fa_thr) + " were found."
        msg += " Try a larger roi or a lower threshold."
        warnings.warn(msg, UserWarning)

    lambdas = tenfit.evals[indices][:, :2]
    S0s = roi[indices][:, np.nonzero(gtab.b0s_mask)[0]]

    response, ratio = _get_response(S0s, lambdas)

    if return_number_of_voxels:
        return response, ratio, indices[0].size

    return response, ratio
Example #19
0
    def eudx_advanced(self, dti_file, mask_file, gtab,
                      seed_num=100000, stop_val=0.1):
        """
        Tracking with more complex tensors - experimental

        Initializes the graph with nodes corresponding to the number of ROIs

        **Positional Arguments:**

                dti_file:
                    - File (registered) to use for tensor/fiber tracking
                mask_file:
                    - Brain mask to keep tensors inside the brain
                gtab:
                    - dipy formatted bval/bvec Structure

        **Optional Arguments:**
                seed_num:
                    - Number of seeds to use for fiber tracking
                stop_val:
                    - Value to cutoff fiber track
        """

        img = nb.load(dti_file)
        data = img.get_data()

        img = nb.load(mask_file)

        mask = img.get_data()
        mask = mask > 0  # to ensure binary mask

        """
        For the constrained spherical deconvolution we need to estimate the
        response function (see :ref:`example_reconst_csd`) and create a model.
        """

        response, ratio = auto_response(gtab, data, roi_radius=10,
                                        fa_thr=0.7)

        csd_model = ConstrainedSphericalDeconvModel(gtab, response)

        """
        Next, we use ``peaks_from_model`` to fit the data and calculated
        the fiber directions in all voxels.
        """

        sphere = get_sphere('symmetric724')

        csd_peaks = peaks_from_model(model=csd_model,
                                     data=data,
                                     sphere=sphere,
                                     mask=mask,
                                     relative_peak_threshold=.5,
                                     min_separation_angle=25,
                                     parallel=True)

        """
        For the tracking part, we will use ``csd_model`` fiber directions
        but stop tracking where fractional anisotropy (FA) is low (< 0.1).
        To derive the FA, used as a stopping criterion, we need to fit a
        tensor model first. Here, we use weighted least squares (WLS).
        """
        print 'tensors...'

        tensor_model = TensorModel(gtab, fit_method='WLS')
        tensor_fit = tensor_model.fit(data, mask)

        FA = fractional_anisotropy(tensor_fit.evals)

        """
        In order for the stopping values to be used with our tracking
        algorithm we need to have the same dimensions as the
        ``csd_peaks.peak_values``. For this reason, we can assign the
        same FA value to every peak direction in the same voxel in
        the following way.
        """

        stopping_values = np.zeros(csd_peaks.peak_values.shape)
        stopping_values[:] = FA[..., None]

        streamline_generator = EuDX(stopping_values,
                                    csd_peaks.peak_indices,
                                    seeds=seed_num,
                                    odf_vertices=sphere.vertices,
                                    a_low=stop_val)

        streamlines = [streamline for streamline in streamline_generator]

        return streamlines
Example #20
0
def auto_response(gtab, data, roi_center=None, roi_radius=10, fa_thr=0.7):
    """ Automatic estimation of response function using FA

    Parameters
    ----------
    gtab : GradientTable
    data : ndarray
        diffusion data
    roi_center : tuple, (3,)
        Center of ROI in data. If center is None, it is assumed that it is
        the center of the volume with shape `data.shape[:3]`.
    roi_radius : int
        radius of cubic ROI
    fa_thr : float
        FA threshold

    Returns
    -------
    response : tuple, (2,)
        (`evals`, `S0`)
    ratio : float
        the ratio between smallest versus largest eigenvalue of the response

    Notes
    -----
    In CSD there is an important pre-processing step: the estimation of the
    fiber response function. In order to do this we look for voxels with very
    anisotropic configurations. For example we can use an ROI (20x20x20) at
    the center of the volume and store the signal values for the voxels with
    FA values higher than 0.7. Of course, if we haven't precalculated FA we
    need to fit a Tensor model to the datasets. Which is what we do  in this
    function.

    For the response we also need to find the average S0 in the ROI. This is
    possible using `gtab.b0s_mask()` we can find all the S0 volumes (which
    correspond to b-values equal 0) in the dataset.

    The `response` consists always of a prolate tensor created by averaging
    the highest and second highest eigenvalues in the ROI with FA higher than
    threshold. We also include the average S0s.

    Finally, we also return the `ratio` which is used for the SDT models.
    """

    ten = TensorModel(gtab)
    if roi_center is None:
        ci, cj, ck = np.array(data.shape[:3]) / 2
    else:
        ci, cj, ck = roi_center
    w = roi_radius
    roi = data[ci - w: ci + w, cj - w: cj + w, ck - w: ck + w]
    tenfit = ten.fit(roi)
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    indices = np.where(FA > fa_thr)
    lambdas = tenfit.evals[indices][:, :2]
    S0s = roi[indices][:, np.nonzero(gtab.b0s_mask)[0]]
    S0 = np.mean(S0s)
    l01 = np.mean(lambdas, axis=0)
    evals = np.array([l01[0], l01[1], l01[1]])
    response = (evals, S0)
    ratio = evals[1]/evals[0]
    return response, ratio
Example #21
0
    def _run_interface(self, runtime):
        from dipy.core.gradients import GradientTable
        from dipy.reconst.dti import fractional_anisotropy, mean_diffusivity
        from dipy.reconst.csdeconv import recursive_response, auto_response

        img = nb.load(self.inputs.in_file)
        affine = img.get_affine()

        if isdefined(self.inputs.in_mask):
            msk = nb.load(self.inputs.in_mask).get_data()
            msk[msk > 0] = 1
            msk[msk < 0] = 0
        else:
            msk = np.ones(imref.get_shape())

        data = img.get_data().astype(np.float32)
        gtab = self._get_gradient_table()

        evals = np.nan_to_num(nb.load(self.inputs.in_evals).get_data())
        FA = np.nan_to_num(fractional_anisotropy(evals)) * msk
        indices = np.where(FA > self.inputs.fa_thresh)
        S0s = data[indices][:, np.nonzero(gtab.b0s_mask)[0]]
        S0 = np.mean(S0s)

        if self.inputs.auto:
            response, ratio = auto_response(gtab, data,
                                            roi_radius=self.inputs.roi_radius,
                                            fa_thr=self.inputs.fa_thresh)
            response = response[0].tolist() + [S0]
        elif self.inputs.recursive:
            MD = np.nan_to_num(mean_diffusivity(evals)) * msk
            indices = np.logical_or(
                FA >= 0.4, (np.logical_and(FA >= 0.15, MD >= 0.0011)))
            data = nb.load(self.inputs.in_file).get_data()
            response = recursive_response(gtab, data, mask=indices, sh_order=8,
                                          peak_thr=0.01, init_fa=0.08,
                                          init_trace=0.0021, iter=8,
                                          convergence=0.001,
                                          parallel=True)
            ratio = abs(response[1] / response[0])
        else:
            lambdas = evals[indices]
            l01 = np.sort(np.mean(lambdas, axis=0))

            response = np.array([l01[-1], l01[-2], l01[-2], S0])
            ratio = abs(response[1] / response[0])

        if ratio > 0.25:
            IFLOGGER.warn(('Estimated response is not prolate enough. '
                           'Ratio=%0.3f.') % ratio)
        elif ratio < 1.e-5 or np.any(np.isnan(response)):
            response = np.array([1.8e-3, 3.6e-4, 3.6e-4, S0])
            IFLOGGER.warn(
                ('Estimated response is not valid, using a default one'))
        else:
            IFLOGGER.info(('Estimated response: %s') % str(response[:3]))

        np.savetxt(op.abspath(self.inputs.response), response)

        wm_mask = np.zeros_like(FA)
        wm_mask[indices] = 1
        nb.Nifti1Image(
            wm_mask.astype(np.uint8), affine,
            None).to_filename(op.abspath(self.inputs.out_mask))
        return runtime
Example #22
0
def tensor(evals,
           evecs,
           scalar_colors=None,
           sphere=None,
           scale=2.2,
           norm=True):
    """Plot many tensors as ellipsoids simultaneously.

    Parameters
    ----------
    evals : (3,) or (X, 3) or (X, Y, 3) or (X, Y, Z, 3) ndarray
        eigenvalues
    evecs : (3, 3) or (X, 3, 3) or (X, Y, 3, 3) or (X, Y, Z, 3, 3) ndarray
        eigenvectors
    scalar_colors : (3,) or (X, 3) or (X, Y, 3) or (X, Y, Z, 3) ndarray
        RGB colors used to show the tensors
        Default None, color the ellipsoids using ``color_fa``
    sphere : Sphere,
        this sphere will be transformed to the tensor ellipsoid
        Default is None which uses a symmetric sphere with 724 points.
    scale : float,
        distance between ellipsoids.
    norm : boolean,
        Normalize `evals`.

    Returns
    -------
    actor : vtkActor
        Ellipsoids

    Examples
    --------
    >>> from dipy.viz import fvtk
    >>> r = fvtk.ren()
    >>> evals = np.array([1.4, .35, .35]) * 10 ** (-3)
    >>> evecs = np.eye(3)
    >>> from dipy.data import get_sphere
    >>> sphere = get_sphere('symmetric724')
    >>> fvtk.add(r, fvtk.tensor(evals, evecs, sphere=sphere))
    >>> #fvtk.show(r)

    """

    evals = np.asarray(evals)
    if evals.ndim > 4:
        raise ValueError("Wrong shape")
    evals = _makeNd(evals, 4)
    evecs = _makeNd(evecs, 5)

    grid_shape = np.array(evals.shape[:3])

    if sphere is None:
        from dipy.data import get_sphere
        sphere = get_sphere('symmetric724')
    faces = np.asarray(sphere.faces, dtype=int)
    vertices = sphere.vertices

    colors = vtk.vtkUnsignedCharArray()
    colors.SetNumberOfComponents(3)
    colors.SetName("Colors")

    if scalar_colors is None:
        from dipy.reconst.dti import color_fa, fractional_anisotropy
        cfa = color_fa(fractional_anisotropy(evals), evecs)
    else:
        cfa = _makeNd(scalar_colors, 4)

    list_sq = []
    list_cols = []

    for ijk in ndindex(grid_shape):
        ea = evals[ijk]
        if norm:
            ea /= ea.max()
        ea = np.diag(ea.copy())

        ev = evecs[ijk].copy()
        xyz = np.dot(ev, np.dot(ea, vertices.T))

        xyz += scale * (ijk - grid_shape / 2.)[:, None]

        xyz = xyz.T

        list_sq.append(xyz)

        acolor = np.zeros(xyz.shape)
        acolor[:, :] = np.interp(cfa[ijk], [0, 1], [0, 255])
        list_cols.append(acolor.astype('ubyte'))

    points = vtk.vtkPoints()
    triangles = vtk.vtkCellArray()

    for k in xrange(len(list_sq)):

        xyz = list_sq[k]

        cols = list_cols[k]

        for i in xrange(xyz.shape[0]):

            points.InsertNextPoint(*xyz[i])
            colors.InsertNextTuple3(*cols[i])

        for j in xrange(faces.shape[0]):

            triangle = vtk.vtkTriangle()
            triangle.GetPointIds().SetId(0, faces[j, 0] + k * xyz.shape[0])
            triangle.GetPointIds().SetId(1, faces[j, 1] + k * xyz.shape[0])
            triangle.GetPointIds().SetId(2, faces[j, 2] + k * xyz.shape[0])
            triangles.InsertNextCell(triangle)
            del triangle

    polydata = vtk.vtkPolyData()
    polydata.SetPoints(points)
    polydata.SetPolys(triangles)

    polydata.GetPointData().SetScalars(colors)
    polydata.Modified()

    mapper = vtk.vtkPolyDataMapper()
    if major_version <= 5:
        mapper.SetInput(polydata)
    else:
        mapper.SetInputData(polydata)

    actor = vtk.vtkActor()
    actor.SetMapper(mapper)

    return actor
Example #23
0
def test_recursive_response_calibration():
    """
    Test the recursive response calibration method.
    """
    SNR = 100
    S0 = 1
    sh_order = 8

    _, fbvals, fbvecs = get_data('small_64D')

    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)
    sphere = get_sphere('symmetric724')

    gtab = gradient_table(bvals, bvecs)
    evals = np.array([0.0015, 0.0003, 0.0003])
    evecs = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]).T
    mevals = np.array(([0.0015, 0.0003, 0.0003],
                       [0.0015, 0.0003, 0.0003]))
    angles = [(0, 0), (90, 0)]

    where_dwi = lazy_index(~gtab.b0s_mask)

    S_cross, sticks_cross = multi_tensor(gtab, mevals, S0, angles=angles,
                                         fractions=[50, 50], snr=SNR)

    S_single = single_tensor(gtab, S0, evals, evecs, snr=SNR)

    data = np.concatenate((np.tile(S_cross, (8, 1)),
                           np.tile(S_single, (2, 1))),
                          axis=0)

    odf_gt_cross = multi_tensor_odf(sphere.vertices, mevals, angles, [50, 50])

    odf_gt_single = single_tensor_odf(sphere.vertices, evals, evecs)

    response = recursive_response(gtab, data, mask=None, sh_order=8,
                                  peak_thr=0.01, init_fa=0.05,
                                  init_trace=0.0021, iter=8, convergence=0.001,
                                  parallel=False)

    csd = ConstrainedSphericalDeconvModel(gtab, response)

    csd_fit = csd.fit(data)

    assert_equal(np.all(csd_fit.shm_coeff[:, 0] >= 0), True)

    fodf = csd_fit.odf(sphere)

    directions_gt_single, _, _ = peak_directions(odf_gt_single, sphere)
    directions_gt_cross, _, _ = peak_directions(odf_gt_cross, sphere)
    directions_single, _, _ = peak_directions(fodf[8, :], sphere)
    directions_cross, _, _ = peak_directions(fodf[0, :], sphere)

    ang_sim = angular_similarity(directions_cross, directions_gt_cross)
    assert_equal(ang_sim > 1.9, True)
    assert_equal(directions_cross.shape[0], 2)
    assert_equal(directions_gt_cross.shape[0], 2)

    ang_sim = angular_similarity(directions_single, directions_gt_single)
    assert_equal(ang_sim > 0.9, True)
    assert_equal(directions_single.shape[0], 1)
    assert_equal(directions_gt_single.shape[0], 1)

    sphere = Sphere(xyz=gtab.gradients[where_dwi])
    sf = response.on_sphere(sphere)
    S = np.concatenate(([response.S0], sf))

    tenmodel = dti.TensorModel(gtab, min_signal=0.001)

    tenfit = tenmodel.fit(S)
    FA = fractional_anisotropy(tenfit.evals)
    FA_gt = fractional_anisotropy(evals)
    assert_almost_equal(FA, FA_gt, 1)
def dodata(f_name,data_path):
    dipy_home = pjoin(os.path.expanduser('~'), 'dipy_data')
    folder = pjoin(dipy_home, data_path)
    fraw = pjoin(folder, f_name+'.nii.gz')
    fbval = pjoin(folder, f_name+'.bval')
    fbvec = pjoin(folder, f_name+'.bvec')
    flabels = pjoin(folder, f_name+'.nii-label.nii.gz')
    
    bvals, bvecs = read_bvals_bvecs(fbval, fbvec)
    gtab = gradient_table(bvals, bvecs)
    
    img = nib.load(fraw)
    data = img.get_data()
    affine = img.get_affine()
    
    label_img = nib.load(flabels)
    labels=label_img.get_data()
    lap=through_label_sl.label_position(labels, labelValue=1)    
    dataslice = data[40:80, 20:80, lap[2][2] / 2]
    #print lap[2][2]/2
    
    #get_csd_gfa(f_name,data,gtab,dataslice)
    
    maskdata, mask = median_otsu(data, 2, 1, False, vol_idx=range(10, 50), dilate=2) #不去背景
    
    """ get fa and tensor evecs and ODF"""
    from dipy.reconst.dti import TensorModel,mean_diffusivity
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data, mask)
    
    sphere = get_sphere('symmetric724')
    
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
      
    np.save(os.getcwd()+'\zhibiao'+f_name+'_FA.npy',FA)
    fa_img = nib.Nifti1Image(FA.astype(np.float32), affine)
    nib.save(fa_img,os.getcwd()+'\zhibiao'+f_name+'_FA.nii.gz')
    print('Saving "DTI_tensor_fa.nii.gz" sucessful.')
    evecs_img = nib.Nifti1Image(tenfit.evecs.astype(np.float32), affine)
    nib.save(evecs_img, os.getcwd()+'\zhibiao'+f_name+'_DTI_tensor_evecs.nii.gz')
    print('Saving "DTI_tensor_evecs.nii.gz" sucessful.')
    MD1 = mean_diffusivity(tenfit.evals)
    nib.save(nib.Nifti1Image(MD1.astype(np.float32), img.get_affine()), os.getcwd()+'\zhibiao'+f_name+'_MD.nii.gz')
    
    
    #tensor_odfs = tenmodel.fit(data[20:50, 55:85, 38:39]).odf(sphere)
    #from dipy.reconst.odf import gfa
    #dti_gfa=gfa(tensor_odfs)
    
    wm_mask = (np.logical_or(FA >= 0.4, (np.logical_and(FA >= 0.15, MD >= 0.0011))))

    response = recursive_response(gtab, data, mask=wm_mask, sh_order=8,
                                  peak_thr=0.01, init_fa=0.08,
                                  init_trace=0.0021, iter=8, convergence=0.001,
                                  parallel=False)
    from dipy.reconst.csdeconv import ConstrainedSphericalDeconvModel
    csd_model = ConstrainedSphericalDeconvModel(gtab, response)
    
    #csd_fit = csd_model.fit(data)

    from dipy.direction import peaks_from_model

    csd_peaks = peaks_from_model(model=csd_model,
                                 data=data,
                                 sphere=sphere,
                                 relative_peak_threshold=.5,
                                 min_separation_angle=25,
                                 parallel=False)
    
    GFA = csd_peaks.gfa
    
    nib.save(GFA, os.getcwd()+'\zhibiao'+f_name+'_MSD.nii.gz')
    print('Saving "GFA.nii.gz" sucessful.')
    
    from dipy.reconst.shore import ShoreModel
    asm = ShoreModel(gtab)
    print('Calculating...SHORE msd')
    asmfit = asm.fit(data,mask)
    msd = asmfit.msd()
    msd[np.isnan(msd)] = 0
    
    #print GFA[:,:,slice].T
    print('Saving msd_img.png')
    nib.save(msd, os.getcwd()+'\zhibiao'+f_name+'_GFA.nii.gz')
Example #25
0
def tensor(evals, evecs, scalar_colors=None,
           sphere=None, scale=2.2, norm=True):
    """Plot many tensors as ellipsoids simultaneously.

    Parameters
    ----------
    evals : (3,) or (X, 3) or (X, Y, 3) or (X, Y, Z, 3) ndarray
        eigenvalues
    evecs : (3, 3) or (X, 3, 3) or (X, Y, 3, 3) or (X, Y, Z, 3, 3) ndarray
        eigenvectors
    scalar_colors : (3,) or (X, 3) or (X, Y, 3) or (X, Y, Z, 3) ndarray
        RGB colors used to show the tensors
        Default None, color the ellipsoids using ``color_fa``
    sphere : Sphere,
        this sphere will be transformed to the tensor ellipsoid
        Default is None which uses a symmetric sphere with 724 points.
    scale : float,
        distance between ellipsoids.
    norm : boolean,
        Normalize `evals`.

    Returns
    -------
    actor : vtkActor
        Ellipsoids

    Examples
    --------
    >>> from dipy.viz import fvtk
    >>> r = fvtk.ren()
    >>> evals = np.array([1.4, .35, .35]) * 10 ** (-3)
    >>> evecs = np.eye(3)
    >>> from dipy.data import get_sphere
    >>> sphere = get_sphere('symmetric724')
    >>> fvtk.add(r, fvtk.tensor(evals, evecs, sphere=sphere))
    >>> #fvtk.show(r)

    """

    evals = np.asarray(evals)
    if evals.ndim > 4:
        raise ValueError("Wrong shape")
    evals = _makeNd(evals, 4)
    evecs = _makeNd(evecs, 5)

    grid_shape = np.array(evals.shape[:3])

    if sphere is None:
        from dipy.data import get_sphere
        sphere = get_sphere('symmetric724')
    faces = np.asarray(sphere.faces, dtype=int)
    vertices = sphere.vertices

    colors = vtk.vtkUnsignedCharArray()
    colors.SetNumberOfComponents(3)
    colors.SetName("Colors")

    if scalar_colors is None:
        from dipy.reconst.dti import color_fa, fractional_anisotropy
        cfa = color_fa(fractional_anisotropy(evals), evecs)
    else:
        cfa = _makeNd(scalar_colors, 4)

    list_sq = []
    list_cols = []

    for ijk in ndindex(grid_shape):
        ea = evals[ijk]
        if norm:
            ea /= ea.max()
        ea = np.diag(ea.copy())

        ev = evecs[ijk].copy()
        xyz = np.dot(ev, np.dot(ea, vertices.T))

        xyz += scale * (ijk - grid_shape / 2.)[:, None]

        xyz = xyz.T

        list_sq.append(xyz)

        acolor = np.zeros(xyz.shape)
        acolor[:, :] = np.interp(cfa[ijk], [0, 1], [0, 255])
        list_cols.append(acolor.astype('ubyte'))

    points = vtk.vtkPoints()
    triangles = vtk.vtkCellArray()

    for k in xrange(len(list_sq)):

        xyz = list_sq[k]

        cols = list_cols[k]

        for i in xrange(xyz.shape[0]):

            points.InsertNextPoint(*xyz[i])
            colors.InsertNextTuple3(*cols[i])

        for j in xrange(faces.shape[0]):

            triangle = vtk.vtkTriangle()
            triangle.GetPointIds().SetId(0, faces[j, 0] + k * xyz.shape[0])
            triangle.GetPointIds().SetId(1, faces[j, 1] + k * xyz.shape[0])
            triangle.GetPointIds().SetId(2, faces[j, 2] + k * xyz.shape[0])
            triangles.InsertNextCell(triangle)
            del triangle

    polydata = vtk.vtkPolyData()
    polydata.SetPoints(points)
    polydata.SetPolys(triangles)

    polydata.GetPointData().SetScalars(colors)
    polydata.Modified()

    mapper = vtk.vtkPolyDataMapper()
    if major_version <= 5:
        mapper.SetInput(polydata)
    else:
        mapper.SetInputData(polydata)

    actor = vtk.vtkActor()
    actor.SetMapper(mapper)

    return actor
# ---------------------------------------------------------------
print('Fitting the free water DTI model...')
# ---------------------------------------------------------------

t0 = time.time()
fw_params = nls_fit_tensor(gtab, data, mask)
dt = time.time() - t0
print("This step took %f seconds to run" % dt)

# ----------------------------------------------------------------
print('Compute tensor statistic from the fitted parameters...')
# ----------------------------------------------------------------

evals = fw_params[..., :3]
FA = dti.fractional_anisotropy(evals)
MD = dti.mean_diffusivity(evals)
F = fw_params[..., 12]

# ----------------------------------------------------------------
print('Compute standard DTI for comparison...')
# ----------------------------------------------------------------

dtimodel = dti.TensorModel(gtab)

dtifit = dtimodel.fit(data, mask=mask)

dti_FA = dtifit.fa
dti_MD = dtifit.md

# ----------------------------------------------------------------
Example #27
0
    def run(self, input_files, bvalues_files, bvectors_files, mask_files,
            b0_threshold=50.0, save_metrics=[],
            out_dir='', out_dt_tensor='dti_tensors.nii.gz', out_fa='fa.nii.gz',
            out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz',
            out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz',
            out_evec='evecs.nii.gz', out_eval='evals.nii.gz',
            out_dk_tensor="dki_tensors.nii.gz",
            out_mk="mk.nii.gz", out_ak="ak.nii.gz", out_rk="rk.nii.gz"):
        """ Workflow for Diffusion Kurtosis reconstruction and for computing
        DKI metrics. Performs a DKI reconstruction on the files by 'globing'
        ``input_files`` and saves the DKI metrics in a directory specified by
        ``out_dir``.

        Parameters
        ----------
        input_files : string
            Path to the input volumes. This path may contain wildcards to
            process multiple inputs at once.
        bvalues_files : string
            Path to the bvalues files. This path may contain wildcards to use
            multiple bvalues files at once.
        bvectors_files : string
            Path to the bvalues files. This path may contain wildcards to use
            multiple bvalues files at once.
        mask_files : string
            Path to the input masks. This path may contain wildcards to use
            multiple masks at once. (default: No mask used)
        b0_threshold : float, optional
            Threshold used to find b=0 directions (default 0.0)
        save_metrics : variable string, optional
            List of metrics to save.
            Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval
            (default [] (all))
        out_dir : string, optional
            Output directory (default input file directory)
        out_dt_tensor : string, optional
            Name of the tensors volume to be saved
            (default: 'dti_tensors.nii.gz')
        out_dk_tensor : string, optional
            Name of the tensors volume to be saved
            (default 'dki_tensors.nii.gz')
        out_fa : string, optional
            Name of the fractional anisotropy volume to be saved
            (default 'fa.nii.gz')
        out_ga : string, optional
            Name of the geodesic anisotropy volume to be saved
            (default 'ga.nii.gz')
        out_rgb : string, optional
            Name of the color fa volume to be saved (default 'rgb.nii.gz')
        out_md : string, optional
            Name of the mean diffusivity volume to be saved
            (default 'md.nii.gz')
        out_ad : string, optional
            Name of the axial diffusivity volume to be saved
            (default 'ad.nii.gz')
        out_rd : string, optional
            Name of the radial diffusivity volume to be saved
            (default 'rd.nii.gz')
        out_mode : string, optional
            Name of the mode volume to be saved (default 'mode.nii.gz')
        out_evec : string, optional
            Name of the eigenvectors volume to be saved
            (default 'evecs.nii.gz')
        out_eval : string, optional
            Name of the eigenvalues to be saved (default 'evals.nii.gz')
        out_mk : string, optional
            Name of the mean kurtosis to be saved (default: 'mk.nii.gz')
        out_ak : string, optional
            Name of the axial kurtosis to be saved (default: 'ak.nii.gz')
        out_rk : string, optional
            Name of the radial kurtosis to be saved (default: 'rk.nii.gz')

        References
        ----------

        .. [1] Tabesh, A., Jensen, J.H., Ardekani, B.A., Helpern, J.A., 2011.
           Estimation of tensors and tensor-derived measures in diffusional
           kurtosis imaging. Magn Reson Med. 65(3), 823-836

        .. [2] Jensen, Jens H., Joseph A. Helpern, Anita Ramani, Hanzhang Lu,
           and Kyle Kaczynski. 2005. Diffusional Kurtosis Imaging: The
           Quantification of Non-Gaussian Water Diffusion by Means of Magnetic
           Resonance Imaging. MRM 53 (6):1432-40.
        """
        io_it = self.get_io_iterator()

        for (dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad,
             omode, oevecs, oevals, odk_tensor, omk, oak, ork) in io_it:

            logging.info('Computing DKI metrics for {0}'.format(dwi))
            data, affine = load_nifti(dwi)

            if mask is not None:
                mask = nib.load(mask).get_data().astype(np.bool)

            dkfit, _ = self.get_fitted_tensor(data, mask, bval, bvec,
                                              b0_threshold)

            if not save_metrics:
                save_metrics = ['mk', 'rk', 'ak', 'fa', 'md', 'rd', 'ad', 'ga',
                                'rgb', 'mode', 'evec', 'eval', 'dt_tensor',
                                'dk_tensor']

            evals, evecs, kt = split_dki_param(dkfit.model_params)
            FA = fractional_anisotropy(evals)
            FA[np.isnan(FA)] = 0
            FA = np.clip(FA, 0, 1)

            if 'dt_tensor' in save_metrics:
                tensor_vals = lower_triangular(dkfit.quadratic_form)
                correct_order = [0, 1, 3, 2, 4, 5]
                tensor_vals_reordered = tensor_vals[..., correct_order]
                save_nifti(otensor, tensor_vals_reordered.astype(np.float32),
                           affine)

            if 'dk_tensor' in save_metrics:
                save_nifti(odk_tensor, dkfit.kt.astype(np.float32), affine)

            if 'fa' in save_metrics:
                save_nifti(ofa, FA.astype(np.float32), affine)

            if 'ga' in save_metrics:
                GA = geodesic_anisotropy(dkfit.evals)
                save_nifti(oga, GA.astype(np.float32), affine)

            if 'rgb' in save_metrics:
                RGB = color_fa(FA, dkfit.evecs)
                save_nifti(orgb, np.array(255 * RGB, 'uint8'), affine)

            if 'md' in save_metrics:
                MD = mean_diffusivity(dkfit.evals)
                save_nifti(omd, MD.astype(np.float32), affine)

            if 'ad' in save_metrics:
                AD = axial_diffusivity(dkfit.evals)
                save_nifti(oad, AD.astype(np.float32), affine)

            if 'rd' in save_metrics:
                RD = radial_diffusivity(dkfit.evals)
                save_nifti(orad, RD.astype(np.float32), affine)

            if 'mode' in save_metrics:
                MODE = get_mode(dkfit.quadratic_form)
                save_nifti(omode, MODE.astype(np.float32), affine)

            if 'evec' in save_metrics:
                save_nifti(oevecs, dkfit.evecs.astype(np.float32), affine)

            if 'eval' in save_metrics:
                save_nifti(oevals, dkfit.evals.astype(np.float32), affine)

            if 'mk' in save_metrics:
                save_nifti(omk, dkfit.mk().astype(np.float32), affine)

            if 'ak' in save_metrics:
                save_nifti(oak, dkfit.ak().astype(np.float32), affine)

            if 'rk' in save_metrics:
                save_nifti(ork, dkfit.rk().astype(np.float32), affine)

            logging.info('DKI metrics saved in {0}'.
                         format(os.path.dirname(oevals)))
Example #28
0
    def run(self, input_files, bvalues_files, bvectors_files, mask_files,
            b0_threshold=50, bvecs_tol=0.01, save_metrics=[],
            out_dir='', out_tensor='tensors.nii.gz', out_fa='fa.nii.gz',
            out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz',
            out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz',
            out_evec='evecs.nii.gz', out_eval='evals.nii.gz'):
        """ Workflow for tensor reconstruction and for computing DTI metrics.
        using Weighted Least-Squares.
        Performs a tensor reconstruction on the files by 'globing'
        ``input_files`` and saves the DTI metrics in a directory specified by
        ``out_dir``.

        Parameters
        ----------
        input_files : string
            Path to the input volumes. This path may contain wildcards to
            process multiple inputs at once.
        bvalues_files : string
            Path to the bvalues files. This path may contain wildcards to use
            multiple bvalues files at once.
        bvectors_files : string
            Path to the bvectors files. This path may contain wildcards to use
            multiple bvectors files at once.
        mask_files : string
            Path to the input masks. This path may contain wildcards to use
            multiple masks at once. (default: No mask used)
        b0_threshold : float, optional
            Threshold used to find b=0 directions (default 0.0)
        bvecs_tol : float, optional
            Threshold used to check that norm(bvec) = 1 +/- bvecs_tol
            b-vectors are unit vectors (default 0.01)
        save_metrics : variable string, optional
            List of metrics to save.
            Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval
            (default [] (all))
        out_dir : string, optional
            Output directory (default input file directory)
        out_tensor : string, optional
            Name of the tensors volume to be saved (default 'tensors.nii.gz')
        out_fa : string, optional
            Name of the fractional anisotropy volume to be saved
            (default 'fa.nii.gz')
        out_ga : string, optional
            Name of the geodesic anisotropy volume to be saved
            (default 'ga.nii.gz')
        out_rgb : string, optional
            Name of the color fa volume to be saved (default 'rgb.nii.gz')
        out_md : string, optional
            Name of the mean diffusivity volume to be saved
            (default 'md.nii.gz')
        out_ad : string, optional
            Name of the axial diffusivity volume to be saved
            (default 'ad.nii.gz')
        out_rd : string, optional
            Name of the radial diffusivity volume to be saved
            (default 'rd.nii.gz')
        out_mode : string, optional
            Name of the mode volume to be saved (default 'mode.nii.gz')
        out_evec : string, optional
            Name of the eigenvectors volume to be saved
            (default 'evecs.nii.gz')
        out_eval : string, optional
            Name of the eigenvalues to be saved (default 'evals.nii.gz')

        References
        ----------
        .. [1] Basser, P.J., Mattiello, J., LeBihan, D., 1994. Estimation of
           the effective self-diffusion tensor from the NMR spin echo. J Magn
           Reson B 103, 247-254.

        .. [2] Basser, P., Pierpaoli, C., 1996. Microstructural and
           physiological features of tissues elucidated by quantitative
           diffusion-tensor MRI.  Journal of Magnetic Resonance 111, 209-219.

        .. [3] Lin-Ching C., Jones D.K., Pierpaoli, C. 2005. RESTORE: Robust
           estimation of tensors by outlier rejection. MRM 53: 1088-1095

        .. [4] hung, SW., Lu, Y., Henry, R.G., 2006. Comparison of bootstrap
           approaches for estimation of uncertainties of DTI parameters.
           NeuroImage 33, 531-541.

        """
        io_it = self.get_io_iterator()

        for dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, \
                omode, oevecs, oevals in io_it:

            logging.info('Computing DTI metrics for {0}'.format(dwi))
            data, affine = load_nifti(dwi)

            if mask is not None:
                mask = nib.load(mask).get_data().astype(np.bool)

            tenfit, _ = self.get_fitted_tensor(data, mask, bval, bvec,
                                               b0_threshold, bvecs_tol)

            if not save_metrics:
                save_metrics = ['fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode',
                                'evec', 'eval', 'tensor']

            FA = fractional_anisotropy(tenfit.evals)
            FA[np.isnan(FA)] = 0
            FA = np.clip(FA, 0, 1)

            if 'tensor' in save_metrics:
                tensor_vals = lower_triangular(tenfit.quadratic_form)
                correct_order = [0, 1, 3, 2, 4, 5]
                tensor_vals_reordered = tensor_vals[..., correct_order]

                save_nifti(otensor, tensor_vals_reordered.astype(np.float32),
                           affine)

            if 'fa' in save_metrics:
                save_nifti(ofa, FA.astype(np.float32), affine)

            if 'ga' in save_metrics:
                GA = geodesic_anisotropy(tenfit.evals)
                save_nifti(oga, GA.astype(np.float32), affine)

            if 'rgb' in save_metrics:
                RGB = color_fa(FA, tenfit.evecs)
                save_nifti(orgb, np.array(255 * RGB, 'uint8'), affine)

            if 'md' in save_metrics:
                MD = mean_diffusivity(tenfit.evals)
                save_nifti(omd, MD.astype(np.float32), affine)

            if 'ad' in save_metrics:
                AD = axial_diffusivity(tenfit.evals)
                save_nifti(oad, AD.astype(np.float32), affine)

            if 'rd' in save_metrics:
                RD = radial_diffusivity(tenfit.evals)
                save_nifti(orad, RD.astype(np.float32), affine)

            if 'mode' in save_metrics:
                MODE = get_mode(tenfit.quadratic_form)
                save_nifti(omode, MODE.astype(np.float32), affine)

            if 'evec' in save_metrics:
                save_nifti(oevecs, tenfit.evecs.astype(np.float32), affine)

            if 'eval' in save_metrics:
                save_nifti(oevals, tenfit.evals.astype(np.float32), affine)

            dname_ = os.path.dirname(oevals)
            if dname_ == '':
                logging.info('DTI metrics saved in current directory')
            else:
                logging.info(
                        'DTI metrics saved in {0}'.format(dname_))
Example #29
0
def tens_mod_fa_est(gtab_file, dwi_file, B0_mask):
    """
    Estimate a tensor FA image to use for registrations.

    Parameters
    ----------
    gtab_file : str
        File path to pickled DiPy gradient table object.
    dwi_file : str
        File path to diffusion weighted image.
    B0_mask : str
        File path to B0 brain mask.

    Returns
    -------
    fa_path : str
        File path to FA Nifti1Image.
    B0_mask : str
        File path to B0 brain mask Nifti1Image.
    gtab_file : str
        File path to pickled DiPy gradient table object.
    dwi_file : str
        File path to diffusion weighted Nifti1Image.
    fa_md_path : str
        File path to FA/MD mask Nifti1Image.
    """
    import os
    from dipy.io import load_pickle
    from dipy.reconst.dti import TensorModel
    from dipy.reconst.dti import fractional_anisotropy, mean_diffusivity

    gtab = load_pickle(gtab_file)

    data = nib.load(dwi_file, mmap=False).get_fdata(dtype=np.float32)

    print("Generating tensor FA image to use for registrations...")
    nodif_B0_img = nib.load(B0_mask, mmap=False)
    nodif_B0_mask_data = nodif_B0_img.get_fdata().astype("bool")
    model = TensorModel(gtab)
    mod = model.fit(data, nodif_B0_mask_data)
    FA = fractional_anisotropy(mod.evals)
    # MD = mean_diffusivity(mod.evals)
    # FA_MD = np.logical_or(
    #     FA >= 0.2, (np.logical_and(
    #         FA >= 0.08, MD >= 0.0011)))
    # FA_MD[np.isnan(FA_MD)] = 0
    FA = np.nan_to_num(np.asarray(FA.astype('float32')))

    fa_path = f"{os.path.dirname(B0_mask)}{'/tensor_fa.nii.gz'}"
    nib.save(nib.Nifti1Image(FA, nodif_B0_img.affine), fa_path)

    # md_path = f"{os.path.dirname(B0_mask)}{'/tensor_md.nii.gz'}"
    # nib.save(
    #     nib.Nifti1Image(
    #         MD.astype(
    #             np.float32),
    #         nodif_B0_img.affine),
    #     md_path)

    nodif_B0_img.uncache()
    del FA

    return fa_path, B0_mask, gtab_file, dwi_file
def main():
    parser = _build_args_parser()
    args = parser.parse_args()

    if not args.not_all:
        args.fa = args.fa or 'fa.nii.gz'
        args.ga = args.ga or 'ga.nii.gz'
        args.rgb = args.rgb or 'rgb.nii.gz'
        args.md = args.md or 'md.nii.gz'
        args.ad = args.ad or 'ad.nii.gz'
        args.rd = args.rd or 'rd.nii.gz'
        args.mode = args.mode or 'mode.nii.gz'
        args.norm = args.norm or 'tensor_norm.nii.gz'
        args.tensor = args.tensor or 'tensor.nii.gz'
        args.evecs = args.evecs or 'tensor_evecs.nii.gz'
        args.evals = args.evals or 'tensor_evals.nii.gz'
        args.residual = args.residual or 'dti_residual.nii.gz'
        args.p_i_signal =\
            args.p_i_signal or 'physically_implausible_signals_mask.nii.gz'
        args.pulsation = args.pulsation or 'pulsation_and_misalignment.nii.gz'

    outputs = [
        args.fa, args.ga, args.rgb, args.md, args.ad, args.rd, args.mode,
        args.norm, args.tensor, args.evecs, args.evals, args.residual,
        args.p_i_signal, args.pulsation
    ]
    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_data()
    affine = img.get_affine()
    if args.mask is None:
        mask = None
    else:
        mask = nib.load(args.mask).get_data().astype(np.bool)

    # Validate bvals and bvecs
    logging.info('Tensor estimation with the %s method...', args.method)
    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)

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

    # Get tensors
    if args.method == 'restore':
        sigma = ne.estimate_sigma(data)
        tenmodel = TensorModel(gtab,
                               fit_method=args.method,
                               sigma=sigma,
                               min_signal=_get_min_nonzero_signal(data))
    else:
        tenmodel = TensorModel(gtab,
                               fit_method=args.method,
                               min_signal=_get_min_nonzero_signal(data))

    tenfit = tenmodel.fit(data, mask)

    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    FA = np.clip(FA, 0, 1)

    if args.tensor:
        # Get the Tensor values and format them for visualisation
        # in the Fibernavigator.
        tensor_vals = lower_triangular(tenfit.quadratic_form)
        correct_order = [0, 1, 3, 2, 4, 5]
        tensor_vals_reordered = tensor_vals[..., correct_order]
        fiber_tensors = nib.Nifti1Image(
            tensor_vals_reordered.astype(np.float32), affine)
        nib.save(fiber_tensors, args.tensor)

    if args.fa:
        fa_img = nib.Nifti1Image(FA.astype(np.float32), affine)
        nib.save(fa_img, args.fa)

    if args.ga:
        GA = geodesic_anisotropy(tenfit.evals)
        GA[np.isnan(GA)] = 0

        ga_img = nib.Nifti1Image(GA.astype(np.float32), affine)
        nib.save(ga_img, args.ga)

    if args.rgb:
        RGB = color_fa(FA, tenfit.evecs)
        rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine)
        nib.save(rgb_img, args.rgb)

    if args.md:
        MD = mean_diffusivity(tenfit.evals)
        md_img = nib.Nifti1Image(MD.astype(np.float32), affine)
        nib.save(md_img, args.md)

    if args.ad:
        AD = axial_diffusivity(tenfit.evals)
        ad_img = nib.Nifti1Image(AD.astype(np.float32), affine)
        nib.save(ad_img, args.ad)

    if args.rd:
        RD = radial_diffusivity(tenfit.evals)
        rd_img = nib.Nifti1Image(RD.astype(np.float32), affine)
        nib.save(rd_img, args.rd)

    if args.mode:
        # Compute tensor mode
        inter_mode = dipy_mode(tenfit.quadratic_form)

        # Since the mode computation can generate NANs when not masked,
        # we need to remove them.
        non_nan_indices = np.isfinite(inter_mode)
        mode = np.zeros(inter_mode.shape)
        mode[non_nan_indices] = inter_mode[non_nan_indices]

        mode_img = nib.Nifti1Image(mode.astype(np.float32), affine)
        nib.save(mode_img, args.mode)

    if args.norm:
        NORM = norm(tenfit.quadratic_form)
        norm_img = nib.Nifti1Image(NORM.astype(np.float32), affine)
        nib.save(norm_img, args.norm)

    if args.evecs:
        evecs = tenfit.evecs.astype(np.float32)
        evecs_img = nib.Nifti1Image(evecs, affine)
        nib.save(evecs_img, args.evecs)

        # save individual e-vectors also
        e1_img = nib.Nifti1Image(evecs[..., 0], affine)
        e2_img = nib.Nifti1Image(evecs[..., 1], affine)
        e3_img = nib.Nifti1Image(evecs[..., 2], affine)

        nib.save(e1_img, add_filename_suffix(args.evecs, '_v1'))
        nib.save(e2_img, add_filename_suffix(args.evecs, '_v2'))
        nib.save(e3_img, add_filename_suffix(args.evecs, '_v3'))

    if args.evals:
        evals = tenfit.evals.astype(np.float32)
        evals_img = nib.Nifti1Image(evals, affine)
        nib.save(evals_img, args.evals)

        # save individual e-values also
        e1_img = nib.Nifti1Image(evals[..., 0], affine)
        e2_img = nib.Nifti1Image(evals[..., 1], affine)
        e3_img = nib.Nifti1Image(evals[..., 2], affine)

        nib.save(e1_img, add_filename_suffix(args.evals, '_e1'))
        nib.save(e2_img, add_filename_suffix(args.evals, '_e2'))
        nib.save(e3_img, add_filename_suffix(args.evals, '_e3'))

    if args.p_i_signal:
        S0 = np.mean(data[..., gtab.b0s_mask], axis=-1, keepdims=True)
        DWI = data[..., ~gtab.b0s_mask]
        pis_mask = np.max(S0 < DWI, axis=-1)

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

        pis_img = nib.Nifti1Image(pis_mask.astype(np.int16), affine)
        nib.save(pis_img, args.p_i_signal)

    if args.pulsation:
        STD = np.std(data[..., ~gtab.b0s_mask], axis=-1)

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

        std_img = nib.Nifti1Image(STD.astype(np.float32), affine)
        nib.save(std_img, add_filename_suffix(args.pulsation, '_std_dwi'))

        if np.sum(gtab.b0s_mask) <= 1:
            logger.info('Not enough b=0 images to output standard '
                        'deviation map')
        else:
            if len(np.where(gtab.b0s_mask)) == 2:
                logger.info('Only two b=0 images. Be careful with the '
                            'interpretation of this std map')

            STD = np.std(data[..., gtab.b0s_mask], axis=-1)

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

            std_img = nib.Nifti1Image(STD.astype(np.float32), affine)
            nib.save(std_img, add_filename_suffix(args.pulsation, '_std_b0'))

    if args.residual:
        if args.mask is None:
            logger.info("Outlier detection will not be performed, since no "
                        "mask was provided.")
        S0 = np.mean(data[..., gtab.b0s_mask], axis=-1)
        data_p = tenfit.predict(gtab, S0)
        R = np.mean(np.abs(data_p[..., ~gtab.b0s_mask] -
                           data[..., ~gtab.b0s_mask]),
                    axis=-1)

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

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

        R_k = np.zeros(data.shape[-1])  # mean residual per DWI
        std = np.zeros(data.shape[-1])  # std residual per DWI
        q1 = np.zeros(data.shape[-1])  # first quartile
        q3 = np.zeros(data.shape[-1])  # third quartile
        iqr = np.zeros(data.shape[-1])  # interquartile
        for i in range(data.shape[-1]):
            x = np.abs(data_p[..., i] - data[..., i])[mask]
            R_k[i] = np.mean(x)
            std[i] = np.std(x)
            q3[i], q1[i] = np.percentile(x, [75, 25])
            iqr[i] = q3[i] - q1[i]

            # Outliers are observations that fall below Q1 - 1.5(IQR) or
            # above Q3 + 1.5(IQR) We check if a volume is an outlier only if
            # we have a mask, else we are biased.
            if args.mask is not None and R_k[i] < (q1[i] - 1.5 * iqr[i]) \
                    or R_k[i] > (q3[i] + 1.5 * iqr[i]):
                logger.warning(
                    'WARNING: Diffusion-Weighted Image i=%s is an '
                    'outlier', i)

        residual_basename, _ = split_name_with_nii(args.residual)
        res_stats_basename = residual_basename + ".npy"
        np.save(add_filename_suffix(res_stats_basename, "_mean_residuals"),
                R_k)
        np.save(add_filename_suffix(res_stats_basename, "_q1_residuals"), q1)
        np.save(add_filename_suffix(res_stats_basename, "_q3_residuals"), q3)
        np.save(add_filename_suffix(res_stats_basename, "_iqr_residuals"), iqr)
        np.save(add_filename_suffix(res_stats_basename, "_std_residuals"), std)

        # To do: I would like to have an error bar with q1 and q3.
        # Now, q1 acts as a std
        dwi = np.arange(R_k[~gtab.b0s_mask].shape[0])
        plt.bar(dwi,
                R_k[~gtab.b0s_mask],
                0.75,
                color='y',
                yerr=q1[~gtab.b0s_mask])
        plt.xlabel('DW image')
        plt.ylabel('Mean residuals +- q1')
        plt.title('Residuals')
        plt.savefig(residual_basename + '_residuals_stats.png')
Example #31
0
def prepare_data_for_actors(dwi_filename,
                            bvals_filename,
                            bvecs_filename,
                            target_template_filename,
                            slices_choice,
                            shells=None):
    # Load and prepare the data
    dwi_img = nib.load(dwi_filename)
    dwi_data = dwi_img.get_data()
    dwi_affine = dwi_img.get_affine()

    bvals, bvecs = read_bvals_bvecs(bvals_filename, bvecs_filename)

    target_template_img = nib.load(target_template_filename)
    target_template_data = target_template_img.get_data()
    target_template_affine = target_template_img.affine
    mask_data = np.zeros(target_template_data.shape)
    mask_data[target_template_data > 0] = 1

    # Prepare mask for tensors fit
    x_slice, y_slice, z_slice = slices_choice
    mask_data = prepare_slices_mask(mask_data, x_slice, y_slice, z_slice)

    # Extract B0
    gtab = gradient_table(bvals, normalize_bvecs(bvecs), b0_threshold=10)
    b0_idx = np.where(gtab.b0s_mask)[0]
    mean_b0 = np.mean(dwi_data[..., b0_idx], axis=3, dtype=dwi_data.dtype)

    if shells:
        indices = [get_shell_indices(bvals, shell) for shell in shells]
        indices = np.sort(np.hstack(indices))

        if len(indices) < 1:
            raise ValueError(
                'There are no volumes that have the supplied b-values.')
        shell_data = np.zeros((dwi_data.shape[:-1] + (len(indices), )),
                              dtype=dwi_data.dtype)
        shell_bvecs = np.zeros((len(indices), 3))
        shell_bvals = np.zeros((len(indices), ))
        for i, indice in enumerate(indices):
            shell_data[..., i] = dwi_data[..., indice]
            shell_bvals[i] = bvals[indice]
            shell_bvecs[i, :] = bvecs[indice, :]
    else:
        shell_data = dwi_data
        shell_bvals = bvals
        shell_bvecs = bvecs

    # Register the DWI data to the template
    transformed_dwi, transformation = register_image(
        target_template_data,
        target_template_affine,
        mean_b0,
        dwi_affine,
        transformation_type='rigid',
        dwi=shell_data)

    # Rotate gradients
    rotated_bvecs = np.dot(shell_bvecs, transformation[0:3, 0:3])

    rotated_bvecs = normalize_bvecs(rotated_bvecs)
    rotated_gtab = gradient_table(shell_bvals, rotated_bvecs, b0_threshold=10)

    # Get tensors
    tensor_model = TensorModel(rotated_gtab, fit_method='LS')
    tensor_fit = tensor_model.fit(transformed_dwi, mask_data)
    # Get FA
    fa_map = np.clip(fractional_anisotropy(tensor_fit.evals), 0, 1)

    # Get eigen vals/vecs
    evals = np.zeros(target_template_data.shape + (1, ))
    evals[..., 0] = tensor_fit.evals[..., 0] / np.max(tensor_fit.evals[..., 0])
    evecs = np.zeros(target_template_data.shape + (1, 3))
    evecs[:, :, :, 0, :] = tensor_fit.evecs[..., 0]

    return fa_map, evals, evecs
def nonlinfit_fn(dwi, bvecs, bvals, base_name):
    import nibabel as nb
    import numpy as np
    import os.path as op
    import dipy.reconst.dti as dti
    from dipy.core.gradients import GradientTable

    dwi_img = nb.load(dwi)
    dwi_data = dwi_img.get_data()
    dwi_affine = dwi_img.get_affine()
    
    from dipy.segment.mask import median_otsu
    b0_mask, mask = median_otsu(dwi_data, 2, 4)
    # Mask the data so that tensors are not fit for
    # unnecessary voxels
    mask_img = nb.Nifti1Image(mask.astype(np.float32), dwi_affine)
    b0_imgs = nb.Nifti1Image(b0_mask.astype(np.float32), dwi_affine)
    b0_img = nb.four_to_three(b0_imgs)[0]

    out_mask_name = op.abspath(base_name + '_binary_mask.nii.gz')
    out_b0_name = op.abspath(base_name + '_b0_mask.nii.gz')
    nb.save(mask_img, out_mask_name)
    nb.save(b0_img, out_b0_name)

    # Load the gradient strengths and directions
    bvals = np.loadtxt(bvals)
    gradients = np.loadtxt(bvecs).T

    # Place in Dipy's preferred format
    gtab = GradientTable(gradients)
    gtab.bvals = bvals

    # Fit the tensors to the data
    tenmodel = dti.TensorModel(gtab, fit_method="NLLS")
    tenfit = tenmodel.fit(dwi_data, mask)

    # Calculate the fit, fa, and md of each voxel's tensor
    tensor_data = tenfit.lower_triangular()
    print('Computing anisotropy measures (FA, MD, RGB)')
    from dipy.reconst.dti import fractional_anisotropy, color_fa

    evals = tenfit.evals.astype(np.float32)
    FA = fractional_anisotropy(np.abs(evals))
    FA = np.clip(FA, 0, 1)

    MD = dti.mean_diffusivity(np.abs(evals))
    norm = dti.norm(tenfit.quadratic_form)

    RGB = color_fa(FA, tenfit.evecs)

    evecs = tenfit.evecs.astype(np.float32)
    mode = tenfit.mode.astype(np.float32)

    # Write tensor as a 4D Nifti image with the original affine
    tensor_fit_img = nb.Nifti1Image(tensor_data.astype(np.float32), dwi_affine)
    mode_img = nb.Nifti1Image(mode.astype(np.float32), dwi_affine)
    norm_img = nb.Nifti1Image(norm.astype(np.float32), dwi_affine)
    FA_img = nb.Nifti1Image(FA.astype(np.float32), dwi_affine)
    evecs_img = nb.Nifti1Image(evecs, dwi_affine)
    evals_img = nb.Nifti1Image(evals, dwi_affine)
    rgb_img = nb.Nifti1Image(np.array(255 * RGB, 'uint8'), dwi_affine)
    MD_img = nb.Nifti1Image(MD.astype(np.float32), dwi_affine)

    out_tensor_file = op.abspath(base_name + "_tensor.nii.gz")
    out_mode_file = op.abspath(base_name + "_mode.nii.gz")
    out_fa_file = op.abspath(base_name + "_fa.nii.gz")
    out_norm_file = op.abspath(base_name + "_norm.nii.gz")
    out_evals_file = op.abspath(base_name + "_evals.nii.gz")
    out_evecs_file = op.abspath(base_name + "_evecs.nii.gz")
    out_rgb_fa_file = op.abspath(base_name + "_rgb_fa.nii.gz")
    out_md_file = op.abspath(base_name + "_md.nii.gz")

    nb.save(rgb_img, out_rgb_fa_file)
    nb.save(norm_img, out_norm_file)
    nb.save(mode_img, out_mode_file)
    nb.save(tensor_fit_img, out_tensor_file)
    nb.save(evecs_img, out_evecs_file)
    nb.save(evals_img, out_evals_file)
    nb.save(FA_img, out_fa_file)
    nb.save(MD_img, out_md_file)
    print('Tensor fit image saved as {i}'.format(i=out_tensor_file))
    print('FA image saved as {i}'.format(i=out_fa_file))
    print('MD image saved as {i}'.format(i=out_md_file))
    return out_tensor_file, out_fa_file, out_md_file, \
        out_evecs_file, out_evals_file, out_rgb_fa_file, out_norm_file, \
        out_mode_file, out_mask_name, out_b0_name
Example #33
0
    def run(self, input_files, bvalues, bvectors, mask_files, b0_threshold=0.0,
            save_metrics=[],
            out_dir='', out_tensor='tensors.nii.gz', out_fa='fa.nii.gz',
            out_ga='ga.nii.gz', out_rgb='rgb.nii.gz', out_md='md.nii.gz',
            out_ad='ad.nii.gz', out_rd='rd.nii.gz', out_mode='mode.nii.gz',
            out_evec='evecs.nii.gz', out_eval='evals.nii.gz'):

        """ Workflow for tensor reconstruction and for computing DTI metrics.
        Performs a tensor reconstruction on the files by 'globing'
        ``input_files`` and saves the DTI metrics in a directory specified by
        ``out_dir``.

        Parameters
        ----------
        input_files : string
            Path to the input volumes. This path may contain wildcards to
            process multiple inputs at once.
        bvalues : string
            Path to the bvalues files. This path may contain wildcards to use
            multiple bvalues files at once.
        bvectors : string
            Path to the bvalues files. This path may contain wildcards to use
            multiple bvalues files at once.
        mask_files : string
            Path to the input masks. This path may contain wildcards to use
            multiple masks at once. (default: No mask used)
        b0_threshold : float, optional
            Threshold used to find b=0 directions (default 0.0)
        save_metrics : variable string, optional
            List of metrics to save.
            Possible values: fa, ga, rgb, md, ad, rd, mode, tensor, evec, eval
            (default [] (all))
        out_dir : string, optional
            Output directory (default input file directory)
        out_tensor : string, optional
            Name of the tensors volume to be saved (default 'tensors.nii.gz')
        out_fa : string, optional
            Name of the fractional anisotropy volume to be saved
            (default 'fa.nii.gz')
        out_ga : string, optional
            Name of the geodesic anisotropy volume to be saved
            (default 'ga.nii.gz')
        out_rgb : string, optional
            Name of the color fa volume to be saved (default 'rgb.nii.gz')
        out_md : string, optional
            Name of the mean diffusivity volume to be saved
            (default 'md.nii.gz')
        out_ad : string, optional
            Name of the axial diffusivity volume to be saved
            (default 'ad.nii.gz')
        out_rd : string, optional
            Name of the radial diffusivity volume to be saved
            (default 'rd.nii.gz')
        out_mode : string, optional
            Name of the mode volume to be saved (default 'mode.nii.gz')
        out_evec : string, optional
            Name of the eigenvectors volume to be saved
            (default 'evecs.nii.gz')
        out_eval : string, optional
            Name of the eigenvalues to be saved (default 'evals.nii.gz')
        """
        io_it = self.get_io_iterator()

        for dwi, bval, bvec, mask, otensor, ofa, oga, orgb, omd, oad, orad, \
            omode, oevecs, oevals in io_it:

            logging.info('Computing DTI metrics for {0}'.format(dwi))

            img = nib.load(dwi)
            data = img.get_data()
            affine = img.get_affine()

            if mask is None:
                mask = None
            else:
                mask = nib.load(mask).get_data().astype(np.bool)

            tenfit, _ = self.get_fitted_tensor(data, mask, bval, bvec,
                                               b0_threshold)

            if not save_metrics:
                save_metrics = ['fa', 'md', 'rd', 'ad', 'ga', 'rgb', 'mode',
                                'evec', 'eval', 'tensor']

            FA = fractional_anisotropy(tenfit.evals)
            FA[np.isnan(FA)] = 0
            FA = np.clip(FA, 0, 1)

            if 'tensor' in save_metrics:
                tensor_vals = lower_triangular(tenfit.quadratic_form)
                correct_order = [0, 1, 3, 2, 4, 5]
                tensor_vals_reordered = tensor_vals[..., correct_order]
                fiber_tensors = nib.Nifti1Image(tensor_vals_reordered.astype(
                    np.float32), affine)
                nib.save(fiber_tensors, otensor)

            if 'fa' in save_metrics:
                fa_img = nib.Nifti1Image(FA.astype(np.float32), affine)
                nib.save(fa_img, ofa)

            if 'ga' in save_metrics:
                GA = geodesic_anisotropy(tenfit.evals)
                ga_img = nib.Nifti1Image(GA.astype(np.float32), affine)
                nib.save(ga_img, oga)

            if 'rgb' in save_metrics:
                RGB = color_fa(FA, tenfit.evecs)
                rgb_img = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine)
                nib.save(rgb_img, orgb)

            if 'md' in save_metrics:
                MD = mean_diffusivity(tenfit.evals)
                md_img = nib.Nifti1Image(MD.astype(np.float32), affine)
                nib.save(md_img, omd)

            if 'ad' in save_metrics:
                AD = axial_diffusivity(tenfit.evals)
                ad_img = nib.Nifti1Image(AD.astype(np.float32), affine)
                nib.save(ad_img, oad)

            if 'rd' in save_metrics:
                RD = radial_diffusivity(tenfit.evals)
                rd_img = nib.Nifti1Image(RD.astype(np.float32), affine)
                nib.save(rd_img, orad)

            if 'mode' in save_metrics:
                MODE = get_mode(tenfit.quadratic_form)
                mode_img = nib.Nifti1Image(MODE.astype(np.float32), affine)
                nib.save(mode_img, omode)

            if 'evec' in save_metrics:
                evecs_img = nib.Nifti1Image(tenfit.evecs.astype(np.float32), affine)
                nib.save(evecs_img, oevecs)

            if 'eval' in save_metrics:
                evals_img = nib.Nifti1Image(tenfit.evals.astype(np.float32), affine)
                nib.save(evals_img, oevals)

            logging.info('DTI metrics saved in {0}'.
                         format(os.path.dirname(oevals)))
Example #34
0
def test_fa_of_zero():
    evals = np.zeros((4, 3))
    fa = fractional_anisotropy(evals)
    assert_array_equal(fa, 0)
Example #35
0
    def compute_tensors(self, dti_vol, atlas_file, gtab):
        # WGR:TODO figure out how to organize tensor options and formats
        # WGR:TODO figure out how to deal with files on disk vs. in workspace
        """
        Takes registered DTI image and produces tensors

        **Positional Arguments:**

                dti_vol:
                    - Registered DTI volume, from workspace.
                atlas_file:
                    - File containing an atlas (or brain mask).
                gtab:
                    - Structure containing dipy formatted bval/bvec information
        """

        labeldata = nib.load(atlas_file)

        label = labeldata.get_data()

        """
        Create a brain mask. Here we just threshold labels.
        """

        mask = (label > 0)

        gtab.info
        print data.shape
        """
        For the constrained spherical deconvolution we need to estimate the
        response function (see :ref:`example_reconst_csd`) and create a model.
        """

        response, ratio = auto_response(gtab, dti_vol, roi_radius=10,
                                        fa_thr=0.7)

        csd_model = ConstrainedSphericalDeconvModel(gtab, response)

        """
        Next, we use ``peaks_from_model`` to fit the data and calculated
        the fiber directions in all voxels.
        """

        sphere = get_sphere('symmetric724')

        csd_peaks = peaks_from_model(model=csd_model,
                                     data=data,
                                     sphere=sphere,
                                     mask=mask,
                                     relative_peak_threshold=.5,
                                     min_separation_angle=25,
                                     parallel=True)

        """
        For the tracking part, we will use ``csd_model`` fiber directions
        but stop tracking where fractional anisotropy (FA) is low (< 0.1).
        To derive the FA, used as a stopping criterion, we need to fit a
        tensor model first. Here, we use weighted least squares (WLS).
        """
        print 'tensors...'

        tensor_model = TensorModel(gtab, fit_method='WLS')
        tensor_fit = tensor_model.fit(data, mask)

        FA = fractional_anisotropy(tensor_fit.evals)

        """
        In order for the stopping values to be used with our tracking
        algorithm we need to have the same dimensions as the
        ``csd_peaks.peak_values``. For this reason, we can assign the
        same FA value to every peak direction in the same voxel in
        the following way.
        """

        stopping_values = np.zeros(csd_peaks.peak_values.shape)
        stopping_values[:] = FA[..., None]
        print datetime.now() - startTime
        pass
from dipy.io.pickles import save_pickle, load_pickle

from time import time

threshold = 0.75
from dipy.data import get_sphere
sphere = get_sphere('symmetric724')
dname = 'SNR20/'

if __name__ == '__main__':
    data, affine, gtab = get_test_hardi(snr=20, denoised=0)    
    mask = get_test_mask()
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data, mask)
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    nib.save(nib.Nifti1Image(FA.astype('float32'), affine), 
             'FA.nii.gz')
    
    for i in range(27) :
        print 'White matter bundle: ', i
        wm_mask = get_test_wm_mask(i)
        print(FA[wm_mask].max())
        indicesAniso = np.where(np.logical_and(FA > threshold, wm_mask))  

        print '    Response function'
        S0s = data[indicesAniso][:, np.nonzero(gtab.b0s_mask)[0]]                               
        S0 = np.mean(S0s)
        if S0 == 0 :
            S0 = 1       
def getFAfromSix(sixArr, axis=-1):
    mat = six2mat(sixArr)
    eig = np.linalg.eig(mat)[0]
    fa = fractional_anisotropy(eig)
    return fa