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 UfoStandardForwardProjector(DataProcessor): def __init__(self, volume_geometry=None, sinogram_geometry=None): kwargs = { 'volume_geometry': volume_geometry, 'sinogram_geometry': sinogram_geometry } super(UfoStandardForwardProjector, self).__init__(**kwargs) 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[1] read.props.height = vol.shape[0] if(len(vol.shape) == 2): read.props.number = 1 else: read.props.number = vol.shape[2] read.props.bitdepth = 32 forwardproject = pm.get_task('forwardproject') forwardproject.props.number = vol.shape[0] 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, forwardproject) graph.connect_nodes(forwardproject, write) scheduler.run(graph) return sino_arr