From 495512324b84a75782f9fbc11921668ad9c170a9 Mon Sep 17 00:00:00 2001 From: "Daniel M. Pelt" Date: Thu, 5 Mar 2015 15:19:43 +0100 Subject: Added Python support for CUDA projectors --- python/astra/creators.py | 66 ++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 41 deletions(-) (limited to 'python/astra/creators.py') diff --git a/python/astra/creators.py b/python/astra/creators.py index 9aba464..2e2dc71 100644 --- a/python/astra/creators.py +++ b/python/astra/creators.py @@ -30,15 +30,16 @@ import math from . import data2d from . import data3d from . import projector +from . import projector3d from . import algorithm def astra_dict(intype): """Creates a dict to use with the ASTRA Toolbox. - + :param intype: Type of the ASTRA object. :type intype: :class:`string` :returns: :class:`dict` -- An ASTRA dict of type ``intype``. - + """ if intype == 'SIRT_CUDA2': intype = 'SIRT_CUDA' @@ -255,25 +256,23 @@ This method can be called in a number of ways: raise Exception('not enough variables: astra_create_proj_geom(parallel3d_vec, det_row_count, det_col_count, V)') if not args[2].shape[1] == 12: raise Exception('V should be a Nx12 matrix, with N the number of projections') - return {'type': 'parallel3d_vec','DetectorRowCount':args[0],'DetectorColCount':args[1],'Vectors':args[2]} + return {'type': 'parallel3d_vec','DetectorRowCount':args[0],'DetectorColCount':args[1],'Vectors':args[2]} elif intype == 'sparse_matrix': if len(args) < 4: raise Exception( 'not enough variables: astra_create_proj_geom(sparse_matrix, det_width, det_count, angles, matrix_id)') return {'type': 'sparse_matrix', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2], 'MatrixID': args[3]} else: - raise Exception('Error: unknown type ' + intype) + raise Exception('Error: unknown type ' + intype) -def create_backprojection(data, proj_id, useCUDA=False, returnData=True): +def create_backprojection(data, proj_id, returnData=True): """Create a backprojection of a sinogram (2D). :param data: Sinogram data or ID. :type data: :class:`numpy.ndarray` or :class:`int` :param proj_id: ID of the projector to use. :type proj_id: :class:`int` -:param useCUDA: If ``True``, use CUDA for the calculation. -:type useCUDA: :class:`bool` :param returnData: If False, only return the ID of the backprojection. :type returnData: :class:`bool` :returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the backprojection. Otherwise, returns a tuple containing the ID of the backprojection and the backprojection itself, in that order. @@ -287,13 +286,13 @@ def create_backprojection(data, proj_id, useCUDA=False, returnData=True): sino_id = data vol_id = data2d.create('-vol', vol_geom, 0) - algString = 'BP' - if useCUDA: - algString = algString + '_CUDA' + if projector.is_cuda(proj_id): + algString = 'BP_CUDA' + else: + algString = 'BP' cfg = astra_dict(algString) - if not useCUDA: - cfg['ProjectorId'] = proj_id + cfg['ProjectorId'] = proj_id cfg['ProjectionDataId'] = sino_id cfg['ReconstructionDataId'] = vol_id alg_id = algorithm.create(cfg) @@ -345,20 +344,13 @@ def create_backprojection3d_gpu(data, proj_geom, vol_geom, returnData=True): return vol_id -def create_sino(data, proj_id=None, proj_geom=None, vol_geom=None, - useCUDA=False, returnData=True, gpuIndex=None): +def create_sino(data, proj_id, returnData=True, gpuIndex=None): """Create a forward projection of an image (2D). :param data: Image data or ID. :type data: :class:`numpy.ndarray` or :class:`int` :param proj_id: ID of the projector to use. :type proj_id: :class:`int` - :param proj_geom: Projection geometry. - :type proj_geom: :class:`dict` - :param vol_geom: Volume geometry. - :type vol_geom: :class:`dict` - :param useCUDA: If ``True``, use CUDA for the calculation. - :type useCUDA: :class:`bool` :param returnData: If False, only return the ID of the forward projection. :type returnData: :class:`bool` :param gpuIndex: Optional GPU index. @@ -374,31 +366,20 @@ def create_sino(data, proj_id=None, proj_geom=None, vol_geom=None, ``proj_geom`` and ``vol_geom``. If ``proj_id`` is given, then ``proj_geom`` and ``vol_geom`` must be None and vice versa. """ - if proj_id is not None: - proj_geom = projector.projection_geometry(proj_id) - vol_geom = projector.volume_geometry(proj_id) - elif proj_geom is not None and vol_geom is not None: - if not useCUDA: - # We need more parameters to create projector. - raise ValueError( - """A ``proj_id`` is needed when CUDA is not used.""") - else: - raise Exception("""The geometry setup is not defined. - The geometry of setup is defined by ``proj_id`` or with - ``proj_geom`` and ``vol_geom``. If ``proj_id`` is given, then - ``proj_geom`` and ``vol_geom`` must be None and vice versa.""") + proj_geom = projector.projection_geometry(proj_id) + vol_geom = projector.volume_geometry(proj_id) if isinstance(data, np.ndarray): volume_id = data2d.create('-vol', vol_geom, data) else: volume_id = data sino_id = data2d.create('-sino', proj_geom, 0) - algString = 'FP' - if useCUDA: - algString = algString + '_CUDA' + if projector.is_cuda(proj_id): + algString = 'FP_CUDA' + else: + algString = 'FP' cfg = astra_dict(algString) - if not useCUDA: - cfg['ProjectorId'] = proj_id + cfg['ProjectorId'] = proj_id if gpuIndex is not None: cfg['option'] = {'GPUindex': gpuIndex} cfg['ProjectionDataId'] = sino_id @@ -496,8 +477,7 @@ def create_reconstruction(rec_type, proj_id, sinogram, iterations=1, use_mask='n vol_geom = projector.volume_geometry(proj_id) recon_id = data2d.create('-vol', vol_geom, 0) cfg = astra_dict(rec_type) - if not 'CUDA' in rec_type: - cfg['ProjectorId'] = proj_id + cfg['ProjectorId'] = proj_id cfg['ProjectionDataId'] = sino_id cfg['ReconstructionDataId'] = recon_id cfg['options'] = {} @@ -560,4 +540,8 @@ def create_projector(proj_type, proj_geom, vol_geom): cfg = astra_dict(proj_type) cfg['ProjectionGeometry'] = proj_geom cfg['VolumeGeometry'] = vol_geom - return projector.create(cfg) + types3d = ['linear3d', 'linearcone', 'cuda3d'] + if proj_type in types3d: + return projector3d.create(cfg) + else: + return projector.create(cfg) -- cgit v1.2.3 From f603045f5bb41de6bc1ffa93badd932b891f5f1d Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 6 Mar 2015 10:58:50 +0100 Subject: Adjust docstring and samples to new python create_sino function --- python/astra/creators.py | 4 ---- samples/python/s001_sinogram_par2d.py | 4 ++-- samples/python/s003_gpu_reconstruction.py | 4 ++-- samples/python/s008_gpu_selection.py | 4 ++-- samples/python/s012_masks.py | 4 ++-- samples/python/s013_constraints.py | 4 ++-- samples/python/s014_FBP.py | 4 ++-- samples/python/s015_fp_bp.py | 14 +++++++------- 8 files changed, 19 insertions(+), 23 deletions(-) (limited to 'python/astra/creators.py') diff --git a/python/astra/creators.py b/python/astra/creators.py index 2e2dc71..68bc8a2 100644 --- a/python/astra/creators.py +++ b/python/astra/creators.py @@ -361,10 +361,6 @@ def create_sino(data, proj_id, returnData=True, gpuIndex=None): projection. Otherwise, returns a tuple containing the ID of the forward projection and the forward projection itself, in that order. - - The geometry of setup is defined by ``proj_id`` or with - ``proj_geom`` and ``vol_geom``. If ``proj_id`` is given, then - ``proj_geom`` and ``vol_geom`` must be None and vice versa. """ proj_geom = projector.projection_geometry(proj_id) vol_geom = projector.volume_geometry(proj_id) diff --git a/samples/python/s001_sinogram_par2d.py b/samples/python/s001_sinogram_par2d.py index 009d9b3..1d1b912 100644 --- a/samples/python/s001_sinogram_par2d.py +++ b/samples/python/s001_sinogram_par2d.py @@ -43,8 +43,8 @@ P = scipy.io.loadmat('phantom.mat')['phantom256'] # Create a sinogram using the GPU. # Note that the first time the GPU is accessed, there may be a delay # of up to 10 seconds for initialization. -proj_id = astra.create_projector('line',proj_geom,vol_geom) -sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) +proj_id = astra.create_projector('cuda',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id) import pylab pylab.gray() diff --git a/samples/python/s003_gpu_reconstruction.py b/samples/python/s003_gpu_reconstruction.py index 4f6ec1f..07b38ef 100644 --- a/samples/python/s003_gpu_reconstruction.py +++ b/samples/python/s003_gpu_reconstruction.py @@ -33,8 +33,8 @@ proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180 # As before, create a sinogram from a phantom import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] -proj_id = astra.create_projector('line',proj_geom,vol_geom) -sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) +proj_id = astra.create_projector('cuda',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id) import pylab pylab.gray() diff --git a/samples/python/s008_gpu_selection.py b/samples/python/s008_gpu_selection.py index c42e53b..a180802 100644 --- a/samples/python/s008_gpu_selection.py +++ b/samples/python/s008_gpu_selection.py @@ -32,10 +32,10 @@ proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180 import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] -proj_id = astra.create_projector('line',proj_geom,vol_geom) +proj_id = astra.create_projector('cuda',proj_geom,vol_geom) # Create a sinogram from a phantom, using GPU #1. (The default is #0) -sinogram_id, sinogram = astra.create_sino(P, proj_id, useCUDA=True, gpuIndex=1) +sinogram_id, sinogram = astra.create_sino(P, proj_id, gpuIndex=1) # Set up the parameters for a reconstruction algorithm using the GPU diff --git a/samples/python/s012_masks.py b/samples/python/s012_masks.py index 441d11b..0f667b0 100644 --- a/samples/python/s012_masks.py +++ b/samples/python/s012_masks.py @@ -48,8 +48,8 @@ proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,50, # As before, create a sinogram from a phantom import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] -proj_id = astra.create_projector('line',proj_geom,vol_geom) -sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) +proj_id = astra.create_projector('cuda',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id) pylab.figure(2) pylab.imshow(P) diff --git a/samples/python/s013_constraints.py b/samples/python/s013_constraints.py index 009360e..8b63d5e 100644 --- a/samples/python/s013_constraints.py +++ b/samples/python/s013_constraints.py @@ -36,8 +36,8 @@ proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,50, # As before, create a sinogram from a phantom import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] -proj_id = astra.create_projector('line',proj_geom,vol_geom) -sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) +proj_id = astra.create_projector('cuda',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id) import pylab pylab.gray() diff --git a/samples/python/s014_FBP.py b/samples/python/s014_FBP.py index ef4afc2..2f8e388 100644 --- a/samples/python/s014_FBP.py +++ b/samples/python/s014_FBP.py @@ -33,8 +33,8 @@ proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180 # As before, create a sinogram from a phantom import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] -proj_id = astra.create_projector('line',proj_geom,vol_geom) -sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) +proj_id = astra.create_projector('cuda',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id) import pylab pylab.gray() diff --git a/samples/python/s015_fp_bp.py b/samples/python/s015_fp_bp.py index 10c238d..fa0bf86 100644 --- a/samples/python/s015_fp_bp.py +++ b/samples/python/s015_fp_bp.py @@ -26,8 +26,8 @@ # This example demonstrates using the FP and BP primitives with Matlab's lsqr -# solver. Calls to FP (astra_create_sino_cuda) and -# BP (astra_create_backprojection_cuda) are wrapped in a function astra_wrap, +# solver. Calls to FP (astra.create_sino) and +# BP (astra.create_backprojection) are wrapped in a function astra_wrap, # and a handle to this function is passed to lsqr. # Because in this case the inputs/outputs of FP and BP have to be vectors @@ -39,17 +39,17 @@ import numpy as np # FP/BP wrapper class class astra_wrap(object): def __init__(self,proj_geom,vol_geom): - self.proj_id = astra.create_projector('line',proj_geom,vol_geom) + self.proj_id = astra.create_projector('cuda',proj_geom,vol_geom) self.shape = (proj_geom['DetectorCount']*len(proj_geom['ProjectionAngles']),vol_geom['GridColCount']*vol_geom['GridRowCount']) self.dtype = np.float def matvec(self,v): - sid, s = astra.create_sino(np.reshape(v,(vol_geom['GridRowCount'],vol_geom['GridColCount'])),self.proj_id,useCUDA=True) + sid, s = astra.create_sino(np.reshape(v,(vol_geom['GridRowCount'],vol_geom['GridColCount'])),self.proj_id) astra.data2d.delete(sid) return s.flatten() def rmatvec(self,v): - bid, b = astra.create_backprojection(np.reshape(v,(len(proj_geom['ProjectionAngles']),proj_geom['DetectorCount'],)),self.proj_id,useCUDA=True) + bid, b = astra.create_backprojection(np.reshape(v,(len(proj_geom['ProjectionAngles']),proj_geom['DetectorCount'],)),self.proj_id) astra.data2d.delete(bid) return b.flatten() @@ -61,8 +61,8 @@ import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] # Create a sinogram using the GPU. -proj_id = astra.create_projector('line',proj_geom,vol_geom) -sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) +proj_id = astra.create_projector('cuda',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id) # Reshape the sinogram into a vector b = sinogram.flatten() -- cgit v1.2.3