Example #1
0
def test_interpolate_scalar_3d():
    np.random.seed(9216326)
    sz = 64
    target_shape = (sz, sz, sz)
    image = np.empty(target_shape, dtype=floating)
    image[...] = np.random.randint(0, 10, np.size(image)).reshape(target_shape)

    extended_image = np.zeros((sz + 2, sz + 2, sz + 2), dtype=floating)
    extended_image[1:sz + 1, 1:sz + 1, 1:sz + 1] = image[...]

    # Select some coordinates inside the image to interpolate at
    nsamples = 800
    locations =\
        np.random.ranf(3 * nsamples).reshape((nsamples, 3)) * (sz + 2) - 1.0
    extended_locations = locations + 1.0  # shift coordinates one voxel

    # Call the implementation under test
    interp, inside = interpolate_scalar_3d(image, locations)

    # Call the reference implementation
    expected = map_coordinates(extended_image,
                               extended_locations.transpose(),
                               order=1)

    npt.assert_array_almost_equal(expected, interp)

    # Test interpolation stability along the boundary
    epsilon = 5e-8
    for k in range(3):
        for offset in [0, sz - 1]:
            delta = ((np.random.ranf(nsamples) * 2) - 1) * epsilon
            locations[:, k] = delta + offset
            locations[:, (k + 1) % 3] = np.random.ranf(nsamples) * (sz - 1)
            locations[:, (k + 2) % 3] = np.random.ranf(nsamples) * (sz - 1)
            interp, inside = interpolate_scalar_3d(image, locations)

            locations[:, k] = offset
            expected = map_coordinates(image, locations.transpose(), order=1)
            npt.assert_array_almost_equal(expected, interp)

            if offset == 0:
                expected_flag = np.array(delta >= 0, dtype=np.int32)
            else:
                expected_flag = np.array(delta <= 0, dtype=np.int32)
            npt.assert_array_almost_equal(expected_flag, inside)
Example #2
0
def _extract_vals(data, streamlines, affine, threedvec=False):
    """
    Helper function for use with `values_from_volume`.

    Parameters
    ----------
    data : 3D or 4D array
        Scalar (for 3D) and vector (for 4D) values to be extracted. For 4D
        data, interpolation will be done on the 3 spatial dimensions in each
        volume.

    streamlines : ndarray or list
        If array, of shape (n_streamlines, n_nodes, 3)
        If list, len(n_streamlines) with (n_nodes, 3) array in
        each element of the list.

    affine : array_like (4, 4)
        The mapping from voxel coordinates to streamline points.
        The voxel_to_rasmm matrix, typically from a NIFTI file.

    threedvec : bool
        Whether the last dimension has length 3. This is a special case in
        which we can use :func:`dipy.core.interpolate.interpolate_vector_3d`
        for the interploation of 4D volumes without looping over the elements
        of the last dimension.

    Returns
    ---------
    array or list (depending on the input) : values interpolate to each
        coordinate along the length of each streamline
    """
    data = data.astype(np.float)
    if (isinstance(streamlines, list)
            or isinstance(streamlines, types.GeneratorType)
            or isinstance(streamlines, Streamlines)):
        streamlines = transform_streamlines(streamlines, np.linalg.inv(affine))
        vals = []
        for sl in streamlines:
            if threedvec:
                vals.append(
                    list(interpolate_vector_3d(data, sl.astype(np.float))[0]))
            else:
                vals.append(
                    list(interpolate_scalar_3d(data, sl.astype(np.float))[0]))

    elif isinstance(streamlines, np.ndarray):
        sl_shape = streamlines.shape
        sl_cat = streamlines.reshape(sl_shape[0] * sl_shape[1],
                                     3).astype(np.float)

        inv_affine = np.linalg.inv(affine)
        sl_cat = (np.dot(sl_cat, inv_affine[:3, :3]) + inv_affine[:3, 3])

        # So that we can index in one operation:
        if threedvec:
            vals = np.array(interpolate_vector_3d(data, sl_cat)[0])
        else:
            vals = np.array(interpolate_scalar_3d(data, sl_cat)[0])
        vals = np.reshape(vals, (sl_shape[0], sl_shape[1], -1))
        if vals.shape[-1] == 1:
            vals = np.reshape(vals, vals.shape[:-1])
    else:
        raise RuntimeError("Extracting values from a volume ",
                           "requires streamlines input as an array, ",
                           "a list of arrays, or a streamline generator.")

    return vals