Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Analysis of EDS Spectra

EDS_Tools: Spectroscopy


Analysis of EDS Spectra


OpenInColab

part of

pyTEMlib

a pycroscopy ecosystem package

Notebook by Gerd Duscher, 2025

Microscopy Facilities
Institute of Advanced Materials & Manufacturing
The University of Tennessee, Knoxville

Model based analysis and quantification of data acquired with transmission electron microscopes

Content

An Introduction into displaying and analyzing EDS spectrum images and spectra This works also on Google Colab.

Prerequesites

Install pyTEMlib

If you have not done so in the Introduction Notebook, please test and install pyTEMlib and other important packages with the code cell below.

import sys
import importlib.metadata

def test_package(package_name):
    """Test if package exists and returns version or -1"""
    try:
        version = importlib.metadata.version(package_name)
    except importlib.metadata.PackageNotFoundError:
        version = '-1'
    return version


# pyTEMlib setup ------------------
if test_package('pyTEMlib') < '0.2025.11.0':
    print('installing pyTEMlib')
   
    !{sys.executable} -m pip install pyTEMlib --upgrade
# ------------------------------
print('done')
Fetching long content....
ERROR: Could not install packages due to an OSError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\gduscher\\AppData\\Local\\anaconda3\\envs\\pytem\\Lib\\site-packages\\sidpy\\base\\num_utils.py'
Consider using the `--user` option or check the permissions.

Loading of necessary libraries

Please note, that we only need to load the pyTEMlib library, which is based on sidpy Datsets.

%matplotlib widget
import sys
import numpy as np
import matplotlib.pylab as plt

# using  pyTEMlib.eds_tools, pyTEMlib.file_tools and pyTEMlib.eels_tools (for line definitions)
sys.path.insert(0, '..//..//')
sys.path.insert(0, '..//..//..//SciFiReaders//')


%load_ext autoreload
%autoreload 2
import SciFiReaders
    
import pyTEMlib

if 'google.colab' in sys.modules:
    from google.colab import output
    output.enable_custom_widget_manager()
    from google.colab import drive

if 'google.colab' in sys.modules:
    drive.mount("/content/drive")

# For archiving reasons it is a good idea to print the version numbers out at this point
print('pyTEM version: ',pyTEMlib.__version__)
__notebook__ = 'EDS_Spectrum_Analysis'
__notebook_version__ = '2025_10_27'
You don't have igor2 installed.     If you wish to open igor files, you will need to install it     (pip install igor2) before attempting.
pyTEM version:  0.2025.12.0

Open File

Load File

Select a main dataset and any additional data like reference data and such.

# C:\Users\gduscher\OneDrive - University of Tennessee\google_drive\2022 Experiments\Spectra\20221214\AlCe-200kV
fileWidget = pyTEMlib.file_tools.FileWidget()
Loading...
Loading...

Select and Plot Dataset

Select a dataset from the drop down value and display it with the code cell below.

Here we sum the spectra of the 4 quadrants and define the detector parameter.

spectrum = fileWidget.selected_dataset
view = spectrum.plot()
Loading...
### Does not work for spectrum images
# 
start = np.searchsorted(spectrum.energy_scale.values, 100)
energy_scale = spectrum.energy_scale.values[start:]
detector_Efficiency= pyTEMlib.eds_tools.detector_response(spectrum)  # tags, spectrum.energy_scale.values[start:])
if 'start_energy' not in spectrum.metadata['EDS']['detector']:
    spectrum.metadata['EDS']['detector']['start_energy'] = 120
spectrum[:np.searchsorted(spectrum.energy_scale.values,spectrum.metadata['EDS']['detector']['start_energy'])] = 0.
spectrum.metadata['EDS']['detector']['detector_efficiency']  = detector_Efficiency

Find Elements

# --------Input -----------
minimum_number_of_peaks = 10
# --------------------------

elements = pyTEMlib.eds_tools.get_elements(spectrum, minimum_number_of_peaks, verbose=False)

plt.figure()
plt.plot(spectrum.energy_scale,spectrum, label = 'spectrum')
pyTEMlib.eds_tools.plot_lines(spectrum.metadata['EDS'], plt.gca())
plt.legend();
elements
c:\Users\gduscher\AppData\Local\anaconda3\Lib\site-packages\dask\array\core.py:1744: FutureWarning: The `numpy.argsort` function is not implemented by Dask array. You may want to use the da.map_blocks function or something similar to silence this warning. Your code may stop working in a future release.
  warnings.warn(
['Sr', 'Cu', 'O', 'Ti']
Loading...

Quantify

Fit spectrum

peaks, pp = pyTEMlib.eds_tools.fit_model(spectrum, use_detector_efficiency=True)
model = pyTEMlib.eds_tools.get_model(spectrum)

plt.figure()
plt.plot(spectrum.energy_scale.values, spectrum, label='spectrum')
plt.plot(spectrum.energy_scale.values, model, label='model')
plt.plot(spectrum.energy_scale.values, np.array(spectrum)-np.array(model), label='difference')
plt.xlabel('energy (eV)')
pyTEMlib.eds_tools.plot_lines(spectrum.metadata['EDS'], plt.gca())
plt.axhline(y=0, xmin=0, xmax=1, color='gray')
plt.legend();
Loading...

Quantify Spectrum

first with Bote-Salvat cross section using dictionaries calculated with emtables package.

pyTEMlib.eds_tools.quantify_eds(spectrum, mask =['Cu'])
using cross sections for quantification
Sr: 23.42 at% 47.63 wt%
Ti: 32.34 at% 35.95 wt%
O : 44.24 at% 16.43 wt%

then with k-factor dictionary

q_dict = pyTEMlib.eds_tools.load_k_factors()
tags = pyTEMlib.eds_tools.quantify_eds(spectrum, q_dict, mask = ['Cu'])
using k-factors for quantification
Sr: 25.22 at% 52.20 wt%
O : 48.84 at% 18.46 wt%
Ti: 25.94 at% 29.34 wt%
excluded from quantification  ['Cu']

Absorption Correction

Lower energy lines will be more affected than higher x-ray lines.

At thin sample location (<50nm) absorption is not significant.

# ------ Input ----------
thickness_in_nm = 250
# -----------------------
pyTEMlib.eds_tools.apply_absorption_correction(spectrum, thickness_in_nm)
for key, value in spectrum.metadata['EDS']['GUI'].items():
    if 'corrected-atom%' in value:
        print(f"Element: {key}, Corrected Atom%: {value['corrected-atom%']:.2f}, Corrected Weight%: {value['corrected-weight%']:.2f}")
Element: Sr, Corrected Atom%: 19.59, Corrected Weight%: 47.03
Element: Cu, Corrected Atom%: 0.00, Corrected Weight%: 0.00
Element: Ti, Corrected Atom%: 20.29, Corrected Weight%: 26.61
Element: O, Corrected Atom%: 60.12, Corrected Weight%: 26.35

Summary

The spectrum is modeled completely with background and characteristic peak-families.

Either

  • k-factors in a file (here from Spectra300) or

  • Bothe-Salvat cross-sections

are used for quantification.

Appendix

Background

The determined background used for the model-based quantification is based on the detector effciency.

Note:

The detector efficiency is also used for the quantification model.