XPS module

The peakFit object

Note

Peak-fitting functions are hiding in the current release, but are not yet fully developed, tested or documented. The code snippet below conveys roughly how the process works at present. Look for this functionality in a future release.

#----  Create a model object
model = pesto.XPS.peakFit()

# Populate it with features
model.appendVoigtDoublet(amplitude=45e3,position=23.783,splitting=1.03,ratio=0.66,gauss_width=0.23,lorentz_width=0.21,label="C1")
model.appendVoigtDoublet(amplitude=39465,position=24.074,splitting=1.03,ratio=0.66,gauss_width=0.28,lorentz_width=0.21,label="C2")
model.appendVoigtDoublet(amplitude=20000,position=24.413,splitting=1.03,ratio=0.66,gauss_width=0.49,lorentz_width=0.21,label="C3")
model.append_BG_offset(offset=8000)
model.append_BG_shirley(shirleyfactor=0.001)

#---- configure some rules around how and whether parameters are allowed to change during the fit

# Don't allow the lorentzian width to change
model.getFeatureByLabel("C1").getParameterByLabel("lorentz_width").unlocked=False
model.getFeatureByLabel("C2").getParameterByLabel("lorentz_width").unlocked=False
model.getFeatureByLabel("C3").getParameterByLabel("lorentz_width").unlocked=False

# Don't allow the intensity ratio of the doublets to stray too far from the theoretical value
model.getFeatureByLabel("C1").getParameterByLabel('ratio').minimum=0.66 * 0.9
model.getFeatureByLabel("C1").getParameterByLabel('ratio').maximum=0.66 * 1.1
model.getFeatureByLabel("C2").getParameterByLabel('ratio').minimum=0.66 * 0.9
model.getFeatureByLabel("C2").getParameterByLabel('ratio').maximum=0.66 * 1.1
model.getFeatureByLabel("C3").getParameterByLabel('ratio').minimum=0.66 * 0.9
model.getFeatureByLabel("C3").getParameterByLabel('ratio').maximum=0.66 * 1.1

# Enforce that spin-orbit splitting can be varied, but it must always be the same for all three components
model.trackParameters(master=model.getFeatureByLabel("C1").getParameterByLabel("splitting"),slave=model.getFeatureByLabel("C2").getParameterByLabel("splitting"))
model.trackParameters(master=model.getFeatureByLabel("C1").getParameterByLabel("splitting"),slave=model.getFeatureByLabel("C3").getParameterByLabel("splitting"))

#----  Perform the fit to experimental data (x,y), and print the optimized parameters
model.doFit(x,y,beQuiet=False)

#----  Plot the fit and the component peaks
model.fitSummary(x,y)
_images/coreLevelFitExample.png

Utility functions

XPS.searchByElement

For a chosen element, display the binding energy and kinetic energy for all core levels. A red entry means that first-order light cannot excite it, but contamination from higher orders may still cause the feature to appear in your measurements. The database covers up to Bi and is based on data from webelements.com, which in turn references mostly Cardona and Ley, Photoemission in Solids I (1978)

def XPS.searchByElement()

Example:

_images/XPS_searchByElement.png

XPS.searchByEnergy

Sometimes you can have an unknown peak and you need to reverse-lookup what it could come from based on its kinetic or binding energy:

def XPS.searchByEnergy()

Example:

_images/XPS_searchByEnergy.png

XPS.searchBySplitting

But since binding energies vary slightly depending on environment and/or the photon energy calibration might not be perfect, an alternative fingerprint if you have a multiplet is to look up candidates based on the spin-orbit splitting:

def XPS.searchBySplitting()

Example:

_images/XPS_searchBySplitting.png

XPS.addPeakLabel

Now that you have hopefully identified all the peaks in your XPS spectrum, here is a helper function for labelling them.

def XPS.addPeakLabel( axis,
                      spectrum,
                      xrange,
                      hv,
                      label):

Required parameters

axis: The matplotlib axis object containing the XPS trace

spectrum: The XPS spectrum being plotted

xrange: Two-element list containing the start and end values of the subregion that will be searched for a peak

Optional parameters

hv: If ‘None’, will assume that you plotted the spectrum ‘as-is’ without modifying the energy axis. If non-zero AND the axis is called ‘Kinetic energy’, it will assume that you asked the plotting function to convert to binding energy, and it will do the same when searching for peaks. Default = None

label: String to label the peak with. Default = ‘’ (i.e. empty string)

Returns:

Nothing (adds a label to an already-existing matplotlib plot)

Example:

_images/XPS_addPeakLabel.png