diff options
Diffstat (limited to 'src/processors')
-rw-r--r-- | src/processors/FBP.py | 32 | ||||
-rw-r--r-- | src/processors/FBP_Stacked.py | 85 | ||||
-rw-r--r-- | src/processors/FBP_Standard.py | 80 | ||||
-rw-r--r-- | src/processors/UfoStackedBackProjector.py | 101 | ||||
-rw-r--r-- | src/processors/UfoStackedForwardProjector.py | 100 | ||||
-rw-r--r-- | src/processors/UfoStandardBackProjector.py | 93 | ||||
-rw-r--r-- | src/processors/UfoStandardForwardProjector.py | 89 | ||||
-rw-r--r-- | src/processors/__init__.py | 5 |
8 files changed, 585 insertions, 0 deletions
diff --git a/src/processors/FBP.py b/src/processors/FBP.py new file mode 100644 index 0000000..c48c590 --- /dev/null +++ b/src/processors/FBP.py @@ -0,0 +1,32 @@ +from cil.framework import DataProcessor +from cil.framework import DataOrder +from src.processors.FBP_Standard import FBP_Standard +from src.processors.FBP_Stacked import FBP_Stacked + +class FBP(DataProcessor): + def __init__(self, volume_geometry, sinogram_geometry, stacked=False, precision_mode='single', stack_num=2): + if stacked==True: + processor = FBP_Stacked(volume_geometry, sinogram_geometry, precision_mode, stack_num) + else: + processor = FBP_Standard(volume_geometry, sinogram_geometry) + + super(FBP, self).__init__(volume_geometry=volume_geometry, sinogram_geometry=sinogram_geometry, + stacked=stacked, + precision_mode=precision_mode, stack_num=stack_num, processor=processor) + + self.processor = processor + + def set_input(self, dataset): + return self.processor.set_input(dataset) + + def get_input(self): + return self.processor.get_input() + + def get_output(self, out=None): + return self.processor.get_output(out=None) + + def check_input(self, dataset): + return self.processor.check_input(dataset) + + def process(self, out=None): + return self.processor.process(out=None) diff --git a/src/processors/FBP_Stacked.py b/src/processors/FBP_Stacked.py new file mode 100644 index 0000000..b6310a1 --- /dev/null +++ b/src/processors/FBP_Stacked.py @@ -0,0 +1,85 @@ +from cil.framework import DataProcessor, ImageData +import numpy as np + +import gi +gi.require_version('Ufo','0.0') +from gi.repository import Ufo + +class FBP_Stacked(DataProcessor): + def __init__(self, volume_geometry, + sinogram_geometry, + precision_mode='single', + stack_num=2): + + kwargs = { + 'volume_geometry': volume_geometry, + 'sinogram_geometry': sinogram_geometry, + 'precision_mode': precision_mode, + 'stack_num': stack_num} + + super(FBP_Stacked, 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.sinogram_geometry.dimension == '2D': + raise ValueError("Expected input dimensions is 3, got {0}" \ + .format(dataset.number_of_dimensions)) + return True + + def set_ImageGeometry(self, volume_geometry): + self.volume_geometry = volume_geometry + + def set_AcquisitionGeometry(self, sinogram_geometry): + self.sinogram_geometry = sinogram_geometry + + def process(self, **kwargs): + # Get DATA + DATA = self.get_input() + DATA = DATA.as_array() + + pm = Ufo.PluginManager() + graph = Ufo.TaskGraph() + scheduler = Ufo.Scheduler() + + read = pm.get_task('memory-in') + read.props.pointer = DATA.__array_interface__['data'][0] + read.props.width = DATA.shape[1] + read.props.height = DATA.shape[0] + read.props.number = DATA.shape[2] + read.props.bitdepth = 32 + + fft = pm.get_task('fft') + fft.props.dimensions = 1 + + filter = pm.get_task('filter') + + ifft = pm.get_task('ifft') + ifft.props.dimensions = 1 + + stack = pm.get_task('stack') + stack.props.number = self.stack_num + + stacked_bp = pm.get_task('stacked-backproject') + stacked_bp.props.axis_pos = DATA.shape[1] / 2 + stacked_bp.props.precision_mode = self.precision_mode + + vol_arr = np.zeros(self.volume_geometry.shape, dtype=np.float32) + + write = pm.get_task('memory-out') + write.props.pointer = vol_arr.__array_interface__['data'][0] + write.props.max_size = vol_arr.nbytes + + graph.connect_nodes(read, fft) + graph.connect_nodes(fft, filter) + graph.connect_nodes(filter, ifft) + graph.connect_nodes(ifft, stack) + graph.connect_nodes(stack, stacked_bp) + graph.connect_nodes(stacked_bp, write) + + scheduler.run(graph) + vol_arr = ImageData(vol_arr, deep_copy=False, geometry=self.volume_geometry.copy(), suppress_warning=True) + return vol_arr diff --git a/src/processors/FBP_Standard.py b/src/processors/FBP_Standard.py new file mode 100644 index 0000000..3fdb91c --- /dev/null +++ b/src/processors/FBP_Standard.py @@ -0,0 +1,80 @@ +from cil.framework import DataProcessor, ImageData +import numpy as np + +import gi +gi.require_version('Ufo','0.0') +from gi.repository import Ufo + +class FBP_Standard(DataProcessor): + def __init__(self, volume_geometry, + sinogram_geometry, + z_dim = None): + + kwargs = { + 'volume_geometry': volume_geometry, + 'sinogram_geometry': sinogram_geometry, + 'z_dim': z_dim} + + super(FBP_Standard, self).__init__(**kwargs) + + self.z_dim = 0 + self.set_ImageGeometry(volume_geometry) + self.set_AcquisitionGeometry(sinogram_geometry) + + def check_input(self, dataset): + if self.sinogram_geometry.dimension == '2D': + self.z_dim = 1 + elif self.sinogram_geometry.dimension == '3D': + self.z_dim = self.sinogram_geometry.shape[2] + + return True + + def set_ImageGeometry(self, volume_geometry): + self.volume_geometry = volume_geometry + + def set_AcquisitionGeometry(self, sinogram_geometry): + self.sinogram_geometry = sinogram_geometry + + def process(self, **kwargs): + # Get DATA + DATA = self.get_input() + DATA = DATA.as_array() + + pm = Ufo.PluginManager() + graph = Ufo.TaskGraph() + scheduler = Ufo.Scheduler() + + read = pm.get_task('memory-in') + read.props.pointer = DATA.__array_interface__['data'][0] + read.props.width = DATA.shape[1] + read.props.height = DATA.shape[0] + read.props.number = self.z_dim + read.props.bitdepth = 32 + + fft = pm.get_task('fft') + fft.props.dimensions = 1 + + filter = pm.get_task('filter') + + ifft = pm.get_task('ifft') + ifft.props.dimensions = 1 + + bp = pm.get_task('backproject') + bp.props.axis_pos = DATA.shape[1] / 2 + + vol_arr = np.zeros(self.volume_geometry.shape, dtype=np.float32) + + write = pm.get_task('memory-out') + write.props.pointer = vol_arr.__array_interface__['data'][0] + write.props.max_size = vol_arr.nbytes + + graph.connect_nodes(read, fft) + graph.connect_nodes(fft, filter) + graph.connect_nodes(filter, ifft) + graph.connect_nodes(ifft, bp) + graph.connect_nodes(bp, write) + + scheduler.run(graph) + vol_arr = ImageData(vol_arr, deep_copy=False, geometry=self.volume_geometry.copy(), suppress_warning=True) + + return vol_arr diff --git a/src/processors/UfoStackedBackProjector.py b/src/processors/UfoStackedBackProjector.py new file mode 100644 index 0000000..a08b0c4 --- /dev/null +++ b/src/processors/UfoStackedBackProjector.py @@ -0,0 +1,101 @@ +import tifffile +from cil.framework import DataProcessor, ImageData, DataOrder +import gi + +gi.require_version('Ufo', '0.0') +from gi.repository import Ufo +import numpy as np + + +class UfoStackedBackProjector(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(UfoStackedBackProjector, 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.sinogram_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): + + DATA = self.get_input() + + data_temp = DATA.as_array() + + arr_out = self.create_backprojection(data_temp, out) + + if out is None: + out = ImageData(arr_out, deep_copy=False, geometry=self.volume_geometry.copy(), suppress_warning=True) + return out + else: + out.fill(arr_out) + + def create_backprojection(self, sino, vol): + + pm = Ufo.PluginManager() + graph = Ufo.TaskGraph() + scheduler = Ufo.Scheduler() + + read = pm.get_task('memory-in') + read.props.pointer = sino.__array_interface__['data'][0] + read.props.width = sino.shape[0] + read.props.height = sino.shape[1] + read.props.number = sino.shape[2] + read.props.bitdepth = 32 + + stack = pm.get_task('stack') + stack.props.number = self.stack_num + + stacked_bp = pm.get_task('stacked-backproject') + stacked_bp.props.axis_pos = sino.shape[1] / 2 + stacked_bp.props.precision_mode = self.precision_mode + + vol_arr = np.zeros(self.volume_geometry.shape, dtype=np.float32) + + write = pm.get_task('memory-out') + write.props.pointer = vol_arr.__array_interface__['data'][0] + write.props.max_size = vol_arr.nbytes + + graph.connect_nodes(read, stack) + graph.connect_nodes(stack, stacked_bp) + graph.connect_nodes(stacked_bp, write) + + scheduler.run(graph) + + return vol_arr diff --git a/src/processors/UfoStackedForwardProjector.py b/src/processors/UfoStackedForwardProjector.py new file mode 100644 index 0000000..86513c6 --- /dev/null +++ b/src/processors/UfoStackedForwardProjector.py @@ -0,0 +1,100 @@ +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 diff --git a/src/processors/UfoStandardBackProjector.py b/src/processors/UfoStandardBackProjector.py new file mode 100644 index 0000000..ee27753 --- /dev/null +++ b/src/processors/UfoStandardBackProjector.py @@ -0,0 +1,93 @@ +#import tifffile +from cil.framework import DataProcessor, ImageData, DataOrder +import gi + +gi.require_version('Ufo', '0.0') +from gi.repository import Ufo +import numpy as np + + +class UfoStandardBackProjector(DataProcessor): + + def __init__(self, + volume_geometry=None, + sinogram_geometry=None): + kwargs = { + 'volume_geometry': volume_geometry, + 'sinogram_geometry': sinogram_geometry} + + super(UfoStandardBackProjector, self).__init__(**kwargs) + + self.set_ImageGeometry(volume_geometry) + self.set_AcquisitionGeometry(sinogram_geometry) + + def check_input(self, dataset): + + if self.sinogram_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): + + DATA = self.get_input() + + data_temp = DATA.as_array() + + arr_out = self.create_backprojection(data_temp, out) + + if out is None: + out = ImageData(arr_out, deep_copy=False, geometry=self.volume_geometry.copy(), suppress_warning=True) + return out + else: + out.fill(arr_out) + + def create_backprojection(self, sino, vol): + + pm = Ufo.PluginManager() + graph = Ufo.TaskGraph() + scheduler = Ufo.Scheduler() + + read = pm.get_task('memory-in') + read.props.pointer = sino.__array_interface__['data'][0] + read.props.width = sino.shape[1] + read.props.height = sino.shape[0] + if(len(sino.shape)==2): + read.props.number = 1 + else: + read.props.number = sino.shape[2] + read.props.bitdepth = 32 + + backproject = pm.get_task('backproject') + backproject.props.axis_pos = sino.shape[1] / 2 + + vol_arr = np.zeros(self.volume_geometry.shape, dtype=np.float32) + + write = pm.get_task('memory-out') + write.props.pointer = vol_arr.__array_interface__['data'][0] + write.props.max_size = vol_arr.nbytes + + graph.connect_nodes(read, backproject) + graph.connect_nodes(backproject, write) + + scheduler.run(graph) + + return vol_arr diff --git a/src/processors/UfoStandardForwardProjector.py b/src/processors/UfoStandardForwardProjector.py new file mode 100644 index 0000000..bb6e0b4 --- /dev/null +++ b/src/processors/UfoStandardForwardProjector.py @@ -0,0 +1,89 @@ +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 diff --git a/src/processors/__init__.py b/src/processors/__init__.py new file mode 100644 index 0000000..c913057 --- /dev/null +++ b/src/processors/__init__.py @@ -0,0 +1,5 @@ +from .UfoStandardForwardProjector import UfoStandardForwardProjector +from .UfoStandardBackProjector import UfoStandardBackProjector +from .UfoStackedForwardProjector import UfoStackedForwardProjector +from .UfoStackedBackProjector import UfoStackedBackProjector +from .FBP import FBP |