def test_ImageGeometry_allocate(self): vgeometry = ImageGeometry(voxel_num_x=4, voxel_num_y=3, channels=2) image = vgeometry.allocate() self.assertEqual(0,image.as_array()[0][0][0]) image = vgeometry.allocate(1) self.assertEqual(1,image.as_array()[0][0][0]) default_order = ['channel' , 'horizontal_y' , 'horizontal_x'] self.assertEqual(default_order[0], image.dimension_labels[0]) self.assertEqual(default_order[1], image.dimension_labels[1]) self.assertEqual(default_order[2], image.dimension_labels[2]) order = [ 'horizontal_x' , 'horizontal_y', 'channel' ] vgeometry.set_labels(order) image = vgeometry.allocate(0) self.assertEqual(order[0], image.dimension_labels[0]) self.assertEqual(order[1], image.dimension_labels[1]) self.assertEqual(order[2], image.dimension_labels[2]) ig = ImageGeometry(2,3,2) try: z = ImageData(numpy.random.randint(10, size=(2,3)), geometry=ig) self.assertTrue(False) except ValueError as ve: print (ve) self.assertTrue(True)
class NEXUSDataReader(object): def __init__(self, **kwargs): ''' Constructor Input: file_name full path to NEXUS file ''' self.file_name = kwargs.get('file_name', None) if self.file_name is not None: self.set_up(file_name=self.file_name) def set_up(self, file_name=None): self.file_name = os.path.abspath(file_name) # check that h5py library is installed if (h5pyAvailable == False): raise Exception('h5py is not available, cannot load NEXUS files.') if self.file_name == None: raise Exception('Path to nexus file is required.') # check if nexus file exists if not (os.path.isfile(self.file_name)): raise Exception('File\n {}\n does not exist.'.format( self.file_name)) self._geometry = None def read_dimension_labels(self, attrs): dimension_labels = [None] * 4 for k, v in attrs.items(): if k in ['dim0', 'dim1', 'dim2', 'dim3']: dimension_labels[int(k[3:])] = v # remove Nones dimension_labels = [i for i in dimension_labels if i] if len(dimension_labels) == 0: dimension_labels = None return dimension_labels def get_geometry(self): ''' Parse NEXUS file and returns either ImageData or Acquisition Data depending on file content ''' with h5py.File(self.file_name, 'r') as dfile: if np.string_(dfile.attrs['creator']) != np.string_( 'NEXUSDataWriter.py'): raise Exception( 'We can parse only files created by NEXUSDataWriter.py') ds_data = dfile['entry1/tomo_entry/data/data'] if ds_data.attrs['data_type'] == 'ImageData': self._geometry = ImageGeometry( voxel_num_x=int(ds_data.attrs['voxel_num_x']), voxel_num_y=int(ds_data.attrs['voxel_num_y']), voxel_num_z=int(ds_data.attrs['voxel_num_z']), voxel_size_x=ds_data.attrs['voxel_size_x'], voxel_size_y=ds_data.attrs['voxel_size_y'], voxel_size_z=ds_data.attrs['voxel_size_z'], center_x=ds_data.attrs['center_x'], center_y=ds_data.attrs['center_y'], center_z=ds_data.attrs['center_z'], channels=ds_data.attrs['channels']) if ds_data.attrs.__contains__('channel_spacing') == True: self._geometry.channel_spacing = ds_data.attrs[ 'channel_spacing'] # read the dimension_labels from dim{} dimension_labels = self.read_dimension_labels(ds_data.attrs) else: # AcquisitionData if ds_data.attrs.__contains__('dist_source_center') or dfile[ 'entry1/tomo_entry'].__contains__( 'config/source/position'): geom_type = 'cone' else: geom_type = 'parallel' if ds_data.attrs.__contains__('num_pixels_v'): num_pixels_v = ds_data.attrs.get('num_pixels_v') elif ds_data.attrs.__contains__('pixel_num_v'): num_pixels_v = ds_data.attrs.get('pixel_num_v') else: num_pixels_v = 1 if num_pixels_v > 1: dim = 3 else: dim = 2 if self.is_old_file_version(): num_pixels_h = ds_data.attrs.get('pixel_num_h', 1) num_channels = ds_data.attrs['channels'] ds_angles = dfile['entry1/tomo_entry/data/rotation_angle'] if geom_type == 'cone' and dim == 3: self._geometry = AcquisitionGeometry.create_Cone3D( source_position=[ 0, -ds_data.attrs['dist_source_center'], 0 ], detector_position=[ 0, ds_data.attrs['dist_center_detector'], 0 ]) elif geom_type == 'cone' and dim == 2: self._geometry = AcquisitionGeometry.create_Cone2D( source_position=[ 0, -ds_data.attrs['dist_source_center'] ], detector_position=[ 0, ds_data.attrs['dist_center_detector'] ]) elif geom_type == 'parallel' and dim == 3: self._geometry = AcquisitionGeometry.create_Parallel3D( ) elif geom_type == 'parallel' and dim == 2: self._geometry = AcquisitionGeometry.create_Parallel2D( ) else: num_pixels_h = ds_data.attrs.get('num_pixels_h', 1) num_channels = ds_data.attrs['num_channels'] ds_angles = dfile['entry1/tomo_entry/config/angles'] rotation_axis_position = list(dfile[ 'entry1/tomo_entry/config/rotation_axis/position']) detector_position = list( dfile['entry1/tomo_entry/config/detector/position']) ds_detector = dfile['entry1/tomo_entry/config/detector'] if ds_detector.__contains__('direction_x'): detector_direction_x = list(dfile[ 'entry1/tomo_entry/config/detector/direction_x']) else: detector_direction_x = list(dfile[ 'entry1/tomo_entry/config/detector/direction_row']) if ds_detector.__contains__('direction_y'): detector_direction_y = list(dfile[ 'entry1/tomo_entry/config/detector/direction_y']) elif ds_detector.__contains__('direction_col'): detector_direction_y = list(dfile[ 'entry1/tomo_entry/config/detector/direction_col']) ds_rotate = dfile['entry1/tomo_entry/config/rotation_axis'] if ds_rotate.__contains__('direction'): rotation_axis_direction = list(dfile[ 'entry1/tomo_entry/config/rotation_axis/direction'] ) if geom_type == 'cone': source_position = list( dfile['entry1/tomo_entry/config/source/position']) if dim == 2: self._geometry = AcquisitionGeometry.create_Cone2D( source_position, detector_position, detector_direction_x, rotation_axis_position) else: self._geometry = AcquisitionGeometry.create_Cone3D(source_position,\ detector_position, detector_direction_x, detector_direction_y,\ rotation_axis_position, rotation_axis_direction) else: ray_direction = list( dfile['entry1/tomo_entry/config/ray/direction']) if dim == 2: self._geometry = AcquisitionGeometry.create_Parallel2D( ray_direction, detector_position, detector_direction_x, rotation_axis_position) else: self._geometry = AcquisitionGeometry.create_Parallel3D(ray_direction,\ detector_position, detector_direction_x, detector_direction_y,\ rotation_axis_position, rotation_axis_direction) # for all Aquisition data #set angles angles = list(ds_angles) angle_unit = ds_angles.attrs.get('angle_unit', 'degree') initial_angle = ds_angles.attrs.get('initial_angle', 0) self._geometry.set_angles(angles, initial_angle=initial_angle, angle_unit=angle_unit) #set panel pixel_size_v = ds_data.attrs.get('pixel_size_v', ds_data.attrs['pixel_size_h']) origin = ds_data.attrs.get('panel_origin', 'bottom-left') self._geometry.set_panel((num_pixels_h, num_pixels_v),\ pixel_size=(ds_data.attrs['pixel_size_h'], pixel_size_v),\ origin=origin) # set channels self._geometry.set_channels(num_channels) dimension_labels = [] dimension_labels = self.read_dimension_labels(ds_data.attrs) #set labels self._geometry.set_labels(dimension_labels) return self._geometry def read(self): if self._geometry is None: self.get_geometry() with h5py.File(self.file_name, 'r') as dfile: ds_data = dfile['entry1/tomo_entry/data/data'] data = np.array(ds_data, dtype=np.float32) # handle old files? if self.is_old_file_version(): if isinstance(self._geometry, AcquisitionGeometry): return AcquisitionData(data, True, geometry=self._geometry, suppress_warning=True) elif isinstance(self._geometry, ImageGeometry): return ImageData(data, True, geometry=self._geometry, suppress_warning=True) else: raise TypeError("Unsupported geometry. Expected ImageGeometry or AcquisitionGeometry, got {}"\ .format(type(self._geometry))) output = self._geometry.allocate(None) output.fill(data) return output def load_data(self): '''alias of read''' return self.read() def is_old_file_version(self): #return ds_data.attrs.__contains__('geom_type') with h5py.File(self.file_name, 'r') as dfile: if np.string_(dfile.attrs['creator']) != np.string_( 'NEXUSDataWriter.py'): raise Exception( 'We can parse only files created by NEXUSDataWriter.py') ds_data = dfile['entry1/tomo_entry/data/data'] return 'geom_type' in ds_data.attrs.keys()
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_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_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)) 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 ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() self.assertTrue( non_default_dimension_labels == list(data.dimension_labels)) def test_ImageDataAllocate2b(self): non_default_dimension_labels = [ ImageGeometry.HORIZONTAL_X, ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_Y, ImageGeometry.CHANNEL ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() 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 ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() 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 ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() 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 ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() 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 ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() 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 ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() 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 ] self.ig.set_labels(non_default_dimension_labels) data = self.ig.allocate() 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)) 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 ] self.ag.set_labels(non_default_dimension_labels) data = self.ag.allocate() self.assertTrue( non_default_dimension_labels == list(data.dimension_labels)) def test_AcquisitionDataAllocate2b(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] self.ag.set_labels(non_default_dimension_labels) data = self.ag.allocate() self.assertTrue(data.shape == (4, 20, 2, 3)) def test_AcquisitionDataSubset1a(self): non_default_dimension_labels = [ AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL, AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE ] self.ag.set_labels(non_default_dimension_labels) data = self.ag.allocate() #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 ] self.ag.set_labels(non_default_dimension_labels) data = self.ag.allocate() #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 ] self.ag.set_labels(non_default_dimension_labels) data = self.ag.allocate() #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 ] self.ag.set_labels(non_default_dimension_labels) data = self.ag.allocate() #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 ] self.ag.set_labels(non_default_dimension_labels) 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_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, 20)) def test_AcquisitionDataSubset1i(self): data = self.ag_cone.allocate() sliceme = 1 sub = data.subset(vertical=sliceme, force=True) self.assertTrue(sub.shape == (4, 3, 20)) 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, ))