예제 #1
0
def test_vector_norm():
    A = np.array([[1, 0, 0], [3, 4, 0], [0, 5, 12], [1, 2, 3]])
    expected = np.array([1, 5, 13, np.sqrt(14)])
    assert_array_almost_equal(vector_norm(A), expected)
    expected.shape = (4, 1)
    assert_array_almost_equal(vector_norm(A, keepdims=True), expected)
    assert_array_almost_equal(vector_norm(A.T, axis=0, keepdims=True),
                              expected.T)
예제 #2
0
def test_vector_norm():
    A = np.array([[1, 0, 0],
                  [3, 4, 0],
                  [0, 5, 12],
                  [1, 2, 3]])
    expected = np.array([1, 5, 13, np.sqrt(14)])
    assert_array_almost_equal(vector_norm(A), expected)
    expected.shape = (4, 1)
    assert_array_almost_equal(vector_norm(A, keepdims=True), expected)
    assert_array_almost_equal(vector_norm(A.T, axis=0, keepdims=True),
                              expected.T)
예제 #3
0
def gradient_table_from_bvals_bvecs(bvals,
                                    bvecs,
                                    b0_threshold=0,
                                    atol=1e-2,
                                    **kwargs):
    """Creates a GradientTable from a bvals array and a bvecs array

    Parameters
    ----------
    bvals : array_like (N,)
        The b-value, or magnitude, of each gradient direction.
    bvecs : array_like (N, 3)
        The direction, represented as a unit vector, of each gradient.
    b0_threshold : float
        Gradients with b-value less than or equal to `bo_threshold` are
        considered to not have diffusion weighting.
    atol : float
        Each vector in `bvecs` must be a unit vectors up to a tolerance of
        `atol`.

    Other Parameters
    ----------------
    **kwargs : dict
        Other keyword inputs are passed to GradientTable.

    Returns
    -------
    gradients : GradientTable
        A GradientTable with all the gradient information.

    See Also
    --------
    GradientTable, gradient_table

    """
    bvals = np.asarray(bvals, np.float)
    bvecs = np.asarray(bvecs, np.float)
    dwi_mask = bvals > b0_threshold

    # check that bvals is (N,) array and bvecs is (N, 3) unit vectors
    if bvals.ndim != 1 or bvecs.ndim != 2 or bvecs.shape[0] != bvals.shape[0]:
        raise ValueError("bvals and bvecs should be (N,) and (N, 3) arrays "
                         "respectively, where N is the number of diffusion "
                         "gradients")

    bvecs = np.where(np.isnan(bvecs), 0, bvecs)
    bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol
    if bvecs.shape[1] != 3 or not np.all(bvecs_close_to_1[dwi_mask]):
        raise ValueError("bvecs should be (N, 3), a set of N unit vectors")

    bvecs = np.where(bvecs_close_to_1[:, None], bvecs, 0)
    bvals = bvals * bvecs_close_to_1
    gradients = bvals[:, None] * bvecs

    grad_table = GradientTable(gradients, b0_threshold=b0_threshold, **kwargs)
    grad_table.bvals = bvals
    grad_table.bvecs = bvecs
    grad_table.b0s_mask = ~dwi_mask

    return grad_table
예제 #4
0
파일: gradients.py 프로젝트: MPDean/dipy
def gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=0, atol=1e-2,
                                    **kwargs):
    """Creates a GradientTable from a bvals array and a bvecs array

    Parameters
    ----------
    bvals : array_like (N,)
        The b-value, or magnitude, of each gradient direction.
    bvecs : array_like (N, 3)
        The direction, represented as a unit vector, of each gradient.
    b0_threshold : float
        Gradients with b-value less than or equal to `bo_threshold` are
        considered to not have diffusion weighting.
    atol : float
        Each vector in `bvecs` must be a unit vectors up to a tolerance of
        `atol`.

    Other Parameters
    ----------------
    **kwargs : dict
        Other keyword inputs are passed to GradientTable.

    Returns
    -------
    gradients : GradientTable
        A GradientTable with all the gradient information.

    See Also
    --------
    GradientTable, gradient_table

    """
    bvals = np.asarray(bvals, np.float)
    bvecs = np.asarray(bvecs, np.float)
    dwi_mask = bvals > b0_threshold

    # check that bvals is (N,) array and bvecs is (N, 3) unit vectors
    if bvals.ndim != 1 or bvecs.ndim != 2 or bvecs.shape[0] != bvals.shape[0]:
        raise ValueError("bvals and bvecs should be (N,) and (N, 3) arrays "
                         "respectively, where N is the number of diffusion "
                         "gradients")

    bvecs = np.where(np.isnan(bvecs), 0, bvecs)
    bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol
    if bvecs.shape[1] != 3 or not np.all(bvecs_close_to_1[dwi_mask]):
        raise ValueError("bvecs should be (N, 3), a set of N unit vectors")

    bvecs = np.where(bvecs_close_to_1[:, None], bvecs, 0)
    bvals = bvals * bvecs_close_to_1
    gradients = bvals[:, None] * bvecs

    grad_table = GradientTable(gradients, b0_threshold=b0_threshold, **kwargs)
    grad_table.bvals = bvals
    grad_table.bvecs = bvecs
    grad_table.b0s_mask = ~dwi_mask

    return grad_table
예제 #5
0
def test_inplace_norm():
    vec = [[8, 15, 0], [0, 36, 77]]
    norm1 = vector_norm(vec)
    norm2 = in_place_norm(vec)
    npt.assert_equal(norm1, norm2)

    vec = [[8.0, 15.0, 0.0], [0.0, 36.0, 77.0]]
    norm1 = vector_norm(vec)
    norm2 = in_place_norm(vec)
    npt.assert_equal(norm1, norm2)

    vec = [[8, 15, 0], [0, 36, 77]]
    norm1 = vector_norm(vec, keepdims=True)
    norm2 = in_place_norm(vec, keepdims=True)
    npt.assert_equal(norm1, norm2)

    vec = [[8, 15, 0], [0, 36, 77]]
    norm1 = vector_norm(vec, axis=0)
    norm2 = in_place_norm(vec, axis=0)
    npt.assert_equal(norm1, norm2)
예제 #6
0
    def subdivide(self, n=1):
        """Subdivides each face of the sphere into four new faces.

        New vertices are created at a, b, and c. Then each face [x, y, z] is
        divided into faces [x, a, c], [y, a, b], [z, b, c], and [a, b, c].

        ::

                y
                /\
               /  \
             a/____\b
             /\    /\
            /  \  /  \
           /____\/____\
          x      c     z

        Parameters
        ----------
        n : int, optional
            The number of subdivisions to preform.

        Returns
        -------
        new_sphere : Sphere
            The subdivided sphere.

        """
        vertices = self.vertices
        faces = self.faces
        for _ in xrange(n):
            edges, mapping = unique_edges(faces, return_mapping=True)
            new_vertices = vertices[edges].sum(1)
            new_vertices /= vector_norm(new_vertices, keepdims=True)
            mapping += len(vertices)
            vertices = np.vstack([vertices, new_vertices])

            x, y, z = faces.T
            a, b, c = mapping.T
            face1 = np.column_stack([x, a, c])
            face2 = np.column_stack([y, b, a])
            face3 = np.column_stack([z, c, b])
            face4 = mapping
            faces = np.concatenate([face1, face2, face3, face4])

        if len(vertices) < 2**16:
            faces = np.asarray(faces, dtype='uint16')
        return Sphere(xyz=vertices, faces=faces)
예제 #7
0
파일: sphere.py 프로젝트: DALILA2015/dipy
    def subdivide(self, n=1):
        """Subdivides each face of the sphere into four new faces.

        New vertices are created at a, b, and c. Then each face [x, y, z] is
        divided into faces [x, a, c], [y, a, b], [z, b, c], and [a, b, c].

        ::

                y
                /\
               /  \
             a/____\b
             /\    /\
            /  \  /  \
           /____\/____\
          x      c     z

        Parameters
        ----------
        n : int, optional
            The number of subdivisions to preform.

        Returns
        -------
        new_sphere : Sphere
            The subdivided sphere.

        """
        vertices = self.vertices
        faces = self.faces
        for i in xrange(n):
            edges, mapping = unique_edges(faces, return_mapping=True)
            new_vertices = vertices[edges].sum(1)
            new_vertices /= vector_norm(new_vertices, keepdims=True)
            mapping += len(vertices)
            vertices = np.vstack([vertices, new_vertices])

            x, y, z = faces.T
            a, b, c = mapping.T
            face1 = np.column_stack([x, a, c])
            face2 = np.column_stack([y, b, a])
            face3 = np.column_stack([z, c, b])
            face4 = mapping
            faces = np.concatenate([face1, face2, face3, face4])

        if len(vertices) < 2**16:
            faces = np.asarray(faces, dtype='uint16')
        return Sphere(xyz=vertices, faces=faces)
예제 #8
0
def test_hemisphere_faces():

    t = (1 + np.sqrt(5)) / 2
    vertices = np.array([
        [-t, -1, 0],
        [-t, 1, 0],
        [1, 0, t],
        [-1, 0, t],
        [0, t, 1],
        [0, -t, 1],
    ])
    vertices /= vector_norm(vertices, keepdims=True)
    faces = np.array([
        [0, 1, 2],
        [0, 1, 3],
        [0, 2, 4],
        [1, 3, 4],
        [2, 3, 4],
        [1, 2, 5],
        [0, 3, 5],
        [2, 3, 5],
        [0, 4, 5],
        [1, 4, 5],
    ])
    edges = np.array([
        (0, 1),
        (0, 2),
        (0, 3),
        (0, 4),
        (0, 5),
        (1, 2),
        (1, 3),
        (1, 4),
        (1, 5),
        (2, 3),
        (2, 4),
        (2, 5),
        (3, 4),
        (3, 5),
        (4, 5),
    ])

    h = HemiSphere(xyz=vertices)
    nt.assert_equal(len(h.edges), len(edges))
    nt.assert_equal(array_to_set(h.edges), array_to_set(edges))
    nt.assert_equal(len(h.faces), len(faces))
    nt.assert_equal(array_to_set(h.faces), array_to_set(faces))
예제 #9
0
def test_hemisphere_faces():

    t = (1 + np.sqrt(5)) / 2
    vertices = np.array(
        [[ -t, -1,  0],
         [ -t,  1,  0],
         [  1,  0,  t],
         [ -1,  0,  t],
         [  0,  t,  1],
         [  0, -t,  1],
        ])
    vertices /= vector_norm(vertices, keepdims=True)
    faces = np.array(
        [[0, 1, 2],
         [0, 1, 3],
         [0, 2, 4],
         [1, 3, 4],
         [2, 3, 4],
         [1, 2, 5],
         [0, 3, 5],
         [2, 3, 5],
         [0, 4, 5],
         [1, 4, 5],
        ])
    edges = np.array(
        [(0, 1),
         (0, 2),
         (0, 3),
         (0, 4),
         (0, 5),
         (1, 2),
         (1, 3),
         (1, 4),
         (1, 5),
         (2, 3),
         (2, 4),
         (2, 5),
         (3, 4),
         (3, 5),
         (4, 5),
        ])

    h = HemiSphere(xyz=vertices)
    nt.assert_equal(len(h.edges), len(edges))
    nt.assert_equal(array_to_set(h.edges), array_to_set(edges))
    nt.assert_equal(len(h.faces), len(faces))
    nt.assert_equal(array_to_set(h.faces), array_to_set(faces))
예제 #10
0
def test_b2q():
    # conversion of b matrix to q
    q = np.array([1,2,3])
    s = vector_norm(q)
    B = np.outer(q, q)
    yield assert_array_almost_equal(q*s, B2q(B))
    q = np.array([1,2,3])
    # check that the sign of the vector as positive x convention
    B = np.outer(-q, -q)
    yield assert_array_almost_equal(q*s, B2q(B))
    q = np.array([-1, 2, 3])
    B = np.outer(q, q)
    yield assert_array_almost_equal(-q*s, B2q(B))
    B = np.eye(3) * -1
    yield assert_raises(ValueError, B2q, B)
    # no error if we up the tolerance
    q = B2q(B, tol=1)
예제 #11
0
def test_b2q():
    # conversion of b matrix to q
    q = np.array([1, 2, 3])
    s = vector_norm(q)
    B = np.outer(q, q)
    yield assert_array_almost_equal(q * s, B2q(B))
    q = np.array([1, 2, 3])
    # check that the sign of the vector as positive x convention
    B = np.outer(-q, -q)
    yield assert_array_almost_equal(q * s, B2q(B))
    q = np.array([-1, 2, 3])
    B = np.outer(q, q)
    yield assert_array_almost_equal(-q * s, B2q(B))
    B = np.eye(3) * -1
    yield assert_raises(ValueError, B2q, B)
    # no error if we up the tolerance
    q = B2q(B, tol=1)
예제 #12
0
def tensor_odf(evals, evecs, sphere):
    """
    Calculate the tensor Orientation Distribution Function

    Parameters
    ----------
    evals : array (4D)
        Eigenvalues of a tensor. Shape (x, y, z, 3).
    evecs : array (5D)
        Eigenvectors of a tensor. Shape (x, y, z, 3, 3)
    sphere : sphere object
        The ODF will be calculated in each vertex of this sphere.
    """
    odf = np.zeros((evals.shape[:3] + (sphere.vertices.shape[0], )))
    mask = np.where((evals[..., 0] > 0) & (evals[..., 1] > 0)
                    & (evals[..., 2] > 0))

    lower = 4 * np.pi * np.sqrt(np.prod(evals[mask], -1))
    projection = np.dot(sphere.vertices, evecs[mask])
    projection /= np.sqrt(evals[mask])
    odf[mask] = ((vector_norm(projection)**-3) / lower).T
    return odf
예제 #13
0
파일: dti.py 프로젝트: jyeatman/pyAFQ
def tensor_odf(evals, evecs, sphere):
    """
    Calculate the tensor Orientation Distribution Function

    Parameters
    ----------
    evals : array (4D)
        Eigenvalues of a tensor. Shape (x, y, z, 3).
    evecs : array (5D)
        Eigenvectors of a tensor. Shape (x, y, z, 3, 3)
    sphere : sphere object
        The ODF will be calculated in each vertex of this sphere.
    """
    odf = np.zeros((evals.shape[:3] + (sphere.vertices.shape[0],)))
    mask = np.where((evals[..., 0] > 0) &
                    (evals[..., 1] > 0) &
                    (evals[..., 2] > 0))

    lower = 4 * np.pi * np.sqrt(np.prod(evals[mask], -1))
    projection = np.dot(sphere.vertices, evecs[mask])
    projection /= np.sqrt(evals[mask])
    odf[mask] = ((vector_norm(projection) ** -3) / lower).T
    return odf
예제 #14
0
def gradient_table_from_bvals_bvecs(bvals,
                                    bvecs,
                                    b0_threshold=50,
                                    atol=1e-2,
                                    btens=None,
                                    **kwargs):
    """Creates a GradientTable from a bvals array and a bvecs array

    Parameters
    ----------
    bvals : array_like (N,)
        The b-value, or magnitude, of each gradient direction.
    bvecs : array_like (N, 3)
        The direction, represented as a unit vector, of each gradient.
    b0_threshold : float
        Gradients with b-value less than or equal to `bo_threshold` are
        considered to not have diffusion weighting.
    atol : float
        Each vector in `bvecs` must be a unit vectors up to a tolerance of
        `atol`.
    btens : can be any of three options
        1. a string specifying the shape of the encoding tensor for all volumes
           in data. Options: 'LTE', 'PTE', 'STE', 'CTE' corresponding to
           linear, planar, spherical, and "cigar-shaped" tensor encoding.
           Tensors are rotated so that linear and cigar tensors are aligned
           with the corresponding gradient direction and the planar tensor's
           normal is aligned with the corresponding gradient direction.
           Magnitude is scaled to match the b-value.
        2. an array of strings of shape (N,), (N, 1), or (1, N) specifying
           encoding tensor shape for each volume separately. N corresponds to
           the number volumes in data. Options for elements in array: 'LTE',
           'PTE', 'STE', 'CTE' corresponding to linear, planar, spherical, and
           "cigar-shaped" tensor encoding. Tensors are rotated so that linear
           and cigar tensors are aligned with the corresponding gradient
           direction and the planar tensor's normal is aligned with the
           corresponding gradient direction. Magnitude is scaled to match the
           b-value.
        3. an array of shape (N,3,3) specifying the b-tensor of each volume
           exactly. N corresponds to the number volumes in data. No rotation or
           scaling is performed.

    Other Parameters
    ----------------
    **kwargs : dict
        Other keyword inputs are passed to GradientTable.

    Returns
    -------
    gradients : GradientTable
        A GradientTable with all the gradient information.

    See Also
    --------
    GradientTable, gradient_table

    """
    bvals = np.asarray(bvals, float)
    bvecs = np.asarray(bvecs, float)
    dwi_mask = bvals > b0_threshold

    # check that bvals is (N,) array and bvecs is (N, 3) unit vectors
    if bvals.ndim != 1 or bvecs.ndim != 2 or bvecs.shape[0] != bvals.shape[0]:
        raise ValueError("bvals and bvecs should be (N,) and (N, 3) arrays "
                         "respectively, where N is the number of diffusion "
                         "gradients")
    # checking for negative bvals
    if b0_threshold < 0:
        raise ValueError("Negative bvals in the data are not feasible")

    # Upper bound for the b0_threshold
    if b0_threshold >= 200:
        warn("b0_threshold has a value > 199")

    # checking for the correctness of bvals
    if b0_threshold < bvals.min():
        warn("b0_threshold (value: {0}) is too low, increase your \
             b0_threshold. It should be higher than the lowest b0 value \
             ({1}).".format(b0_threshold, bvals.min()))

    bvecs = np.where(np.isnan(bvecs), 0, bvecs)
    bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol
    if bvecs.shape[1] != 3:
        raise ValueError("bvecs should be (N, 3)")
    if not np.all(bvecs_close_to_1[dwi_mask]):
        raise ValueError("The vectors in bvecs should be unit (The tolerance "
                         "can be modified as an input parameter)")

    bvecs = np.where(bvecs_close_to_1[:, None], bvecs, 0)
    bvals = bvals * bvecs_close_to_1
    gradients = bvals[:, None] * bvecs

    grad_table = GradientTable(gradients,
                               b0_threshold=b0_threshold,
                               btens=btens,
                               **kwargs)
    grad_table.bvals = bvals
    grad_table.bvecs = bvecs
    grad_table.b0s_mask = ~dwi_mask

    return grad_table
예제 #15
0
파일: gradients.py 프로젝트: arokem/dipy
def gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=50, atol=1e-2,
                                    **kwargs):
    """Creates a GradientTable from a bvals array and a bvecs array

    Parameters
    ----------
    bvals : array_like (N,)
        The b-value, or magnitude, of each gradient direction.
    bvecs : array_like (N, 3)
        The direction, represented as a unit vector, of each gradient.
    b0_threshold : float
        Gradients with b-value less than or equal to `bo_threshold` are
        considered to not have diffusion weighting.
    atol : float
        Each vector in `bvecs` must be a unit vectors up to a tolerance of
        `atol`.

    Other Parameters
    ----------------
    **kwargs : dict
        Other keyword inputs are passed to GradientTable.

    Returns
    -------
    gradients : GradientTable
        A GradientTable with all the gradient information.

    See Also
    --------
    GradientTable, gradient_table

    """
    bvals = np.asarray(bvals, np.float)
    bvecs = np.asarray(bvecs, np.float)
    dwi_mask = bvals > b0_threshold

    # check that bvals is (N,) array and bvecs is (N, 3) unit vectors
    if bvals.ndim != 1 or bvecs.ndim != 2 or bvecs.shape[0] != bvals.shape[0]:
        raise ValueError("bvals and bvecs should be (N,) and (N, 3) arrays "
                         "respectively, where N is the number of diffusion "
                         "gradients")
    # checking for negative bvals
    if b0_threshold < 0:
        raise ValueError("Negative bvals in the data are not feasible")

    # Upper bound for the b0_threshold
    if b0_threshold >= 200:
        warn("b0_threshold has a value > 199")

    # checking for the correctness of bvals
    if b0_threshold < bvals.min():
        warn("b0_threshold (value: {0}) is too low, increase your \
             b0_threshold. It should higher than the first b0 value \
             ({1}).".format(b0_threshold, bvals.min()))

    bvecs = np.where(np.isnan(bvecs), 0, bvecs)
    bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol
    if bvecs.shape[1] != 3:
        raise ValueError("bvecs should be (N, 3)")
    if not np.all(bvecs_close_to_1[dwi_mask]):
        raise ValueError("The vectors in bvecs should be unit (The tolerance "
                         "can be modified as an input parameter)")

    bvecs = np.where(bvecs_close_to_1[:, None], bvecs, 0)
    bvals = bvals * bvecs_close_to_1
    gradients = bvals[:, None] * bvecs

    grad_table = GradientTable(gradients, b0_threshold=b0_threshold, **kwargs)
    grad_table.bvals = bvals
    grad_table.bvecs = bvecs
    grad_table.b0s_mask = ~dwi_mask

    return grad_table
예제 #16
0
파일: gradients.py 프로젝트: MPDean/dipy
 def bvals(self):
     return vector_norm(self.gradients)
예제 #17
0
파일: sphere.py 프로젝트: DALILA2015/dipy
t = (1 + np.sqrt(5)) / 2
icosahedron_vertices = np.array(
    [[  t,  1,  0], #  0
     [ -t,  1,  0], #  1
     [  t, -1,  0], #  2
     [ -t, -1,  0], #  3
     [  1,  0,  t], #  4
     [  1,  0, -t], #  5
     [ -1,  0,  t], #  6
     [ -1,  0, -t], #  7
     [  0,  t,  1], #  8
     [  0, -t,  1], #  9
     [  0,  t, -1], # 10
     [  0, -t, -1], # 11
    ])
icosahedron_vertices /= vector_norm(icosahedron_vertices, keepdims=True)
icosahedron_faces = np.array(
    [[ 8,  4,  0],
     [ 2,  5,  0],
     [ 2,  5, 11],
     [ 9,  2, 11],
     [ 2,  4,  0],
     [ 9,  2,  4],
     [10,  8,  1],
     [10,  8,  0],
     [10,  5,  0],
     [ 6,  3,  1],
     [ 9,  6,  3],
     [ 6,  8,  1],
     [ 6,  8,  4],
     [ 9,  6,  4],
예제 #18
0
icosahedron_vertices = np.array([
    [t, 1, 0],  # 0
    [-t, 1, 0],  # 1
    [t, -1, 0],  # 2
    [-t, -1, 0],  # 3
    [1, 0, t],  # 4
    [1, 0, -t],  # 5
    [-1, 0, t],  # 6
    [-1, 0, -t],  # 7
    [0, t, 1],  # 8
    [0, -t, 1],  # 9
    [0, t, -1],  # 10
    [0, -t, -1],
])  # 11

icosahedron_vertices /= vector_norm(icosahedron_vertices, keepdims=True)
icosahedron_faces = np.array([
    [8, 4, 0],
    [2, 5, 0],
    [2, 5, 11],
    [9, 2, 11],
    [2, 4, 0],
    [9, 2, 4],
    [10, 8, 1],
    [10, 8, 0],
    [10, 5, 0],
    [6, 3, 1],
    [9, 6, 3],
    [6, 8, 1],
    [6, 8, 4],
    [9, 6, 4],
예제 #19
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))
예제 #20
0
 def bvals(self):
     return vector_norm(self.gradients)
예제 #21
0
def fix_bvals_bvecs(fbvals,
                    fbvecs,
                    b0_threshold=50,
                    atol=1e-2,
                    outpath=None,
                    identifier="_fix",
                    writeformat="classic"):
    """
    Read b-values and b-vectors from disk

    Parameters
    ----------
    fbvals : str
       Full path to file with b-values. None to not read bvals.
    fbvecs : str
       Full path of file with b-vectors. None to not read bvecs.

    Returns
    -------
    bvals : array, (N,) or None
    bvecs : array, (N, 3) or None

    Notes
    -----
    Files can be either '.bvals'/'.bvecs' or '.txt' or '.npy' (containing
    arrays stored with the appropriate values).
    """

    # Loop over the provided inputs, reading each one in turn and adding them
    # to this list:
    bvals, bvecs = read_bvals(fbvals, fbvecs)

    # If bvecs is None, you can just return now w/o making more checks:
    if bvecs is None:
        return bvals, bvecs

    if bvecs.ndim != 2:
        raise IOError('bvec file should be saved as a two dimensional array')
    if bvecs.shape[1] > bvecs.shape[0]:
        bvecs = bvecs.T

    if bvecs.shape[1] == 4:
        if np.max(bvecs[:, 0]) > b0_threshold:
            if bvals is None:
                bvals = bvec[0, :]
            bvecs = np.delete(bvecs, 0, 1)

    # If bvals is None, you don't need to check that they have the same shape:
    if bvals is None:
        return bvals, bvecs

    if len(bvals.shape) > 1:
        raise IOError('bval file should have one row')

    if max(bvals.shape) != max(bvecs.shape):
        raise IOError('b-values and b-vectors shapes do not correspond')

    from dipy.core.geometry import vector_norm

    bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol

    if bvecs.shape[1] != 3:
        raise ValueError("bvecs should be (N, 3)")
    dwi_mask = bvals > b0_threshold
    if not np.all(bvecs_close_to_1[dwi_mask]):
        correctvals = [
            i for i, val in enumerate(bvecs_close_to_1) if val and dwi_mask[i]
        ]
        incorrectvals = [
            i for i, val in enumerate(bvecs_close_to_1)
            if not val and dwi_mask[i]
        ]
        baseline_bval = bvals[correctvals[0]]
        for i in incorrectvals:
            if dwi_mask[i]:
                bvecs[i, :] = bvecs[i, :] / np.sqrt(bvals[i] / baseline_bval)
        bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol
        if not np.all(bvecs_close_to_1[dwi_mask]):
            incorrectvals = [
                i for i, val in enumerate(bvecs_close_to_1)
                if not val and dwi_mask[i]
            ]
            raise ValueError(
                "The vectors in bvecs should be unit (The tolerance "
                "can be modified as an input parameter)")

    if outpath is None:
        base, ext = splitext(fbvals)
    else:
        base = os.path.join(outpath,
                            os.path.basename(fbvals).replace(".txt", ""))
        ext = ".txt"

    fbvals = base + identifier + ext
    if writeformat == "classic":
        np.savetxt(fbvals, bvals)
    if writeformat == "dsi":
        with open(fbvals, 'w') as File_object:
            for bval in bvals:
                if bval > 10:
                    bval = int(round(bval))
                else:
                    bval = 0
                File_object.write(str(bval) + "\t")
    #base, ext = splitext(fbvecs)
    basevecs = base.replace("bvals", "bvecs")
    fbvecs = basevecs + identifier + ext
    if writeformat == "classic":
        if not os.path.isfile(fbvecs):
            np.savetxt(fbvecs, bvecs)
    #    with open(fbvecs, 'w') as f:
    #        f.write(str(bvec))
    if writeformat == "dsi":
        with open(fbvecs, 'w') as File_object:
            for i in [0, 1, 2]:
                for j in np.arange(np.shape(bvecs)[0]):
                    if bvecs[j, i] == 0:
                        bvec = 0
                    else:
                        bvec = round(bvecs[j, i], 3)
                    File_object.write(str(bvec) + "\t")
                File_object.write("\n")
            File_object.close()

    return fbvals, fbvecs
예제 #22
0
파일: code.py 프로젝트: haanme/FinnBrain
def nii2streamlines(imgfile, maskfile, bvals, bvecs, output_prefix):
    import numpy as np
    import nibabel as nib
    import os
    from dipy.core.geometry import vector_norm

    from dipy.reconst.dti import TensorModel

    print "nii2streamlines"

    img = nib.load(imgfile)
    bvals = np.genfromtxt(bvals)
    bvecs = np.genfromtxt(bvecs)
    # transpose if necessary to be Nx3 matrix
    if bvecs.shape[1] != 3:
        bvecs = bvecs.T
    # re-scale vectors to be close to 1
    for bvec_i in range(bvecs.shape[0]):
            coeff = vector_norm(bvecs[bvec_i])
            coeff_before = abs(coeff - 1)
            if coeff==0:
                continue
            bvecs[bvec_i] = bvecs[bvec_i]/coeff
            coeff_after = abs(vector_norm(bvecs[bvec_i]) - 1)
            print "Norm " + str(coeff_before) + "->" + str(coeff_after)

    from nipype.utils.filemanip import split_filename
    _, prefix, _  = split_filename(imgfile)

    from dipy.data import gradient_table

    gtab = gradient_table(bvals, bvecs)
    data = img.get_data()
    affine = img.get_affine()
    zooms = img.get_header().get_zooms()[:3]
    new_zooms = (2., 2., 2.)
    data2, affine2 = data, affine
    mask = nib.load(maskfile).get_data().astype(np.bool)
    tenmodel = TensorModel(gtab)
    tenfit = tenmodel.fit(data2, mask)

    from dipy.reconst.dti import fractional_anisotropy
    FA = fractional_anisotropy(tenfit.evals)
    FA[np.isnan(FA)] = 0
    fa_img = nib.Nifti1Image(FA, img.get_affine())
    nib.save(fa_img, experiment_dir + '/' + output_prefix + '/' + ('%s_tensor_fa.nii.gz' % prefix))

    evecs = tenfit.evecs

    evec_img = nib.Nifti1Image(evecs, img.get_affine())
    nib.save(evec_img, experiment_dir + '/' + output_prefix + '/' + ('%s_tensor_evec.nii.gz' % prefix))

    from dipy.data import get_sphere
    sphere = get_sphere('symmetric724')
    from dipy.reconst.dti import quantize_evecs

    peak_indices = quantize_evecs(tenfit.evecs, sphere.vertices)

    from dipy.tracking.eudx import EuDX

    eu = EuDX(FA, peak_indices, odf_vertices = sphere.vertices, a_low=0.2, seeds=10**6, ang_thr=35)
    tensor_streamlines = [streamline for streamline in eu]

    hdr = nib.trackvis.empty_header()
    hdr['voxel_size'] = new_zooms
    hdr['voxel_order'] = 'LPS'
    hdr['dim'] = data2.shape[:3]

    import dipy.tracking.metrics as dmetrics
    tensor_streamlines = ((sl, None, None) for sl in tensor_streamlines if dmetrics.length(sl) > 15)

    ten_sl_fname = experiment_dir + '/' + output_prefix + '/' + ('%s_streamline.trk' % prefix)

    nib.trackvis.write(ten_sl_fname, tensor_streamlines, hdr, points_space='voxel')
    return ten_sl_fname
예제 #23
0
def gradient_table_from_bvals_bvecs(bvals, bvecs, b0_threshold=50, atol=1e-2,
                                    **kwargs):
    """Creates a GradientTable from a bvals array and a bvecs array

    Parameters
    ----------
    bvals : array_like (N,)
        The b-value, or magnitude, of each gradient direction.
    bvecs : array_like (N, 3)
        The direction, represented as a unit vector, of each gradient.
    b0_threshold : float
        Gradients with b-value less than or equal to `bo_threshold` are
        considered to not have diffusion weighting.
    atol : float
        Each vector in `bvecs` must be a unit vectors up to a tolerance of
        `atol`.

    Other Parameters
    ----------------
    **kwargs : dict
        Other keyword inputs are passed to GradientTable.

    Returns
    -------
    gradients : GradientTable
        A GradientTable with all the gradient information.

    See Also
    --------
    GradientTable, gradient_table

    """
    bvals = np.asarray(bvals, np.float)
    bvecs = np.asarray(bvecs, np.float)
    dwi_mask = bvals > b0_threshold

    # check that bvals is (N,) array and bvecs is (N, 3) unit vectors
    if bvals.ndim != 1 or bvecs.ndim != 2 or bvecs.shape[0] != bvals.shape[0]:
        raise ValueError("bvals and bvecs should be (N,) and (N, 3) arrays "
                         "respectively, where N is the number of diffusion "
                         "gradients")
    # checking for negative bvals
    if b0_threshold < 0:
        raise ValueError("Negative bvals in the data are not feasible")

    # Upper bound for the b0_threshold
    if b0_threshold >= 200:
        warn("b0_threshold has a value > 199")

    # checking for the correctness of bvals
    if b0_threshold < bvals.min():
        warn("b0_threshold (value: {0}) is too low, increase your \
             b0_threshold. It should higher than the first b0 value \
             ({1}).".format(b0_threshold, bvals.min()))

    bvecs = np.where(np.isnan(bvecs), 0, bvecs)
    bvecs_close_to_1 = abs(vector_norm(bvecs) - 1) <= atol
    if bvecs.shape[1] != 3:
        raise ValueError("bvecs should be (N, 3)")
    if not np.all(bvecs_close_to_1[dwi_mask]):
        raise ValueError("The vectors in bvecs should be unit (The tolerance "
                         "can be modified as an input parameter)")

    bvecs = np.where(bvecs_close_to_1[:, None], bvecs, 0)
    bvals = bvals * bvecs_close_to_1
    gradients = bvals[:, None] * bvecs

    grad_table = GradientTable(gradients, b0_threshold=b0_threshold, **kwargs)
    grad_table.bvals = bvals
    grad_table.bvecs = bvecs
    grad_table.b0s_mask = ~dwi_mask

    return grad_table