Beispiel #1
0
    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],
                              sgeometry.dimension_labels)
        sino = sgeometry.allocate()

        # test reshape
        new_order = [AcquisitionGeometry.HORIZONTAL ,
                 AcquisitionGeometry.CHANNEL , AcquisitionGeometry.VERTICAL ,
                 AcquisitionGeometry.ANGLE]
        ss = sino.subset(new_order)

        self.assertListEqual(new_order, ss.geometry.dimension_labels)

        ss1 = ss.subset(vertical = 0)
        self.assertListEqual([AcquisitionGeometry.HORIZONTAL ,
                 AcquisitionGeometry.CHANNEL  ,
                 AcquisitionGeometry.ANGLE], ss1.geometry.dimension_labels)
        ss2 = ss.subset(vertical = 0, channel=0)
        self.assertListEqual([AcquisitionGeometry.HORIZONTAL ,
                 AcquisitionGeometry.ANGLE], ss2.geometry.dimension_labels)
Beispiel #2
0
 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()
     shape = sino.shape
     print ("shape", shape)
     self.assertEqual(0,sino.as_array()[0][0][0][0])
     self.assertEqual(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' ]
     sino = ageometry.allocate(0,dimension_labels=order)
     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])
Beispiel #3
0
 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)
Beispiel #4
0
    def setUp(self):
        self.ig = ImageGeometry(1, 2, 3, channels=4)
        angles = numpy.asarray([90., 0., -90.], dtype=numpy.float32)

        self.ag = AcquisitionGeometry('cone',
                                      'edo',
                                      pixel_num_h=20,
                                      pixel_num_v=2,
                                      angles=angles,
                                      dist_source_center=312.2,
                                      dist_center_detector=123.,
                                      channels=4)
Beispiel #5
0
    def __init__(self, geomv, geomp, default=False):
        super(CCPiProjectorSimple, self).__init__()
        
        # Store volume and sinogram geometries.
        self.acquisition_geometry = geomp
        self.volume_geometry = geomv
        
        if geomp.geom_type == "cone":
            raise TypeError('Can only handle parallel beam')
        
        # set-up the geometries if compatible
        geoms = setupCCPiGeometries(geomv, geomp, 0)
        

        vg = ImageGeometry(voxel_num_x=geoms['output_volume_x'],
                           voxel_num_y=geoms['output_volume_y'], 
                           voxel_num_z=geoms['output_volume_z'])

        pg = AcquisitionGeometry('parallel',
                          '3D',
                          geomp.angles,
                          geoms['n_h'], geomp.pixel_size_h,
                          geoms['n_v'], geomp.pixel_size_v #2D in 3D is a slice 1 pixel thick
                          )
        if not default:
            # check if geometry is the same (on the voxels)
            if not ( vg.voxel_num_x == geomv.voxel_num_x and \
                     vg.voxel_num_y == geomv.voxel_num_y and \
                     vg.voxel_num_z == geomv.voxel_num_z ):
                msg = 'The required volume geometry will not work\nThe following would\n'
                msg += vg.__str__()
                raise ValueError(msg)
            if not (pg.pixel_num_h == geomp.pixel_num_h and \
                    pg.pixel_num_v == geomp.pixel_num_v and \
                    len( pg.angles ) == len( geomp.angles ) ) :
                msg = 'The required acquisition geometry will not work\nThe following would\n'
                msg += pg.__str__()
                raise ValueError(msg)
        
        self.fp = CCPiForwardProjector(image_geometry=vg,
                                       acquisition_geometry=pg,
                                       output_axes_order=['angle','vertical','horizontal'])
        
        self.bp = CCPiBackwardProjector(image_geometry=vg,
                                    acquisition_geometry=pg,
                                    output_axes_order=[ ImageGeometry.HORIZONTAL_X,
                 ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL])
                
        # Initialise empty for singular value.
        self.s1 = None
        self.ag = pg
        self.vg = vg
Beispiel #6
0
def setupCCPiGeometries(ig, ag, counter):
    Phantom_ccpi = ig.allocate(dimension_labels=[
        ImageGeometry.HORIZONTAL_X, ImageGeometry.HORIZONTAL_Y,
        ImageGeometry.VERTICAL
    ])

    voxel_per_pixel = 1
    angles = ag.angles
    geoms = pbalg.pb_setup_geometry_from_image(Phantom_ccpi.as_array(), angles,
                                               voxel_per_pixel)

    pg = AcquisitionGeometry(
        'parallel',
        '3D',
        angles,
        geoms['n_h'],
        1.0,
        geoms['n_v'],
        1.0  #2D in 3D is a slice 1 pixel thick
    )

    center_of_rotation = Phantom_ccpi.get_dimension_size('horizontal_x') / 2
    #ad = AcquisitionData(geometry=pg,dimension_labels=['angle','vertical','horizontal'])
    ad = pg.allocate(dimension_labels=[
        AcquisitionGeometry.ANGLE, AcquisitionGeometry.VERTICAL,
        AcquisitionGeometry.HORIZONTAL
    ])
    geoms_i = pbalg.pb_setup_geometry_from_acquisition(ad.as_array(), angles,
                                                       center_of_rotation,
                                                       voxel_per_pixel)

    counter += 1

    if counter < 4:
        print(geoms, geoms_i)
        if (not (geoms_i == geoms)):
            print("not equal and {} {} {}".format(counter,
                                                  geoms['output_volume_z'],
                                                  geoms_i['output_volume_z']))
            X = max(geoms['output_volume_x'], geoms_i['output_volume_x'])
            Y = max(geoms['output_volume_y'], geoms_i['output_volume_y'])
            Z = max(geoms['output_volume_z'], geoms_i['output_volume_z'])
            return setupCCPiGeometries(X, Y, Z, angles, counter)
        else:
            print("happy now {} {} {}".format(counter,
                                              geoms['output_volume_z'],
                                              geoms_i['output_volume_z']))

            return geoms
    else:
        return geoms_i
Beispiel #7
0
    def load(self):
        pixel_num_h = 0
        pixel_num_v = 0
        xpixel_size = 0
        ypixel_size = 0
        source_x = 0
        detector_x = 0
        with open(self.filename) as f:
            content = f.readlines()
        content = [x.strip() for x in content]
        for line in content:
            if line.startswith("SrcToObject"):
                source_x = float(line.split('=')[1])
            elif line.startswith("SrcToDetector"):
                detector_x = float(line.split('=')[1])
            elif line.startswith("DetectorPixelsY"):
                pixel_num_v = int(line.split('=')[1])
                #self.num_of_vertical_pixels = self.calc_v_alighment(self.num_of_vertical_pixels, self.pixels_per_voxel)
            elif line.startswith("DetectorPixelsX"):
                pixel_num_h = int(line.split('=')[1])
            elif line.startswith("DetectorPixelSizeX"):
                xpixel_size = float(line.split('=')[1])
            elif line.startswith("DetectorPixelSizeY"):
                ypixel_size = float(line.split('=')[1])
            elif line.startswith("Projections"):
                self.num_projections = int(line.split('=')[1])
            elif line.startswith("InitialAngle"):
                self.initial_angle = float(line.split('=')[1])
            elif line.startswith("Name"):
                self.experiment_name = line.split('=')[1]
            elif line.startswith("Scattering"):
                self.scattering = float(line.split('=')[1])
            elif line.startswith("WhiteLevel"):
                self.white_level = float(line.split('=')[1])
            elif line.startswith("MaskRadius"):
                self.mask_radius = float(line.split('=')[1])

        #Read Angles
        angles = self.read_angles()
        self.geometry = AcquisitionGeometry(
            'cone',
            '3D',
            angles,
            pixel_num_h,
            xpixel_size,
            pixel_num_v,
            ypixel_size,
            -1 * source_x,
            detector_x - source_x,
        )
 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))
Beispiel #9
0
 def get_acquisition_data(self, dimensions=None):
     '''
     This method load the acquisition data and given dimension and returns an AcquisitionData Object
     '''
     data = self.load_projection(dimensions)
     dims = self.get_projection_dimensions()
     geometry = AcquisitionGeometry(
         'parallel',
         '3D',
         self.get_projection_angles(),
         pixel_num_h=dims[2],
         pixel_size_h=1,
         pixel_num_v=dims[1],
         pixel_size_v=1,
         dist_source_center=None,
         dist_center_detector=None,
         channels=1,
         dimension_labels=['angle', 'vertical', 'horizontal'])
     out = geometry.allocate()
     out.fill(data)
     return out
Beispiel #10
0
 def range_geometry(self):
     return AcquisitionGeometry(self.ag.geom_type,
                            self.ag.dimension,
                            self.ag.angles,
                            self.ag.pixel_num_h,
                            self.ag.pixel_size_h,
                            self.ag.pixel_num_v,
                            self.ag.pixel_size_v,
                            self.ag.dist_source_center,
                            self.ag.dist_center_detector,
                            self.ag.channels,
                            )
Beispiel #11
0
    def testwriteAcquisitionData(self):
        im_size = 5
        ag2d = AcquisitionGeometry(geom_type = 'parallel', 
                                   dimension = '2D', 
                                   angles = numpy.array([0, 1]), 
                                   pixel_num_h = im_size, 
                                   pixel_size_h = 1, 
                                   pixel_num_v = im_size, 
                                   pixel_size_v = 1)
        ad2d = ag2d.allocate()
        writer = NEXUSDataWriter()
        writer.set_up(file_name = os.path.join(os.getcwd(), 'test_nexus_ad2d.nxs'),
                      data_container = ad2d)
        writer.write_file()
        
        ag3d = AcquisitionGeometry(geom_type = 'cone', 
                                   dimension = '3D', 
                                   angles = numpy.array([0, 1]), 
                                   pixel_num_h = im_size, 
                                   pixel_size_h = 1, 
                                   pixel_num_v = im_size, 
                                   pixel_size_v = 1,
                                   dist_source_center = 1,
                                   dist_center_detector = 1, 
                                   channels = im_size)
        ad3d = ag3d.allocate()
        writer = NEXUSDataWriter()
        writer.set_up(file_name = os.path.join(os.getcwd(), 'test_nexus_ad3d.nxs'),
                      data_container = ad3d)
        writer.write_file()

        self.stestreadAcquisitionData()
Beispiel #12
0
 def stestreadAcquisitionData(self):
     im_size = 5
     ag2d_test = AcquisitionGeometry(geom_type = 'parallel', 
                                     dimension = '2D', 
                                     angles = numpy.array([0, 1]), 
                                     pixel_num_h = im_size, 
                                     pixel_size_h = 1, 
                                     pixel_num_v = im_size, 
                                     pixel_size_v = 1)
     ad2d_test = ag2d_test.allocate()
     
     reader2d = NEXUSDataReader()
     reader2d.set_up(nexus_file = os.path.join(os.getcwd(), 'test_nexus_ad2d.nxs'))
     ad2d = reader2d.load_data()
     ag2d = reader2d.get_geometry()
     numpy.testing.assert_array_equal(ad2d.as_array(), ad2d_test.as_array(), 'Loaded image is not correct')
     self.assertEqual(ag2d.geom_type, ag2d_test.geom_type, 'ImageGeometry.geom_type is not correct')
     numpy.testing.assert_array_equal(ag2d.angles, ag2d_test.angles, 'ImageGeometry.angles is not correct')
     self.assertEqual(ag2d.pixel_num_h, ag2d_test.pixel_num_h, 'ImageGeometry.pixel_num_h is not correct')
     self.assertEqual(ag2d.pixel_size_h, ag2d_test.pixel_size_h, 'ImageGeometry.pixel_size_h is not correct')
     self.assertEqual(ag2d.pixel_num_v, ag2d_test.pixel_num_v, 'ImageGeometry.pixel_num_v is not correct')
     self.assertEqual(ag2d.pixel_size_v, ag2d_test.pixel_size_v, 'ImageGeometry.pixel_size_v is not correct')
     
     ag3d_test = AcquisitionGeometry(geom_type = 'cone', 
                                     dimension = '3D', 
                                     angles = numpy.array([0, 1]), 
                                     pixel_num_h = im_size, 
                                     pixel_size_h = 1, 
                                     pixel_num_v = im_size, 
                                     pixel_size_v = 1,
                                     dist_source_center = 1,
                                     dist_center_detector = 1, 
                                     channels = im_size)
     ad3d_test = ag3d_test.allocate()
     
     reader3d = NEXUSDataReader()
     reader3d.set_up(nexus_file = os.path.join(os.getcwd(), 'test_nexus_ad3d.nxs'))
     ad3d = reader3d.load_data()
     ag3d = reader3d.get_geometry()
     
     numpy.testing.assert_array_equal(ad3d.as_array(), ad3d_test.as_array(), 'Loaded image is not correct')
     numpy.testing.assert_array_equal(ag3d.angles, ag3d_test.angles, 'AcquisitionGeometry.angles is not correct')
     self.assertEqual(ag3d.geom_type, ag3d_test.geom_type, 'AcquisitionGeometry.geom_type is not correct')
     self.assertEqual(ag3d.dimension, ag3d_test.dimension, 'AcquisitionGeometry.dimension is not correct')
     self.assertEqual(ag3d.pixel_num_h, ag3d_test.pixel_num_h, 'AcquisitionGeometry.pixel_num_h is not correct')
     self.assertEqual(ag3d.pixel_size_h, ag3d_test.pixel_size_h, 'AcquisitionGeometry.pixel_size_h is not correct')
     self.assertEqual(ag3d.pixel_num_v, ag3d_test.pixel_num_v, 'AcquisitionGeometry.pixel_num_v is not correct')
     self.assertEqual(ag3d.pixel_size_v, ag3d_test.pixel_size_v, 'AcquisitionGeometry.pixel_size_v is not correct')
     self.assertEqual(ag3d.dist_source_center, ag3d_test.dist_source_center, 'AcquisitionGeometry.dist_source_center is not correct')
     self.assertEqual(ag3d.dist_center_detector, ag3d_test.dist_center_detector, 'AcquisitionGeometry.dist_center_detector is not correct')
     self.assertEqual(ag3d.channels, ag3d_test.channels, 'AcquisitionGeometry.channels is not correct')
             
     def tearDown(self):
         os.remove(os.path.join(os.getcwd(), 'test_nexus_im.nxs'))
         os.remove(os.path.join(os.getcwd(), 'test_nexus_ad2d.nxs'))
         os.remove(os.path.join(os.getcwd(), 'test_nexus_ad3d.nxs'))
def setupCCPiGeometries(voxel_num_x, voxel_num_y, voxel_num_z, angles, counter):
    
    vg = ImageGeometry(voxel_num_x=voxel_num_x,voxel_num_y=voxel_num_y, voxel_num_z=voxel_num_z)
    Phantom_ccpi = ImageData(geometry=vg,
                        dimension_labels=['horizontal_x','horizontal_y','vertical'])
    #.subset(['horizontal_x','horizontal_y','vertical'])
    # ask the ccpi code what dimensions it would like
        
    voxel_per_pixel = 1
    geoms = pbalg.pb_setup_geometry_from_image(Phantom_ccpi.as_array(),
                                                angles,
                                                voxel_per_pixel )
    
    pg = AcquisitionGeometry('parallel',
                              '3D',
                              angles,
                              geoms['n_h'], 1.0,
                              geoms['n_v'], 1.0 #2D in 3D is a slice 1 pixel thick
                              )
    
    center_of_rotation = Phantom_ccpi.get_dimension_size('horizontal_x') / 2
    ad = AcquisitionData(geometry=pg,dimension_labels=['angle','vertical','horizontal'])
    geoms_i = pbalg.pb_setup_geometry_from_acquisition(ad.as_array(),
                                                angles,
                                                center_of_rotation,
                                                voxel_per_pixel )
    
    counter+=1
    
    if counter < 4:
        if (not ( geoms_i == geoms )):
            print ("not equal and {0}".format(counter))
            X = max(geoms['output_volume_x'], geoms_i['output_volume_x'])
            Y = max(geoms['output_volume_y'], geoms_i['output_volume_y'])
            Z = max(geoms['output_volume_z'], geoms_i['output_volume_z'])
            return setupCCPiGeometries(X,Y,Z,angles, counter)
        else:
            return geoms
    else:
        return geoms_i
Beispiel #14
0
        return self.volume_geometry

    def range_geometry(self):
        return self.sinogram_geometry

    def norm(self):
        x0 = self.volume_geometry.allocate('random')
        self.s1, sall, svec = LinearOperator.PowerMethod(self, 50, x0)
        return self.s1


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)
Beispiel #15
0
    def set_up(self,
               xtek_file=None,
               roi=-1,
               binning=[1, 1],
               normalize=False,
               flip=False):

        self.xtek_file = xtek_file
        self.roi = roi
        self.binning = binning
        self.normalize = normalize
        self.flip = flip

        if self.xtek_file == None:
            raise Exception('Path to xtek file is required.')

        # check if xtek file exists
        if not (os.path.isfile(self.xtek_file)):
            raise Exception('File\n {}\n does not exist.'.format(
                self.xtek_file))

        # check that PIL library is installed
        if (pilAvailable == False):
            raise Exception(
                "PIL (pillow) is not available, cannot load TIFF files.")

        # parse xtek file
        with open(self.xtek_file, 'r') as f:
            content = f.readlines()

        content = [x.strip() for x in content]

        for line in content:
            # filename of TIFF files
            if line.startswith("Name"):
                self._experiment_name = line.split('=')[1]
            # number of projections
            elif line.startswith("Projections"):
                num_projections = int(line.split('=')[1])
            # white level - used for normalization
            elif line.startswith("WhiteLevel"):
                self._white_level = float(line.split('=')[1])
            # number of pixels along Y axis
            elif line.startswith("DetectorPixelsY"):
                pixel_num_v_0 = int(line.split('=')[1])
            # number of pixels along X axis
            elif line.startswith("DetectorPixelsX"):
                pixel_num_h_0 = int(line.split('=')[1])
            # pixel size along X axis
            elif line.startswith("DetectorPixelSizeX"):
                pixel_size_h_0 = float(line.split('=')[1])
            # pixel size along Y axis
            elif line.startswith("DetectorPixelSizeY"):
                pixel_size_v_0 = float(line.split('=')[1])
            # source to center of rotation distance
            elif line.startswith("SrcToObject"):
                source_x = float(line.split('=')[1])
            # source to detector distance
            elif line.startswith("SrcToDetector"):
                detector_x = float(line.split('=')[1])
            # initial angular position of a rotation stage
            elif line.startswith("InitialAngle"):
                initial_angle = float(line.split('=')[1])
            # angular increment (in degrees)
            elif line.startswith("AngularStep"):
                angular_step = float(line.split('=')[1])

        if self.roi == -1:
            self._roi_par = [(0, pixel_num_v_0), \
                              (0, pixel_num_h_0)]
        else:
            self._roi_par = self.roi.copy()
            if self._roi_par[0] == -1:
                self._roi_par[0] = (0, pixel_num_v_0)
            if self._roi_par[1] == -1:
                self._roi_par[1] = (0, pixel_num_h_0)

        # calculate number of pixels and pixel size
        if (self.binning == [1, 1]):
            pixel_num_v = self._roi_par[0][1] - self._roi_par[0][0]
            pixel_num_h = self._roi_par[1][1] - self._roi_par[1][0]
            pixel_size_v = pixel_size_v_0
            pixel_size_h = pixel_size_h_0
        else:
            pixel_num_v = (self._roi_par[0][1] -
                           self._roi_par[0][0]) // self.binning[0]
            pixel_num_h = (self._roi_par[1][1] -
                           self._roi_par[1][0]) // self.binning[1]
            pixel_size_v = pixel_size_v_0 * self.binning[0]
            pixel_size_h = pixel_size_h_0 * self.binning[1]
        '''
        Parse the angles file .ang or _ctdata.txt file and returns the angles
        as an numpy array. 
        '''
        input_path = os.path.dirname(self.xtek_file)
        angles_ctdata_file = os.path.join(input_path, '_ctdata.txt')
        angles_named_file = os.path.join(input_path,
                                         self._experiment_name + '.ang')
        angles = numpy.zeros(num_projections, dtype='float')

        # look for _ctdata.txt
        if os.path.exists(angles_ctdata_file):
            # read txt file with angles
            with open(angles_ctdata_file) as f:
                content = f.readlines()
            # skip firt three lines
            # read the middle value of 3 values in each line as angles in degrees
            index = 0
            for line in content[3:]:
                angles[index] = float(line.split(' ')[1])
                index += 1
            angles = angles + initial_angle

        # look for ang file
        elif os.path.exists(angles_named_file):
            # read the angles file which is text with first line as header
            with open(angles_named_file) as f:
                content = f.readlines()
            # skip first line
            index = 0
            for line in content[1:]:
                angles[index] = float(line.split(':')[1])
                index += 1
            angles = numpy.flipud(
                angles + initial_angle)  # angles are in the reverse order

        else:  # calculate angles based on xtek file
            angles = initial_angle + angular_step * range(num_projections)

        # fill in metadata
        self._ag = AcquisitionGeometry(geom_type='cone',
                                       dimension='3D',
                                       angles=angles,
                                       pixel_num_h=pixel_num_h,
                                       pixel_size_h=pixel_size_h,
                                       pixel_num_v=pixel_num_v,
                                       pixel_size_v=pixel_size_v,
                                       dist_source_center=source_x,
                                       dist_center_detector=detector_x -
                                       source_x,
                                       channels=1,
                                       angle_unit='degree')
Beispiel #16
0
        igtmp.shape = self.volume_geometry.shape[1:]
        igtmp.dimension_labels = ['horizontal_y', 'horizontal_x']
        igtmp.channels = 1

        agtmp = self.sinogram_geometry.clone()
        agtmp.shape = self.sinogram_geometry.shape[1:]
        agtmp.dimension_labels = ['angle', 'horizontal']
        agtmp.channels = 1

        Atmp = AstraProjectorSimple(igtmp, agtmp, device=self.device)

        return Atmp.norm()


if __name__ == '__main__':

    from ccpi.framework import ImageGeometry, AcquisitionGeometry
    import numpy as np

    N = 30
    angles = np.linspace(0, np.pi, 180)
    ig = ImageGeometry(N, N, channels=5)
    ag = AcquisitionGeometry('parallel',
                             '2D',
                             angles,
                             pixel_num_h=N,
                             channels=5)

    A = AstraProjectorMC(ig, ag, 'gpu')
    print(A.norm())
# set to 0 to simulate a "virtual detector" with same detector pixel size as
# object pixel size).
angles_num = 40
det_num = 400

SourceOrig = 20
OrigDetec = 100

geo_mag = (SourceOrig+OrigDetec)/SourceOrig

det_w = geo_mag*dx*1

if test_case==1:
    angles = np.linspace(0,np.pi,angles_num,endpoint=False)
    ag = AcquisitionGeometry('parallel',
                             '2D',
                             angles,
                             det_num,det_w)
elif test_case==2:
    angles = np.linspace(0,2*np.pi,angles_num,endpoint=False)
    ag = AcquisitionGeometry('cone',
                             '2D',
                             angles,
                             det_num,
                             det_w,
                             dist_source_center=SourceOrig, 
                             dist_center_detector=OrigDetec)
else:
    NotImplemented

# Set up Operator object combining the ImageGeometry and AcquisitionGeometry
# wrapping calls to ASTRA as well as specifying whether to use CPU or GPU.
Beispiel #18
0
    def load_data(self):
        '''
        Parse NEXUS file and returns either ImageData or Acquisition Data 
        depending on file content
        '''

        try:
            with h5py.File(self.nexus_file, 'r') as file:

                if np.string_(file.attrs['creator']) != np.string_(
                        'NEXUSDataWriter.py'):
                    raise Exception(
                        'We can parse only files created by NEXUSDataWriter.py'
                    )

                ds_data = file['entry1/tomo_entry/data/data']
                data = np.array(ds_data, dtype='float32')

                dimension_labels = []

                for i in range(data.ndim):
                    dimension_labels.append(ds_data.attrs['dim{}'.format(i)])

                if ds_data.attrs['data_type'] == 'ImageData':
                    self._geometry = ImageGeometry(
                        voxel_num_x=ds_data.attrs['voxel_num_x'],
                        voxel_num_y=ds_data.attrs['voxel_num_y'],
                        voxel_num_z=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'])

                    return ImageData(array=data,
                                     deep_copy=False,
                                     geometry=self._geometry,
                                     dimension_labels=dimension_labels)

                else:  # AcquisitionData
                    if ds_data.attrs.__contains__('dist_source_center'):
                        dist_source_center = ds_data.attrs[
                            'dist_source_center']
                    else:
                        dist_source_center = None

                    if ds_data.attrs.__contains__('dist_center_detector'):
                        dist_center_detector = ds_data.attrs[
                            'dist_center_detector']
                    else:
                        dist_center_detector = None

                    self._geometry = AcquisitionGeometry(
                        geom_type=ds_data.attrs['geom_type'],
                        dimension=ds_data.attrs['dimension'],
                        dist_source_center=dist_source_center,
                        dist_center_detector=dist_center_detector,
                        pixel_num_h=ds_data.attrs['pixel_num_h'],
                        pixel_size_h=ds_data.attrs['pixel_size_h'],
                        pixel_num_v=ds_data.attrs['pixel_num_v'],
                        pixel_size_v=ds_data.attrs['pixel_size_v'],
                        channels=ds_data.attrs['channels'],
                        angles=np.array(
                            file['entry1/tomo_entry/data/rotation_angle'],
                            dtype='float32'))
                    #angle_unit = file['entry1/tomo_entry/data/rotation_angle'].attrs['units'])

                    return AcquisitionData(array=data,
                                           deep_copy=False,
                                           geometry=self._geometry,
                                           dimension_labels=dimension_labels)

        except:
            print("Error reading nexus file")
            raise
Beispiel #19
0
fig = plt.figure()
ims1 = []
for sl in range(0,np.shape(phantom_2Dt)[0]):    
    im1 = plt.imshow(phantom_2Dt[sl,:,:], animated=True, vmin=0, vmax=1)    
    ims1.append([im1])
ani1 = animation.ArtistAnimation(fig, ims1, interval=500,repeat_delay=10)
plt.show() 

    
ig = ImageGeometry(voxel_num_x = N, voxel_num_y = N, channels = np.shape(phantom_2Dt)[0])
data = ImageData(phantom_2Dt, geometry=ig)

detectors = N
angles = np.linspace(0,np.pi,180)

ag = AcquisitionGeometry('parallel','2D', angles, detectors, channels = np.shape(phantom_2Dt)[0])
Aop = AstraProjectorMC(ig, ag, dev)
sin = Aop.direct(data)

scale = 2
n1 = scale * np.random.poisson(sin.as_array()/scale)
noisy_data = AcquisitionData(n1, ag)

# Regularisation Parameter
alpha = 10

# Create operators
#op1 = Gradient(ig)
op1 = Gradient(ig, correlation='SpaceChannels')
op2 = Aop
Beispiel #20
0
class XTEKReader(object):
    '''
    Reader class for loading XTEK files
    '''
    def __init__(self, xtek_config_filename=None):
        '''
        This takes in the xtek config filename and loads the dataset and the
        required geometry parameters
        '''
        self.projections = None
        self.geometry = {}
        self.filename = xtek_config_filename
        self.load()

    def load(self):
        pixel_num_h = 0
        pixel_num_v = 0
        xpixel_size = 0
        ypixel_size = 0
        source_x = 0
        detector_x = 0
        with open(self.filename) as f:
            content = f.readlines()
        content = [x.strip() for x in content]
        for line in content:
            if line.startswith("SrcToObject"):
                source_x = float(line.split('=')[1])
            elif line.startswith("SrcToDetector"):
                detector_x = float(line.split('=')[1])
            elif line.startswith("DetectorPixelsY"):
                pixel_num_v = int(line.split('=')[1])
                #self.num_of_vertical_pixels = self.calc_v_alighment(self.num_of_vertical_pixels, self.pixels_per_voxel)
            elif line.startswith("DetectorPixelsX"):
                pixel_num_h = int(line.split('=')[1])
            elif line.startswith("DetectorPixelSizeX"):
                xpixel_size = float(line.split('=')[1])
            elif line.startswith("DetectorPixelSizeY"):
                ypixel_size = float(line.split('=')[1])
            elif line.startswith("Projections"):
                self.num_projections = int(line.split('=')[1])
            elif line.startswith("InitialAngle"):
                self.initial_angle = float(line.split('=')[1])
            elif line.startswith("Name"):
                self.experiment_name = line.split('=')[1]
            elif line.startswith("Scattering"):
                self.scattering = float(line.split('=')[1])
            elif line.startswith("WhiteLevel"):
                self.white_level = float(line.split('=')[1])
            elif line.startswith("MaskRadius"):
                self.mask_radius = float(line.split('=')[1])

        #Read Angles
        angles = self.read_angles()
        self.geometry = AcquisitionGeometry(
            'cone',
            '3D',
            angles,
            pixel_num_h,
            xpixel_size,
            pixel_num_v,
            ypixel_size,
            -1 * source_x,
            detector_x - source_x,
        )

    def read_angles(self):
        """
        Read the angles file .ang or _ctdata.txt file and returns the angles
        as an numpy array. 
        """
        input_path = os.path.dirname(self.filename)
        angles_ctdata_file = os.path.join(input_path, '_ctdata.txt')
        angles_named_file = os.path.join(input_path,
                                         self.experiment_name + '.ang')
        angles = np.zeros(self.num_projections, dtype='f')
        #look for _ctdata.txt
        if os.path.exists(angles_ctdata_file):
            #read txt file with angles
            with open(angles_ctdata_file) as f:
                content = f.readlines()
            #skip firt three lines
            #read the middle value of 3 values in each line as angles in degrees
            index = 0
            for line in content[3:]:
                self.angles[index] = float(line.split(' ')[1])
                index += 1
            angles = np.deg2rad(self.angles + self.initial_angle)
        elif os.path.exists(angles_named_file):
            #read the angles file which is text with first line as header
            with open(angles_named_file) as f:
                content = f.readlines()
            #skip first line
            index = 0
            for line in content[1:]:
                angles[index] = float(line.split(':')[1])
                index += 1
            angles = np.flipud(
                angles + self.initial_angle)  #angles are in the reverse order
        else:
            raise RuntimeError("Can't find angles file")
        return angles

    def load_projection(self, dimensions=None):
        '''
        This method reads the projection images from the directory and returns a numpy array
        '''
        if not pilAvailable:
            raise ImportError('Image library pillow is not installed')
        if dimensions != None:
            raise NotImplementedError(
                'Extracting subset of data is not implemented')
        input_path = os.path.dirname(self.filename)
        pixels = np.zeros((self.num_projections, self.geometry.pixel_num_h,
                           self.geometry.pixel_num_v),
                          dtype='float32')
        for i in range(1, self.num_projections + 1):
            im = Image.open(
                os.path.join(input_path,
                             self.experiment_name + "_%04d" % i + ".tif"))
            pixels[i - 1, :, :] = np.fliplr(np.transpose(np.array(
                im)))  ##Not sure this is the correct way to populate the image

        #normalising the data
        #TODO: Move this to a processor
        pixels = pixels - (self.white_level * self.scattering) / 100.0
        pixels[
            pixels <
            0.0] = 0.000001  # all negative values to approximately 0 as the std log of zero and non negative number is not defined
        return pixels

    def get_acquisition_data(self, dimensions=None):
        '''
        This method load the acquisition data and given dimension and returns an AcquisitionData Object
        '''
        data = self.load_projection(dimensions)
        out = self.geometry.allocate()
        out.fill(data)
        return out
Beispiel #21
0
    def get_acquisition_data_subset(self, ymin=None, ymax=None):
        '''
        This method load the acquisition data and given dimension and returns an AcquisitionData Object
        '''
        if not h5pyAvailable:
            raise Exception("Error: h5py is not installed")
        if self.filename is None:
            return
        try:

            with NexusFile(self.filename, 'r') as file:
                try:
                    dims = self.get_projection_dimensions()
                except KeyError:
                    pass
                dims = file[self.data_path].shape
                if ymin is None and ymax is None:

                    try:
                        image_keys = self.get_image_keys()
                        print("image_keys", image_keys)
                        projections = np.array(file[self.data_path])
                        data = projections[image_keys == 0]
                    except KeyError as ke:
                        print(ke)
                        data = np.array(file[self.data_path])

                else:
                    image_keys = self.get_image_keys()
                    print("image_keys", image_keys)
                    projections = np.array(
                        file[self.data_path])[image_keys == 0]
                    if ymin is None:
                        ymin = 0
                        if ymax > dims[1]:
                            raise ValueError('ymax out of range')
                        data = projections[:, :ymax, :]
                    elif ymax is None:
                        ymax = dims[1]
                        if ymin < 0:
                            raise ValueError('ymin out of range')
                        data = projections[:, ymin:, :]
                    else:
                        if ymax > dims[1]:
                            raise ValueError('ymax out of range')
                        if ymin < 0:
                            raise ValueError('ymin out of range')

                        data = projections[:, ymin:ymax, :]

        except:
            print("Error reading nexus file")
            raise

        try:
            angles = self.get_projection_angles()
        except KeyError as ke:
            n = data.shape[0]
            angles = np.linspace(0, n, n + 1, dtype=np.float32)

        if ymax - ymin > 1:

            geometry = AcquisitionGeometry(
                'parallel',
                '3D',
                angles,
                pixel_num_h=dims[2],
                pixel_size_h=1,
                pixel_num_v=ymax - ymin,
                pixel_size_v=1,
                dist_source_center=None,
                dist_center_detector=None,
                channels=1,
                dimension_labels=['angle', 'vertical', 'horizontal'])
            out = geometry.allocate()
            out.fill(data)
            return out
        elif ymax - ymin == 1:
            geometry = AcquisitionGeometry(
                'parallel',
                '2D',
                angles,
                pixel_num_h=dims[2],
                pixel_size_h=1,
                dist_source_center=None,
                dist_center_detector=None,
                channels=1,
                dimension_labels=['angle', 'horizontal'])
            out = geometry.allocate()
            out.fill(data.squeeze())
            return out
Beispiel #22
0
    def calculate_norm(self):

        return self.A3D.norm()


if __name__ == '__main__':

    from ccpi.framework import ImageGeometry, AcquisitionGeometry

    N = 30
    channels = 5
    angles = np.linspace(0, np.pi, 180)
    ig = ImageGeometry(N, N, N, channels=channels)
    ag = AcquisitionGeometry('parallel',
                             '3D',
                             angles,
                             pixel_num_h=N,
                             pixel_num_v=5,
                             channels=channels)

    A3DMC = AstraProjector3DMC(ig, ag)
    z = A3DMC.norm()

#    igtmp3D = A3DMC.volume_geometry.clone()
#    igtmp3D.channels = 1
#    igtmp3D.shape = A3DMC.volume_geometry.shape[1:]
#    igtmp3D.dimension_labels = ['vertical', 'horizontal_y', 'horizontal_x']
#
#    agtmp3D = A3DMC.sinogram_geometry.clone()
#    agtmp3D.channels = 1
#    agtmp3D.shape = A3DMC.sinogram_geometry.shape[1:]
#    agtmp3D.dimension_labels = ['vertical', 'angle', 'horizontal']
Beispiel #23
0
    def __init__(self,
                 volume_geometry,
                 sinogram_geometry,
                 device='cpu',
                 filter_type='ram-lak',
                 **kwargs):

        if sinogram_geometry.dimension == '3D':

            # For 3D FBP and parallel goemetry, we perform 2D FBP per slice
            # Therofore, we need vol_geom2D, porj_geom2D attributes to setup in the DataProcessor.
            # There are both CPU/GPU options for this case

            if sinogram_geometry.geom_type == 'parallel':

                # By default, we select GPU device
                super(FBP, self).__init__(volume_geometry=volume_geometry,
                                          sinogram_geometry=sinogram_geometry,
                                          device='gpu',
                                          proj_id=None,
                                          vol_geom2D=None,
                                          proj_geom2D=None,
                                          filter_type=filter_type)

                # we need a 2D image and acquisition geometry
                ig2D = ImageGeometry(
                    voxel_num_x=self.volume_geometry.voxel_num_x,
                    voxel_num_y=self.volume_geometry.voxel_num_y,
                    voxel_size_x=self.volume_geometry.voxel_size_x,
                    voxel_size_y=self.volume_geometry.voxel_size_y)

                ag2D = AcquisitionGeometry(
                    geom_type=self.sinogram_geometry.geom_type,
                    dimension='2D',
                    angles=self.sinogram_geometry.angles,
                    pixel_num_h=self.sinogram_geometry.pixel_num_h,
                    pixel_size_h=self.sinogram_geometry.pixel_size_h)

                # Convert to Astra Geometries
                self.vol_geom2D, self.proj_geom2D = convert_geometry_to_astra(
                    ig2D, ag2D)

                if self.device == 'gpu':
                    self.set_projector(
                        astra.create_projector('cuda', self.proj_geom2D,
                                               self.vol_geom2D))
                else:
                    self.set_projector(
                        astra.create_projector('line', self.proj_geom2D,
                                               self.vol_geom2D))

            elif sinogram_geometry.geom_type == 'cone':

                # For 3D cone we do not need  ASTRA proj_id
                super(FBP, self).__init__(volume_geometry=volume_geometry,
                                          sinogram_geometry=sinogram_geometry,
                                          device='gpu',
                                          filter_type='ram-lak')

                #Raise an error if the user select a filter other than ram-lak
                if self.filter_type != 'ram-lak':
                    raise NotImplementedError(
                        'Currently in astra, FDK has only ram-lak available')
        else:

            # Setup for 2D case
            super(FBP, self).__init__(volume_geometry=volume_geometry,
                                      sinogram_geometry=sinogram_geometry,
                                      device=device,
                                      proj_id=None,
                                      filter_type=filter_type)

            # Raise an error if the user select a filter other than ram-lak, for 2D case
            if self.filter_type != 'ram-lak' and self.device == 'cpu':
                raise NotImplementedError(
                    'Currently in astra, 2D FBP is using only the ram-lak filter, switch to gpu for other filters'
                )

            if (self.sinogram_geometry.geom_type == 'cone' and self.device
                    == 'gpu') and self.sinogram_geometry.channels >= 1:
                warnings.warn(
                    "For FanFlat geometry there is a mismatch between CPU & GPU filtered back projection. Currently, only CPU case provides a reasonable result."
                )

            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, self.sinogram_geometry)

            # Here we define proj_id that will be used for ASTRA
            # ASTRA projector, to be stored
            if self.device == 'cpu':

                # Note that 'line' only one option
                if self.sinogram_geometry.geom_type == 'parallel':
                    self.set_projector(
                        astra.create_projector('line', proj_geom, vol_geom))

                elif self.sinogram_geometry.geom_type == 'cone':
                    self.set_projector(
                        astra.create_projector('line_fanflat', proj_geom,
                                               vol_geom))

                else:
                    NotImplemented

            elif self.device == 'gpu':

                self.set_projector(
                    astra.create_projector('cuda', proj_geom, vol_geom))

            else:
                NotImplemented
Beispiel #24
0
    def domain_geometry(self):
        return self.volume_geometry

    def range_geometry(self):
        return self.sinogram_geometry


if __name__ == '__main__':

    from ccpi.framework import ImageGeometry, AcquisitionGeometry
    import numpy as np

    N = 30
    angles = np.linspace(0, np.pi, 180)
    ig = ImageGeometry(N, N)
    ag = AcquisitionGeometry('parallel', '2D', angles, pixel_num_h=N)
    A = ProjectionOperator(ig, ag, 'cpu')
    print(A.norm())

    ig = ImageGeometry(N, N, N)
    ag = AcquisitionGeometry(
        'parallel',
        '3D',
        angles,
        pixel_num_v=N,
        pixel_num_h=N,
        dimension_labels=['vertical', 'angle', 'horizontal'])
    A = ProjectionOperator(ig, ag, 'gpu')
    print(A.norm())

    ig = ImageGeometry(N, N, channels=2)
Beispiel #25
0
    def get_acquisition_data_batch(self, bmin=None, bmax=None):
        if not h5pyAvailable:
            raise Exception("Error: h5py is not installed")
        if self.filename is None:
            return
        try:

            with NexusFile(self.filename, 'r') as file:
                try:
                    dims = self.get_projection_dimensions()
                except KeyError:
                    dims = file[self.data_path].shape
                if bmin is None or bmax is None:
                    raise ValueError(
                        'get_acquisition_data_batch: please specify fastest index batch limits'
                    )

                if bmin >= 0 and bmin < bmax and bmax <= dims[0]:
                    data = np.array(file[self.data_path][bmin:bmax])
                else:
                    raise ValueError(
                        'get_acquisition_data_batch: bmin {0}>0 bmax {1}<{2}'.
                        format(bmin, bmax, dims[0]))

        except:
            print("Error reading nexus file")
            raise

        try:
            angles = self.get_projection_angles()[bmin:bmax]
        except KeyError as ke:
            n = data.shape[0]
            angles = np.linspace(0, n, n + 1, dtype=np.float32)[bmin:bmax]

        if bmax - bmin > 1:

            geometry = AcquisitionGeometry(
                'parallel',
                '3D',
                angles,
                pixel_num_h=dims[2],
                pixel_size_h=1,
                pixel_num_v=bmax - bmin,
                pixel_size_v=1,
                dist_source_center=None,
                dist_center_detector=None,
                channels=1,
                dimension_labels=['angle', 'vertical', 'horizontal'])
            out = geometry.allocate()
            out.fill(data)
            return out

        elif bmax - bmin == 1:
            geometry = AcquisitionGeometry(
                'parallel',
                '2D',
                angles,
                pixel_num_h=dims[2],
                pixel_size_h=1,
                dist_source_center=None,
                dist_center_detector=None,
                channels=1,
                dimension_labels=['angle', 'horizontal'])
            out = geometry.allocate()
            out.fill(data.squeeze())
            return out
Beispiel #26
0
            nonzero] = ProjAngleChannels[ll, i, nonzero] / flat1[nonzero]

eqzero = ProjAngleChannels == 0
ProjAngleChannels[eqzero] = 1
ProjAngleChannels_NormLog = -np.log(
    ProjAngleChannels)  # normalised and neg-log data

# extact sinogram over energy channels
selectedVertical_slice = 256
sino_all_channels = ProjAngleChannels_NormLog[:, :, :, selectedVertical_slice]
# Set angles to use
angles = np.linspace(-np.pi, np.pi, totalAngles, endpoint=False)

# set the geometry
ig = ImageGeometry(n, n)
ag = AcquisitionGeometry('parallel', '2D', angles, n, 1)
Aop = AstraProjectorSimple(ig, ag, 'gpu')

# loop to reconstruct energy channels
REC_chan = np.zeros((totChannels, n, n), 'float32')
for i in range(0, totChannels, 1):
    sino_channel = sino_all_channels[:,
                                     i, :]  # extract a sinogram for i-th channel

    print("Initial guess")
    x_init = ImageData(geometry=ig)

    # Create least squares object instance with projector and data.
    print("Create least squares object instance with projector and data.")
    f = Norm2sq(Aop, DataContainer(sino_channel), c=0.5)
# Set angles to use
#angles = numpy.linspace(-numpy.pi,numpy.pi,num_angles,endpoint=False)
angles = np.linspace(-180, 180, num_angles, endpoint=False) * np.pi / 180

# Define full 3D acquisition geometry and data container.
# NOTE: Default order of labels of the acquisition geometry is
# [channel, angle, vertical, horizontal]
# Here, we have data with an order of ['channel', vertical, angle, horizontal]
# hence we use the dimension_labels as a last argument

ag = AcquisitionGeometry(
    'cone',
    '3D',
    angles,
    pixel_num_h=num_pixels_h,
    pixel_size_h=0.25,
    pixel_num_v=num_pixels_v,
    pixel_size_v=0.25,
    dist_source_center=233.0,
    dist_center_detector=245.0,
    channels=num_channels,
    dimension_labels=['channel', 'vertical', 'angle', 'horizontal'])

# AcquisitionData 3D + channels
data = AcquisitionData(
    X, ag, dimension_labels=['channel', 'vertical', 'angle', 'horizontal'])

# First need the geometric magnification to scale the voxel size relative
# to the detector pixel size.
# magnification factor  =  250/1.76
# dist_source , dist center do not matter
Beispiel #28
0
class TestSubset(unittest.TestCase):
    def setUp(self):
        self.ig = ImageGeometry(1, 2, 3, channels=4)
        angles = numpy.asarray([90., 0., -90.], dtype=numpy.float32)

        self.ag = AcquisitionGeometry('cone',
                                      'edo',
                                      pixel_num_h=20,
                                      pixel_num_v=2,
                                      angles=angles,
                                      dist_source_center=312.2,
                                      dist_center_detector=123.,
                                      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()
        default_dimension_labels = [
            ImageGeometry.CHANNEL, ImageGeometry.VERTICAL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.HORIZONTAL_X
        ]
        self.assertTrue(data.shape == (4, 3, 2, 1))

    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 == (1, 3, 2, 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()
        default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.ANGLE,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.HORIZONTAL
        ]

        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)
        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])
Beispiel #29
0
from ccpi.optimisation.functions import ZeroFunction, BlockFunction, L2NormSquared
from ccpi.astra.operators import AstraProjectorSimple
from ccpi.framework import TestData
import os, sys

loader = TestData(data_dir=os.path.join(sys.prefix, 'share', 'ccpi'))

# Create Ground truth phantom and Sinogram
N = 150
M = 150
data = loader.load(TestData.SIMPLE_PHANTOM_2D, size=(N, M), scale=(0, 1))
ig = data.geometry

detectors = N
angles = np.linspace(0, np.pi, N, dtype=np.float32)
ag = AcquisitionGeometry('parallel', '2D', angles, detectors)

device = input('Available device: GPU==1 / CPU==0 ')
if device == '1':
    dev = 'gpu'
else:
    dev = 'cpu'

Aop = AstraProjectorSimple(ig, ag, dev)
sin = Aop.direct(data)

noisy_data = AcquisitionData(sin.as_array() + np.random.normal(0, 3, ig.shape))

# Setup and run the CGLS algorithm
alpha = 50
Grad = Gradient(ig)
eqzero = data == 0
data[eqzero] = 1

data_rel = -numpy.log(data)

# Permute order to get: angles, vertical, horizontal, as default in framework.
data_rel = numpy.transpose(data_rel,(0,2,1))

# Set angles to use
angles = numpy.linspace(-numpy.pi,numpy.pi,num_angles,endpoint=False)

# Create 3D acquisition geometry and acquisition data
ag = AcquisitionGeometry('parallel',
                         '3D',
                         angles,
                         pixel_num_h=imsize,
                         pixel_num_v=imsize)
b = AcquisitionData(data_rel, geometry=ag)

# Reduce to single (noncentral) slice by extracting relevant parameters from data and its
# geometry. Perhaps create function to extract central slice automatically?
b2d = b.subset(vertical=128)
ag2d = AcquisitionGeometry('parallel',
                         '2D',
                         ag.angles,
                         pixel_num_h=ag.pixel_num_h)
b2d.geometry = ag2d

# Create 2D image geometry
ig2d = ImageGeometry(voxel_num_x=ag2d.pixel_num_h,