def __init__(self, volume_geometry=None, sinogram_geometry=None, proj_id=None, device='cpu'): kwargs = { 'volume_geometry' : volume_geometry, 'sinogram_geometry' : sinogram_geometry, 'proj_id' : proj_id, 'device' : device } #DataProcessor.__init__(self, **kwargs) super(AstraForwardProjector, self).__init__(**kwargs) self.set_ImageGeometry(volume_geometry) self.set_AcquisitionGeometry(sinogram_geometry) # Set up ASTRA Volume and projection geometry, not to be stored in self vol_geom, proj_geom = convert_geometry_to_astra(self.volume_geometry, self.sinogram_geometry) # ASTRA projector, to be stored if device == 'cpu': # Note that 'line' only one option if self.sinogram_geometry.geom_type == 'parallel': self.set_projector(astra.create_projector('line', proj_geom, vol_geom) ) elif self.sinogram_geometry.geom_type == 'cone': self.set_projector(astra.create_projector('line_fanflat', proj_geom, vol_geom) ) else: NotImplemented elif device == 'gpu': self.set_projector(astra.create_projector('cuda', proj_geom, vol_geom) ) else: NotImplemented
def __init__(self, data_root_path, folder, geo_full, geo_sparse, pre_trans_img=None, Dataset_name="test"): self.Dataset_name = Dataset_name self.geo_full = geo_full self.geo_sparse = geo_sparse self.imgset = BasicData(data_root_path, folder, self.geo_full["nVoxelX"], pre_trans_img, Dataset_name) ## Full----------------------------------------- self.vol_geom_full = astra.create_vol_geom(self.geo_full["nVoxelY"], self.geo_full["nVoxelX"], -1*self.geo_full["sVoxelY"]/2, self.geo_full["sVoxelY"]/2, -1*self.geo_full["sVoxelX"]/2, self.geo_full["sVoxelX"]/2) self.proj_geom_full = astra.create_proj_geom(self.geo_full["mode"], self.geo_full["dDetecU"], self.geo_full["nDetecU"], np.linspace(self.geo_full["start_angle"], self.geo_full["end_angle"], self.geo_full["sino_views"],False), self.geo_full["DSO"], self.geo_full["DOD"]) if self.geo_full["mode"] is "parallel": self.proj_id_full = astra.create_projector("linear", self.proj_geom_full, self.vol_geom_full) elif self.geo_full["mode"] is "fanflat": self.proj_id_full = astra.create_projector("line_fanflat", self.proj_geom_full, self.vol_geom_full) ## Sparse----------------------------------------- self.vol_geom_sparse = astra.create_vol_geom(self.geo_sparse["nVoxelY"], self.geo_sparse["nVoxelX"], -1*self.geo_sparse["sVoxelY"]/2, self.geo_sparse["sVoxelY"]/2, -1*self.geo_sparse["sVoxelX"]/2, self.geo_sparse["sVoxelX"]/2) self.proj_geom_sparse = astra.create_proj_geom(self.geo_sparse["mode"], self.geo_sparse["dDetecU"], self.geo_sparse["nDetecU"], np.linspace(self.geo_sparse["start_angle"], self.geo_sparse["end_angle"], self.geo_sparse["sino_views"],False), self.geo_sparse["DSO"], self.geo_sparse["DOD"]) if self.geo_sparse["mode"] is "parallel": self.proj_id_sparse = astra.create_projector("linear", self.proj_geom_sparse, self.vol_geom_sparse) elif self.geo_sparse["mode"] is "fanflat": self.proj_id_sparse = astra.create_projector("line_fanflat", self.proj_geom_sparse, self.vol_geom_sparse)
def __init__(self, DetectorsDim, AnglesVec, CenterRotOffset, ObjSize, device): self.DetectorsDim = DetectorsDim self.AnglesVec = AnglesVec self.ObjSize = ObjSize if CenterRotOffset is None: 'scalar geometry since parallel_vec is not implemented for CPU ASTRA modules yet?' self.proj_geom = astra.create_proj_geom('parallel', 1.0, DetectorsDim, AnglesVec) else: # define astra vector geometry (default) vectors = vec_geom_init2D(AnglesVec, 1.0, CenterRotOffset) self.proj_geom = astra.create_proj_geom('parallel_vec', DetectorsDim, vectors) self.vol_geom = astra.create_vol_geom(ObjSize, ObjSize) if device == 'cpu': self.proj_id = astra.create_projector('line', self.proj_geom, self.vol_geom) # for CPU self.device = 1 elif device == 'gpu': self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom) # for GPU self.device = 0 else: print("Select between 'cpu' or 'gpu' for device") # add optomo operator self.A_optomo = astra.OpTomo(self.proj_id)
def initialize(self): """Initialize the ASTRA projectors.""" if not self.is_initialized: if self.is_3d: projector_type = "cuda3d" else: if has_cuda: projector_type = "cuda" else: projector_type = "linear" opts = { "VoxelSuperSampling": self.super_sampling, "DetectorSuperSampling": self.super_sampling } if self.has_individual_projs: self.proj_id = [ astra.create_projector(projector_type, pg, self.vol_geom, opts) for pg in self.proj_geom_ind ] self.W_ind = [astra.OpTomo(p_id) for p_id in self.proj_id] self.proj_id.append( astra.create_projector(projector_type, self.proj_geom_all, self.vol_geom, opts)) self.W_all = astra.OpTomo(self.proj_id[-1]) super().initialize()
def fbp(sinogram, geo): vol_geom = astra.create_vol_geom(geo["nVoxelY"], geo["nVoxelX"], -1 * geo["sVoxelY"] / 2, geo["sVoxelY"] / 2, -1 * geo["sVoxelX"] / 2, geo["sVoxelX"] / 2) proj_geom = astra.create_proj_geom( geo["mode"], geo["dDetecU"], geo["nDetecU"], np.linspace(geo["start_angle"], geo["end_angle"], geo["sino_views"], False), geo["DSO"], geo["DOD"]) if geo["mode"] is "parallel": proj_id = astra.create_projector("linear", proj_geom, vol_geom) elif geo["mode"] is "fanflat": proj_id = astra.create_projector("line_fanflat", proj_geom_full, vol_geom) rec_id = astra.data2d.create('-vol', vol_geom) sinogram_id = astra.data2d.create('-sino', proj_geom, sinogram) cfg = astra.astra_dict('FBP') cfg['ProjectorId'] = proj_id cfg["FilterType"] = "Ram-Lak" cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id) image_recon = astra.data2d.get(rec_id) astra.algorithm.delete(alg_id) astra.data2d.delete(rec_id) astra.data2d.delete(sinogram_id) return image_recon
def __init__(self, DetectorsDim, AnglesVec, ObjSize, OS, device): self.DetectorsDim = DetectorsDim self.AnglesVec = AnglesVec self.ObjSize = ObjSize ################ arrange ordered-subsets ################ import numpy as np AnglesTot = np.size(AnglesVec) # total number of angles self.NumbProjBins = (int)(np.ceil( float(AnglesTot) / float(OS))) # get the number of projections per bin (subset) self.newInd_Vec = np.zeros( [OS, self.NumbProjBins], dtype='int') # 2D array of OS-sorted indeces for sub_ind in range(OS): ind_sel = 0 for proj_ind in range(self.NumbProjBins): indexS = ind_sel + sub_ind if (indexS < AnglesTot): self.newInd_Vec[sub_ind, proj_ind] = indexS ind_sel += OS # create full ASTRA geometry (to calculate Lipshitz constant) self.proj_geom = astra.create_proj_geom('parallel', 1.0, DetectorsDim, AnglesVec) self.vol_geom = astra.create_vol_geom(ObjSize, ObjSize) if device == 'cpu': self.proj_id = astra.create_projector('line', self.proj_geom, self.vol_geom) # for CPU self.device = 1 elif device == 'gpu': self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom) # for GPU self.device = 0 else: print("Select between 'cpu' or 'gpu' for device") # create OS-specific ASTRA geometry self.proj_geom_OS = {} self.proj_id_OS = {} for sub_ind in range(OS): self.indVec = self.newInd_Vec[sub_ind, :] # OS-specific indices if (self.indVec[self.NumbProjBins - 1] == 0): self.indVec = self.indVec[:-1] #shrink vector size anglesOS = self.AnglesVec[self.indVec] # OS-specific angles self.proj_geom_OS[sub_ind] = astra.create_proj_geom( 'parallel', 1.0, DetectorsDim, anglesOS) if self.device == 1: self.proj_id_OS[sub_ind] = astra.create_projector( 'line', self.proj_geom_OS[sub_ind], self.vol_geom) # for CPU if self.device == 0: self.proj_id_OS[sub_ind] = astra.create_projector( 'cuda', self.proj_geom_OS[sub_ind], self.vol_geom) # for GPU
def project(image, geo): vol_geom = astra.create_vol_geom(geo["nVoxelY"], geo["nVoxelX"], -1*geo["sVoxelY"]/2, geo["sVoxelY"]/2, -1*geo["sVoxelX"]/2, geo["sVoxelX"]/2) proj_geom = astra.create_proj_geom(geo["mode"], geo["dDetecU"], geo["nDetecU"], np.linspace(geo["start_angle"], geo["end_angle"], geo["sino_views"],False), geo["DSO"], geo["DOD"]) if geo["mode"] is "parallel": proj_id = astra.create_projector("linear", proj_geom, vol_geom) elif geo["mode"] is "fanflat": proj_id = astra.create_projector("line_fanflat", proj_geom, vol_geom) sinogram_id, sino = astra.create_sino(image, proj_id) astra.data2d.delete(sinogram_id) sinogram = copy.deepcopy(sino) return sinogram
def bp0(sino, det_col=111, num_angles=222, voxel_size_mm=1): """Wrapper for astra forward projector :param sino: :param projector_id: :return: backprojected sinogram """ vol_geom = astra.create_vol_geom(sino.shape) proj_id = astra.create_projector( 'cuda', astra.create_proj_geom('parallel', 1.0, det_col, np.linspace(0, np.pi, num_angles, False)), vol_geom) rec_id, backprojection = astra.create_backprojection(sino * voxel_size_mm, proj_id) # rec_id, backprojection = astra.create_backprojection(sino, projector_id) # backprojection /= sino.shape[0] # backprojection *= np.pi astra.data2d.delete(rec_id) astra.projector.delete(proj_id) return backprojection
def pid(number_of_angles): """Return projector ID. :param number_of_angles: :return: """ return astra.create_projector('cuda', astra.create_proj_geom('parallel', 1.0, vshape[0], np.linspace(0, np.pi, number_of_angles, False)), vol_geom)
def run_soft_ineq(data, name, alpha, bound): d_pr, M, m = check_bounds(data['data'], bound, 0) pixel_size = 1.0 proj_geom = astra.create_proj_geom( 'parallel', pixel_size, d_pr.shape[1], data['angles'] ) rec_pix = d_pr.shape[1] vol_geom = astra.create_vol_geom(rec_pix, rec_pix) projector = astra.create_projector('linear', proj_geom, vol_geom) res = ineq_linear_least_squares(1.0, proj_geom, vol_geom, np.exp(-d_pr), projector, np.exp(-bound), alpha) plt.figure() plt.imshow(res, cmap=plt.cm.viridis) plt.colorbar(orientation='horizontal') name_suffix = '%s_a%.1f' % (name, alpha) plt.title("%s, alpha %.1f" % (name, alpha)) plt.savefig('soft_ineq_' + name_suffix + '.png') # plt.show(block=False) np.savetxt(name_suffix, res)
def run_fbp(data, bound): d_pr, M, m = check_bounds(data['data'], bound, 0) pixel_size = 1.0 proj_geom = astra.create_proj_geom( 'parallel', pixel_size, d_pr.shape[1], data['angles'] ) rec_pix = d_pr.shape[1] vol_geom = astra.create_vol_geom(rec_pix, rec_pix) projector = astra.create_projector('linear', proj_geom, vol_geom) res = fbp(1.0, proj_geom, vol_geom, np.exp(-d_pr), projector, np.exp(-bound)) plt.figure() plt.imshow(res, cmap=plt.cm.viridis) plt.colorbar(orientation='vertical') name_suffix = 'FBP' plt.title("FBP") plt.savefig(name_suffix + '.png') np.savetxt(name_suffix, res) return res
def recon_sirt_fbp(im, angles, iter, temppath ): """Reconstruct a sinogram with the SIRT-FBP algorithm (Pelt, 2015). Parameters ---------- im : array_like Sinogram image data as numpy array. iter : int Number of iterations to be used for the computation of SIRT filter. angles : double Value in radians representing the number of angles of the input sinogram. """ # Create ASTRA geometries: vol_geom = astra.create_vol_geom(im.shape[1] , im.shape[1]) proj_geom = astra.create_proj_geom('parallel', 1.0, im.shape[1], linspace(0,angles,im.shape[0],False)) proj = astra.create_projector('cuda', proj_geom, vol_geom) p = astra.OpTomo(proj) # Register plugin with ASTRA astra.plugin.register(sirtfbp.plugin) # Create the ASTRA projector im_rec = p.reconstruct('SIRT-FBP',im, iter, extraOptions={'filter_dir':temppath}) return im_rec.astype(float32)
def __init__(self, angles, img_size, det_count, sdist, ddist, det_spacing): self.angles = angles self.vol_geom = astra.create_vol_geom(img_size, img_size) self.proj_geom = astra.create_proj_geom('fanflat', det_spacing, det_count, self.angles, sdist, ddist) self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom) self.data2d = []
def fdk(proj_data, vol_geom, proj_geom): vol_id = astra.data3d.create('-vol', vol_geom) proj_id = astra.data3d.create('-sino', proj_geom, proj_data) projector = astra.create_projector("cuda3d", proj_geom, vol_geom) astra.experimental.accumulate_FDK(projector, vol_id, proj_id) return vol_id, astra.data3d.get_shared(vol_id)
def K(x: np.array) -> np.array: # Create sinogram. proj_id = astra.create_projector(proj_type, proj_geom, vol_geom) sino_id, sino = astra.create_sino(x, proj_id) astra.data2d.delete(sino_id) astra.projector.delete(proj_id) return sino
def bp0(sino, det_col=111, num_angles=222, voxel_size_mm=1): """Wrapper for astra forward projector :param sino: :param projector_id: :return: backprojected sinogram """ vol_geom = astra.create_vol_geom(sino.shape) proj_id = astra.create_projector( 'cuda', astra.create_proj_geom('parallel', 1.0, det_col, np.linspace(0, np.pi, num_angles, False)), vol_geom) rec_id, backprojection = astra.create_backprojection( sino * voxel_size_mm, proj_id) # rec_id, backprojection = astra.create_backprojection(sino, projector_id) # backprojection /= sino.shape[0] # backprojection *= np.pi astra.data2d.delete(rec_id) astra.projector.delete(proj_id) return backprojection
def _managed_recon(sino, cfg, proj_geom, vol_geom) -> Generator[Tuple[int, int], None, None]: proj_id = None sino_id = None rec_id = None alg_id = None try: proj_id = astra.create_projector('cuda', proj_geom, vol_geom) sino_id = astra.data2d.create('-sino', proj_geom, sino) rec_id = astra.data2d.create('-vol', vol_geom) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sino_id cfg['ProjectorId'] = proj_id alg_id = astra.algorithm.create(cfg) yield alg_id, rec_id finally: if alg_id: astra.algorithm.delete(alg_id) if proj_id: astra.projector.delete(proj_id) if sino_id: astra.data2d.delete(sino_id) if rec_id: astra.data2d.delete(rec_id)
def full_reconstruct(p): # Create geometries and projector. vol_geom = astra.create_vol_geom(128, 128) angles = np.linspace(0, np.pi, 180, endpoint=False) proj_geom = astra.create_proj_geom('parallel', 1., 128, angles) projector_id = astra.create_projector('linear', proj_geom, vol_geom) # Create sinogram. sinogram_id, sinogram = astra.create_sino(p, projector_id) # Create reconstruction. reconstruction_id = astra.data2d.create('-vol', vol_geom) cfg = astra.astra_dict('FBP') cfg['ReconstructionDataId'] = reconstruction_id cfg['ProjectionDataId'] = sinogram_id cfg['ProjectorId'] = projector_id cfg['option'] = {} cfg['option']['MinConstraint'] = 0. # Force solution to be nonnegative. algorithm_id = astra.algorithm.create(cfg) astra.algorithm.run(algorithm_id, 100) # 100 iterations. reconstruction = astra.data2d.get(reconstruction_id) return reconstruction # Cleanup. astra.algorithm.delete(algorithm_id) astra.data2d.delete(reconstruction_id) astra.data2d.delete(sinogram_id) astra.projector.delete(projector_id)
def run(self, iterations): self.fn = getFilterFile(self.fd, self.pg, iterations, self.rg, self.osz) if os.path.exists(self.fn): flt = np.load(self.fn) self.v[:] = self.customFBP(flt) return nd = self.nd if self.osz: nds = self.osz else: nds = nd na = len(self.ang) pgc = astra.create_proj_geom('parallel',1.0,nd,self.ang) vgc = astra.create_vol_geom((nds,nds)) pidc = astra.create_projector('strip',pgc,vgc) x = np.zeros((nds,nds)) xs = np.zeros((nds,nds)) sf = np.zeros((na,nd)) vid = astra.data2d.create('-vol',vgc) sid = astra.data2d.create('-sino',pgc) cfg = astra.astra_dict('FP') cfg['ProjectorId']=pidc cfg['ProjectionDataId']=sid cfg['VolumeDataId']=vid fpid = astra.algorithm.create(cfg) cfg = astra.astra_dict('BP') cfg['ProjectorId']=pidc cfg['ProjectionDataId']=sid cfg['ReconstructionDataId']=vid bpid = astra.algorithm.create(cfg) vc = astra.data2d.get_shared(vid) sc = astra.data2d.get_shared(sid) x[nds//2,nds//2]=1 alp = 1./(na*nds) if self.rg: if self.rg*alp >=0.1: alp = 0.1/self.rg astra.log.info('Computing filter...') for i in range(iterations): if i%10==0: astra.log.info('{:.2f} % done'.format(100*float(i)/iterations)) xs+=x vc[:] = x astra.algorithm.run(fpid) astra.algorithm.run(bpid) if self.rg: dx = x[:-1,:] - x[1:,:] dy = x[:,:-1] - x[:,1:] x[:-1,:] -= self.rg*dx*alp x[1:,:] += self.rg*dx*alp x[:,:-1] -= self.rg*dy*alp x[:,1:] += self.rg*dy*alp x -= vc*alp vc[:] = xs astra.algorithm.run(fpid) flt = sc.copy()*alp astra.algorithm.delete([fpid,bpid]) astra.algorithm.delete([vid,sid]) np.save(self.fn,flt) self.v[:] = self.customFBP(flt) astra.projector.delete(pidc)
def recon_sirt_fbp(im, angles, iter, temppath): """Reconstruct a sinogram with the SIRT-FBP algorithm (Pelt, 2015). Parameters ---------- im : array_like Sinogram image data as numpy array. iter : int Number of iterations to be used for the computation of SIRT filter. angles : double Value in radians representing the number of angles of the input sinogram. """ # Create ASTRA geometries: vol_geom = astra.create_vol_geom(im.shape[1], im.shape[1]) proj_geom = astra.create_proj_geom('parallel', 1.0, im.shape[1], linspace(0, angles, im.shape[0], False)) proj = astra.create_projector('cuda', proj_geom, vol_geom) p = astra.OpTomo(proj) # Register plugin with ASTRA astra.plugin.register(sirtfbp.plugin) # Create the ASTRA projector im_rec = p.reconstruct('SIRT-FBP', im, iter, extraOptions={'filter_dir': temppath}) return im_rec.astype(float32)
def Kadj(sino: np.array) -> np.array: # Create objects for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom) sino_id = astra.data2d.create('-sino', proj_geom, sino) proj_id = astra.create_projector(proj_type, proj_geom, vol_geom) # Set up the parameters for the backpropagation reconstruction. cfg = astra.astra_dict(alg) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sino_id cfg['ProjectorId'] = proj_id # Create the algorithm object from the configuration structure alg_id = astra.algorithm.create(cfg) # Run algorithm. astra.algorithm.run(alg_id) # Get the result rec = astra.data2d.get(rec_id) # Clean up and return result. astra.algorithm.delete(alg_id) astra.data2d.delete(rec_id) astra.data2d.delete(sino_id) astra.projector.delete(proj_id) return rec
def SIRT2D_cpu(sinogram, Niter, proj_geom, vol_geom): # Create a data object for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom) proj_id = astra.create_projector('strip',proj_geom,vol_geom) sinogram_id = astra.data2d.create('-sino', proj_geom, sinogram) # Set up the parameters for a reconstruction algorithm using the CPU cfg = astra.astra_dict('SIRT') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id cfg['ProjectorId'] = proj_id cfg['option']={} cfg['option']['MinConstraint'] = 0 # Create the algorithm object from the configuration structure alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id, Niter) # Get the result rec = astra.data2d.get(rec_id) # Clean up. astra.algorithm.delete(alg_id) astra.data2d.delete(rec_id) astra.data2d.delete(sinogram_id) astra.projector.delete(proj_id) return rec;
def _backproject_block_mult_( projections, volume, proj_geom, vol_geom): """ Multiplicative backprojection of a single block. """ try: # Need to create a copy of the volume: volume_ = numpy.zeros_like(volume) sin_id = astra.data3d.link('-sino', proj_geom, projections) vol_id = astra.data3d.link('-vol', vol_geom, volume_) projector_id = astra.create_projector('cuda3d', proj_geom, vol_geom) # We are using accumulate version to avoid creating additional copies of data. asex.accumulate_BP(projector_id, vol_id, sin_id) except: # The idea here is that we try to delete data3d objects even if ASTRA crashed try: astra.algorithm.delete(projector_id) astra.data3d.delete(sin_id) astra.data3d.delete(vol_id) finally: info = sys.exc_info() traceback.print_exception(*info) volume *= volume_ astra.algorithm.delete(projector_id) astra.data3d.delete(sin_id) astra.data3d.delete(vol_id)
def astra_rec_cuda(tomo, center, recon, theta, vol_geom, niter, proj_type, gpu_index, opts): # Lazy import ASTRA import astra as astra_mod nslices, nang, ndet = tomo.shape cfg = astra_mod.astra_dict(opts['method']) if 'extra_options' in opts: # NOTE: we are modifying 'extra_options' and so need to make a copy cfg['option'] = copy.deepcopy(opts['extra_options']) else: cfg['option'] = {} if gpu_index is not None: cfg['option']['GPUindex'] = gpu_index oc = None const_theta = np.ones(nang) proj_geom = astra_mod.create_proj_geom( 'parallel', 1.0, ndet, theta.astype(np.float64)) for i in range(nslices): if center[i] != oc: oc = center[i] proj_geom['option'] = { 'ExtraDetectorOffset': (center[i] - ndet / 2.) * const_theta} pid = astra_mod.create_projector(proj_type, proj_geom, vol_geom) cfg['ProjectorId'] = pid sid = astra_mod.data2d.link('-sino', proj_geom, tomo[i]) cfg['ProjectionDataId'] = sid vid = astra_mod.data2d.link('-vol', vol_geom, recon[i]) cfg['ReconstructionDataId'] = vid alg_id = astra_mod.algorithm.create(cfg) astra_mod.algorithm.run(alg_id, niter) astra_mod.algorithm.delete(alg_id) astra_mod.data2d.delete(vid) astra_mod.data2d.delete(sid) astra_mod.projector.delete(pid)
def _managed_recon(sino: np.ndarray, cfg, proj_geom, vol_geom) -> Generator[Tuple[int, int], None, None]: proj_id = None sino_id = None rec_id = None alg_id = None try: proj_type = 'cuda' if CudaChecker().cuda_is_present() else 'line' LOG.debug("Using projection type {}".format(proj_type)) proj_id = astra.create_projector(proj_type, proj_geom, vol_geom) sino_id = astra.data2d.create('-sino', proj_geom, sino) rec_id = astra.data2d.create('-vol', vol_geom) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sino_id cfg['ProjectorId'] = proj_id alg_id = astra.algorithm.create(cfg) yield alg_id, rec_id finally: if alg_id: astra.algorithm.delete(alg_id) if proj_id: astra.projector.delete(proj_id) if sino_id: astra.data2d.delete(sino_id) if rec_id: astra.data2d.delete(rec_id)
def __init__(self, angles, img_size): self.angles = angles self.vol_geom = astra.create_vol_geom(img_size, img_size) self.proj_geom = astra.create_proj_geom('parallel', 1.0, img_size, self.angles) self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom)
def astra_rec_cuda(tomo, center, recon, theta, vol_geom, niter, proj_type, gpu_index, opts): # Lazy import ASTRA import astra as astra_mod nslices, nang, ndet = tomo.shape cfg = astra_mod.astra_dict(opts['method']) if 'extra_options' in opts: # NOTE: we are modifying 'extra_options' and so need to make a copy cfg['option'] = copy.deepcopy(opts['extra_options']) else: cfg['option'] = {} if gpu_index is not None: cfg['option']['GPUindex'] = gpu_index oc = None const_theta = np.ones(nang) proj_geom = astra_mod.create_proj_geom('parallel', 1.0, ndet, theta.astype(np.float64)) for i in range(nslices): if center[i] != oc: oc = center[i] proj_geom['option'] = { 'ExtraDetectorOffset': (center[i] - ndet / 2.) * const_theta } pid = astra_mod.create_projector(proj_type, proj_geom, vol_geom) cfg['ProjectorId'] = pid sid = astra_mod.data2d.link('-sino', proj_geom, tomo[i]) cfg['ProjectionDataId'] = sid vid = astra_mod.data2d.link('-vol', vol_geom, recon[i]) cfg['ReconstructionDataId'] = vid alg_id = astra_mod.algorithm.create(cfg) astra_mod.algorithm.run(alg_id, niter) astra_mod.algorithm.delete(alg_id) astra_mod.data2d.delete(vid) astra_mod.data2d.delete(sid) astra_mod.projector.delete(pid)
def __init__(self, DetectorsDim, AnglesVec, ObjSize, device): self.DetectorsDim = DetectorsDim self.AnglesVec = AnglesVec self.ObjSize = ObjSize self.proj_geom = astra.create_proj_geom('parallel', 1.0, DetectorsDim, AnglesVec) self.vol_geom = astra.create_vol_geom(ObjSize, ObjSize) if device == 'cpu': self.proj_id = astra.create_projector('line', self.proj_geom, self.vol_geom) # for CPU self.device = 1 elif device == 'gpu': self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom) # for GPU self.device = 0 else: print ("Select between 'cpu' or 'gpu' for device") # add optomo operator self.A_optomo = astra.OpTomo(self.proj_id)
def _forwardproject_block_(projections, volume, proj_geom, vol_geom, operation = '+'): """ Use this internal function to compute backprojection of a single block of data. """ try: if (operation == '+'): projections_ = projections elif (operation == '*') | (operation == '/'): projections_ = numpy.zeros_like(projections) else: ValueError('Unknown operation type!') sin_id = astra.data3d.link('-sino', proj_geom, projections_) vol_id = astra.data3d.link('-vol', vol_geom, volume) projector_id = astra.create_projector('cuda3d', proj_geom, vol_geom) asex.accumulate_FP(projector_id, vol_id, sin_id) if (operation == '*'): projections *= projections_ elif (operation == '/'): projections_[projections_ < 1e-10] = numpy.inf projections /= projections_ except: print("ASTRA error:", sys.exc_info()) finally: astra.algorithm.delete(projector_id) astra.data3d.delete(sin_id) astra.data3d.delete(vol_id)
def astra_rec_cpu(tomo, center, recon, theta, vol_geom, niter, proj_type, opts): # Lazy import ASTRA import astra as astra_mod nslices, nang, ndet = tomo.shape cfg = astra_mod.astra_dict(opts['method']) if 'extra_options' in opts: cfg['option'] = opts['extra_options'] proj_geom = astra_mod.create_proj_geom('parallel', 1.0, ndet, theta.astype(np.float64)) pid = astra_mod.create_projector(proj_type, proj_geom, vol_geom) sino = np.zeros((nang, ndet), dtype=np.float32) sid = astra_mod.data2d.link('-sino', proj_geom, sino) cfg['ProjectorId'] = pid cfg['ProjectionDataId'] = sid for i in range(nslices): shft = int(np.round(ndet / 2. - center[i])) if not shft == 0: sino[:] = np.roll(tomo[i], shft) l = shft r = ndet + shft if l < 0: l = 0 if r > ndet: r = ndet sino[:, :l] = 0 sino[:, r:] = 0 else: sino[:] = tomo[i] vid = astra_mod.data2d.link('-vol', vol_geom, recon[i]) cfg['ReconstructionDataId'] = vid alg_id = astra_mod.algorithm.create(cfg) astra_mod.algorithm.run(alg_id, niter) astra_mod.algorithm.delete(alg_id) astra_mod.data2d.delete(vid) astra_mod.data2d.delete(sid) astra_mod.projector.delete(pid)
def _backproject_block(self, proj_data, proj_geom, vol_data, vol_geom, algorithm): ''' Backproject a single block of data ''' # TODO: # Do we need to introduce ShortScan parameter? # At the moment we will ignore MinConstraint / MaxConstraint try: sin_id = astra.data3d.link('-sino', proj_geom, numpy.ascontiguousarray(proj_data)) vol_id = astra.data3d.link('-vol', vol_geom, vol_data) projector_id = astra.create_projector('cuda3d', proj_geom, vol_geom) if algorithm == 'BP3D_CUDA': asex.accumulate_BP(projector_id, vol_id, sin_id) elif algorithm == 'FDK_CUDA': asex.accumulate_FDK(projector_id, vol_id, sin_id) else: raise ValueError('Unknown ASTRA algorithm type.') except: print("ASTRA error:", sys.exc_info()) finally: astra.data3d.delete(sin_id) astra.data3d.delete(vol_id) astra.projector.delete(projector_id) return vol_data
def project(vol_data, vol_geom, proj_geom): vol_id = astra.data3d.create('-vol', vol_geom, vol_data) proj_id = astra.data3d.create('-sino', proj_geom) projector = astra.create_projector("cuda3d", proj_geom, vol_geom) astra.experimental.do_composite_FP(projector, [vol_id], [proj_id]) return proj_id, astra.data3d.get_shared(proj_id)
def astrafp(im, ang, prj="cuda"): proj_geom = astra.create_proj_geom("parallel", 1.0, im.shape[0], np.array([ang, 0])) vol_geom = astra.create_vol_geom(im.shape) pid = astra.create_projector(prj, proj_geom, vol_geom) w = astra.OpTomo(pid) fpim = w * im astra.projector.delete(pid) return fpim[0 : im.shape[0]]
def __init__(self, n_pixels, n_angles, rayperdetec=None): ''' Initialize the ASTRA toolbox with a simple parallel configuration. The image is assumed to be square, and the detector count is equal to the number of rows/columns. ''' self.vol_geom = astra.create_vol_geom(n_pixels, n_pixels) self.proj_geom = astra.create_proj_geom('parallel', 1.0, n_pixels, np.linspace(0,np.pi,n_angles,False)) self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom)
def DT(W,p, vol_size, proj_size, angles, Ngv, lamb=10, PU = 'cuda', K = 4, Niter = 50, epsilon=1e-4): [Nx,Nz] = vol_size [Ndetx, Ndety] = proj_size Nan = len(angles) if Ndety==1: sinogram = p.reshape([Nan, Ndetx]) else: sinogram = p.reshape([Nan, Ndetx, Ndety]) # create projection geometry and operator print('TVR-DART ...') print('Create projection geometry and operator...') proj_geom = astra.create_proj_geom('parallel', 1.0, Ndetx, angles) vol_geom = astra.create_vol_geom(Nz,Nx) proj_id = astra.create_projector(PU,proj_geom,vol_geom) W = astra.OpTomo(proj_id) # initial reconstruction print('Initial reconstruction...') recsirt = SIRT.recon(sinogram, 200, proj_geom, vol_geom, PU) sf = np.max(recsirt) p = p/sf if Ndety==1: sinogram = p.reshape([Nan, Ndetx]) else: sinogram = p.reshape([Nan, Ndetx, Ndety]) recsirt = recsirt/sf # set initial TVR-DART parameters K = K*np.ones(Ngv-1) gv = np.linspace(0, 1, Ngv,True) param0 = gv2param(gv,K) # Esimating parameter using a small section of the dataset print('Estimation of optimal parameters...') if Ndety==1: Segrec,param_esti = joint(W,p, recsirt, param0 ,lamb) else: Elist = np.sum(recsirt,axis=(0,2)) index = np.argmax(Elist) index1 = np.max(np.hstack((0,index-1))) index2 = np.min(np.hstack((index+1,Ndety-1))) x0_esti = recsirt[:,index1:index2+1,:] sinogram_esti = sinogram[:,:,index1:index2+1] p_esti = sinogram_esti.reshape(Nan*Ndetx*(index2-index1+1)) Segrec,param_esti = joint(W,p_esti, x0_esti, param0 ,lamb) # Reconstruction with estimated parameter print('Reconstruction with estimated parameters...') Segrec,rec = recon(W,p, recsirt, param_esti, lamb, Niter, epsilon) [gv,K] = param2gv(param_esti) param_esti = gv2param(gv*sf,K) Segrec = Segrec*sf; return Segrec, param_esti;
def single_test(self, geom_type, proj_type, alg, iters, vss, dss): if alg == 'FBP' and 'fanflat' in geom_type: self.skipTest('CPU FBP is parallel-beam only') is3D = (geom_type in ['parallel3d', 'cone']) for vg in VolumeGeometries(is3D, 'FDK' not in alg): for pg in ProjectionGeometries(geom_type): if not is3D: vol = np.zeros((128, 128), dtype=np.float32) vol[50:70, 50:70] = 1 else: vol = np.zeros((64, 64, 64), dtype=np.float32) vol[25:35, 25:35, 25:35] = 1 options = {} if vss > 1: options["VoxelSuperSampling"] = vss if dss > 1: options["DetectorSuperSampling"] = vss proj_id = astra.create_projector(proj_type, pg, vg, options=options) if not is3D: sino_id, sinogram = astra.create_sino(vol, proj_id) else: sino_id, sinogram = astra.create_sino3d_gpu(vol, pg, vg) if not is3D: DATA = astra.data2d else: DATA = astra.data3d rec_id = DATA.create('-vol', vg, 0.0 if 'EM' not in alg else 1.0) cfg = astra.astra_dict(alg) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sino_id cfg['ProjectorId'] = proj_id alg_id = astra.algorithm.create(cfg) for i in range(iters): astra.algorithm.run(alg_id, 1) rec = DATA.get(rec_id) astra.astra.delete([sino_id, alg_id, alg_id, proj_id]) if not is3D: val = np.sum(rec[55:65, 55:65]) / 100. else: val = np.sum(rec[27:32, 27:32, 27:32]) / 125. TOL = 5e-2 if DISPLAY and abs(val - 1.0) >= TOL: print(geom_type, proj_type, alg, vg, pg) print(val) pylab.gray() if not is3D: pylab.imshow(rec) else: pylab.imshow(rec[:, 32, :]) pylab.show() self.assertTrue(abs(val - 1.0) < TOL)
def reconstruct(self, sinogram, centre_of_rotation, angles, shape, center): ctr = centre_of_rotation width = sinogram.shape[1] pad = 50 sino = np.nan_to_num(sinogram) # pad the array so that the centre of rotation is in the middle alen = ctr blen = width - ctr mid = width / 2.0 if (ctr > mid): plow = pad phigh = (alen - blen) + pad else: plow = (blen - alen) + pad phigh = pad logdata = np.log(sino+1) sinogram = np.pad(logdata, ((0, 0), (int(plow), int(phigh))), mode='reflect') width = sinogram.shape[1] vol_geom = astra.create_vol_geom(shape[0], shape[1]) proj_geom = astra.create_proj_geom('parallel', 1.0, width, np.deg2rad(angles)) sinogram_id = astra.data2d.create("-sino", proj_geom, sinogram) # Create a data object for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom) proj_id = astra.create_projector('strip', proj_geom, vol_geom) cfg = astra.astra_dict(self.parameters['reconstruction_type']) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id cfg['ProjectorId'] = proj_id # Create the algorithm object from the configuration structure alg_id = astra.algorithm.create(cfg) # Run 20 iterations of the algorithm itterations = int(self.parameters['number_of_iterations']) # This will have a runtime in the order of 10 seconds. astra.algorithm.run(alg_id, itterations) # Get the result rec = astra.data2d.get(rec_id) # Clean up. astra.algorithm.delete(alg_id) astra.data2d.delete(rec_id) astra.data2d.delete(sinogram_id) return rec
def astra_reconstruction(self, sino, vol_geom, proj_geom): # currently hard-coded - for 3D version only! #sino = np.transpose(sino, (1, 0, 2)) self.sino_id = self.astra_function.create("-sino", proj_geom, sino) # Create a data object for the reconstruction self.rec_id = self.astra_function.create('-vol', vol_geom) cfg = self.cfg_setup() if self.alg_type is '2D' and not "CUDA" in self.name: proj_id = astra.create_projector('strip', proj_geom, vol_geom) cfg['ProjectorId'] = proj_id return self.run_astra(cfg)
def _basic_par2d_fp(type): import astra import numpy as np vg = astra.create_vol_geom(2, 32) pg = astra.create_proj_geom('parallel', 1, 32, [0]) proj_id = astra.create_projector(type, pg, vg) vol = np.random.rand(2, 32) (sino_id, sino) = astra.create_sino(vol, proj_id) astra.data2d.delete(sino_id) astra.projector.delete(proj_id) err = np.max(np.abs(sino[0,:] - np.sum(vol,axis=0))) return err < 1e-6
def set_config(self, rec_id, sino_id, proj_geom, vol_geom): cfg = astra.astra_dict(self.alg) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sino_id if 'FBP' in self.alg: fbp_filter = self.parameters['FBP_filter'] if 'FBP_filter' in \ self.parameters.keys() else 'none' cfg['FilterType'] = fbp_filter if 'projector' in self.parameters.keys(): proj_id = astra.create_projector( self.parameters['projector'], proj_geom, vol_geom) cfg['ProjectorId'] = proj_id cfg = self.set_options(cfg) return cfg
def set_config(self, rec_id, sino_id, proj_geom, vol_geom): cfg = astra.astra_dict(self.alg) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sino_id if 'FBP' in self.alg: cfg['FilterType'] = self.parameters['FBP_filter'] if 'projector' in self.parameters.keys(): proj_id = astra.create_projector( self.parameters['projector'], proj_geom, vol_geom) cfg['ProjectorId'] = proj_id # mask not currently working correctly for SIRT or SART algorithms sirt_or_sart = [a for a in ['SIRT', 'SART'] if a in self.alg] if self.mask_id and not sirt_or_sart: cfg['option'] = {} cfg['option']['ReconstructionMaskId'] = self.mask_id cfg = self.set_options(cfg) return cfg
def geom_setup_2D(self, dim_det_cols): in_pData = self.get_plugin_in_datasets()[0] cor = self.cor + self.pad_amount sino_shape = in_pData.get_shape() nCols = sino_shape[dim_det_cols] self.p_low, self.p_high = \ self.array_pad(cor[0], nCols + 2*self.pad_amount) sino_width = \ sino_shape[1] + self.p_low + self.p_high + 2*self.pad_amount vol_geom = astra.create_vol_geom(self.vol_shape[0], self.vol_shape[1]) self.proj_geom = astra.create_proj_geom('parallel', 1.0, sino_width, np.deg2rad(self.angles)) self.rec_id = self.astra_function.create('-vol', vol_geom) self.cfg = self.cfg_setup() if self.alg_type is '2D' and "CUDA" not in self.name: proj_id = astra.create_projector('strip', self.proj_geom, vol_geom) self.cfg['ProjectorId'] = proj_id
def fp0(image, det_col=111, num_angles=222, voxel_size_mm=1): """Wrapper for astra forward projector :param image: :return: sinogram """ vol_geom = astra.create_vol_geom(image.shape) proj_id = astra.create_projector( 'cuda', astra.create_proj_geom('parallel', 1.0, det_col, np.linspace(0, np.pi, num_angles, False)), vol_geom) sino_id, sino = astra.create_sino(image, proj_id) sino *= voxel_size_mm astra.data2d.delete(sino_id) astra.projector.delete(proj_id) return sino
def reconstruct2D(self, sinogram, angles, shape, alg_name, iterations): vol_geom = astra.create_vol_geom(shape[0], shape[1]) proj_geom = astra.create_proj_geom('parallel', 1.0, sinogram.shape[1], np.deg2rad(angles)) sinogram_id = astra.data2d.create("-sino", proj_geom, sinogram) # Create a data object for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom) cfg = astra.astra_dict(alg_name) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id if not "CUDA" in alg_name: proj_id = astra.create_projector('strip', proj_geom, vol_geom) cfg['ProjectorId'] = proj_id # Create the algorithm object from the configuration structure alg_id = astra.algorithm.create(cfg) # This will have a runtime in the order of 10 seconds. astra.algorithm.run(alg_id, iterations) if "CUDA" in alg_name and "FBP" not in alg_name: self.res += astra.algorithm.get_res_norm(alg_id)**2 print math.sqrt(self.res) # Get the result rec = astra.data2d.get(rec_id) astra.algorithm.delete(alg_id) astra.data2d.delete(rec_id) astra.data2d.delete(sinogram_id) return rec
ts -= s # ts = W*v - s W.BP(ts,out=tv) tv *= self.rel / s.size v -= tv # v = v - rel * W'*(W*v-s) / s.size if __name__=='__main__': vol_geom = astra.create_vol_geom(256, 256) proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) # As before, create a sinogram from a phantom import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] proj_id = astra.create_projector('cuda',proj_geom,vol_geom) # construct the OpTomo object W = astra.OpTomo(proj_id) sinogram = W * P sinogram = sinogram.reshape([180, 384]) # Register the plugin with ASTRA # First we import the package that contains the plugin import s018_plugin # Then, we register the plugin class with ASTRA astra.plugin.register(s018_plugin.LandweberPlugin) # Get a list of registered plugins six.print_(astra.plugin.get_registered())
def astra_run(*args): # Lazy import ASTRA import astra as astra_mod # Get shared arrays tomo = mproc.SHARED_TOMO recon = mproc.SHARED_ARRAY # Unpack arguments nang = args[0] nslices = args[1] ndet = args[2] centers = args[3] angles = args[4] num_gridx = args[5]['num_gridx'] num_gridy = args[5]['num_gridy'] opts = args[5]['options'] istart = args[6] iend = args[7] # Check options for o in needed_options['astra']: if o not in opts: logger.error("Option %s needed for ASTRA reconstruction." % (o,)) raise ValueError() for o in default_options['astra']: if o not in opts: opts[o] = default_options['astra'][o] # Create ASTRA geometries vol_geom = astra_mod.create_vol_geom((num_gridx, num_gridy)) proj_geom = astra_mod.create_proj_geom( 'parallel', 1.0, ndet, angles.astype(np.float64)) # Number of GPUs to use if opts['proj_type'] == 'cuda' and opts['gpu_list'] is not None: import concurrent.futures gpu_list = opts['gpu_list'] nbatch = len(gpu_list) executor = concurrent.futures.ThreadPoolExecutor(max_workers=nbatch) else: nbatch = 1 # Create ASTRA data sino = np.zeros((nbatch, nang, ndet), dtype=np.float32) # Create ASTRA config cfg = astra_mod.astra_dict(opts['method']) if opts['proj_type'] != 'cuda': pi = astra_mod.create_projector(opts['proj_type'], proj_geom, vol_geom) sid = astra_mod.data2d.link('-sino', proj_geom, sino[0]) cfg['ProjectorId'] = pi cfg['ProjectionDataId'] = sid use_cuda = False else: use_cuda = True if 'extra_options' in opts: cfg['option'] = opts['extra_options'] else: cfg['option'] = {} # Perform reconstruction vids = [] algs = [] pids = [] sids = [] for ib in range(istart, iend, nbatch): for j in range(nbatch): i = ib+j if i>=iend: break sino[j] = tomo[:, i, :] cfg['option']['z_id'] = i # Fix center of rotation if use_cuda: proj_geom['option'] = { 'ExtraDetectorOffset': (centers[i] - ndet / 2.) * np.ones(nang)} sid = astra_mod.data2d.link('-sino', proj_geom, sino[j]) sids.append(sid) cfg['ProjectionDataId'] = sid pi = astra_mod.create_projector( opts['proj_type'], proj_geom, vol_geom) pids.append(pi) cfg['ProjectorId'] = pi else: # Temporary workaround, will be fixed in later ASTRA version shft = int(np.round(ndet / 2. - centers[i])) sino[0] = np.roll(sino, shft) l = shft r = sino.shape[1] + shft if l < 0: l = 0 if r > sino.shape[1]: r = sino.shape[1] sino[0, :, 0:l] = 0 sino[0, :, r:sino.shape[1]] = 0 vid = astra_mod.data2d.link('-vol', vol_geom, recon[i]) vids.append(vid) cfg['ReconstructionDataId'] = vid if nbatch>1: cfg['option']['GPUindex'] = gpu_list[j] alg_id = astra_mod.algorithm.create(cfg) algs.append(alg_id) if nbatch==1: astra_mod.algorithm.run(algs[0], opts['num_iter']) else: thrds = [executor.submit(lambda q: astra_mod.algorithm.run(q, opts['num_iter']), alg_id) for alg_id in algs] for q in thrds: q.result() astra_mod.algorithm.delete(algs) del algs[:] astra_mod.data2d.delete(vids) del vids[:] if use_cuda: astra_mod.projector.delete(pids) del pids[:] astra_mod.data2d.delete(sids) del sids[:] # Clean up if not use_cuda: astra_mod.projector.delete(pi) astra_mod.data2d.delete(sid)
import scipy.io as sio import os import tifffile # Geometry details: number of projections, size of dataset, and amount of noise na = 64 nd = 256 ns = 128 i0 = 10**3 # Create ASTRA geometries vol_geom = astra.create_vol_geom(nd,nd) proj_geom = astra.create_proj_geom('parallel',1.0,nd,np.linspace(0,np.pi,na,False)) # Create the ASTRA projector pid = astra.create_projector('linear',proj_geom,vol_geom) # change 'linear' to 'cuda' to use GPU p = astra.OpTomo(pid) # Create simulated HQ dataset for training hq = np.zeros((ns,nd,nd)) hq[:,nd//4:3*nd//4,nd//4:3*nd//4]=1 hq[:,3*nd//8:5*nd//8,3*nd//8:5*nd//8]=0 try: os.mkdir('hqrecs/') except OSError: pass projections = np.zeros((ns, na, nd)) for i in range(ns): projections[i] = astra.add_noise_to_sino((p*hq[i]).reshape(p.sshape),i0) tifffile.imsave('hqrecs/{:04d}.tiff'.format(i),hq[i])
def __init__(self, proj_geom, vol_geom): self.proj_id = astra.create_projector('line', proj_geom, vol_geom) self.shape = ( proj_geom['DetectorCount'] * len(proj_geom['ProjectionAngles']), vol_geom['GridColCount'] * vol_geom['GridRowCount']) self.dtype = np.float
import astra import numpy as np cor_shift = 3.6 vol_geom = astra.create_vol_geom(256, 256) proj_geom = astra.create_proj_geom('parallel', 1.0, 256, np.linspace(0,np.pi,180,False)) # Projection geometry with shifted center of rotation proj_geom_cor = astra.geom_postalignment(proj_geom, cor_shift) # As before, create a sinogram from a phantom, using the shifted center of rotation import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] proj_id_cor = astra.create_projector('cuda',proj_geom_cor,vol_geom) sinogram_id, sinogram = astra.create_sino(P, proj_id_cor) # Change the projection geometry metadata attached to the sinogram to standard geometry, # and try to do a reconstruction, to show the misalignment artifacts caused by # the shifted center of rotation astra.data2d.change_geometry(sinogram_id, proj_geom) import pylab pylab.gray() pylab.figure(1) pylab.imshow(P) pylab.figure(2) pylab.imshow(sinogram) # Create a data object for the reconstruction
def __init__(self, n_pixels, angles, rot_center=None, fullscan=False, super_sampling=None): """ Initialize the ASTRA toolbox with a simple parallel configuration. The image is assumed to be square, and the detector count is equal to the number of rows/columns. n_pixels: integer number of pixels of one dimension of the image angles : integer or numpy.ndarray number of projection angles (if integer), or custom series of angles rot_center : float user-defined rotation center fullscan : boolean if True, use a 360 scan configuration super_sampling : integer Detector and Pixel supersampling """ if isinstance(n_pixels, int): n_x, n_y = n_pixels, n_pixels else: # assuming iterable n_pixels = tuple(n_pixels) n_x, n_y = n_pixels angle_max = np.pi if fullscan: angle_max *= 2 if isinstance(angles, int): angles = np.linspace(0, angle_max, angles, False) n_angles = angles.shape[0] self.vol_geom = astra.create_vol_geom(n_x, n_y) self.proj_geom = astra.create_proj_geom('parallel', 1.0, n_pixels, angles) if rot_center: o_angles = np.ones(n_angles) if isinstance(n_angles, int) else np.ones_like(n_angles) self.proj_geom['option'] = {'ExtraDetectorOffset': (rot_center - n_x / 2.) * o_angles} self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom) # vg : Volume geometry self.vg = astra.projector.volume_geometry(self.proj_id) # pg : projection geometry self.pg = astra.projector.projection_geometry(self.proj_id) # ---- Configure Projector ------ # sinogram shape self.sshape = astra.functions.geom_size(self.pg) # Configure projector self.cfg_proj = astra.creators.astra_dict('FP_CUDA') self.cfg_proj['ProjectorId'] = self.proj_id if super_sampling: self.cfg_proj['option'] = {'DetectorSuperSampling':super_sampling} # ---- Configure Backprojector ------ # volume shape self.vshape = astra.functions.geom_size(self.vg) # Configure backprojector self.cfg_backproj = astra.creators.astra_dict('BP_CUDA') self.cfg_backproj['ProjectorId'] = self.proj_id if super_sampling: self.cfg_backproj['option'] = {'PixelSuperSampling':super_sampling} # ------------------- self.rot_center = rot_center if rot_center else n_pixels/2 self.n_pixels = n_pixels self.angles = angles
#GNU General Public License for more details. # #You should have received a copy of the GNU General Public License #along with the Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. # #----------------------------------------------------------------------- import astra import numpy as np vol_geom = astra.create_vol_geom(256, 256) proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) # For CPU-based algorithms, a "projector" object specifies the projection # model used. In this case, we use the "strip" model. proj_id = astra.create_projector('strip', proj_geom, vol_geom) # Create a sinogram from a phantom import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] sinogram_id, sinogram = astra.create_sino(P, proj_id) import pylab #pylab.gray() #pylab.figure(1) #pylab.imshow(P) #pylab.figure(2) #pylab.imshow(sinogram) # Create a data object for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom)
# Create a simple hollow cube phantom cube1 = np.zeros((32,32,16)) cube1[4:28,4:28,4:16] = 1 cube2 = np.zeros((128,128,64)) cube2[16:112,16:112,0:112] = 1 cube2[33:97,33:97,4:28] = 0 vol1 = astra.data3d.create('-vol', vol_geom1, cube1) vol2 = astra.data3d.create('-vol', vol_geom2, cube2) proj1 = astra.data3d.create('-proj3d', proj_geom1, 0) proj2 = astra.data3d.create('-proj3d', proj_geom2, 0) # The actual geometries don't matter for this composite FP/BP case projector = astra.create_projector('cuda3d', proj_geom1, vol_geom1) do_composite_FP(projector, [vol1, vol2], [proj1, proj2]) proj_data1 = astra.data3d.get(proj1) proj_data2 = astra.data3d.get(proj2) # Display a single projection image import pylab pylab.gray() pylab.figure(1) pylab.imshow(proj_data1[:,0,:]) pylab.figure(2) pylab.imshow(proj_data2[:,0,:]) pylab.show()
def __init__(self, slice_shape, angles, dwidth=None, rot_center=None, fullscan=False, cudafbp=False, super_sampling=None): """ Create a tomography parallel beam geometry. Parameters ----------- slice_shape: int or tuple Shape of the slice. Can be in the form (n_x, n_y) or N. If the argument is an integer N, the slice is assumed to be square of dimensions (N, N). Mind that if providing (n_x, n_y), n_x is the number of columns of the image. angles: integer or numpy.ndarray Projection angles in radians. If this argument is an integer, the projections angles are linear between [0, pi[ if fullscan=False, or in [0, 2*pi[ if fullscan=True. If this argument is a 1D array, this means that custom angles (in radians) are provided. dwidth: (optional) integer detector width (number of pixels). If not provided, max(n_x, n_y) is taken. rot_center: (optional) float user-defined rotation center. If not provided, dwidth/2 is taken. fullscan: (optional) boolean, default is False if True, use a 360 scan geometry. cudafbp: (optionnal) boolean, default is False If True, use the built-in FBP of ASTRA instead of using Python to filter the projections. super_sampling: integer Detector and Pixel supersampling """ if isinstance(slice_shape, int): n_x, n_y = slice_shape, slice_shape else: slice_shape = tuple(slice_shape) n_x, n_y = slice_shape if dwidth is None: dwidth = max(n_x, n_y) angle_max = np.pi if fullscan: angle_max *= 2 if isinstance(angles, int): angles = np.linspace(0, angle_max, angles, False) n_angles = angles.shape[0] self.vol_geom = astra.create_vol_geom(n_x, n_y) self.proj_geom = astra.create_proj_geom('parallel', 1.0, dwidth, angles) if rot_center: o_angles = np.ones(n_angles) if isinstance(n_angles, int) else np.ones_like(n_angles) self.proj_geom['option'] = {'ExtraDetectorOffset': (rot_center - n_x / 2.) * o_angles} self.proj_id = astra.create_projector('cuda', self.proj_geom, self.vol_geom) # vg : Volume geometry self.vg = astra.projector.volume_geometry(self.proj_id) # pg : projection geometry self.pg = astra.projector.projection_geometry(self.proj_id) # ---- Configure Projector ------ # sinogram shape self.sshape = astra.functions.geom_size(self.pg) # Configure projector self.cfg_proj = astra.creators.astra_dict('FP_CUDA') self.cfg_proj['ProjectorId'] = self.proj_id if super_sampling: self.cfg_proj['option'] = {'DetectorSuperSampling':super_sampling} # ---- Configure Backprojector ------ # volume shape self.vshape = astra.functions.geom_size(self.vg) # Configure backprojector if cudafbp: self.cfg_backproj = astra.creators.astra_dict('FBP_CUDA') self.cfg_backproj['FilterType'] = 'Ram-Lak' else: self.cfg_backproj = astra.creators.astra_dict('BP_CUDA') self.cfg_backproj['ProjectorId'] = self.proj_id if super_sampling: self.cfg_backproj['option'] = {'PixelSuperSampling':super_sampling} # ------------------- self.n_x = n_x self.n_y = n_y self.dwidth = dwidth self.n_a = angles.shape[0] self.rot_center = rot_center if rot_center else dwidth//2 self.angles = angles self.cudafbp = cudafbp if not(cudafbp): _ramp = self.compute_ramp_filter(dwidth*2)*2.0 self.rampfilter = np.abs(np.fft.fft(_ramp)) else: self.rampfilter = None
#along with PySIRT-FBP. If not, see <http://www.gnu.org/licenses/>. # #----------------------------------------------------------------------- import sirtfbp import phantom import astra import numpy as np import os nd = 256 na = 32 # Create ASTRA geometries vol_geom = astra.create_vol_geom(nd,nd) proj_geom = astra.create_proj_geom('parallel',1.0,nd,np.linspace(0,np.pi,na,False)) pi = astra.create_projector('linear', proj_geom, vol_geom) # change 'linear' to 'cuda' for GPU p = astra.OpTomo(pi) # Load the phantom from disk testPhantom = phantom.phantom(nd) # Calculate the forward projection of the phantom testSino = (p*testPhantom).reshape((na,nd)) # Add some noise to the sinogram testSino = astra.add_noise_to_sino(testSino,10**3) # Register plugin with ASTRA astra.plugin.register(sirtfbp.plugin) # Reconstruct the image using SIRT-FBP, FBP, and SIRT.
c = np.linspace(-127.5,127.5,256) x, y = np.meshgrid(c,c) mask = np.array((x**2 + y**2 < 127.5**2),dtype=np.float) import pylab pylab.gray() pylab.figure(1) pylab.imshow(mask) vol_geom = astra.create_vol_geom(256, 256) proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,50,False)) # 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) pylab.figure(2) pylab.imshow(P) pylab.figure(3) pylab.imshow(sinogram) # Create a data object for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom) # Create a data object for the mask mask_id = astra.data2d.create('-vol', vol_geom, mask) # Set up the parameters for a reconstruction algorithm using the GPU cfg = astra.astra_dict('SIRT_CUDA')
def astra_run(*args): # Lazy import ASTRA import astra as astra_mod # Get shared arrays tomo = mproc.SHARED_TOMO recon = mproc.SHARED_ARRAY # Unpack arguments nang = args[0] nslices = args[1] ndet = args[2] centers = args[3] angles = args[4] num_gridx = args[5]['num_gridx'] num_gridy = args[5]['num_gridy'] opts = args[5]['options'] istart = args[6] iend = args[7] # Check options for o in needed_options['astra']: if o not in opts: logger.error("Option %s needed for ASTRA reconstruction." % (o,)) raise ValueError() for o in default_options['astra']: if o not in opts: opts[o] = default_options['astra'][o] # Create ASTRA geometries vol_geom = astra_mod.create_vol_geom((num_gridx, num_gridy)) proj_geom = astra_mod.create_proj_geom( 'parallel', 1.0, ndet, angles.astype(np.float64)) # Create ASTRA data id sino = np.zeros((nang, ndet), dtype=np.float32) # Create ASTRA config cfg = astra_mod.astra_dict(opts['method']) if opts['proj_type'] != 'cuda': pi = astra_mod.create_projector(opts['proj_type'], proj_geom, vol_geom) sid = astra_mod.data2d.link('-sino', proj_geom, sino) cfg['ProjectorId'] = pi cfg['ProjectionDataId'] = sid use_cuda = False else: use_cuda = True if 'extra_options' in opts: cfg['option'] = opts['extra_options'] else: cfg['option'] = {} # Perform reconstruction for i in xrange(istart, iend): sino[:] = tomo[:, i, :] cfg['option']['z_id'] = i # Fix center of rotation if use_cuda: proj_geom['option'] = { 'ExtraDetectorOffset': (centers[i] - ndet / 2.) * np.ones(nang)} sid = astra_mod.data2d.link('-sino', proj_geom, sino) cfg['ProjectionDataId'] = sid pi = astra_mod.create_projector( opts['proj_type'], proj_geom, vol_geom) cfg['ProjectorId'] = pi else: # Temporary workaround, will be fixed in later ASTRA version shft = int(np.round(ndet / 2. - centers[i])) sino[:] = np.roll(sino, shft) l = shft r = sino.shape[1] + shft if l < 0: l = 0 if r > sino.shape[1]: r = sino.shape[1] sino[:, 0:l] = 0 sino[:, r:sino.shape[1]] = 0 vid = astra_mod.data2d.link('-vol', vol_geom, recon[i]) cfg['ReconstructionDataId'] = vid alg_id = astra_mod.algorithm.create(cfg) astra_mod.algorithm.run(alg_id, opts['num_iter']) astra_mod.algorithm.delete(alg_id) astra_mod.data2d.delete(vid) if use_cuda: astra_mod.projector.delete(pi) astra_mod.data2d.delete(sid) # Clean up if not use_cuda: astra_mod.projector.delete(pi) astra_mod.data2d.delete(sid)
def astra(*args): """ Reconstruct object using the ASTRA toolbox Extra options ---------- method : str ASTRA reconstruction method to use. num_iter : int, optional Number of algorithm iterations performed. proj_type : str, optional ASTRA projector type to use: 'line', 'linear', or 'strip' (CPU only). extra_options : dict, optional Extra options for the ASTRA config (i.e. those in cfg['option']) Warning ------- When using CUDA, only 1 CPU core can be used. Example ------- >>> import tomopy >>> obj = tomopy.shepp3d() # Generate an object. >>> ang = tomopy.angles(180) # Generate uniformly spaced tilt angles. >>> sim = tomopy.project(obj, ang) # Calculate projections. >>> >>> # Reconstruct object: >>> rec = tomopy.recon(sim, ang, algorithm=tomopy.astra, >>> options={'method':'SART', 'num_iter':10*180, 'proj_type':'linear', >>> 'extra_options':{'MinConstraint':0}}) >>> >>> # Show 64th slice of the reconstructed object. >>> import pylab >>> pylab.imshow(rec[64], cmap='gray') >>> pylab.show() """ # Lazy import ASTRA import astra as astra_mod # Get shared arrays tomo = mproc.SHARED_TOMO recon = mproc.SHARED_ARRAY # Unpack arguments nang = args[0] nslices = args[1] ndet = args[2] centers = args[3] angles = args[4] num_gridx = args[5]['num_gridx'] num_gridy = args[5]['num_gridy'] opts = args[5]['options'] istart = args[6] iend = args[7] # Check options for o in needed_options['astra']: if not o in opts: logger.error("Option %s needed for ASTRA reconstruction." % (o,)) raise ValueError() for o in default_options['astra']: if not o in opts: opts[o] = default_options['astra'][o] # Create ASTRA geometries vol_geom = astra_mod.create_vol_geom((num_gridx,num_gridy)) proj_geom = astra_mod.create_proj_geom('parallel',1.0,ndet,angles.astype(np.float64)) # Create ASTRA data id sino = np.zeros((nang, ndet), dtype=np.float32) # Create ASTRA config cfg = astra_mod.astra_dict(opts['method']) if opts['proj_type']!='cuda': pi = astra_mod.create_projector(opts['proj_type'], proj_geom, vol_geom) sid = astra_mod.data2d.link('-sino', proj_geom, sino) cfg['ProjectorId'] = pi cfg['ProjectionDataId'] = sid use_cuda=False else: use_cuda=True if 'extra_options' in opts: cfg['option'] = opts['extra_options'] else: cfg['option'] = {} # Perform reconstruction for i in xrange(istart, iend): sino[:] = tomo[:,i,:] cfg['option']['z_id']=i # Fix center of rotation if use_cuda: proj_geom['option'] = {'ExtraDetectorOffset': (centers[i]-ndet/2.)*np.ones(nang)} sid = astra_mod.data2d.link('-sino', proj_geom, sino) cfg['ProjectionDataId'] = sid pi = astra_mod.create_projector(opts['proj_type'], proj_geom, vol_geom) cfg['ProjectorId'] = pi else: # Temporary workaround, will be fixed in later ASTRA version shft = int(np.round(ndet/2.-centers[i])) sino[:] = np.roll(sino,shft) l = shft r = sino.shape[1]+shft if l<0: l=0 if r>sino.shape[1]: r=sino.shape[1] sino[:,0:l]=0 sino[:,r:sino.shape[1]]=0 vid = astra_mod.data2d.link('-vol', vol_geom, recon[i]) cfg['ReconstructionDataId'] = vid alg_id = astra_mod.algorithm.create(cfg) astra_mod.algorithm.run(alg_id, opts['num_iter']) astra_mod.algorithm.delete(alg_id) astra_mod.data2d.delete(vid) if use_cuda: astra_mod.projector.delete(pi) astra_mod.data2d.delete(sid) # Clean up if not use_cuda: astra_mod.projector.delete(pi) astra_mod.data2d.delete(sid)
# along with the Python interface to the ASTRA Toolbox. If not, see <http://www.gnu.org/licenses/>. # # ----------------------------------------------------------------------- import astra import numpy as np import scipy.sparse.linalg vol_geom = astra.create_vol_geom(256, 256) proj_geom = astra.create_proj_geom("parallel", 1.0, 384, np.linspace(0, np.pi, 180, False)) # As before, create a sinogram from a phantom import scipy.io P = scipy.io.loadmat("phantom.mat")["phantom256"] proj_id = astra.create_projector("cuda", proj_geom, vol_geom) # construct the OpTomo object W = astra.OpTomo(proj_id) sinogram = W * P sinogram = sinogram.reshape([180, 384]) import pylab pylab.gray() pylab.figure(1) pylab.imshow(P) pylab.figure(2) pylab.imshow(sinogram)