summaryrefslogtreecommitdiffstats
path: root/src/processors/UfoStandardBackProjector.py
blob: ee277530336fce09fccffa9b3325a95314def590 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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