Skip to content

Commit 6b8eb8b

Browse files
committed
WIP: simplify index interpolation to rounding
1 parent f21af6b commit 6b8eb8b

File tree

6 files changed

+249
-160
lines changed

6 files changed

+249
-160
lines changed

examples/tomo/checks/check_axes_cone2d_vec_fp.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,13 @@
7070
proj_data = ray_trafo(phantom)
7171

7272
# Axis in this image is x. This corresponds to 0 degrees or index 0.
73-
proj_data.show(indices=[0, None],
74-
title='Projection at 0 degrees ~ Sum along y axis')
73+
proj_data.show(
74+
indices=[0, None],
75+
title='Projection at 0 degrees ~ Sum along y axis'
76+
)
7577
fig, ax = plt.subplots()
7678
ax.plot(sum_along_y)
77-
ax.set_xlabel('x')
78-
plt.title('Sum along y axis')
79+
ax.set(xlabel="x", title='Sum along y axis')
7980
plt.show()
8081
# Check axes in geometry
8182
axis_sum_y = geometry.det_axis(0)

odl/tomo/backends/astra_cpu.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
astra_volume_geometry)
2121
from odl.tomo.backends.util import _add_default_complex_impl
2222
from odl.tomo.geometry import (
23-
DivergentBeamGeometry, Geometry, ParallelBeamGeometry)
23+
ConeVecGeometry, DivergentBeamGeometry, Geometry, ParallelBeamGeometry,
24+
ParallelVecGeometry)
2425
from odl.util import writable_array
2526

2627
try:
@@ -52,16 +53,24 @@ def default_astra_proj_type(geom):
5253
5354
- `ParallelBeamGeometry`: ``'linear'``
5455
- `DivergentBeamGeometry`: ``'line_fanflat'``
56+
- `ParallelVecGeometry`: ``'linear'``
57+
- `ConeVecGeometry`: ``'line_fanflat'``
5558
5659
In 3D:
5760
5861
- `ParallelBeamGeometry`: ``'linear3d'``
5962
- `DivergentBeamGeometry`: ``'linearcone'``
63+
- `ParallelVecGeometry`: ``'linear3d'``
64+
- `ConeVecGeometry`: ``'linearcone'``
6065
"""
6166
if isinstance(geom, ParallelBeamGeometry):
6267
return 'linear' if geom.ndim == 2 else 'linear3d'
6368
elif isinstance(geom, DivergentBeamGeometry):
6469
return 'line_fanflat' if geom.ndim == 2 else 'linearcone'
70+
elif isinstance(geom, ParallelVecGeometry):
71+
return 'linear' if geom.ndim == 2 else 'linear3d'
72+
elif isinstance(geom, ConeVecGeometry):
73+
return 'line_fanflat' if geom.ndim == 2 else 'linearcone'
6574
else:
6675
raise TypeError(
6776
'no default exists for {}, `astra_proj_type` must be given '

odl/tomo/backends/astra_setup.py

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,11 @@ def astra_projection_geometry(geometry):
300300
raise ValueError('non-uniform detector sampling is not supported')
301301

302302
# Parallel 2D
303-
if (isinstance(geometry, ParallelBeamGeometry) and
304-
isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector)) and
305-
geometry.ndim == 2):
303+
if (
304+
isinstance(geometry, ParallelBeamGeometry)
305+
and isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector))
306+
and geometry.ndim == 2
307+
):
306308
det_count = geometry.detector.size
307309
if astra_supports('par2d_vec_geometry'):
308310
vecs = parallel_2d_geom_to_astra_vecs(geometry, coords='ASTRA')
@@ -327,9 +329,11 @@ def astra_projection_geometry(geometry):
327329
proj_geom = astra.create_proj_geom('parallel_vec', det_count, vecs)
328330

329331
# Cone 2D (aka fan beam)
330-
elif (isinstance(geometry, DivergentBeamGeometry) and
331-
isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector)) and
332-
geometry.ndim == 2):
332+
elif (
333+
isinstance(geometry, DivergentBeamGeometry)
334+
and isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector))
335+
and geometry.ndim == 2
336+
):
333337
det_count = geometry.detector.size
334338
vecs = cone_2d_geom_to_astra_vecs(geometry, coords='ASTRA')
335339
proj_geom = astra.create_proj_geom('fanflat_vec', det_count, vecs)
@@ -341,46 +345,55 @@ def astra_projection_geometry(geometry):
341345
proj_geom = astra.create_proj_geom('fanflat_vec', det_count, vecs)
342346

343347
# Parallel 3D
344-
elif (isinstance(geometry, ParallelBeamGeometry) and
345-
isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector)) and
346-
geometry.ndim == 3):
348+
elif (
349+
isinstance(geometry, ParallelBeamGeometry)
350+
and isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector))
351+
and geometry.ndim == 3
352+
):
347353
# Swap detector axes (see `parallel_3d_geom_to_astra_vecs`)
348354
det_row_count = geometry.det_partition.shape[0]
349355
det_col_count = geometry.det_partition.shape[1]
350356
vecs = parallel_3d_geom_to_astra_vecs(geometry, coords='ASTRA')
351357
proj_geom = astra.create_proj_geom(
352-
'parallel3d_vec', det_row_count, det_col_count, vecs)
358+
'parallel3d_vec', det_row_count, det_col_count, vecs
359+
)
353360

354361
# Parallel 3D vec
355362
elif isinstance(geometry, ParallelVecGeometry) and geometry.ndim == 3:
356363
det_row_count = geometry.det_partition.shape[1]
357364
det_col_count = geometry.det_partition.shape[0]
358365
vecs = vecs_odl_to_astra_coords(geometry.vectors)
359-
proj_geom = astra.create_proj_geom('parallel3d_vec', det_row_count,
360-
det_col_count, vecs)
366+
proj_geom = astra.create_proj_geom(
367+
'parallel3d_vec', det_row_count, det_col_count, vecs
368+
)
361369

362370
# Cone 3D
363-
elif (isinstance(geometry, DivergentBeamGeometry) and
364-
isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector)) and
365-
geometry.ndim == 3):
371+
elif (
372+
isinstance(geometry, DivergentBeamGeometry)
373+
and isinstance(geometry.detector, (Flat1dDetector, Flat2dDetector))
374+
and geometry.ndim == 3
375+
):
366376
# Swap detector axes (see `conebeam_3d_geom_to_astra_vecs`)
367377
det_row_count = geometry.det_partition.shape[0]
368378
det_col_count = geometry.det_partition.shape[1]
369379
vecs = cone_3d_geom_to_astra_vecs(geometry, coords='ASTRA')
370380
proj_geom = astra.create_proj_geom(
371-
'cone_vec', det_row_count, det_col_count, vecs)
381+
'cone_vec', det_row_count, det_col_count, vecs
382+
)
372383

373384
# Cone 3D vec
374385
elif isinstance(geometry, ConeVecGeometry) and geometry.ndim == 3:
375386
det_row_count = geometry.det_partition.shape[1]
376387
det_col_count = geometry.det_partition.shape[0]
377388
vecs = vecs_odl_to_astra_coords(geometry.vectors)
378-
proj_geom = astra.create_proj_geom('cone_vec', det_row_count,
379-
det_col_count, vecs)
389+
proj_geom = astra.create_proj_geom(
390+
'cone_vec', det_row_count, det_col_count, vecs
391+
)
380392

381393
else:
382-
raise NotImplementedError('unknown ASTRA geometry type {!r}'
383-
''.format(geometry))
394+
raise NotImplementedError(
395+
'unknown ASTRA geometry type {!r}'.format(geometry)
396+
)
384397

385398
if 'astra' not in geometry.implementation_cache:
386399
# Save computed value for later

odl/tomo/geometry/conebeam.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333

3434
class FanBeamGeometry(DivergentBeamGeometry):
35-
3635
"""Fan beam (2d cone beam) geometry.
3736
3837
The source moves on a circle with radius ``src_radius``, and the
@@ -41,7 +40,7 @@ class FanBeamGeometry(DivergentBeamGeometry):
4140
radii can be chosen as 0, which corresponds to a stationary source
4241
or detector, respectively.
4342
44-
The motion parameter is the 1d rotation angle parameterizing source
43+
The motion parameter is the 1d rotation angle that parametrizes source
4544
and detector positions simultaneously.
4645
4746
In the standard configuration, the detector is perpendicular to the
@@ -713,7 +712,6 @@ def __getitem__(self, indices):
713712

714713

715714
class ConeBeamGeometry(DivergentBeamGeometry, AxisOrientedGeometry):
716-
717715
"""Cone beam geometry with circular/helical source curve.
718716
719717
The source moves along a spiral oriented along a fixed ``axis``, with
@@ -1212,7 +1210,7 @@ def det_axes(self, angle):
12121210
12131211
Parameters
12141212
----------
1215-
angles : float or `array-like`
1213+
angle : float or `array-like`
12161214
Angle(s) in radians describing the counter-clockwise rotation
12171215
of the detector around `axis`.
12181216
@@ -1707,7 +1705,7 @@ def cone_beam_geometry(space, src_radius, det_radius, num_angles=None,
17071705
# used here is (w/2)/(rs+rd) = rho/rs since both are equal to tan(alpha),
17081706
# where alpha is the half fan angle.
17091707
rs = float(src_radius)
1710-
if (rs <= rho):
1708+
if rs <= rho:
17111709
raise ValueError('source too close to the object, resulting in '
17121710
'infinite detector for full coverage')
17131711
rd = float(det_radius)
@@ -1749,6 +1747,10 @@ def cone_beam_geometry(space, src_radius, det_radius, num_angles=None,
17491747
det_max_pt = [w / 2, h / 2]
17501748
if det_shape is None:
17511749
det_shape = [num_px_horiz, num_px_vert]
1750+
else:
1751+
raise ValueError(
1752+
'`space.ndim` must be 2 or 3, got {}'.format(space.ndim)
1753+
)
17521754

17531755
fan_angle = 2 * np.arctan(rho / rs)
17541756
if short_scan:
@@ -1877,7 +1879,7 @@ def helical_geometry(space, src_radius, det_radius, num_turns,
18771879
# used here is (w/2)/(rs+rd) = rho/rs since both are equal to tan(alpha),
18781880
# where alpha is the half fan angle.
18791881
rs = float(src_radius)
1880-
if (rs <= rho):
1882+
if rs <= rho:
18811883
raise ValueError('source too close to the object, resulting in '
18821884
'infinite detector for full coverage')
18831885
rd = float(det_radius)
@@ -1925,7 +1927,6 @@ def helical_geometry(space, src_radius, det_radius, num_turns,
19251927

19261928

19271929
class ConeVecGeometry(VecGeometry):
1928-
19291930
"""Cone beam 2D or 3D geometry defined by a collection of vectors.
19301931
19311932
This geometry gives maximal flexibility for representing locations
@@ -1963,6 +1964,8 @@ class ConeVecGeometry(VecGeometry):
19631964
linear paths.
19641965
"""
19651966

1967+
# `rotation_matrix` not implemented; reason: missing
1968+
19661969
@property
19671970
def _slice_src(self):
19681971
"""Slice for the source position part of `vectors`."""
@@ -2055,9 +2058,9 @@ def det_to_src(self, mparam, dparam, normalized=True):
20552058
20562059
Parameters
20572060
----------
2058-
mpar : `motion_params` element
2061+
mparam : `motion_params` element
20592062
Motion parameter at which to evaluate.
2060-
dpar : `det_params` element
2063+
dparam : `det_params` element
20612064
Detector parameter at which to evaluate.
20622065
normalized : bool, optional
20632066
If ``True``, return a normalized (unit) vector.
@@ -2075,8 +2078,10 @@ def det_to_src(self, mparam, dparam, normalized=True):
20752078
raise ValueError('`dparam` {} not in the valid range {}'
20762079
''.format(dparam, self.det_params))
20772080

2078-
vec = (self.src_position(mparam) -
2079-
self.det_point_position(mparam, dparam))
2081+
vec = (
2082+
self.src_position(mparam)
2083+
- self.det_point_position(mparam, dparam)
2084+
)
20802085

20812086
if normalized:
20822087
# axis = -1 allows this to be vectorized

0 commit comments

Comments
 (0)