def test_equal(self): AG = AcquisitionGeometry.create_Parallel3D() AG.set_channels(4, ['a','b','c','d']) AG.set_panel([2,3]) AG.set_angles([0,1,2,3,5]) AG.set_labels(('horizontal','angle','vertical','channel')) AG2 = AcquisitionGeometry.create_Parallel3D() AG2.set_channels(4, ['a','b','c','d']) AG2.set_panel([2,3]) AG2.set_angles([0,1,2,3,5]) AG2.set_labels(('horizontal','angle','vertical','channel')) self.assertTrue(AG == AG2) #test not equal AG3 = AG2.copy() AG3.config.system.ray.direction = [1,0,0] self.assertFalse(AG == AG3) AG3 = AG2.copy() AG3.config.panel.num_pixels = [1,2] self.assertFalse(AG == AG3) AG3 = AG2.copy() AG3.config.channels.channel_labels = ['d','b','c','d'] self.assertFalse(AG == AG3) AG3 = AG2.copy() AG3.config.angles.angle_unit ='radian' self.assertFalse(AG == AG3) AG3 = AG2.copy() AG3.config.angles.angle_data[0] = -1 self.assertFalse(AG == AG3)
def test_create_Parallel2D(self): #default AG = AcquisitionGeometry.create_Parallel2D() numpy.testing.assert_allclose(AG.config.system.ray.direction, [0,1], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.detector.position, [0,0], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.detector.direction_x, [1,0], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.rotation_axis.position, [0,0], rtol=1E-6) #values ray_direction = [0.1, 3.0] detector_position = [-1.3,1000.0] detector_direction_x = [1,0.2] rotation_axis_position = [0.1,2] AG = AcquisitionGeometry.create_Parallel2D(ray_direction, detector_position, detector_direction_x, rotation_axis_position) ray_direction = numpy.asarray(ray_direction) detector_direction_x = numpy.asarray(detector_direction_x) ray_direction /= numpy.sqrt((ray_direction**2).sum()) detector_direction_x /= numpy.sqrt((detector_direction_x**2).sum()) numpy.testing.assert_allclose(AG.config.system.ray.direction, ray_direction, rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.detector.position, detector_position, rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.detector.direction_x, detector_direction_x, rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.rotation_axis.position, rotation_axis_position, rtol=1E-6)
def setUp(self): #%% Setup Geometry voxel_num_xy = 16 voxel_num_z = 4 pix_size = 0.2 det_pix_x = voxel_num_xy det_pix_y = voxel_num_z num_projections = 36 angles = np.linspace(0, 360, num=num_projections, endpoint=False) self.ag = AcquisitionGeometry.create_Parallel2D()\ .set_angles(angles)\ .set_panel(det_pix_x, pix_size)\ .set_labels(['angle','horizontal']) self.ig = self.ag.get_ImageGeometry() self.ag3D = AcquisitionGeometry.create_Parallel3D()\ .set_angles(angles)\ .set_panel((det_pix_x,det_pix_y), (pix_size,pix_size))\ .set_labels(['angle','vertical','horizontal']) self.ig3D = self.ag3D.get_ImageGeometry() self.ad3D = self.ag3D.allocate('random') self.ig3D = self.ag3D.get_ImageGeometry()
def test_AcquisitionData(self): ag = AcquisitionGeometry.create_Parallel3D().set_panel( [5, 4]).set_angles([0, 1, 2]).set_channels(2).set_labels( ['channel', 'angle', 'vertical', 'horizontal']) data = ag.allocate(None) data_new = data.get_slice(angle=2) self.assertEquals(data_new.shape, (2, 4, 5)) self.assertEquals(data_new.geometry.dimension_labels, ('channel', 'vertical', 'horizontal')) #won't return a geometry for un-reconstructable slice ag = AcquisitionGeometry.create_Cone3D( [0, -200, 0], [0, 200, 0]).set_panel([5, 4]).set_angles( [0, 1, 2]).set_channels(2).set_labels( ['channel', 'angle', 'vertical', 'horizontal']) data = ag.allocate('random') data_new = data.get_slice(vertical=1, force=True) self.assertEquals(data_new.shape, (2, 3, 5)) self.assertTrue(isinstance(data_new, (DataContainer))) self.assertIsNone(data_new.geometry) self.assertEquals(data_new.dimension_labels, ('channel', 'angle', 'horizontal')) #if 'centre' is between pixels interpolates data_new = data.get_slice(vertical='centre') self.assertEquals(data_new.shape, (2, 3, 5)) self.assertEquals(data_new.geometry.dimension_labels, ('channel', 'angle', 'horizontal')) numpy.testing.assert_allclose( data_new.array, (data.array[:, :, 1, :] + data.array[:, :, 2, :]) / 2)
def test_get_ImageGeometry(self): AG = AcquisitionGeometry.create_Parallel2D()\ .set_panel(num_pixels=[512,1],pixel_size=[0.1,0.1]) IG = AG.get_ImageGeometry() IG_gold = ImageGeometry(512,512,0,0.1,0.1,1,0,0,0,1) self.assertEqual(IG, IG_gold) AG = AcquisitionGeometry.create_Parallel3D()\ .set_panel(num_pixels=[512,3],pixel_size=[0.1,0.2]) IG = AG.get_ImageGeometry() IG_gold = ImageGeometry(512,512,3,0.1,0.1,0.2,0,0,0,1) self.assertEqual(IG, IG_gold) AG = AcquisitionGeometry.create_Cone2D(source_position=[0,-500], detector_position=[0.,500.])\ .set_panel(num_pixels=[512,1],pixel_size=[0.1,0.2]) IG = AG.get_ImageGeometry() IG_gold = ImageGeometry(512,512,0,0.05,0.05,1,0,0,0,1) self.assertEqual(IG, IG_gold) AG = AcquisitionGeometry.create_Cone3D(source_position=[0,-500,0], detector_position=[0.,500.,0])\ .set_panel(num_pixels=[512,3],pixel_size=[0.1,0.2]) IG = AG.get_ImageGeometry() IG_gold = ImageGeometry(512,512,3,0.05,0.05,0.1,0,0,0,1) self.assertEqual(IG, IG_gold) AG = AcquisitionGeometry.create_Cone3D(source_position=[0,-500,0], detector_position=[0.,500.,0])\ .set_panel(num_pixels=[512,3],pixel_size=[0.1,0.2]) IG = AG.get_ImageGeometry(resolution=0.5) IG_gold = ImageGeometry(256,256,2,0.025,0.025,0.05,0,0,0,1) self.assertEqual(IG, IG_gold)
def test_system_description(self): AG = AcquisitionGeometry.create_Cone3D(source_position=[0, -50, 0], detector_position=[0, 100, 0]) self.assertTrue(AG.system_description == 'simple') AG = AcquisitionGeometry.create_Cone3D(source_position=[-50, 0, 0], detector_position=[100, 0, 0], detector_direction_x=[0, -1, 0]) self.assertTrue(AG.system_description == 'simple') AG = AcquisitionGeometry.create_Cone3D( source_position=[5, -50, 0], detector_position=[5, 100, 0], rotation_axis_position=[5, 0, 0]) self.assertTrue(AG.system_description == 'simple') AG = AcquisitionGeometry.create_Cone3D(source_position=[5, -50, 0], detector_position=[0, 100, 0]) self.assertTrue(AG.system_description == 'advanced') AG = AcquisitionGeometry.create_Cone3D( source_position=[0, -50, 0], detector_position=[0, 100, 0], rotation_axis_position=[5, 0, 0]) self.assertTrue(AG.system_description == 'offset')
def __init__(self, volume_geometry, sinogram_geometry): super(FBP_Flexible, self).__init__(volume_geometry=volume_geometry, sinogram_geometry=sinogram_geometry) #convert parallel geomerty to cone with large source to object sino_geom_cone = sinogram_geometry.copy() sino_geom_cone.config.system.update_reference_frame() #reverse ray direction unit-vector direction and extend to inf cone_source = -sino_geom_cone.config.system.ray.direction * sino_geom_cone.config.panel.pixel_size[ 1] * sino_geom_cone.config.panel.num_pixels[1] * 1e6 detector_position = sino_geom_cone.config.system.detector.position detector_direction_x = sino_geom_cone.config.system.detector.direction_x if sinogram_geometry.dimension == '2D': tmp = AcquisitionGeometry.create_Cone2D(cone_source, detector_position, detector_direction_x) else: detector_direction_y = sino_geom_cone.config.system.detector.direction_y tmp = AcquisitionGeometry.create_Cone3D(cone_source, detector_position, detector_direction_x, detector_direction_y) sino_geom_cone.config.system = tmp.config.system.copy() self.vol_geom_astra, self.proj_geom_astra = convert_geometry_to_astra_vec( volume_geometry, sino_geom_cone)
def setUp(self): N = 128 angles = np.linspace(0, np.pi, 180, dtype='float32') ag = AcquisitionGeometry.create_Parallel2D()\ .set_angles(angles, angle_unit='radian')\ .set_panel(N, 0.1)\ .set_labels(['angle', 'horizontal']) ig = ag.get_ImageGeometry() ag3 = AcquisitionGeometry.create_Parallel3D()\ .set_angles(angles, angle_unit='radian')\ .set_panel((N, N), (0.1, 0.1))\ .set_labels(['vertical', 'angle', 'horizontal']) ig3 = ag3.get_ImageGeometry() self.ig = ig self.ag = ag self.ig3 = ig3 self.ag3 = ag3 self.norm = 14.85
def test_calculate_magnification(self): AG = AcquisitionGeometry.create_Cone2D(source_position=[0,-500], detector_position=[0.,1000.]) out = AG.config.system.calculate_magnification() self.assertEqual(out, [500, 1000, 3]) AG = AcquisitionGeometry.create_Cone2D(source_position=[0,-500], detector_position=[0.,1000.], rotation_axis_position=[0.,250.]) out = AG.config.system.calculate_magnification() self.assertEqual(out, [750, 750, 2]) AG = AcquisitionGeometry.create_Cone2D(source_position=[0,-500], detector_position=[0.,1000.], rotation_axis_position=[5.,0.]) out = AG.config.system.calculate_magnification() source_to_object = numpy.sqrt(5.0**2 + 500.0**2) theta = math.atan2(5.0,500.0) source_to_detector = 1500.0/math.cos(theta) self.assertEqual(out, [source_to_object, source_to_detector - source_to_object, source_to_detector/source_to_object]) AG = AcquisitionGeometry.create_Cone2D(source_position=[0,-500], detector_position=[0.,1000.], rotation_axis_position=[5.,0.],detector_direction_x=[math.sqrt(5),math.sqrt(5)]) out = AG.config.system.calculate_magnification() source_to_object = numpy.sqrt(5.0**2 + 500.0**2) ab = (AG.config.system.rotation_axis.position - AG.config.system.source.position).astype(numpy.float64)/source_to_object #source_position + d * ab = detector_position + t * detector_direction_x #x: d * ab[0] = t * detector_direction_x[0] #y: -500 + d * ab[1] = 1000 + t * detector_direction_x[1] # t = (d * ab[0]) / math.sqrt(5) # d = 1500 / (ab[1] - ab[0]) source_to_detector = 1500 / (ab[1] - ab[0]) self.assertEqual(out, [source_to_object, source_to_detector - source_to_object, source_to_detector/source_to_object])
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 setUp(self): #%% Setup Geometry voxel_num_xy = 255 voxel_num_z = 15 mag = 2 src_to_obj = 50 src_to_det = src_to_obj * mag pix_size = 0.2 det_pix_x = voxel_num_xy det_pix_y = voxel_num_z num_projections = 1000 angles = np.linspace(0, 360, num=num_projections, endpoint=False) self.ag = AcquisitionGeometry.create_Cone2D([0,-src_to_obj],[0,src_to_det-src_to_obj])\ .set_angles(angles)\ .set_panel(det_pix_x, pix_size)\ .set_labels(['angle','horizontal']) self.ig = self.ag.get_ImageGeometry() self.ag3D = AcquisitionGeometry.create_Cone3D([0,-src_to_obj,0],[0,src_to_det-src_to_obj,0])\ .set_angles(angles)\ .set_panel((det_pix_x,det_pix_y), (pix_size,pix_size))\ .set_labels(['angle','vertical','horizontal']) self.ig3D = self.ag3D.get_ImageGeometry() self.ad3D = self.ag3D.allocate('random') self.ig3D = self.ag3D.get_ImageGeometry()
def setUp(self): #%% Setup Geometry voxel_num_xy = 255 voxel_num_z = 15 cs_ind = (voxel_num_z - 1) // 2 mag = 2 src_to_obj = 50 src_to_det = src_to_obj * mag pix_size = 0.2 det_pix_x = voxel_num_xy det_pix_y = voxel_num_z num_projections = 1000 angles = np.linspace(0, 360, num=num_projections, endpoint=False) self.ag = AcquisitionGeometry.create_Cone2D([0,-src_to_obj],[0,src_to_det-src_to_obj])\ .set_angles(angles)\ .set_panel(det_pix_x, pix_size)\ .set_labels(['angle','horizontal']) self.ig = self.ag.get_ImageGeometry() self.ag3D = AcquisitionGeometry.create_Cone3D([0,-src_to_obj,0],[0,src_to_det-src_to_obj,0])\ .set_angles(angles)\ .set_panel((det_pix_x,det_pix_y), (pix_size,pix_size))\ .set_labels(['angle','vertical','horizontal']) self.ig3D = self.ag3D.get_ImageGeometry() #%% Create phantom kernel_size = voxel_num_xy kernel_radius = (kernel_size - 1) // 2 y, x = np.ogrid[-kernel_radius:kernel_radius + 1, -kernel_radius:kernel_radius + 1] circle1 = [5, 0, 0] #r,x,y dist1 = ((x - circle1[1])**2 + (y - circle1[2])**2)**0.5 circle2 = [5, 80, 0] #r,x,y dist2 = ((x - circle2[1])**2 + (y - circle2[2])**2)**0.5 circle3 = [25, 0, 80] #r,x,y dist3 = ((x - circle3[1])**2 + (y - circle3[2])**2)**0.5 mask1 = (dist1 - circle1[0]).clip(0, 1) mask2 = (dist2 - circle2[0]).clip(0, 1) mask3 = (dist3 - circle3[0]).clip(0, 1) phantom = 1 - np.logical_and(np.logical_and(mask1, mask2), mask3) self.golden_data = self.ig3D.allocate(0) for i in range(4): self.golden_data.fill(array=phantom, vertical=7 + i) self.golden_data_cs = self.golden_data.get_slice(vertical=cs_ind, force=True) self.Op = ProjectionOperator(self.ig3D, self.ag3D) self.fp = self.Op.direct(self.golden_data)
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 test_get_centre_slice(self): AG = AcquisitionGeometry.create_Parallel3D(detector_direction_y=[0,1,1]) AG.set_panel([1000,2000],[1,1]) AG_cs = AG.get_centre_slice() AG2 = AcquisitionGeometry.create_Parallel2D() AG2.set_panel([1000,1],[1,math.sqrt(0.5)]) self.assertEqual(AG2, AG_cs)
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_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 setUp(self): #%% Setup Geometry voxel_num_xy = 255 voxel_num_z = 15 self.cs_ind = (voxel_num_z-1)//2 src_to_obj = 500 src_to_det = src_to_obj pix_size = 0.2 det_pix_x = voxel_num_xy det_pix_y = voxel_num_z num_projections = 360 angles = np.linspace(0, 2*np.pi, num=num_projections, endpoint=False) self.ag_cone = AcquisitionGeometry.create_Cone3D([0,-src_to_obj,0],[0,src_to_det-src_to_obj,0])\ .set_angles(angles, angle_unit='radian')\ .set_panel((det_pix_x,det_pix_y), (pix_size,pix_size))\ .set_labels(['vertical','angle','horizontal']) self.ag_parallel = AcquisitionGeometry.create_Parallel3D()\ .set_angles(angles, angle_unit='radian')\ .set_panel((det_pix_x,det_pix_y), (pix_size,pix_size))\ .set_labels(['vertical','angle','horizontal']) self.ig_3D = self.ag_parallel.get_ImageGeometry() #%% Create phantom kernel_size = voxel_num_xy kernel_radius = (kernel_size - 1) // 2 y, x = np.ogrid[-kernel_radius:kernel_radius+1, -kernel_radius:kernel_radius+1] circle1 = [5,0,0] #r,x,y dist1 = ((x - circle1[1])**2 + (y - circle1[2])**2)**0.5 circle2 = [5,100,0] #r,x,y dist2 = ((x - circle2[1])**2 + (y - circle2[2])**2)**0.5 circle3 = [25,0,100] #r,x,y dist3 = ((x - circle3[1])**2 + (y - circle3[2])**2)**0.5 mask1 =(dist1 - circle1[0]).clip(0,1) mask2 =(dist2 - circle2[0]).clip(0,1) mask3 =(dist3 - circle3[0]).clip(0,1) phantom = 1 - np.logical_and(np.logical_and(mask1, mask2),mask3) self.golden_data = self.ig_3D.allocate(0) for i in range(4): self.golden_data.fill(array=phantom, vertical=7+i) self.golden_data_cs = self.golden_data.subset(vertical=self.cs_ind)
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 )
def setUp(self): self.ig = ImageGeometry(2, 3, 4, channels=5) angles = numpy.asarray([90., 0., -90.], dtype=numpy.float32) self.ag_cone = AcquisitionGeometry.create_Cone3D([0,-500,0],[0,500,0])\ .set_panel((20,2))\ .set_angles(angles)\ .set_channels(4) self.ag = AcquisitionGeometry.create_Parallel3D()\ .set_angles(angles)\ .set_channels(4)\ .set_panel((20,2))
def test_system_description(self): AG = AcquisitionGeometry.create_Parallel3D() self.assertTrue(AG.system_description == 'simple') AG = AcquisitionGeometry.create_Parallel3D( detector_position=[5, 0, 0], rotation_axis_position=[5, 0, 0]) self.assertTrue(AG.system_description == 'simple') AG = AcquisitionGeometry.create_Parallel3D( rotation_axis_position=[5, 0, 0]) self.assertTrue(AG.system_description == 'offset') AG = AcquisitionGeometry.create_Parallel3D(ray_direction=[1, 1, 0]) self.assertTrue(AG.system_description == 'advanced')
def test_filtering(self): ag = AcquisitionGeometry.create_Parallel3D()\ .set_panel([64,3],[0.1,0.1])\ .set_angles([0,90]) ad = ag.allocate('random', seed=0) reconstructor = FBP(ad) out1 = ad.copy() reconstructor._pre_filtering(out1) #by hand filter = reconstructor.get_filter_array() reconstructor._calculate_weights(ag) pad0 = (len(filter) - ag.pixel_num_h) // 2 pad1 = len(filter) - ag.pixel_num_h - pad0 out2 = ad.array.copy() out2 *= reconstructor._weights for i in range(2): proj_padded = np.zeros((ag.pixel_num_v, len(filter))) proj_padded[:, pad0:-pad1] = out2[i] filtered_proj = fft(proj_padded, axis=-1) filtered_proj *= filter filtered_proj = ifft(filtered_proj, axis=-1) out2[i] = np.real(filtered_proj)[:, pad0:-pad1] diff = (out1 - out2).abs().max() self.assertLess(diff, 1e-5)
def has_gpu_tigre(): if not has_tigre: return False has_gpu = True if has_nvidia_smi(): from cil.plugins.tigre import ProjectionOperator from tigre.utilities.errors import TigreCudaCallError N = 3 angles = np.linspace(0, np.pi, 2, dtype='float32') ag = AcquisitionGeometry.create_Cone2D([0,-100],[0,200])\ .set_angles(angles, angle_unit='radian')\ .set_panel(N, 0.1)\ .set_labels(['angle', 'horizontal']) ig = ag.get_ImageGeometry() data = ig.allocate(1) Op = ProjectionOperator(ig, ag) try: Op.direct(data) has_gpu = True except TigreCudaCallError: has_gpu = False else: has_gpu = False print("has_gpu_tigre\t{}".format(has_gpu)) return has_gpu
def test_L1Norm_2D(self): model = 12 # select a model number from the library N = 400 # set dimension of the phantom path = os.path.dirname(tomophantom.__file__) path_library2D = os.path.join(path, "Phantom2DLibrary.dat") phantom_2D = TomoP2D.Model(model, N, path_library2D) # data = ImageData(phantom_2D) ig = ImageGeometry(voxel_num_x=N, voxel_num_y=N) data = ig.allocate(None) data.fill(phantom_2D) # Create acquisition data and geometry detectors = N angles = np.linspace(0, 180, 120, dtype=np.float32) ag = AcquisitionGeometry.create_Parallel2D()\ .set_angles(angles, angle_unit=AcquisitionGeometry.DEGREE)\ .set_panel(detectors) sin = ag.allocate(None) sino = TomoP2D.ModelSino(model, detectors, detectors, angles, path_library2D) sin.fill(sino) sin_stripe = sin.copy() # sin_stripe = sin tmp = sin_stripe.as_array() tmp[:,::27]=tmp[:,::28] sin_stripe.fill(tmp) ring_recon = RingRemover(20, "db15", 21, info = True)(sin_stripe) error = (ring_recon - sin).abs().as_array().mean() print ("L1Norm ", error) np.testing.assert_almost_equal(error, 83.20592, 4)
def test_align_reference_frame_tigre(self): ag = AcquisitionGeometry.create_Cone2D(source_position=[0, 50], detector_position=[0., -100.], rotation_axis_position=[5., 2]) ag.set_panel(100) ag_align = ag.copy() ag_align.config.system.align_reference_frame('tigre') numpy.testing.assert_allclose(ag_align.config.system.source.position, [0, -ag.dist_source_center], atol=1E-6) numpy.testing.assert_allclose( ag_align.config.system.rotation_axis.position, [0, 0], rtol=1E-6) cos_theta = abs( ag.config.system.source.position[1] - ag.config.system.rotation_axis.position[1]) / ag.dist_source_center sin_theta = math.sin(math.acos(cos_theta)) vec = ag.config.system.detector.position - ag.config.system.source.position tmp = abs(vec[1]) * cos_theta det_y = tmp - ag.dist_source_center det_x = numpy.sqrt(vec[1]**2 - tmp**2) numpy.testing.assert_allclose(ag_align.config.system.detector.position, [det_x, det_y], rtol=1E-6) dir_x = -ag.config.system.detector.direction_x[0] * cos_theta dir_y = ag.config.system.detector.direction_x[0] * sin_theta numpy.testing.assert_allclose( ag_align.config.system.detector.direction_x, [dir_x, dir_y], rtol=1E-6)
def test_get_centre_slice(self): AG = AcquisitionGeometry.create_Cone2D(source_position=[0, -500], detector_position=[0., 1000.]) AG2 = AG.copy() AG2.config.system.get_centre_slice() self.assertEqual(AG.config.system, AG2.config.system)
def test_fill_dimension_AcquisitionData(self): ag = AcquisitionGeometry.create_Parallel3D() ag.set_channels(4) ag.set_panel([2,3]) ag.set_angles([0,1,2,3,5]) ag.set_labels(('horizontal','angle','vertical','channel')) u = ag.allocate(0) print (u.shape) # (2, 5, 3, 4) a = numpy.ones((2,5)) # default_labels = [ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.HORIZONTAL_X] b = u.subset(channel=0, vertical=0) print(b.shape) data = u.as_array() u.fill(a, channel=0, vertical=0) print(u.shape) numpy.testing.assert_array_equal(u.subset(channel=0, vertical=0).as_array(), a) u.fill(2, channel=0, vertical=0) numpy.testing.assert_array_equal(u.subset(channel=0, vertical=0).as_array(), 2 * a) u.fill(2, channel=0, vertical=0) numpy.testing.assert_array_equal(u.subset(channel=0, vertical=0).as_array(), 2 * a) b = u.subset(channel=0, vertical=0) b.fill(3) u.fill(b, channel=1, vertical=1) numpy.testing.assert_array_equal(u.subset(channel=1, vertical=1).as_array(), 3 * a)
def test_fill_dimension_AcquisitionData(self): ag = AcquisitionGeometry.create_Parallel3D() ag.set_channels(4) ag.set_panel([2,3]) ag.set_angles([0,1,2,3,5]) ag.set_labels(('horizontal','angle','vertical','channel')) u = ag.allocate(0) a = numpy.ones((4,2)) # default_labels = [ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.HORIZONTAL_X] data = u.as_array() axis_number = u.get_dimension_axis('horizontal_y') u.fill(a, horizontal_y=0) numpy.testing.assert_array_equal(u.subset(horizontal_y=0).as_array(), a) u.fill(2, horizontal_y=1) numpy.testing.assert_array_equal(u.subset(horizontal_y=0).as_array(), 2 * a) u.fill(2, horizontal_y=1) numpy.testing.assert_array_equal(u.subset(horizontal_y=1).as_array(), 2 * a) b = u.subset(horizontal_y=2) b.fill(3) u.fill(b, horizontal_y=2) numpy.testing.assert_array_equal(u.subset(horizontal_y=2).as_array(), 3 * a) # slice with 2 axis a = numpy.ones((2,)) u.fill(a, horizontal_y=1, vertical=0) numpy.testing.assert_array_equal(u.subset(horizontal_y=1, vertical=0).as_array(), a)
def test_align_reference_frame_tigre(self): AG = AcquisitionGeometry.create_Cone3D( source_position=[5, 500, 0], detector_position=[5., -1000., 0], rotation_axis_position=[5, 0, 0], rotation_axis_direction=[0, 0, -1]) AG.config.system.align_reference_frame('tigre') numpy.testing.assert_allclose(AG.config.system.source.position, [0, -500, 0], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.detector.position, [0, 1000, 0], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.detector.direction_x, [1, 0, 0], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.detector.direction_y, [0, 0, -1], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.rotation_axis.position, [0, 0, 0], rtol=1E-6) numpy.testing.assert_allclose(AG.config.system.rotation_axis.direction, [0, 0, 1], rtol=1E-6)
def test_cone3D_simple(self): ag = AcquisitionGeometry.create_Cone3D(source_position=[0,-2,0], detector_position=[0,1,0])\ .set_angles(self.angles_deg, angle_unit='degree')\ .set_labels(['vertical', 'angle','horizontal'])\ .set_panel((self.num_pixels_x,self.num_pixels_y), (self.pixel_size_x,self.pixel_size_y)) ig = ag.get_ImageGeometry() ig.voxel_num_y = 50 ig.voxel_size_y /= 2 angles_rad = np.array([-np.pi / 2, -np.pi, -3 * np.pi / 2]) tg_geometry, tg_angles = CIL2TIGREGeometry.getTIGREGeometry(ig, ag) np.testing.assert_allclose( tg_geometry.DSD, ag.dist_center_detector + ag.dist_source_center) np.testing.assert_allclose(tg_geometry.DSO, ag.dist_source_center) np.testing.assert_allclose(tg_angles, angles_rad) np.testing.assert_allclose(tg_geometry.dDetector, ag.config.panel.pixel_size[::-1]) np.testing.assert_allclose(tg_geometry.nDetector, ag.config.panel.num_pixels[::-1]) np.testing.assert_allclose( tg_geometry.sDetector, tg_geometry.dDetector * tg_geometry.nDetector) np.testing.assert_allclose(tg_geometry.rotDetector, 0) np.testing.assert_allclose(tg_geometry.offDetector, 0) np.testing.assert_allclose(tg_geometry.offOrigin, 0) mag = ag.magnification np.testing.assert_allclose(tg_geometry.nVoxel, [3, 50, 128]) np.testing.assert_allclose(tg_geometry.dVoxel, [0.2 / mag, 0.05 / mag, 0.1 / mag])
def test_weights(self): ag = AcquisitionGeometry.create_Cone3D([0,-1,0],[0,2,0])\ .set_panel([3,4],[0.1,0.2])\ .set_angles([0,90]) ad = ag.allocate(0) reconstructor = FDK(ad) reconstructor._calculate_weights(ag) weights = reconstructor._weights scaling = 7.5 * np.pi weights_new = np.ones_like(weights) det_size_x = ag.pixel_size_h * ag.pixel_num_h det_size_y = ag.pixel_size_v * ag.pixel_num_v ray_length_z = 3 for j in range(4): ray_length_y = -det_size_y / 2 + ag.pixel_size_v * (j + 0.5) for i in range(3): ray_length_x = -det_size_x / 2 + ag.pixel_size_h * (i + 0.5) ray_length = (ray_length_x**2 + ray_length_y**2 + ray_length_z**2)**0.5 weights_new[j, i] = scaling * ray_length_z / ray_length diff = np.max(np.abs(weights - weights_new)) self.assertLess(diff, 1e-5)