summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xWrappers/Python/ccpi/plugins/processors/AcquisitionDataPadder.py116
-rw-r--r--Wrappers/Python/ccpi/plugins/processors/__init__.py2
-rw-r--r--Wrappers/Python/conda-recipe/meta.yaml15
-rw-r--r--Wrappers/Python/test/__init__.py0
-rwxr-xr-xWrappers/Python/test/test_Processors.py55
5 files changed, 186 insertions, 2 deletions
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
--- /dev/null
+++ b/Wrappers/Python/test/__init__.py
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())
+