ellipsoid_phantom

odl.phantom.geometric.ellipsoid_phantom(space, ellipsoids, min_pt=None, max_pt=None)[source]

Return a phantom given by ellipsoids.

Parameters
spaceDiscretizedSpace

Space in which the phantom should be created, must be 2- or 3-dimensional. If space.shape is 1 in an axis, a corresponding slice of the phantom is created (instead of squashing the whole phantom into the slice).

ellipsoidssequence of sequences

If space is 2-dimensional, each row should contain the entries

'value',
'axis_1', 'axis_2',
'center_x', 'center_y',
'rotation'

If space is 3-dimensional, each row should contain the entries

'value',
'axis_1', 'axis_2', 'axis_3',
'center_x', 'center_y', 'center_z',
'rotation_phi', 'rotation_theta', 'rotation_psi'

The provided ellipsoids need to be specified relative to the reference rectangle [-1, -1] x [1, 1], or analogously in 3d. The angles are to be given in radians.

min_pt, max_ptarray-like, optional

If provided, use these vectors to determine the bounding box of the phantom instead of space.min_pt and space.max_pt. It is currently required that min_pt >= space.min_pt and max_pt <= space.max_pt, i.e., shifting or scaling outside the original space is not allowed.

Providing one of them results in a shift, e.g., for min_pt:

new_min_pt = min_pt
new_max_pt = space.max_pt + (min_pt - space.min_pt)

Providing both results in a scaled version of the phantom.

See also

odl.phantom.transmission.shepp_logan

Classical Shepp-Logan phantom, typically used for transmission imaging

odl.phantom.transmission.shepp_logan_ellipsoids

Ellipses for the Shepp-Logan phantom

odl.phantom.geometric.defrise_ellipses

Ellipses for the Defrise phantom

Notes

The phantom is created by adding the values of each ellipse. The ellipses are defined by a center point (center_x, center_y, [center_z]), the lengths of its principial axes (axis_1, axis_2, [axis_2]), and a rotation angle rotation in 2D or Euler angles (rotation_phi, rotation_theta, rotation_psi) in 3D.

This function is heavily optimized, achieving runtimes about 20 times faster than “trivial” implementations. It is therefore recommended to use it in all phantoms where applicable.

The main optimization is that it only considers a subset of all the points when updating for each ellipse. It does this by first finding a subset of points that could possibly be inside the ellipse. This optimization is very good for “spherical” ellipsoids, but not so much for elongated or rotated ones.

It also does calculations wherever possible on the meshgrid instead of individual points.

Examples

Create a circle with a smaller circle inside:

>>> space = odl.uniform_discr([-1, -1], [1, 1], [5, 5])
>>> ellipses = [[1.0, 1.0, 1.0, 0.0, 0.0, 0.0],
...             [1.0, 0.6, 0.6, 0.0, 0.0, 0.0]]
>>> print(ellipsoid_phantom(space, ellipses))
[[ 0.,  0.,  1.,  0.,  0.],
 [ 0.,  1.,  2.,  1.,  0.],
 [ 1.,  2.,  2.,  2.,  1.],
 [ 0.,  1.,  2.,  1.,  0.],
 [ 0.,  0.,  1.,  0.,  0.]]