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 _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 _backproject_block_add_(projections, volume, proj_geom, vol_geom, algorithm='BP3D_CUDA', negative=False): """ Additive backprojection of a single block. Use negative = True if you want subtraction instead of addition. """ try: if negative: projections *= -1 # If volume is a memmap - create a temporary copy in RAM if isinstance(volume, numpy.memmap): vol_temp = numpy.ascontiguousarray(volume) vol_id = astra.data3d.link('-vol', vol_geom, vol_temp) else: vol_id = astra.data3d.link('-vol', vol_geom, volume) sin_id = astra.data3d.link('-sino', proj_geom, projections) projector_id = astra.create_projector('cuda3d', proj_geom, vol_geom) # We are using accumulate version to avoid creating additional copies of data. 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.') if isinstance(volume, numpy.memmap): volume[:] = vol_temp except: # The idea here is that we try to delete data3d objects even if ASTRA crashed try: if negative: projections *= -1 astra.algorithm.delete(projector_id) astra.data3d.delete(sin_id) astra.data3d.delete(vol_id) finally: info = sys.exc_info() traceback.print_exception(*info) if negative: projections *= -1 astra.algorithm.delete(projector_id) astra.data3d.delete(sin_id) astra.data3d.delete(vol_id)
def _backproject_block_(projections, volume, proj_geom, vol_geom, algorithm='BP3D_CUDA', operation='+'): """ Use this internal function to compute backprojection of a single block of data. """ try: if (operation == '+'): volume_ = volume elif (operation == '*') | (operation == '/'): volume_ = np.zeros_like(volume) 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) 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.') if (operation == '*'): volume *= volume_ elif (operation == '/'): volume_[volume_ < 1e-10] = numpy.inf volume /= volume_ except: print("ASTRA error:", sys.exc_info()) finally: astra.algorithm.delete(projector_id) astra.data3d.delete(sin_id) astra.data3d.delete(vol_id)
def _backproject_block_(projections, volume, proj_geom, vol_geom, algorithm = 'BP3D_CUDA', operation = '+'): """ Use this internal function to compute backprojection of a single block of data. """ # Unfortunately need to hide the experimental ASTRA import astra.experimental as asex try: if (operation == '+'): volume_ = volume elif (operation == '*') | (operation == '/'): volume_ = numpy.zeros_like(volume) 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) 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.') if (operation == '*'): volume *= volume_ #flexUtil.display_slice(volume, dim = 0, title = 'worm') # This is really slow but needed in case of overlap for EM: volume_ *= 0 astra.data3d.delete(sin_id) sin_id = astra.data3d.link('-sino', proj_geom, projections * 0 + 1) asex.accumulate_BP(projector_id, vol_id, sin_id) #flexUtil.display_slice(volume_, dim = 0, title = 'norm') volume_[volume_ < 0.01] = 0.01 volume /= volume_ #flexUtil.display_slice(volume, dim = 0, title = 'rorm') elif (operation == '/'): volume_[volume_ < 1e-3] = numpy.inf volume /= volume_ except: print("ASTRA error:", sys.exc_info()) finally: astra.algorithm.delete(projector_id) astra.data3d.delete(sin_id) astra.data3d.delete(vol_id)