Chapter 2: Diffraction
2.2. The Electron#
part of
MSE672: Introduction to Transmission Electron Microscopy
Spring 2024
Gerd Duscher | Khalid Hattar |
Microscopy Facilities | Tennessee Ion Beam Materials Laboratory |
Materials Science & Engineering | Nuclear Engineering |
Institute of Advanced Materials & Manufacturing | |
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.2024.1.0':
print('installing pyTEMlib')
!{sys.executable} -m pip install --upgrade pyTEMlib -q
if 'google.colab' in sys.modules:
!{sys.executable} -m pip install numpy==1.24.4
print('done')
done
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 \(\frac{1}{2}\) (lepton).
Non–relativistic De Broglie wavelength of electron:
\(\lambda = \frac{h}{p} = \frac{h}{\sqrt{2m_0E_{kin}}} \approx \frac{1.22}{\sqrt{E_{kin}}}\)
E is the kinetic energy of the electron: \(E_{kin} = 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 = 300.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 2.24 pm for acceleration voltage 300.0 kV
which is a velocity of 324852582.95 m/s or 108.36% 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: \(\lambda = \frac{h}{\sqrt{2m_e E_{kin} *(1+\frac{E_{kin}}{2 m_e c^2})}}\)
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 = 300.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 1.97 pm for acceleration voltage 300.0 kV
100kV : \(\lambda\) = 4 pm \(<\) than diameter of an atom
The relativistic parameters are:
E (keV) |
\(\lambda\) (pm) |
M/m\(_0\) |
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#
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 300keV:
The classic velocity of the electron is 324852582.95 m/s or 108.36% of the speed of light
The relativistic velocity of the electron is 232796486.28 m/s or 77.65% 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
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_dynamically_allowed(atoms, verbose=False)
get_metric_tensor(matrix)
The metric tensor of the lattice.
get_rotation_matrix(tags)
zone axis in global coordinate system
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
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']
kinematic_scattering2(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
-------
ato,s:
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 \(\mu\)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 = \frac{C}{s}\)$
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?