From 57b81fd1fe64cac63194386b383d40707e5bbdf0 Mon Sep 17 00:00:00 2001
From: Edoardo Pasca <edo.paskino@gmail.com>
Date: Fri, 21 Jun 2019 22:22:42 +0100
Subject: Reorganise processors (#24)

* add test phase

* updated test

* removed unused import

* updated test
---
 .../plugins/processors/AcquisitionDataPadder.py    | 116 +++++++++++++++++++++
 .../Python/ccpi/plugins/processors/__init__.py     |   2 +-
 Wrappers/Python/conda-recipe/meta.yaml             |  15 ++-
 Wrappers/Python/test/__init__.py                   |   0
 Wrappers/Python/test/test_Processors.py            |  55 ++++++++++
 5 files changed, 186 insertions(+), 2 deletions(-)
 create mode 100755 Wrappers/Python/ccpi/plugins/processors/AcquisitionDataPadder.py
 create mode 100644 Wrappers/Python/test/__init__.py
 create mode 100755 Wrappers/Python/test/test_Processors.py

diff --git a/Wrappers/Python/ccpi/plugins/processors/AcquisitionDataPadder.py b/Wrappers/Python/ccpi/plugins/processors/AcquisitionDataPadder.py
new file mode 100755
index 0000000..4033c7b
--- /dev/null
+++ b/Wrappers/Python/ccpi/plugins/processors/AcquisitionDataPadder.py
@@ -0,0 +1,116 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Apr 30 13:43:52 2019
+
+@author: ofn77899
+"""
+from ccpi.framework import DataProcessor, DataContainer, AcquisitionData,\
+ AcquisitionGeometry, ImageGeometry, ImageData
+from ccpi.reconstruction.parallelbeam import alg as pbalg
+import numpy
+
+class AcquisitionDataPadder(DataProcessor):
+    '''Normalization based on flat and dark
+    
+    This processor read in a AcquisitionData and normalises it based on 
+    the instrument reading with and without incident photons or neutrons.
+    
+    Input: AcquisitionData
+    Parameter: 2D projection with flat field (or stack)
+               2D projection with dark field (or stack)
+    Output: AcquisitionDataSetn
+    '''
+    
+    def __init__(self, 
+                 center_of_rotation   = None,
+                 acquisition_geometry = None,
+                 pad_value            = 1e-5):
+        kwargs = {
+                  'acquisition_geometry' : acquisition_geometry, 
+                  'center_of_rotation'   : center_of_rotation,
+                  'pad_value'            : pad_value
+                  }
+        
+        super(AcquisitionDataPadder, self).__init__(**kwargs)
+        
+    def check_input(self, dataset):
+        if self.acquisition_geometry is None:
+            self.acquisition_geometry = dataset.geometry
+        if dataset.number_of_dimensions == 3:
+               return True
+        else:
+            raise ValueError("Expected input dimensions is 2 or 3, got {0}"\
+                             .format(dataset.number_of_dimensions))
+
+    def process(self, out=None):
+        projections = self.get_input()
+        w = projections.get_dimension_size('horizontal')
+        print ("horizontal ", w)
+        delta = w - 2 * self.center_of_rotation
+               
+        padded_width = int (
+                numpy.ceil(abs(delta)) + w
+                )
+        delta_pix = padded_width - w
+        
+        voxel_per_pixel = 1
+        geom = pbalg.pb_setup_geometry_from_acquisition(projections.as_array(),
+                                            self.acquisition_geometry.angles,
+                                            self.center_of_rotation,
+                                            voxel_per_pixel )
+        
+        print ("geom", geom)
+        padded_geometry = self.acquisition_geometry.clone()
+        
+        padded_geometry.pixel_num_h = geom['n_h']
+        padded_geometry.pixel_num_v = geom['n_v']
+        
+        delta_pix_h = padded_geometry.pixel_num_h - self.acquisition_geometry.pixel_num_h
+        delta_pix_v = padded_geometry.pixel_num_v - self.acquisition_geometry.pixel_num_v
+        
+        if delta_pix_h == 0:
+            delta_pix_h = delta_pix
+            padded_geometry.pixel_num_h = padded_width
+        #initialize a new AcquisitionData with values close to 0
+        out = AcquisitionData(geometry=padded_geometry)
+        out = out + self.pad_value
+        
+        
+        #pad in the horizontal-vertical plane -> slice on angles
+        if delta > 0:
+            #pad left of middle
+            command = "out.array["
+            for i in range(out.number_of_dimensions):
+                if out.dimension_labels[i] == 'horizontal':
+                    value = '{0}:{1}'.format(delta_pix_h, delta_pix_h+w)
+                    command = command + str(value)
+                else:
+                    if out.dimension_labels[i] == 'vertical' :
+                        value = '{0}:'.format(delta_pix_v)
+                        command = command + str(value)
+                    else:
+                        command = command + ":"
+                if i < out.number_of_dimensions -1:
+                    command = command + ','
+            command = command + '] = projections.array'
+            #print (command)    
+        else:
+            #pad right of middle
+            command = "out.array["
+            for i in range(out.number_of_dimensions):
+                if out.dimension_labels[i] == 'horizontal':
+                    value = '{0}:{1}'.format(0, w)
+                    command = command + str(value)
+                else:
+                    if out.dimension_labels[i] == 'vertical' :
+                        value = '{0}:'.format(delta_pix_v)
+                        command = command + str(value)
+                    else:
+                        command = command + ":"
+                if i < out.number_of_dimensions -1:
+                    command = command + ','
+            command = command + '] = projections.array'
+            #print (command)    
+            #cleaned = eval(command)
+        exec(command)
+        return out
diff --git a/Wrappers/Python/ccpi/plugins/processors/__init__.py b/Wrappers/Python/ccpi/plugins/processors/__init__.py
index e688671..da13b98 100644
--- a/Wrappers/Python/ccpi/plugins/processors/__init__.py
+++ b/Wrappers/Python/ccpi/plugins/processors/__init__.py
@@ -1,4 +1,4 @@
 from .processors import setupCCPiGeometries
 from .processors import CCPiForwardProjector
 from .processors import CCPiBackwardProjector
-from .processors import AcquisitionDataPadder
+from .AcquisitionDataPadder import AcquisitionDataPadder
diff --git a/Wrappers/Python/conda-recipe/meta.yaml b/Wrappers/Python/conda-recipe/meta.yaml
index ab67b0c..c9126d4 100644
--- a/Wrappers/Python/conda-recipe/meta.yaml
+++ b/Wrappers/Python/conda-recipe/meta.yaml
@@ -8,7 +8,20 @@ build:
   script_env:
     - CIL_VERSION   
 #  number: 0
-  
+test:
+  requires:
+    - python-wget
+    - cvxpy # [ unix and py36 and np115 ]
+
+  source_files:
+    - ./test # [win]
+    - ./ccpi/Wrappers/Python/test # [not win] 
+
+  commands:
+    - python -c "import os; print (os.getcwd())"
+    - python -m unittest discover # [win]
+    - python -m unittest discover -s ccpi/Wrappers/Python/test # [not win]
+    
 requirements:
   build:
     - python
diff --git a/Wrappers/Python/test/__init__.py b/Wrappers/Python/test/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Wrappers/Python/test/test_Processors.py b/Wrappers/Python/test/test_Processors.py
new file mode 100755
index 0000000..0c43126
--- /dev/null
+++ b/Wrappers/Python/test/test_Processors.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Apr 30 14:39:20 2019
+
+@author: ofn77899
+"""
+
+import sys
+import unittest
+import numpy
+from ccpi.framework import DataProcessor
+from ccpi.framework import DataContainer
+from ccpi.framework import ImageData
+from ccpi.framework import AcquisitionData
+from ccpi.framework import ImageGeometry
+from ccpi.framework import AcquisitionGeometry
+from timeit import default_timer as timer
+from ccpi.io.reader import NexusReader
+from ccpi.processors import CenterOfRotationFinder
+from ccpi.plugins.processors import AcquisitionDataPadder
+import wget
+import os
+import math
+
+class TestDataProcessor(unittest.TestCase):
+    def setUp(self):
+        wget.download('https://github.com/DiamondLightSource/Savu/raw/master/test_data/data/24737_fd.nxs')
+        self.filename = '24737_fd.nxs'
+
+    def tearDown(self):
+        os.remove(self.filename)
+
+    def test_AcquisitionDataPadder(self):
+        reader = NexusReader(self.filename)
+        ad = reader.get_acquisition_data_whole()
+        print (ad.geometry)
+        cf = CenterOfRotationFinder()
+        cf.set_input(ad)
+        print ("Center of rotation", cf.get_output())
+        self.assertAlmostEqual(86.25, cf.get_output())
+        
+        adp = AcquisitionDataPadder(acquisition_geometry=cf.get_input().geometry,center_of_rotation=cf.get_output(),pad_value=0)
+        adp.set_input(ad)
+        padded_data = adp.get_output()
+        print ("Padded data shape", padded_data.shape)
+        print ("      " , padded_data.dimension_labels)
+        idx = None
+        for k,v in padded_data.dimension_labels.items():
+            if v == AcquisitionGeometry.HORIZONTAL:
+                idx = k
+
+        padded_axis = padded_data.shape[idx]
+        self.assertEqual(padded_axis , math.ceil(cf.get_output() * 2))
+        numpy.save("pippo.npy" , padded_data.as_array())
+    
-- 
cgit v1.2.3