|
16 | 16 | from odl.tomo.geometry.detector import Detector, Flat1dDetector, Flat2dDetector |
17 | 17 | from odl.tomo.util import axis_rotation_matrix, is_inside_bounds |
18 | 18 | from odl.util import ( |
19 | | - normalized_scalar_param_list, safe_int_conv, signature_string_parts, |
20 | | - repr_string, REPR_PRECISION, npy_printoptions) |
| 19 | + normalized_scalar_param_list, normalized_index_expression, |
| 20 | + safe_int_conv, signature_string_parts, repr_string, REPR_PRECISION, |
| 21 | + npy_printoptions, array_str) |
21 | 22 |
|
22 | 23 |
|
23 | 24 | __all__ = ('Geometry', 'DivergentBeamGeometry', 'AxisOrientedGeometry', |
@@ -1046,6 +1047,74 @@ def det_axes(self, index): |
1046 | 1047 | det_v = det_v_left + frac_part * (det_v_right - det_v_left) |
1047 | 1048 | return (det_u, det_v) |
1048 | 1049 |
|
| 1050 | + def __getitem__(self, indices): |
| 1051 | + """Return ``self[indices]``. |
| 1052 | +
|
| 1053 | + The returned geometry is the vec geometry gained by slicing |
| 1054 | + `vectors` with the given ``indices`` along the first axis and |
| 1055 | + using the original `det_shape`. |
| 1056 | +
|
| 1057 | + Parameters |
| 1058 | + ---------- |
| 1059 | + indices : index expression |
| 1060 | + Object used to slice `vectors` along the first axis. |
| 1061 | +
|
| 1062 | +
|
| 1063 | + Raises |
| 1064 | + ------ |
| 1065 | + ValueError |
| 1066 | + If ``indices`` slices along other axes than the first. |
| 1067 | +
|
| 1068 | + Examples |
| 1069 | + -------- |
| 1070 | + >>> vecs_2d = [[0, 1, 0, 1, 1, 0], |
| 1071 | + ... [0, 1, 0, 1, -1, 0], |
| 1072 | + ... [-1, 0, -1, 0, 0, 1], |
| 1073 | + ... [-1, 0, -1, 0, 0, -1]] |
| 1074 | + >>> det_shape = (10,) |
| 1075 | + >>> geom = odl.tomo.ParallelVecGeometry(det_shape, vecs_2d) |
| 1076 | + >>> geom[0] # first angle only |
| 1077 | + ParallelVecGeometry((10,), array([[ 0., 1., 0., 1., 1., 0.]])) |
| 1078 | + >>> geom[:3] # first 3 angles |
| 1079 | + ParallelVecGeometry( |
| 1080 | + (10,), |
| 1081 | + array([[ 0., 1., 0., 1., 1., 0.], |
| 1082 | + [ 0., 1., 0., 1., -1., 0.], |
| 1083 | + [-1., 0., -1., 0., 0., 1.]]) |
| 1084 | + ) |
| 1085 | + >>> geom[::2] # every second angle, starting at the first |
| 1086 | + ParallelVecGeometry( |
| 1087 | + (10,), |
| 1088 | + array([[ 0., 1., 0., 1., 1., 0.], |
| 1089 | + [-1., 0., -1., 0., 0., 1.]]) |
| 1090 | + ) |
| 1091 | + >>> geom[[0, -1]] # first and last |
| 1092 | + ParallelVecGeometry( |
| 1093 | + (10,), |
| 1094 | + array([[ 0., 1., 0., 1., 1., 0.], |
| 1095 | + [-1., 0., -1., 0., 0., -1.]]) |
| 1096 | + ) |
| 1097 | + """ |
| 1098 | + # Index vectors and make sure that we still have a valid shape |
| 1099 | + # for ASTRA vecs of the same type |
| 1100 | + sub_vecs = self.vectors[indices] |
| 1101 | + if np.isscalar(sub_vecs) or not hasattr(sub_vecs, 'shape'): |
| 1102 | + raise ValueError( |
| 1103 | + 'indexing of `vectors` results in scalar or non-array ' |
| 1104 | + '(type {})'.format(type(sub_vecs))) |
| 1105 | + |
| 1106 | + if sub_vecs.ndim == 1 and sub_vecs.shape[0] == self.vectors.shape[1]: |
| 1107 | + # Reduced to single vector, add missing dimension |
| 1108 | + sub_vecs = sub_vecs[None, :] |
| 1109 | + |
| 1110 | + if sub_vecs.ndim != 2 or sub_vecs.shape[1] != self.vectors.shape[1]: |
| 1111 | + raise ValueError( |
| 1112 | + 'indexing of `vectors` results in array of shape {0}, ' |
| 1113 | + 'expected (N, {1}) or ({1},)' |
| 1114 | + ''.format(sub_vecs.shape, self.vectors.shape[1])) |
| 1115 | + |
| 1116 | + return type(self)(self.detector.shape, sub_vecs) |
| 1117 | + |
1049 | 1118 | def __repr__(self): |
1050 | 1119 | """Return ``repr(self)``.""" |
1051 | 1120 | posargs = [self.det_partition.shape, self.vectors] |
|
0 commit comments