diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/astra/PyIncludes.pxd | 4 | ||||
| -rw-r--r-- | python/astra/creators.py | 13 | ||||
| -rw-r--r-- | python/astra/data2d_c.pyx | 4 | ||||
| -rw-r--r-- | python/astra/functions.py | 56 | 
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 +  | 
