def astra_fp_3d(volume, proj_geom): """ :param proj_geom: :param volume: :return:3D sinogram """ detector_size = volume.shape[1] slices_number = volume.shape[0] rec_size = detector_size vol_geom = build_volume_geometry_3d(rec_size, slices_number) sinogram_id = astra.data3d.create('-sino', proj_geom) # Create a data object for the reconstruction rec_id = astra.data3d.create('-vol', vol_geom, data=volume) # Set up the parameters for a reconstruction algorithm using the GPU cfg = astra.astra_dict('FP3D_CUDA') cfg['VolumeDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id cfg['option'] = {} alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id, 1) res_sino = astra.data3d.get(sinogram_id) # Clean up. Note that GPU memory is tied up in the algorithm object, # and main RAM in the data objects. astra.algorithm.delete(alg_id) astra.data3d.delete(rec_id) astra.data3d.delete(sinogram_id) astra.clear() return res_sino
def getSystemMatrix(geom): vectors = np.zeros((len(geom), 12), dtype=np.float32) for i, _ in enumerate(vectors): vectors[i, [0, 1, 2]] = geom[i]['Anode'] vectors[i, [3, 4, 5]] = geom[i]['Detector'] vectors[i, [6, 7, 8]] = geom[i]['U Axis'] vectors[i, [9, 10, 11]] = geom[i]['V Axis'] # Range of X, Y, Z in mm over the entire volume volX = np.array([-10, 10]) volY = np.array([-9, 20]) volZ = np.array([-15, 15]) # Chosen grid size voxelSize = [0.1, 0.1, 0.1] # Set reconstruction grid size # Length of the OVERALL volume grid volSize = np.array([ volX.ptp() / voxelSize[0], volY.ptp() / voxelSize[1], volZ.ptp() / voxelSize[2] ], dtype=int) gridSize = volSize gridX = np.linspace(volX[0], volX[1], gridSize[0]) gridY = np.linspace(volY[0], volY[1], gridSize[1]) gridZ = np.linspace(volZ[0], volZ[1], gridSize[2]) # Setup ASTRA geometry proj_geom = astra.create_proj_geom('cone_vec', 512, 512, vectors) vol_geom = astra.create_vol_geom(volSize[1], volSize[0], volSize[2], volX[0], volX[1], volY[0], volY[1], volZ[0], volZ[1]) # 3D projectors: cuda3d # blob not implemented, linear3d and linearcone not available(?) proj_id = astra.create_projector('cuda3d', proj_geom, vol_geom) # Get the OpTomo representation of the system matrix for brevity W = astra.optomo.OpTomo(proj_id) # Clearing astra variables (only need W) astra.clear() # Print volume size print(f'Volume grid size (px): {gridSize}') return W
def astra_recon_3d(sinogram, proj_geom, method=['CGLS3D_CUDA', 10], data=None): """ :param proj_geom: :param sinogram: :param method: :param n_iters: :param data: :return: """ methods = parse_recon_methods(method) detector_size = sinogram.shape[-1] slices_number = sinogram.shape[0] rec_size = detector_size vol_geom = astra.create_vol_geom(rec_size, rec_size, slices_number) sinogram_id = astra.data3d.create('-sino', proj_geom, data=sinogram) # Create a data object for the reconstruction rec_id = astra.data3d.create('-vol', vol_geom, data) alg_id = None for m in methods: cfg = astra.astra_dict(m[0]) cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id cfg['option'] = m[2] alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id, m[1]) astra.algorithm.delete(alg_id) tomo_rec = astra.data3d.get(rec_id) # Clean up. Note that GPU memory is tied up in the algorithm object, # and main RAM in the data objects. astra.data3d.delete(rec_id) astra.data3d.delete(sinogram_id) astra.clear() return tomo_rec
astra.algorithm.run(self.forward_alg_id) self.projection_data = astra.data3d.get(self.projection_id) def backward(self): astra.algorithm.run(self.backward_alg_id) self.volume_data = astra.data3d.get(self.volume_id) def clear(self): astra.data3d.delete(self.volume_id) astra.data3d.delete(self.projection_id) astra.algorithm.delete(self.forward_alg_id) astra.algorithm.delete(self.backward_alg_id) # SIRT astra.clear() p = Projector() p.init() p.forward() p.backward() class Mmm: def __init__(self, num_voxel=(100, 100, 100)): self.num_voxel = num_voxel self.vol_geom = astra.create_vol_geom(self.num_voxel) self.volume_id = astra.data3d.create('-vol', self.vol_geom, 0) counter = 0 num_voxel = (10, 10, 10)
def forward(self): astra.algorithm.run(self.forward_alg_id) self.projection_data = astra.data3d.get(self.projection_id) def backward(self): astra.algorithm.run(self.backward_alg_id) self.volume_data = astra.data3d.get(self.volume_id) def clear(self): astra.data3d.delete(self.volume_id) astra.data3d.delete(self.projection_id) astra.algorithm.delete(self.forward_alg_id) astra.algorithm.delete(self.backward_alg_id) # SIRT astra.clear() p = Projector() p.init() p.forward() p.backward() class Mmm: def __init__(self, num_voxel = (100, 100, 100)): self.num_voxel = num_voxel self.vol_geom = astra.create_vol_geom(self.num_voxel) self.volume_id = astra.data3d.create('-vol', self.vol_geom, 0) counter = 0 num_voxel = (10, 10, 10)
def astra_sirt_error(sinogram, angles, iterations=50, constrain=True, thresh=0, cuda=False): """ Perform SIRT reconstruction using the Astra toolbox algorithms. Args ---------- stack : NumPy array Tilt series data either of the form [angles, x] or [angles, y, x] where y is the tilt axis and x is the projection axis. angles : list or NumPy array Projection angles in degrees. thickness : int or float Number of pixels in the projection (through-thickness) direction for the reconstructed volume. If None, thickness is set to be the same as that in the x-direction of the sinogram. iterations : integer Number of iterations for the SIRT reconstruction. constrain : boolean If True, output reconstruction is constrained above value given by 'thresh'. Default is True. thresh : integer or float Value above which to constrain the reconstructed data if 'constrain' is True. cuda : boolean If True, use the CUDA-accelerated Astra algorithms. Otherwise, use the CPU-based algorithms Returns ---------- rec : Numpy array 3D array of the form [y, z, x] containing the reconstructed object. """ sino = sinogram.data[:, 0, :] thetas = angles * np.pi / 180 n_angles, x_pix = sino.shape thickness = x_pix rec = np.zeros([thickness, x_pix], sino.dtype) vol_geom = astra.create_vol_geom(thickness, x_pix) proj_geom = astra.create_proj_geom('parallel', 1, x_pix, thetas) data_id = astra.data2d.create('-sino', proj_geom, sino) rec_id = astra.data2d.create('-vol', vol_geom) if cuda: cfg = astra.astra_dict('SIRT_CUDA') else: proj_id = astra.create_projector('strip', proj_geom, vol_geom) cfg = astra.astra_dict('SIRT') cfg['ProjectorId'] = proj_id cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = data_id if constrain: cfg['option'] = {} cfg['option']['MinConstraint'] = thresh alg_id = astra.algorithm.create(cfg) residual_error = np.zeros(iterations) rec_stack = np.zeros([iterations, thickness, x_pix]) for i in range(iterations): astra.algorithm.run(alg_id, 1) rec = astra.data2d.get(rec_id) rec_stack[i] = rec forward_project = astra_project(rec, angles=angles, cuda=cuda)[:, 0, :] residual_error[i] = np.sqrt(np.square(forward_project - sino).sum()) astra.clear() return rec_stack, residual_error
def astra_fbp(stack, angles, thickness=None, cuda=False): """ Perform SIRT reconstruction using the Astra toolbox algorithms. Args ---------- stack : NumPy array Tilt series data either of the form [angles, x] or [angles, y, x] where y is the tilt axis and x is the projection axis. angles : list or NumPy array Projection angles in degrees. thickness : int or float Number of pixels in the projection (through-thickness) direction for the reconstructed volume. If None, thickness is set to be the same as that in the x-direction of the sinogram. cuda : boolean If True, use the CUDA-accelerated Astra algorithms. Otherwise, use the CPU-based algorithms Returns ---------- rec : Numpy array 3D array of the form [y, z, x] containing the reconstructed object. """ thetas = angles * np.pi / 180 if len(stack.shape) == 2: data = np.expand_dims(stack, 1) else: data = stack data = np.rollaxis(data, 1) y_pix, n_angles, x_pix = data.shape if thickness is None: thickness = data.shape[2] if cuda: rec = np.zeros([y_pix, thickness, x_pix], data.dtype) vol_geom = astra.create_vol_geom(thickness, x_pix) proj_geom = astra.create_proj_geom('parallel', 1, x_pix, thetas) data_id = astra.data2d.create('-sino', proj_geom) rec_id = astra.data2d.create('-vol', vol_geom) cfg = astra.astra_dict('FBP_CUDA') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = data_id cfg['option'] = {} cfg['option']['FilterType'] = 'ram-lak' alg_id = astra.algorithm.create(cfg) for i in range(0, y_pix): astra.data2d.store(data_id, data[i, :, :]) astra.algorithm.run(alg_id) rec[i, :, :] = astra.data2d.get(rec_id) astra.algorithm.delete(alg_id) astra.data3d.delete(rec_id) astra.data3d.delete(data_id) else: rec = np.zeros([y_pix, thickness, x_pix], data.dtype) vol_geom = astra.create_vol_geom(thickness, x_pix) proj_geom = astra.create_proj_geom('parallel', 1.0, x_pix, thetas) proj_id = astra.create_projector('strip', proj_geom, vol_geom) rec_id = astra.data2d.create('-vol', vol_geom) sinogram_id = astra.data2d.create('-sino', proj_geom, data[0, :, :]) cfg = astra.astra_dict('FBP') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id cfg['ProjectorId'] = proj_id cfg['option'] = {} cfg['option']['FilterType'] = 'ram-lak' alg_id = astra.algorithm.create(cfg) for i in range(0, y_pix): astra.data2d.store(sinogram_id, data[i, :, :]) astra.algorithm.run(alg_id) rec[i, :, :] = astra.data2d.get(rec_id) astra.algorithm.delete(alg_id) astra.data2d.delete(rec_id) astra.data2d.delete(sinogram_id) astra.clear() return rec
def astra_sirt(stack, angles, thickness=None, iterations=50, constrain=True, thresh=0, cuda=False): """ Perform SIRT reconstruction using the Astra toolbox algorithms. Args ---------- stack : NumPy array Tilt series data either of the form [angles, x] or [angles, y, x] where y is the tilt axis and x is the projection axis. angles : list or NumPy array Projection angles in degrees. thickness : int or float Number of pixels in the projection (through-thickness) direction for the reconstructed volume. If None, thickness is set to be the same as that in the x-direction of the sinogram. iterations : integer Number of iterations for the SIRT reconstruction. constrain : boolean If True, output reconstruction is constrained above value given by 'thresh'. Default is True. thresh : integer or float Value above which to constrain the reconstructed data if 'constrain' is True. cuda : boolean If True, use the CUDA-accelerated Astra algorithms. Otherwise, use the CPU-based algorithms Returns ---------- rec : Numpy array 3D array of the form [y, z, x] containing the reconstructed object. """ thetas = angles * np.pi / 180 if len(stack.shape) == 2: data = np.expand_dims(stack, 1) else: data = stack data = np.rollaxis(data, 1) y_pix, n_angles, x_pix = data.shape if thickness is None: thickness = data.shape[2] if cuda: chunksize = 128 rec = np.zeros([y_pix, thickness, x_pix], data.dtype) nchunks = int(np.ceil(y_pix / chunksize)) if nchunks == 1: chunksize = y_pix chunk_list = [[0, y_pix]] else: chunk_list = [None] * nchunks for i in range(0, int(y_pix / chunksize)): chunk_list[i] = [i * chunksize, (i + 1) * chunksize] if (np.mod(y_pix, chunksize) != 0) and (nchunks > 1): chunk_list[-1] = [ chunk_list[-2][1], chunk_list[-2][1] + np.mod(y_pix, chunksize) ] for i in range(0, len(chunk_list)): chunk = data[chunk_list[i][0]:chunk_list[i][1], :, :] vol_geom = astra.create_vol_geom(thickness, x_pix, chunk.shape[0]) proj_geom = astra.create_proj_geom('parallel3d', 1, 1, chunk.shape[0], x_pix, thetas) data_id = astra.data3d.create('-proj3d', proj_geom, chunk) rec_id = astra.data3d.create('-vol', vol_geom) cfg = astra.astra_dict('SIRT3D_CUDA') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = data_id if constrain: cfg['option'] = {} cfg['option']['MinConstraint'] = thresh alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id, iterations) rec[chunk_list[i][0]:chunk_list[i][1], :, :] =\ astra.data3d.get(rec_id) astra.algorithm.delete(alg_id) astra.data3d.delete(rec_id) astra.data3d.delete(data_id) else: rec = np.zeros([y_pix, thickness, x_pix], data.dtype) vol_geom = astra.create_vol_geom(thickness, x_pix) proj_geom = astra.create_proj_geom('parallel', 1.0, x_pix, thetas) proj_id = astra.create_projector('strip', proj_geom, vol_geom) rec_id = astra.data2d.create('-vol', vol_geom) sinogram_id = astra.data2d.create('-sino', proj_geom, data[0, :, :]) cfg = astra.astra_dict('SIRT') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id cfg['ProjectorId'] = proj_id if constrain: cfg['option'] = {} cfg['option']['MinConstraint'] = thresh alg_id = astra.algorithm.create(cfg) for i in range(0, y_pix): astra.data2d.store(sinogram_id, data[i, :, :]) astra.algorithm.run(alg_id, iterations) rec[i, :, :] = astra.data2d.get(rec_id) astra.algorithm.delete(alg_id) astra.data2d.delete(rec_id) astra.data2d.delete(sinogram_id) astra.clear() return rec