Beispiel #1
0
def cal_NetYield2(eV0,
                  Atoms,
                  xHe=0,
                  xAl=0,
                  xKapton=0,
                  WD=6.0,
                  xsw=0,
                  WriteFile='Y',
                  xsect_resonant=0.0,
                  sample=''):
    #   incident energy, list of elements, experimental conditions
    #   this one tries Ka, Kb, Lg, Lb, La, Lb
    angle0 = 45.
    textOut = ''
    if xsw != 0 and WriteFile == 'Y': print('XSW measurements')
    if sample == '':
        Include_SelfAbsorption = 'No'
    else:
        Include_SelfAbsorption = 'Yes'
        angle0 = sample.angle / math.pi * 180.
        textOut = sample.txt  # substrate concentration
    NetYield = []
    NetTrans = []
    Net = []
    out2 = ''
    net = 0.0
    text0 = ''
    edges = ['K', 'K', 'L1', 'L1', 'L2', 'L2', 'L2', 'L3', 'L3', 'L3']
    Fluo_lines = ['Ka', 'Kb', 'Lb', 'Lg', 'Ln', 'Lb', 'Lg', 'Ll', 'La', 'Lb']
    outputfile = 'Elemental_Sensitivity.txt'
    if WriteFile == 'Y':
        fo = open(outputfile, 'w')
        desc = ' '
        if xHe == 0: desc = ' not '
        if xsw == -1:
            out1 = '# 13IDC XRM/XSW using QuadVortex, incident x-ray energy at ' + str(
                eV0) + ' eV at ' + str(angle0) + ' degrees \n'
            out1+='# Helium path'+desc+'used, '+str(xAl)+' Al attenuators, '+str(xKapton+1)+' Kapton attenuators, '\
              +str(WD)+' cm working distance. \n'
        else:
            out1 = '# 13IDC XRM/XSW using QuadVortex + collimator,  incident x-ray energy at ' + str(
                eV0) + ' eV at ' + str(angle0) + ' degrees \n'
            out1+='# Helium path'+desc+'used, '+str(xAl)+' Al attenuators, '+str(xKapton)+' Kapton attenuators, '\
              +str(WD)+' cm working distance. \n'
        print(out1)
        fo.write(out1)
        if sample != '':
            for stuff in Atoms:
                text1 = '%6.3e %s/cm^3' % (stuff.Conc * sample.Nat1,
                                           stuff.AtSym)
                text0 = text0 + ' ' + text1
        textOut = textOut + ' ' + text0  # substrate concentration + other concentrations
        out1 = '# ' + text0 + '\n'
        if print2screen:
            print(out1)
        fo.write(out1)
        out1 = '%s\t%s\t%s   \t%s   \t%s   \t%s   \t%s\n' % (
            'atom', 'emit', 'emit_energy', 'yield', 'transmission',
            'net_sensitivity', 'sensitivity*concentration')
        if print2screen:
            print(out1)
        fo.write(out1)
    for (ii, atom) in enumerate(Atoms):
        atnum = f1f2.AtSym2AtNum(atom.AtSym)
        temp = f1f2.AtNum2f1f2Xsect(atnum, eV0)
        xsect = temp[
            2]  # photo-electric cross-section for fluorescence yield, temp[4] is total for attenuation
        con = atom.Conc
        for (nn, edge) in enumerate(edges):
            emit = Fluo_lines[nn]
            #edge='K';   emit='Ka'       # check K edge Ka emission
            temp = fluo_elem.get_avgElamFY(
                atom.AtSym, edge, emit, eV0,
                useAvg=1)  # July2012: useAvg=1 causes problem
            print(emit)
            fy = temp[0]
            emit_eV = temp[1]
            emit_prob = temp[2]
            if fy == 0.0 or emit_prob == 0:
                continue  # try next item if FY=0
            else:
                if xsect_resonant != 0.0:  # use input value near edge
                    xsect = xsect_resonant  # for cross-section near absoprtion edge
                #print(xsect,fy,emit_prob)
                net_yield = xsect * fy * emit_prob  # net_yield --> cross-section, yield, emission_probability
                # net transmission --> transmission from surface through detector
                ## ------------------   [self-absorption]     ------------------------------
                trans_SelfAbsorp = 1.0  # for self-absorption.
                if Include_SelfAbsorption == 'Yes':
                    sample.getPenetration(eV0)  # incident x-ray attenuation
                    if fy * emit_eV * emit_prob == 0:  # any one of three is zero
                        break  # skip
                    sample.getLa(emit_eV)
                    # account for incident x-ray attenuation, emitted x-ray attenuation
                    trans_SelfAbsorp = sample.scale  # for elements that are not part of substrate
                    if (atom in sample.ElemListFY):
                        if atom.tag == 'substrate1':
                            trans_SelfAbsorp = sample.scale1  # for elements that are part of top substrate
                        if atom.tag == 'substrate2':
                            trans_SelfAbsorp = sample.scale2  # for elements that are part of bottom substrate
## ----------------------------------------------------------------------------
            net_trans = Assemble_Detector(emit_eV, xHe, xAl, xKapton, WD, xsw)
            net = net_yield * net_trans * trans_SelfAbsorp  # elemental sensitivity
            inten = net * con  # sensitivity * concentration
            if WriteFile == 'Y':
                out1 = '%s\t%s\t%6.1f   \t%.3e   \t%.3e   \t%.3e   \t%.3e\n' % (
                    atom.AtSym + '_' + edge, emit, emit_eV, net_yield,
                    net_trans, net, inten)
                fo.write(out1)
            if print2screen:
                print('%s %s %6.1f net_yield=%.3e net_trans=%.3e net=%.3e\t' %
                      (atom.AtSym + '_' + edge, emit, emit_eV, net_yield,
                       net_trans, net))
            #print(out1)+'  %s, depth-dependent factor= %6.4f' % (atom.tag, trans_SelfAbsorp)
            if emit == 'Kb' and fy != 0:  # if above K edge, don't bother trying L edges
                break
    return textOut
Beispiel #2
0
def sim_spectra(eV0, Atoms, xHe=0, xAl=0, xKapton=0, WD=6.0, xsw=0, sample=''):
    # sample=sample matrix with object attribues to add self-absorption effect
    # Atoms is a list with elements that have attributes AtSym, Conc, tag
    if xsw == -1: xKapton = xKapton - 1  # no collimator
    Include_SelfAbsorption = 'Yes'
    Print2Screen = 'No'
    if sample == '': Include_SelfAbsorption = 'No'
    if xsw != 0: print('XSW measurements')
    xx = []
    yy = []
    tag = []
    intensity_max = -10.0
    LoLimit = 1e-10
    angle0 = ''
    text1 = ''
    if sample != '':  # sample matrix option is used
        angle0 = str(sample.angle * 180. / math.pi)
        angle0 = angle0[:5]
        for (ii, item) in enumerate(
                sample.ElemListFY):  # add matrix elements to the lists
            Atoms.append(item)
    outputfile = 'simSpectrum_table.txt'
    fo = open(outputfile, 'w')
    out1 = '#incident x-ray at ' + str(eV0) + ' eV and ' + angle0 + ' Deg.\n'
    if Print2Screen == 'Yes': print(out1)
    fo.write(out1)
    out1 = '#Emission\tenergy(eV)\tintensity \n'
    if Print2Screen == 'Yes': print(out1)
    fo.write(out1)
    out2 = '#'
    for (ix, atom) in enumerate(Atoms):
        atnum = f1f2.AtSym2AtNum(atom.AtSym)
        # con=Conc[ix]
        con = atom.Conc
        out2 = out2 + atom.AtSym + '[' + str(con) + ']   '
        for edge in ['K', 'L1', 'L2', 'L3']:
            temp = f1f2.AtNum2f1f2Xsect(atnum, eV0)
            xsect = temp[
                2]  # photoelectric crosssection for each element at incident x-ray, fluorescence yield
            temp = elam.use_ElamFY(atom.AtSym, edge)
            edge_eV = float(temp[2])  # absorption edge
            if eV0 > edge_eV:
                fy = float(temp[3])
                for EmitLine in temp[4]:
                    EmitName = EmitLine[1]
                    emit_eV = float(EmitLine[2])
                    emit_prob = float(EmitLine[3])
                    if emit_eV < fluo_emit_min:
                        continue  # ignore fluorescence below fluo_emit_min (global variable)
                    name = atom.AtSym + '_' + EmitName
                    # net transmission --> transmission from surface through detector
                    ## ------------------   [self-absorption]     ------------------------------
                    trans_SelfAbsorp = 1.0  # for self-absorption.
                    if Include_SelfAbsorption == 'Yes':
                        sample.getPenetration(
                            eV0)  # incident x-ray attenuation
                        eV0str = str(eV0)
                        text1 = ' absorption_length1(%seV)= %2.2e%s \
                                absorption_length2(%seV)= %2.2e%s' % (
                            eV0str, sample.la1 * 1.e4, 'microns', eV0str,
                            sample.la2 * 1.e4, 'microns')
                        # text1 is added to sample.txt later
                        sample.getLa(
                            emit_eV)  # emitted fluorescence attenuation
                        trans_SelfAbsorp = sample.scale  # for elements that are not part of substrate
                        if (atom in sample.ElemListFY):
                            if atom.tag == 'substrate1':
                                trans_SelfAbsorp = sample.scale1  # for elements that are part of top substrate
                            if atom.tag == 'substrate2':
                                trans_SelfAbsorp = sample.scale2  # for elements that are part of bottom substrate


## ----------------------------------------------------------------------------
                    trans = Assemble_Detector(emit_eV, xHe, xAl, xKapton, WD,
                                              xsw)
                    intensity = con * fy * emit_prob * xsect * trans * trans_SelfAbsorp
                    if intensity < LoLimit:
                        continue  # skip weak emission, arbtraray limit =1e-10.
                    if intensity > intensity_max: intensity_max = intensity
                    xx.append(emit_eV)
                    yy.append(intensity)
                    tag.append(name)
    for ix in range(len(yy)):
        yy[ix] = yy[
            ix] / intensity_max * 100.00  # makes the strongest line to 100.0
        out1 = '%s\t%f\t%f \n' % (tag[ix], xx[ix], yy[ix])
        if Print2Screen == 'Yes': print(out1)
        fo.write(out1)
    if Print2Screen == 'Yes': print(out2)
    fo.write(out2)
    fo.close()
    out1 = sim_GaussPeaks(
        xx, yy, det_res, eV0
    )  # det_res: detector resoultion for Gaussian width (global variable)
    if Include_SelfAbsorption == 'Yes':
        sample.txt = sample.txt + text1  # sample.txt is combined to output of cal_NetYield
    text = cal_NetYield2(
        eV0, Atoms, xHe, xAl, xKapton, WD, xsw,
        sample=sample)  # calculate net yield with weight-averaged emission
    print(out2)
    return text  # cal_NetYield2 output is str with number densities of elements
Beispiel #3
0
 def __init__(self, composition1='Si', density1=2.33, thickness1=0.1, \
                    composition2='Si', density2=2.33, thickness2=0.1, angle0=45.0, option='surface'):
     self.composition1 = composition1  # ex) Fe2O3
     out = f1f2.get_ChemName(composition1)  # output from get_ChemName
     self.ElemList1 = out[
         0]  # list of elments in matrix: 'Fe', 'O' for Fe2O3
     self.ElemInd1 = out[1]  # list of index: 2, 3 for Fe2O3
     self.ElemFrt1 = out[2]  # list of fraction: 0.4, 0.6 for Fe2O3
     self.density1 = density1  # in g/cm^3
     self.thickness1 = thickness1  # top layer thickness in cm
     self.composition2 = composition2
     out = f1f2.get_ChemName(composition2)
     self.ElemList2 = out[0]  # for the bottom substrate
     self.ElemInd2 = out[1]
     self.ElemFrt2 = out[2]
     self.density2 = density2
     self.thickness2 = thickness2  # bottom layer thickness in cm
     self.angle = angle0 * math.pi / 180.  # in radian, incident beam angle, surface normal =pi/2
     self.option = option  # option for fluorescing element location, surface/top/bottom
     self.la1 = 1.0  # absoprtion length in cm
     self.delta1 = 0.1  # index of refraction, real part correction
     self.beta1 = 0.1  # index of refraction, imaginary part
     self.Nat1 = 1.0  # atomic number density of the Fe2O3, 1e22 Fe2O3 atoms /cm^3
     self.la2 = 1.0
     self.delta2 = 0.1
     self.beta2 = 0.1
     self.Nat2 = 1.0  # atomic number density of the first element, 1e22 Fe2O3 atoms/cm^3
     self.scale = 1.0  # weighted average over the depth range: sum of (trans*factors)
     self.scale1 = 1.0  # sum of (trans*1.0) this is for substrate element in top layer
     self.scale2 = 1.0  # sum of (trans*thickness2/thickness1) for substrate element in bottom layer
     self.ElemListFY = []  # fluorescing element
     self.ElemFrtFY = []  # fraction for fluorescing element
     self.Nat1 = 1  # atomic number density in atoms/cc, for example # of Fe2O3/cm^3 for Fe2O3 substrate
     self.Nat2 = 1  # atomic number density in atoms/cc
     substrate1_material = Material(composition1, density1)
     AtNumDen1 = substrate1_material.NumDen  #  substrate1
     substrate2_material = Material(composition2, density2)
     AtNumDen2 = substrate2_material.NumDen  #  substrate2, fixed 8/12/10
     self.Nat1 = AtNumDen1
     self.Nat2 = AtNumDen2
     self.txt = ''
     text1 = 'substrate1:%6.3e %s/cm^3' % (AtNumDen1, composition1)
     #print(text1)
     text2 = 'substrate2:%6.3e %s/cm^3' % (AtNumDen2, composition2)
     self.txt = text1 + '  ' + text2
     print(self.txt)
     # atom.conc is normalized to the number density of substrate1 molecule
     for (ii, item) in enumerate(self.ElemList1):
         if f1f2.AtSym2AtNum(item) >= 12:  # ignore elements below Mg
             #atom=ElemFY(item, self.ElemFrt1[ii], 'substrate1')
             atom = ElemFY(item, self.ElemInd1[ii], 'substrate1')
             # eg. for Fe2O3, Fe concentration is 2 (=2 x Fe2O3 number density)
             self.ElemListFY.append(atom)
     for (ii, item) in enumerate(self.ElemList2):
         if f1f2.AtSym2AtNum(item) >= 12:  # ignore elements below Mg
             #atom=ElemFY(item, self.ElemFrt2[ii], 'substrate2')
             atom = ElemFY(item, self.ElemInd2[ii] * AtNumDen2 / AtNumDen1,
                           'substrate2')
             self.ElemListFY.append(atom)
     numLayer = 100  # each layer is sliced into 100 sublayers.
     self.depths = []  # depth values for calculation
     for ii in range(numLayer):
         step = 1.0 / numLayer
         self.depths.append(step * ii * self.thickness1)
     for ii in range(numLayer):
         step = 1.0 / numLayer
         self.depths.append(step * ii * self.thickness2 + self.thickness1)
     self.factors = []  # 1 or pre if element present at each depth
     pre = self.thickness2 / self.thickness1  # prefactor, if two layers have different thickness
     if self.option == 'surface':  # fluorescecing atoms present in only on the surface
         for ii in range(len(self.depths)):
             if ii == 0:
                 self.factors.append(1.0)
             else:
                 self.factors.append(0.0)
     if self.option == 'all':  # fluorescecing atoms present throughout
         for ii in range(len(self.depths)):
             if self.depths[ii] < self.thickness1:
                 self.factors.append(1.0)
             else:
                 self.factors.append(pre)
     if self.option == 'top':  # fluorescecing atoms present only in the top layer
         for ii in range(len(self.depths)):
             if self.depths[ii] < self.thickness1:
                 self.factors.append(1.0)
             else:
                 self.factors.append(0.0)
     if self.option == 'bottom':  # fluorescecing atoms present only in the bottom layer
         for ii in range(len(self.depths)):
             if self.depths[ii] < self.thickness1:
                 self.factors.append(0.0)
             else:
                 self.factors.append(pre)
     # note: fluorescing substrate atoms present throughout regardless of the option.
     self.trans = []  # transmission to surface for emitted fluorescence
     self.absrp = []  # absorption until surface for emitted fluorescence
     self.inten0 = []  # incident x-ray intensity at each depth
     for ii in range(len(self.depths)):
         self.trans.append(0.5)
         self.absrp.append(0.5)
         self.inten0.append(0.5)