# Copyright 2018 United Kingdom Research and Innovation# Copyright 2018 The University of Manchester## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.## Authors:# CIL Developers, listed at: https://github.com/TomographicImaging/CIL/blob/master/NOTICE.txtimportnumpyfrom.labelsimportAcquisitionDimension,Backendfrom.data_containerimportDataContainerfrom.partitionerimportPartitioner
[docs]classAcquisitionData(DataContainer,Partitioner):'''DataContainer for holding 2D or 3D sinogram'''__container_priority__=1@propertydefgeometry(self):returnself._geometry@geometry.setterdefgeometry(self,val):self._geometry=val@propertydefdimension_labels(self):returnself.geometry.dimension_labels@dimension_labels.setterdefdimension_labels(self,val):ifvalisnotNone:raiseValueError("Unable to set the dimension_labels directly. Use geometry.set_labels() instead")def__init__(self,array=None,deep_copy=True,geometry=None,**kwargs):dtype=kwargs.get('dtype',numpy.float32)ifgeometryisNone:raiseAttributeError("AcquisitionData requires a geometry")labels=kwargs.get('dimension_labels',None)iflabelsisnotNoneandlabels!=geometry.dimension_labels:raiseValueError("Deprecated: 'dimension_labels' cannot be set with 'allocate()'. Use 'geometry.set_labels()' to modify the geometry before using allocate.")ifarrayisNone:array=numpy.empty(geometry.shape,dtype=dtype)elifissubclass(type(array),DataContainer):array=array.as_array()elifissubclass(type(array),numpy.ndarray):# remove singleton dimensionsarray=numpy.squeeze(array)else:raiseTypeError('array must be a CIL type DataContainer or numpy.ndarray got {}'.format(type(array)))ifarray.shape!=geometry.shape:raiseValueError('Shape mismatch got {} expected {}'.format(array.shape,geometry.shape))super(AcquisitionData,self).__init__(array,deep_copy,geometry=geometry,**kwargs)def__eq__(self,other):''' Check if two AcquisitionData objects are equal. This is done by checking if the geometry, data and dtype are equal. Also, if the other object is a numpy.ndarray, it will check if the data and dtype are equal. Parameters ---------- other: AcquisitionData or numpy.ndarray The object to compare with. Returns ------- bool True if the two objects are equal, False otherwise. '''ifisinstance(other,AcquisitionData):ifnumpy.array_equal(self.as_array(),other.as_array()) \
andself.geometry==other.geometry \
andself.dtype==other.dtype:returnTrueelifnumpy.array_equal(self.as_array(),other)andself.dtype==other.dtype:returnTrueelse:returnFalse
[docs]defget_slice(self,channel=None,angle=None,vertical=None,horizontal=None,force=False):'''Returns a new dataset of a single slice in the requested direction.'''try:geometry_new=self.geometry.get_slice(channel=channel,angle=angle,vertical=vertical,horizontal=horizontal)exceptValueError:ifforce:geometry_new=Noneelse:raiseValueError("Unable to return slice of requested AcquisitionData. Use 'force=True' to return DataContainer instead.")#get new data#if vertical = 'centre' slice convert to index and subset, this will interpolate 2 rows to get the center slice valueifvertical=='centre':dim=self.geometry.dimension_labels.index('vertical')centre_slice_pos=(self.geometry.shape[dim]-1)/2.ind0=int(numpy.floor(centre_slice_pos))w2=centre_slice_pos-ind0out=DataContainer.get_slice(self,channel=channel,angle=angle,vertical=ind0,horizontal=horizontal)ifw2>0:out2=DataContainer.get_slice(self,channel=channel,angle=angle,vertical=ind0+1,horizontal=horizontal)out=out*(1-w2)+out2*w2else:out=DataContainer.get_slice(self,channel=channel,angle=angle,vertical=vertical,horizontal=horizontal)iflen(out.shape)==1orgeometry_newisNone:returnoutelse:returnAcquisitionData(out.array,deep_copy=False,geometry=geometry_new,suppress_warning=True)
[docs]defreorder(self,order):''' Reorders the data in memory as requested. This is an in-place operation. Parameters ---------- order: list or str Ordered list of labels from self.dimension_labels, or string 'astra' or 'tigre'. '''iforderinBackend:order=AcquisitionDimension.get_order_for_engine(order,self.geometry)super().reorder(order)