def phantom_assign_concentration(ph_or, data_type=np.float32):
    """Builds the phantom used in:
    - N. Viganò and V. A. Solé, “Physically corrected forward operators for
    induced emission tomography: a simulation study,” Meas. Sci. Technol., no.
    Advanced X-Ray Tomography, pp. 1–26, Nov. 2017.

    :param ph_or: DESCRIPTION
    :type ph_or: TYPE
    :param data_type: DESCRIPTION, defaults to np.float32
    :type data_type: TYPE, optional

    :return: DESCRIPTION
    :rtype: TYPE
    """
    # ph_air = ph_or < 0.1
    ph_FeO = 0.5 < ph_or
    ph_CaO = np.logical_and(0.25 < ph_or, ph_or < 0.5)
    ph_CaC = np.logical_and(0.1 < ph_or, ph_or < 0.25)

    conv_mm_to_cm = 1e-1
    conv_um_to_mm = 1e-3
    voxel_size_um = 0.5
    voxel_size_cm = voxel_size_um * conv_um_to_mm * conv_mm_to_cm  # cm to micron
    print("Sample size: [%g %g] um" %
          (ph_or.shape[0] * voxel_size_um, ph_or.shape[1] * voxel_size_um))

    import xraylib

    xraylib.XRayInit()
    cp_fo = xraylib.GetCompoundDataNISTByName("Ferric Oxide")
    cp_co = xraylib.GetCompoundDataNISTByName("Calcium Oxide")
    cp_cc = xraylib.GetCompoundDataNISTByName("Calcium Carbonate")

    ca_an = xraylib.SymbolToAtomicNumber("Ca")
    ca_kal = xraylib.LineEnergy(ca_an, xraylib.KA_LINE)

    in_energy_keV = 20
    out_energy_keV = ca_kal

    ph_lin_att_in = (
        ph_FeO * xraylib.CS_Total_CP("Ferric Oxide", in_energy_keV) *
        cp_fo["density"] +
        ph_CaC * xraylib.CS_Total_CP("Calcium Carbonate", in_energy_keV) *
        cp_cc["density"] + ph_CaO *
        xraylib.CS_Total_CP("Calcium Oxide", in_energy_keV) * cp_co["density"])

    ph_lin_att_out = (
        ph_FeO * xraylib.CS_Total_CP("Ferric Oxide", out_energy_keV) *
        cp_fo["density"] +
        ph_CaC * xraylib.CS_Total_CP("Calcium Carbonate", out_energy_keV) *
        cp_cc["density"] +
        ph_CaO * xraylib.CS_Total_CP("Calcium Oxide", out_energy_keV) *
        cp_co["density"])

    vol_att_in = ph_lin_att_in * voxel_size_cm
    vol_att_out = ph_lin_att_out * voxel_size_cm

    ca_cs = xraylib.CS_FluorLine_Kissel(
        ca_an, xraylib.KA_LINE, in_energy_keV)  # fluo production for cm2/g
    ph_CaC_mass_fract = cp_cc["massFractions"][np.where(
        np.array(cp_cc["Elements"]) == ca_an)[0][0]]
    ph_CaO_mass_fract = cp_co["massFractions"][np.where(
        np.array(cp_co["Elements"]) == ca_an)[0][0]]

    ph = ph_CaC * ph_CaC_mass_fract * cp_cc[
        "density"] + ph_CaO * ph_CaO_mass_fract * cp_co["density"]
    ph = ph * ca_cs * voxel_size_cm

    return (ph, vol_att_in, vol_att_out)
Beispiel #2
0
#########################################################################
import copy
import logging

from flupy.algorithms.xrf_lmfit_models.compton_model import ComptonModel
from flupy.algorithms.xrf_lmfit_models.elastic_model import ElasticModel
from flupy.algorithms.xrf_lmfit_models.element_model import ElementModel
from flupy.algorithms.xrf_lmfit_models.pileup_model import PileupModel
from flupy.algorithms.xrf_lmfit_models.model_tools import _set_parameter_hint,_link_model_param_hints,_set_parameter_and_link_hint
from flupy.algorithms.xrf_calculations.transitions_and_shells import *
from itertools import combinations_with_replacement,combinations
import xraylib
from lmfit import Model


xraylib.XRayInit()
logger = logging.getLogger(__name__)

class XRFLinearModelSpectrum(object):
    """

    Construct Fluorescence spectrum which includes elastic peak,
    compton and a single element peaks. To be used for fitting
    a XRF fitting a series of spectra.

    """

    def __init__(self, params, elementlist):
        """
        Parameters
        ----------
Beispiel #3
0
def ABSORB(Beam_Theta, Detector_Theta, Beam_Energy, t):

    import xraylib

    xraylib.XRayInit()
    xraylib.SetErrorMessages(0)

    def GetMaterialMu(
        E, data
    ):  # send in  the photon energy and the dictionary holding the layer information
        Ele = data['Element']
        Mol = data['MolFrac']
        t = 0
        for i in range(len(Ele)):
            t += xraylib.AtomicWeight(xraylib.SymbolToAtomicNumber(
                Ele[i])) * Mol[i]
        mu = 0
        for i in range(len(Ele)):
            mu += (xraylib.CS_Total(xraylib.SymbolToAtomicNumber(Ele[i]), E) *
                   xraylib.AtomicWeight(xraylib.SymbolToAtomicNumber(Ele[i])) *
                   Mol[i] / t)
        return mu  # total attenuataion w/ coherent scattering in cm2/g

    def Density(Material):  # send a string of the compound of interest
        if Material == 'ZnO':
            return 5.6  #g/cm3
        elif Material == 'CIGS':
            return 5.75  #g/cm3
        elif Material == 'ITO':
            return 7.14  #g/cm3
        elif Material == 'CdS':
            return 4.826  #g/cm3
        elif Material == 'Kapton':  # http://physics.nist.gov/cgi-bin/Star/compos.pl?matno=179
            return 1.42  #g/cm3
        elif Material == 'SiN':
            return 3.44  #g/cm3
        if Material == 'Mo':
            return 10.2  #g/cm3

    def GetLayerInfo(
        Layer
    ):  #send in a string to get typical layer thickness and dictionary of composition
        um_to_cm = 10**-4

        if Layer == 'ZnO':
            mat = {'Element': ['Zn', 'O'], 'MolFrac': [1, 1]}
            t = 0.2 * um_to_cm
            return mat, t
        elif Layer == 'CdS':
            mat = {'Element': ['Cd', 'S'], 'MolFrac': [1, 1]}
            t = 0.05 * um_to_cm
            return mat, t
        elif Layer == 'Kapton':
            mat = {
                'Element': ['H', 'C', 'N', 'O'],
                'MolFrac': [0.026362, 0.691133, 0.073270, 0.209235]
            }  # http://physics.nist.gov/cgi-bin/Star/compos.pl?matno=179
            t = 26.6 * um_to_cm  #measured using profilometer
            return mat, t
        elif Layer == 'ITO':
            mat = {
                'Element': ['In', 'Sn', 'O'],
                'MolFrac': [1.8, 0.1, 2.9]
            }  #90% In2O3 #10% SnO2
            t = 0.15 * um_to_cm
            return mat, t
        elif Layer == 'Mo':
            mat = {'Element': ['Mo'], 'MolFrac': [1]}
            t = 0.7 * um_to_cm
            return mat, t

    def GetFluorescenceEnergy(
        Element, Beam
    ):  # send in the element and the beam energy to get the Excited Fluorescence Energy
        #this will return the highest energy fluorescence photon capable of being excited by the beam
        Z = xraylib.SymbolToAtomicNumber(Element)
        F = xraylib.LineEnergy(Z, xraylib.KA1_LINE)
        if xraylib.EdgeEnergy(Z, xraylib.K_SHELL) > Beam:
            F = xraylib.LineEnergy(Z, xraylib.LA1_LINE)
            if xraylib.EdgeEnergy(Z, xraylib.L1_SHELL) > Beam:
                F = xraylib.LineEnergy(Z, xraylib.LB1_LINE)
                if xraylib.EdgeEnergy(Z, xraylib.L2_SHELL) > Beam:
                    F = xraylib.LineEnergy(Z, xraylib.LB1_LINE)
                    if xraylib.EdgeEnergy(Z, xraylib.L3_SHELL) > Beam:
                        F = xraylib.LineEnergy(Z, xraylib.LG1_LINE)
                        if xraylib.EdgeEnergy(Z, xraylib.M1_SHELL) > Beam:
                            F = xraylib.LineEnergy(Z, xraylib.MA1_LINE)
        return F

    def GetIIO(Layer, Energy):
        ROI, t = GetLayerInfo(Layer)
        return np.exp(-Density(Layer) * GetMaterialMu(Energy, ROI) * t)

    #conversion factor
    um_to_cm = 10**-4
    t = t * um_to_cm

    ##Set incident Beam Energy and Detector Geometry
    # Beam_Theta = 90 #degrees
    # Detector_Theta = 47 #degrees
    # Beam_Energy = 10.5 #keV
    # Get Layor of interest information
    L = 'CIGS'
    ROI = {'Element': ['Cu', 'In', 'Ga', 'Se'], 'MolFrac': [0.8, 0.8, 0.2, 2]}
    Elem = ROI['Element']

    # define sublayers thickness and adjust based on measurement geometry
    dt = 0.01 * um_to_cm  # 10 nm stepsizes
    steps = int(t / dt)
    T = np.ones((steps, 1)) * dt
    beam_path = T / np.sin(Beam_Theta * np.pi / 180)
    fluor_path = T / np.sin(Detector_Theta * np.pi / 180)

    # initialize variables to hold correction factors
    iio = [None] * steps
    factors = [None] * len(Elem)
    #print 'For a film thickness of ', t/um_to_cm, 'microns:'
    #loop over sublayers for self attenuation and top layer attenuation
    ti = time()
    for ind, Z in enumerate(Elem):
        for N in range(steps):
            beam_in = -Density(L) * GetMaterialMu(Beam_Energy,
                                                  ROI) * beam_path[0:N]
            beam_out = -Density(L) * GetMaterialMu(
                GetFluorescenceEnergy(Z, Beam_Energy), ROI) * fluor_path[0:N]
            iio[N] = np.exp(np.sum(beam_in + beam_out))
        factors[ind] = np.sum(iio) / N * GetIIO(
            'Kapton', Beam_Energy) * GetIIO(
                'Kapton', GetFluorescenceEnergy(Z, Beam_Energy))
        #print 'The absorption of ', Z, 'in', L,'at beam energy', Beam_Energy,'is', round(factors[ind]*100,2)
    #print 'Calculation Time = ', round(time()-ti,2),'s for ', steps, 'iterations on ', ind+1,' elements'
    return factors