Exemple #1
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)
Exemple #2
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],
                              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))
Exemple #3
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(0)
        shape = sino.shape
        print("shape", shape)
        self.assertAlmostEqual(0., sino.as_array()[0][0][0][0])
        self.assertAlmostEqual(
            0.,
            sino.as_array()[shape[0] - 1][shape[1] - 1][shape[2] -
                                                        1][shape[3] - 1])

        sino = ageometry.allocate(1)
        self.assertEqual(1, sino.as_array()[0][0][0][0])
        self.assertEqual(
            1,
            sino.as_array()[shape[0] - 1][shape[1] - 1][shape[2] -
                                                        1][shape[3] - 1])
        print(sino.dimension_labels, sino.shape, ageometry)

        default_order = ['channel', 'angle', 'vertical', 'horizontal']
        self.assertEqual(default_order[0], sino.dimension_labels[0])
        self.assertEqual(default_order[1], sino.dimension_labels[1])
        self.assertEqual(default_order[2], sino.dimension_labels[2])
        self.assertEqual(default_order[3], sino.dimension_labels[3])
        order = ['vertical', 'horizontal', 'channel', 'angle']
        ageometry.set_labels(order)
        sino = ageometry.allocate(0)
        print(sino.dimension_labels, sino.shape, ageometry)
        self.assertEqual(order[0], sino.dimension_labels[0])
        self.assertEqual(order[1], sino.dimension_labels[1])
        self.assertEqual(order[2], sino.dimension_labels[2])
        self.assertEqual(order[2], sino.dimension_labels[2])

        try:
            z = AcquisitionData(numpy.random.randint(10, size=(2, 3)),
                                geometry=ageometry)
            self.assertTrue(False)
        except ValueError as ve:
            print(ve)
            self.assertTrue(True)
Exemple #4
0
 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)
Exemple #5
0
    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 )
Exemple #6
0
class TXRMDataReader(object):
    
    def __init__(self, 
                 **kwargs):
        '''
        Constructor
        
        Input:
            
            txrm_file       full path to .txrm file
                    
        '''
        
        self.txrm_file = kwargs.get('file_name', None)
        
        if self.txrm_file is not None:
            self.set_up(file_name = self.txrm_file)
        self._metadata = None
            
    def set_up(self, 
               file_name = None,
               angle_unit = AcquisitionGeometry.DEGREE):
        
        self.txrm_file = os.path.abspath(file_name)
        
        if self.txrm_file == None:
            raise ValueError('Path to txrm file is required.')
        
        # check if txrm file exists
        if not(os.path.isfile(self.txrm_file)):
            raise FileNotFoundError('{}'.format(self.txrm_file))  
        possible_units = [AcquisitionGeometry.DEGREE, AcquisitionGeometry.RADIAN]
        if angle_unit in possible_units:
            self.angle_unit = angle_unit
        else:
            raise ValueError('angle_unit should be one of {}'.format(possible_units))

    def get_geometry(self):
        '''
        Return AcquisitionGeometry object
        '''
        
        return self._ag
        
    def read(self):
        '''
        Reads projections and return AcquisitionData container
        '''
        # the import will raise an ImportError if dxchange is not installed
        import dxchange
        # Load projections and most metadata
        data, metadata = dxchange.read_txrm(self.txrm_file)
        number_of_images = data.shape[0]
        
        # Read source to center and detector to center distances
        with olefile.OleFileIO(self.txrm_file) as ole:
            StoRADistance = dxchange.reader._read_ole_arr(ole, \
                    'ImageInfo/StoRADistance', "<{0}f".format(number_of_images))
            DtoRADistance = dxchange.reader._read_ole_arr(ole, \
                    'ImageInfo/DtoRADistance', "<{0}f".format(number_of_images))
            
        dist_source_center   = np.abs( StoRADistance[0] )
        dist_center_detector = np.abs( DtoRADistance[0] )
        
        # normalise data by flatfield
        data = data / metadata['reference']
        
        # circularly shift data by rounded x and y shifts
        for k in range(number_of_images):
            data[k,:,:] = np.roll(data[k,:,:], \
                (int(metadata['x-shifts'][k]),int(metadata['y-shifts'][k])), \
                axis=(1,0))
        
        # Pixelsize loaded in metadata is really the voxel size in um.
        # We can compute the effective detector pixel size as the geometric
        # magnification times the voxel size.
        d_pixel_size = ((dist_source_center+dist_center_detector)/dist_source_center)*metadata['pixel_size']
        
        # convert angles to requested unit measure, Zeiss stores in radians
        if self.angle_unit == AcquisitionGeometry.DEGREE:
            angles = np.degrees(metadata['thetas'])
        else:
            angles = np.asarray(metadata['thetas'])

        self._ag = AcquisitionGeometry(geom_type = 'cone', 
                                       dimension = '3D', 
                                       angles = angles, 
                                       pixel_num_h = metadata['image_width'], 
                                       pixel_size_h = d_pixel_size/1000, 
                                       pixel_num_v = metadata['image_height'], 
                                       pixel_size_v = d_pixel_size/1000, 
                                       dist_source_center =  dist_source_center, 
                                       dist_center_detector = dist_center_detector, 
                                       channels = 1,
                                       angle_unit = self.angle_unit,
                                       dimension_labels = ['angle', \
                                                           'vertical', \
                                                           'horizontal'])
        acq_data = self._ag.allocate(None)
        acq_data.fill(data)
        self._metadata = metadata
        return acq_data
    def load_projections(self):
        '''alias of read for backward compatibility'''
        return self.read()
        
    def get_metadata(self):
        '''return the metadata of the loaded file'''
        return self._metadata
Exemple #7
0
    def test_SPDHG_vs_PDHG_implicit(self):

        data = dataexample.SIMPLE_PHANTOM_2D.get(size=(128, 128))

        ig = data.geometry
        ig.voxel_size_x = 0.1
        ig.voxel_size_y = 0.1

        detectors = ig.shape[0]
        angles = np.linspace(0, np.pi, 90)
        ag = AcquisitionGeometry('parallel',
                                 '2D',
                                 angles,
                                 detectors,
                                 pixel_size_h=0.1,
                                 angle_unit='radian')
        # Select device
        dev = 'cpu'

        Aop = AstraProjectorSimple(ig, ag, dev)

        sin = Aop.direct(data)
        # Create noisy data. Apply Gaussian noise
        noises = ['gaussian', 'poisson']
        noise = noises[1]
        noisy_data = ag.allocate()
        if noise == 'poisson':
            np.random.seed(10)
            scale = 20
            eta = 0
            noisy_data.fill(
                np.random.poisson(scale * (eta + sin.as_array())) / scale)
        elif noise == 'gaussian':
            np.random.seed(10)
            n1 = np.random.normal(0, 0.1, size=ag.shape)
            noisy_data.fill(n1 + sin.as_array())

        else:
            raise ValueError('Unsupported Noise ', noise)

        # Create BlockOperator
        operator = Aop
        f = KullbackLeibler(b=noisy_data)
        alpha = 0.005
        g = alpha * TotalVariation(50, 1e-4, lower=0)
        normK = operator.norm()

        #% 'implicit' PDHG, preconditioned step-sizes
        tau_tmp = 1.
        sigma_tmp = 1.
        tau = sigma_tmp / operator.adjoint(
            tau_tmp * operator.range_geometry().allocate(1.))
        sigma = tau_tmp / operator.direct(
            sigma_tmp * operator.domain_geometry().allocate(1.))
        #    initial = operator.domain_geometry().allocate()

        #    # Setup and run the PDHG algorithm
        pdhg = PDHG(f=f,
                    g=g,
                    operator=operator,
                    tau=tau,
                    sigma=sigma,
                    max_iteration=1000,
                    update_objective_interval=500)
        pdhg.run(verbose=0)

        subsets = 10
        size_of_subsets = int(len(angles) / subsets)
        # take angles and create uniform subsets in uniform+sequential setting
        list_angles = [
            angles[i:i + size_of_subsets]
            for i in range(0, len(angles), size_of_subsets)
        ]
        # create acquisitioin geometries for each the interval of splitting angles
        list_geoms = [
            AcquisitionGeometry('parallel',
                                '2D',
                                list_angles[i],
                                detectors,
                                pixel_size_h=0.1,
                                angle_unit='radian')
            for i in range(len(list_angles))
        ]
        # create with operators as many as the subsets
        A = BlockOperator(*[
            AstraProjectorSimple(ig, list_geoms[i], dev)
            for i in range(subsets)
        ])
        ## number of subsets
        #(sub2ind, ind2sub) = divide_1Darray_equally(range(len(A)), subsets)
        #
        ## acquisisiton data
        AD_list = []
        for sub_num in range(subsets):
            for i in range(0, len(angles), size_of_subsets):
                arr = noisy_data.as_array()[i:i + size_of_subsets, :]
                AD_list.append(
                    AcquisitionData(arr, geometry=list_geoms[sub_num]))

        g = BlockDataContainer(*AD_list)

        ## block function
        F = BlockFunction(*[KullbackLeibler(b=g[i]) for i in range(subsets)])
        G = alpha * TotalVariation(50, 1e-4, lower=0)

        prob = [1 / len(A)] * len(A)
        spdhg = SPDHG(f=F,
                      g=G,
                      operator=A,
                      max_iteration=1000,
                      update_objective_interval=200,
                      prob=prob)
        spdhg.run(1000, verbose=0)
        from cil.utilities.quality_measures import mae, mse, psnr
        qm = (mae(spdhg.get_output(),
                  pdhg.get_output()), mse(spdhg.get_output(),
                                          pdhg.get_output()),
              psnr(spdhg.get_output(), pdhg.get_output()))
        if debug_print:
            print("Quality measures", qm)

        np.testing.assert_almost_equal(mae(spdhg.get_output(),
                                           pdhg.get_output()),
                                       0.000335,
                                       decimal=3)
        np.testing.assert_almost_equal(mse(spdhg.get_output(),
                                           pdhg.get_output()),
                                       5.51141e-06,
                                       decimal=3)
        else:
            out.fill(self.fp.get_output())

    def adjoint(self, DATA, out=None):
        self.bp.set_input(DATA)

        if out is None:
            return self.bp.get_output()
        else:
            out.fill(self.bp.get_output())


if __name__ == '__main__':

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

    A = AstraProjector3DSimple(ig, ag)
    print(A.norm())

    x = ig.allocate('random_int')
    sin = A.direct(x)

    y = ag.allocate('random_int')
    im = A.adjoint(y)
Exemple #9
0
class TestSubset(unittest.TestCase):
    def setUp(self):
        self.ig = ImageGeometry(2, 3, 4, channels=5)
        angles = numpy.asarray([90., 0., -90.], dtype=numpy.float32)

        self.ag = AcquisitionGeometry('parallel',
                                      'edo',
                                      pixel_num_h=20,
                                      pixel_num_v=2,
                                      angles=angles,
                                      dist_source_center=312.2,
                                      dist_center_detector=123.,
                                      channels=4)

        self.ag_cone = AcquisitionGeometry.create_Cone3D([0,-500,0],[0,500,0])\
                                     .set_panel((2,20))\
                                     .set_angles(self.ag.angles)\
                                     .set_channels(4)

    def test_ImageDataAllocate1a(self):
        data = self.ig.allocate()
        default_dimension_labels = [
            ImageGeometry.CHANNEL, ImageGeometry.VERTICAL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.HORIZONTAL_X
        ]
        self.assertTrue(
            default_dimension_labels == list(data.dimension_labels.values()))

    def test_ImageDataAllocate1b(self):
        data = self.ig.allocate()
        self.assertTrue(data.shape == (5, 4, 3, 2))

    def test_ImageDataAllocate2a(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.VERTICAL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.CHANNEL
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        self.assertTrue(non_default_dimension_labels == list(
            data.dimension_labels.values()))

    def test_ImageDataAllocate2b(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.VERTICAL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.CHANNEL
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        self.assertTrue(data.shape == (2, 4, 3, 5))

    def test_ImageDataSubset1a(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        sub = data.subset(horizontal_y=1)
        self.assertTrue(sub.shape == (2, 5, 4))

    def test_ImageDataSubset2a(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        sub = data.subset(horizontal_x=1)
        self.assertTrue(sub.shape == (5, 3, 4))

    def test_ImageDataSubset3a(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        sub = data.subset(channel=1)
        self.assertTrue(sub.shape == (2, 3, 4))

    def test_ImageDataSubset4a(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        sub = data.subset(vertical=1)
        self.assertTrue(sub.shape == (2, 5, 3))

    def test_ImageDataSubset5a(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.HORIZONTAL_Y
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        sub = data.subset(horizontal_y=1)
        self.assertTrue(sub.shape == (2, ))

    def test_ImageDataSubset1b(self):
        non_default_dimension_labels = [
            ImageGeometry.HORIZONTAL_X, ImageGeometry.CHANNEL,
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL
        ]
        data = self.ig.allocate(dimension_labels=non_default_dimension_labels)
        new_dimension_labels = [
            ImageGeometry.HORIZONTAL_Y, ImageGeometry.CHANNEL,
            ImageGeometry.VERTICAL, ImageGeometry.HORIZONTAL_X
        ]
        sub = data.subset(dimensions=new_dimension_labels)
        self.assertTrue(sub.shape == (3, 5, 4, 2))

    def test_ImageDataSubset1c(self):
        data = self.ig.allocate()
        sub = data.subset(channel=0, horizontal_x=0, horizontal_y=0)
        self.assertTrue(sub.shape == (4, ))

    def test_AcquisitionDataAllocate1a(self):
        data = self.ag.allocate()
        default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.ANGLE,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.HORIZONTAL
        ]
        self.assertTrue(
            default_dimension_labels == list(data.dimension_labels.values()))

    def test_AcquisitionDataAllocate1b(self):
        data = self.ag.allocate()
        self.assertTrue(data.shape == (4, 3, 2, 20))

    def test_AcquisitionDataAllocate2a(self):
        non_default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE
        ]
        data = self.ag.allocate(dimension_labels=non_default_dimension_labels)

        self.assertTrue(non_default_dimension_labels == list(
            data.dimension_labels.values()))

    def test_AcquisitionDataAllocate2b(self):
        non_default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE
        ]
        data = self.ag.allocate(dimension_labels=non_default_dimension_labels)
        self.assertTrue(data.shape == (4, 20, 2, 3))

    def test_AcquisitionDataSubset1a(self):
        non_default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE
        ]
        data = self.ag.allocate(dimension_labels=non_default_dimension_labels)
        #self.assertTrue( data.shape == (4,20,2,3))
        sub = data.subset(vertical=0)
        self.assertTrue(sub.shape == (4, 20, 3))

    def test_AcquisitionDataSubset1b(self):
        non_default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE
        ]
        data = self.ag.allocate(dimension_labels=non_default_dimension_labels)
        #self.assertTrue( data.shape == (4,20,2,3))
        sub = data.subset(channel=0)
        self.assertTrue(sub.shape == (20, 2, 3))

    def test_AcquisitionDataSubset1c(self):
        non_default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE
        ]
        data = self.ag.allocate(dimension_labels=non_default_dimension_labels)
        #self.assertTrue( data.shape == (4,20,2,3))
        sub = data.subset(horizontal=0, force=True)
        self.assertTrue(sub.shape == (4, 2, 3))

    def test_AcquisitionDataSubset1d(self):
        non_default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE
        ]
        data = self.ag.allocate(dimension_labels=non_default_dimension_labels)
        #self.assertTrue( data.shape == (4,20,2,3))
        sliceme = 1
        sub = data.subset(angle=sliceme)
        #print (sub.shape  , sub.dimension_labels)
        self.assertTrue(sub.shape == (4, 20, 2))
        self.assertTrue(
            sub.geometry.angles[0] == data.geometry.angles[sliceme])

    def test_AcquisitionDataSubset1e(self):
        non_default_dimension_labels = [
            AcquisitionGeometry.CHANNEL, AcquisitionGeometry.HORIZONTAL,
            AcquisitionGeometry.VERTICAL, AcquisitionGeometry.ANGLE
        ]
        data = self.ag.allocate(dimension_labels=non_default_dimension_labels)
        #self.assertTrue( data.shape == (4,20,2,3))
        sliceme = 1
        sub = data.subset(angle=sliceme)
        self.assertTrue(
            sub.geometry.angles[0] == data.geometry.angles[sliceme])

    def test_AcquisitionDataSubset1f(self):

        data = self.ag.allocate()
        #self.assertTrue( data.shape == (4,20,2,3))
        sliceme = 1
        sub = data.subset(angle=sliceme)
        self.assertTrue(
            sub.geometry.angles[0] == data.geometry.angles[sliceme])

    def test_AcquisitionDataSubset1g(self):

        data = self.ag_cone.allocate()
        sliceme = 1
        sub = data.subset(angle=sliceme)
        self.assertTrue(
            sub.geometry.angles[0] == data.geometry.angles[sliceme])

    def test_AcquisitionDataSubset1h(self):

        data = self.ag_cone.allocate()
        sub = data.subset(vertical='centre')
        self.assertTrue(sub.geometry.shape == (4, 3, 2))

    def test_AcquisitionDataSubset1i(self):

        data = self.ag_cone.allocate()
        sliceme = 1
        sub = data.subset(vertical=sliceme, force=True)
        self.assertTrue(sub.shape == (4, 3, 2))

    def test_AcquisitionDataSubset1j(self):

        data = self.ag.allocate()
        sub = data.subset(angle=0)
        sub = sub.subset(vertical=0)
        sub = sub.subset(horizontal=0, force=True)

        self.assertTrue(sub.shape == (4, ))