Example #1
0
def test_diffeomorphic_map_simplification_3d():
    r""" Test simplification of 3D diffeomorphic maps

    Create an invertible deformation field, and define a DiffeomorphicMap
    using different voxel-to-space transforms for domain, codomain, and
    reference discretizations, also use a non-identity pre-aligning matrix.
    Warp a sphere using the diffeomorphic map to obtain the expected warped
    sphere. Now simplify the DiffeomorphicMap and warp the same sphere
    using this simplified map. Verify that the two warped spheres are equal
    up to numerical precision.
    """
    # create a simple affine transformation
    domain_shape = (64, 64, 64)
    codomain_shape = (80, 80, 80)
    nr = domain_shape[0]
    nc = domain_shape[1]
    ns = domain_shape[2]
    s = 1.1
    t = 0.25
    trans = np.array([[1, 0, 0, -t * ns], [0, 1, 0, -t * nr],
                      [0, 0, 1, -t * nc], [0, 0, 0, 1]])
    trans_inv = np.linalg.inv(trans)
    scale = np.array([[1 * s, 0, 0, 0], [0, 1 * s, 0, 0], [0, 0, 1 * s, 0],
                      [0, 0, 0, 1]])
    gt_affine = trans_inv.dot(scale.dot(trans))
    # Create the invertible displacement fields and the sphere
    radius = 16
    sphere = vfu.create_sphere(codomain_shape[0], codomain_shape[1],
                               codomain_shape[2], radius)
    d, dinv = vfu.create_harmonic_fields_3d(domain_shape[0], domain_shape[1],
                                            domain_shape[2], 0.3, 6)
    # Define different voxel-to-space transforms for domain, codomain and
    # reference grid, also, use a non-identity pre-align transform
    D = gt_affine
    C = imwarp.mult_aff(gt_affine, gt_affine)
    R = np.eye(4)
    P = gt_affine

    # Create the original diffeomorphic map
    diff_map = imwarp.DiffeomorphicMap(3, domain_shape, R, domain_shape, D,
                                       codomain_shape, C, P)
    diff_map.forward = np.array(d, dtype=floating)
    diff_map.backward = np.array(dinv, dtype=floating)
    # Warp the sphere to obtain the expected image
    expected = diff_map.transform(sphere, 'linear')

    # Simplify
    simplified = diff_map.get_simplified_transform()
    # warp the sphere
    warped = simplified.transform(sphere, 'linear')
    # verify that the simplified map is equivalent to the
    # original one
    assert_array_almost_equal(warped, expected)
    # And of course, it must be simpler...
    assert_equal(simplified.domain_grid2world, None)
    assert_equal(simplified.codomain_grid2world, None)
    assert_equal(simplified.disp_grid2world, None)
    assert_equal(simplified.domain_world2grid, None)
    assert_equal(simplified.codomain_world2grid, None)
    assert_equal(simplified.disp_world2grid, None)
Example #2
0
def test_diffeomorphic_map_simplification_3d():
    r"""
    Create an invertible deformation field, and define a DiffeomorphicMap
    using different voxel-to-space transforms for domain, codomain, and
    reference discretizations, also use a non-identity pre-aligning matrix.
    Warp a sphere using the diffeomorphic map to obtain the expected warped
    sphere. Now simplify the DiffeomorphicMap and warp the same sphere using
    this simplified map. Verify that the two warped spheres are equal up to
    numerical precision.
    """
    #create a simple affine transformation
    domain_shape = (64, 64, 64)
    codomain_shape = (80, 80, 80)
    nr = domain_shape[0]
    nc = domain_shape[1]
    ns = domain_shape[2]
    s = 1.1
    t = 0.25
    trans = np.array([[1, 0, 0, -t*ns],
                      [0, 1, 0, -t*nr],
                      [0, 0, 1, -t*nc],
                      [0, 0, 0, 1]])
    trans_inv = np.linalg.inv(trans)
    scale = np.array([[1*s, 0, 0, 0],
                      [0, 1*s, 0, 0],
                      [0, 0, 1*s, 0],
                      [0, 0, 0, 1]])
    gt_affine = trans_inv.dot(scale.dot(trans))
    # Create the invertible displacement fields and the sphere
    radius = 16
    sphere = vfu.create_sphere(codomain_shape[0], codomain_shape[1],
                               codomain_shape[2], radius)
    d, dinv = vfu.create_harmonic_fields_3d(domain_shape[0], domain_shape[1],
                                            domain_shape[2], 0.3, 6)
    #Define different voxel-to-space transforms for domain, codomain and
    #reference grid, also, use a non-identity pre-align transform
    D = gt_affine
    C = imwarp.mult_aff(gt_affine, gt_affine)
    R = np.eye(4)
    P = gt_affine

    #Create the original diffeomorphic map
    diff_map = imwarp.DiffeomorphicMap(3, domain_shape, R,
                                          domain_shape, D,
                                          codomain_shape, C,
                                          P)
    diff_map.forward = np.array(d, dtype = floating)
    diff_map.backward = np.array(dinv, dtype = floating)
    #Warp the sphere to obtain the expected image
    expected = diff_map.transform(sphere, 'linear')

    #Simplify
    simplified = diff_map.get_simplified_transform()
    #warp the sphere
    warped = simplified.transform(sphere, 'linear')
    #verify that the simplified map is equivalent to the
    #original one
    assert_array_almost_equal(warped, expected)
    #And of course, it must be simpler...
    assert_equal(simplified.domain_affine, None)
    assert_equal(simplified.codomain_affine, None)
    assert_equal(simplified.disp_affine, None)
    assert_equal(simplified.domain_affine_inv, None)
    assert_equal(simplified.codomain_affine_inv, None)
    assert_equal(simplified.disp_affine_inv, None)
Example #3
0
from dipy.align import vector_fields as vfu
# from dipy.align.transforms import regtransforms
# from dipy.align.parzenhist import sample_domain_regular

sh = (64, 64, 64)
ns = sh[0]
nr = sh[1]
nc = sh[2]

# Create an image of a sphere
radius = 24
sphere = vfu.create_sphere(ns, nr, nc, radius)
sphere = np.array(sphere, dtype=floating)

# Create a displacement field for warping
d, dinv = vfu.create_harmonic_fields_3d(ns, nr, nc, 0.2, 8)
d = np.asarray(d).astype(floating)

# Create grid coordinates
x_0 = np.asarray(range(sh[0]))
x_1 = np.asarray(range(sh[1]))
x_2 = np.asarray(range(sh[2]))
X = np.empty((4, ) + sh, dtype=np.float64)
O = np.ones(sh)
X[0, ...] = x_0[:, None, None] * O
X[1, ...] = x_1[None, :, None] * O
X[2, ...] = x_2[None, None, :] * O
X[3, ...] = 1

# Select an arbitrary rotation axis
axis = np.array([.5, 2.0, 1.5])
Example #4
0
def test_warp(shape):
    """Tests the cython implementation of the 3d warpings against scipy."""

    ndim = len(shape)
    radius = shape[0] / 3

    if ndim == 3:
        # Create an image of a sphere
        volume = vfu.create_sphere(*shape, radius)
        volume = np.array(volume, dtype=floating)

        # Create a displacement field for warping
        d, dinv = vfu.create_harmonic_fields_3d(*shape, 0.2, 8)
    else:
        # Create an image of a circle
        volume = vfu.create_circle(*shape, radius)
        volume = np.array(volume, dtype=floating)

        # Create a displacement field for warping
        d, dinv = vfu.create_harmonic_fields_2d(*shape, 0.2, 8)
    d = np.asarray(d).astype(floating)

    if ndim == 3:
        # Select an arbitrary rotation axis
        axis = np.array([0.5, 2.0, 1.5])
        # Select an arbitrary translation matrix
        t = 0.1
        trans = np.array([
            [1, 0, 0, -t * shape[0]],
            [0, 1, 0, -t * shape[1]],
            [0, 0, 1, -t * shape[2]],
            [0, 0, 0, 1],
        ])
        trans_inv = np.linalg.inv(trans)
        theta = np.pi / 5
        s = 1.1
        rot = np.zeros(shape=(4, 4))
        rot[:3, :3] = geometry.rodrigues_axis_rotation(axis, theta)
        rot[3, 3] = 1.0

        scale = np.array([[1 * s, 0, 0, 0], [0, 1 * s, 0, 0], [0, 0, 1 * s, 0],
                          [0, 0, 0, 1]])
    elif ndim == 2:
        # Select an arbitrary translation matrix
        t = 0.1
        trans = np.array([[1, 0, -t * shape[0]], [0, 1, -t * shape[1]],
                          [0, 0, 1]])
        trans_inv = np.linalg.inv(trans)
        theta = -1 * np.pi / 6.0
        s = 0.42
        ct = np.cos(theta)
        st = np.sin(theta)

        rot = np.array([[ct, -st, 0], [st, ct, 0], [0, 0, 1]])

        scale = np.array([[1 * s, 0, 0], [0, 1 * s, 0], [0, 0, 1]])

    aff = trans_inv.dot(scale.dot(rot.dot(trans)))

    # Select arbitrary (but different) grid-to-space transforms
    sampling_grid2world = scale
    field_grid2world = aff
    field_world2grid = np.linalg.inv(field_grid2world)
    image_grid2world = aff.dot(scale)
    image_world2grid = np.linalg.inv(image_grid2world)

    A = field_world2grid.dot(sampling_grid2world)
    B = image_world2grid.dot(sampling_grid2world)
    C = image_world2grid

    # Reorient the displacement field according to its grid-to-space
    # transform
    dcopy = np.copy(d)
    if ndim == 3:
        vfu.reorient_vector_field_3d(dcopy, field_grid2world)
        expected = vfu.warp_3d(volume, dcopy, A, B, C,
                               np.array(shape, dtype=np.int32))
    elif ndim == 2:
        vfu.reorient_vector_field_2d(dcopy, field_grid2world)
        expected = vfu.warp_2d(volume, dcopy, A, B, C,
                               np.array(shape, dtype=np.int32))

    dcopyg = cupy.asarray(dcopy)
    volumeg = cupy.asarray(volume)
    Ag = cupy.asarray(A)
    Bg = cupy.asarray(B)
    Cg = cupy.asarray(C)

    warped = warp(volumeg, dcopyg, Ag, Bg, Cg, order=1, mode="constant")

    cupy.testing.assert_array_almost_equal(warped, expected, decimal=4)