summaryrefslogtreecommitdiffstats
path: root/python/astra
diff options
context:
space:
mode:
Diffstat (limited to 'python/astra')
-rw-r--r--python/astra/PyIncludes.pxd4
-rw-r--r--python/astra/creators.py13
-rw-r--r--python/astra/data2d_c.pyx4
-rw-r--r--python/astra/functions.py56
4 files changed, 76 insertions, 1 deletions
diff --git a/python/astra/PyIncludes.pxd b/python/astra/PyIncludes.pxd
index 4a4ce43..61425c9 100644
--- a/python/astra/PyIncludes.pxd
+++ b/python/astra/PyIncludes.pxd
@@ -128,6 +128,10 @@ cdef extern from "astra/FanFlatVecProjectionGeometry2D.h" namespace "astra":
cdef cppclass CFanFlatVecProjectionGeometry2D:
CFanFlatVecProjectionGeometry2D()
+cdef extern from "astra/ParallelVecProjectionGeometry2D.h" namespace "astra":
+ cdef cppclass CParallelVecProjectionGeometry2D:
+ CParallelVecProjectionGeometry2D()
+
cdef extern from "astra/ParallelProjectionGeometry2D.h" namespace "astra":
cdef cppclass CParallelProjectionGeometry2D:
CParallelProjectionGeometry2D()
diff --git a/python/astra/creators.py b/python/astra/creators.py
index 18504ea..82fd9d1 100644
--- a/python/astra/creators.py
+++ b/python/astra/creators.py
@@ -155,6 +155,13 @@ This method can be called in a number of ways:
:type angles: :class:`numpy.ndarray`
:returns: A parallel projection geometry.
+``create_proj_geom('parallel_vec', det_count, V)``:
+
+:param det_count: Number of detector pixels.
+:type det_count: :class:`int`
+:param V: Vector array.
+:type V: :class:`numpy.ndarray`
+:returns: A parallel-beam projection geometry.
``create_proj_geom('fanflat', det_width, det_count, angles, source_origin, origin_det)``:
@@ -242,6 +249,12 @@ This method can be called in a number of ways:
raise Exception(
'not enough variables: astra_create_proj_geom(parallel, detector_spacing, det_count, angles)')
return {'type': 'parallel', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2]}
+ elif intype == 'parallel_vec':
+ if len(args) < 2:
+ raise Exception('not enough variables: astra_create_proj_geom(parallel_vec, det_count, V)')
+ if not args[1].shape[1] == 6:
+ raise Exception('V should be a Nx6 matrix, with N the number of projections')
+ return {'type':'parallel_vec', 'DetectorCount':args[0], 'Vectors':args[1]}
elif intype == 'fanflat':
if len(args) < 5:
raise Exception('not enough variables: astra_create_proj_geom(fanflat, det_width, det_count, angles, source_origin, origin_det)')
diff --git a/python/astra/data2d_c.pyx b/python/astra/data2d_c.pyx
index 65e80ce..2242d3b 100644
--- a/python/astra/data2d_c.pyx
+++ b/python/astra/data2d_c.pyx
@@ -109,6 +109,8 @@ def create(datatype, geometry, data=None, link=False):
ppGeometry = <CProjectionGeometry2D * >new CFanFlatProjectionGeometry2D()
elif (tpe == 'fanflat_vec'):
ppGeometry = <CProjectionGeometry2D * >new CFanFlatVecProjectionGeometry2D()
+ elif (tpe == 'parallel_vec'):
+ ppGeometry = <CProjectionGeometry2D * >new CParallelVecProjectionGeometry2D()
else:
ppGeometry = <CProjectionGeometry2D * >new CParallelProjectionGeometry2D()
if not ppGeometry.initialize(cfg[0]):
@@ -222,6 +224,8 @@ def change_geometry(i, geom):
ppGeometry = <CProjectionGeometry2D * >new CFanFlatProjectionGeometry2D()
elif (tpe == 'fanflat_vec'):
ppGeometry = <CProjectionGeometry2D * >new CFanFlatVecProjectionGeometry2D()
+ elif (tpe == 'parallel_vec'):
+ ppGeometry = <CProjectionGeometry2D * >new CParallelVecProjectionGeometry2D()
else:
ppGeometry = <CProjectionGeometry2D * >new CParallelProjectionGeometry2D()
if not ppGeometry.initialize(cfg[0]):
diff --git a/python/astra/functions.py b/python/astra/functions.py
index 3f4aa82..9927eee 100644
--- a/python/astra/functions.py
+++ b/python/astra/functions.py
@@ -172,7 +172,27 @@ def geom_2vec(proj_geom):
:param proj_geom: Projection geometry to convert
:type proj_geom: :class:`dict`
"""
- if proj_geom['type'] == 'fanflat':
+
+ if proj_geom['type'] == 'parallel':
+ angles = proj_geom['ProjectionAngles']
+ vectors = np.zeros((len(angles), 6))
+ for i in range(len(angles)):
+
+ # source
+ vectors[i, 0] = np.sin(angles[i])
+ vectors[i, 1] = -np.cos(angles[i])
+
+ # center of detector
+ vectors[i, 2] = 0
+ vectors[i, 3] = 0
+
+ # vector from detector pixel 0 to 1
+ vectors[i, 4] = np.cos(angles[i]) * proj_geom['DetectorWidth']
+ vectors[i, 5] = np.sin(angles[i]) * proj_geom['DetectorWidth']
+ proj_geom_out = ac.create_proj_geom(
+ 'parallel_vec', proj_geom['DetectorCount'], vectors)
+
+ elif proj_geom['type'] == 'fanflat':
angles = proj_geom['ProjectionAngles']
vectors = np.zeros((len(angles), 6))
for i in range(len(angles)):
@@ -251,3 +271,37 @@ def geom_2vec(proj_geom):
raise ValueError(
'No suitable vector geometry found for type: ' + proj_geom['type'])
return proj_geom_out
+
+
+def geom_postalignment(proj_geom, factor):
+ """Returns the size of a volume or sinogram, based on the projection or volume geometry.
+
+ :param proj_geom: input projection geometry (vector-based only, use astra.geom_2vec to convert conventional projection geometries)
+ :type proj_geom: :class:`dict`
+ :param factor: Optional axis index to return
+ :type factor: :class:`float`
+ """
+
+ if proj_geom['type'] == 'parallel_vec' or proj_geom['type'] == 'fanflat_vec':
+ for i in range(proj_geom['Vectors'].shape[0]):
+ proj_geom['Vectors'][i,2] = proj_geom['Vectors'][i,2] + factor * proj_geom['Vectors'][i,4];
+ proj_geom['Vectors'][i,3] = proj_geom['Vectors'][i,3] + factor * proj_geom['Vectors'][i,5];
+
+ elif proj_geom['type'] == 'parallel3d_vec' or proj_geom['type'] == 'cone_vec':
+
+ if len(factor) == 1:
+ for i in range(proj_geom['Vectors'].shape[0]):
+ proj_geom['Vectors'][i,3] = proj_geom['Vectors'][i,3] + factor * proj_geom['Vectors'][i,6];
+ proj_geom['Vectors'][i,4] = proj_geom['Vectors'][i,4] + factor * proj_geom['Vectors'][i,7];
+ proj_geom['Vectors'][i,5] = proj_geom['Vectors'][i,5] + factor * proj_geom['Vectors'][i,8];
+
+ elif len(factor) > 1:
+ for i in range(proj_geom['Vectors'].shape[0]):
+ proj_geom['Vectors'][i,3] = proj_geom['Vectors'][i,3] + factor[0] * proj_geom['Vectors'][i,6] + factor[1] * proj_geom['Vectors'][i, 9];
+ proj_geom['Vectors'][i,4] = proj_geom['Vectors'][i,4] + factor[0] * proj_geom['Vectors'][i,7] + factor[1] * proj_geom['Vectors'][i,10];
+ proj_geom['Vectors'][i,5] = proj_geom['Vectors'][i,5] + factor[0] * proj_geom['Vectors'][i,8] + factor[1] * proj_geom['Vectors'][i,11];
+ else:
+ raise ValueError('No suitable geometry for postalignment: ' + proj_geom['type'])
+
+ return proj_geom
+