def matvec(self, v): sid, s = astra.create_sino( np.reshape(v, (vol_geom['GridRowCount'], vol_geom['GridColCount'])), self.proj_id) # , useCUDA=True) astra.data2d.delete(sid) return s.flatten()
def matvec(self, v): sid, s = astra.create_sino( np.reshape(v, (vol_geom['GridRowCount'], vol_geom['GridColCount'])), self.proj_id) astra.data2d.delete(sid) return s.ravel()
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 forwprojOS(self, image, no_os): """Applying forward projection for a specific subset""" sinogram_id, sinogram = astra.create_sino(image, self.proj_id_OS[no_os]) astra.data2d.delete(sinogram_id) astra.data2d.delete(self.proj_id_OS[no_os]) return sinogram
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 forward(self, x): Y = np.empty((x.shape[0], len(self.angles), x.shape[1]), dtype=np.float32) for i in range(x.shape[0]): pid, Y[i] = astra.create_sino(x[i], self.proj_id) self.data2d.append(pid) return Y
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 forward_single(self, x): vol_geom = astra.create_vol_geom(x.shape[0], x.shape[1]) proj_geom = astra.create_proj_geom('parallel', 1.0, x.shape[0], self.angles) proj_id = astra.create_projector('cuda', proj_geom, vol_geom) self.projectors.append(proj_id) return astra.create_sino(x, proj_id)
def forward(self, x): device = x.device x = x.cpu().numpy() Y = np.empty((x.shape[0], len(self.angles), x.shape[1]), dtype=np.float32) for i in range(x.shape[0]): _, Y[i] = astra.create_sino(x[i], self.proj_id) return torch.from_numpy(Y).to(device)
def test_fanbeam_error(device, batch_size, image_size, angles, spacing, distances, det_count, clip_to_circle): # generate random images # generate random images det_count = int(det_count * image_size) mask_radius = det_count / 2.0 if clip_to_circle else -1 x = generate_random_images(1, image_size, mask_radius)[0] s_dist, d_dist = distances s_dist *= image_size d_dist *= image_size # astra vol_geom = astra.create_vol_geom(x.shape[0], x.shape[1]) proj_geom = astra.create_proj_geom('fanflat', spacing, det_count, angles, s_dist, d_dist) proj_id = astra.create_projector('cuda', proj_geom, vol_geom) id, astra_y = astra.create_sino(x, proj_id) _, astra_bp = astra.create_backprojection(astra_y, proj_id) if clip_to_circle: astra_bp *= circle_mask(image_size, mask_radius) # TODO clean astra structures # our implementation radon = RadonFanbeam(image_size, angles, s_dist, d_dist, det_count=det_count, det_spacing=spacing, clip_to_circle=clip_to_circle) x = torch.FloatTensor(x).to(device).view(1, x.shape[0], x.shape[1]) # repeat data to fill batch size x = torch.cat([x] * batch_size, dim=0) our_fp = radon.forward(x) our_bp = radon.backprojection(our_fp) forward_error = relative_error(astra_y, our_fp[0].cpu().numpy()) back_error = relative_error(astra_bp, our_bp[0].cpu().numpy()) # if back_error > 5e-3: # plt.imshow(astra_bp) # plt.figure() # plt.imshow(our_bp[0].cpu().numpy()) # plt.show() print(np.max(our_fp.cpu().numpy()), np.max(our_bp.cpu().numpy())) print( f"batch: {batch_size}, size: {image_size}, angles: {len(angles)}, spacing: {spacing}, distances: {distances} circle: {clip_to_circle}, forward: {forward_error}, back: {back_error}" ) # TODO better checks assert_less(forward_error, 1e-2) assert_less(back_error, 5e-3)
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 _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 proj(img, num_sen, sen_width, theta): shape = img.shape if not len(shape) == 2: raise ValueError('Invalid img shape {}.'.format(shape)) vol_geom = astra.create_vol_geom(*shape) proj_geom = astra.create_proj_geom('parallel', sen_width, num_sen, theta) proj_id = astra.create_projector('cuda', proj_geom, vol_geom) sinogram_id, sinogram = astra.create_sino(img, proj_id) sinogram = np.array(sinogram) astra.data2d.clear() astra.projector.clear() astra.algorithm.clear() return sinogram
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 sinogram(p, r, n, poisson_noise=False, s_and_p_noise = False, gaussian_noise = False, prob=10**-2, val=None, mean =0, std=None): # Create geometries and projector #adds noise to sinogram too # p is phantom # r is range of angles eg pi # n is number of angles used #prob : float, optional #Independent probability that each element of a pixel might be #corrupted by the salt and pepper type noise. #val : float, optional #Value to be assigned to the corrupted pixels. projector_id = geom_setup(p.shape[0], r, n)[1] # Create sinogram. sinogram = astra.create_sino(p, projector_id)[1] #Noise section is 95% copied from tomopy #https://tomopy.readthedocs.io/en/latest/_modules/tomopy/sim/project.html #if poisson_noise == True: #sinogram = np.random.poisson(sinogram) #return sinogram #sinogram = np.random.poisson(sinogram * 10000) / 10000 #sinogram[sinogram > 1.1] = 1.1 #sinogram /= 1.1 if s_and_p_noise == True: dx, dy = sinogram.shape ind = np.random.rand(dx, dy) < prob if val is None: val = sinogram.max() sinogram[ind] = val return sinogram else: sinogram[ind] = val if gaussian_noise == True: #sinogram = np.ndarray.dtype.as_ndarray(sinogram) if std is None: std = sinogram.max() * 0.5 dx, dy = sinogram.shape sinogram += std * np.random.randn(dx, dy) + mean return sinogram
def fanflat_simulation(dectors_numbers, matrix_data): vol_geom = astra.create_vol_geom(256, 256) proj_geom = astra.create_proj_geom('fanflat_vec', dectors_numbers, matrix_data) # As before, create a sinogram from a phantom import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] proj_id = astra.create_projector('line_fanflat', proj_geom, vol_geom) #TODO: fix that, maybe in cuda works 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 configuration cfg = astra.astra_dict('FBP') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id cfg['ProjectorId'] = proj_id cfg['option'] = { 'FilterType': 'Ram-Lak' } # possible values for FilterType: # none, ram-lak, shepp-logan, cosine, hamming, hann, tukey, lanczos, # triangular, gaussian, barlett-hann, blackman, nuttall, blackman-harris, # blackman-nuttall, flat-top, kaiser, parzen # Create and run the algorithm object from the configuration structure alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id) # Get the result rec = astra.data2d.get(rec_id) pylab.figure(3) pylab.imshow(rec) pylab.show() # 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.data2d.delete(rec_id) astra.data2d.delete(sinogram_id) astra.projector.delete(proj_id)
def process(self, out=None): IM = self.get_input() sinogram_id, arr_out = astra.create_sino(IM.as_array(), self.proj_id) astra.data2d.delete(sinogram_id) if out is None: out = AcquisitionData(arr_out, deep_copy=False, geometry=self.sinogram_geometry.copy(), suppress_warning=True) return out else: out.fill(arr_out)
def fp(image, projector_id): """Wrapper for astra forward projector :param image: :param projector_id: :return: sinogram """ sino_id, sino = astra.create_sino(image, projector_id) sino *= voxel_size_mm sino /= sino.shape[0] astra.data2d.delete(sino_id) return sino
def process(self, out=None): IM = self.get_input() if out is None: DATA = self.sinogram_geometry.allocate(None) else: DATA = out for k in range(DATA.geometry.channels): vol_temp = IM.as_array()[k] sinogram_id, DATA.as_array()[k] = astra.create_sino( vol_temp, self.proj_id) astra.data2d.delete(sinogram_id) if out is None: return DATA
def process(self): IM = self.get_input() DATA = AcquisitionData(geometry=self.sinogram_geometry) #sinogram_id, DATA = astra.create_sino( IM.as_array(), # self.proj_id) sinogram_id, DATA.array = astra.create_sino(IM.as_array(), self.proj_id) astra.data2d.delete(sinogram_id) if self.device == 'cpu': return DATA else: if self.sinogram_geometry.geom_type == 'cone': return DATA else: scaling = 1.0 / self.volume_geometry.voxel_size_x return scaling * DATA
def astra_project(obj, angles, cuda=False): """ Calculate projection of a 3D object using Astra-toolbox. Args ---------- obj : NumPy array Either a 2D or 3D array containing the object to project. If 2D, the structure is of the form [z, x] where z is the projection axis. If 3D, the strucutre is [y, z, x] where y is the tilt axis. angles : list or NumPy array The projection angles in degrees cuda : boolean If True, perform reconstruction using the GPU-accelerated algorithm. Returns ---------- sino : Numpy array 3D array of the form [y, angle, x] containing the projection of the input object """ if len(obj.shape) == 2: obj = np.expand_dims(obj, 0) thetas = np.pi * angles / 180. y_pix, thickness, x_pix = obj.shape if cuda: vol_geom = astra.create_vol_geom(thickness, x_pix, y_pix) proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0, y_pix, x_pix, thetas) sino_id, sino = astra.create_sino3d_gpu(obj, proj_geom, vol_geom) astra.data3d.delete(sino_id) else: sino = np.zeros([y_pix, len(angles), x_pix], np.float32) 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) for i in range(0, y_pix): sino_id, sino[i, :, :] = astra.create_sino(obj[i, :, :], proj_id, vol_geom) astra.data2d.delete(sino_id) sino = np.rollaxis(sino, 1) return sino
def process(self): IM = self.get_input() #create the output AcquisitionData DATA = AcquisitionData(geometry=self.sinogram_geometry) for k in range(DATA.geometry.channels): sinogram_id, DATA.as_array()[k] = astra.create_sino( IM.as_array()[k], self.proj_id) astra.data2d.delete(sinogram_id) if self.device == 'cpu': return DATA else: if self.sinogram_geometry.geom_type == 'cone': return DATA else: scaling = (1.0 / self.volume_geometry.voxel_size_x) return scaling * DATA
def get_A_b(img, angles, det_row_count=1, det_col_count=256): ''' Возвращает матрицу системы линейных уравнений params: img - изображение angles - количество углов проекций det_row_count - расстояние между 2 проекциями детектора det_col_count - количество измерений для каждого угла return: A - system matrix b - projection vector ''' vol_geom = astra.create_vol_geom(img.shape[0], img.shape[1]) proj_geom = astra.create_proj_geom('parallel', det_row_count, det_col_count, angles) proj_id = astra.create_projector('linear', proj_geom, vol_geom) matrix_id = astra.projector.matrix(proj_id) A = astra.matrix.get(matrix_id).astype(np.float) sinogram_id, sino = astra.create_sino(img, proj_id) return A, sino
def __getitem__(self, idx): if self.Dataset_name in ['Mayo_test', 'MayoRaw_test']: img, ld_img, imgname = self.imgset[idx] else: img, ld_img = self.imgset[idx] if self.Dataset_name in ['MayoRaw_test', 'MayoRaw']: sinogram = ld_img else: sinogram = [] for i in range(self.recon_slices): sinogram_id, sinogram_tmp = astra.create_sino( ld_img[i], self.proj_id) astra.data2d.delete(sinogram_id) sinogram.append(sinogram_tmp) if self.post_trans_img is not None: for i in range(self.recon_slices): img[i], _, _ = self.post_trans_img(img[i]) sinogram[i] = self.img_a * sinogram[i] + self.img_Ab img, sinogram = np.array(img), np.array(sinogram) if self.post_trans_sino is not None: sinogram, _, _ = self.post_trans_sino(sinogram) if self.Dataset_name in ['Mayo', 'MayoRaw']: sample = { 'ndct': torch.from_numpy(img).type(torch.FloatTensor), 'sinogram': torch.from_numpy(sinogram).type(torch.FloatTensor) } else: sample = { 'ndct': torch.from_numpy(img).type(torch.FloatTensor), 'sinogram': torch.from_numpy(sinogram).type(torch.FloatTensor), 'name': imgname, 'RescaleSlope': self.img_a, 'RescaleIntercept': self.img_Ab } return sample
def create_model_tilt_series(model, angles=None): """ Create a tilt series from a 3D volume. Args ---------- model : NumPy array 3D array containing the model volume to project to a tilt series angles : NumPy array Projection angles for tilt series Returns ---------- model : TomoStack object Tilt series of the model data """ if type(angles) is not np.ndarray: angles = np.arange(0, 180, 2) if type(model) is hs.signals.Signal2D: model = model.data xdim = model.shape[2] ydim = model.shape[1] thickness = model.shape[0] proj_data = np.zeros([len(angles), ydim, xdim]) vol_geom = astra.create_vol_geom(thickness, xdim, ydim) tilts = angles * np.pi / 180 proj_geom = astra.create_proj_geom('parallel', 1, xdim, tilts) proj_id = astra.create_projector('strip', proj_geom, vol_geom) for i in range(0, model.shape[1]): sino_id, proj_data[:, i, :] = astra.create_sino(model[:, i, :], proj_id) stack = numpy_to_tomo_stack(proj_data) stack.axes_manager[0].offset = angles[0] stack.axes_manager[0].scale = np.abs(angles[1] - angles[0]) return stack
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 __init__(self, root_dir, folder, geo, pre_trans_img=None, post_trans_img=None, post_trans_sino=None, Dataset_name='Mayo_test'): self.Dataset_name = Dataset_name self.imgset = TrainData(root_dir, folder, geo['nVoxelX'], geo['slices'], pre_trans_img, Dataset_name) self.vol_geom = astra.create_vol_geom( geo['nVoxelY'], geo['nVoxelX'], -1 * geo['sVoxelY'] / 2 + geo['offOriginY'], geo['sVoxelY'] / 2 + geo['offOriginY'], -1 * geo['sVoxelX'] / 2 + geo['offOriginX'], geo['sVoxelX'] / 2 + geo['offOriginX']) self.proj_geom = astra.create_proj_geom( geo['mode'], geo['dDetecU'], geo['nDetecU'], np.linspace(geo['start_angle'], geo['end_angle'], geo['views'], False), geo['DSO'], geo['DOD']) if geo['mode'] is 'parallel': self.proj_id = astra.create_projector('linear', self.proj_geom, self.vol_geom) elif geo['mode'] is 'fanflat': self.proj_id = astra.create_projector('line_fanflat', self.proj_geom, self.vol_geom) #line_fanflat _, img_a, img_b = post_trans_img( np.ones((geo['nVoxelX'], geo['nVoxelY']))) sinogram_id, img_Ab = astra.create_sino( np.ones((geo['nVoxelX'], geo['nVoxelY'])) * img_b, self.proj_id) astra.data2d.delete(sinogram_id) self.img_a, self.img_Ab = img_a, img_Ab self.recon_slices = geo['slices'] self.post_trans_img = post_trans_img self.post_trans_sino = post_trans_sino
def radon(f, theta): ''' Takes a numpy.ndarray containing the discretisation of the data and theta containing the angles that the radon transform will be taken with and returns a numpy.ndarray containing the radon transformed data i.e a sinogram of f. ''' vol_geom = astra.create_vol_geom(f.shape[0], f.shape[1]) proj_geom = astra.create_proj_geom('parallel', 1.0, 367, theta) f_id = astra.data2d.create('-vol', vol_geom, f) sin_id = astra.data2d.create('-sino', proj_geom) proj_id = astra.create_projector('line', proj_geom, vol_geom) sin_id, sin_data = astra.create_sino(f, proj_id) astra.data2d.clear() astra.projector.clear() return sin_data
def SIRT_libr(img, angles, det_row_count=1, det_col_count=256): ''' Стандартный библиотечный SIRT ''' vol_geom = astra.create_vol_geom(img.shape[0], img.shape[1]) proj_geom = astra.create_proj_geom('parallel', det_row_count, det_col_count, angles) proj_id = astra.create_projector('linear', proj_geom, vol_geom) sinogram_id, sino = astra.create_sino(img, proj_id) start = time.time() recon_id = astra.data2d.create('-vol', vol_geom, 0) cfg = astra.astra_dict('SIRT') cfg['ProjectorId'] = proj_id cfg['ProjectionDataId'] = sinogram_id cfg['ReconstructionDataId'] = recon_id algorithm_id = astra.algorithm.create(cfg) astra.algorithm.run(algorithm_id, 200) new_img = astra.data2d.get(recon_id) end = time.time() plt.title('Стандартный SIRT') plt.imshow(new_img, cmap='gray') plt.show() print('Время работы SIRT из стандартной библиотеки: {} секунд'.format(end - start))
def forwproj(self, image): """Applying forward projection""" sinogram_id, sinogram = astra.create_sino(image, self.proj_id) astra.data2d.delete(sinogram_id) astra.data2d.delete(self.proj_id) return sinogram
def matvec(self,v): sid, s = astra.create_sino(np.reshape(v,(vol_geom['GridRowCount'],vol_geom['GridColCount'])),self.proj_id) astra.data2d.delete(sid) return s.ravel()
# --- ASTRA --- # Define ASTRA geometry vol_geom = astra.create_vol_geom(domain_size[0], domain_size[1]) proj_geom = astra.create_proj_geom('parallel', np.linalg.norm(domain_size) / det_size, det_size, np.linspace(0, np.pi, n_angles)) # Create ASTRA projector proj_id = astra.create_projector('line', proj_geom, vol_geom) # Create sinogram sinogram_id, sinogram = astra.create_sino(data, proj_id) # Create a data object for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom) # Set up the parameters for a reconstruction algorithm using the CPU backend cfg = astra.astra_dict('CGLS') 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) with odl.util.Timer('ASTRA run'): # Run the algorithm
# along with 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)) import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] 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, gpuIndex=1) # Set up the parameters for a reconstruction algorithm using the GPU rec_id = astra.data2d.create('-vol', vol_geom) cfg = astra.astra_dict('SIRT_CUDA') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id # Use GPU #1 for the reconstruction. (The default is #0.) cfg['option'] = {} cfg['option']['GPUindex'] = 1 # Run 150 iterations of the algorithm alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id, 150)
def matvec(self, v): sid, s = astra.create_sino( np.reshape(v, (vol_geom['GridRowCount'], vol_geom[ 'GridColCount'])), self.proj_id) # , useCUDA=True) astra.data2d.delete(sid) return s.flatten()
def proj(self, slice_data): sid, proj_data = astra.create_sino(slice_data, self.proj_id) astra.data2d.delete(sid) return proj_data
#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)) import scipy.io P = scipy.io.loadmat('phantom.mat')['phantom256'] proj_id = astra.create_projector('line',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) # Set up the parameters for a reconstruction algorithm using the GPU rec_id = astra.data2d.create('-vol', vol_geom) cfg = astra.astra_dict('SIRT_CUDA') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id # Use GPU #1 for the reconstruction. (The default is #0.) cfg['option'] = {} cfg['option']['GPUindex'] = 1 # Run 150 iterations of the algorithm alg_id = astra.algorithm.create(cfg) astra.algorithm.run(alg_id, 150)
except ImportError: # six 1.3.0 from six.moves import xrange as range import astra import numpy as np import scipy.io import matplotlib.pyplot as plt 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 P = scipy.io.loadmat('phantom.mat')['phantom256'] proj_id = astra.create_projector('cuda',proj_geom,vol_geom) sinogram_id, sinogram = astra.create_sino(P, proj_id) plt.gray() plt.figure(1) plt.imshow(P) plt.figure(2) plt.imshow(sinogram) # Create a data object for the reconstruction rec_id = astra.data2d.create('-vol', vol_geom) # Set up the parameters for a reconstruction algorithm using the GPU cfg = astra.astra_dict('SIRT_CUDA') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id
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') cfg['ReconstructionDataId'] = rec_id
from six.moves import range except ImportError: # six 1.3.0 from six.moves import xrange as range 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)) # 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) 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) # Set up the parameters for a reconstruction algorithm using the GPU cfg = astra.astra_dict('SIRT_CUDA') cfg['ReconstructionDataId'] = rec_id cfg['ProjectionDataId'] = sinogram_id
def single_test(self, type, proj_type): shape = np.random.randint(*range2d, size=2) # these rectangles are biased, but that shouldn't matter rect_min = [ np.random.randint(0, a) for a in shape ] rect_max = [ np.random.randint(rect_min[i]+1, shape[i]+1) for i in range(len(shape))] if FLEXVOL: if not NONSQUARE: pixsize = np.array([0.5, 0.5]) + np.random.random() else: pixsize = 0.5 + np.random.random(size=2) origin = 10 * np.random.random(size=2) else: pixsize = (1.,1.) origin = (0.,0.) vg = astra.create_vol_geom(shape[1], shape[0], origin[0] - 0.5 * shape[0] * pixsize[0], origin[0] + 0.5 * shape[0] * pixsize[0], origin[1] - 0.5 * shape[1] * pixsize[1], origin[1] + 0.5 * shape[1] * pixsize[1]) if type == 'parallel': pg = gen_random_geometry_parallel() projector_id = astra.create_projector(proj_type, pg, vg) elif type == 'parallel_vec': pg = gen_random_geometry_parallel_vec() projector_id = astra.create_projector(proj_type, pg, vg) elif type == 'fanflat': pg = gen_random_geometry_fanflat() projector_id = astra.create_projector(proj_type_to_fan(proj_type), pg, vg) elif type == 'fanflat_vec': pg = gen_random_geometry_fanflat_vec() projector_id = astra.create_projector(proj_type_to_fan(proj_type), pg, vg) data = np.zeros((shape[1], shape[0]), dtype=np.float32) data[rect_min[1]:rect_max[1],rect_min[0]:rect_max[0]] = 1 sinogram_id, sinogram = astra.create_sino(data, projector_id) self.assertTrue(np.all(np.isfinite(sinogram))) #print(pg) #print(vg) astra.data2d.delete(sinogram_id) astra.projector.delete(projector_id) # NB: Flipped y-axis here, since that is how astra interprets 2D volumes xmin = origin[0] + (-0.5 * shape[0] + rect_min[0]) * pixsize[0] xmax = origin[0] + (-0.5 * shape[0] + rect_max[0]) * pixsize[0] ymin = origin[1] + (+0.5 * shape[1] - rect_max[1]) * pixsize[1] ymax = origin[1] + (+0.5 * shape[1] - rect_min[1]) * pixsize[1] if proj_type == 'line': a = np.zeros(np.prod(astra.functions.geom_size(pg)), dtype=np.float32) b = np.zeros(np.prod(astra.functions.geom_size(pg)), dtype=np.float32) c = np.zeros(np.prod(astra.functions.geom_size(pg)), dtype=np.float32) for i, (center, edge1, edge2) in enumerate(gen_lines(pg)): (src, det) = center try: detweight = pg['DetectorWidth'] except KeyError: if 'fan' not in type: detweight = effective_detweight(src, det, pg['Vectors'][i//pg['DetectorCount'],4:6]) else: detweight = np.linalg.norm(pg['Vectors'][i//pg['DetectorCount'],4:6], ord=2) # We compute line intersections with slightly bigger (cw) and # smaller (aw) rectangles, and see if the kernel falls # between these two values. (aw,bw,cw) = intersect_line_rectangle_interval(src, det, xmin, xmax, ymin, ymax, 1e-3) a[i] = aw * detweight b[i] = bw * detweight c[i] = cw * detweight a = a.reshape(astra.functions.geom_size(pg)) b = b.reshape(astra.functions.geom_size(pg)) c = c.reshape(astra.functions.geom_size(pg)) if not np.all(np.isfinite(a)): raise RuntimeError("Invalid value in reference sinogram") if not np.all(np.isfinite(b)): raise RuntimeError("Invalid value in reference sinogram") if not np.all(np.isfinite(c)): raise RuntimeError("Invalid value in reference sinogram") self.assertTrue(np.all(np.isfinite(sinogram))) # Check if sinogram lies between a and c y = np.min(sinogram-a) z = np.min(c-sinogram) if DISPLAY and (z < 0 or y < 0): display_mismatch_triple(data, sinogram, a, b, c) self.assertFalse(z < 0 or y < 0) elif proj_type == 'linear' or proj_type == 'cuda': a = np.zeros(np.prod(astra.functions.geom_size(pg)), dtype=np.float32) for i, (center, edge1, edge2) in enumerate(gen_lines(pg)): (src, det) = center (xd, yd) = det - src try: detweight = pg['DetectorWidth'] except KeyError: if 'fan' not in type: detweight = effective_detweight(src, det, pg['Vectors'][i//pg['DetectorCount'],4:6]) else: detweight = np.linalg.norm(pg['Vectors'][i//pg['DetectorCount'],4:6], ord=2) l = 0.0 if np.abs(xd) > np.abs(yd): # horizontal ray length = math.sqrt(1.0 + abs(yd/xd)**2) y_seg = (ymin, ymax) for j in range(rect_min[0], rect_max[0]): x = origin[0] + (-0.5 * shape[0] + j + 0.5) * pixsize[0] w = intersect_line_vertical_segment_linear(center[0], center[1], x, y_seg, pixsize[1]) # limited interpolation precision with cuda if CUDA_8BIT_LINEAR and proj_type == 'cuda': w = np.round(w * 256.0) / 256.0 l += w * length * pixsize[0] * detweight else: length = math.sqrt(1.0 + abs(xd/yd)**2) x_seg = (xmin, xmax) for j in range(rect_min[1], rect_max[1]): y = origin[1] + (+0.5 * shape[1] - j - 0.5) * pixsize[1] w = intersect_line_horizontal_segment_linear(center[0], center[1], y, x_seg, pixsize[0]) # limited interpolation precision with cuda if CUDA_8BIT_LINEAR and proj_type == 'cuda': w = np.round(w * 256.0) / 256.0 l += w * length * pixsize[1] * detweight a[i] = l a = a.reshape(astra.functions.geom_size(pg)) if not np.all(np.isfinite(a)): raise RuntimeError("Invalid value in reference sinogram") x = np.max(np.abs(sinogram-a)) TOL = 2e-3 if proj_type != 'cuda' else CUDA_TOL if DISPLAY and x > TOL: display_mismatch(data, sinogram, a) self.assertFalse(x > TOL) elif proj_type == 'distance_driven': a = np.zeros(np.prod(astra.functions.geom_size(pg)), dtype=np.float32) for i, (center, edge1, edge2) in enumerate(gen_lines(pg)): (xd, yd) = center[1] - center[0] l = 0.0 if np.abs(xd) > np.abs(yd): # horizontal ray y_seg = (ymin, ymax) for j in range(rect_min[0], rect_max[0]): x = origin[0] + (-0.5 * shape[0] + j + 0.5) * pixsize[0] l += intersect_ray_vertical_segment(edge1, edge2, x, y_seg) * pixsize[0] else: x_seg = (xmin, xmax) for j in range(rect_min[1], rect_max[1]): y = origin[1] + (+0.5 * shape[1] - j - 0.5) * pixsize[1] l += intersect_ray_horizontal_segment(edge1, edge2, y, x_seg) * pixsize[1] a[i] = l a = a.reshape(astra.functions.geom_size(pg)) if not np.all(np.isfinite(a)): raise RuntimeError("Invalid value in reference sinogram") x = np.max(np.abs(sinogram-a)) TOL = 2e-3 if DISPLAY and x > TOL: display_mismatch(data, sinogram, a) self.assertFalse(x > TOL) elif proj_type == 'strip' and 'fan' in type: a = np.zeros(np.prod(astra.functions.geom_size(pg)), dtype=np.float32) for i, (center, edge1, edge2) in enumerate(gen_lines(pg)): (src, det) = center det_dist = np.linalg.norm(src-det, ord=2) l = 0.0 for j in range(rect_min[0], rect_max[0]): xmin = origin[0] + (-0.5 * shape[0] + j) * pixsize[0] xmax = origin[0] + (-0.5 * shape[0] + j + 1) * pixsize[0] xcen = 0.5 * (xmin + xmax) for k in range(rect_min[1], rect_max[1]): ymin = origin[1] + (+0.5 * shape[1] - k - 1) * pixsize[1] ymax = origin[1] + (+0.5 * shape[1] - k) * pixsize[1] ycen = 0.5 * (ymin + ymax) scale = det_dist / np.linalg.norm( src - np.array((xcen,ycen)), ord=2 ) w = intersect_ray_rect(edge1, edge2, xmin, xmax, ymin, ymax) l += w * scale a[i] = l a = a.reshape(astra.functions.geom_size(pg)) if not np.all(np.isfinite(a)): raise RuntimeError("Invalid value in reference sinogram") x = np.max(np.abs(sinogram-a)) TOL = 8e-3 if DISPLAY and x > TOL: display_mismatch(data, sinogram, a) self.assertFalse(x > TOL) elif proj_type == 'strip': a = np.zeros(np.prod(astra.functions.geom_size(pg)), dtype=np.float32) for i, (center, edge1, edge2) in enumerate(gen_lines(pg)): a[i] = intersect_ray_rect(edge1, edge2, xmin, xmax, ymin, ymax) a = a.reshape(astra.functions.geom_size(pg)) if not np.all(np.isfinite(a)): raise RuntimeError("Invalid value in reference sinogram") x = np.max(np.abs(sinogram-a)) TOL = 8e-3 if DISPLAY and x > TOL: display_mismatch(data, sinogram, a) self.assertFalse(x > TOL)