Parallel3dEulerGeometry.det_axes

Parallel3dEulerGeometry.det_axes(self, angles)[source]

Return the detector axes tuple at angles.

Parameters
anglesarray-like or sequence

Euler angles in radians describing the rotation of the detector. The length of the provided argument (along the first axis in case of an array) must be equal to the number of Euler angles in this geometry.

Returns
axesnumpy.ndarray

Unit vector(s) along which the detector is aligned. If angles is a single pair (or triplet) of Euler angles, the returned array has shape (2, 3), otherwise broadcast(*angles).shape + (2, 3).

Notes

To get an array that enumerates the detector axes in the first dimension, move the second-to-last axis to the first position:

axes = det_axes(angle) axes_enumeration = np.moveaxis(deriv, -2, 0)

Examples

Calling the method with a single set of angles produces a (2, 3) array of vertically stacked vectors:

>>> apart = odl.uniform_partition([0, 0], [np.pi, 2 * np.pi],
...                               (10, 20))
>>> dpart = odl.uniform_partition([-1, -1], [1, 1], (20, 20))
>>> geom = Parallel3dEulerGeometry(apart, dpart)
>>> geom.det_axes([0, 0])
array([[ 1.,  0.,  0.],
       [ 0.,  0.,  1.]])
>>> np.allclose(geom.det_axes([np.pi / 2, 0]), [[0, 1, 0],
...                                             [0, 0, 1]])
True

The method is vectorized, i.e., it can be called with multiple angle parameters at once. Each of the angle arrays can have different shapes and will be broadcast against each other to determine the final shape:

>>> # The first axis enumerates the angles
>>> np.allclose(geom.det_axes(([0, np.pi / 2], [0, 0])),
...             [[[1, 0, 0],
...               [0, 0, 1]],
...              [[0, 1, 0],
...               [0, 0, 1]]])
True
>>> # Pairs of Euler angles in a (4, 5) array each
>>> geom.det_axes((np.zeros((4, 5)), np.zeros((4, 5)))).shape
(4, 5, 2, 3)
>>> # Using broadcasting for "outer product" type result
>>> geom.det_axes((np.zeros((4, 1)), np.zeros((1, 5)))).shape
(4, 5, 2, 3)