diff options
-rw-r--r-- | Wrappers/Python/ccpi/astra/astra_ops.py | 4 | ||||
-rw-r--r-- | Wrappers/Python/ccpi/astra/astra_processors.py | 32 | ||||
-rw-r--r-- | Wrappers/Python/ccpi/astra/astra_utils.py | 20 | ||||
-rw-r--r-- | Wrappers/Python/ccpi/framework.py | 12 | ||||
-rwxr-xr-x | Wrappers/Python/conda-recipe/run_test.py | 167 | ||||
-rwxr-xr-x | Wrappers/Python/wip/simple_mc_demo.py | 1 |
6 files changed, 202 insertions, 34 deletions
diff --git a/Wrappers/Python/ccpi/astra/astra_ops.py b/Wrappers/Python/ccpi/astra/astra_ops.py index c409529..5f25eec 100644 --- a/Wrappers/Python/ccpi/astra/astra_ops.py +++ b/Wrappers/Python/ccpi/astra/astra_ops.py @@ -17,9 +17,11 @@ from ccpi.reconstruction.ops import Operator import numpy +import astra from ccpi.framework import AcquisitionData, ImageData from ccpi.reconstruction.ops import PowerMethodNonsquare -from ccpi.astra.astra_processors import * +from ccpi.astra.astra_processors import AstraForwardProjector, AstraBackProjector, \ + AstraForwardProjectorMC, AstraBackProjectorMC class AstraProjectorSimple(Operator): """ASTRA projector modified to use DataSet and geometry.""" diff --git a/Wrappers/Python/ccpi/astra/astra_processors.py b/Wrappers/Python/ccpi/astra/astra_processors.py index bf6048b..3de43bf 100644 --- a/Wrappers/Python/ccpi/astra/astra_processors.py +++ b/Wrappers/Python/ccpi/astra/astra_processors.py @@ -28,8 +28,8 @@ class AstraForwardProjector(DataSetProcessor): #DataSetProcessor.__init__(self, **kwargs) super(AstraForwardProjector, self).__init__(**kwargs) - self.setVolumeGeometry(volume_geometry) - self.setSinogramGeometry(sinogram_geometry) + self.set_ImageGeometry(volume_geometry) + self.set_AcquisitionGeometry(sinogram_geometry) # Set up ASTRA Volume and projection geometry, not to be stored in self vol_geom, proj_geom = convert_geometry_to_astra(self.volume_geometry, @@ -39,13 +39,13 @@ class AstraForwardProjector(DataSetProcessor): if device == 'cpu': # Note that 'line' only one option if self.sinogram_geometry.geom_type == 'parallel': - self.setProjector(astra.create_projector('line', proj_geom, vol_geom) ) + self.set_projector(astra.create_projector('line', proj_geom, vol_geom) ) elif self.sinogram_geometry.geom_type == 'cone': - self.setProjector(astra.create_projector('line_fanflat', proj_geom, vol_geom) ) + self.set_projector(astra.create_projector('line_fanflat', proj_geom, vol_geom) ) else: NotImplemented elif device == 'gpu': - self.setProjector(astra.create_projector('cuda', proj_geom, vol_geom) ) + self.set_projector(astra.create_projector('cuda', proj_geom, vol_geom) ) else: NotImplemented @@ -57,13 +57,13 @@ class AstraForwardProjector(DataSetProcessor): raise ValueError("Expected input dimensions is 2 or 3, got {0}"\ .format(dataset.number_of_dimensions)) - def setProjector(self, proj_id): + def set_projector(self, proj_id): self.proj_id = proj_id - def setVolumeGeometry(self, volume_geometry): + def set_ImageGeometry(self, volume_geometry): self.volume_geometry = volume_geometry - def setSinogramGeometry(self, sinogram_geometry): + def set_AcquisitionGeometry(self, sinogram_geometry): self.sinogram_geometry = sinogram_geometry def process(self): @@ -102,8 +102,8 @@ class AstraBackProjector(DataSetProcessor): #DataSetProcessor.__init__(self, **kwargs) super(AstraBackProjector, self).__init__(**kwargs) - self.setVolumeGeometry(volume_geometry) - self.setSinogramGeometry(sinogram_geometry) + self.set_ImageGeometry(volume_geometry) + self.set_AcquisitionGeometry(sinogram_geometry) # Set up ASTRA Volume and projection geometry, not to be stored in self vol_geom, proj_geom = convert_geometry_to_astra(self.volume_geometry, @@ -113,13 +113,13 @@ class AstraBackProjector(DataSetProcessor): if device == 'cpu': # Note that 'line' only one option if self.sinogram_geometry.geom_type == 'parallel': - self.setProjector(astra.create_projector('line', proj_geom, vol_geom) ) + self.set_projector(astra.create_projector('line', proj_geom, vol_geom) ) elif self.sinogram_geometry.geom_type == 'cone': - self.setProjector(astra.create_projector('line_fanflat', proj_geom, vol_geom) ) + self.set_projector(astra.create_projector('line_fanflat', proj_geom, vol_geom) ) else: NotImplemented elif device == 'gpu': - self.setProjector(astra.create_projector('cuda', proj_geom, vol_geom) ) + self.set_projector(astra.create_projector('cuda', proj_geom, vol_geom) ) else: NotImplemented @@ -130,13 +130,13 @@ class AstraBackProjector(DataSetProcessor): raise ValueError("Expected input dimensions is 2 or 3, got {0}"\ .format(dataset.number_of_dimensions)) - def setProjector(self, proj_id): + def set_projector(self, proj_id): self.proj_id = proj_id - def setVolumeGeometry(self, volume_geometry): + def set_ImageGeometry(self, volume_geometry): self.volume_geometry = volume_geometry - def setSinogramGeometry(self, sinogram_geometry): + def set_AcquisitionGeometry(self, sinogram_geometry): self.sinogram_geometry = sinogram_geometry def process(self): diff --git a/Wrappers/Python/ccpi/astra/astra_utils.py b/Wrappers/Python/ccpi/astra/astra_utils.py index 8b5043a..dedb4fe 100644 --- a/Wrappers/Python/ccpi/astra/astra_utils.py +++ b/Wrappers/Python/ccpi/astra/astra_utils.py @@ -5,10 +5,10 @@ def convert_geometry_to_astra(volume_geometry, sinogram_geometry): if sinogram_geometry.dimension == '2D': vol_geom = astra.create_vol_geom(volume_geometry.voxel_num_x, volume_geometry.voxel_num_y, - volume_geometry.getMinX(), - volume_geometry.getMaxX(), - volume_geometry.getMinY(), - volume_geometry.getMaxY()) + volume_geometry.get_min_x(), + volume_geometry.get_max_x(), + volume_geometry.get_min_y(), + volume_geometry.get_max_y()) if sinogram_geometry.geom_type == 'parallel': proj_geom = astra.create_proj_geom('parallel', @@ -29,12 +29,12 @@ def convert_geometry_to_astra(volume_geometry, sinogram_geometry): vol_geom = astra.create_vol_geom(volume_geometry.voxel_num_x, volume_geometry.voxel_num_y, volume_geometry.voxel_num_z, - volume_geometry.getMinX(), - volume_geometry.getMaxX(), - volume_geometry.getMinY(), - volume_geometry.getMaxY(), - volume_geometry.getMinZ(), - volume_geometry.getMaxZ()) + volume_geometry.get_min_x(), + volume_geometry.get_max_x(), + volume_geometry.get_min_y(), + volume_geometry.get_max_y(), + volume_geometry.get_min_z(), + volume_geometry.get_max_z()) if sinogram_geometry.proj_geom == 'parallel': proj_geom = astra.create_proj_geom('parallel3d', diff --git a/Wrappers/Python/ccpi/framework.py b/Wrappers/Python/ccpi/framework.py index 9b0cf54..877becf 100644 --- a/Wrappers/Python/ccpi/framework.py +++ b/Wrappers/Python/ccpi/framework.py @@ -59,25 +59,25 @@ class ImageGeometry: self.center_z = center_z self.channels = channels - def getMinX(self): + def get_min_x(self): return self.center_x - 0.5*self.voxel_num_x*self.voxel_size_x - def getMaxX(self): + def get_max_x(self): return self.center_x + 0.5*self.voxel_num_x*self.voxel_size_x - def getMinY(self): + def get_min_y(self): return self.center_y - 0.5*self.voxel_num_y*self.voxel_size_y - def getMaxY(self): + def get_max_y(self): return self.center_y + 0.5*self.voxel_num_y*self.voxel_size_y - def getMinZ(self): + def get_min_z(self): if not voxel_num_z == 0: return self.center_z - 0.5*self.voxel_num_z*self.voxel_size_z else: return 0 - def getMaxZ(self): + def get_max_z(self): if not voxel_num_z == 0: return self.center_z + 0.5*self.voxel_num_z*self.voxel_size_z else: diff --git a/Wrappers/Python/conda-recipe/run_test.py b/Wrappers/Python/conda-recipe/run_test.py new file mode 100755 index 0000000..6a20d05 --- /dev/null +++ b/Wrappers/Python/conda-recipe/run_test.py @@ -0,0 +1,167 @@ +import unittest
+import numpy
+from ccpi.framework import DataContainer, ImageData, AcquisitionData, \
+ ImageGeometry, AcquisitionGeometry
+import sys
+
+class TestDataContainer(unittest.TestCase):
+
+ def test_creation_nocopy(self):
+ shape = (2,3,4,5)
+ size = shape[0]
+ for i in range(1, len(shape)):
+ size = size * shape[i]
+ #print("a refcount " , sys.getrefcount(a))
+ a = numpy.asarray([i for i in range( size )])
+ #print("a refcount " , sys.getrefcount(a))
+ a = numpy.reshape(a, shape)
+ #print("a refcount " , sys.getrefcount(a))
+ ds = DataContainer(a, False, ['X', 'Y','Z' ,'W'])
+ #print("a refcount " , sys.getrefcount(a))
+ self.assertEqual(sys.getrefcount(a),3)
+ self.assertEqual(ds.dimension_labels , {0: 'X', 1: 'Y', 2: 'Z', 3: 'W'})
+
+ def test_creation_copy(self):
+ shape = (2,3,4,5)
+ size = shape[0]
+ for i in range(1, len(shape)):
+ size = size * shape[i]
+ #print("a refcount " , sys.getrefcount(a))
+ a = numpy.asarray([i for i in range( size )])
+ #print("a refcount " , sys.getrefcount(a))
+ a = numpy.reshape(a, shape)
+ #print("a refcount " , sys.getrefcount(a))
+ ds = DataContainer(a, True, ['X', 'Y','Z' ,'W'])
+ #print("a refcount " , sys.getrefcount(a))
+ self.assertEqual(sys.getrefcount(a),2)
+
+ def test_subset(self):
+ shape = (4,3,2)
+ a = [i for i in range(2*3*4)]
+ a = numpy.asarray(a)
+ a = numpy.reshape(a, shape)
+ ds = DataContainer(a, True, ['X', 'Y','Z'])
+ sub = ds.subset(['X'])
+ res = True
+ try:
+ numpy.testing.assert_array_equal(sub.as_array(),
+ numpy.asarray([0,6,12,18]))
+ except AssertionError as err:
+ res = False
+ print (err)
+ self.assertTrue(res)
+
+ sub = ds.subset(['X'], Y=2, Z=0)
+ res = True
+ try:
+ numpy.testing.assert_array_equal(sub.as_array(),
+ numpy.asarray([4,10,16,22]))
+ except AssertionError as err:
+ res = False
+ print (err)
+ self.assertTrue(res)
+
+
+ sub = ds.subset(['Y'])
+ try:
+ numpy.testing.assert_array_equal(
+ sub.as_array(), numpy.asarray([0,2,4]))
+ res = True
+ except AssertionError as err:
+ res = False
+ print (err)
+ self.assertTrue(res)
+
+
+ sub = ds.subset(['Z'])
+ try:
+ numpy.testing.assert_array_equal(
+ sub.as_array(), numpy.asarray([0,1]))
+ res = True
+ except AssertionError as err:
+ res = False
+ print (err)
+ self.assertTrue(res)
+ sub = ds.subset(['Z'], X=1, Y=2)
+ try:
+ numpy.testing.assert_array_equal(
+ sub.as_array(), numpy.asarray([10,11]))
+ res = True
+ except AssertionError as err:
+ res = False
+ print (err)
+ self.assertTrue(res)
+
+ print(a)
+ sub = ds.subset(['X', 'Y'] , Z=1)
+ res = True
+ try:
+ numpy.testing.assert_array_equal(sub.as_array(),
+ numpy.asarray([[ 1, 3, 5],
+ [ 7, 9, 11],
+ [13, 15, 17],
+ [19, 21, 23]]))
+ except AssertionError as err:
+ res = False
+ print (err)
+ self.assertTrue(res)
+
+ def test_ImageData(self):
+ # create ImageData from geometry
+ vgeometry = ImageGeometry(voxel_num_x=4, voxel_num_y=3, channels=2)
+ vol = ImageData(geometry=vgeometry)
+ self.assertEqual(vol.shape , (2,3,4))
+
+ vol1 = vol + 1
+ self.assertNumpyArrayEqual(vol1.as_array(), numpy.ones(vol.shape))
+
+ vol1 = vol - 1
+ self.assertNumpyArrayEqual(vol1.as_array(), -numpy.ones(vol.shape))
+
+ vol1 = 2 * (vol + 1)
+ self.assertNumpyArrayEqual(vol1.as_array(), 2 * numpy.ones(vol.shape))
+
+ vol1 = (vol + 1) / 2
+ self.assertNumpyArrayEqual(vol1.as_array(), numpy.ones(vol.shape) / 2 )
+
+ vol1 = vol + 1
+ self.assertEqual(vol1.sum() , 2*3*4)
+ vol1 = ( vol + 2 ) ** 2
+ self.assertNumpyArrayEqual(vol1.as_array(), numpy.ones(vol.shape) * 4 )
+
+
+
+ def test_AcquisitionData(self):
+ sgeometry = AcquisitionGeometry(dimension=2, angles=numpy.linspace(0, 180, num=10),
+ geom_type='parallel', pixel_num_v=3,
+ pixel_num_h=5 , channels=2)
+ sino = AcquisitionData(geometry=sgeometry)
+ self.assertEqual(sino.shape , (2,10,3,5))
+
+
+ def assertNumpyArrayEqual(self, first, second):
+ res = True
+ try:
+ numpy.testing.assert_array_equal(first, second)
+ except AssertionError as err:
+ res = False
+ print (err)
+ self.assertTrue(res)
+# =============================================================================
+# def test_upper(self):
+# self.assertEqual('foo'.upper(), 'FOO')
+#
+# def test_isupper(self):
+# self.assertTrue('FOO'.isupper())
+# self.assertFalse('Foo'.isupper())
+#
+# def test_split(self):
+# s = 'hello world'
+# self.assertEqual(s.split(), ['hello', 'world'])
+# # check that s.split fails when the separator is not a string
+# with self.assertRaises(TypeError):
+# s.split(2)
+# =============================================================================
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file diff --git a/Wrappers/Python/wip/simple_mc_demo.py b/Wrappers/Python/wip/simple_mc_demo.py index f15e704..f77a678 100755 --- a/Wrappers/Python/wip/simple_mc_demo.py +++ b/Wrappers/Python/wip/simple_mc_demo.py @@ -5,7 +5,6 @@ from ccpi.framework import ImageData, AcquisitionData, ImageGeometry, Acquisitio from ccpi.reconstruction.algs import FISTA from ccpi.reconstruction.funcs import Norm2sq, Norm1 from ccpi.astra.astra_ops import AstraProjectorMC -from ccpi.reconstruction.geoms import VolumeGeometry, SinogramGeometry import numpy import matplotlib.pyplot as plt |