Esempio n. 1
0
def test_real_sym_sh_basis():
    # This test should do for now
    # The tournier07 basis should be the same as re-ordering and re-scaling the
    # descoteaux07 basis
    new_order = [0, 5, 4, 3, 2, 1, 14, 13, 12, 11, 10, 9, 8, 7, 6]
    sphere = hemi_icosahedron.subdivide(2)
    basis, m, n = real_sym_sh_mrtrix(4, sphere.theta, sphere.phi)
    expected = basis[:, new_order]
    expected *= np.where(m == 0, 1., np.sqrt(2))

    descoteaux07_basis, m, n = real_sym_sh_basis(4, sphere.theta, sphere.phi)
    assert_array_almost_equal(descoteaux07_basis, expected)
Esempio n. 2
0
def test_real_sym_sh_mrtrix():
    coef, expected, sphere = mrtrix_spherical_functions()
    basis, m, n = real_sym_sh_mrtrix(8, sphere.theta, sphere.phi)
    func = np.dot(coef, basis.T)
    assert_array_almost_equal(func, expected, 4)
Esempio n. 3
0
def test_real_sym_sh_mrtrix():
    coef, expected, sphere = mrtrix_spherical_functions()
    basis, m, n = real_sym_sh_mrtrix(8, sphere.theta, sphere.phi)
    func = np.dot(coef, basis.T)
    assert_array_almost_equal(func, expected, 4)
Esempio n. 4
0
    def __init__(self, dmipy_acquisition_scheme, N_angular_samples=10):
        self.Nsamples = N_angular_samples
        scheme = dmipy_acquisition_scheme

        thetas = np.linspace(0, np.pi / 2, N_angular_samples)
        r = np.ones(N_angular_samples)
        phis = np.zeros(N_angular_samples)
        angles = np.c_[r, thetas, phis]
        angles_cart = utils.sphere2cart(angles)

        b_all_shells = []
        Gdirs_all_shells = []
        delta_all_shells = []
        Delta_all_shells = []
        shell_indices = []
        for shell_index in scheme.unique_dwi_indices:
            b = scheme.shell_bvalues[shell_index]
            b_all_shells.append(np.tile(b, N_angular_samples))
            if scheme.shell_delta is not None:
                delta = scheme.shell_delta[shell_index]
                delta_all_shells.append(np.tile(delta, N_angular_samples))
            if scheme.shell_Delta is not None:
                Delta = scheme.shell_Delta[shell_index]
                Delta_all_shells.append(np.tile(Delta, N_angular_samples))
            Gdirs_all_shells.append(angles_cart)
            shell_indices.append(np.tile(shell_index, N_angular_samples))

        self.shell_indices = np.hstack(shell_indices)
        self.bvalues = np.hstack(b_all_shells)
        self.gradient_directions = np.vstack(Gdirs_all_shells)
        self.delta = None
        if scheme.shell_delta is not None:
            self.delta = np.hstack(delta_all_shells)
        self.Delta = None
        if scheme.shell_Delta is not None:
            self.Delta = np.hstack(Delta_all_shells)
        if self.delta is not None and self.Delta is not None:
            self.gradient_strengths = g_from_b(self.bvalues, self.delta,
                                               self.Delta)
            self.qvalues = q_from_g(self.gradient_strengths, self.delta)
            self.tau = self.Delta - self.delta / 3.0
        else:
            self.gradient_strengths = self.qvalues = self.tau = None
        self.b0_mask = np.tile(False, len(self.bvalues))
        self.shell_delta = scheme.shell_delta
        self.shell_Delta = scheme.shell_Delta
        self.unique_b0_indices = scheme.unique_b0_indices
        self.unique_shell_indices = scheme.unique_shell_indices
        self.unique_dwi_indices = scheme.unique_dwi_indices
        self.N_b0_shells = len(self.unique_b0_indices)
        self.N_dwi_shells = len(self.unique_dwi_indices)
        self.N_shells = len(self.unique_shell_indices)
        self.number_of_measurements = len(self.bvalues)

        self.shell_sh_matrices = {}
        self.shell_sh_orders = {}
        for shell_index in scheme.unique_dwi_indices:
            self.shell_sh_orders[shell_index] = int(
                scheme.shell_sh_orders[shell_index])
            self.shell_sh_matrices[shell_index] = real_sym_sh_mrtrix(
                self.shell_sh_orders[shell_index], thetas, phis)[0]

        self.inverse_rh_matrix = {
            rh_order: np.linalg.pinv(real_sym_rh_basis(rh_order, thetas, phis))
            for rh_order in np.arange(0, 15, 2)
        }
Esempio n. 5
0
    def __init__(self, bvalues, gradient_directions, qvalues,
                 gradient_strengths, delta, Delta, TE, min_b_shell_distance,
                 b0_threshold):
        self.min_b_shell_distance = float(min_b_shell_distance)
        self.b0_threshold = float(b0_threshold)
        self.bvalues = bvalues.astype(float)
        self.b0_mask = self.bvalues <= b0_threshold
        self.number_of_b0s = np.sum(self.b0_mask)
        self.number_of_measurements = len(self.bvalues)
        self.gradient_directions = gradient_directions.astype(float)
        self.qvalues = None
        if qvalues is not None:
            self.qvalues = qvalues.astype(float)
        self.gradient_strengths = None
        if gradient_strengths is not None:
            self.gradient_strengths = gradient_strengths.astype(float)
        self.delta = None
        if delta is not None:
            self.delta = delta.astype(float)
        self.Delta = None
        if Delta is not None:
            self.Delta = Delta.astype(float)
        self.TE = None
        self.N_TE = 1  # default if not given
        if TE is not None:
            self.TE = TE.astype(float)
        self.tau = None
        if self.delta is not None and self.Delta is not None:
            self.tau = Delta - delta / 3.
        # if there are more then 1 measurement
        if self.number_of_measurements > 1:
            # we check if there are multiple unique delta-Delta combinations
            if self.TE is not None:
                deltas = np.c_[self.delta, self.Delta, self.TE]
            elif self.delta is not None and self.Delta is not None:
                deltas = np.c_[self.delta, self.Delta]
            elif self.delta is None and self.Delta is not None:
                deltas = np.c_[self.Delta]
            elif self.delta is not None and self.Delta is None:
                deltas = np.c_[self.delta]
            else:
                deltas = []

            if deltas == []:
                deltas = np.c_[np.zeros(len(self.bvalues))]
            unique_deltas = np.unique(deltas, axis=0)
            self.shell_indices = np.zeros(len(bvalues), dtype=int)
            self.shell_bvalues = []
            max_index = 0
            # for every unique combination we separate shells based on bvalue
            # reason for separation is that different combinations of
            # delta and Delta can result in the same b-value, which could
            # result in wrong classification of DWIs to unique shells.
            for unique_deltas_ in unique_deltas:
                delta_mask = np.all(deltas == unique_deltas_, axis=1)
                masked_bvals = bvalues[delta_mask]
                if len(masked_bvals) > 1:
                    shell_indices_, shell_bvalues_ = (
                        calculate_shell_bvalues_and_indices(
                            masked_bvals, min_b_shell_distance))
                else:
                    shell_indices_, shell_bvalues_ = np.array(0), masked_bvals
                self.shell_indices[delta_mask] = shell_indices_ + max_index
                self.shell_bvalues.append(shell_bvalues_)
                max_index = max(self.shell_indices + 1)
            self.shell_bvalues = np.hstack(self.shell_bvalues)
            self.shell_b0_mask = self.shell_bvalues <= b0_threshold

            first_indices = [
                np.argmax(self.shell_indices == ind)
                for ind in np.arange(self.shell_indices.max() + 1)
            ]
            self.shell_qvalues = None
            if self.qvalues is not None:
                self.shell_qvalues = self.qvalues[first_indices]
            self.shell_gradient_strengths = None
            if self.gradient_strengths is not None:
                self.shell_gradient_strengths = (
                    self.gradient_strengths[first_indices])
            self.shell_delta = None
            if self.delta is not None:
                self.shell_delta = self.delta[first_indices]
            self.shell_Delta = None
            if self.Delta is not None:
                self.shell_Delta = self.Delta[first_indices]
            self.shell_TE = None
            if self.TE is not None:
                self.shell_TE = self.TE[first_indices]
                if (len(np.unique(self.TE)) != len(
                        np.unique(self.TE[self.b0_mask]))):
                    msg = "Not every TE shell has b0 measurements.\n"
                    msg += "This is required to properly normalize the signal."
                    msg += " Make sure the TE values for b0-measurements have "
                    msg += "not defaulted to 0 for example."
                    raise ValueError(msg)
                self.N_TE = len(self.shell_TE)
        # if for some reason only one measurement is given (for testing)
        else:
            self.shell_bvalues = self.bvalues
            self.shell_indices = np.r_[int(0)]
            if self.shell_bvalues > b0_threshold:
                self.shell_b0_mask = np.r_[False]
            else:
                self.shell_b0_mask = np.r_[True]
            self.shell_qvalues = self.qvalues
            self.shell_gradient_strengths = self.gradient_strengths
            self.shell_delta = self.delta
            self.shell_Delta = self.Delta
            self.shell_TE = TE

        # calculates observation matrices to convert spherical harmonic
        # coefficients to the positions on the sphere for every shell
        self.unique_b0_indices = np.unique(self.shell_indices[self.b0_mask])
        self.unique_dwi_indices = np.unique(self.shell_indices[~self.b0_mask])
        self.unique_shell_indices = np.unique(self.shell_indices)
        self.N_b0_shells = len(self.unique_b0_indices)
        self.N_dwi_shells = len(self.unique_dwi_indices)
        self.N_shells = len(self.unique_shell_indices)
        self.shell_sh_matrices = {}
        self.shell_sh_orders = {}
        for shell_index in self.unique_b0_indices:
            self.shell_sh_orders[shell_index] = 0
        for shell_index in self.unique_dwi_indices:
            shell_mask = self.shell_indices == shell_index
            bvecs_shell = self.gradient_directions[shell_mask]
            _, theta_, phi_ = utils.cart2sphere(bvecs_shell).T
            self.shell_sh_orders[shell_index] = get_sh_order_from_bval(
                self.shell_bvalues[shell_index])
            self.shell_sh_matrices[shell_index] = real_sym_sh_mrtrix(
                self.shell_sh_orders[shell_index], theta_, phi_)[0]
        # warning in case there are no b0 measurements
        if sum(self.b0_mask) == 0:
            msg = "No b0 measurements were detected. Check if the b0_threshold"
            msg += " option is high enough, or if there is a mistake in the "
            msg += "acquisition design."
            warn(msg)

        self.spherical_mean_scheme = SphericalMeanAcquisitionScheme(
            self.shell_bvalues, self.shell_qvalues,
            self.shell_gradient_strengths, self.shell_Delta, self.shell_delta)
        if len(self.unique_dwi_indices) > 0:
            self.rotational_harmonics_scheme = (
                RotationalHarmonicsAcquisitionScheme(self))
Esempio n. 6
0
numba, have_numba, _ = optional_package("numba")

GRADIENT_TABLES_PATH = pkg_resources.resource_filename('dmipy',
                                                       'data/gradient_tables')
SIGNAL_MODELS_PATH = pkg_resources.resource_filename('dmipy', 'signal_models')
DATA_PATH = pkg_resources.resource_filename('dmipy', 'data')
SPHERE_CARTESIAN = np.loadtxt(join(GRADIENT_TABLES_PATH,
                                   'sphere_with_cap.txt'))
SPHERE_SPHERICAL = utils.cart2sphere(SPHERE_CARTESIAN)
log_bingham_normalization_splinefit = np.load(join(
    DATA_PATH, "bingham_normalization_splinefit.npz"),
                                              encoding='bytes')['arr_0']

inverse_sh_matrix_kernel = {
    sh_order: np.linalg.pinv(
        real_sym_sh_mrtrix(sh_order, hemisphere.theta, hemisphere.phi)[0])
    for sh_order in np.arange(0, 15, 2)
}
BETA_SCALING = 1e-6

__all__ = [
    'get_sh_order_from_odi', 'SD1Watson', 'SD2Bingham', 'DD1Gamma',
    'odi2kappa', 'kappa2odi'
]


def get_sh_order_from_odi(odi):
    "Returns minimum sh_order to estimate spherical harmonics for given odi."
    odis = np.array([
        0.80606061, 0.46666667, 0.25333333, 0.15636364, 0.09818182, 0.06909091,
        0.