Skip to content

Commit 1ca6fed

Browse files
committed
WIP: simplify index interpolation to rounding
1 parent 40dadda commit 1ca6fed

File tree

6 files changed

+255
-166
lines changed

6 files changed

+255
-166
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: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2014-2019 The ODL contributors
1+
# Copyright 2014-2020 The ODL contributors
22
#
33
# This file is part of ODL.
44
#
@@ -17,7 +17,8 @@
1717
astra_algorithm, astra_data, astra_projection_geometry, astra_projector,
1818
astra_volume_geometry)
1919
from odl.tomo.geometry import (
20-
DivergentBeamGeometry, Geometry, ParallelBeamGeometry)
20+
ConeVecGeometry, DivergentBeamGeometry, Geometry, ParallelBeamGeometry,
21+
ParallelVecGeometry)
2122
from odl.util import writable_array
2223

2324
try:
@@ -49,20 +50,28 @@ def default_astra_proj_type(geom):
4950
5051
- `ParallelBeamGeometry`: ``'linear'``
5152
- `DivergentBeamGeometry`: ``'line_fanflat'``
53+
- `ParallelVecGeometry`: ``'linear'``
54+
- `ConeVecGeometry`: ``'line_fanflat'``
5255
5356
In 3D:
5457
5558
- `ParallelBeamGeometry`: ``'linear3d'``
5659
- `DivergentBeamGeometry`: ``'linearcone'``
60+
- `ParallelVecGeometry`: ``'linear3d'``
61+
- `ConeVecGeometry`: ``'linearcone'``
5762
"""
5863
if isinstance(geom, ParallelBeamGeometry):
5964
return 'linear' if geom.ndim == 2 else 'linear3d'
6065
elif isinstance(geom, DivergentBeamGeometry):
6166
return 'line_fanflat' if geom.ndim == 2 else 'linearcone'
67+
elif isinstance(geom, ParallelVecGeometry):
68+
return 'linear' if geom.ndim == 2 else 'linear3d'
69+
elif isinstance(geom, ConeVecGeometry):
70+
return 'line_fanflat' if geom.ndim == 2 else 'linearcone'
6271
else:
6372
raise TypeError(
64-
'no default exists for {}, `astra_proj_type` must be given explicitly'
65-
''.format(type(geom))
73+
'no default exists for {}, `astra_proj_type` must be given '
74+
'explicitly'.format(type(geom))
6675
)
6776

6877

odl/tomo/backends/astra_setup.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2014-2019 The ODL contributors
1+
# Copyright 2014-2020 The ODL contributors
22
#
33
# This file is part of ODL.
44
#
@@ -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: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2014-2019 The ODL contributors
1+
# Copyright 2014-2020 The ODL contributors
22
#
33
# This file is part of ODL.
44
#
@@ -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
@@ -592,7 +591,6 @@ def __getitem__(self, indices):
592591

593592

594593
class ConeBeamGeometry(DivergentBeamGeometry, AxisOrientedGeometry):
595-
596594
"""Cone beam geometry with circular/helical source curve.
597595
598596
The source moves along a spiral oriented along a fixed ``axis``, with
@@ -1034,7 +1032,7 @@ def det_axes(self, angle):
10341032
10351033
Parameters
10361034
----------
1037-
angles : float or `array-like`
1035+
angle : float or `array-like`
10381036
Angle(s) in radians describing the counter-clockwise rotation
10391037
of the detector around `axis`.
10401038
@@ -1466,7 +1464,7 @@ def cone_beam_geometry(space, src_radius, det_radius, num_angles=None,
14661464
# used here is (w/2)/(rs+rd) = rho/rs since both are equal to tan(alpha),
14671465
# where alpha is the half fan angle.
14681466
rs = float(src_radius)
1469-
if (rs <= rho):
1467+
if rs <= rho:
14701468
raise ValueError('source too close to the object, resulting in '
14711469
'infinite detector for full coverage')
14721470
rd = float(det_radius)
@@ -1508,6 +1506,10 @@ def cone_beam_geometry(space, src_radius, det_radius, num_angles=None,
15081506
det_max_pt = [w / 2, h / 2]
15091507
if det_shape is None:
15101508
det_shape = [num_px_horiz, num_px_vert]
1509+
else:
1510+
raise ValueError(
1511+
'`space.ndim` must be 2 or 3, got {}'.format(space.ndim)
1512+
)
15111513

15121514
fan_angle = 2 * np.arctan(rho / rs)
15131515
if short_scan:
@@ -1636,7 +1638,7 @@ def helical_geometry(space, src_radius, det_radius, num_turns,
16361638
# used here is (w/2)/(rs+rd) = rho/rs since both are equal to tan(alpha),
16371639
# where alpha is the half fan angle.
16381640
rs = float(src_radius)
1639-
if (rs <= rho):
1641+
if rs <= rho:
16401642
raise ValueError('source too close to the object, resulting in '
16411643
'infinite detector for full coverage')
16421644
rd = float(det_radius)
@@ -1684,7 +1686,6 @@ def helical_geometry(space, src_radius, det_radius, num_turns,
16841686

16851687

16861688
class ConeVecGeometry(VecGeometry):
1687-
16881689
"""Cone beam 2D or 3D geometry defined by a collection of vectors.
16891690
16901691
This geometry gives maximal flexibility for representing locations
@@ -1722,6 +1723,8 @@ class ConeVecGeometry(VecGeometry):
17221723
linear paths.
17231724
"""
17241725

1726+
# `rotation_matrix` not implemented; reason: missing
1727+
17251728
@property
17261729
def _slice_src(self):
17271730
"""Slice for the source position part of `vectors`."""
@@ -1814,9 +1817,9 @@ def det_to_src(self, mparam, dparam, normalized=True):
18141817
18151818
Parameters
18161819
----------
1817-
mpar : `motion_params` element
1820+
mparam : `motion_params` element
18181821
Motion parameter at which to evaluate.
1819-
dpar : `det_params` element
1822+
dparam : `det_params` element
18201823
Detector parameter at which to evaluate.
18211824
normalized : bool, optional
18221825
If ``True``, return a normalized (unit) vector.
@@ -1834,8 +1837,10 @@ def det_to_src(self, mparam, dparam, normalized=True):
18341837
raise ValueError('`dparam` {} not in the valid range {}'
18351838
''.format(dparam, self.det_params))
18361839

1837-
vec = (self.src_position(mparam) -
1838-
self.det_point_position(mparam, dparam))
1840+
vec = (
1841+
self.src_position(mparam)
1842+
- self.det_point_position(mparam, dparam)
1843+
)
18391844

18401845
if normalized:
18411846
# axis = -1 allows this to be vectorized

0 commit comments

Comments
 (0)