Beispiel #1
0
def find_xrf_peaks_list(energy,fitelements,fitting_range):
    xrf_list=[]
    for el in enumerate(fitelements):
        z =  xl.SymbolToAtomicNumber(el)
        temp_shell_list=[]
        for shell in enumerate(shells):
            if(xl.EdgeEnergy(z,shell)< energy-0.2):
                en=xl.LineEnergy(z,shell)
                if(en > fitting_range[0] and en < fitting_range[1]):
                    temp_shell_list.append(shell)
        if temp_shell_list:
            xrf_list.append(el,z,temp_shell_list)
    return xrf_list
Beispiel #2
0
def find_pileup_peak_list(energy,fitelements,fitting_range,pileup_cut_off):
    """
    Determine how many pileup peaks should be in the fit and return a list of element and shell combos
    """
    # work out the combinations of elements then see what fits..
    pileup_list=[]
    pileup_descript=[]
    # combinations of all elements..
    sumpeak_combinations=combinations_with_replacement(fitelements,2)
    for combo in sumpeak_combinations: 
        z1 =  xl.SymbolToAtomicNumber(combo[0])
        z2 =  xl.SymbolToAtomicNumber(combo[1])
        for shell1 in shells:
            if(xl.EdgeEnergy(z1,shell1)< energy-0.2):
                e1 = xl.LineEnergy(z1,shell1)
                for shell2 in shells:
                    if(xl.EdgeEnergy(z2,shell2)< energy-0.2):
                        e2=xl.LineEnergy(z2,shell2)
                        sum_peak_energy = e1+e2
                        if(sum_peak_energy > fitting_range[0] and sum_peak_energy < fitting_range[1] and sum_peak_energy>pileup_cut_off):
                            # Now add the peak to the list
                            pileup_list.append((combo,(z1,z1),(shell1,shell2)))
    return pileup_list
Beispiel #3
0
def find_escape_peak_list(energy,fitelements,fitting_range,detectortype):
    escape_list=[]
    for el in enumerate(fitelements):
        z =  xl.SymbolToAtomicNumber(el)
        temp_shell_list=[]
        for shell in enumerate(shells):
            if(xl.EdgeEnergy(z,shell)< energy-0.2):
                en=xl.LineEnergy(z,shell)
                escape_energy = calc_escape_energy(en,detectortype)
                if(escape_energy[0] > fitting_range[0] and escape_energy[0] < fitting_range[1]):
                    temp_shell_list.append(shell)
                    
        if temp_shell_list:
            escape_list.append(el,z,temp_shell_list)
    return escape_list
Beispiel #4
0
    def findLines(self, paramdict=XRFDataset().paramdict):
        """
        Calculates the line energies to fit
        """
        # Incident Energy  used in the experiment
        # Energy range to use for fitting
        pileup_cut_off = paramdict["FitParams"]["pileup_cutoff_keV"]
        include_pileup = paramdict["FitParams"]["include_pileup"]
        include_escape = paramdict["FitParams"]["include_escape"]
        fitting_range = paramdict["FitParams"]["fitted_energy_range_keV"]
        #         x = paramdict["FitParams"]["mca_energies_used"]
        energy = paramdict["Experiment"]["incident_energy_keV"]
        detectortype = 'Vortex_SDD_Xspress'
        fitelements = paramdict["Experiment"]["elements"]
        peakpos = []
        escape_peaks = []
        for _j, el in enumerate(fitelements):
            z = xl.SymbolToAtomicNumber(str(el))
            for i, shell in enumerate(shells):
                if (xl.EdgeEnergy(z, shell) < energy - 0.5):
                    linepos = 0.0
                    count = 0.0
                    for line in transitions[i]:
                        en = xl.LineEnergy(z, line)
                        if (en > 0.0):
                            linepos += en
                            count += 1.0
                    if (count == 0.0):
                        break
                    linepos = linepos / count
                    if (linepos > fitting_range[0]
                            and linepos < fitting_range[1]):
                        peakpos.append(linepos)
        peakpos = np.array(peakpos)
        too_low = set(list(peakpos[peakpos > fitting_range[0]]))
        too_high = set(list(peakpos[peakpos < fitting_range[1]]))
        bar = list(too_low and too_high)
        bar = np.unique(bar)
        peakpos = list(bar)
        peaks = []
        peaks.extend(peakpos)
        if (include_escape):
            for i in range(len(peakpos)):
                escape_energy = calc_escape_energy(peakpos[i], detectortype)[0]
                if (escape_energy > fitting_range[0]):
                    if (escape_energy < fitting_range[1]):
                        escape_peaks.extend([escape_energy])

    #         print escape_peaks
            peaks.extend(escape_peaks)

        if (include_pileup):  # applies just to the fluorescence lines
            pileup_peaks = []
            peakpos1 = np.array(peakpos)
            peakpos_high = peakpos1[peakpos1 > pileup_cut_off]
            peakpos_high = list(peakpos_high)
            for i in range(len(peakpos_high)):
                foo = [peakpos_high[i] + x for x in peakpos_high[i:]]
                foo = np.array(foo)
                pileup_peaks.extend(foo)
            pileup_peaks = np.unique(sorted(pileup_peaks))
            peaks.extend(pileup_peaks)
        peakpos = peaks
        peakpos = np.array(peakpos)
        too_low = set(list(peakpos[peakpos > fitting_range[0]]))
        too_high = set(list(peakpos[peakpos < fitting_range[1] - 0.5]))
        bar = list(too_low and too_high)
        bar = np.unique(bar)
        peakpos = list(bar)
        peakpos = np.unique(peakpos)
        #         print peakpos
        return peakpos
Beispiel #5
0
def create_element_spectra_matrix(paramdict,trans_curve):
    """
    Calculates the fitting matrix for given element list aout and optimized
    parameters guess.

    Args:
    -----

            guess:      Optimized/to be optimized parameters used to calculate characteristic lines.
            x:          Array of energy in KeV.
            ESZ:        List of atomic numbers
            att:        Attentuation
            background: Average background of total spectrum.

    Returns:
    --------

            Returns fitting matrix DB which is a (N by 2*num + 2) matrix where num
            is the number of elements to be included in the fitting matrix, 3
            is included to create space for the background, scatter peak and
            compton peak contributions which are given seperate rows and N is the
            number of data points.

    """

    # Incident Energy  used in the experiment
    # Energy range to use for fitting
    pileup_cut_off = paramdict["FitParams"]["pileup_cutoff_keV"]
    include_pileup = paramdict["FitParams"]["include_pileup"]
    include_escape = paramdict["FitParams"]["include_escape"]
    combine_escape = paramdict["FitParams"]["combine_escape_and_xrf"]
    fitting_range  = paramdict["FitParams"]["fitted_energy_range_keV"]
    x              = paramdict["FitParams"]["mca_energies_used"]
    energy         =  paramdict["Experiment"]["incident_energy_keV"]
    
  #  print "fitting_range",fitting_range
  #  print "x",x
  #  print "energy",energy  
    #  Create the standard line shapes
    #  Loop over the elements and determine
    #  if they are present in the energy range
    #  Determine the line that should be present....
    #
    detectortype=paramdict["Detectors"]["type"]
    detector = paramdict["Detectors"][detectortype]
    sigma = detector["xrf_sigma"]
    tail = detector["xrf_tail_amplitude"]
    slope = detector["xrf_slope"]
    step = detector["xrf_step"]
    detectortype=detector["detector_type"]
    no_of_transitions = len(transitions)
    fitelements =paramdict["Experiment"]["elements"]
    no_of_elements=len(fitelements)
    #
    # 
    DB_descript=[]
    temp_array = np.zeros((3,no_of_elements,no_of_transitions))
    
    
    for j,el in enumerate(fitelements):
        #
        # loop over shells for that element
        #
        z = xl.SymbolToAtomicNumber(el)
        for i,shell in enumerate(shells):
            #
            # check the edge is < energy, i.e. that it can be excited
            # 
            #
            if(xl.EdgeEnergy(z,shell)< energy-0.2):
                # Check the transition from that edge are within the energy range used
                linepos=0.0
                count=0.0
                amp=0.0
                for line in transitions[i]:
                    en = xl.LineEnergy(z,line)
                    # rad rate for relative size of the transition
                    if(en>0.0):
                        amp += xl.RadRate(z, line)
                        linepos+=xl.RadRate(z, line)*en
                        count+=1.0
                if(count==0.0):
                    break                        
                linepos = linepos/amp
                #amp=amp/count
                #print "linepos",el,linepos,transitions[i]
                if(linepos > fitting_range[0] and linepos < fitting_range[1]):
                    
                    # if we are all good then calculate the xrf peaks
                    # add  
                    temp_array[0][j][i]=1
                    #
                    # is the pileup peak for this element in the fitted energy range ? 
                    # Considering only double pileup..    
                    #    
                    if(include_pileup):
#                         for line in transitions[i]:
#                             en = xl.LineEnergy(z,line)
#                             # rad rate for relative size of the transition
#                             if(en>0.0):
#                                 amp += xl.RadRate(z, line)
#                                 linepos+=en
#                                 count+=1.0
#                             if(count==0.0):
#                                 break                        
#                         amp=amp/count
                        print 'z',z,linepos,amp
                        if(2.*linepos > fitting_range[0] and 2.*linepos < fitting_range[1] and 2.*linepos>pileup_cut_off):
                            temp_array[1][j][i]=1
                    # Is the escape peak for the element in the fitted energy range ?     
                    # escape peak could be present if xrf peak is not...
                    # 
                    if(include_escape):
                        escape_energy = calc_escape_energy(linepos,detectortype)
                        if(escape_energy[0] > fitting_range[0] and escape_energy[0] < fitting_range[1]):
                            temp_array[2][j][i]=1

    
    #  So far we've just included the double events of a single element as pileup
    #  but you can of course have 2 concentrated elements - e.g. Cu and Ni and the pileup is Cu+Ni.
    #  Now work out the sum peaks...
    #
    pileup_indices = np.unique(np.where(np.any(temp_array[1]>0, axis=1))[0])
    print "pileup_indices",pileup_indices
    sumpeak_combinations=combinations_with_replacement(pileup_indices,2)
    n=len(pileup_indices)
    r=2
    nsumpeaks = math.factorial(n+r-1)/ math.factorial(r) / math.factorial(n-1)
    # Work out how many different types of peaks there are....
    #
    _a,no_xrf_peaks,no_pileup_peaks_with_xrf,no_pileup_peaks_no_xrf,\
       no_escape_peaks_with_xrf, no_escape_peaks_no_xrf   = countIt(temp_array)              
    
    #
    if(combine_escape):
        no_escape_peaks_with_xrf, no_escape_peaks_no_xrf=0,0
    #
    # So the total no of curves is...
    #
    # pq changes 7/9/15
    no_of_curves = no_xrf_peaks + no_pileup_peaks_with_xrf + no_pileup_peaks_no_xrf+ \
       +no_escape_peaks_with_xrf + no_escape_peaks_no_xrf+(nsumpeaks - no_pileup_peaks_with_xrf - no_pileup_peaks_no_xrf)
    #no_of_curves = no_xrf_peaks + no_pileup_peaks_with_xrf + no_pileup_peaks_no_xrf+ \
    #   +no_escape_peaks_with_xrf + no_escape_peaks_no_xrf


    DB_curves = np.zeros((no_of_curves,x.size),order='F')
    DB_areas = np.zeros((no_of_curves,no_of_transitions),order='F')
    DB_cs = np.zeros((no_of_curves,no_of_transitions),order='F')

    #
    #
    # now create a constraints array...
    #
    #
    #
    #
    #    
#    no_of_constraints = no_xrf_peaks + 2*no_pileup_peaks_with_xrf + no_pileup_peaks_no_xrf+ \
#       +2*no_escape_peaks_with_xrf + no_escape_peaks_no_xrf
            
    no_of_constraints = no_xrf_peaks + 2*(nsumpeaks-no_pileup_peaks_no_xrf) + no_pileup_peaks_no_xrf+ \
       +2*no_escape_peaks_with_xrf + no_escape_peaks_no_xrf        
       
       
    #
    # rows = curves
    # columns = parameters
    #
    DB_constraints = np.zeros((no_of_constraints,no_of_curves),order='F')              

    #
    # A bit of a scruffy method...
    #
    xrf_indices = np.unique(np.where(np.any(temp_array[0]>0, axis=1))[0])
    pileup_indices = np.unique(np.where(np.any(temp_array[1]>0, axis=1))[0])
    print "pileup_indices2",pileup_indices
    escape_indices = np.unique(np.where(np.any(temp_array[2]>0, axis=1))[0])
    print "escape_indices2", escape_indices
    dd= np.hstack((xrf_indices,pileup_indices))
    dd=np.hstack((dd,escape_indices))
    _tmp,indx_list=np.unique(dd,return_inverse=True)    
    print 'silly lists',xrf_indices,indx_list,dd
    #
    #
    # Now build all the curves....
    #
    #transmission_curve = 
    #     
    # XRF first...
    print "no_xrf_peaks",no_xrf_peaks
    print "no xrf pileup_peaks",no_pileup_peaks_with_xrf,no_pileup_peaks_no_xrf
    print "no of independent escape_peaks",no_escape_peaks_with_xrf,no_escape_peaks_no_xrf
    
    CS_cross=np.zeros(no_of_transitions)
    for i in range(no_xrf_peaks):
        elindex = xrf_indices[i]
        el = fitelements[elindex]
        z = xl.SymbolToAtomicNumber(el)
        #
        # Work out the fluorescence cross section..
        #
        CS_cross=CS_cross*0.0
        if(type(trans_curve) is dict):
            trans_line = trans_curve[el]
        else:
            trans_line = trans_curve    
        line,areas = characteristic_lines(x, z,temp_array[0,elindex], transitions,sigma, tail, slope, step,detectortype,combine_escape,trans_line)
        
        for j in range(no_of_transitions):
            if(temp_array[0,elindex][j]>0.0):
                for eline in transitions[j]:
                    CS_cross[j]+=xl.CS_FluorLine(z,eline,energy)
        #olderr = np.seterr(divide='ignore')
#         for j in range(no_of_transitions):
#             if(CS_cross[j]>0):
#                 areas[j]=areas[j]/CS_cross[j]
#             else:
#                 areas[j]=0.0
        for j in range(no_of_transitions):
            if(CS_cross[j]<=0):
                areas[j]=0.0

        #areas=np.nan_to_num(areas)
        DB_curves[i]=line
        DB_areas[i] = areas
        DB_cs[i] =  CS_cross
        DB_descript.append(["xrf","xrf",el,z])
        #
        # Set the contraint to 1 (means > 0)
        #
        #   
        #
        #
        DB_constraints[i][i]=1
#        curvecount+=1   
        
    #
    # Now pileup peaks
    #
    no_pileup_peaks=no_pileup_peaks_with_xrf + no_pileup_peaks_no_xrf
    no_escape_peaks=no_escape_peaks_with_xrf + no_escape_peaks_no_xrf
    pileup_limit  = paramdict["FitParams"]["pileup_limit"]
    pileup_limit = -1.0/pileup_limit
 #   pileup_sigma = sigma*paramdict["FitParams"]["pileup_factor"]
    constraint_count = no_xrf_peaks
    
#     for i in range(no_xrf_peaks, no_xrf_peaks+no_pileup_peaks):
#         elindex = pileup_indices[i-no_xrf_peaks]
#         el = fitelements[elindex]
#         z = xl.SymbolToAtomicNumber(el)
#         if(type(trans_curve) is dict):
#             trans_line = trans_curve[el]
#         else:
#             trans_line = trans_curve    
#         line,areas = pileup_characteristic_lines(x, z, temp_array[1,elindex],transitions, pileup_sigma, tail, slope, step,trans_line)
#         DB_curves[i]=line
#         DB_areas[i][0]=areas
#         
#         DB_descript.append(["xrf","pileup",el,z])
#         #
#         # constraint, curve,parameter
#         #
#         DB_constraints[constraint_count][i] =1
#         constraint_count += 1
#         if(elindex in xrf_indices):
#             #print "constraint_count",constraint_count,indx[i-no_xrf_peaks],i-no_xrf_peaks
#             DB_constraints[constraint_count][indx_list[i]] =1
#             DB_constraints[constraint_count][i] =pileup_limit
#             constraint_count+=1
    sumcount = no_xrf_peaks
    for sumcombo in sumpeak_combinations:
        el1 = fitelements[sumcombo[0]]
        el2 = fitelements[sumcombo[1]]
        z1 = xl.SymbolToAtomicNumber(el1)
        z2 = xl.SymbolToAtomicNumber(el2)
        translist1 = temp_array[1,sumcombo[0]]
        translist2  = temp_array[1,sumcombo[1]] 
        line,areas = sumup_line_pair(x, z1, z2, translist1,translist2,transitions, sigma, tail, slope, step,correction=None)
        DB_curves[sumcount]=line
        DB_areas[sumcount][0]=areas
        DB_descript.append(["xrf","pileup",str(el1)+str(el2),str(z1+str(z2))])
        #
        # constraint, curve,parameter
        # constrain the curve to be positive...
        DB_constraints[constraint_count][sumcount] =1
        # If the pileup peak has XRF peaks...constrain it so it can't be stupidly big compated to the XRF peak. 
        constraint_count += 1
        #if(elindex in xrf_indices):
            #print "constraint_count",constraint_count,indx[i-no_xrf_peaks],i-no_xrf_peaks
        # The corresponding xrf peaks for this pileup event are..
        DB_constraints[constraint_count][indx_list[sumcount]] =1
        DB_constraints[constraint_count][indx_list[sumcount]] =1
        # This current curve index = sumcount
        DB_constraints[constraint_count][sumcount] =pileup_limit
        #constraint_count+=1
    #
        #sumcount=sumcount+1
    #
    # now escape peaks...if treated separately
    #
    escape_limit  = paramdict["FitParams"]["pileup_limit"]
    escape_limit = -1.0/escape_limit
    
    for i in range(no_xrf_peaks+no_pileup_peaks, no_xrf_peaks+no_pileup_peaks+no_escape_peaks):
        elindex = escape_indices[i-no_xrf_peaks-no_pileup_peaks]
        el = fitelements[elindex]
        z = xl.SymbolToAtomicNumber(el)
        if(type(trans_curve) is dict):
            trans_line = trans_curve[el]
        else:
            trans_line = trans_curve    
        line,areas,_ratio = escape_characteristic_lines(x, z, temp_array[2,elindex],transitions, sigma, tail, slope, step,detectortype,trans_line)
        DB_curves[i]=line
        DB_areas[i]=areas
        DB_descript.append(["xrf","escape",el,z])
        #
        # constraint, curve,parameter
        #
        DB_constraints[constraint_count][i] =1
        constraint_count += 1
        if(elindex in xrf_indices):
            DB_constraints[constraint_count][indx_list[i]] =1.
            # allow at most 50% variation from the theoretical estimate of the escape peak amplitude...
            # this allows us to compensate for angular variations which are not that well defined in the experiment...
            DB_constraints[constraint_count][i] =escape_limit # -(1.0/(ratio*1.5))   
            
            constraint_count+=1

            
    return DB_curves,DB_areas,DB_cs,DB_constraints,DB_descript
Beispiel #6
0
def characteristic_lines(x, Z, translist,transitions, sigma, tail, slope, step,\
                      detectortype,include_escape=False,correction=None):
    """
    Calculates characteristic XRF lines in given transitions by given elements Z.

    Args:
    -----

            x:              Array of energy in KeV.
            Z:              Input element number
            translist  :    index list of transitions 0=exclude, 1=include  
            transitions:    List of transitions
            sigma:          Detector precision.
            tail : Amplitude for gaussian_tail contribution.
            slope:          Slope of tail. Slope = sigma.
            step            step for hypermet
            detectortype:   Si or Ge for determining escape peak amplitude and position
            include_escape  : Include escape peak in the line profile (otherwise it can be treated seperately)
            correction      :  Attenuation correction - basically product of sample matrix, filter, detector absorption and transmission 
                            effects  

    Returns:
    --------

            Returns characteristic XRF lines for given transitions in element Z.
    """
    # the final line...
    line = np.zeros(x.size)
    # transition lines
    tline = np.zeros(x.size)
    # escape peak lines
    eline = np.zeros(x.size)

    pre_attenuation_area = np.zeros(len(translist))
    post_attenuation_area = np.zeros(len(translist))

    # Loop over the all the transitions...

    for i, gt in enumerate(transitions):
        tline = tline * 0.0
        eline = eline * 0.0
        #
        # translist says whether the transition is to be included...
        # this depends on the incident energy etc.
        #
        if (translist[i] == 0):
            pre_attenuation_area[i] = 0.0
            post_attenuation_area[i] = 0.0
            continue
        else:
            for ht in gt:
                # rad rate for relative size of the transition
                amplitude = xl.RadRate(Z, ht)
                if amplitude != 0.0:
                    # energy of this transition..
                    energy = xl.LineEnergy(Z, ht)
                    # mixture of gaussian, tail + shelf
                    tline = tline + amplitude * (gaussian(x, energy, sigma)[0] +\
                           gaussian_tail(x, energy, energy, sigma, tail, slope) +\
                                         shelf(x, energy, sigma, step) )
                    # if you are including calculated escape peaks then add them in now...
                    if (include_escape):
                        eline = eline + amplitude * escape_peak_calculated(
                            x, energy, sigma, detectortype)[0]
            # sum area - only for XRF peaks...
            pre_attenuation_area[i] = pre_attenuation_area[i] + np.sum(tline)
            #
            # apply the attenutation correction after the area calculation...
            #
            if (correction != None):
                tline = tline * correction
            post_attenuation_area[i] = post_attenuation_area[i] + np.sum(tline)
        # total line shape - sum of transitions lines + escape peaks..
        line = line + tline + eline
    return line, pre_attenuation_area