Ejemplo n.º 1
0
def test_diffusivities():
    psphere = get_sphere('symmetric362')
    bvecs = np.concatenate(([[0, 0, 0]], psphere.vertices))
    bvals = np.zeros(len(bvecs)) + 1000
    bvals[0] = 0
    gtab = grad.gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0001], [0.0015, 0.0003, 0.0003]))
    mevecs = [np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
              np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]])]
    S = single_tensor(gtab, 100, mevals[0], mevecs[0], snr=None)

    dm = dti.TensorModel(gtab, 'LS')
    dmfit = dm.fit(S)

    md = mean_diffusivity(dmfit.evals)
    Trace = trace(dmfit.evals)
    rd = radial_diffusivity(dmfit.evals)
    ad = axial_diffusivity(dmfit.evals)
    lin = linearity(dmfit.evals)
    plan = planarity(dmfit.evals)
    spher = sphericity(dmfit.evals)

    assert_almost_equal(md, (0.0015 + 0.0003 + 0.0001) / 3)
    assert_almost_equal(Trace, (0.0015 + 0.0003 + 0.0001))
    assert_almost_equal(ad, 0.0015)
    assert_almost_equal(rd, (0.0003 + 0.0001) / 2)
    assert_almost_equal(lin, (0.0015 - 0.0003)/Trace)
    assert_almost_equal(plan, 2 * (0.0003 - 0.0001)/Trace)
    assert_almost_equal(spher, (3 * 0.0001)/Trace)
Ejemplo n.º 2
0
def test_diffusivities():
    psphere = get_sphere('symmetric362')
    bvecs = np.concatenate(([[0, 0, 0]], psphere.vertices))
    bvals = np.zeros(len(bvecs)) + 1000
    bvals[0] = 0
    gtab = grad.gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0001], [0.0015, 0.0003, 0.0003]))
    mevecs = [np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
              np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]])]
    S = single_tensor(gtab, 100, mevals[0], mevecs[0], snr=None)

    dm = dti.TensorModel(gtab, 'LS')
    dmfit = dm.fit(S)

    md = mean_diffusivity(dmfit.evals)
    Trace = trace(dmfit.evals)
    rd = radial_diffusivity(dmfit.evals)
    ad = axial_diffusivity(dmfit.evals)
    lin = linearity(dmfit.evals)
    plan = planarity(dmfit.evals)
    spher = sphericity(dmfit.evals)

    assert_almost_equal(md, (0.0015 + 0.0003 + 0.0001) / 3)
    assert_almost_equal(Trace, (0.0015 + 0.0003 + 0.0001))
    assert_almost_equal(ad, 0.0015)
    assert_almost_equal(rd, (0.0003 + 0.0001) / 2)
    assert_almost_equal(lin, (0.0015 - 0.0003)/Trace)
    assert_almost_equal(plan, 2 * (0.0003 - 0.0001)/Trace)
    assert_almost_equal(spher, (3 * 0.0001)/Trace)
Ejemplo n.º 3
0
def test_wls_and_ls_fit():
    """
    Tests the WLS and LS fitting functions to see if they returns the correct
    eigenvalues and eigenvectors.

    Uses data/55dir_grad.bvec as the gradient table and 3by3by56.nii
    as the data.

    """

    # Defining Test Voxel (avoid nibabel dependency) ###

    # Recall: D = [Dxx,Dyy,Dzz,Dxy,Dxz,Dyz,log(S_0)] and D ~ 10^-4 mm^2 /s
    b0 = 1000.
    bvec, bval = read_bvec_file(get_data('55dir_grad.bvec'))
    B = bval[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)
    # Design Matrix
    gtab = grad.gradient_table(bval, bvec)
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1,) + Y.shape

    # Testing WLS Fit on Single Voxel
    # If you do something wonky (passing min_signal<0), you should get an
    # error:
    npt.assert_raises(ValueError, TensorModel, gtab, fit_method='WLS',
                      min_signal=-1)

    # Estimate tensor from test signals
    model = TensorModel(gtab, fit_method='WLS', return_S0_hat=True)
    tensor_est = model.fit(Y)
    assert_equal(tensor_est.shape, Y.shape[:-1])
    assert_array_almost_equal(tensor_est.evals[0], evals)
    assert_array_almost_equal(tensor_est.quadratic_form[0], tensor,
                              err_msg="Calculation of tensor from Y does not "
                                      "compare to analytical solution")
    assert_almost_equal(tensor_est.md[0], md)
    assert_array_almost_equal(tensor_est.S0_hat[0], b0, decimal=3)

    # Test that we can fit a single voxel's worth of data (a 1d array)
    y = Y[0]
    tensor_est = model.fit(y)
    assert_equal(tensor_est.shape, tuple())
    assert_array_almost_equal(tensor_est.evals, evals)
    assert_array_almost_equal(tensor_est.quadratic_form, tensor)
    assert_almost_equal(tensor_est.md, md)
    assert_array_almost_equal(tensor_est.lower_triangular(b0), D)

    # Test using fit_method='LS'
    model = TensorModel(gtab, fit_method='LS')
    tensor_est = model.fit(y)
    assert_equal(tensor_est.shape, tuple())
    assert_array_almost_equal(tensor_est.evals, evals)
    assert_array_almost_equal(tensor_est.quadratic_form, tensor)
    assert_almost_equal(tensor_est.md, md)
    assert_array_almost_equal(tensor_est.lower_triangular(b0), D)
    assert_array_almost_equal(tensor_est.linearity, linearity(evals))
    assert_array_almost_equal(tensor_est.planarity, planarity(evals))
    assert_array_almost_equal(tensor_est.sphericity, sphericity(evals))
Ejemplo n.º 4
0
def test_wls_and_ls_fit():
    """
    Tests the WLS and LS fitting functions to see if they returns the correct
    eigenvalues and eigenvectors.

    Uses data/55dir_grad.bvec as the gradient table and 3by3by56.nii
    as the data.

    """

    # Defining Test Voxel (avoid nibabel dependency) ###

    # Recall: D = [Dxx,Dyy,Dzz,Dxy,Dxz,Dyz,log(S_0)] and D ~ 10^-4 mm^2 /s
    b0 = 1000.
    bvec, bval = read_bvec_file(get_data('55dir_grad.bvec'))
    B = bval[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)
    # Design Matrix
    gtab = grad.gradient_table(bval, bvec)
    X = dti.design_matrix(gtab)
    # Signals
    Y = np.exp(np.dot(X, D))
    assert_almost_equal(Y[0], b0)
    Y.shape = (-1,) + Y.shape

    # Testing WLS Fit on Single Voxel
    # If you do something wonky (passing min_signal<0), you should get an
    # error:
    npt.assert_raises(ValueError, TensorModel, gtab, fit_method='WLS',
                      min_signal=-1)

    # Estimate tensor from test signals
    model = TensorModel(gtab, fit_method='WLS', return_S0_hat=True)
    tensor_est = model.fit(Y)
    assert_equal(tensor_est.shape, Y.shape[:-1])
    assert_array_almost_equal(tensor_est.evals[0], evals)
    assert_array_almost_equal(tensor_est.quadratic_form[0], tensor,
                              err_msg="Calculation of tensor from Y does not "
                                      "compare to analytical solution")
    assert_almost_equal(tensor_est.md[0], md)
    assert_array_almost_equal(tensor_est.S0_hat[0], b0, decimal=3)

    # Test that we can fit a single voxel's worth of data (a 1d array)
    y = Y[0]
    tensor_est = model.fit(y)
    assert_equal(tensor_est.shape, tuple())
    assert_array_almost_equal(tensor_est.evals, evals)
    assert_array_almost_equal(tensor_est.quadratic_form, tensor)
    assert_almost_equal(tensor_est.md, md)
    assert_array_almost_equal(tensor_est.lower_triangular(b0), D)

    # Test using fit_method='LS'
    model = TensorModel(gtab, fit_method='LS')
    tensor_est = model.fit(y)
    assert_equal(tensor_est.shape, tuple())
    assert_array_almost_equal(tensor_est.evals, evals)
    assert_array_almost_equal(tensor_est.quadratic_form, tensor)
    assert_almost_equal(tensor_est.md, md)
    assert_array_almost_equal(tensor_est.lower_triangular(b0), D)
    assert_array_almost_equal(tensor_est.linearity, linearity(evals))
    assert_array_almost_equal(tensor_est.planarity, planarity(evals))
    assert_array_almost_equal(tensor_est.sphericity, sphericity(evals))
Ejemplo n.º 5
0
    def fit(self, data, mask=None):

        tenfit = self.tenmodel.fit(data, mask)
        evals = tenfit.evals
        tensor_linearity = dti.linearity(evals)
        if tensor_linearity > self.tensor_linearity_threshold:
            R = tenfit.evecs
        else:
            R = None

        # improves robustness of the fitting to include a
        # lower bound on eigenvalues.
        evals = np.clip(evals, self.tensor_scale_lower_bound, evals.max())
        mu = np.sqrt(evals.mean() * 2 * self.tau)
        qvals = np.sqrt(self.gtab.bvals / self.tau) / (2 * np.pi)

        Q_mu_dependent = shore_Q_mu_dependent(self.radial_order, mu, qvals)

        M = Q_mu_dependent * self.Q_mu_independent

        if not self.positive_constraint and not self.constraint_e0 and not\
            self.laplacian_regularization and not\
                self.separated_regularization:
            coef = np.dot(np.dot(np.linalg.pinv((np.dot(M.T, M))), M.T), data)

        if self.laplacian_regularization:
            laplacian_matrix = self.laplacian_matrix * mu

            if self.laplacian_weighting == 'GCV':
                lopt = generalized_crossvalidation(data, M, laplacian_matrix)
            else:
                lopt = self.laplacian_weighting

            if self.constraint_e0 or self.positive_constraint:
                Q = matrix(np.dot(M.T, M) + lopt * laplacian_matrix)
            else:
                Mreg = np.dot(M.T, M) + lopt * laplacian_matrix
                zeros = np.zeros(Mreg.shape[0])
                coef = zeros

                if (data == 0).all():
                    coef = zeros
                else:
                    try:
                        MregInv = np.linalg.pinv(Mreg)
                        coef = np.dot(np.dot(MregInv, M.T), data)
                    except np.linalg.linalg.LinAlgError as err:
                        if 'SVD did not converge' in err.message:
                            warnings.warn('SVD did not converge')
                            coef = zeros
                        else:
                            raise

        else:
            lopt = 0

        if self.separated_regularization:
            N_mat = self.N_mat
            L_mat = self.L_mat
            if self.separated_weighting == 'GCV':
                loptN, loptL = generalized_crossvalidation2D(
                    data, M, N_mat, L_mat)
            else:
                loptN = loptL = self.separated_weighting

            if self.constraint_e0 or self.positive_constraint:
                Q = matrix(np.dot(M.T, M) + loptN * N_mat + loptL * L_mat)
            else:
                Mreg = np.dot(M.T, M) + loptN * N_mat + loptL * L_mat
                zeros = np.zeros(Mreg.shape[0])
                coef = zeros

                if (data == 0).all():
                    coef = zeros
                else:
                    try:
                        MregInv = np.linalg.pinv(Mreg)
                        coef = np.dot(np.dot(MregInv, M.T), data)
                    except np.linalg.linalg.LinAlgError as err:
                        if 'SVD did not converge' in err.message:
                            warnings.warn('SVD did not converge')
                            coef = zeros
                        else:
                            raise

        else:
            loptN = loptL = 0

        if self.constraint_e0 or self.positive_constraint:
            Q = matrix(np.dot(M.T, M))

            if self.positive_constraint:
                constraint_grid = self.constraint_grid
                K_independent = self.pos_K_independent
                K_dependent = shore_K_mu_dependent(self.radial_order, mu,
                                                   constraint_grid)
                K = K_independent * K_dependent
                G = matrix(-1 * K)
                h = matrix(np.zeros((K.shape[0])), (K.shape[0], 1))
            else:
                G = None
                h = None
            if self.constraint_e0:
                data = data / data[self.gtab.b0s_mask].mean()
                p = matrix(-1 * np.dot(M.T, data))
                A = matrix(M[0], (1, M.shape[1]))
                b = matrix(1.0)
            else:
                p = matrix(-1 * np.dot(M.T, data))
                A = None
                b = None
            solvers.options['show_progress'] = False

            try:
                sol = solvers.qp(Q, p, G, h, A, b)
                coef = np.array(sol['x'])[:, 0]
            except ValueError:
                coef = np.zeros(self.ind_mat.shape[0])

        if not (self.constraint_e0):
            coef = coef / sum(coef * self.B_mat)

        # Apply the mask to the coefficients
        if mask is not None:
            mask = np.asarray(mask, dtype=bool)
            coef *= mask[..., None]

        return ShoreOzarslanFit(self, coef, mu, R, lopt, loptN, loptL)