Source code for cil.processors.TransmissionAbsorptionConverter
# Copyright 2021 United Kingdom Research and Innovation# Copyright 2021 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.txtfromcil.frameworkimportDataProcessor,AcquisitionData,ImageData,DataContainerimportloggingimportnumpyimportnumbafromcil.utilitiesimportmultiprocessingascil_mplog=logging.getLogger(__name__)
[docs]classTransmissionAbsorptionConverter(DataProcessor):r'''Processor to convert from transmission measurements to absorption based on the Beer-Lambert law, by: - dividing by white_level, - clipping data to min_intensity (any values below min intensity are set to min_intensity) - taking the logarithm and multiplying by minus 1. If the data contains zero or negative values, inf or NaN values will be present in the output. Parameters: ----------- min_intensity: float, default=0.0 Clips data below this value to ensure log is taken of positive numbers only. white_level: float, default=1.0 A float defining incidence intensity in the Beer-Lambert law. accelerated: bool, default=True Specify whether to use multi-threading using numba. Returns: -------- AcquisitionData, ImageData or DataContainer depending on input data type, return is suppressed if 'out' is passed Notes: ------ If it's unknown whether the data contains zero or negative values, it's recommended to set min_intensity to a small positive value. '''def__init__(self,min_intensity=0.0,white_level=1.0,accelerated=True,):kwargs={'min_intensity':min_intensity,'white_level':white_level,'_accelerated':accelerated}super(TransmissionAbsorptionConverter,self).__init__(**kwargs)defcheck_input(self,data):ifnot(issubclass(type(data),DataContainer)):raiseTypeError('Processor supports only following data types:\n'+' - ImageData\n - AcquisitionData\n'+' - DataContainer')ifself.min_intensity<=0:log.info(f"\n Current min_intensity = {self.min_intensity}: output may contain NaN or inf. Ensure your data only contains positive values or set min_intensity to a small positive value.")returnTruedefprocess(self,out=None):data=self.get_input()ifoutisNone:out=data.geometry.allocate(None)arr_in=data.as_array()arr_out=out.as_array()# we choose an arbitrary chunk size of 6400, which is a multiple of 32, to allow for efficient threadingchunk_size=6400num_chunks=data.size//chunk_sizeif(self._accelerated):remainder=data.size%chunk_sizenum_threads_original=numba.get_num_threads()numba.set_num_threads(cil_mp.NUM_THREADS)numba_loop(arr_in,num_chunks,chunk_size,remainder,1/self.white_level,self.min_intensity,arr_out)numba.set_num_threads(num_threads_original)else:ifself.white_level!=1:numpy.multiply(arr_in,1/self.white_level,out=arr_out)arr_in=arr_outifself.min_intensity>0:numpy.clip(arr_in,self.min_intensity,None,out=arr_out)arr_in=arr_outnumpy.log(arr_in,out=arr_out)numpy.negative(arr_out,out=arr_out)out.fill(arr_out)returnout