from cil.framework import DataProcessor, AcquisitionData, DataOrder import gi gi.require_version('Ufo', '0.0') from gi.repository import Ufo import numpy as np class UfoStackedForwardProjector(DataProcessor): def __init__(self, volume_geometry=None, sinogram_geometry=None, precision_mode=None, stack_num=None): kwargs = { 'volume_geometry': volume_geometry, 'sinogram_geometry': sinogram_geometry, 'precision_mode': precision_mode, 'stack_num': stack_num } super(UfoStackedForwardProjector, self).__init__(**kwargs) self.precision_mode = precision_mode self.stack_num = stack_num self.set_ImageGeometry(volume_geometry) self.set_AcquisitionGeometry(sinogram_geometry) def check_input(self, dataset): if self.volume_geometry.shape != dataset.geometry.shape: raise ValueError("Dataset not compatible with geometry used to create the projector") return True def set_ImageGeometry(self, volume_geometry): DataOrder.check_order_for_engine('astra', volume_geometry) if len(volume_geometry.dimension_labels) > 3: raise ValueError("Supports 2D and 3D data only, got {0}".format(volume_geometry.number_of_dimensions)) self.volume_geometry = volume_geometry.copy() def set_AcquisitionGeometry(self, sinogram_geometry): DataOrder.check_order_for_engine('astra', sinogram_geometry) if len(sinogram_geometry.dimension_labels) > 3: raise ValueError("Supports 2D and 3D data only, got {0}".format(self.volume_geometry.number_of_dimensions)) self.sinogram_geometry = sinogram_geometry.copy() def process(self, out=None): IM = self.get_input() data_temp = IM.as_array() arr_out = self.create_sinogram(data_temp, out) 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 create_sinogram(self, vol, sino): pm = Ufo.PluginManager() graph = Ufo.TaskGraph() scheduler = Ufo.Scheduler() read = pm.get_task('memory-in') read.props.pointer = vol.__array_interface__['data'][0] read.props.width = vol.shape[0] read.props.height = vol.shape[1] read.props.number = vol.shape[2] read.props.bitdepth = 32 stack = pm.get_task('stack') stack.props.number = self.stack_num stacked_fp = pm.get_task('stacked-forwardproject') stacked_fp.props.number = vol.shape[0] stacked_fp.props.precision_mode = self.precision_mode sino_arr = np.zeros(self.sinogram_geometry.shape, dtype=np.float32) write = pm.get_task('memory-out') write.props.pointer = sino_arr.__array_interface__['data'][0] write.props.max_size = sino_arr.nbytes graph.connect_nodes(read, stack) graph.connect_nodes(stack, stacked_fp) graph.connect_nodes(stacked_fp, write) scheduler.run(graph) return sino_arr