Chapter 2: Diffraction


2.2. The Electron#

Download

OpenInColab

part of

MSE672: Introduction to Transmission Electron Microscopy

Spring 2025
by Gerd Duscher

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

Background and methods to analysis and quantification of data acquired with transmission electron microscopes.

First we load the code to make figures from pyTEMlib

2.2.1. Import packages for figures and#

2.2.1.1. Check Installed Packages#

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

if test_package('pyTEMlib') < '0.2025.1.0':
    print('installing pyTEMlib')
    !{sys.executable} -m pip install  --upgrade pyTEMlib -q

print('done')
installing pyTEMlib
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 578.4/578.4 kB 7.8 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 84.2/84.2 kB 5.6 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 105.5/105.5 kB 6.8 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.9/2.9 MB 53.8 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 515.7/515.7 kB 29.0 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 37.5 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.0/1.0 MB 37.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.4/1.4 MB 41.4 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 41.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 119.4/119.4 kB 6.8 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 44.8/44.8 kB 2.3 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 69.9/69.9 kB 4.4 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 49.5 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 43.3/43.3 kB 2.5 MB/s eta 0:00:00
?25hdone

Please restart the session (in Runtime menu) in Google Colab.

2.2.1.2. Load the plotting and figure packages#

%matplotlib widget
import matplotlib.pylab as plt
import numpy as np
import sys
if 'google.colab' in sys.modules:
    from google.colab import output
    output.enable_custom_widget_manager()

import scipy  # we will use the constants part only

2.2.2. Interaction of Common Particles with Matter#

We generally use electron, photons, and neutrons for diffraction/scattering experiments.

These particles interact with differently with matter:

X-rays $\leftrightarrow$ electron density
neutrons $\leftrightarrow$ mass of nucleus
neutrons $\leftrightarrow$ magnetic moment
electrons $\leftrightarrow$ screened charge of nucleus

We will deal with the nature of electrons more closely in the following

2.2.3. Non-relativistic de Broglie Wavelength#

The electron is a elementary particle with spin 12 (lepton).

Non–relativistic De Broglie wavelength of electron:

λ=hp=h2m0Ekin1.22Ekin

E is the kinetic energy of the electron: Ekin=eU [eV].

The wave length in a TEM is usually a couple of picometers . This is a factor of 100 smaller than your XRD-source.

Obvioulsy, we are in the wave picture right now.

# --------- input  ---------------------------
acceleration_voltage_V = U = 100.0 * 1000.0 #V
# --------------------------------------------
## energy
E_kin = acceleration_voltage_V * scipy.constants.elementary_charge
h = scipy.constants.Planck
m0 = scipy.constants.electron_mass
c = scipy.constants.speed_of_light

wave_length_m = h/np.sqrt(2*m0*E_kin) # non-relativistic wavelength in m

# # please note that we will keep all length units in Angstrom if possible.
# # otherwise we use only SI units!!!
wave_length_A = wave_length_m *1e10 # now in Angstrom

print(f'Classic wave length is {wave_length_A*100.:.2f} pm for acceleration voltage {acceleration_voltage_V/1000.:.1f} kV')
# Notice that we change units in the output to make them most readable.

print(f' which is a velocity of {np.sqrt(2/m0*E_kin):.2f} m/s or {np.sqrt(2/m0*E_kin)/c*100:.2f}% of the speed of light')
Classic wave length is 3.88 pm for acceleration voltage 100.0 kV
 which is a velocity of 187553726.21 m/s or 62.56% of the speed of light

2.2.4. Relativistic Correction#

In the table below we see that the speeds of the electron is rather close to the speed of light c

The formula for relativistic corrected wavelength is: λ=h2meEkin(1+Ekin2mec2)

Please note: All units are internally in SI units: kg, s, V, J, except the length wihich is in nm!

We multiply with the appropriate factors for the output

# ---------Input: Acceleration Voltage --
E0 = acceleration_voltage_V = 100.0 *1000.0 # V
# ---------------------------------------
E_kin = acceleration_voltage_V * scipy.constants.elementary_charge
h = scipy.constants.Planck
m0 = scipy.constants.electron_mass
c = scipy.constants.speed_of_light

#relativisitic wavelength
wave_length = h/np.sqrt(2* m0 * E_kin * (1 + E_kin / (2 * m0 * c**2))) #in m

print(f'The relativistically corrected wave length is {wave_length*1e12:.2f} pm for acceleration voltage {acceleration_voltage_V/1000:.1f} kV')
The relativistically corrected wave length is 3.70 pm for acceleration voltage 100.0 kV

100kV : λ = 4 pm < than diameter of an atom

The relativistic parameters are:

E (keV)

λ (pm)

M/m0

v/c

10

12.2

1.0796

0.1950

30

6.98

1.129

0.3284

100

3.70

1.1957

0.5482

200

2.51

1.3914

0.6953

400

1.64

1.7828

0.8275

1000

0.87

2.9569

0.9411

The same functionality (and code) is used in the kinematic_scattering library and we can test the values of above table.

Please change the acceleration voltage (acceleration_voltage_V) above.

2.2.4.1. Relativistic velocity#

v2c2=Ekin(Ekin+2mec2)(Ekin+mec2)2
v = np.sqrt(E_kin * (E_kin + 2 * m0 * c**2)/(E_kin + m0 * c**2) **2)*c

print(f'For an acceleration voltage of {acceleration_voltage_V/1000:.0f}keV: ')
print(f'The classic velocity of the electron  is {np.sqrt(2/m0 * E_kin):.2f} m/s or {np.sqrt(2 / m0 * E_kin)/c * 100:.2f}% of the speed of light')
print(f'The relativistic velocity of the electron  is {v:.2f} m/s or {v/c*100:.2f}% of the speed of light')
For an acceleration voltage of 100keV: 
The classic velocity of the electron  is 187553726.21 m/s or 62.56% of the speed of light
The relativistic velocity of the electron  is 164352479.73 m/s or 54.82% of the speed of light

2.2.5. That means that the resolution is not limited by the wavelength!#

# Import Kinematic Scattering Library
import pyTEMlib.kinematic_scattering as ks         # Kinematic scattering Library

acceleration_voltage= 30*1e3
wave_length = ks.get_wavelength(acceleration_voltage)
print(f'The relativistically corrected wave length is {wave_length*1e2:.2f} pm for acceleration voltage {acceleration_voltage/1000:.1f} kV')

# Wavelength in Angstrom
def get_wavelength(acceleration_voltage):
    """
    Calculates the relativistic corrected de Broglie wave length of an electron

    Input:
    ------
        acceleration voltage in volt
    Output:
    -------
        wave length in Angstrom
    """
    E = acceleration_voltage * scipy.constants.elementary_charge
    h = scipy.constants.Planck
    m0 = scipy.constants.electron_mass
    c = scipy.constants.speed_of_light

    wavelength = h / np.sqrt(2 * m0 * E * (1 + (E / (2 * m0 * c ** 2))))
    return wavelength * 10**10
The relativistically corrected wave length is 6.98 pm for acceleration voltage 30.0 kV
help(ks.get_wavelength)
Help on function get_wavelength in module pyTEMlib.kinematic_scattering:

get_wavelength(acceleration_voltage)
    Calculates the relativistic corrected de Broglie wavelength of an electron in Angstrom

    Parameter:
    ---------
    acceleration_voltage: float
        acceleration voltage in volt
    Returns:
    -------
    wavelength: float
        wave length in Angstrom (= meter *10**10)
help(ks)
Help on module pyTEMlib.kinematic_scattering in pyTEMlib:

NAME
    pyTEMlib.kinematic_scattering

DESCRIPTION
    kinematic_scattering
    Copyright by Gerd Duscher

    The University of Tennessee, Knoxville
    Department of Materials Science & Engineering

    Sources:
       Scattering Theory:
       Zuo and Spence, "Advanced TEM", 2017

       Spence and Zuo, Electron Microdiffraction, Plenum 1992

       Atomic Form Factor:
           Kirkland: Advanced Computing in Electron Microscopy 2nd edition
           Appendix C

    Units:
        everything is in SI units, except length which is given in Angstrom.

    Usage:
        See the notebooks for examples of these routines

    All the input and output is done through a ase.Atoms object and the dictionary in the info attribute

FUNCTIONS
    Zuo_fig_3_18(verbose=True)
        Input for Figure 3.18 in Zuo and Spence "Advanced TEM", 2017

        This input acts as an example as well as a reference

        Parameters:
        -----------
        verbose: boolean:
            optional to see output
        Returns:
        -------
            atoms: ase.Atoms
                Silicon crystal structure
            e
            dictionary: tags is the dictionary of all input and output parameter needed to reproduce that figure.

    check_sanity(atoms, verbose_level=0)
        Check sanity of input parameters

    example(verbose=True)
        same as Zuo_fig_3_18

    feq(element, q)
        Atomic form factor parametrized in 1/Angstrom but converted to 1/Angstrom

        The atomic form factor is from Kirkland: Advanced Computing in Electron Microscopy 2nd edition, Appendix C.
        From Appendix C of Kirkland, "Advanced Computing in Electron Microscopy", 3Ard ed.
        Calculation of electron form factor for specific q:
        Using equation Kirkland C.15

        Parameters
        ----------
        element: string
            element name
        q: float
            magnitude of scattering vector in 1/Angstrom -- (=> exp(-i*g.r), physics negative convention)

        Returns
        -------
        fL+fG: float
            atomic scattering vector

    find_angles(zone)
        Microscope stage coordinates of zone

    find_nearest_zone_axis(tags)
        Test all zone axis up to a maximum of hkl_max

    get_all_miller_indices(hkl_max)

    get_dynamically_allowed(atoms, verbose=False)

    get_metric_tensor(matrix)
        The metric tensor of the lattice.

    get_rotation_matrix(angles, in_radians=False)
        Rotation of zone axis by mistilt

        Parameters
        ----------
        angles: ist or numpy array of float
            list of mistilt angles (default in degrees)
        in_radians: boolean default False
            default is angles in degrees

        Returns
        -------
        rotation_matrix: np.ndarray (3x3)
            rotation matrix in 3d

    get_wavelength(acceleration_voltage)
        Calculates the relativistic corrected de Broglie wavelength of an electron in Angstrom

        Parameter:
        ---------
        acceleration_voltage: float
            acceleration voltage in volt
        Returns:
        -------
        wavelength: float
            wave length in Angstrom (= meter *10**10)

    get_zone_rotation(tags)
        zone axis in global coordinate system

    kinematic_scattering(atoms, verbose=False)
        All kinematic scattering calculation

        Calculates Bragg spots, Kikuchi lines, excess, and deficient HOLZ lines

        Parameters
        ----------
        atoms: ase.Atoms
            object with crystal structure:
            and with experimental parameters in info attribute:
            'acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max'
            Optional parameters are:
            'mistilt', convergence_angle_mrad', and 'crystal_name'
            verbose = True will give extended output of the calculation
        verbose: boolean
            default is False

        Returns
        -------
        atoms:
            There are three sub_dictionaries in info attribute:
            ['allowed'], ['forbidden'], and ['HOLZ']
            ['allowed'] and ['forbidden'] dictionaries contain:
                ['Sg'], ['hkl'], ['g'], ['structure factor'], ['intensities'],
                ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], ['HHOLZ'], ['label'], and ['Laue_zone']
            the ['HOLZ'] dictionary contains:
                ['slope'], ['distance'], ['theta'], ['g_deficient'], ['g_excess'], ['hkl'], ['intensities'],
                ['ZOLZ'], ['FOLZ'], ['SOLZ'], ['HOLZ'], and  ['HHOLZ']
            Please note that the Kikuchi lines are the HOLZ lines of ZOLZ

            There are also a few parameters stored in the main dictionary:
                ['wave_length_nm'], ['reciprocal_unit_cell'], ['inner_potential_V'], ['incident_wave_vector'],
                ['volume'], ['theta'], ['phi'], and ['incident_wave_vector_vacuum']

    make_pretty_labels(hkls, hex_label=False)
        Make pretty labels

        Parameters
        ----------
        hkls: np.ndarray
            a numpy array with all the Miller indices to be labeled
        hex_label: boolean - optional
            if True this will make for Miller indices.

        Returns
        -------
        hkl_label: list
            list of labels in Latex format

    read_poscar(filename)

    ring_pattern_calculation(atoms, verbose=False)
        Calculate the ring diffraction pattern of a crystal structure

        Parameters
        ----------
        atoms: Crystal
            crystal structure
        verbose: verbose print-outs
            set to False
        Returns
        -------
        tags: dict
            dictionary with diffraction information added

    scattering_matrix(tags, verbose_level=1)
        Scattering matrix

    stage_rotation_matrix(alpha, beta)
        Microscope stage coordinate system

    vector_norm(g)
        Length of vector

        depreciated - use np.linalg.norm

    zone_mistilt(zone, angles)
        Rotation of zone axis by mistilt

        Parameters
        ----------
        zone: list or numpy array of int
            zone axis in Miller indices
        angles: ist or numpy array of float
            list of mistilt angles in degree

        Returns
        -------
        new_zone_axis: np.ndarray (3)
            new tilted zone axis

DATA
    a_l = 0.3336
    base_l = [(0.6666666666666666, 0.3333333333333333, 0.5), (0.3333333333...
    c_l = 0.4754
    cdb = {'ag': {'a': 4.0853, 'crystal_name': 'silver', 'elements': 'Ag',...
    crystal_data_base = {'ag': {'a': 4.0853, 'crystal_name': 'silver', 'el...
    electronFF = {'Ac': {'Z': 89, 'bond_length': [2.09, 1.88, 1.7, 0], 'ch...
    inputKeys = ['acceleration_voltage_V', 'zone_hkl', 'Sg_max', 'hkl_max'...
    jmol_colors = array([[1.   , 0.   , 0.   ],
           [1.   , 1. ...02, 0...
    optional_inputKeys = ['crystal', 'lattice_parameter_nm', 'convergence_...

FILE
    c:\users\gduscher\appdata\local\anaconda3\lib\site-packages\pytemlib\kinematic_scattering.py

2.2.6. Particle Flux and Current#

It is important todetermine the order of magitude of how many electrons are hitting the sample.

The electron sources deliver in the order of μA current, but most of these electrons are not used.

In a modern electron microscope, we talk about a range of 1pA to 1nA in the electron beam.

We start with the defition of an Ampere: $A=Cs$

That definition is enough to calculate the number ofelectron per time unit (flux).

print(f" elementary charge: {scipy.constants.physical_constants['elementary charge'][0]:.5g} {scipy.constants.physical_constants['elementary charge'][1]}")
print(f'\n  1pA is {1e-12/scipy.constants.elementary_charge:.3} electrons/s or {1e-12/scipy.constants.elementary_charge/1000:.0f} electrons/ms')
print(f' 10pA is {10e-12/scipy.constants.elementary_charge:.3} electrons/s')
print(f'100pA is {100e-12/scipy.constants.elementary_charge*1 :.3} electrons/s')

print(f'\n at 10pA an electron will hit the sample every {scipy.constants.elementary_charge/10e-12 * 1e9:.2f} ns ')
 elementary charge: 1.6022e-19 C

  1pA is 6.24e+06 electrons/s or 6242 electrons/ms
 10pA is 6.24e+07 electrons/s
100pA is 6.24e+08 electrons/s

 at 10pA an electron will hit the sample every 16.02 ns 

We see that we have much lower fluence in the TEM than in a laser (how could they do femtosecond pulses otherwise).

2.2.6.1. Question#

How long does one have to integrate a detector to register 1 electron with an electron beam of 1.6pA?