Chapter 3: Imaging
3.3. Contrast Transfer Function#
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.
3.3.1. Load important packages#
3.3.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.2.3':
print('installing pyTEMlib')
!{sys.executable} -m pip install --upgrade pyTEMlib -q
print('done')
done
3.3.1.2. Load Packages#
We will use
numpy and matplotlib (installed with magic comand %pylab.)
some more plotting functions for circle and tables
The pyTEMlib kinematic scattering librarty is only used to determine the wavelength.
%matplotlib widget
import matplotlib.pyplot as plt
import numpy as np
import sys
if 'google.colab' in sys.modules:
from google.colab import output
output.enable_custom_widget_manager()
# Multidimensional Image library
import scipy.ndimage as ndimage
# Some additional plotting libraries
from matplotlib.patches import Circle
from IPython.display import HTML, display
# Import libraries from pyTEMlib
import pyTEMlib
import pyTEMlib.animation
import pyTEMlib.kinematic_scattering as ks # Kinematic sCattering Library
# it is a good idea to show the version numbers at this point for archiving reasons.
print('pyTEM version: ',pyTEMlib.__version__)
__notebook_version__ = '2022_03_23'
pyTEM version: 0.2024.02.2
3.3.2. Lens Aberrations#
This theoretical resolution of the de Broglie Wavelength as discussed in the Resolution Notebook is not achieved so far, because electro-magnetic lenses are as bad as
bottom of champagne bottle (Europe)
bottom of coke bottle (US)
We need to look into the aberrations of lenses if we want to understand resolution in the TEM
3.3.2.1. Schematic of Aberration#
An ideal lens converges all rays going through the lens parallel to the optical axis in the focal point.
The wavefront is laying on a circle, meaning all rays are perpendicular to the tagent of a sphere centered at the focal point. (press ideal rays below)
Aberrated rays of a certain distance (and angle in cylindrical coordinates) to the optical axis cut the optic axis at a point which is not the focal point and lay on a sphere with the center at that point. (press aberrated rays in figure below to visualize)
In the case of spherical aberration the point of rays cutting the optical axis with distance will move more and more away from the focal point. The projection of that aberration is an ellipse. (as shown below with aberration wavefront pressed)
The difference between the ideal (spherical) wavefront and the aberrated one is directly related to the aberration function.( which is schematically visualized if aberration function is pressed below)
view_i = pyTEMlib.animation.InteractiveAberration()
3.3.2.2. Notation of Aberrations#
The notations of the coefficients \(C_{m,n}\) of the aberration function \(\chi\) is defined according to Krivanek et al.:
Notation |
Order of ray aberr. |
Order of wave aberr. |
Name |
Symmetry |
---|---|---|---|---|
C\(_{01A}\) |
0 |
1 |
Probe shift in x direction |
1-fold |
C\(_{01B}\) |
0 |
1 |
Probe shift in y direction |
1-fold |
C\(_{1}\) |
1 |
2 |
Defocus |
Rotational |
C\(_{12}\) |
1 |
2 |
Astigmatism |
2-fold |
C\(_{21}\) |
2 |
3 |
Coma |
1-fold |
C\(_{23}\) |
2 |
3 |
3-fold astigmatism |
3-fold |
C\(_{3}\) |
3 |
4 |
Spherical aberration (C\(_s\)) |
Rotational |
C\(_{32}\) |
3 |
4 |
2–fold astig of C\(_s\) |
3-fold |
C\(_{34}\) |
3 |
4 |
4–fold astig of C\(_s\) |
3-fold |
I am using that notation because the Nion dedicated STEMs use this notation.
With the above notation the aberration function is expressed in spherical coordinates as: $$ \chi(\theta, \phi) = { \theta [ C_{01A}\cos(\phi)+C_{01B}\sin(\phi)]\
\frac{\theta^2}{2}[C_1+C_{12A}\cos(2\phi)+C_{12B}\sin(2\phi)]+\nonumber \
\frac{\theta^3}{3}[C_{21A}\cos(\phi)+C_{21B}\sin(\phi)+ C_{23A}\cos(3\phi)+C_{23B}\sin(3\phi)]+\nonumber \
\frac{\theta^4}{4}[C_3+C_{32A}\cos(2\phi)+C_{32B}\sin(2\phi)+ C_{34A}\cos(4\phi)+C_{34B}\sin(4\phi)]+ \nonumber\
…}\nonumber $$ which is equivalent to:
you notice that \(m\) is the order of aberration +1
3.3.2.3. Aberrations of a (Non-Corrected) TEM#
We set typical values for our TEM (Zeiss Libbra 200MC)
acceleration_voltage_V = 200*1e3 # Microscope voltage in V
C_s=2.2 # Spherical abberation coefficient in mm
defocus = -90 # Microscope defocus in nm
C_c=2.0 # Chromatic abberation coefficient in mm
3.3.3. Contrast Transfer Function#
For an uncorrected microscope the defocus \(\Delta f\) and the spherical aberration \(C_s = C_{30}\) are the resolution limiting parameter. The aberration function reduces to:
which is in carthesian coordinates $\(\chi(k)=\frac{\pi}{2}C_s\lambda^3k^4-\pi \Delta f \lambda k^2\)$
Incidentily, these aberrations are also independent of the azimutal angle and are isotrope in that direction.
The deBrouglie wave length of the electrons \(\lambda\) is calculated from the acceleration voltage as in notebook The Electron
The functions that tells us what spatial frequencies are transfered from object to image is called the Contrast Transfer Function (CTF).
With
\(A\): objective aperture function;
\(E\): envelope or damping function;
\(\chi\) aberration function.
The sin function in above equation points to the oscillatory nature of the contrast transfer function, which is the worst possible behavior for a transfer functions. Some spatial frequencies are transfered with positive intensities, with others negative intensities and some even not at all. This is as far away from an ideally square transfer function as imaginable.
To mitigate this problem, one aims for a rather flat aberration function for as long a range of spatial frequency as possible: The function \(\sin(\chi)\) is flat if \(\frac{d\chi}{du}\) is zero.
We set the left term to zero to get the flat portion and get:
When \(\chi \) is \(-120^{\rm o}\) (or \(-2\pi/3\)) we get:
3.3.4. Scherzer Focus#
Combining the two equations gives a certain defocus value: the Scherzer focus \(\Delta f_{Sch}\):
acceleration_voltage = 200*1e3 # microscope acceleration voltage in V
C_s = 2.2 # spherical abberation coefficient in mm
def calculate_scherzer(wavelength, C_s):
"""
Calculate the Scherzer defocus.
Input:
C_s: float - spherical aberration in mm (convention) will internally be scaled to Angstrom
wavelength: float - wavelength in Angstrom
order: int - optional the order of the Scherzer defocus
Output:
scherzer_defocus: float - Scherzer defocus in Angstrom
"""
C_s = C_s * 1e7 # now in Angstrom
scherzer_defocus = -np.sqrt(3/2 * C_s * wavelength) # in nm
return scherzer_defocus
wavelength = ks.get_wavelength(acceleration_voltage) # in nm
scherzer =calculate_scherzer(wavelength, C_s)
print(f'Scherzer defocus is {scherzer/10:.1f} nm')
Scherzer defocus is -126.7 nm
3.3.4.1. Higher Order Scherzer Defoci#
Often the dimensionless form of the aberration function \(\chi(k)\) is used where we substitute
into the aberration function \(\chi(k)\):
and get: $\(\chi(K) = \pi(0.5 K^4 - D K^2)\)$
The minimum of a function is determined by setting the first derivative to zero. In our case we use the aberration function that only considers spherical aberration and defocus. $\( \frac{\partial \chi(K)}{K} = \pi (2K^3 -2DK) = 0\\ \)\( \)\( K^2-D = 0\\ \)\( \)\( K = \sqrt{D} \)$
We use this result and substitute \(K\) with \(\sqrt{D}\) in the original equation of \(\chi(K)\): $\( \chi(K) = \pi \left( 0.5\left(\sqrt{K}\right)^4 - D \left(\sqrt{D}\right)^2 \right)\\ = \pi \left(0.5 D^2 - D^2 \right)\\ = -0.5D^2\\ {\rm with\ condition\ for\ }\sin\left[\chi(K)\right] \approx \pm 1 \ \ \\ = -\left[ \frac{2 n_D -1}{2}\right]\pi -\frac{\pi}{4} \)$
The optimum defocus is therefore: $\( D = \sqrt{2 n_D - 0.5}\\ \Delta f = \sqrt{(2 n_D - 0.5) C_s \lambda}\\ {\rm with:\ } n_D = 1, 2, 3 , ...\\ \)$
The case \(n_D = 1\) is refered to as Scherzer focus. (\(n_D = 2\) as 2\(^{nd}\) Scherzer, …)
In the code cell below, the Scherzer defoci are calculated up to order 6. Change the \(C_s\) and acceleration_voltage values and see what happend to the optimum defocus.
C_s = 2.2 # in mm
acceleration_voltage = 200*1e3 # in eV
def calculate_scherzer(wavelength, C_s, order=1):
"""
Calculate the Scherzer defocus.
Input:
C_s: float - spherical aberration in mm (convention) will internally be scaled to Angstrom
wavelength: float - wavelength in Angstrom
order: int - optional the order of the Scherzer defocus
Output:
Scherzer defocus in Angstrom
"""
C_s = C_s*1e7 # now in nm
scherzer= -np.sqrt((2*order-0.5) * C_s*wavelength) # in Angstrom
return scherzer
wavelength = ks.get_wavelength(acceleration_voltage)
Scherzer_defoci = np.zeros([5,2])
Scherzer_defoci[:,0] = np.arange(5)+1 # the n_D values of order of Scherzer defocus
for n_D in Scherzer_defoci[:,0]:
Scherzer_defoci[int(n_D-1),1] = calculate_scherzer(wavelength, C_s, order=n_D)/10 # Scherzer defocii in nm
Scherzer_defoci = np.array(np.round(Scherzer_defoci,0), dtype=int)
plt.figure(figsize=(5,2))
plt.title(f'Scherzer defoci for energy: {acceleration_voltage/1000:.0f} keV and $C_s$: {C_s:.1f} mm' )
collabel=("$n_D$", "$\Delta f$ (nm)")
plt.axis('tight')
plt.axis('off')
the_table = plt.table(cellText=Scherzer_defoci, colLabels=collabel, loc='center')
Go to Contrast transfer function to see the effect on the image contrast of defocus.
3.3.5. Point Resolution#
The point resolution of a microscope is defined as the spatial frequency ‘’u’’res where the CTF crosses the abscissa for the first time. At Scherzer defocus this value is maximized:
Contributions with a spatial frequency higher than the point resolution can be filtered out with an appropriate aperture leading to easily interpretable images at the cost of a lot of information lost.
# Calculate the resolution at Scherzer defocus, Cs is in mm, lambda is in nm
# The returned value is in nm
acceleration_voltage = 200*1e3 # in eV
C_s = 2.2
wavelength = ks.get_wavelength(acceleration_voltage)
def calculate_resolution_scherzer(wavelength, C_s):
"""
Calculates the resolution at Scherzer defocus
Input:
wavelength: float - wavelength of electrons in Angstrom
C_s: float - spherical aberration in mm (convention)
Output:
resolution: float - resolution at Scherzer in Angstrom
"""
C_s = C_s*1e7 # now in nm
wavelength = wavelength
scherzerres=0.64 * wavelength**0.75 * C_s**0.25
return scherzerres
scherzer = calculate_scherzer(wavelength, C_s)
scherzer_resolution = calculate_resolution_scherzer(wavelength, C_s)
print(f'Point resolution (at Scherzer focus) is {scherzer_resolution:.2f} Angstrom')
Point resolution (at Scherzer focus) is 2.76 Angstrom
3.3.6. Contrast transfer function#
Now we plot the CTF for Scherzer defocus for spatial frequencies \(u\) (distances in k- or reciprocal space): $\(\chi(u)=\frac{\pi}{2}C_s\lambda^3u^4-\pi \Delta f \lambda u^2\)$
Please note that we will see the square of the CTF: CTF\(^2\) in the intensity of the images.
In the code cell below change the value of defocus2
by setting the order of Scherzer defocus \(n_D\), or replace it by a random nuymber.
defocus2 = calculate_scherzer(wavelength, C_s, order=3)
defocus = scherzer = calculate_scherzer(wavelength, C_s)
wavelength = ks.get_wavelength(acceleration_voltage)
ref_scale_x = 0.016537397801242235/10
u = np.linspace(0,1023,1024)*ref_scale_x
def calculate_ctf(wavelength, C_s, defocus,k):
# everything in Angstrom
C_s = C_s*10**7
ctf = np.sin(np.pi*defocus*wavelength * k**2 + 0.5*np.pi*C_s*wavelength**3 * k**4)
return ctf
ctf = calculate_ctf(wavelength, C_s, defocus,u)
ctf2= calculate_ctf(wavelength, C_s, defocus2,u)
plt.figure(figsize=(8,4))
plt.title(f'CTF for C$_s$: {C_s:.1f} mm and defocus $\Delta f$: {defocus/10:.0f}nm')
plt.plot(u,ctf, label = f'ctf df = {defocus/10:.1f}')
plt.plot(u,ctf2, label = f'ctf df = {defocus2/10:.1f}')
plt.plot([1/scherzer_resolution,1/scherzer_resolution],[-1,1],linewidth = 3, label ='Point res.')
plt.plot([0,10],[0,0],linewidth = 1, c='black')
plt.xlabel('angle (1/$\AA$)')
plt.legend(loc=0)
plt.xlim(0,1.)
(0.0, 1.0)
3.3.7. The Diffractogram of an Amorphous Sample#
First we define the aberration function chi \(\chi\) by using above formula:
def make_chi( phi, theta, aberrations) :
"""
###
# Aberration function chi
###
phi and theta are meshgrids of the angles in polar coordinates.
aberrations is a dictionary with the aberrations coefficients
Attention: an empty aberrations dictionary will give you a perfect aberration
"""
chi = np.zeros(theta.shape)
for n in range(6): ## First Sum up to fifth order
term_first_sum = np.power(theta,n+1)/(n+1) # term in first sum
second_sum = np.zeros(theta.shape) ## second Sum intialized with zeros
for m in range((n+1)%2,n+2, 2):
#print(n, m)
if m >0:
if f'C{n}{m}a' not in aberrations: # Set non existent aberrations coefficient to zero
aberrations[f'C{n}{m}a'] = 0.
if f'C{n}{m}b' not in aberrations:
aberrations[f'C{n}{m}b'] = 0.
# term in second sum
second_sum = second_sum + aberrations[f'C{n}{m}a'] *np.cos(m* phi) + aberrations[f'C{n}{m}b'] *np.sin(m* phi)
else:
if f'C{n}{m}' not in aberrations: # Set non existent aberrations coefficient to zero
aberrations[f'C{n}{m}'] = 0.
# term in second sum
second_sum = second_sum + aberrations[f'C{n}{m}']
chi = chi + term_first_sum * second_sum *2*np.pi/ aberrations['wavelength']
return chi
3.3.7.1. Setting up angle and calculate aberration function#
We set up all the angles over which we want to calculate the aberration function
def get_chi( ab, sizeX, sizeY, tags, verbose= False):
"""
####
# Internally reciprocal lattice vectors in 1/nm or rad.
# All calculations of chi in angles.
# All aberration coefficients in nm
"""
ApAngle=ab['convergence_angle']/1000.0 # in rad
wl = ks.get_wavelength(ab['acceleration_voltage'])
if verbose:
print(f"Acceleration voltage {ab['acceleration_voltage']/1000:}kV => wavelength {wl*1000.:.2f}pm")
ab['wavelength'] = wl
## Reciprocal plane in 1/nm
dk = 1/ab['FOV']
kx = np.array(dk*(-sizeX/2.+ np.arange(sizeX)))
ky = np.array(dk*(-sizeY/2.+ np.arange(sizeY)))
Txv, Tyv = np.meshgrid(kx, ky)
# define reciprocal plane in angles
phi = np.arctan2(Txv, Tyv)
theta = np.arctan2(np.sqrt(Txv**2 + Tyv**2),1/wl)
## calculate chi
chi = (make_chi(phi,theta,ab))
## Aperture function
mask = theta >= ApAngle
aperture =np.ones((sizeX,sizeY),dtype=float)
aperture[mask] = 0.
return chi, aperture
def print_abberrations(ab):
from IPython.display import HTML, display
output = '<html><body>'
output+= f"Abberrations [nm] for acceleration voltage: {ab['acceleration_voltage']/1e3:.0f} kV"
output+= '<table>'
output+= f"<tr><td> C10 </td><td> {ab['C10']/10:.1f} </tr>"
output+= f"<tr><td> C12a </td><td> {ab['C12a']/10:20.1f} <td> C12b </td><td> {ab['C12b']/10:20.1f} </tr>"
output+= f"<tr><td> C21a </td><td> {ab['C21a']/10:.1f} <td> C21b </td><td> {ab['C21b']/10:.1f} "
output+= f" <td> C23a </td><td> {ab['C23a']/10:.1f} <td> C23b </td><td> {ab['C21b']/10:.1f} </tr>"
output+= f"<tr><td> C30 </td><td> {ab['C30']/10:.1f} </tr>"
output+= f"<tr><td> C32a </td><td> {ab['C32a']/10:20.1f} <td> C32b </td><td> {ab['C32b']/10:20.1f} "
output+= f"<td> C34a </td><td> {ab['C34a']/10:20.1f} <td> C34b </td><td> {ab['C34b']/10:20.1f} </tr>"
output+= f"<tr><td> C41a </td><td> {ab['C41a']/10:.3g} <td> C41b </td><td> {ab['C41b']/10:.3g} "
output+= f" <td> C43a </td><td> {ab['C43a']/10:.3g} <td> C43b </td><td> {ab['C41b']/10:.3g} </tr>"
output+= f"<tr><td> C50 </td><td> {ab['C50']/10:.3g} </tr>"
output+= f"<tr><td> Cc </td><td> {ab['Cc']/10:.3g} </tr>"
output+='</table></body></html>'
display(HTML(output))
3.3.7.2. Define all aberration coefficients and paramters necessary#
ab = {'C10':0,'C12a':0,'C12b':0,'C21a':0,'C21b':0,'C23a':0,'C23b':0,'C30':0.,
'C32a':0.,'C32b':-0.,'C34a':0.,'C34b':0.,'C41a':0.,'C41b':-0.,'C43a':0.,
'C43b':-0.,'C45a':-0.,'C45b':-0.,'C50':0.,'C52a':-0.,'C52b':0.,
'C54a':-0.,'C54b':-0.,'C56a':-0.,'C56b':0.}
ab['C30'] = .5*1e7
ab['Cc'] = 2.0*1e7
ab['source_size'] = 2.0
ab['acceleration_voltage'] = 200000
ab['convergence_angle'] = 10
ab['origin'] = 'target aberrations'
ab['TEM_name'] = 'ZeissMC200'
ab_zero = ab.copy()
sizeX = sizeY = 512
sigma = 6 ## carbon
3.3.7.3. Calculate Diffractogram#
Let’s assume a completely random object then the excit wave function will be also random, we weight those random wave vectors according to the interaction parameter in an exponential function as before. So, we got us a transmission function and an exit wave \(q_r\)
ab = ab_zero.copy()
ab['C10'] = -540 # calculate_scherzer(wavelength, C_s, order=1)
ab['C12b'] = 150
ab['FOV'] = 400
ab['convergence_angle'] = 40 # in mrad
V_noise =np.random.rand(sizeX,sizeY)
smoothing = 1
phi_r = ndimage.gaussian_filter(V_noise, sigma=(smoothing, smoothing), order=0)
q_r = np.exp(1j*sigma * phi_r)
Q_k = np.fft.fftshift(np.fft.ifft2(q_r))
chi, A_k = get_chi( ab, sizeX, sizeY, ab, verbose= True)
T_k = (np.exp(-1j*chi))
t_r = (np.fft.ifft2(np.fft.fftshift(T_k)))
psi_r = np.fft.fftshift(np.fft.ifft2((Q_k*T_k)))
i_r = np.real(psi_r*np.conjugate(psi_r))
diffractogram_k = np.absolute(np.fft.fftshift(np.fft.ifft2(i_r)))
fig, ax = plt.subplots(1, 2, figsize=(8, 4))
extent = [-int(ab['FOV']/2),int(ab['FOV']/2),-int(ab['FOV']/2),int(ab['FOV']/2)]
ax[0].imshow(i_r, extent = [-int(ab['FOV']/2),int(ab['FOV']/2),-int(ab['FOV']/2),int(ab['FOV']/2)])
ax[0].set_ylabel('distance [nm]')
ax[0].set_title('Sample')
extent_ff = 1/np.array(extent)*sizeX/(np.pi/2)
ax[1].imshow(np.log2(diffractogram_k), extent = extent_ff)
ax[1].set_ylabel("reciprocal distance [mrad]")
ax[1].set_title('Diffractogram')
scherzer_angle = 1/scherzer_resolution * wavelength *1000.
from matplotlib.patches import Circle
point_resolution = Circle((0, 0),radius = scherzer_angle, linestyle=':', fill = False, color = 'red')
ax[1].add_patch(point_resolution)
plt.tight_layout();
print_abberrations(ab)
Acceleration voltage 200.0kV => wavelength 25.08pm
C10 | -54.0 | ||||||
C12a | 0.0 | C12b | 15.0 | ||||
C21a | 0.0 | C21b | 0.0 | C23a | 0.0 | C23b | 0.0 |
C30 | 500000.0 | ||||||
C32a | 0.0 | C32b | -0.0 | C34a | 0.0 | C34b | 0.0 |
C41a | 0 | C41b | -0 | C43a | 0 | C43b | -0 |
C50 | 0 | ||||||
Cc | 2e+06 |
def diffractogram(ab):
V_noise =np.random.rand(sizeX,sizeY)
smoothing = 1
phi_r = ndimage.gaussian_filter(V_noise, sigma=(smoothing, smoothing), order=0)
q_r = np.exp(1j*sigma * phi_r)
Q_k = np.fft.fftshift(np.fft.ifft2(q_r))
chi, A_k = get_chi( ab, sizeX, sizeY, ab, verbose= True)
T_k = (np.exp(-1j*chi))
t_r = (np.fft.ifft2(np.fft.fftshift(T_k)))
psi_r = np.fft.fftshift(np.fft.ifft2((Q_k*T_k)))
i_r = np.real(psi_r*np.conjugate(psi_r))
diffractogram_k = np.absolute(np.fft.fftshift(np.fft.ifft2(i_r)))
fig, ax = plt.subplots(1, 2, figsize=(8, 4))
extent = [-int(ab['FOV']/2),int(ab['FOV']/2),-int(ab['FOV']/2),int(ab['FOV']/2)]
ax[0].imshow(i_r, extent = [-int(ab['FOV']/2),int(ab['FOV']/2),-int(ab['FOV']/2),int(ab['FOV']/2)])
ax[0].set_ylabel('distance [$\AA$]')
ax[0].set_title('Sample')
extent_ff = 1/np.array(extent)*sizeX/(np.pi/2)
ax[1].imshow(np.log2(diffractogram_k), extent = extent_ff)
ax[1].set_ylabel("reciprocal distance [mrad]")
ax[1].set_title('Diffractogram')
scherzer_angle = 1/scherzer_resolution * ab['wavelength'] *10000.
point_resolution = Circle((0, 0),radius = scherzer_angle, linestyle=':', fill = False, color = 'red')
ax[1].add_patch(point_resolution)
plt.tight_layout();
print_abberrations(ab)
Now we can explore the effect of astigmatism
#All values in Angstrom
ab['C10'] = -500
ab['C12a'] = 200
ab['C12b'] = 0
ab['FOV'] = 400
diffractogram(ab)
Acceleration voltage 200.0kV => wavelength 25.08pm
C10 | -50.0 | ||||||
C12a | 20.0 | C12b | 0.0 | ||||
C21a | 0.0 | C21b | 0.0 | C23a | 0.0 | C23b | 0.0 |
C30 | 500000.0 | ||||||
C32a | 0.0 | C32b | -0.0 | C34a | 0.0 | C34b | 0.0 |
C41a | 0 | C41b | -0 | C43a | 0 | C43b | -0 |
C50 | 0 | ||||||
Cc | 2e+06 |
3.3.7.4. Aberrations of a (Non-Corrected) TEM#
We set typical values for our TEM (Zeiss Libbra 200MC)
acceleration_voltage_V = 200*1e3 # Microscope voltage in V
C_s = 2.2 # Spherical abberation coefficient in mm
defocus = -90 # Microscope defocus in nm
C_c = 2.0 # Chromatic abberation coefficient in mm
3.3.8. Stability Parameters and Dampening of CTF#
For stability, which is expressed as a dampening of the contrast transfer function. These envelope functions are determined by the following parameters.
Experimental parameters
chromatic aberration \(C_c\)
energy spread of the electron gun
convergence angle \(\alpha\)
Stability parameters
stability of the acceleration voltage
stability of objective lens current
driftrate fo the sample
IObj_stability = .1 # The objective lens stability in ppm (Delta I Obj/I Obj)*1e6
HT_stability = 0.1/200000*1e4 # The stabilty of the HT supply in ppm (Delta V/V)*1e6
source_spread = 0.6 # The energy spread of the electron source in eV.
# FEG: 0.9 eV and LaB6: 2.0 eV are typical energy spread values for these emitters
source_alpha = 0.1 # The covergence semiangle of the source in mrad
# Note FEG and LaB6 buttons provide typical alpha value for these emitters
drift_rate = 1 # The drift rate in Angstrom/s. Note no exposure time is provided so
# the Edrift envelope is for a 1s exposure.
However it is the ‘’envelope function’’ ‘’E(‘’’u’’’)’’ which usually dampens the signal of beams scattered at high angles, and imposes a maximum to the transmitted spatial frequency. This maximum determines the highest resolution attainable with a microscope and is known as the information limit. ‘’E(‘’’u’’’)’’ can be described as a product of single envelopes:
due to
\(E_s(u)\): source envelope
\(E_c(u)\): chromatic aberration
\(E_d(u)\): specimen drift
In principle we also should consider:
\(E_v(u)\): specimen vibration
\(E_D(u)\): detector but we generally handle that by oversampling the image (an atom is more than a pixel)
Specimen drift and vibration can be minimized in a stable environment. It is usually the spherical aberration \(C_s\) that limits spatial coherency and defines \(E_s(u)\) and the chromatic aberration \(C_c\), together with current and voltage instabilities that define the temporal coherency in \(E_c(u)\). These two envelopes determine the information limit by damping the signal transfer in Fourier space with increasing spatial frequency \(u\).
where α is the semiangle of the pencil of rays illuminating the sample. Clearly, if the wave aberration (‘here represented by ‘’Cs’’ and Δ’’f’’) vanished, this envelope function would be a constant one. In case of an uncorrected TEM with fixed ‘’Cs’’, the damping due to this envelope function can be minimized by optimizing the defocus at which the image is recorded (Lichte defocus).
The temporal envelope function can be expressed as
Here, \(\delta\) is the focal spread with the chromatic aberration \(C_c\) as the parameter:
The terms \(\Delta I_\text{obj}/I_\text{obj}\) and \(\Delta V_\text{acc}/V_\text{acc}\) represent instabilities in of the total current in the magnetic lenses and the acceleration voltage. \(\Delta E/V_\text{acc}\) is the energy spread of electrons emitted by the source.
defocus= scherzer
C_c = 2.0
#Compute the Es function - source dependent envelope function
def source_Env(wavelength,source_alpha, defocus, Cs, k):
alpha=source_alpha
alpha=alpha/1e3 # convert mrads to rads
var1=-1*((np.pi*alpha)/wavelength)**2
EsEnv= np.exp(var1*(Cs*10*(wavelength)**3*k**3+defocus*wavelength*k)**2)
return EsEnv
# Calculate the envelope component due to the chromatic aberration
def coherence_Env(IObj_stability, HT_stability, source_spread, Cc, voltage, wavelength, k):
objstability = IObj_stability/1e6
envelope_voltage = voltage #// in volts
ht_stability = HT_stability/1e7 # in ppm
source_energy_spread = source_spread
source_relative_energy_spread = source_energy_spread/envelope_voltage
Cc=Cc*1e7 #// convert to nm
delta=Cc*(4*(objstability)**2+(source_relative_energy_spread)**2+(ht_stability)**2)**0.5
EcEnv=np.exp(-0.5*(np.pi*(wavelength)*delta)**2*k**4)
return EcEnv
#Compute the drift envelope function
def drift_Env(drift_rate,k):
drift=drift_rate
edEnv=np.exp(-(1/6)*(np.pi*k*drift)**2)
return edEnv
Env_source = source_Env(wavelength, source_alpha, defocus, C_s, u)
Env_coherence = coherence_Env(IObj_stability, HT_stability, source_spread, C_c, acceleration_voltage_V, wavelength, u)
Env_drift = drift_Env(drift_rate, u)
Env_total = Env_source*Env_coherence*Env_drift
ctf = calculate_ctf(wavelength, C_s, defocus,u)
##Plot CTF and Envelope functions
plt.figure(figsize=(8,5))
plt.title(f'CTF for defocus {defocus:.1f} $\AA$')
#plt.plot(k,np.abs(ctf), label = f'ctf df = {defocus:.1f}')
plt.plot(u,(ctf*Env_total), c='blue', label = f'ctf dampened')
plt.plot(u,(Env_total), c='red', label = f'envelope all')
plt.plot(u,(-Env_total), c='red')
plt.plot(u,(Env_coherence), c='green', label = f'envelope coherence')
plt.plot(u,(-Env_coherence), c='green')
plt.plot(u,(Env_source), c='orange', label = f'envelope source')
plt.plot(u,(-Env_source), c='orange')
plt.plot(u,(Env_drift), c='purple', label = f'envelope drift')
plt.plot(u,(-Env_drift), c='purple')
plt.plot([0,20], [0,0], c='black')
plt.plot([1/scherzer_resolution,1/scherzer_resolution],[0,1],linewidth = 3)
plt.legend(loc=1)
plt.xlim(0,1)
#plt.ylim(0)
print(f'Information limit is {1/u[np.argmin(np.abs(Env_total-np.exp(-1)))]:.2f} Ang ')
Information limit is 2.08 Ang
The Diffractogram will give us the intensity and so we will get the squared of the CTF
##Plot CTF and Envelope functions
plt.figure(figsize=(8,4))
plt.title(f'CTF for defocus {defocus/10 :.1f}nm')
#plt.plot(k,np.abs(ctf), label = f'ctf df = {defocus:.1f}')
plt.plot(u,(ctf*Env_total)**2,c='b', label = f'ctf dampened')
plt.plot(u,(Env_total)**2,c='r', label = f'envelope all')
plt.plot(u,(Env_coherence)**2,c='g', label = f'envelope coherence')
plt.plot(u,(Env_source)**2,c='orange', label = f'envelope source')
plt.plot(u,(Env_drift)**2, c='purple', label = f'envelope drift')
plt.plot([1/scherzer_resolution,1/scherzer_resolution],[0,1],linewidth = 3)
plt.xlabel('angle (1/$\AA$)')
plt.legend(loc=1)
plt.xlim(0,1)
plt.ylim(0,1.1)
print(f'Information limit is {1/u[np.argmin(np.abs(Env_total-np.exp(-1)))]:.2f} Ang ')
Information limit is 2.08 Ang
3.3.9. Conclusion:#
The contrast transfer function allows us to evaluate the resolution capabilities of a TEM.
In the Zeiss Libra 200MC the point resolution is given by the relative high spherical aberration of \(C_s = 2.2\)mm.
The information limit is dominated by the energy spread of the electron source (which is excellent).
The diffractogram (Fourier Transform) of an amorphous sample allows to directly determine the aberrations:
determine defocus and set
correct astigmatism
These parameters are important for image interpretation and image simulations.