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) sino = sgeometry.allocate() self.assertEqual(sino.shape, (2, 10, 3, 5)) ag = AcquisitionGeometry (pixel_num_h=2,pixel_num_v=3,channels=4, dimension=2, angles=numpy.linspace(0, 180, num=10), geom_type='parallel', ) print (ag.shape) print (ag.dimension_labels) data = ag.allocate() self.assertNumpyArrayEqual(numpy.asarray(data.shape), numpy.asarray(ag.shape)) self.assertNumpyArrayEqual(numpy.asarray(data.shape), data.as_array().shape) print (data.shape, ag.shape, data.as_array().shape) ag2 = AcquisitionGeometry (pixel_num_h=2,pixel_num_v=3,channels=4, dimension=2, angles=numpy.linspace(0, 180, num=10), geom_type='parallel', dimension_labels=[AcquisitionGeometry.VERTICAL , AcquisitionGeometry.ANGLE, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.CHANNEL]) data = ag2.allocate() print (data.shape, ag2.shape, data.as_array().shape) self.assertNumpyArrayEqual(numpy.asarray(data.shape), numpy.asarray(ag2.shape)) self.assertNumpyArrayEqual(numpy.asarray(data.shape), data.as_array().shape)
def test_AcquisitionDataSubset(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) # expected dimension_labels self.assertListEqual([AcquisitionGeometry.CHANNEL , AcquisitionGeometry.ANGLE , AcquisitionGeometry.VERTICAL , AcquisitionGeometry.HORIZONTAL], list(sgeometry.dimension_labels)) sino = sgeometry.allocate() # test reshape new_order = [AcquisitionGeometry.HORIZONTAL , AcquisitionGeometry.CHANNEL , AcquisitionGeometry.VERTICAL , AcquisitionGeometry.ANGLE] sino.reorder(new_order) self.assertListEqual(new_order, list(sino.geometry.dimension_labels)) ss1 = sino.get_slice(vertical = 0) self.assertListEqual([AcquisitionGeometry.HORIZONTAL , AcquisitionGeometry.CHANNEL , AcquisitionGeometry.ANGLE], list(ss1.geometry.dimension_labels)) ss2 = sino.get_slice(vertical = 0, channel=0) self.assertListEqual([AcquisitionGeometry.HORIZONTAL , AcquisitionGeometry.ANGLE], list(ss2.geometry.dimension_labels))
def test_AcquisitionGeometry_allocate(self): ageometry = AcquisitionGeometry(dimension=2, angles=numpy.linspace(0, 180, num=10), geom_type='parallel', pixel_num_v=3, pixel_num_h=5, channels=2) sino = ageometry.allocate(0) shape = sino.shape print("shape", shape) self.assertAlmostEqual(0., sino.as_array()[0][0][0][0]) self.assertAlmostEqual( 0., sino.as_array()[shape[0] - 1][shape[1] - 1][shape[2] - 1][shape[3] - 1]) sino = ageometry.allocate(1) self.assertEqual(1, sino.as_array()[0][0][0][0]) self.assertEqual( 1, sino.as_array()[shape[0] - 1][shape[1] - 1][shape[2] - 1][shape[3] - 1]) print(sino.dimension_labels, sino.shape, ageometry) default_order = ['channel', 'angle', 'vertical', 'horizontal'] self.assertEqual(default_order[0], sino.dimension_labels[0]) self.assertEqual(default_order[1], sino.dimension_labels[1]) self.assertEqual(default_order[2], sino.dimension_labels[2]) self.assertEqual(default_order[3], sino.dimension_labels[3]) order = ['vertical', 'horizontal', 'channel', 'angle'] ageometry.set_labels(order) sino = ageometry.allocate(0) print(sino.dimension_labels, sino.shape, ageometry) self.assertEqual(order[0], sino.dimension_labels[0]) self.assertEqual(order[1], sino.dimension_labels[1]) self.assertEqual(order[2], sino.dimension_labels[2]) self.assertEqual(order[2], sino.dimension_labels[2]) try: z = AcquisitionData(numpy.random.randint(10, size=(2, 3)), geometry=ageometry) self.assertTrue(False) except ValueError as ve: print(ve) self.assertTrue(True)
def test_AcquisitionGeometry_allocate_complex(self): ageometry = AcquisitionGeometry(dimension=2, angles=numpy.linspace(0, 180, num=10), geom_type='parallel', pixel_num_v=3, pixel_num_h=5, channels=2) sino = ageometry.allocate(0, dtype=numpy.complex64) shape = sino.shape print ("shape", shape) print ("dtype", sino.dtype) r = (1 + 1j*1)* numpy.ones(sino.shape, dtype=sino.dtype) sino.fill(r) self.assertAlmostEqual(sino.squared_norm(), sino.size*2)
def test_size(self): print ("test size") ig = ImageGeometry(10,10) d1 = ig.allocate(1) self.assertEqual( d1.size, 100 ) sgeometry = AcquisitionGeometry(dimension=2, angles=numpy.linspace(0, 180, num=10), geom_type='parallel', pixel_num_v=3, pixel_num_h=5, channels=2) ad = sgeometry.allocate() self.assertEqual( ad.size, 3*5*10*2 )
class TXRMDataReader(object): def __init__(self, **kwargs): ''' Constructor Input: txrm_file full path to .txrm file ''' self.txrm_file = kwargs.get('file_name', None) if self.txrm_file is not None: self.set_up(file_name = self.txrm_file) self._metadata = None def set_up(self, file_name = None, angle_unit = AcquisitionGeometry.DEGREE): self.txrm_file = os.path.abspath(file_name) if self.txrm_file == None: raise ValueError('Path to txrm file is required.') # check if txrm file exists if not(os.path.isfile(self.txrm_file)): raise FileNotFoundError('{}'.format(self.txrm_file)) possible_units = [AcquisitionGeometry.DEGREE, AcquisitionGeometry.RADIAN] if angle_unit in possible_units: self.angle_unit = angle_unit else: raise ValueError('angle_unit should be one of {}'.format(possible_units)) def get_geometry(self): ''' Return AcquisitionGeometry object ''' return self._ag def read(self): ''' Reads projections and return AcquisitionData container ''' # the import will raise an ImportError if dxchange is not installed import dxchange # Load projections and most metadata data, metadata = dxchange.read_txrm(self.txrm_file) number_of_images = data.shape[0] # Read source to center and detector to center distances with olefile.OleFileIO(self.txrm_file) as ole: StoRADistance = dxchange.reader._read_ole_arr(ole, \ 'ImageInfo/StoRADistance', "<{0}f".format(number_of_images)) DtoRADistance = dxchange.reader._read_ole_arr(ole, \ 'ImageInfo/DtoRADistance', "<{0}f".format(number_of_images)) dist_source_center = np.abs( StoRADistance[0] ) dist_center_detector = np.abs( DtoRADistance[0] ) # normalise data by flatfield data = data / metadata['reference'] # circularly shift data by rounded x and y shifts for k in range(number_of_images): data[k,:,:] = np.roll(data[k,:,:], \ (int(metadata['x-shifts'][k]),int(metadata['y-shifts'][k])), \ axis=(1,0)) # Pixelsize loaded in metadata is really the voxel size in um. # We can compute the effective detector pixel size as the geometric # magnification times the voxel size. d_pixel_size = ((dist_source_center+dist_center_detector)/dist_source_center)*metadata['pixel_size'] # convert angles to requested unit measure, Zeiss stores in radians if self.angle_unit == AcquisitionGeometry.DEGREE: angles = np.degrees(metadata['thetas']) else: angles = np.asarray(metadata['thetas']) self._ag = AcquisitionGeometry(geom_type = 'cone', dimension = '3D', angles = angles, pixel_num_h = metadata['image_width'], pixel_size_h = d_pixel_size/1000, pixel_num_v = metadata['image_height'], pixel_size_v = d_pixel_size/1000, dist_source_center = dist_source_center, dist_center_detector = dist_center_detector, channels = 1, angle_unit = self.angle_unit, dimension_labels = ['angle', \ 'vertical', \ 'horizontal']) acq_data = self._ag.allocate(None) acq_data.fill(data) self._metadata = metadata return acq_data def load_projections(self): '''alias of read for backward compatibility''' return self.read() def get_metadata(self): '''return the metadata of the loaded file''' return self._metadata
def test_SPDHG_vs_PDHG_implicit(self): data = dataexample.SIMPLE_PHANTOM_2D.get(size=(128, 128)) ig = data.geometry ig.voxel_size_x = 0.1 ig.voxel_size_y = 0.1 detectors = ig.shape[0] angles = np.linspace(0, np.pi, 90) ag = AcquisitionGeometry('parallel', '2D', angles, detectors, pixel_size_h=0.1, angle_unit='radian') # Select device dev = 'cpu' Aop = AstraProjectorSimple(ig, ag, dev) sin = Aop.direct(data) # Create noisy data. Apply Gaussian noise noises = ['gaussian', 'poisson'] noise = noises[1] noisy_data = ag.allocate() if noise == 'poisson': np.random.seed(10) scale = 20 eta = 0 noisy_data.fill( np.random.poisson(scale * (eta + sin.as_array())) / scale) elif noise == 'gaussian': np.random.seed(10) n1 = np.random.normal(0, 0.1, size=ag.shape) noisy_data.fill(n1 + sin.as_array()) else: raise ValueError('Unsupported Noise ', noise) # Create BlockOperator operator = Aop f = KullbackLeibler(b=noisy_data) alpha = 0.005 g = alpha * TotalVariation(50, 1e-4, lower=0) normK = operator.norm() #% 'implicit' PDHG, preconditioned step-sizes tau_tmp = 1. sigma_tmp = 1. tau = sigma_tmp / operator.adjoint( tau_tmp * operator.range_geometry().allocate(1.)) sigma = tau_tmp / operator.direct( sigma_tmp * operator.domain_geometry().allocate(1.)) # initial = operator.domain_geometry().allocate() # # Setup and run the PDHG algorithm pdhg = PDHG(f=f, g=g, operator=operator, tau=tau, sigma=sigma, max_iteration=1000, update_objective_interval=500) pdhg.run(verbose=0) subsets = 10 size_of_subsets = int(len(angles) / subsets) # take angles and create uniform subsets in uniform+sequential setting list_angles = [ angles[i:i + size_of_subsets] for i in range(0, len(angles), size_of_subsets) ] # create acquisitioin geometries for each the interval of splitting angles list_geoms = [ AcquisitionGeometry('parallel', '2D', list_angles[i], detectors, pixel_size_h=0.1, angle_unit='radian') for i in range(len(list_angles)) ] # create with operators as many as the subsets A = BlockOperator(*[ AstraProjectorSimple(ig, list_geoms[i], dev) for i in range(subsets) ]) ## number of subsets #(sub2ind, ind2sub) = divide_1Darray_equally(range(len(A)), subsets) # ## acquisisiton data AD_list = [] for sub_num in range(subsets): for i in range(0, len(angles), size_of_subsets): arr = noisy_data.as_array()[i:i + size_of_subsets, :] AD_list.append( AcquisitionData(arr, geometry=list_geoms[sub_num])) g = BlockDataContainer(*AD_list) ## block function F = BlockFunction(*[KullbackLeibler(b=g[i]) for i in range(subsets)]) G = alpha * TotalVariation(50, 1e-4, lower=0) prob = [1 / len(A)] * len(A) spdhg = SPDHG(f=F, g=G, operator=A, max_iteration=1000, update_objective_interval=200, prob=prob) spdhg.run(1000, verbose=0) from cil.utilities.quality_measures import mae, mse, psnr qm = (mae(spdhg.get_output(), pdhg.get_output()), mse(spdhg.get_output(), pdhg.get_output()), psnr(spdhg.get_output(), pdhg.get_output())) if debug_print: print("Quality measures", qm) np.testing.assert_almost_equal(mae(spdhg.get_output(), pdhg.get_output()), 0.000335, decimal=3) np.testing.assert_almost_equal(mse(spdhg.get_output(), pdhg.get_output()), 5.51141e-06, decimal=3)
else: out.fill(self.fp.get_output()) def adjoint(self, DATA, out=None): self.bp.set_input(DATA) if out is None: return self.bp.get_output() else: out.fill(self.bp.get_output()) if __name__ == '__main__': N = 30 angles = np.linspace(0, np.pi, 180) ig = ImageGeometry(N, N, N) ag = AcquisitionGeometry('parallel', '3D', angles, pixel_num_h=N, pixel_num_v=5) A = AstraProjector3DSimple(ig, ag) print(A.norm()) x = ig.allocate('random_int') sin = A.direct(x) y = ag.allocate('random_int') im = A.adjoint(y)
class TestSubset(unittest.TestCase): def setUp(self): self.ig = ImageGeometry(2, 3, 4, channels=5) angles = numpy.asarray([90., 0., -90.], dtype=numpy.float32) self.ag = AcquisitionGeometry('parallel', 'edo', pixel_num_h=20, pixel_num_v=2, angles=angles, dist_source_center=312.2, dist_center_detector=123., channels=4) self.ag_cone = AcquisitionGeometry.create_Cone3D([0,-500,0],[0,500,0])\ .set_panel((2,20))\ .set_angles(self.ag.angles)\ .set_channels(4) def test_ImageDataAllocate1a(self): data = self.ig.allocate() default_dimension_labels = [ ImageGeometry.CHANNEL, ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.HORIZONTAL_X ] self.assertTrue( default_dimension_labels == list(data.dimension_labels.values())) def test_ImageDataAllocate1b(self): data = self.ig.allocate() self.assertTrue(data.shape == (5, 4, 3, 2)) def test_ImageDataAllocate2a(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.CHANNEL ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) self.assertTrue(non_default_dimension_labels == list( data.dimension_labels.values())) def test_ImageDataAllocate2b(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.CHANNEL ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) self.assertTrue(data.shape == (2, 4, 3, 5)) def test_ImageDataSubset1a(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) sub = data.subset(horizontal_y=1) self.assertTrue(sub.shape == (2, 5, 4)) def test_ImageDataSubset2a(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) sub = data.subset(horizontal_x=1) self.assertTrue(sub.shape == (5, 3, 4)) def test_ImageDataSubset3a(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) sub = data.subset(channel=1) self.assertTrue(sub.shape == (2, 3, 4)) def test_ImageDataSubset4a(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) sub = data.subset(vertical=1) self.assertTrue(sub.shape == (2, 5, 3)) def test_ImageDataSubset5a(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.HORIZONTAL_Y ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) sub = data.subset(horizontal_y=1) self.assertTrue(sub.shape == (2, )) def test_ImageDataSubset1b(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL ] data = self.ig.allocate(dimension_labels=non_default_dimension_labels) new_dimension_labels = [ ImageGeometry.HORIZONTAL_Y, ImageGeometry.CHANNEL, ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_X ] sub = data.subset(dimensions=new_dimension_labels) self.assertTrue(sub.shape == (3, 5, 4, 2)) def test_ImageDataSubset1c(self): data = self.ig.allocate() sub = data.subset(channel=0, horizontal_x=0, horizontal_y=0) self.assertTrue(sub.shape == (4, )) def test_AcquisitionDataAllocate1a(self): data = self.ag.allocate() default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.ANGLE, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.HORIZONTAL ] self.assertTrue( default_dimension_labels == list(data.dimension_labels.values())) def test_AcquisitionDataAllocate1b(self): data = self.ag.allocate() self.assertTrue(data.shape == (4, 3, 2, 20)) def test_AcquisitionDataAllocate2a(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] data = self.ag.allocate(dimension_labels=non_default_dimension_labels) self.assertTrue(non_default_dimension_labels == list( data.dimension_labels.values())) def test_AcquisitionDataAllocate2b(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] data = self.ag.allocate(dimension_labels=non_default_dimension_labels) self.assertTrue(data.shape == (4, 20, 2, 3)) def test_AcquisitionDataSubset1a(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] data = self.ag.allocate(dimension_labels=non_default_dimension_labels) #self.assertTrue( data.shape == (4,20,2,3)) sub = data.subset(vertical=0) self.assertTrue(sub.shape == (4, 20, 3)) def test_AcquisitionDataSubset1b(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] data = self.ag.allocate(dimension_labels=non_default_dimension_labels) #self.assertTrue( data.shape == (4,20,2,3)) sub = data.subset(channel=0) self.assertTrue(sub.shape == (20, 2, 3)) def test_AcquisitionDataSubset1c(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] data = self.ag.allocate(dimension_labels=non_default_dimension_labels) #self.assertTrue( data.shape == (4,20,2,3)) sub = data.subset(horizontal=0, force=True) self.assertTrue(sub.shape == (4, 2, 3)) def test_AcquisitionDataSubset1d(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] data = self.ag.allocate(dimension_labels=non_default_dimension_labels) #self.assertTrue( data.shape == (4,20,2,3)) sliceme = 1 sub = data.subset(angle=sliceme) #print (sub.shape , sub.dimension_labels) self.assertTrue(sub.shape == (4, 20, 2)) self.assertTrue( sub.geometry.angles[0] == data.geometry.angles[sliceme]) def test_AcquisitionDataSubset1e(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] data = self.ag.allocate(dimension_labels=non_default_dimension_labels) #self.assertTrue( data.shape == (4,20,2,3)) sliceme = 1 sub = data.subset(angle=sliceme) self.assertTrue( sub.geometry.angles[0] == data.geometry.angles[sliceme]) def test_AcquisitionDataSubset1f(self): data = self.ag.allocate() #self.assertTrue( data.shape == (4,20,2,3)) sliceme = 1 sub = data.subset(angle=sliceme) self.assertTrue( sub.geometry.angles[0] == data.geometry.angles[sliceme]) def test_AcquisitionDataSubset1g(self): data = self.ag_cone.allocate() sliceme = 1 sub = data.subset(angle=sliceme) self.assertTrue( sub.geometry.angles[0] == data.geometry.angles[sliceme]) def test_AcquisitionDataSubset1h(self): data = self.ag_cone.allocate() sub = data.subset(vertical='centre') self.assertTrue(sub.geometry.shape == (4, 3, 2)) def test_AcquisitionDataSubset1i(self): data = self.ag_cone.allocate() sliceme = 1 sub = data.subset(vertical=sliceme, force=True) self.assertTrue(sub.shape == (4, 3, 2)) def test_AcquisitionDataSubset1j(self): data = self.ag.allocate() sub = data.subset(angle=0) sub = sub.subset(vertical=0) sub = sub.subset(horizontal=0, force=True) self.assertTrue(sub.shape == (4, ))