Beispiel #1
0
def normalize_gradients(bvecs,
                        bvals,
                        b0_threshold,
                        bvec_norm_epsilon=0.1,
                        b_scale=True):
    """
    Normalize b-vectors and b-values.

    The resulting b-vectors will be of unit length for the non-zero b-values.
    The resultinb b-values will be normalized by the square of the
    corresponding vector amplitude.

    Parameters
    ----------
    bvecs : m x n 2d array
        Raw b-vectors array.
    bvals : 1d array
        Raw b-values float array.
    b0_threshold : float
        Gradient threshold below which volumes and vectors are considered B0's.

    Returns
    -------
    bvecs : m x n 2d array
        Unit-normed b-vectors array.
    bvals : 1d int array
        Vector amplitude square normed b-values array.

    """
    from dipy.core.gradients import round_bvals

    bvals = np.array(bvals, dtype="float32")
    bvecs = np.array(bvecs, dtype="float32")

    b0s = bvals < b0_threshold
    b0_vecs = np.linalg.norm(bvecs, axis=1) < bvec_norm_epsilon

    # Check for bval-bvec discrepancy.
    if not np.all(b0s == b0_vecs):
        raise ValueError(
            "Inconsistent bvals and bvecs (%d, %d low-b, respectively)." %
            (b0s.sum(), b0_vecs.sum()))

    # Rescale b-vals if requested
    if b_scale:
        bvals[~b0s] *= np.linalg.norm(bvecs[~b0s], axis=1)**2

    # Ensure b0s have (0, 0, 0) vectors
    bvecs[b0s, :3] = np.zeros(3)

    # Round bvals
    bvals = round_bvals(bvals)

    # Rescale b-vecs, skipping b0's, on the appropriate axis to unit-norm
    # length.
    bvecs[~b0s] /= np.linalg.norm(bvecs[~b0s], axis=1)[..., np.newaxis]
    return bvecs, bvals.astype("uint16")
Beispiel #2
0
def test_round_bvals():
    bvals_gt = np.array([1000, 1000, 1000, 1000, 2000, 2000, 2000, 2000, 0])
    b = round_bvals(bvals_gt)
    npt.assert_array_almost_equal(bvals_gt, b)

    bvals = np.array([995, 995, 995, 995, 2005, 2005, 2005, 2005, 0])
    # We don't consider differences this small to be sufficient:
    b = round_bvals(bvals)
    npt.assert_array_almost_equal(bvals_gt, b)

    # Unless you specify that you are interested in this magnitude of changes:
    b = round_bvals(bvals, bmag=0)
    npt.assert_array_almost_equal(bvals, b)

    # Case that b-values are in ms/um2
    bvals = np.array(
        [0.995, 0.995, 0.995, 0.995, 2.005, 2.005, 2.005, 2.005, 0])
    b = round_bvals(bvals)
    bvals_gt = np.array([1, 1, 1, 1, 2, 2, 2, 2, 0])
    npt.assert_array_almost_equal(bvals_gt, b)
Beispiel #3
0
def test_round_bvals():
    bvals_gt = np.array([1000, 1000, 1000, 1000, 2000, 2000, 2000, 2000, 0])
    b = round_bvals(bvals_gt)
    npt.assert_array_almost_equal(bvals_gt, b)

    bvals = np.array([995, 995, 995, 995, 2005, 2005, 2005, 2005, 0])
    # We don't consider differences this small to be sufficient:
    b = round_bvals(bvals)
    npt.assert_array_almost_equal(bvals_gt, b)

    # Unless you specify that you are interested in this magnitude of changes:
    b = round_bvals(bvals, bmag=0)
    npt.assert_array_almost_equal(bvals, b)

    # Case that b-valuea are in ms/um2
    bvals = np.array([0.995, 0.995, 0.995, 0.995, 2.005, 2.005, 2.005, 2.005,
                      0])
    b = round_bvals(bvals)
    bvals_gt = np.array([1, 1, 1, 1, 2, 2, 2, 2, 0])
    npt.assert_array_almost_equal(bvals_gt, b)
Beispiel #4
0
def msdki_prediction(msdki_params, gtab, S0=1.0):
    """
    Predict the mean signal given the parameters of the mean signal DKI, an
    GradientTable object and S0 signal.

    Parameters
    ----------
    params : ndarray ([X, Y, Z, ...], 2)
        Array containing the mean signal diffusivity and mean signal kurtosis
        in its last axis
    gtab : a GradientTable class instance
        The gradient table for this prediction
    S0 : float or ndarray (optional)
        The non diffusion-weighted signal in every voxel, or across all
        voxels. Default: 1

    Notes
    -----
    The predicted signal is given by:
        $MS(b) = S_0 * exp(-bD + 1/6 b^{2} D^{2} K)$, where $D$ and $K$ are the
        mean signal diffusivity and mean signal kurtosis.

    References
    ----------
    .. [1] Henriques, R.N., 2018. Advanced Methods for Diffusion MRI Data
           Analysis and their Application to the Healthy Ageing Brain (Doctoral
           thesis). Downing College, University of Cambridge.
           https://doi.org/10.17863/CAM.29356
    """
    A = design_matrix(round_bvals(gtab.bvals))

    params = msdki_params.copy()
    params[..., 1] = params[..., 1] * params[..., 0] ** 2

    if isinstance(S0, float) or isinstance(S0, int):
        pred_sig = S0 * np.exp(np.dot(params, A[:, :2].T))
    elif S0.size == 1:
        pred_sig = S0 * np.exp(np.dot(params, A[:, :2].T))
    else:
        nv = gtab.bvals.size
        S0r = np.zeros(S0.shape + gtab.bvals.shape)
        for vi in range(nv):
            S0r[..., vi] = S0
        pred_sig = S0r * np.exp(np.dot(params, A[:, :2].T))

    return pred_sig
Beispiel #5
0
def msdki_prediction(msdki_params, gtab, S0=1.0):
    """
    Predict the mean signal given the parameters of the mean signal DKI, an
    GradientTable object and S0 signal.

    Parameters
    ----------
    params : ndarray ([X, Y, Z, ...], 2)
        Array containing the mean signal diffusivity and mean signal kurtosis
        in its last axis
    gtab : a GradientTable class instance
        The gradient table for this prediction
    S0 : float or ndarray (optional)
        The non diffusion-weighted signal in every voxel, or across all
        voxels. Default: 1

    Notes
    -----
    The predicted signal is given by:
        $MS(b) = S_0 * exp(-bD + 1/6 b^{2} D^{2} K)$, where $D$ and $K$ are the
        mean signal diffusivity and mean signal kurtosis.

    References
    ----------
    .. [1] Henriques, R.N., 2018. Advanced Methods for Diffusion MRI Data
           Analysis and their Application to the Healthy Ageing Brain (Doctoral
           thesis). Downing College, University of Cambridge.
           https://doi.org/10.17863/CAM.29356
    """
    A = design_matrix(round_bvals(gtab.bvals))

    params = msdki_params.copy()
    params[..., 1] = params[..., 1] * params[..., 0] ** 2

    if isinstance(S0, float) or isinstance(S0, int):
        pred_sig = S0 * np.exp(np.dot(params, A[:, :2].T))
    elif S0.size == 1:
        pred_sig = S0 * np.exp(np.dot(params, A[:, :2].T))
    else:
        nv = gtab.bvals.size
        S0r = np.zeros(S0.shape + gtab.bvals.shape)
        for vi in range(nv):
            S0r[..., vi] = S0
        pred_sig = S0r * np.exp(np.dot(params, A[:, :2].T))

    return pred_sig
Beispiel #6
0
def normalize_gradients(bvecs,
                        bvals,
                        b0_threshold=B0_THRESHOLD,
                        bvec_norm_epsilon=BVEC_NORM_EPSILON,
                        b_scale=True,
                        raise_error=False):
    """
    Normalize b-vectors and b-values.

    The resulting b-vectors will be of unit length for the non-zero b-values.
    The resultinb b-values will be normalized by the square of the
    corresponding vector amplitude.

    Parameters
    ----------
    bvecs : m x n 2d array
        Raw b-vectors array.
    bvals : 1d array
        Raw b-values float array.
    b0_threshold : float
        Gradient threshold below which volumes and vectors are considered B0's.

    Returns
    -------
    bvecs : m x n 2d array
        Unit-normed b-vectors array.
    bvals : 1d int array
        Vector amplitude square normed b-values array.

    Examples
    --------
    >>> bvecs = np.vstack((np.zeros(3), 2.0 * np.eye(3), -0.8 * np.eye(3), np.ones(3)))
    >>> bvals = np.array([1000] * bvecs.shape[0])
    >>> normalize_gradients(bvecs, bvals, 50)  # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ValueError:

    >>> bvals[0] = 0.0
    >>> norm_vecs, norm_vals = normalize_gradients(bvecs, bvals)
    >>> np.all(norm_vecs[0] == 0)
    True

    >>> norm_vecs[1, ...].tolist()
    [1.0, 0.0, 0.0]

    >>> norm_vals[0]
    0
    >>> norm_vals[1]
    4000
    >>> norm_vals[-2]
    600
    >>> norm_vals[-1]
    3000

    >>> norm_vecs, norm_vals = normalize_gradients(bvecs, bvals, b_scale=False)
    >>> norm_vals[0]
    0
    >>> np.all(norm_vals[1:] == 1000)
    True

    """
    bvals = np.array(bvals, dtype='float32')
    bvecs = np.array(bvecs, dtype='float32')

    b0s = bvals < b0_threshold
    b0_vecs = np.linalg.norm(bvecs, axis=1) < bvec_norm_epsilon

    # Check for bval-bvec discrepancy.
    if not np.all(b0s == b0_vecs):
        msg = f"Inconsistent bvals and bvecs ({b0s.sum()}, {b0_vecs.sum()} low-b, respectively)."
        if raise_error:
            raise ValueError(msg)
        config.loggers.cli.warning(msg)

    # Rescale b-vals if requested
    if b_scale:
        bvals[~b0s] *= np.linalg.norm(bvecs[~b0s], axis=1)**2

    # Ensure b0s have (0, 0, 0) vectors
    bvecs[b0s, :3] = np.zeros(3)

    # Round bvals
    bvals = round_bvals(bvals)

    # Rescale b-vecs, skipping b0's, on the appropriate axis to unit-norm length.
    bvecs[~b0s] /= np.linalg.norm(bvecs[~b0s], axis=1)[..., np.newaxis]
    return bvecs, bvals.astype('uint16')
Beispiel #7
0
""" Testing Mean Signal DKI (MSDKI) """

from __future__ import division, print_function, absolute_import

import numpy as np
import random
from numpy.testing import assert_array_almost_equal, assert_raises
from dipy.sims.voxel import multi_tensor_dki
from dipy.io.gradients import read_bvals_bvecs
from dipy.core.gradients import (gradient_table, unique_bvals, round_bvals)
from dipy.data import get_fnames
import dipy.reconst.msdki as msdki

fimg, fbvals, fbvecs = get_fnames('small_64D')
bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)
bvals = round_bvals(bvals)
gtab = gradient_table(bvals, bvecs)

# 2 shells for techniques that requires multishell data
bvals_3s = np.concatenate((bvals, bvals * 1.5, bvals * 2), axis=0)
bvecs_3s = np.concatenate((bvecs, bvecs, bvecs), axis=0)
gtab_3s = gradient_table(bvals_3s, bvecs_3s)

# Simulation 1. Spherical kurtosis tensor - MSK and MSD from the MSDKI model
# should be equal to the MK and MD of the DKI tensor for cases of
# spherical kurtosis tensors
Di = 0.00099
De = 0.00226
mevals_sph = np.array([[Di, Di, Di], [De, De, De]])
f = 0.5
frac_sph = [f * 100, (1.0 - f) * 100]
Beispiel #8
0
from __future__ import division, print_function, absolute_import

import numpy as np
import random
from numpy.testing import assert_array_almost_equal
from nose.tools import assert_raises
from dipy.sims.voxel import multi_tensor_dki
from dipy.io.gradients import read_bvals_bvecs
from dipy.core.gradients import (gradient_table, unique_bvals, round_bvals)
from dipy.data import get_fnames
import dipy.reconst.msdki as msdki

fimg, fbvals, fbvecs = get_fnames('small_64D')
bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)
bvals = round_bvals(bvals)
gtab = gradient_table(bvals, bvecs)

# 2 shells for techniques that requires multishell data
bvals_3s = np.concatenate((bvals, bvals*1.5, bvals * 2), axis=0)
bvecs_3s = np.concatenate((bvecs, bvecs, bvecs), axis=0)
gtab_3s = gradient_table(bvals_3s, bvecs_3s)

# Simulation 1. Spherical kurtosis tensor - MSK and MSD from the MSDKI model
# should be equa to the MK and MD of the DKI tensor for cases of
# spherical kurtosis tensors
Di = 0.00099
De = 0.00226
mevals_sph = np.array([[Di, Di, Di], [De, De, De]])
f = 0.5
frac_sph = [f * 100, (1.0 - f) * 100]