def test_transform_geometric_centers_3d(): # Create arbitrary image-to-space transforms axis = np.array([.5, 2.0, 1.5]) t = 0.15 # translation factor for theta in [-1 * np.pi / 6.0, 0.0, np.pi / 5.0]: # rotation angle for s in [0.83, 1.3, 2.07]: # scale m_shapes = [(256, 256, 128), (255, 255, 127), (64, 127, 142)] for shape_moving in m_shapes: s_shapes = [(256, 256, 128), (255, 255, 127), (64, 127, 142)] for shape_static in s_shapes: moving = np.ndarray(shape=shape_moving) static = np.ndarray(shape=shape_static) trans = np.array([[1, 0, 0, -t * shape_static[0]], [0, 1, 0, -t * shape_static[1]], [0, 0, 1, -t * shape_static[2]], [0, 0, 0, 1]]) trans_inv = npl.inv(trans) 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]]) static_grid2world = trans_inv.dot( scale.dot(rot.dot(trans))) moving_grid2world = npl.inv(static_grid2world) # Expected translation c_static = np.array(shape_static, dtype=np.float64) * 0.5 c_static = tuple(c_static) c_static = static_grid2world.dot(c_static + (1,))[:3] c_moving = np.array(shape_moving, dtype=np.float64) * 0.5 c_moving = tuple(c_moving) c_moving = moving_grid2world.dot(c_moving + (1,))[:3] expected = np.eye(4) expected[:3, 3] = c_moving - c_static # Implementation under test actual = imaffine.transform_geometric_centers( static, static_grid2world, moving, moving_grid2world) assert_array_almost_equal(actual.affine, expected)