Parallel3dAxisGeometry.det_point_position¶
- Parallel3dAxisGeometry.det_point_position(mparam, dparam)¶
Return the detector point at
(mparam, dparam).The position is computed as follows:
pos = refpoint(mparam) + rotation_matrix(mparam).dot(detector.surface(dparam))
In other words, the motion parameter
mparamis used to move the detector reference point, and the detector parameterdparamdefines an intrinsic shift that is added to the reference point.- Parameters:
- mparam
array-likeor sequence Motion parameter(s) at which to evaluate. If
motion_params.ndim >= 2, a sequence of that length must be provided.- dparam
array-likeor sequence Detector parameter(s) at which to evaluate. If
det_params.ndim >= 2, a sequence of that length must be provided.
- mparam
- Returns:
- pos
numpy.ndarray Vector(s) pointing from the origin to the detector point. The shape of the returned array is obtained from the (broadcast) shapes of
mparamanddparam, and broadcasting is supported within both parameters and between them. The precise definition of the shape isbroadcast(bcast_mparam, bcast_dparam).shape + (ndim,), wherebcast_mparamismparamifmotion_paramsis 1D,broadcast(*mparam)otherwise,
and
bcast_dparamdefined analogously.
- pos
Examples
The method works with single parameter values, in which case a single vector is returned:
>>> apart = odl.uniform_partition(0, np.pi, 10) >>> dpart = odl.uniform_partition(-1, 1, 20) >>> geom = odl.tomo.Parallel2dGeometry(apart, dpart) >>> geom.det_point_position(0, 0) # (0, 1) + 0 * (1, 0) array([ 0., 1.]) >>> geom.det_point_position(0, 1) # (0, 1) + 1 * (1, 0) array([ 1., 1.]) >>> pt = geom.det_point_position(np.pi / 2, 0) # (-1, 0) + 0 * (0, 1) >>> np.allclose(pt, [-1, 0]) True >>> pt = geom.det_point_position(np.pi / 2, 1) # (-1, 0) + 1 * (0, 1) >>> np.allclose(pt, [-1, 1]) True
Both variables support vectorized calls, i.e., stacks of parameters can be provided. The order of axes in the output (left of the
ndimaxis for the vector dimension) corresponds to the order of arguments:>>> geom.det_point_position(0, [-1, 0, 0.5, 1]) array([[-1. , 1. ], [ 0. , 1. ], [ 0.5, 1. ], [ 1. , 1. ]]) >>> pts = geom.det_point_position([0, np.pi / 2, np.pi], 0) >>> np.allclose(pts, [[0, 1], ... [-1, 0], ... [0, -1]]) True >>> # Providing 3 pairs of parameters, resulting in 3 vectors >>> pts = geom.det_point_position([0, np.pi / 2, np.pi], ... [-1, 0, 1]) >>> pts[0] # Corresponds to angle = 0, dparam = -1 array([-1., 1.]) >>> pts.shape (3, 2) >>> # Pairs of parameters arranged in arrays of same size >>> geom.det_point_position(np.zeros((4, 5)), np.zeros((4, 5))).shape (4, 5, 2) >>> # "Outer product" type evaluation using broadcasting >>> geom.det_point_position(np.zeros((4, 1)), np.zeros((1, 5))).shape (4, 5, 2)
More complicated 3D geometry with 2 angle variables and 2 detector variables:
>>> apart = odl.uniform_partition([0, 0], [np.pi, 2 * np.pi], ... (10, 20)) >>> dpart = odl.uniform_partition([-1, -1], [1, 1], (20, 20)) >>> geom = odl.tomo.Parallel3dEulerGeometry(apart, dpart) >>> # 2 values for each variable, resulting in 2 vectors >>> angles = ([0, np.pi / 2], [0, np.pi]) >>> dparams = ([-1, 0], [-1, 0]) >>> pts = geom.det_point_position(angles, dparams) >>> pts[0] # Corresponds to angle = (0, 0), dparam = (-1, -1) array([-1., 1., -1.]) >>> pts.shape (2, 3) >>> # 4 x 5 parameters for both >>> angles = dparams = (np.zeros((4, 5)), np.zeros((4, 5))) >>> geom.det_point_position(angles, dparams).shape (4, 5, 3) >>> # Broadcasting angles to shape (4, 5, 1, 1) >>> angles = (np.zeros((4, 1, 1, 1)), np.zeros((1, 5, 1, 1))) >>> # Broadcasting dparams to shape (1, 1, 6, 7) >>> dparams = (np.zeros((1, 1, 6, 1)), np.zeros((1, 1, 1, 7))) >>> # Total broadcast parameter shape is (4, 5, 6, 7) >>> geom.det_point_position(angles, dparams).shape (4, 5, 6, 7, 3)