FanBeamGeometry.det_refpoint

FanBeamGeometry.det_refpoint(angle)[source]

Return the detector reference point position at angle.

For an angle phi, the detector position is given by

det_ref(phi) = translation +
               rot_matrix(phi) * (det_rad * src_to_det_init) +
               detector_shift(phi)

where src_to_det_init is the initial unit vector pointing from source to detector and

detector_shift(phi) = rot_matrix(phi) *
                      (shift[0] * src_to_det_init +
                      shift[1] * tangent)

where tangent is a vector tangent to the trajectory

Parameters:
anglefloat or array-like

Angle(s) in radians describing the counter-clockwise rotation of source and detector.

Returns:
pointnumpy.ndarray

Vector(s) pointing from the origin to the detector reference point. If angle is a single parameter, the returned array has shape (2,), otherwise angle.shape + (2,).

See also

src_position

Examples

With default arguments, the detector starts at det_rad * e_y and rotates to det_rad * (-e_x) at 90 degrees:

>>> apart = odl.uniform_partition(0, 2 * np.pi, 10)
>>> dpart = odl.uniform_partition(-1, 1, 20)
>>> geom = FanBeamGeometry(apart, dpart, src_radius=2, det_radius=5)
>>> geom.det_refpoint(0)
array([ 0.,  5.])
>>> np.allclose(geom.det_refpoint(np.pi / 2), [-5, 0])
True

The method is vectorized, i.e., it can be called with multiple angles at once:

>>> points = geom.det_refpoint([0, np.pi / 2])
>>> np.allclose(points[0], [0, 5])
True
>>> np.allclose(points[1], [-5, 0])
True

Specifying detector offset:

>>> apart = odl.uniform_partition(0, 2 * np.pi, 4)
>>> geom = FanBeamGeometry(
...     apart, dpart,
...     src_radius=1, det_radius=1,
...     det_shift_func=lambda angle: [0.0, 0.1],
...     src_to_det_init=(0.71, -0.71))
>>> geom.angles
array([ 0.78539816,  2.35619449,  3.92699082,  5.49778714])
>>> np.round(geom.det_refpoint(geom.angles), 2)
array([[ 1. ,  0.1],
       [-0.1,  1. ],
       [-1. , -0.1],
       [ 0.1, -1. ]])