def test_reorient_bvecs():
    sq2 = np.sqrt(2) / 2
    bvals = np.concatenate([[0], np.ones(6) * 1000])
    bvecs = np.array([[0, 0, 0],
                      [1, 0, 0],
                      [0, 1, 0],
                      [0, 0, 1],
                      [sq2, sq2, 0],
                      [sq2, 0, sq2],
                      [0, sq2, sq2]])

    gt = gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=0)
    # The simple case: all affines are identity
    affs = np.zeros((6, 4, 4))
    for i in range(4):
        affs[:, i, i] = 1

    # We should get back the same b-vectors
    new_gt = reorient_bvecs(gt, affs)
    npt.assert_equal(gt.bvecs, new_gt.bvecs)

    # Now apply some rotations
    rotation_affines = []
    rotated_bvecs = bvecs[:]
    for i in np.where(~gt.b0s_mask)[0]:
        rot_ang = np.random.rand()
        cos_rot = np.cos(rot_ang)
        sin_rot = np.sin(rot_ang)
        rotation_affines.append(np.array([[1, 0, 0, 0],
                                          [0, cos_rot, -sin_rot, 0],
                                          [0, sin_rot, cos_rot, 0],
                                          [0, 0, 0, 1]]))
        rotated_bvecs[i] = np.dot(rotation_affines[-1][:3, :3],
                                  bvecs[i])

    # Copy over the rotation affines
    full_affines = rotation_affines[:]
    # And add some scaling and translation to each one to make this harder
    for i in range(len(full_affines)):
        full_affines[i] = np.dot(full_affines[i],
                                 np.array([[2.5, 0, 0, -10],
                                           [0, 2.2, 0, 20],
                                           [0, 0, 1, 0],
                                           [0, 0, 0, 1]]))

    gt_rot = gradient_table_from_bvals_bvecs(bvals,
                                             rotated_bvecs, b0_threshold=0)
    new_gt = reorient_bvecs(gt_rot, full_affines)
    # At the end of all this, we should be able to recover the original
    # vectors
    npt.assert_almost_equal(gt.bvecs, new_gt.bvecs)

    # We should be able to pass just the 3-by-3 rotation components to the same
    # effect
    new_gt = reorient_bvecs(gt_rot, np.array(rotation_affines)[:, :3, :3])
    npt.assert_almost_equal(gt.bvecs, new_gt.bvecs)

    # Verify that giving the wrong number of affines raises an error:
    full_affines.append(np.zeros((4, 4)))
    npt.assert_raises(ValueError, reorient_bvecs, gt_rot, full_affines)
Example #2
0
def test_reorient_bvecs():
    sq2 = np.sqrt(2) / 2
    bvals = np.concatenate([[0], np.ones(6) * 1000])
    bvecs = np.array([[0, 0, 0],
                      [1, 0, 0],
                      [0, 1, 0],
                      [0, 0, 1],
                      [sq2, sq2, 0],
                      [sq2, 0, sq2],
                      [0, sq2, sq2]])

    gt = gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=0)
    # The simple case: all affines are identity
    affs = np.zeros((6, 4, 4))
    for i in range(4):
        affs[:, i, i] = 1

    # We should get back the same b-vectors
    new_gt = reorient_bvecs(gt, affs)
    npt.assert_equal(gt.bvecs, new_gt.bvecs)

    # Now apply some rotations
    rotation_affines = []
    rotated_bvecs = bvecs[:]
    for i in np.where(~gt.b0s_mask)[0]:
        rot_ang = np.random.rand()
        cos_rot = np.cos(rot_ang)
        sin_rot = np.sin(rot_ang)
        rotation_affines.append(np.array([[1, 0, 0, 0],
                                          [0, cos_rot, -sin_rot, 0],
                                          [0, sin_rot, cos_rot, 0],
                                          [0, 0, 0, 1]]))
        rotated_bvecs[i] = np.dot(rotation_affines[-1][:3, :3],
                                  bvecs[i])

    # Copy over the rotation affines
    full_affines = rotation_affines[:]
    # And add some scaling and translation to each one to make this harder
    for i in range(len(full_affines)):
        full_affines[i] = np.dot(full_affines[i],
                                 np.array([[2.5, 0, 0, -10],
                                           [0, 2.2, 0, 20],
                                           [0, 0, 1, 0],
                                           [0, 0, 0, 1]]))

    gt_rot = gradient_table_from_bvals_bvecs(bvals,
                                             rotated_bvecs, b0_threshold=0)
    new_gt = reorient_bvecs(gt_rot, full_affines)
    # At the end of all this, we should be able to recover the original
    # vectors
    npt.assert_almost_equal(gt.bvecs, new_gt.bvecs)

    # We should be able to pass just the 3-by-3 rotation components to the same
    # effect
    new_gt = reorient_bvecs(gt_rot, np.array(rotation_affines)[:, :3, :3])
    npt.assert_almost_equal(gt.bvecs, new_gt.bvecs)

    # Verify that giving the wrong number of affines raises an error:
    full_affines.append(np.zeros((4, 4)))
    assert_raises(ValueError, reorient_bvecs, gt_rot, full_affines)
def test_gradient_table_from_bvals_bvecs():

    sq2 = np.sqrt(2) / 2
    bvals = [0, 1, 2, 3, 4, 5, 6, 0]
    bvecs = np.array([[0, 0, 0],
                      [1, 0, 0],
                      [0, 1, 0],
                      [0, 0, 1],
                      [sq2, sq2, 0],
                      [sq2, 0, sq2],
                      [0, sq2, sq2],
                      [0, 0, 0]])

    gt = gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=0)
    npt.assert_array_equal(gt.bvecs, bvecs)
    npt.assert_array_equal(gt.bvals, bvals)
    npt.assert_array_equal(gt.gradients, np.reshape(bvals, (-1, 1)) * bvecs)
    npt.assert_array_equal(gt.b0s_mask, [1, 0, 0, 0, 0, 0, 0, 1])

    # Test nans are replaced by 0
    new_bvecs = bvecs.copy()
    new_bvecs[[0, -1]] = np.nan
    gt = gradient_table_from_bvals_bvecs(bvals, new_bvecs, b0_threshold=0)
    npt.assert_array_equal(gt.bvecs, bvecs)

    # Bvalue > 0 for non-unit vector
    bad_bvals = [2, 1, 2, 3, 4, 5, 6, 0]
    npt.assert_raises(ValueError, gradient_table_from_bvals_bvecs, bad_bvals,
                      bvecs, b0_threshold=0.)
    # num_gard inconsistent bvals, bvecs
    bad_bvals = np.ones(7)
    npt.assert_raises(ValueError, gradient_table_from_bvals_bvecs, bad_bvals,
                      bvecs, b0_threshold=0.)
    # negative bvals
    bad_bvals = [-1, -1, -1, -5, -6, -10]
    npt.assert_raises(ValueError, gradient_table_from_bvals_bvecs, bad_bvals,
                      bvecs, b0_threshold=0.)
    # bvals not 1d
    bad_bvals = np.ones((1, 8))
    npt.assert_raises(ValueError, gradient_table_from_bvals_bvecs, bad_bvals,
                      bvecs, b0_threshold=0.)
    # bvec not 2d
    bad_bvecs = np.ones((1, 8, 3))
    npt.assert_raises(ValueError, gradient_table_from_bvals_bvecs, bvals,
                      bad_bvecs, b0_threshold=0.)
    # bvec not (N, 3)
    bad_bvecs = np.ones((8, 2))
    npt.assert_raises(ValueError, gradient_table_from_bvals_bvecs, bvals,
                      bad_bvecs, b0_threshold=0.)
    # bvecs not unit vectors
    bad_bvecs = bvecs * 2
    npt.assert_raises(ValueError, gradient_table_from_bvals_bvecs, bvals,
                      bad_bvecs, b0_threshold=0.)

    # Test **kargs get passed along
    gt = gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=0,
                                         big_delta=5, small_delta=2)
    npt.assert_equal(gt.big_delta, 5)
    npt.assert_equal(gt.small_delta, 2)
Example #4
0
def test_all_zeros():
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS', 'RESTORE']
    for fit_method in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_raises(ValueError, dm.fit, np.zeros(bvals.shape[0]))
Example #5
0
def select_outer_shell(gtab):
    bvals = gtab.bvals
    bvecs = gtab.bvecs
    max_bval = np.max(shells(gtab))
    bvals[bvals != max_bval] = 0
    new_gtab = gradient_table_from_bvals_bvecs(bvals, bvecs)
    return new_gtab
Example #6
0
def compute_RTOP(dwi_, mask_, bvals_, bvecs_):

    if path.exists(dwi_) and path.exists(mask_) and path.exists(
            bvals_) and path.exists(bvecs_):
        dwi = nib.load(dwi_)
        mask = nib.load(mask_)
        bvals = np.loadtxt(bvals_) * units.s / units.mm**2
        bvecs = np.loadtxt(bvecs_)
    else:
        print("One of the files does not exist, exit.")
        exit()

    dwi_data = dwi.get_data()
    mask_data = mask.get_data()

    nodif = dwi.slicer[:, :, :, 0]

    gtab = gradients.gradient_table_from_bvals_bvecs(bvals,
                                                     bvecs,
                                                     b0_threshold=5)
    map_model = mapmri.MapmriModel(gtab,
                                   laplacian_regularization=True,
                                   laplacian_weighting=0.2)
    map_fit = map_model.fit(dwi_data, mask=mask_data)
    rtop = map_fit.rtop()
    rtop_cortex_norm = rtop / rtop[mask_data != 0].mean()

    rtop_nii = nib.Nifti1Image(rtop, affine=dwi.affine)
    rtop_cortex_norm_nii = nib.Nifti1Image(rtop_cortex_norm, affine=dwi.affine)

    rtop_nii.to_filename('RTOP_cortex.nii.gz')
    rtop_cortex_norm_nii.to_filename('RTOP_cortex_norm.nii.gz')

    return
Example #7
0
def test_masked_array_with_tensor():
    data = np.ones((2, 4, 56))
    mask = np.array([[True, False, False, True],
                     [True, False, True, False]])

    bvec, bval = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bval, bvec.T)

    tensor_model = TensorModel(gtab)
    tensor = tensor_model.fit(data, mask=mask)
    assert_equal(tensor.shape, (2, 4))
    assert_equal(tensor.fa.shape, (2, 4))
    assert_equal(tensor.evals.shape, (2, 4, 3))
    assert_equal(tensor.evecs.shape, (2, 4, 3, 3))

    tensor = tensor[0]
    assert_equal(tensor.shape, (4,))
    assert_equal(tensor.fa.shape, (4,))
    assert_equal(tensor.evals.shape, (4, 3))
    assert_equal(tensor.evecs.shape, (4, 3, 3))

    tensor = tensor[0]
    assert_equal(tensor.shape, tuple())
    assert_equal(tensor.fa.shape, tuple())
    assert_equal(tensor.evals.shape, (3,))
    assert_equal(tensor.evecs.shape, (3, 3))
    assert_equal(type(tensor.model_params), np.ndarray)
Example #8
0
def test_masked_array_with_tensor():
    data = np.ones((2, 4, 56))
    mask = np.array([[True, False, False, True],
                     [True, False, True, False]])

    bvec, bval = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bval, bvec.T)

    tensor_model = TensorModel(gtab)
    tensor = tensor_model.fit(data, mask=mask)
    assert_equal(tensor.shape, (2, 4))
    assert_equal(tensor.fa.shape, (2, 4))
    assert_equal(tensor.evals.shape, (2, 4, 3))
    assert_equal(tensor.evecs.shape, (2, 4, 3, 3))

    tensor = tensor[0]
    assert_equal(tensor.shape, (4,))
    assert_equal(tensor.fa.shape, (4,))
    assert_equal(tensor.evals.shape, (4, 3))
    assert_equal(tensor.evecs.shape, (4, 3, 3))

    tensor = tensor[0]
    assert_equal(tensor.shape, tuple())
    assert_equal(tensor.fa.shape, tuple())
    assert_equal(tensor.evals.shape, (3,))
    assert_equal(tensor.evecs.shape, (3, 3))
    assert_equal(type(tensor.model_params), np.ndarray)
Example #9
0
def test_all_zeros():
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS', 'RESTORE']
    for _ in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_array_almost_equal(dm.fit(np.zeros(bvals.shape[0])).evals, 0)
Example #10
0
def test_all_zeros():
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS', 'RESTORE']
    for fit_method in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_array_almost_equal(dm.fit(np.zeros(bvals.shape[0])).evals, 0)
Example #11
0
def test_all_zeros():
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS', 'RESTORE']
    for fit_method in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_raises(ValueError, dm.fit, np.zeros(bvals.shape[0]))
Example #12
0
    def reorient_rasb(self):
        """Reorient the vectors based o a list of affine transforms."""
        from dipy.core.gradients import (gradient_table_from_bvals_bvecs,
                                         reorient_bvecs)

        affines = self._transforms.copy()
        bvals = self._bvals
        bvecs = self._bvecs

        # Verify that number of non-B0 volumes corresponds to the number of
        # affines. If not, try to fix it, or raise an error:
        if len(self._bvals[self._bvals >= self._b0_thres]) != len(affines):
            b0_indices = np.where(self._bvals <= self._b0_thres)[0].tolist()
            if len(self._bvals[self._bvals >= self._b0_thres]) < len(affines):
                for i in sorted(b0_indices, reverse=True):
                    del affines[i]
            if len(self._bvals[self._bvals >= self._b0_thres]) > len(affines):
                ras_b_mat = self._gradients.copy()
                ras_b_mat = np.delete(ras_b_mat, tuple(b0_indices), axis=0)
                bvals = ras_b_mat[:, 3]
                bvecs = ras_b_mat[:, 0:3]
            if len(self._bvals[self._bvals > self._b0_thres]) != len(affines):
                raise ValueError(
                    "Affine transformations do not correspond to gradients")

        # Build gradient table object
        gt = gradient_table_from_bvals_bvecs(bvals,
                                             bvecs,
                                             b0_threshold=self._b0_thres)

        # Reorient table
        new_gt = reorient_bvecs(gt, [np.load(aff) for aff in affines])

        return np.hstack((new_gt.bvecs, new_gt.bvals[..., np.newaxis]))
Example #13
0
def test_all_constant():
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS']
    for fit_method in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_almost_equal(dm.fit(np.zeros(bvals.shape[0])).fa, 0)
        assert_almost_equal(dm.fit(100 * np.ones(bvals.shape[0])).fa, 0)
Example #14
0
def test_all_zeros():
    bvals, bvecs = read_bvals_bvecs(*get_fnames('55dir_grad'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs)
    fit_methods = ['LS', 'OLS', 'NNLS', 'RESTORE']
    for _ in fit_methods:
        dm = dti.TensorModel(gtab)
        npt.assert_array_almost_equal(
            dm.fit(np.zeros(bvals.shape[0])).evals, 0)
Example #15
0
def test_TensorModel():
    data, gtab = dsi_voxels()
    dm = dti.TensorModel(gtab, 'LS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.5, True)
    dm = dti.TensorModel(gtab, 'WLS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.5, True)
    sphere = create_unit_sphere(4)
    assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices))
    assert_almost_equal(dtifit.fa, gfa(dtifit.odf(sphere)), 1)

    # Check that the multivoxel case works:
    dtifit = dm.fit(data)
    assert_equal(dtifit.fa.shape, data.shape[:3])

    # Make some synthetic data
    b0 = 1000.
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    # The first b value is 0., so we take the second one:
    B = bvals[1]
    #Scale the eigenvalues and tensor by the B value so the units match
    D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B
    evals = np.array([2., 1., 0.]) / B
    md = evals.mean()
    tensor = from_lower_triangular(D)
    evecs = np.linalg.eigh(tensor)[1]
    #Design Matrix
    X = dti.design_matrix(bvecs, bvals)
    #Signals
    Y = np.exp(np.dot(X,D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1,) + Y.shape

    # Test fitting with different methods: #XXX Add NNLS methods!
    for fit_method in ['OLS', 'WLS']:
        tensor_model = dti.TensorModel(gtab,
                                       fit_method=fit_method)

        tensor_fit = tensor_model.fit(Y)
        assert_true(tensor_fit.model is tensor_model)
        assert_equal(tensor_fit.shape, Y.shape[:-1])
        assert_array_almost_equal(tensor_fit.evals[0], evals)

        assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor,
                                  err_msg =\
        "Calculation of tensor from Y does not compare to analytical solution")

        assert_almost_equal(tensor_fit.md[0], md)
        assert_equal(tensor_fit.directions.shape[-2], 1)
        assert_equal(tensor_fit.directions.shape[-1], 3)

    # Test error-handling:
    assert_raises(ValueError,
                  dti.TensorModel,
                  gtab,
                  fit_method='crazy_method')
Example #16
0
def test_all_constant():
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS', 'RESTORE']
    for _ in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_almost_equal(dm.fit(100 * np.ones(bvals.shape[0])).fa, 0)
        # Doesn't matter if the signal is smaller than 1:
        assert_almost_equal(dm.fit(0.4 * np.ones(bvals.shape[0])).fa, 0)
Example #17
0
def test_all_constant():
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS', 'RESTORE']
    for fit_method in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_almost_equal(dm.fit(100 * np.ones(bvals.shape[0])).fa, 0)
        # Doesn't matter if the signal is smaller than 1:
        assert_almost_equal(dm.fit(0.4 * np.ones(bvals.shape[0])).fa, 0)
def main():
    parser = build_argparser()
    args = parser.parse_args()

    dwi_name = args.dwi.split('.')[0]
    bvals_filename = dwi_name + ".bvals"
    bvecs_filename = dwi_name + ".bvecs"
    if args.bvals is not None:
        bvals_filename = args.bvals

    if args.bvecs is not None:
        bvecs_filename = args.bvecs

    bvals, bvecs = read_bvals_bvecs(bvals_filename, bvecs_filename)
    gtab = gradient_table_from_bvals_bvecs(bvals, bvecs)
    idx = gtab.bvals == 1000
    idx[np.logical_and(1000 - 15 <= gtab.bvals,
                       gtab.bvals <= 1000 + 15)] = True

    idx[0] = True
    b0_idx = gtab.bvals <= 15
    print("{} b=0 images will be averaged.".format(np.sum(b0_idx)))

    # Make sure we have the right numbers of each bval.
    assert np.sum(idx) == 91
    assert np.sum(
        np.logical_and(2000 - 15 <= gtab.bvals, gtab.bvals <= 2000 + 15)) == 90
    assert np.sum(
        np.logical_and(3000 - 20 <= gtab.bvals, gtab.bvals <= 3000 + 20)) == 90

    new_bvals = gtab.bvals[idx]
    assert new_bvals[0] <= 5
    new_bvals[0] = 0  # Make sure it is 0
    new_bvecs = gtab.bvecs[idx]

    dwi = nib.load(args.dwi)
    b0 = np.mean(dwi.get_data()[:, :, :, b0_idx], axis=-1)
    nii = nib.Nifti1Image(b0, affine=dwi.affine, header=dwi.header)
    out_dir = args.out
    try:
        os.makedirs(out_dir)
    except:
        pass  # Assume it already exists.

    # Write b0
    nib.save(nii, pjoin(out_dir, args.basename + "_b0.nii.gz"))

    new_dwi = dwi.get_data()[:, :, :, idx]
    new_dwi[:, :, :, 0] = b0.copy()
    nii = nib.Nifti1Image(new_dwi, affine=dwi.affine, header=dwi.header)
    dwi_out_name = args.basename + "_b{}".format(args.b_value)
    nib.save(nii, pjoin(out_dir, dwi_out_name + ".nii.gz"))
    open(pjoin(out_dir, dwi_out_name + ".bvecs"), 'w').write("\n".join(
        map(lambda bv: " ".join(map(str, bv)), new_bvecs.T)))
    open(pjoin(out_dir, dwi_out_name + ".bvals"),
         'w').write(" ".join(map(str, new_bvals)))
Example #19
0
def test_fit_method_error():
    bvec, bval = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bval, bvec.T)

    # This should work (smoke-testing!):
    TensorModel(gtab, fit_method='WLS')

    # This should raise an error because there is no such fit_method
    assert_raises(ValueError, TensorModel, gtab, min_signal=1e-9,
                  fit_method='s')
Example #20
0
def test_fit_method_error():
    bvec, bval = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bval, bvec.T)

    # This should work (smoke-testing!):
    TensorModel(gtab, fit_method='WLS')

    # This should raise an error because there is no such fit_method
    assert_raises(ValueError, TensorModel, gtab, min_signal=1e-9,
                  fit_method='s')
Example #21
0
def estimate_tensor(dwi_data, mask, bvals, bvecs):
    '''
    Estimate the tensor image using dipy.
    '''
    gtab = gradient_table_from_bvals_bvecs(bvals, bvecs)
    tenmodel = dti.TensorModel(gtab)
    tenfit = tenmodel.fit(dwi_data, mask=(mask > 0))
    tensor_data = tenfit.lower_triangular().astype('float32')
    tensor_data = tensor_data[..., np.newaxis, :] * mask[..., np.newaxis,
                                                         np.newaxis]
    return tensor_data
Example #22
0
def test_all_constant():
    """

    """
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    fit_methods = ['LS', 'OLS', 'NNLS']
    for fit_method in fit_methods:
        dm = dti.TensorModel(gtab)
        assert_almost_equal(dm.fit(np.zeros(bvals.shape[0])).fa, 0)
        assert_almost_equal(dm.fit(100 * np.ones(bvals.shape[0])).fa, 0)
Example #23
0
def test_tensor_model():
    fdata, fbval, fbvec = get_data('small_25')
    data1 = nib.load(fdata).get_data()
    gtab1 = grad.gradient_table(fbval, fbvec)
    data2, gtab2 = dsi_voxels()
    for data, gtab in zip([data1, data2], [gtab1, gtab2]):
        dm = dti.TensorModel(gtab, 'LS')
        dtifit = dm.fit(data[0, 0, 0])
        assert_equal(dtifit.fa < 0.9, True)
        dm = dti.TensorModel(gtab, 'WLS')
        dtifit = dm.fit(data[0, 0, 0])
        assert_equal(dtifit.fa < 0.9, True)
        assert_equal(dtifit.fa > 0, True)
        sphere = create_unit_sphere(4)
        assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices))
        # Check that the multivoxel case works:
        dtifit = dm.fit(data)

        # Check that it works on signal that has already been normalized to S0:
        dm_to_relative = dti.TensorModel(gtab)
        if np.any(gtab.b0s_mask):
            relative_data = (data[0, 0, 0]/np.mean(data[0, 0, 0,
                                                        gtab.b0s_mask]))

            dtifit_to_relative = dm_to_relative.fit(relative_data)
            npt.assert_almost_equal(dtifit.fa[0, 0, 0], dtifit_to_relative.fa,
                                    decimal=3)

    # And smoke-test that all these operations return sensibly-shaped arrays:
    assert_equal(dtifit.fa.shape, data.shape[:3])
    assert_equal(dtifit.ad.shape, data.shape[:3])
    assert_equal(dtifit.md.shape, data.shape[:3])
    assert_equal(dtifit.rd.shape, data.shape[:3])
    assert_equal(dtifit.trace.shape, data.shape[:3])
    assert_equal(dtifit.mode.shape, data.shape[:3])
    assert_equal(dtifit.linearity.shape, data.shape[:3])
    assert_equal(dtifit.planarity.shape, data.shape[:3])
    assert_equal(dtifit.sphericity.shape, data.shape[:3])

    # Test for the shape of the mask
    assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3, 3)))

    # Make some synthetic data
    b0 = 1000.
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    # The first b value is 0., so we take the second one:
    B = bvals[1]
    # Scale the eigenvalues and tensor by the B value so the units match
    D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B
    evals = np.array([2., 1., 0.]) / B
    md = evals.mean()
    tensor = from_lower_triangular(D)
    A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3)
    mode = (3 * np.sqrt(6) * np.linalg.det(A_squiggle /
            np.linalg.norm(A_squiggle)))
    evals_eigh, evecs_eigh = np.linalg.eigh(tensor)
    # Sort according to eigen-value from large to small:
    evecs = evecs_eigh[:, np.argsort(evals_eigh)[::-1]]
    # Check that eigenvalues and eigenvectors are properly sorted through
    # that previous operation:
    for i in range(3):
        assert_array_almost_equal(np.dot(tensor, evecs[:, i]),
                                  evals[i] * evecs[:, i])
    # Design Matrix
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1,) + Y.shape

    # Test fitting with different methods:
    for fit_method in ['OLS', 'WLS', 'NLLS']:
        tensor_model = dti.TensorModel(gtab,
                                       fit_method=fit_method,
                                       return_S0_hat=True)

        tensor_fit = tensor_model.fit(Y)
        assert_true(tensor_fit.model is tensor_model)
        assert_equal(tensor_fit.shape, Y.shape[:-1])
        assert_array_almost_equal(tensor_fit.evals[0], evals)
        assert_array_almost_equal(tensor_fit.S0_hat, b0, decimal=3)
        # Test that the eigenvectors are correct, one-by-one:
        for i in range(3):
            # Eigenvectors have intrinsic sign ambiguity
            # (see
            # http://prod.sandia.gov/techlib/access-control.cgi/2007/076422.pdf)
            # so we need to allow for sign flips. One of the following should
            # always be true:
            assert_(
                    np.all(np.abs(tensor_fit.evecs[0][:, i] -
                                  evecs[:, i]) < 10e-6) or
                    np.all(np.abs(-tensor_fit.evecs[0][:, i] -
                                  evecs[:, i]) < 10e-6))
            # We set a fixed tolerance of 10e-6, similar to array_almost_equal

        err_msg = "Calculation of tensor from Y does not compare to "
        err_msg += "analytical solution"
        assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor,
                                  err_msg=err_msg)

        assert_almost_equal(tensor_fit.md[0], md)
        assert_array_almost_equal(tensor_fit.mode, mode, decimal=5)
        assert_equal(tensor_fit.directions.shape[-2], 1)
        assert_equal(tensor_fit.directions.shape[-1], 3)

    # Test error-handling:
    assert_raises(ValueError,
                  dti.TensorModel,
                  gtab,
                  fit_method='crazy_method')

    # Test custom fit tensor method
    try:
        model = dti.TensorModel(gtab, fit_method=lambda *args, **kwargs: 42)
        fit = model.fit_method()
    except Exception as exc:
        assert False, "TensorModel should accept custom fit methods: %s" % exc
    assert fit == 42, "Custom fit method for TensorModel returned %s." % fit

    # Test multi-voxel data
    data = np.zeros((3, Y.shape[1]))
    # Normal voxel
    data[0] = Y
    # High diffusion voxel, all diffusing weighted signal equal to zero
    data[1, gtab.b0s_mask] = b0
    data[1, ~gtab.b0s_mask] = 0
    # Masked voxel, all data set to zero
    data[2] = 0.

    tensor_model = dti.TensorModel(gtab)
    fit = tensor_model.fit(data)
    assert_array_almost_equal(fit[0].evals, evals)

    # Return S0_test
    tensor_model = dti.TensorModel(gtab, return_S0_hat=True)
    fit = tensor_model.fit(data)
    assert_array_almost_equal(fit[0].evals, evals)
    assert_array_almost_equal(fit[0].S0_hat, b0)

    # Evals should be high for high diffusion voxel
    assert_(all(fit[1].evals > evals[0] * .9))

    # Evals should be zero where data is masked
    assert_array_almost_equal(fit[2].evals, 0.)
Example #24
0
def initial_fit(dwis,
                bvals,
                bvecs,
                mask,
                wm_roi,
                csf_roi,
                MD,
                csf_percentile=95,
                wm_percentile=5,
                lmin=0.1e-3,
                lmax=2.5e-3,
                evals_lmin=0.1e-3,
                evals_lmax=2.5e-3,
                md_value=0.6e-3,
                interpolate=True,
                fixed_MD=False):
    '''
    Produce the initial estimate of the volume fraction and the initial tensor image
    '''
    print(" - Compute baseline image and DW attenuation.")
    dim_x, dim_y, dim_z = mask.shape
    indices_dwis = (bvals > 0)
    nb_dwis = np.count_nonzero(indices_dwis)
    indices_b0 = (bvals == 0)
    nb_b0 = np.count_nonzero(indices_b0)
    # TO DO : address this line for multi-shell dwi
    b = bvals.max()
    b0 = dwis[..., indices_b0].mean(-1)
    # signal attenuation
    signal = dwis[..., indices_dwis] / b0[..., None]
    np.clip(signal, 1.0e-6, 1 - 1.0e-6, signal)
    signal[np.logical_not(mask)] = 0.
    # tissue b0 references
    csf_b0 = np.percentile(b0[csf_roi], csf_percentile)
    print("\t{0:2d}th percentile of b0 signal in CSF: {1}.".format(
        csf_percentile, csf_b0))
    wm_b0 = np.percentile(b0[wm_roi], wm_percentile)
    print("\t{0:2d}th percentile of b0 signal in WM : {1}.".format(
        wm_percentile, wm_b0))

    print(" - Compute initial volume fraction ...")
    # Eq. 7 from Pasternak 2009 MRM
    epsi = 1e-12  # only used to prevent log(0)
    init_f = 1 - np.log(b0 / wm_b0 + epsi) / np.log(csf_b0 / wm_b0)
    np.clip(init_f, 0.0, 1.0, init_f)
    alpha = init_f.copy()  # exponent for interpolation

    print(" - Compute fixed MD VF map")
    init_f_MD = (np.exp(-b * MD) - np.exp(-b * d)) / (np.exp(-b * md_value) -
                                                      np.exp(-b * d))
    np.clip(init_f_MD, 0.01, 0.99, init_f_MD)

    print(" - Compute min_f and max_f from lmin, lmax")
    ### This was following Pasternak 2009 although with an error
    ### Amin = exp(-b*lmax)   and Amax = exp(-b*lmin)  in that paper
    # min_f = (signal.min(-1)-np.exp(-b*d)) / (np.exp(-b*lmin)-np.exp(-b*d))
    # max_f = (signal.max(-1)-np.exp(-b*d)) / (np.exp(-b*lmax)-np.exp(-b*d))
    ### From Pasternak 2009 method, Amin < At implies that the
    ### term with signal.min(-1) in numerator is the upper bound of f
    ### although in that paper the equation 6 has fmin and fmax reversed.
    ### With lmin, lmax=0.1e-3, 2.5e-3, Amin = 0.08, Awater = 0.04
    ### and one can see that max_f here will usually be >> 1
    min_f = (signal.max(-1) - np.exp(-b * d)) / (np.exp(-b * lmin) -
                                                 np.exp(-b * d))
    max_f = (signal.min(-1) - np.exp(-b * d)) / (np.exp(-b * lmax) -
                                                 np.exp(-b * d))
    # If MD of a voxel is > 3.0e-3, min_f and max_f can be negative.
    # These voxels should be initialized as 0
    np.clip(min_f, 0.0, 1.0, min_f)
    np.clip(max_f, 0.0, 1.0, max_f)
    np.clip(init_f, min_f, max_f, init_f)

    if interpolate:
        print(" - Interpolate two estimates of volume fraction")
        # f = tissue fraction. with init_f high, alpha will be ~1 and init_f_MD will be weighted
        init_f = (np.power(init_f, (1 - alpha))) * (np.power(init_f_MD, alpha))
    elif fixed_MD:
        print(
            " - Using fixed MD value of {0} for inital volume fraction".format(
                md_value))
        init_f = init_f_MD
    else:
        print(" - Using lmin and lmax for initial volume fraction")

    np.clip(init_f, 0.05, 0.99, init_f)  # want minimum 5% of tissue
    init_f[np.isnan(init_f)] = 0.5
    init_f[np.logical_not(mask)] = 0.5

    print(" - Compute initial tissue tensor ...")
    signal[np.isnan(signal)] = 0
    bvecs = bvecs[indices_dwis]
    bvals = bvals[indices_dwis]
    signal_free_water = np.exp(-bvals * d)
    corrected_signal = (signal - (1 - init_f[..., np.newaxis]) \
                     * signal_free_water[np.newaxis, np.newaxis, np.newaxis, :]) \
                     / (init_f[..., np.newaxis])
    np.clip(corrected_signal, 1.0e-3, 1. - 1.0e-3, corrected_signal)
    log_signal = np.log(corrected_signal)
    gtab = gradient_table_from_bvals_bvecs(bvals, bvecs)
    H = dti.design_matrix(gtab)[:, :6]
    pseudo_inv = np.dot(np.linalg.inv(np.dot(H.T, H)), H.T)
    init_tensor = np.dot(log_signal, pseudo_inv.T)

    dti_params = dti.eig_from_lo_tri(init_tensor).reshape(
        (dim_x, dim_y, dim_z, 4, 3))
    evals = dti_params[..., 0, :]
    evecs = dti_params[..., 1:, :]
    if evals_lmin > 0.1e-3:
        print(" - Fatten tensor to {}".format(evals_lmin))
    lower_triangular = clip_tensor_evals(evals, evecs, evals_lmin, evals_lmax)
    lower_triangular[np.logical_not(mask)] = [
        evals_lmin, 0, evals_lmin, 0, 0, evals_lmin
    ]
    nan_mask = np.any(np.isnan(lower_triangular), axis=-1)
    lower_triangular[nan_mask] = [evals_lmin, 0, evals_lmin, 0, 0, evals_lmin]

    init_tensor = lower_triangular[:, :, :, np.newaxis, :]
    return init_f, init_tensor
Example #25
0
def segment_from_dwi(image,
                     bvals_file,
                     bvecs_file,
                     ROI,
                     threshold,
                     mask=None,
                     filename=None,
                     overwrite=True):
    """
    Takes a dwi, bvals and bvecs files and computes FA, RGB and a binary mask
    estimation of the supplied ROI according to a threshold on the RGB.
    """

    # Load raw dwi image
    data = image.get_data()
    affine = image.get_affine()

    # Load bval and bvec files, fit the tensor model
    print("Now fitting tensor model")
    b_vals, b_vecs = read_bvals_bvecs(bvals_file, bvecs_file)
    gtab = gradient_table_from_bvals_bvecs(b_vals, b_vecs)
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data)

    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    FA = np.clip(
        FA, 0,
        1)  # We clamp the FA between 0 and 1 to remove degenerate tensors

    if mask is not None:
        FA = apply_mask(FA, mask)

    FA_vol = nib.Nifti1Image(FA.astype('float32'), affine)

    if filename is None:
        FA_path = 'FA.nii.gz'
    else:
        FA_path = filename + '_FA.nii.gz'

    # Check if FA already exists
    if os.path.exists(FA_path):
        print("FA", FA_path, "already exists!")

        if overwrite is True:
            nib.save(FA_vol, FA_path)
            print("FA", FA_path, "was overwritten")
        else:
            print("New FA was not saved")
    else:
        nib.save(FA_vol, FA_path)
        print("FA was saved as ", FA_path)

    RGB = color_fa(FA, tenfit.evecs)

    if filename is None:
        RGB_path = 'RGB.nii.gz'
    else:
        RGB_path = filename + '_RGB.nii.gz'

    RGB_vol = nib.Nifti1Image(np.array(255 * RGB, 'uint8'), affine)

    # Check if RGB already exists
    if os.path.exists(RGB_path):
        print("RGB", RGB_path, "already exists!")

        if overwrite is True:
            nib.save(RGB_vol, RGB_path)
            print("RGB", RGB_path, "was overwritten")
        else:
            print("New RGB was not saved")
    else:
        nib.save(RGB_vol, RGB_path)
        print("RGB was saved as ", RGB_path)

    return segment_from_RGB(RGB, ROI, threshold)
Example #26
0
def test_TensorModel():
    data, gtab = dsi_voxels()
    dm = dti.TensorModel(gtab, 'LS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.5, True)
    dm = dti.TensorModel(gtab, 'WLS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.5, True)
    sphere = create_unit_sphere(4)
    assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices))
    assert_almost_equal(dtifit.fa, gfa(dtifit.odf(sphere)), 1)

    # Check that the multivoxel case works:
    dtifit = dm.fit(data)

    # And smoke-test that all these operations return sensibly-shaped arrays:
    assert_equal(dtifit.fa.shape, data.shape[:3])
    assert_equal(dtifit.ad.shape, data.shape[:3])
    assert_equal(dtifit.md.shape, data.shape[:3])
    assert_equal(dtifit.rd.shape, data.shape[:3])
    assert_equal(dtifit.trace.shape, data.shape[:3])
    assert_equal(dtifit.mode.shape, data.shape[:3])
    assert_equal(dtifit.linearity.shape, data.shape[:3])
    assert_equal(dtifit.planarity.shape, data.shape[:3])
    assert_equal(dtifit.sphericity.shape, data.shape[:3])

    # Test for the shape of the mask
    assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3,3)))

    # Make some synthetic data
    b0 = 1000.
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    # The first b value is 0., so we take the second one:
    B = bvals[1]
    # Scale the eigenvalues and tensor by the B value so the units match
    D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B
    evals = np.array([2., 1., 0.]) / B
    md = evals.mean()
    tensor = from_lower_triangular(D)
    A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3)
    mode = 3 * np.sqrt(6) * np.linalg.det(A_squiggle / np.linalg.norm(A_squiggle))
    evecs = np.linalg.eigh(tensor)[1]
    # Design Matrix
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1,) + Y.shape

    # Test fitting with different methods:
    for fit_method in ['OLS', 'WLS', 'NLLS']:
        tensor_model = dti.TensorModel(gtab,
                                       fit_method=fit_method)

        tensor_fit = tensor_model.fit(Y)
        assert_true(tensor_fit.model is tensor_model)
        assert_equal(tensor_fit.shape, Y.shape[:-1])
        assert_array_almost_equal(tensor_fit.evals[0], evals)

        assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor,
                                  err_msg=\
        "Calculation of tensor from Y does not compare to analytical solution")

        assert_almost_equal(tensor_fit.md[0], md)
        assert_array_almost_equal(tensor_fit.mode, mode, decimal=5)
        assert_equal(tensor_fit.directions.shape[-2], 1)
        assert_equal(tensor_fit.directions.shape[-1], 3)

    # Test error-handling:
    assert_raises(ValueError,
                  dti.TensorModel,
                  gtab,
                  fit_method='crazy_method')
Example #27
0
def test_tensor_model():
    fdata, fbval, fbvec = get_data('small_25')
    data1 = nib.load(fdata).get_data()
    gtab1 = grad.gradient_table(fbval, fbvec)
    data2, gtab2 = dsi_voxels()
    for data, gtab in zip([data1, data2], [gtab1, gtab2]):
        dm = dti.TensorModel(gtab, 'LS')
        dtifit = dm.fit(data[0, 0, 0])
        assert_equal(dtifit.fa < 0.9, True)
        dm = dti.TensorModel(gtab, 'WLS')
        dtifit = dm.fit(data[0, 0, 0])
        assert_equal(dtifit.fa < 0.9, True)
        assert_equal(dtifit.fa > 0, True)
        sphere = create_unit_sphere(4)
        assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices))
        # Check that the multivoxel case works:
        dtifit = dm.fit(data)

        # Check that it works on signal that has already been normalized to S0:
        dm_to_relative = dti.TensorModel(gtab)
        if np.any(gtab.b0s_mask):
            relative_data = (data[0, 0, 0] /
                             np.mean(data[0, 0, 0, gtab.b0s_mask]))

            dtifit_to_relative = dm_to_relative.fit(relative_data)
            npt.assert_almost_equal(dtifit.fa[0, 0, 0],
                                    dtifit_to_relative.fa,
                                    decimal=3)

    # And smoke-test that all these operations return sensibly-shaped arrays:
    assert_equal(dtifit.fa.shape, data.shape[:3])
    assert_equal(dtifit.ad.shape, data.shape[:3])
    assert_equal(dtifit.md.shape, data.shape[:3])
    assert_equal(dtifit.rd.shape, data.shape[:3])
    assert_equal(dtifit.trace.shape, data.shape[:3])
    assert_equal(dtifit.mode.shape, data.shape[:3])
    assert_equal(dtifit.linearity.shape, data.shape[:3])
    assert_equal(dtifit.planarity.shape, data.shape[:3])
    assert_equal(dtifit.sphericity.shape, data.shape[:3])

    # Test for the shape of the mask
    assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3, 3)))

    # Make some synthetic data
    b0 = 1000.
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    # The first b value is 0., so we take the second one:
    B = bvals[1]
    # Scale the eigenvalues and tensor by the B value so the units match
    D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B
    evals = np.array([2., 1., 0.]) / B
    md = evals.mean()
    tensor = from_lower_triangular(D)
    A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3)
    mode = 3 * np.sqrt(6) * np.linalg.det(
        A_squiggle / np.linalg.norm(A_squiggle))
    evecs = np.linalg.eigh(tensor)[1]
    # Design Matrix
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1, ) + Y.shape

    # Test fitting with different methods:
    for fit_method in ['OLS', 'WLS', 'NLLS']:
        tensor_model = dti.TensorModel(gtab, fit_method=fit_method)

        tensor_fit = tensor_model.fit(Y)
        assert_true(tensor_fit.model is tensor_model)
        assert_equal(tensor_fit.shape, Y.shape[:-1])
        assert_array_almost_equal(tensor_fit.evals[0], evals)

        assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor,
                                  err_msg=\
        "Calculation of tensor from Y does not compare to analytical solution")

        assert_almost_equal(tensor_fit.md[0], md)
        assert_array_almost_equal(tensor_fit.mode, mode, decimal=5)
        assert_equal(tensor_fit.directions.shape[-2], 1)
        assert_equal(tensor_fit.directions.shape[-1], 3)

    # Test error-handling:
    assert_raises(ValueError, dti.TensorModel, gtab, fit_method='crazy_method')

    # Test multi-voxel data
    data = np.zeros((3, Y.shape[1]))
    # Normal voxel
    data[0] = Y
    # High diffusion voxel, all diffusing weighted signal equal to zero
    data[1, gtab.b0s_mask] = b0
    data[1, ~gtab.b0s_mask] = 0
    # Masked voxel, all data set to zero
    data[2] = 0.

    tensor_model = dti.TensorModel(gtab)
    fit = tensor_model.fit(data)
    assert_array_almost_equal(fit[0].evals, evals)

    # Evals should be high for high diffusion voxel
    assert_(all(fit[1].evals > evals[0] * .9))

    # Evals should be zero where data is masked
    assert_array_almost_equal(fit[2].evals, 0.)
Example #28
0
def test_tensor_model():
    fdata, fbval, fbvec = get_data('small_25')
    data = nib.load(fdata).get_data()
    gtab = grad.gradient_table(fbval, fbvec)
    dm = dti.TensorModel(gtab, 'LS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.9, True)
    dm = dti.TensorModel(gtab, 'WLS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.9, True)
    assert_equal(dtifit.fa > 0, True)
    sphere = create_unit_sphere(4)
    assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices))
    # Check that the multivoxel case works:
    dtifit = dm.fit(data)

    # Check that it works on signal that has already been normalized to S0:
    dm_to_relative = dti.TensorModel(gtab)
    relative_data = (data[0, 0, 0]/np.mean(data[0, 0, 0, gtab.b0s_mask]))

    dtifit_to_relative = dm_to_relative.fit(relative_data)
    npt.assert_almost_equal(dtifit.fa[0,0,0], dtifit_to_relative.fa, decimal=3)

    # And smoke-test that all these operations return sensibly-shaped arrays:
    assert_equal(dtifit.fa.shape, data.shape[:3])
    assert_equal(dtifit.ad.shape, data.shape[:3])
    assert_equal(dtifit.md.shape, data.shape[:3])
    assert_equal(dtifit.rd.shape, data.shape[:3])
    assert_equal(dtifit.trace.shape, data.shape[:3])
    assert_equal(dtifit.mode.shape, data.shape[:3])
    assert_equal(dtifit.linearity.shape, data.shape[:3])
    assert_equal(dtifit.planarity.shape, data.shape[:3])
    assert_equal(dtifit.sphericity.shape, data.shape[:3])

    # Test for the shape of the mask
    assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3,3)))

    # Make some synthetic data
    b0 = 1000.
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    # The first b value is 0., so we take the second one:
    B = bvals[1]
    # Scale the eigenvalues and tensor by the B value so the units match
    D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B
    evals = np.array([2., 1., 0.]) / B
    md = evals.mean()
    tensor = from_lower_triangular(D)
    A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3)
    mode = 3 * np.sqrt(6) * np.linalg.det(A_squiggle / np.linalg.norm(A_squiggle))
    evecs = np.linalg.eigh(tensor)[1]
    # Design Matrix
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1,) + Y.shape

    # Test fitting with different methods:
    for fit_method in ['OLS', 'WLS', 'NLLS']:
        tensor_model = dti.TensorModel(gtab,
                                       fit_method=fit_method)

        tensor_fit = tensor_model.fit(Y)
        assert_true(tensor_fit.model is tensor_model)
        assert_equal(tensor_fit.shape, Y.shape[:-1])
        assert_array_almost_equal(tensor_fit.evals[0], evals)

        assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor,
                                  err_msg=\
        "Calculation of tensor from Y does not compare to analytical solution")

        assert_almost_equal(tensor_fit.md[0], md)
        assert_array_almost_equal(tensor_fit.mode, mode, decimal=5)
        assert_equal(tensor_fit.directions.shape[-2], 1)
        assert_equal(tensor_fit.directions.shape[-1], 3)

    # Test error-handling:
    assert_raises(ValueError,
                  dti.TensorModel,
                  gtab,
                  fit_method='crazy_method')

    # Test multi-voxel data
    data = np.zeros((3, Y.shape[1]))
    # Normal voxel
    data[0] = Y
    # High diffusion voxel, all diffusing weighted signal equal to zero
    data[1, gtab.b0s_mask] = b0
    data[1, ~gtab.b0s_mask] = 0
    # Masked voxel, all data set to zero
    data[2] = 0.

    tensor_model = dti.TensorModel(gtab)
    fit = tensor_model.fit(data)
    assert_array_almost_equal(fit[0].evals, evals)

    # Evals should be high for high diffusion voxel
    assert_(all(fit[1].evals > evals[0] * .9))

    # Evals should be zero where data is masked
    assert_array_almost_equal(fit[2].evals, 0.)
Example #29
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 #30
0
def gradient_descent(dwis, bvals, bvecs, mask, init_f, init_tensor, niters=50):
    '''
    Optimize the volume fraction and the tensor via gradient descent.
    '''
    dim_x, dim_y, dim_z = mask.shape
    indices_dwis = (bvals > 0)
    nb_dwis = np.count_nonzero(indices_dwis)
    indices_b0 = (bvals == 0)
    nb_b0 = np.count_nonzero(indices_b0)
    b = bvals.max()
    b0 = dwis[..., indices_b0].mean(-1)
    signal = dwis[..., indices_dwis] / b0[..., None]
    np.clip(signal, 1.0e-6, 1 - 1.0e-6, signal)
    bvals = bvals[indices_dwis]
    bvecs = bvecs[indices_dwis]
    gtab = gradient_table_from_bvals_bvecs(bvals, bvecs)
    H = dti.design_matrix(gtab)[:, :6]
    signal[np.logical_not(mask)] = 0.
    signal = signal[mask]
    lower_triangular = init_tensor[mask, 0]
    volume_fraction = init_f[mask]
    print(" - Begin gradient descent.")
    mask_nvoxels = np.count_nonzero(mask)
    step_size = 1.0e-7
    weight = 100.0
    l_min_loop, l_max_loop = 0.1e-3, 2.5e-3

    for i in range(niters):
        print(" - Iteration {0:d} out of {1:d}.".format(i + 1, niters))

        grad1, predicted_signal_tissue, predicted_signal_water = \
            grad_data_fit_tensor(lower_triangular, signal, H, bvals,
                                 volume_fraction)
        print("\tgrad1 avg: {0:0.4e}".format(np.mean(np.abs(grad1))))
        predicted_signal = volume_fraction[..., None] * predicted_signal_tissue + \
                           (1-volume_fraction[..., None]) * predicted_signal_water
        prediction_error = np.sqrt(((predicted_signal - signal)**2).mean(-1))
        print("\tpref error avg: {0:0.4e}".format(np.mean(prediction_error)))

        gradf = (bvals * (predicted_signal - signal) \
                           * (predicted_signal_tissue - predicted_signal_water)).sum(-1)
        print("\tgradf avg: {0:0.4e}".format(np.mean(np.abs(gradf))))
        volume_fraction -= weight * step_size * gradf

        grad1[np.isnan(grad1)] = 0
        # np.clip(grad1, -1.e5, 1.e5, grad1)
        np.clip(volume_fraction, 0.01, 0.99, volume_fraction)
        lower_triangular -= step_size * grad1
        lower_triangular[np.isnan(lower_triangular)] = 0

        dti_params = dti.eig_from_lo_tri(lower_triangular).reshape(
            (mask_nvoxels, 4, 3))
        evals = dti_params[..., 0, :]
        evecs = dti_params[..., 1:, :]
        lower_triangular = clip_tensor_evals(evals, evecs, l_min_loop,
                                             l_max_loop)
        del dti_params, evals, evecs

    final_tensor = np.zeros((dim_x, dim_y, dim_z, 1, 6), dtype=np.float32)
    final_tensor[mask, 0] = lower_triangular
    final_f = np.zeros((dim_x, dim_y, dim_z), dtype=np.float32)
    final_f[mask] = 1 - volume_fraction

    return final_f, final_tensor
Example #31
0
def test_TensorModel():
    data, gtab = dsi_voxels()
    dm = dti.TensorModel(gtab, 'LS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.5, True)
    dm = dti.TensorModel(gtab, 'WLS')
    dtifit = dm.fit(data[0, 0, 0])
    assert_equal(dtifit.fa < 0.5, True)
    sphere = create_unit_sphere(4)
    assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices))
    assert_almost_equal(dtifit.fa, gfa(dtifit.odf(sphere)), 1)

    # Check that the multivoxel case works:
    dtifit = dm.fit(data)

    # And smoke-test that all these operations return sensibly-shaped arrays:
    assert_equal(dtifit.fa.shape, data.shape[:3])
    assert_equal(dtifit.ad.shape, data.shape[:3])
    assert_equal(dtifit.md.shape, data.shape[:3])
    assert_equal(dtifit.rd.shape, data.shape[:3])
    assert_equal(dtifit.trace.shape, data.shape[:3])
    assert_equal(dtifit.mode.shape, data.shape[:3])
    assert_equal(dtifit.linearity.shape, data.shape[:3])
    assert_equal(dtifit.planarity.shape, data.shape[:3])
    assert_equal(dtifit.sphericity.shape, data.shape[:3])

    # Test for the shape of the mask
    assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3, 3)))

    # Make some synthetic data
    b0 = 1000.
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    # The first b value is 0., so we take the second one:
    B = bvals[1]
    # Scale the eigenvalues and tensor by the B value so the units match
    D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B
    evals = np.array([2., 1., 0.]) / B
    md = evals.mean()
    tensor = from_lower_triangular(D)
    A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3)
    mode = 3 * np.sqrt(6) * np.linalg.det(
        A_squiggle / np.linalg.norm(A_squiggle))
    evecs = np.linalg.eigh(tensor)[1]
    # Design Matrix
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1, ) + Y.shape

    # Test fitting with different methods:
    for fit_method in ['OLS', 'WLS', 'NLLS']:
        tensor_model = dti.TensorModel(gtab, fit_method=fit_method)

        tensor_fit = tensor_model.fit(Y)
        assert_true(tensor_fit.model is tensor_model)
        assert_equal(tensor_fit.shape, Y.shape[:-1])
        assert_array_almost_equal(tensor_fit.evals[0], evals)

        assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor,
                                  err_msg=\
        "Calculation of tensor from Y does not compare to analytical solution")

        assert_almost_equal(tensor_fit.md[0], md)
        assert_array_almost_equal(tensor_fit.mode, mode, decimal=5)
        assert_equal(tensor_fit.directions.shape[-2], 1)
        assert_equal(tensor_fit.directions.shape[-1], 3)

    # Test error-handling:
    assert_raises(ValueError, dti.TensorModel, gtab, fit_method='crazy_method')
Example #32
0
  def reconstruct( diffusion_file, bvals_file, bvecs_file, warped_segmentation_file, fa_file, adc_file, evecs_file ):
    '''
    Reconstruct a diffusion image by fitting a tensor model.
    
    diffusion_file
      the diffusion image file path to reconstruct
    bvals_file
      the b-value file path
    bvecs_file
      the b-vector file path
    warped_segmentation_file
      the segmentation/mask file path
    fa_file
      the fa map output file path
    adc_file
      the adc map output file path
    evecs_file
      the evecs map output file path
    '''
    # load the input image
    input_image = nibabel.load( diffusion_file )

    # grab the input data
    data = input_image.get_data()

    # create a simple mask
    #mask = data[..., 0] > 50
    
    # create a mask from the segmentation file 
    mask_image = nibabel.load( warped_segmentation_file ).get_data()
    mask = mask_image[...] > 0

    # load the bval and bvec files
    b_values, b_vectors = dipy.io.read_bvals_bvecs( bvals_file, bvecs_file )

    # create a gradient table
    gradient_table = gradienter.gradient_table_from_bvals_bvecs( b_values, b_vectors, 0, 10 )

    # instantiate tensor model
    tensor_model = reconstructer.TensorModel( gradient_table )

    print 'starting fiting..'
    # perform tensor fitting
    tensor_fitting = tensor_model.fit( data, mask )
    print 'ending fiting..'


    # create FA map
    fa_map = tensor_fitting.fa

    # clean-up FA map
    fa_map[numpy.isnan( fa_map )] = 0

    # create ADC map
    adc_map = tensor_fitting.md

    # clean-up ADC map
    adc_map[numpy.isnan( adc_map )] = 0

    # create eigenvector map
    evecs_map = tensor_fitting.evecs

    # store the maps
    nibabel.save( nibabel.Nifti1Image( fa_map, input_image.get_affine() ), fa_file )
    nibabel.save( nibabel.Nifti1Image( adc_map, input_image.get_affine() ), adc_file )
    nibabel.save( nibabel.Nifti1Image( evecs_map, input_image.get_affine() ), evecs_file )
Example #33
0
def image_gradient_consistency_check(dwi_file,
                                     bvecs,
                                     bvals,
                                     b0_threshold=B0_THRESHOLD):
    """
    Check that gradient encoding patterns found in the b-values correspond to those
    found in the signal intensity variance across volumes of the dwi image.

    Parameters
    ----------
    dwi_file : str
        Optionally provide a file path to the diffusion-weighted image series to which the
        bvecs/bvals should correspond.
    bvecs : m x n 2d array
        B-vectors array.
    bvals : 1d array
        B-values float array.
    b0_threshold : float
        Gradient threshold below which volumes and vectors are considered B0's.
    """
    import nibabel as nib
    from dipy.core.gradients import gradient_table_from_bvals_bvecs
    from sklearn.cluster import MeanShift, estimate_bandwidth

    # Build gradient table object
    gtab = gradient_table_from_bvals_bvecs(bvals,
                                           bvecs,
                                           b0_threshold=b0_threshold)

    # Check that number of image volumes corresponds to the number of gradient encodings.
    volume_num = nib.load(dwi_file).shape[-1]
    if not len(bvals) == volume_num:
        raise Exception(
            "Expected %d total image samples but found %d total gradient encoding values",
            volume_num, len(bvals))
    # Evaluate B0 locations relative to mean signal variation.
    data = np.array(nib.load(dwi_file).dataobj)
    signal_means = []
    for vol in range(data.shape[-1]):
        signal_means.append(np.mean(data[:, :, :, vol]))
    signal_b0_indices = np.where(
        signal_means > np.mean(signal_means) + 3 * np.std(signal_means))[0]

    # Check B0 locations first
    if not np.allclose(np.where(gtab.b0s_mask == True)[0], signal_b0_indices):
        raise UserWarning(
            'B0 indices in vectors do not correspond to relative high-signal contrast volumes '
            'detected in dwi image.')

    # Next check number of unique b encodings (i.e. shells) and their indices
    X = np.array(signal_means).reshape(-1, 1)
    ms = MeanShift(bandwidth=estimate_bandwidth(X, quantile=0.1),
                   bin_seeding=True)
    ms.fit(X)
    labs, idx = np.unique(ms.labels_, return_index=True)
    ix_img = []
    i = -1
    for val in range(len(ms.labels_)):
        if val in np.sort(idx[::-1]):
            i = i + 1
        ix_img.append(labs[i])
    ix_img = np.array(ix_img)

    ix_vec = []
    i = -1
    for val in range(len(bvals)):
        if bvals[val] != bvals[val - 1]:
            i = i + 1
        ix_vec.append(i)
    ix_vec = np.array(ix_vec)

    if len(ms.cluster_centers_) != len(np.unique(bvals)):
        raise UserWarning(
            'Number of unique b-values does not correspond to number of unique signal gradient '
            'encoding intensities in the dwi image.')

    if np.all(np.isclose(ix_img, ix_vec)) is True:
        raise UserWarning(
            'Positions of b-value B0\'s and shell(s) do not correspond to signal intensity '
            'fluctuation patterns in the dwi image.')
    return
Example #34
0
def test_tensor_model():
    fdata, fbval, fbvec = get_data('small_25')
    data1 = nib.load(fdata).get_data()
    gtab1 = grad.gradient_table(fbval, fbvec)
    data2, gtab2 = dsi_voxels()
    for data, gtab in zip([data1, data2], [gtab1, gtab2]):
        dm = dti.TensorModel(gtab, 'LS')
        dtifit = dm.fit(data[0, 0, 0])
        assert_equal(dtifit.fa < 0.9, True)
        dm = dti.TensorModel(gtab, 'WLS')
        dtifit = dm.fit(data[0, 0, 0])
        assert_equal(dtifit.fa < 0.9, True)
        assert_equal(dtifit.fa > 0, True)
        sphere = create_unit_sphere(4)
        assert_equal(len(dtifit.odf(sphere)), len(sphere.vertices))
        # Check that the multivoxel case works:
        dtifit = dm.fit(data)

        # Check that it works on signal that has already been normalized to S0:
        dm_to_relative = dti.TensorModel(gtab)
        if np.any(gtab.b0s_mask):
            relative_data = (data[0, 0, 0]/np.mean(data[0, 0, 0,
                                                        gtab.b0s_mask]))

            dtifit_to_relative = dm_to_relative.fit(relative_data)
            npt.assert_almost_equal(dtifit.fa[0, 0, 0], dtifit_to_relative.fa,
                                    decimal=3)

    # And smoke-test that all these operations return sensibly-shaped arrays:
    assert_equal(dtifit.fa.shape, data.shape[:3])
    assert_equal(dtifit.ad.shape, data.shape[:3])
    assert_equal(dtifit.md.shape, data.shape[:3])
    assert_equal(dtifit.rd.shape, data.shape[:3])
    assert_equal(dtifit.trace.shape, data.shape[:3])
    assert_equal(dtifit.mode.shape, data.shape[:3])
    assert_equal(dtifit.linearity.shape, data.shape[:3])
    assert_equal(dtifit.planarity.shape, data.shape[:3])
    assert_equal(dtifit.sphericity.shape, data.shape[:3])

    # Test for the shape of the mask
    assert_raises(ValueError, dm.fit, np.ones((10, 10, 3)), np.ones((3, 3)))

    # Make some synthetic data
    b0 = 1000.
    bvecs, bvals = read_bvec_file(get_data('55dir_grad.bvec'))
    gtab = grad.gradient_table_from_bvals_bvecs(bvals, bvecs.T)
    # The first b value is 0., so we take the second one:
    B = bvals[1]
    # Scale the eigenvalues and tensor by the B value so the units match
    D = np.array([1., 1., 1., 0., 0., 1., -np.log(b0) * B]) / B
    evals = np.array([2., 1., 0.]) / B
    md = evals.mean()
    tensor = from_lower_triangular(D)
    A_squiggle = tensor - (1 / 3.0) * np.trace(tensor) * np.eye(3)
    mode = (3 * np.sqrt(6) * np.linalg.det(A_squiggle /
            np.linalg.norm(A_squiggle)))
    evals_eigh, evecs_eigh = np.linalg.eigh(tensor)
    # Sort according to eigen-value from large to small:
    evecs = evecs_eigh[:, np.argsort(evals_eigh)[::-1]]
    # Check that eigenvalues and eigenvectors are properly sorted through
    # that previous operation:
    for i in range(3):
        assert_array_almost_equal(np.dot(tensor, evecs[:, i]),
                                  evals[i] * evecs[:, i])
    # Design Matrix
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1,) + Y.shape

    # Test fitting with different methods:
    for fit_method in ['OLS', 'WLS', 'NLLS']:
        tensor_model = dti.TensorModel(gtab,
                                       fit_method=fit_method,
                                       return_S0_hat=True)

        tensor_fit = tensor_model.fit(Y)
        assert_true(tensor_fit.model is tensor_model)
        assert_equal(tensor_fit.shape, Y.shape[:-1])
        assert_array_almost_equal(tensor_fit.evals[0], evals)
        assert_array_almost_equal(tensor_fit.S0_hat, b0, decimal=3)
        # Test that the eigenvectors are correct, one-by-one:
        for i in range(3):
            # Eigenvectors have intrinsic sign ambiguity
            # (see
            # http://prod.sandia.gov/techlib/access-control.cgi/2007/076422.pdf)
            # so we need to allow for sign flips. One of the following should
            # always be true:
            assert_(
                    np.all(np.abs(tensor_fit.evecs[0][:, i] -
                                  evecs[:, i]) < 10e-6) or
                    np.all(np.abs(-tensor_fit.evecs[0][:, i] -
                                  evecs[:, i]) < 10e-6))
            # We set a fixed tolerance of 10e-6, similar to array_almost_equal

        err_msg = "Calculation of tensor from Y does not compare to "
        err_msg += "analytical solution"
        assert_array_almost_equal(tensor_fit.quadratic_form[0], tensor,
                                  err_msg=err_msg)

        assert_almost_equal(tensor_fit.md[0], md)
        assert_array_almost_equal(tensor_fit.mode, mode, decimal=5)
        assert_equal(tensor_fit.directions.shape[-2], 1)
        assert_equal(tensor_fit.directions.shape[-1], 3)

    # Test error-handling:
    assert_raises(ValueError,
                  dti.TensorModel,
                  gtab,
                  fit_method='crazy_method')

    # Test custom fit tensor method
    try:
        model = dti.TensorModel(gtab, fit_method=lambda *args, **kwargs: 42)
        fit = model.fit_method()
    except Exception as exc:
        assert False, "TensorModel should accept custom fit methods: %s" % exc
    assert fit == 42, "Custom fit method for TensorModel returned %s." % fit

    # Test multi-voxel data
    data = np.zeros((3, Y.shape[1]))
    # Normal voxel
    data[0] = Y
    # High diffusion voxel, all diffusing weighted signal equal to zero
    data[1, gtab.b0s_mask] = b0
    data[1, ~gtab.b0s_mask] = 0
    # Masked voxel, all data set to zero
    data[2] = 0.

    tensor_model = dti.TensorModel(gtab)
    fit = tensor_model.fit(data)
    assert_array_almost_equal(fit[0].evals, evals)

    # Return S0_test
    tensor_model = dti.TensorModel(gtab, return_S0_hat=True)
    fit = tensor_model.fit(data)
    assert_array_almost_equal(fit[0].evals, evals)
    assert_array_almost_equal(fit[0].S0_hat, b0)

    # Evals should be high for high diffusion voxel
    assert_(all(fit[1].evals > evals[0] * .9))

    # Evals should be zero where data is masked
    assert_array_almost_equal(fit[2].evals, 0.)
def main():
    # parse command line parameters
    parser = argparse.ArgumentParser(description='Compute the anisotropic \
    power map for the given dMRI data set. Computes spherical deconvolution \
    from the highest b-balue. ')
    parser.add_argument('data', help='[IN]  4D input data volume')
    parser.add_argument('bval',
                        help='[IN]  text file with b-values (FSL format)')
    parser.add_argument('bvec',
                        help='[IN]  text file with b-vectors (FSL format)')
    parser.add_argument('mask', help='[IN]  3D mask volume')
    parser.add_argument(
        '--power',
        default=2,
        type=float,
        help='[IN]  The degree to which power maps are calculated')
    parser.add_argument('out',
                        help='[OUT] name of file for anisotropic power map')
    parser.add_argument(
        '--attenuation',
        '-a',
        action='store_true',
        default=False,
        help='use signal attenuation instead of full signal amplitude')
    parser.add_argument('--n_processes',
                        '-j',
                        default=8,
                        type=int,
                        help='Number of parallel processes')
    parser.add_argument('--verbose',
                        '-v',
                        action='store_true',
                        default=False,
                        help='be verbose')

    args = parser.parse_args()

    data_file_name = args.data
    bval_file_name = args.bval
    bvec_file_name = args.bvec
    mask_file_name = args.mask
    power = args.power
    out_file_name = args.out
    signal_attenuation = args.attenuation
    nbr_processes = args.n_processes
    verbose = args.verbose

    # load b-values and b-vectors
    if verbose:
        print('loading b-values and b-vectors')
    bvals, bvecs = read_bvals_bvecs(bval_file_name, bvec_file_name)

    # round b-values to 50s
    bvals = np.round(bvals / 50.0) * 50
    b_thresh = np.max(bvals) - 10

    selected_volumes = np.asarray(
        [np.any(tup) for tup in zip(bvals > b_thresh, bvals < 50)])

    gtab = gradient_table_from_bvals_bvecs(bvals[selected_volumes],
                                           bvecs[selected_volumes],
                                           atol=0.1)
    if verbose:
        print(gtab.bvals)

    # load the diffusion data
    if verbose:
        print('loading mask')
    img = nib.load(mask_file_name)
    mask = img.get_data()

    # load the diffusion data
    if verbose:
        print('loading diffusion data')
    img = nib.load(data_file_name)
    affine = img.get_affine()
    data = img.get_data(caching='unchanged')[..., selected_volumes]

    if signal_attenuation:
        # compute signal attenuation
        if verbose:
            print('computing signal attenuation')
        mean_b0 = np.mean(data[..., gtab.b0s_mask], axis=3)
        # vectorize !
        for vol in range(data.shape[3]):
            data[..., vol] = data[..., vol] / mean_b0

    if verbose:
        print('ensuring valid numbers')
    data = np.nan_to_num(data)
    data[data < 0] = 0

    # compute anisotropic power map
    if verbose:
        print('compute anisotropic power map')
    apm = anisotropic_power_map(data,
                                mask,
                                gtab,
                                power=power,
                                nbr_processes=nbr_processes,
                                verbose=verbose)

    # save anisotropic power map
    img = nib.Nifti1Image(apm, affine)
    nib.save(img, out_file_name)
Example #36
0
def main():
    params = readArgs()
    # read in from the command line
    read_args = params.collect_args()
    params.check_args(read_args)

    # get img obj
    dwi_img = nib.load(params.dwi_)
    mask_img = nib.load(params.mask_)

    from dipy.io import read_bvals_bvecs
    bvals, bvecs = read_bvals_bvecs(params.bval_, params.bvec_)

    # need to create the gradient table yo
    from dipy.core.gradients import gradient_table
    gtab = gradient_table(bvals, bvecs, b0_threshold=25)

    # get the data from image objects
    dwi_data = dwi_img.get_data()
    mask_data = mask_img.get_data()
    # and get affine
    img_affine = dwi_img.affine

    from dipy.data import get_sphere
    sphere = get_sphere('repulsion724')

    from dipy.segment.mask import applymask
    dwi_data = applymask(dwi_data, mask_data)

    printfl('dwi_data.shape (%d, %d, %d, %d)' % dwi_data.shape)
    printfl('\nYour bvecs look like this:{0}'.format(bvecs))
    printfl('\nYour bvals look like this:{0}\n'.format(bvals))

    from dipy.reconst.shm import anisotropic_power, sph_harm_lookup, smooth_pinv, normalize_data
    from dipy.core.sphere import HemiSphere

    smooth = 0.0
    normed_data = normalize_data(dwi_data, gtab.b0s_mask)
    normed_data = normed_data[..., np.where(1 - gtab.b0s_mask)[0]]

    from dipy.core.gradients import gradient_table_from_bvals_bvecs
    gtab2 = gradient_table_from_bvals_bvecs(
        gtab.bvals[np.where(1 - gtab.b0s_mask)[0]],
        gtab.bvecs[np.where(1 - gtab.b0s_mask)[0]])

    signal_native_pts = HemiSphere(xyz=gtab2.bvecs)
    sph_harm_basis = sph_harm_lookup.get(None)
    Ba, m, n = sph_harm_basis(params.sh_order_, signal_native_pts.theta,
                              signal_native_pts.phi)

    L = -n * (n + 1)
    invB = smooth_pinv(Ba, np.sqrt(smooth) * L)

    # fit SH basis to DWI signal
    normed_data_sh = np.dot(normed_data, invB.T)

    # power map call
    printfl("fitting power map")
    pow_map = anisotropic_power(normed_data_sh,
                                norm_factor=0.00001,
                                power=2,
                                non_negative=True)

    pow_map_img = nib.Nifti1Image(pow_map.astype(np.float32), img_affine)
    # make output name
    out_name = ''.join(
        [params.output_, '_powMap_sh',
         str(params.sh_order_), '.nii.gz'])

    printfl("writing power map to: {}".format(out_name))
    nib.save(pow_map_img, out_name)
Example #37
0
def test_reorient_bvecs():
    sq2 = np.sqrt(2) / 2
    bvals = np.concatenate([[0], np.ones(6) * 1000])
    bvecs = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1],
                      [sq2, sq2, 0], [sq2, 0, sq2], [0, sq2, sq2]])

    gt = gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=0)
    # The simple case: all affines are identity
    affs = np.zeros((6, 4, 4))
    for i in range(4):
        affs[:, i, i] = 1

    # We should get back the same b-vectors
    new_gt = reorient_bvecs(gt, affs)
    npt.assert_equal(gt.bvecs, new_gt.bvecs)

    # Now apply some rotations
    rotation_affines = []
    rotated_bvecs = bvecs[:]
    for i in np.where(~gt.b0s_mask)[0]:
        rot_ang = np.random.rand()
        cos_rot = np.cos(rot_ang)
        sin_rot = np.sin(rot_ang)
        rotation_affines.append(
            np.array([[1, 0, 0, 0], [0, cos_rot, -sin_rot, 0],
                      [0, sin_rot, cos_rot, 0], [0, 0, 0, 1]]))
        rotated_bvecs[i] = np.dot(rotation_affines[-1][:3, :3], bvecs[i])

    # Copy over the rotation affines
    full_affines = rotation_affines[:]
    # And add some scaling and translation to each one to make this harder
    for i in range(len(full_affines)):
        full_affines[i] = np.dot(
            full_affines[i],
            np.array([[2.5, 0, 0, -10], [0, 2.2, 0, 20], [0, 0, 1, 0],
                      [0, 0, 0, 1]]))

    gt_rot = gradient_table_from_bvals_bvecs(bvals,
                                             rotated_bvecs,
                                             b0_threshold=0)
    new_gt = reorient_bvecs(gt_rot, full_affines)
    # At the end of all this, we should be able to recover the original
    # vectors
    npt.assert_almost_equal(gt.bvecs, new_gt.bvecs)

    # We should be able to pass just the 3-by-3 rotation components to the same
    # effect
    new_gt = reorient_bvecs(gt_rot, np.array(rotation_affines)[:, :3, :3])
    npt.assert_almost_equal(gt.bvecs, new_gt.bvecs)

    # Verify that giving the wrong number of affines raises an error:
    full_affines.append(np.zeros((4, 4)))
    npt.assert_raises(ValueError, reorient_bvecs, gt_rot, full_affines)

    # Shear components in the matrix need to be decomposed into rotation only,
    # and should not lead to scaling of the bvecs
    shear_affines = []
    for i in np.where(~gt.b0s_mask)[0]:
        shear_affines.append(
            np.array([[1, 0, 1, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]))
    # atol is set to 1 here to do the scaling verification here,
    # so that the reorient_bvecs function does not throw an error itself
    new_gt = reorient_bvecs(gt, np.array(shear_affines)[:, :3, :3], atol=1)
    bvecs_close_to_1 = abs(vector_norm(new_gt.bvecs[~gt.b0s_mask]) -
                           1) <= 0.001
    npt.assert_(np.all(bvecs_close_to_1))