示例#1
0
def life(streamline_file, data_file, bvals, bvecs, seed_label, target_label):
    import numpy as np
    import nibabel as nib
    import os
    import dipy.tracking.life as life
    from dipy.core.gradients import gradient_table

    trk_file = nib.streamlines.load(streamline_file)
    streams = trk_file.streamlines
    hdr = trk_file.header

    data_img = nib.load(data_file)
    data = data_img.get_data()

    gtab = gradient_table(bvals, bvecs)
    fiber_model = life.FiberModel(gtab)
    fiber_fit = fiber_model.fit(data, streams, affine=np.eye(4))

    optimized_sl = list(np.array(streams)[np.where(fiber_fit.beta > 0)[0]])

    tractogram = nib.streamlines.Tractogram(optimized_sl)
    tractogram.affine_to_rasmm = data_img.affine
    life_streams = nib.streamlines.TrkFile(tractogram, header=hdr)

    life_trk = os.path.abspath('life_seed-%d_target-%d.trk' %
                               (seed_label, target_label))
    nib.streamlines.save(life_streams, life_trk)

    return streamline_file, life_trk
示例#2
0
def test_FiberFit():
    data_file, bval_file, bvec_file = dpd.get_fnames('small_64D')
    data_ni = nib.load(data_file)
    data = data_ni.get_data()
    bvals, bvecs = read_bvals_bvecs(bval_file, bvec_file)
    gtab = grad.gradient_table(bvals, bvecs)
    FM = life.FiberModel(gtab)
    evals = [0.0015, 0.0005, 0.0005]

    streamline = [[[1, 2, 3], [4, 5, 3], [5, 6, 3], [6, 7, 3]],
                  [[1, 2, 3], [4, 5, 3], [5, 6, 3]]]

    fiber_matrix, vox_coords = FM.setup(streamline, np.eye(4), evals)

    w = np.array([0.5, 0.5])
    sig = opt.spdot(fiber_matrix, w) + 1.0  # Add some isotropic stuff
    S0 = data[..., gtab.b0s_mask]
    this_data = np.zeros((10, 10, 10, 64))
    this_data[vox_coords[:, 0], vox_coords[:, 1], vox_coords[:, 2]] =\
        (sig.reshape((4, 64)) *
         S0[vox_coords[:, 0], vox_coords[:, 1], vox_coords[:, 2]])

    # Grab some realistic S0 values:
    this_data = np.concatenate([data[..., gtab.b0s_mask], this_data], -1)

    fit = FM.fit(this_data, streamline, np.eye(4))
    npt.assert_almost_equal(fit.predict()[1], fit.data[1], decimal=-1)

    # Predict with an input GradientTable
    npt.assert_almost_equal(fit.predict(gtab)[1], fit.data[1], decimal=-1)

    npt.assert_almost_equal(
        this_data[vox_coords[:, 0], vox_coords[:, 1], vox_coords[:, 2]],
        fit.data)
示例#3
0
def test_FiberModel_init():
    # Get some small amount of data:
    data_file, bval_file, bvec_file = dpd.get_fnames('small_64D')
    bvals, bvecs = read_bvals_bvecs(bval_file, bvec_file)
    gtab = grad.gradient_table(bvals, bvecs)
    FM = life.FiberModel(gtab)
    streamline_cases = [[[[1, 2, 3], [4, 5, 3], [5, 6, 3], [6, 7, 3]],
                         [[1, 2, 3], [4, 5, 3], [5, 6, 3]]],
                        [[[1, 2, 3]], [[1, 2, 3], [4, 5, 3], [5, 6, 3]]]]

    affine = np.eye(4)

    for sphere in [None, False, dpd.get_sphere('symmetric362')]:
        for streamline in streamline_cases:
            if streamline == [[[1, 2, 3]], [[1, 2, 3], [4, 5, 3], [5, 6, 3]]]:
                pytest.xfail("Too few nodes in streamline")
            fiber_matrix, vox_coords = FM.setup(streamline,
                                                affine,
                                                sphere=sphere)
            npt.assert_array_equal(
                np.array(vox_coords),
                np.array([[1, 2, 3], [4, 5, 3], [5, 6, 3], [6, 7, 3]]))

            npt.assert_equal(fiber_matrix.shape,
                             (len(vox_coords) * 64, len(streamline)))
示例#4
0
文件: eval.py 项目: geyunxiang/mmdps
def eval_method(name=None, method=None, track_path=None, data_path=None):

    if track_path == None:
        track_path = './Result/Track/tractogram_' + method + '_' + name + '.trk'
    if data_path == None:
        data_path = './data/DWI/' + name + '/'

    if not op.exists(track_path):
        print('no tracking')
        return 0

    else:

        from dipy.io.gradients import read_bvals_bvecs
        from dipy.io.image import load_nifti_data, load_nifti
        from dipy.core.gradients import gradient_table

        data, affine, hardi_img = load_nifti(data_path + 'norm.nii.gz',
                                             return_img=True)
        print(data.shape)
        labels = load_nifti_data(data_path + 'seg.nii.gz')
        # t1_data = load_nifti_data('./data/tanenci_20170601/b0.nii.gz')
        bvals, bvecs = read_bvals_bvecs(data_path + 'DWI.bval',
                                        data_path + 'DWI.bvec')
        gtab = gradient_table(bvals, bvecs)


# Read the candidates from file in voxel space:
    candidate_sl_sft = load_trk(track_path, 'same', bbox_valid_check=False)
    candidate_sl_sft.to_vox()
    candidate_sl = candidate_sl_sft.streamlines

    print('loading finished, begin weighting')

    fiber_model = life.FiberModel(gtab)
    inv_affine = np.linalg.inv(hardi_img.affine)
    fiber_fit = fiber_model.fit(data,
                                reduct(candidate_sl, data[:, :, :, 0]),
                                affine=np.eye(4))

    print('weighting finished, begin prediction')

    beta_baseline = np.zeros(fiber_fit.beta.shape[0])
    pred_weighted = np.reshape(
        opt.spdot(fiber_fit.life_matrix, beta_baseline),
        (fiber_fit.vox_coords.shape[0], np.sum(~gtab.b0s_mask)))

    model_predict = fiber_fit.predict()
    model_error = model_predict - fiber_fit.data
    model_rmse = np.sqrt(np.mean(model_error[:, 10:]**2, -1))
    #print('model_rmse:', model_rmse.shape)

    vol_model = np.zeros(data.shape[:3]) * np.nan
    vol_model[fiber_fit.vox_coords[:, 0], fiber_fit.vox_coords[:, 1],
              fiber_fit.vox_coords[:, 2]] = model_rmse

    #print('error:', np.sum(vol_model) / model_rmse.shape[0])

    return np.sum(model_rmse) / model_rmse.shape[0], vol_model, affine
示例#5
0
def run_LIFE_all(data, gtab, streamlines):
    import dipy.tracking.life as life
    import dipy.core.optimize as opt
    fiber_model = life.FiberModel(gtab)
    fiber_fit = fiber_model.fit(data, streamlines, affine=np.eye(4))
    streamlines_filt = list(np.array(streamlines)[np.where(fiber_fit.beta > 0)[0]])
    beta_baseline = np.zeros(fiber_fit.beta.shape[0])
    pred_weighted = np.reshape(opt.spdot(fiber_fit.life_matrix, beta_baseline),
                               (fiber_fit.vox_coords.shape[0], np.sum(~gtab.b0s_mask)))
    mean_pred = np.empty((fiber_fit.vox_coords.shape[0], gtab.bvals.shape[0]))
    S0 = fiber_fit.b0_signal
    mean_pred[..., gtab.b0s_mask] = S0[:, None]
    mean_pred[..., ~gtab.b0s_mask] = (pred_weighted + fiber_fit.mean_signal[:, None]) * S0[:, None]
    mean_error = mean_pred - fiber_fit.data
    mean_rmse = np.sqrt(np.mean(mean_error ** 2, -1))
    return streamlines_filt, mean_rmse
示例#6
0
def test_fit_data():
    fdata, fbval, fbvec = dpd.get_fnames('small_25')
    fstreamlines = dpd.get_fnames('small_25_streamlines')
    gtab = grad.gradient_table(fbval, fbvec)
    ni_data = nib.load(fdata)
    data = ni_data.get_data()
    tensor_streamlines = nib.streamlines.load(fstreamlines).streamlines
    tensor_streamlines = move_streamlines(tensor_streamlines, np.eye(4),
                                          ni_data.affine)
    life_model = life.FiberModel(gtab)
    life_fit = life_model.fit(data, tensor_streamlines)
    model_error = life_fit.predict() - life_fit.data
    model_rmse = np.sqrt(np.mean(model_error**2, -1))
    matlab_rmse, matlab_weights = dpd.matlab_life_results()
    # Lower error than the matlab implementation for these data:
    npt.assert_(np.median(model_rmse) < np.median(matlab_rmse))
    # And a moderate correlation with the Matlab implementation weights:
    npt.assert_(np.corrcoef(matlab_weights, life_fit.beta)[0, 1] > 0.6)
示例#7
0
def test_FiberModel_init():
    # Get some small amount of data:
    data_file, bval_file, bvec_file = dpd.get_data('small_64D')
    data_ni = nib.load(data_file)
    bvals, bvecs = (np.load(f) for f in (bval_file, bvec_file))
    gtab = dpg.gradient_table(bvals, bvecs)
    FM = life.FiberModel(gtab)

    streamline = [[[1, 2, 3], [4, 5, 3], [5, 6, 3], [6, 7, 3]],
                  [[1, 2, 3], [4, 5, 3], [5, 6, 3]]]

    affine = np.eye(4)

    for sphere in [None, False, dpd.get_sphere('symmetric362')]:
        fiber_matrix, vox_coords = FM.setup(streamline, affine, sphere=sphere)
        npt.assert_array_equal(
            np.array(vox_coords),
            np.array([[1, 2, 3], [4, 5, 3], [5, 6, 3], [6, 7, 3]]))

        npt.assert_equal(fiber_matrix.shape,
                         (len(vox_coords) * 64, len(streamline)))
示例#8
0
def run_LIFE_all(data, gtab, streamlines):
    '''
    Filters tractography streamlines using Linear Fascicle Evaluation (LiFE).

    Parameters
    ----------
    data : array
        4D numpy array of diffusion image data.
    gtab : Obj
        DiPy object storing diffusion gradient information.
    streamlines : ArraySequence
        DiPy list/array-like object of streamline points from tractography.

    Returns
    -------
    streamlines_filt : ArraySequence
        DiPy list/array-like object of filtered streamline fibers with positive beta-coefficients
        after fitting LiFE model.
    mean_rmse : float
        Root Mean-Squared Error (RMSE) when using LiFE-filtered fibers to predict diffusion data.
    '''
    import dipy.tracking.life as life
    import dipy.core.optimize as opt
    fiber_model = life.FiberModel(gtab)
    fiber_fit = fiber_model.fit(data, streamlines, affine=np.eye(4))
    streamlines_filt = list(
        np.array(streamlines)[np.where(fiber_fit.beta > 0)[0]])
    beta_baseline = np.zeros(fiber_fit.beta.shape[0])
    pred_weighted = np.reshape(
        opt.spdot(fiber_fit.life_matrix, beta_baseline),
        (fiber_fit.vox_coords.shape[0], np.sum(~gtab.b0s_mask)))
    mean_pred = np.empty((fiber_fit.vox_coords.shape[0], gtab.bvals.shape[0]))
    S0 = fiber_fit.b0_signal
    mean_pred[..., gtab.b0s_mask] = S0[:, None]
    mean_pred[...,
              ~gtab.b0s_mask] = (pred_weighted +
                                 fiber_fit.mean_signal[:, None]) * S0[:, None]
    mean_error = mean_pred - fiber_fit.data
    mean_rmse = np.sqrt(np.mean(mean_error**2, -1))
    return streamlines_filt, mean_rmse
示例#9
0
def test_fit_data():
    fdata, fbval, fbvec = dpd.get_data('small_25')
    gtab = grad.gradient_table(fbval, fbvec)
    ni_data = nib.load(fdata)
    data = ni_data.get_data()
    dtmodel = dti.TensorModel(gtab)
    dtfit = dtmodel.fit(data)
    sphere = dpd.get_sphere()
    peak_idx = dti.quantize_evecs(dtfit.evecs, sphere.vertices)
    eu = edx.EuDX(dtfit.fa.astype('f8'),
                  peak_idx,
                  seeds=list(nd.ndindex(data.shape[:-1])),
                  odf_vertices=sphere.vertices,
                  a_low=0)
    tensor_streamlines = [streamline for streamline in eu]
    life_model = life.FiberModel(gtab)
    life_fit = life_model.fit(data, tensor_streamlines)
    model_error = life_fit.predict() - life_fit.data
    model_rmse = np.sqrt(np.mean(model_error**2, -1))
    matlab_rmse, matlab_weights = dpd.matlab_life_results()
    # Lower error than the matlab implementation for these data:
    npt.assert_(np.median(model_rmse) < np.median(matlab_rmse))
    # And a moderate correlation with the Matlab implementation weights:
    npt.assert_(np.corrcoef(matlab_weights, life_fit.beta)[0, 1] > 0.68)
示例#10
0
.. figure:: life_candidates.png
   :align: center

   **Candidate connectome before life optimization**

"""
"""

Next, we initialize a LiFE model. We import the `dipy.tracking.life` module,
which contains the classes and functions that implement the model:

"""

import dipy.tracking.life as life

fiber_model = life.FiberModel(gtab)
"""

Since we read the streamlines from a file, already in the voxel space, we do not
need to transform them into this space. Otherwise, if the streamline coordinates
were in the world space (relative to the scanner iso-center, or relative to the
mid-point of the AC-PC-connecting line), we would use this::

   inv_affine = np.linalg.inv(hardi_img.get_affine())

the inverse transformation from world space to the voxel space as the affine for
the following model fit.

The next step is to fit the model, producing a `FiberFit` class instance, that
stores the data, as well as the results of the fitting procedure.
def run_LiFE(subject):
    print 'Process subject ' + subject

    if os.path.isfile(
            os.path.join(path_saveing, subject,
                         'Lamyg2LpMFG_LIFE_started.txt')) == False:
        print "LiFE Files do not exist for this subject, start calculation."

        if os.path.isfile(
                os.path.join(
                    path_saveing, subject,
                    'Lamyg2LpMFG_clustered.trk')) == True and os.path.isfile(
                        os.path.join(path_saveing, subject,
                                     '2M_SIFT.trk')) == True:
            print "All neccessary files there, continue ..."

            print "Show other processes that this subject is processed"
            done = np.array([1])
            np.savetxt(os.path.join(path_saveing, subject,
                                    'Lamyg2LpMFG_LIFE_started.txt'),
                       done,
                       delimiter=',')

            try:
                directory_output = os.path.join(path_saveing, subject)

                print "Start calculation for subject %s" % subject
                f_streamlines = os.path.join(path_saveing, subject,
                                             'Lamyg2LpMFG_clustered.trk')
                f_in_nifti = os.path.join(path, subject,
                                          'T1w/Diffusion/data.nii.gz')

                streams, hdr = tv.read(f_streamlines, points_space='voxel')
                streamlines = [i[0] for i in streams]

                data, affine, gtab, header, shell_mask = load_hcp_data(
                    path, subject)
                dim = header['dim'][1:4]

                # Otherwise all weights are NaN
                data[data <= 0.0] = 1.0

                print "Calculating neighborhood with LiFE"
                fiber_model_neighborhood = life.FiberModel(gtab)
                fiber_fit_neighborhood = fiber_model_neighborhood.fit(
                    data, streamlines, affine=np.eye(4))
                indices_neighborhood = fiber_fit_neighborhood.vox_coords

                neighborhood = np.zeros(dim, dtype=bool)
                for i in range(indices_neighborhood.shape[0]):
                    neighborhood[indices_neighborhood[i][0],
                                 indices_neighborhood[i][1],
                                 indices_neighborhood[i][2]] = 1

                save_as_nifti(
                    path_saveing + subject + "/Lamyg2LpMFG_neighborhood",
                    neighborhood.astype(np.int), affine)

                print 'Find fiber that pass through neighborhood'
                f_streamlines_whole_brain = path_saveing + subject + "/2M_SIFT.trk"
                streams_whole_brain, hdr_whole_brain = tv.read(
                    f_streamlines_whole_brain, points_space='voxel')
                streamlines_whole_brain = [i[0] for i in streams_whole_brain]
                neighborhood_streamlines = utils.target(
                    streamlines_whole_brain, neighborhood, affine=np.eye(4))

                neighborhood_streamlines = list(neighborhood_streamlines)

                strm = ((sl, None, None) for sl in neighborhood_streamlines)
                tv.write(path_saveing + subject +
                         "/Lamyg2LpMFG_2M_SIFT_without_path.trk",
                         strm,
                         hdr_mapping=hdr_whole_brain,
                         points_space='voxel')

                print "Combine streamlines"
                streamlines_together = neighborhood_streamlines + streamlines
                strm_together = ((sl, None, None)
                                 for sl in streamlines_together)
                tv.write(path_saveing + subject +
                         "/Lamyg2LpMFG_2M_SIFT_with_path.trk",
                         strm_together,
                         hdr_mapping=hdr_whole_brain,
                         points_space='voxel')

                print "Start LiFE optimization with new path"
                fiber_model_together = life.FiberModel(gtab)
                fiber_fit_together = fiber_model_together.fit(
                    data, streamlines_together, affine=np.eye(4))
                model_predict_together = fiber_fit_together.predict()
                indices_together = fiber_fit_together.vox_coords

                mask_with = np.zeros(dim, dtype=bool)
                whole_brain_together = np.zeros(header['dim'][1:5])
                for i in range(indices_together.shape[0]):
                    whole_brain_together[
                        indices_together[i][0], indices_together[i][1],
                        indices_together[i][2]] = model_predict_together[i]
                    mask_with[indices_together[i][0], indices_together[i][1],
                              indices_together[i][2]] = 1

                save_as_nifti(
                    path_saveing + subject +
                    "/Lamyg2LpMFG_LiFE_prediction_with_path",
                    whole_brain_together, affine)
                save_as_matlab_file(path_saveing + subject +
                                    "/Lamyg2LpMFG_LiFE_betas_with_path",
                                    beta=fiber_fit_together.beta)
                save_as_nifti(
                    path_saveing +
                    subject + "/Lamyg2LpMFG_LiFE_mask_with_path",
                    mask_with.astype(np.int), affine)

                print "Calculate RMSE with"
                model_error_together = model_predict_together - fiber_fit_together.data
                model_rmse_together = np.sqrt(
                    np.mean(model_error_together[..., ~gtab.b0s_mask]**2, -1))

                whole_brain_rmse_together = np.zeros(dim)
                for i in range(indices_together.shape[0]):
                    whole_brain_rmse_together[
                        indices_together[i][0], indices_together[i][1],
                        indices_together[i][2]] = model_rmse_together[i]

                save_as_nifti(
                    path_saveing + subject +
                    "/Lamyg2LpMFG_LiFE_rmse_with_path",
                    whole_brain_rmse_together, affine)

                print "Start LiFE optimization without new path"
                fiber_fit = copy.deepcopy(fiber_fit_together)
                fiber_fit.beta[-len(streamlines):] = 0
                model_predict = fiber_fit.predict()
                indices = fiber_fit.vox_coords

                whole_brain = np.zeros(header['dim'][1:5])
                mask_without = np.zeros(dim, dtype=bool)
                for i in range(indices.shape[0]):
                    whole_brain[indices[i][0], indices[i][1],
                                indices[i][2]] = model_predict[i]
                    mask_without[indices[i][0], indices[i][1],
                                 indices[i][2]] = 1

                save_as_nifti(
                    path_saveing + subject +
                    "/Lamyg2LpMFG_LiFE_prediction_without_path", whole_brain,
                    affine)
                save_as_matlab_file(path_saveing + subject +
                                    "/Lamyg2LpMFG_LiFE_betas_without_path",
                                    beta=fiber_fit.beta)
                save_as_nifti(
                    path_saveing + subject +
                    "/Lamyg2LpMFG_LiFE_mask_without_path",
                    mask_without.astype(np.int), affine)

                print "Calculate RMSE without"
                model_error = model_predict - fiber_fit.data
                model_rmse = np.sqrt(
                    np.mean(model_error[..., ~gtab.b0s_mask]**2, -1))

                whole_brain_rmse = np.zeros(dim)
                for i in range(indices.shape[0]):
                    whole_brain_rmse[indices[i][0], indices[i][1],
                                     indices[i][2]] = model_rmse[i]

                save_as_nifti(
                    path_saveing + subject +
                    "/Lamyg2LpMFG_LiFE_rmse_without_path", whole_brain_rmse,
                    affine)

                print "All done"
            except:
                print "An error occured while computing LiFE. Skip this subject."
        else:
            print "Some input files are missing, skip this subject."
    else:
        print "LiFE Files exist already for this subject, skip calculation."

    return 0
示例#12
0
def evaluate_streamline_plausibility(dwi_data,
                                     gtab,
                                     mask_data,
                                     streamlines,
                                     affine=np.eye(4),
                                     sphere='repulsion724'):
    """
    Linear Fascicle Evaluation (LiFE) takes any connectome and uses a
    forward modelling approach to predict diffusion measurements in the
    same brain.

    Parameters
    ----------
    dwi_data : array
        4D array of dwi data.
    gtab : Obj
        DiPy object storing diffusion gradient information.
    mask_data : array
       3D Brain mask.
    streamlines : ArraySequence
        DiPy list/array-like object of streamline points from tractography.

    Returns
    -------
    streamlines : ArraySequence
        DiPy list/array-like object of streamline points from tractography.

    References
    ----------
    .. [1] Pestilli, F., Yeatman, J, Rokem, A. Kay, K. and Wandell B.A. (2014).
     Validation and statistical inference in living connectomes.
     Nature Methods 11: 1058-1063. doi:10.1038/nmeth.3098
    """
    import dipy.tracking.life as life
    import dipy.core.optimize as opt
    from dipy.tracking._utils import _mapping_to_voxel
    # from dipy.data import get_sphere
    from dipy.tracking import utils
    from dipy.tracking.streamline import Streamlines

    original_count = len(streamlines)

    streamlines_long = nib.streamlines. \
        array_sequence.ArraySequence(
        [
            s
            for s in streamlines
            if len(s) >= float(10)
        ]
    )
    print('Removing streamlines with negative voxel indices...')
    # Remove any streamlines with negative voxel indices
    lin_T, offset = _mapping_to_voxel(np.eye(4))
    streamlines_positive = []
    for sl in streamlines_long:
        inds = np.dot(sl, lin_T)
        inds += offset
        if not inds.min().round(decimals=6) < 0:
            streamlines_positive.append(sl)
    del streamlines_long

    # Filter resulting streamlines by those that stay entirely
    # inside the ROI of interest
    mask_data = np.array(mask_data, dtype=bool, copy=False)
    streamlines_in_brain = Streamlines(
        utils.target(streamlines_positive, np.eye(4), mask_data, include=True))
    streamlines_in_brain = [i for i in streamlines_in_brain]
    del streamlines_positive
    print('Fitting fiber model...')

    # ! Remember this 4d masking function !
    data_in_mask = np.nan_to_num(
        np.broadcast_to(mask_data[..., None], dwi_data.shape).astype('bool') *
        dwi_data)
    # ! Remember this 4d masking function !

    fiber_model = life.FiberModel(gtab)
    fiber_fit = fiber_model.fit(data_in_mask,
                                streamlines_in_brain,
                                affine=affine,
                                sphere=False)
    # sphere = get_sphere(sphere)
    # fiber_fit = fiber_model.fit(data_in_mask, streamlines_in_brain,
    #                             affine=affine,
    #                             sphere=sphere)
    streamlines = list(
        np.array(streamlines_in_brain)[np.where(fiber_fit.beta > 0)[0]])
    pruned_count = len(streamlines)
    if pruned_count == 0:
        print(
            UserWarning('\nWarning LiFE skipped due to implausible values '
                        'detected in model betas. This does not '
                        'necessarily invalidate the '
                        'tractography. Rather it could indicate that '
                        'you\'ve sampled too few streamlines, or that the '
                        'sampling scheme is simply incompatible with the '
                        'LiFE model. Is your acquisition hemispheric? '
                        'Also check the gradient table for errors. \n'))
        return streamlines_in_brain
    else:
        del streamlines_in_brain

    model_predict = fiber_fit.predict()
    model_error = model_predict - fiber_fit.data
    model_rmse = np.sqrt(np.mean(model_error[:, 10:]**2, -1))
    beta_baseline = np.zeros(fiber_fit.beta.shape[0])
    pred_weighted = np.reshape(
        opt.spdot(fiber_fit.life_matrix, beta_baseline),
        (fiber_fit.vox_coords.shape[0], np.sum(~gtab.b0s_mask)))
    mean_pred = np.empty((fiber_fit.vox_coords.shape[0], gtab.bvals.shape[0]))
    S0 = fiber_fit.b0_signal
    mean_pred[..., gtab.b0s_mask] = S0[:, None]
    mean_pred[...,
              ~gtab.b0s_mask] = (pred_weighted +
                                 fiber_fit.mean_signal[:, None]) * S0[:, None]
    mean_error = mean_pred - fiber_fit.data
    mean_rmse = np.sqrt(np.mean(mean_error**2, -1))
    print(f"Original # Streamlines: {original_count}")
    print(f"Final # Streamlines: {pruned_count}")
    print(f"Streamlines removed: {pruned_count - original_count}")
    print(f"Mean RMSE: {np.mean(mean_rmse)}")
    print(f"Mean Model RMSE: {np.mean(model_rmse)}")
    print(f"Mean Reduction RMSE: {np.mean(mean_rmse - model_rmse)}")
    return streamlines
示例#13
0
def life(dwifile, bvecsfile, bvalsfile, tractogramfile, outdir,
         display_tracks=False, verbose=0):
    """ Linear fascicle evaluation (LiFE)
    Evaluating the results of tractography algorithms is one of the biggest
    challenges for diffusion MRI. One proposal for evaluation of tractography
    results is to use a forward model that predicts the signal from each of a
    set of streamlines, and then fit a linear model to these simultaneous
    prediction.

    Parameters
    ----------
    dwifile: str
        the path to the diffusion dataset.
    bvecsfile: str
        the path to the diffusion b-vectors.
    bvalsfile: str
        the path to the diffusion b-values.
    tractogramfile: str
        the path to the tractogram.
    outdir: str
        the destination folder.
    display_tracks: bool, default False
        if True render the tracks.
    verbose: int, default 0
        the verbosity level.

    Returns
    -------
    life_weights_file: str
        a file containing the fiber track weights.
    life_weights_snap: str
        a snap with the distrubution of weights.
    spatial_error_file: str
        the model root mean square error.
    tracks_snap: str
        a snap with the tracks.
    """
    # Load diffusion data and tractogram
    bvecs = numpy.loadtxt(bvecsfile)
    bvals = numpy.loadtxt(bvalsfile)
    gtab = gradient_table(bvals, bvecs)
    im = nibabel.load(dwifile)
    data = im.get_data()
    trk = nibabel.streamlines.load(tractogramfile)
    if verbose > 0:
        print("[info] Diffusion shape: {0}".format(data.shape))
        print("[info] Number of tracks: {0}".format(len(trk.streamlines)))

    # Express the tractogram in voxel coordiantes
    inv_affine = numpy.linalg.inv(trk.affine)
    trk = [
        numpy.dot(
            numpy.concatenate(
                (
                    streamline,
                    numpy.ones(
                        (len(streamline), 1)
                    )
                ), axis=1
            ),
            inv_affine) for streamline in trk.streamlines]
    trk = [track[..., :3] for track in trk]

    # Create a viewer
    tracks_snap = None
    if display_tracks:
        nb_tracks = len(trk)
        if nb_tracks < 5000:
            downsampling = 1
        else:
            downsampling = nb_tracks // 5000
        tracks_snap = os.path.join(outdir, "tracks.png")
        streamlines_actor = fvtk.line(trk[::downsampling],
                                      line_colors(trk[::downsampling]))
        vol_actor = fvtk.slicer(data[..., 0])

        vol_actor.display(data.shape[0] // 2, None, None)
        ren = fvtk.ren()
        fvtk.add(ren, streamlines_actor)
        fvtk.add(ren, vol_actor)
        fvtk.record(ren, n_frames=1, out_path=tracks_snap, size=(800, 800))
        if verbose > 1:
            fvtk.show(ren)

    # Fit the Life model and save the associated weights
    fiber_model = dpilife.FiberModel(gtab)
    fiber_fit = fiber_model.fit(data, trk, affine=numpy.eye(4))
    life_weights = fiber_fit.beta
    life_weights_file = os.path.join(outdir, "life_weights.txt")
    numpy.savetxt(life_weights_file, life_weights)
    life_weights_snap = os.path.join(outdir, "life_weights.png")
    fig, ax = plt.subplots(1)
    ax.hist(life_weights, bins=100, histtype="step")
    ax.set_xlabel("Fiber weights")
    ax.set_ylabel("# Fibers")
    fig.savefig(life_weights_snap)

    # Invert the model and predict back either the data that was used to fit
    # the model: compute the prediction error of the diffusion-weighted data
    # and calculate the root of the mean squared error.
    model_predict = fiber_fit.predict()
    model_error = model_predict - fiber_fit.data
    model_rmse = numpy.sqrt(numpy.mean(model_error[:, 10:] ** 2, -1))
    data_rmse = numpy.ones(data.shape[:3]) * numpy.nan
    data_rmse[fiber_fit.vox_coords[:, 0],
              fiber_fit.vox_coords[:, 1],
              fiber_fit.vox_coords[:, 2]] = model_rmse
    model_error_file = os.path.join(outdir, "model_rmse.nii.gz")
    error_im = nibabel.Nifti1Image(data_rmse, im.affine)
    nibabel.save(error_im, model_error_file)

    # As a baseline against which we can compare, we assume that the weight
    # for each streamline is equal to zero. This produces the naive prediction
    # of the mean of the signal in each voxel.
    life_weights_baseline = numpy.zeros(life_weights.shape[0])
    pred_weighted = numpy.reshape(
        opt.spdot(fiber_fit.life_matrix, life_weights_baseline),
        (fiber_fit.vox_coords.shape[0], numpy.sum(~gtab.b0s_mask)))
    mean_pred = numpy.empty(
        (fiber_fit.vox_coords.shape[0], gtab.bvals.shape[0]))
    S0 = fiber_fit.b0_signal

    # Since the fitting is done in the demeaned S/S0 domain, we need to add
    # back the mean and then multiply by S0 in every voxels.
    mean_pred[..., gtab.b0s_mask] = S0[:, None]
    mean_pred[..., ~gtab.b0s_mask] = (
            (pred_weighted + fiber_fit.mean_signal[:, None]) * S0[:, None])
    mean_error = mean_pred - fiber_fit.data
    mean_rmse = numpy.sqrt(numpy.mean(mean_error ** 2, -1))
    data_rmse = numpy.ones(data.shape[:3]) * numpy.nan
    data_rmse[fiber_fit.vox_coords[:, 0],
              fiber_fit.vox_coords[:, 1],
              fiber_fit.vox_coords[:, 2]] = mean_rmse
    mean_error_file = os.path.join(outdir, "mean_rmse.nii.gz")
    error_im = nibabel.Nifti1Image(data_rmse, im.affine)
    nibabel.save(error_im, mean_error_file)

    # Compute the improvment array
    data_rmse = numpy.ones(data.shape[:3]) * numpy.nan
    data_rmse[fiber_fit.vox_coords[:, 0],
              fiber_fit.vox_coords[:, 1],
              fiber_fit.vox_coords[:, 2]] = mean_rmse - model_rmse
    improvment_error_file = os.path.join(outdir, "improvment_rmse.nii.gz")
    error_im = nibabel.Nifti1Image(data_rmse, im.affine)
    nibabel.save(error_im, improvment_error_file)

    return (life_weights_file, life_weights_snap, model_error_file,
            mean_error_file, improvment_error_file, tracks_snap)