summaryrefslogtreecommitdiffstats
path: root/src/processors
diff options
context:
space:
mode:
Diffstat (limited to 'src/processors')
-rw-r--r--src/processors/FBP.py32
-rw-r--r--src/processors/FBP_Stacked.py85
-rw-r--r--src/processors/FBP_Standard.py80
-rw-r--r--src/processors/UfoStackedBackProjector.py101
-rw-r--r--src/processors/UfoStackedForwardProjector.py100
-rw-r--r--src/processors/UfoStandardBackProjector.py93
-rw-r--r--src/processors/UfoStandardForwardProjector.py89
-rw-r--r--src/processors/__init__.py5
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