{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "xutlJVbJlFxq" }, "source": [ " **Chapter 2: [Diffraction](CH2_00-Diffraction.ipynb)** \n", "\n", "\n", "
\n", "\n", "\n", "\n", "# The Electron\n", "\n", "\n", "[Download](https://raw.githubusercontent.com/gduscher/MSE672-Introduction-to-TEM//main/Diffraction/CH2_01-Electron.ipynb)\n", "\n", "[![OpenInColab](https://colab.research.google.com/assets/colab-badge.svg)](\n", " https://colab.research.google.com/github/gduscher/MSE672-Introduction-to-TEM/blob/main//Diffraction/CH2_01-Electron.ipynb)\n", "\n", "part of\n", "\n", " **[MSE672: Introduction to Transmission Electron Microscopy](../_MSE672_Intro_TEM.ipynb)**\n", "\n", "**Spring 2026**
\n", "by Gerd Duscher\n", "\n", "Microscopy Facilities
\n", "Institute of Advanced Materials & Manufacturing
\n", "Materials Science & Engineering
\n", "The University of Tennessee, Knoxville\n", "\n", "\n", "Background and methods to analysis and quantification of data acquired with transmission electron microscopes.\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "MMTp_lbFlFxu" }, "source": [ "First we load the code to make figures from pyTEMlib\n", "## Import packages for figures and\n", "### Check Installed Packages" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "0utdrnkYlFxv", "outputId": "bfba2cc5-a1d1-426f-a548-aad34509528c" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "done\n" ] } ], "source": [ "import sys\n", "import importlib.metadata\n", "def test_package(package_name):\n", " \"\"\"Test if package exists and returns version or -1\"\"\"\n", " try:\n", " version = importlib.metadata.version(package_name)\n", " except importlib.metadata.PackageNotFoundError:\n", " version = '-1'\n", " return version\n", "\n", "if test_package('pyTEMlib') < '0.2026.1.0':\n", " print('installing pyTEMlib')\n", " !{sys.executable} -m pip install --upgrade pyTEMlib -q\n", "\n", "print('done')" ] }, { "cell_type": "markdown", "metadata": { "id": "CCr5aLWplFxx" }, "source": [ "> Note for Google Colab\n", ">\n", "> **Restart Session** in the **Runtime Menu**\n", "\n", "### Load the plotting and figure packages" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "id": "l7FfJuYGlFxz" }, "outputs": [], "source": [ "%matplotlib widget\n", "import matplotlib.pylab as plt\n", "import numpy as np\n", "import sys\n", "if 'google.colab' in sys.modules:\n", " from google.colab import output\n", " output.enable_custom_widget_manager()\n", "\n", "import scipy # we will use the constants part only\n", "import pyTEMlib" ] }, { "cell_type": "markdown", "metadata": { "id": "oFXzlKKKlFxz" }, "source": [ "## Interaction of Common Particles with Matter\n", "\n", "We generally use electron, photons, and neutrons for diffraction/scattering\n", "experiments.\n", "\n", "These particles interact with differently with matter:\n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
X-rays$\\leftrightarrow$electron density
neutrons$\\leftrightarrow$mass of nucleus
neutrons$\\leftrightarrow$magnetic moment
electrons$\\leftrightarrow$screened charge of nucleus
\n", "\n", "We will deal with the nature of electrons more closely in the following" ] }, { "cell_type": "markdown", "metadata": { "id": "3QIX30tFlFx1" }, "source": [ "## Non-relativistic de Broglie Wavelength\n", "\n", "\n", "The electron is a elementary particle with spin $\\frac{1}{2}$ (lepton).\n", "\n", "\n", "**Non--relativistic De Broglie wavelength** of electron:\n", "\n", "$\\lambda = \\frac{h}{p} = \\frac{h}{\\sqrt{2m_0E_{kin}}} \\approx \\frac{1.22}{\\sqrt{E_{kin}}}$\n", "\n", "\n", "E is the kinetic energy of the electron: $E_{kin} = eU $ [eV].\n", "\n", "The wave length in a TEM is usually\n", "a couple of picometers . This is a\n", "factor of 100 smaller than your\n", "XRD-source.\n", "\n", "Obvioulsy, we are in the wave picture right now.\n", "\n", "Change to 300 keV acceleration voltage and look at the relativ espeed to the speed of light $c$." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "l9-Bzp_BlFx2", "outputId": "d5463841-753c-4613-94b3-60ed68c6c0cd" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Classic wave length is 3.88 pm for acceleration voltage 100.0 kV\n", " which is a velocity of 187553726.08 m/s or 62.56% of the speed of light\n" ] } ], "source": [ "# --------- input ---------------------------\n", "acceleration_voltage_V = U = 100.0 * 1000.0 #V\n", "# --------------------------------------------\n", "## energy\n", "E_kin = acceleration_voltage_V * scipy.constants.elementary_charge\n", "h = scipy.constants.Planck\n", "m0 = scipy.constants.electron_mass\n", "c = scipy.constants.speed_of_light\n", "\n", "wave_length_m = h/np.sqrt(2*m0*E_kin) # non-relativistic wavelength in m\n", "\n", "# # please note that we will keep all length units in Angstrom if possible.\n", "# # otherwise we use only SI units!!!\n", "wave_length_A = wave_length_m *1e10 # now in Angstrom\n", "\n", "print(f'Classic wave length is {wave_length_A*100.:.2f} pm for acceleration voltage {acceleration_voltage_V/1000.:.1f} kV')\n", "# Notice that we change units in the output to make them most readable.\n", "\n", "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')" ] }, { "cell_type": "markdown", "metadata": { "id": "HZYqUCO9lFx5" }, "source": [ "## Relativistic Correction\n", "In the table below we see that the speeds of the electron is rather close to the speed of light $c$\n", "\n", "The formula for relativistic corrected wavelength is:\n", "$\\lambda = \\frac{h}{\\sqrt{2m_e E_{kin} *(1+\\frac{E_{kin}}{2 m_e c^2})}}$\n", "\n", "**Please note:** All units are internally in SI units: kg, s, V, J, except the length wihich is in nm!\n", "\n", "We multiply with the appropriate factors for the output" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "2gTh8QYtlFx7", "outputId": "66e938b4-1181-4f93-b7d6-8f440abc8e41" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The relativistically corrected wave length is 1.97 pm for acceleration voltage 300.0 kV\n" ] } ], "source": [ "# ---------Input: Acceleration Voltage --\n", "E0 = acceleration_voltage_V = 300.0 *1000.0 # V\n", "# ---------------------------------------\n", "E_kin = acceleration_voltage_V * scipy.constants.elementary_charge\n", "h = scipy.constants.Planck\n", "m0 = scipy.constants.electron_mass\n", "c = scipy.constants.speed_of_light\n", "\n", "#relativisitic wavelength\n", "wave_length = h/np.sqrt(2* m0 * E_kin * (1 + E_kin / (2 * m0 * c**2))) #in m\n", "\n", "print(f'The relativistically corrected wave length is {wave_length*1e12:.2f} pm for acceleration voltage {acceleration_voltage_V/1000:.1f} kV')" ] }, { "cell_type": "markdown", "metadata": { "id": "oHH7-5dElFx8" }, "source": [ "100kV : $\\lambda$ = 4 pm $<$ than diameter of an atom\n", "\n", "The relativistic parameters are:\n", "\n", "\n", "|E (keV)|$\\lambda$ (pm) | M/m$_0$ | v/c|\n", "--------|---------------|---------|----|\n", "|10 | 12.2 | 1.0796 | 0.1950 |\n", "|30 | 6.98 | 1.129 | 0.3284 |\n", "|100 | 3.70 | 1.1957 | 0.5482|\n", "|200 | 2.51 | 1.3914 | 0.6953|\n", "|400 | 1.64 | 1.7828 | 0.8275 |\n", "|1000 | 0.87 | 2.9569 | 0.9411|\n", "\n", "The same functionality (and code) is used in the kinematic_scattering library and we can test the values of above table.\n", "\n", "Please change the acceleration voltage (**acceleration_voltage_V**) above.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "CzJ2-8xalFx-" }, "source": [ "\n", "### Relativistic velocity\n", "\n", "$$\\frac{v^2}{c^2} = \\frac{E_{kin}(E_{kin}+2m_e c^2)}{(E_{kin}+m_e c^2)^2}$$" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "PBhSwxaWlFx-", "outputId": "3b69c1bf-370b-4d3a-ddc2-32d9262506f9" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "For an acceleration voltage of 300keV: \n", "The classic velocity of the electron is 324852582.72 m/s or 108.36% of the speed of light\n", "The relativistic velocity of the electron is 232796486.20 m/s or 77.65% of the speed of light\n" ] } ], "source": [ "v = np.sqrt(E_kin * (E_kin + 2 * m0 * c**2)/(E_kin + m0 * c**2) **2)*c\n", "\n", "print(f'For an acceleration voltage of {acceleration_voltage_V/1000:.0f}keV: ')\n", "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')\n", "print(f'The relativistic velocity of the electron is {v:.2f} m/s or {v/c*100:.2f}% of the speed of light')" ] }, { "cell_type": "markdown", "metadata": { "id": "ALDCK6JXlFyA" }, "source": [ "## That means that the resolution is not limited by the wavelength!\n", "The formula for relativistic corrected wavelength is:\n", "\n", "$\\lambda = \\frac{h}{\\sqrt{2m_e E_{kin} *(1+\\frac{E_{kin}}{2 m_e c^2})}}$" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "P3eVwTeClFyA", "outputId": "91659f3f-0a1f-4ce8-a25a-f5d77e425b68" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The relativistically corrected wave length is 1.97 pm for acceleration voltage 300.0 kV\n" ] } ], "source": [ "# ----- Input -----\n", "acceleration_voltage= 300 * 1000.0\n", "# -------------------\n", "\n", "wave_length = pyTEMlib.diffraction_tools.get_wavelength(acceleration_voltage, unit='A')\n", "print(f'The relativistically corrected wave length is {wave_length*1e2:.2f} pm for acceleration voltage {acceleration_voltage/1000:.1f} kV')\n", "\n", "# Wavelength in Angstrom\n", "def get_wavelength(acceleration_voltage):\n", " \"\"\"\n", " Calculates the relativistic corrected de Broglie wave length of an electron\n", "\n", " Input:\n", " ------\n", " acceleration voltage in volt\n", " Output:\n", " -------\n", " wave length in Angstrom\n", " \"\"\"\n", " E = acceleration_voltage * scipy.constants.elementary_charge\n", " h = scipy.constants.Planck\n", " m0 = scipy.constants.electron_mass\n", " c = scipy.constants.speed_of_light\n", "\n", " wavelength = h / np.sqrt(2 * m0 * E * (1 + (E / (2 * m0 * c ** 2))))\n", " return wavelength * 10**10\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "IUgDFd87lFyB", "outputId": "773650bb-df5a-4ba0-a157-8ecce86468b8" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function get_wavelength in module pyTEMlib.utilities:\n", "\n", "get_wavelength(acceleration_voltage: float, unit: str = 'm') -> float\n", " Calculates the relativistic corrected de Broglie wavelength of an electron in meter\n", " and converts it to the desired unit (m, mm, μm, nm, A, Å, pm)\n", "\n", " Parameter:\n", " ---------\n", " acceleration_voltage: float\n", " acceleration voltage in volt\n", " unit: str\n", " unit of the wavelength, default is meter ('m')\n", " Returns:\n", " -------\n", " wavelength: float\n", " wave length in units given, default meter\n", "\n" ] } ], "source": [ "help(pyTEMlib.diffraction_tools.get_wavelength)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "14A9VNZmlFyD", "outputId": "97e71229-6b2b-4cda-a356-423a7a72d268", "scrolled": true, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on package pyTEMlib.diffraction_tools in pyTEMlib:\n", "\n", "NAME\n", " pyTEMlib.diffraction_tools\n", "\n", "DESCRIPTION\n", " diffraction tools subpackage\n", " A collection of tools to analyze diffraction data\n", " part of pyTEMlib\n", " author: Gerd Duscher, UTK\n", "\n", "PACKAGE CONTENTS\n", " basic\n", " diffraction_plot\n", " dynamic\n", " kinematic\n", " kinematic copy\n", "\n", "FUNCTIONS\n", " calculate_holz(dif)\n", " Calculate HOLZ lines (of allowed reflections)\n", "\n", " center_of_laue_circle(atoms, tags)\n", " Center of Laue circle in microscope coordinates\n", "\n", " check_sanity(atoms, verbose_level=0)\n", " Check sanity of input parameters\n", "\n", " example(verbose=True)\n", " same as zuo_fig_3_18\n", "\n", " feq(element, q)\n", " Atomic form factor parametrized in 1/Angstrom\n", "\n", " find_angles(zone)\n", " Microscope stage coordinates of zone\n", "\n", " find_nearest_zone_axis(tags)\n", " Test all zone axis up to a maximum of hkl_max\n", "\n", " gaussian(xx, pp)\n", " Gaussian function\n", "\n", " get_all_g_vectors(hkl_max, atoms)\n", " Get all reflections up to a maximum Miller index\n", "\n", " get_all_miller_indices(hkl_max)\n", " Get all Miller indices up to hkl_max\n", "\n", " get_allowed_reflections(structure, verbose=False)\n", " Calculate allowed reflections of a crystal structure\n", "\n", " get_bragg_reflections(atoms, in_tags, verbose=False)\n", " sort reflection in allowed and forbidden\n", "\n", " get_cylinder_coordinates(zone_hkl, g, k0_magnitude)\n", " Get cylindrical coordinates of g vectors around zone axis\n", "\n", " get_dynamically_activated(out_tags, verbose=False)\n", " Get dynamically activated forbidden reflections\n", "\n", " get_form_factor(element, q)\n", " Atomic form factor parametrized in 1/Angstrom but converted to 1/Angstrom\n", "\n", " The atomic form factor is from reKirkland: Advanced Computing in\n", " Electron Microscopy 2nd edition, Appendix C.\n", " From Appendix C of Kirkland, \"Advanced Computing in Electron Microscopy\", 3rd ed.\n", " Calculation of electron form factor for specific q:\n", " Using equation Kirkland C.15\n", "\n", " Parameters\n", " ----------\n", " element: string\n", " element name\n", " q: float or numpy.ndarray\n", " magnitude(s) of scattering vector(s) in 1/Angstrom -- (=> exp(-i*g.r),\n", " physics negative convention)\n", "\n", " Returns\n", " -------\n", " fL+fG: float\n", " atomic scattering vector\n", "\n", " get_incident_wave_vector(atoms, acceleration_voltage, verbose=False)\n", " Incident wave vector K0 in vacuum and material\n", "\n", " get_metric_tensor(matrix)\n", " The metric tensor of the lattice.\n", "\n", " get_propagator(\n", " size_in_pixel,\n", " delta_z,\n", " number_layers,\n", " wavelength,\n", " field_of_view,\n", " bandwidth_factor,\n", " verbose=True\n", " )\n", " Get propagator function\n", "\n", " has to be convoluted with wave function after transmission\n", "\n", " Parameter\n", " ---------\n", " size_in_pixel: int\n", " number of pixels of one axis in square image\n", " delta_z: float\n", " distance between layers\n", " number_layers: int\n", " number of layers to make a propagator\n", " wavelength: float\n", " wavelength of incident electrons\n", " field_of_view: float\n", " field of view of image\n", " bandwidth_factor: float\n", " relative bandwidth to avoid anti-aliasing\n", "\n", " Returns\n", " -------\n", " propagator: complex numpy array (layers x size_in_pixel x size_in_pixel)\n", "\n", " get_reflection_families(hkl_sorted, g_sorted, f_sorted, verbose=False)\n", " Determine reflection families and multiplicity\n", "\n", " get_structure_factors(atoms, g_hkl)\n", " Get structure factors for given reciprocal lattice points g_hkl\n", "\n", " get_transmission(potential, acceleration_voltage)\n", " Get transmission function\n", "\n", " has to be multiplied in real space with wave function\n", "\n", " Parameter\n", " ---------\n", " potential: numpy array (nxn)\n", " potential of a layer\n", " acceleration_voltage: float\n", " acceleration voltage in V\n", "\n", " Returns\n", " -------\n", " complex numpy array (nxn)\n", "\n", " get_unit_cell(atoms, tags)\n", " Unit cell and reciprocal unit cell\n", "\n", " get_wavelength(acceleration_voltage: float, unit: str = 'm') -> float\n", " Calculates the relativistic corrected de Broglie wavelength of an electron in meter\n", " and converts it to the desired unit (m, mm, μm, nm, A, Å, pm)\n", "\n", " Parameter:\n", " ---------\n", " acceleration_voltage: float\n", " acceleration voltage in volt\n", " unit: str\n", " unit of the wavelength, default is meter ('m')\n", " Returns:\n", " -------\n", " wavelength: float\n", " wave length in units given, default meter\n", "\n", " get_zone_rotation(tags)\n", " zone axis in global coordinate system\n", "\n", " interaction_parameter(acceleration_voltage)\n", " Calculates interaction parameter sigma\n", "\n", " Parameter\n", " ---------\n", " acceleration_voltage: float\n", " acceleration voltage in volt\n", "\n", " Returns\n", " -------\n", " interaction parameter: float\n", " interaction parameter (dimensionless)\n", "\n", " make_chi(theta, phi, aberrations)\n", " ###\n", " # Aberration function chi\n", " ###\n", " phi and theta are meshgrids of the angles in polar coordinates.\n", " aberrations is a dictionary with the aberrations coefficients\n", " Note: an empty aberration dictionary will give you a perfect aberration\n", "\n", " make_pretty_labels(hkls, hex_label=False)\n", " Make pretty labels\n", "\n", " Parameters\n", " ----------\n", " hkls: np.ndarray\n", " a numpy array with all the Miller indices to be labeled\n", " hex_label: boolean - optional\n", " if True this will make for Miller indices.\n", "\n", " Returns\n", " -------\n", " hkl_label: list\n", " list of labels in Latex format\n", "\n", " multi_slice(\n", " wave,\n", " number_of_unit_cell_z,\n", " number_layers,\n", " transmission,\n", " propagator\n", " )\n", " Multi-Slice Calculation\n", "\n", " The wave function will be changed iteratively\n", "\n", " Parameters\n", " ----------\n", " wave: complex numpy array (nxn)\n", " starting wave function\n", " number_of_unit_cell_z: int\n", " this gives the thickness in multiples of c lattice parameter\n", " number_layers: int\n", " number of layers per unit cell\n", " transmission: complex numpy array\n", " transmission function\n", " propagator: complex numpy array\n", " propagator function\n", "\n", " Returns\n", " -------\n", " complex numpy array\n", "\n", " objective_lens_function(ab, nx, ny, field_of_view, aperture_size=10)\n", " Objective len function to be convoluted with exit wave to derive image function\n", "\n", " Parameter:\n", " ----------\n", " ab: dict\n", " aberrations in nm should at least contain defocus (C10), and spherical aberration (C30)\n", " nx: int\n", " number of pixel in x direction\n", " ny: int\n", " number of pixel in y direction\n", " field_of_view: float\n", " field of view of potential\n", " wavelength: float\n", " wavelength in nm\n", " aperture_size: float\n", " aperture size in 1/nm\n", "\n", " Returns:\n", " --------\n", " object function: numpy array (nx x ny)\n", " extent: list\n", "\n", " output_verbose(atoms, tags)\n", " Verbose output of experimental parameters\n", "\n", " plot_cbed_parameter()\n", " Plot CBED pattern parameters\n", "\n", " plot_diffraction_pattern(\n", " atoms,\n", " diffraction_pattern=None,\n", " unit='mrad',\n", " verbose=False\n", " )\n", " Plot of spot diffraction pattern with matplotlib\n", "\n", " Parameters\n", " ----------\n", " atoms: dictionary or ase.Atoms object\n", " information stored as dictionary either directly or in info attribute of ase.Atoms object\n", " diffraction_pattern: None or sidpy.Dataset\n", " diffraction pattern in background\n", " unit: str default: 'mrad'\n", " unit for plotting, either 'mrad' or '1/nm'\n", "\n", " Returns\n", " -------\n", " fig: matplotlib figure\n", " reference to matplotlib figure\n", "\n", " plot_holz_parameter()\n", " Plot HOLZ pattern parameters\n", "\n", " plot_kikuchi(grey=False)\n", " Plot Kikuchi pattern parameters\n", "\n", " plot_reciprocal_unit_cell_2d(atoms)\n", " Plot # unit cell in reciprocal space in 2D\n", "\n", " plot_ring_pattern(atoms, diffraction_pattern=None)\n", " Plot of ring diffraction pattern with matplotlib\n", "\n", " Parameters\n", " ----------\n", " atoms: dictionary or sidpy.Dataset\n", " information stored as dictionary either directly or in metadata attribute of sidpy.Dataset\n", " grey: bool\n", " plotting in greyscale if True\n", "\n", " Returns\n", " -------\n", " fig: matplotlib figure\n", " reference to matplotlib figure\n", "\n", " plot_saed_parameter(gray=False)\n", " Plot SAED pattern parameters\n", "\n", " plotting_coordinates(\n", " g,\n", " rotation=0.0,\n", " laue_circle=[0, 0],\n", " feature='spot',\n", " k0=None\n", " )\n", " Calculate plotting coordinates for spots and lines\n", " Parameters\n", " ----------\n", " g : numpy array\n", " array of g-vectors in (cylinderical coordinates in rad)\n", " rotation : float\n", " rotation angle in radians\n", " laue_circle : list\n", " position of laue circle in (x,y)\n", " feature : str\n", " 'spot' or 'line' for HOLZ/Kikuchi lines\n", " k0 : float or None\n", " wave vector in 1/nm, if None use g in mrad\n", "\n", " Returns\n", " -------\n", " numpy array\n", " array of plotting coordinates in (x,y) for spots and (x,y,slope) for lines\n", "\n", " potential_1dim(element, r)\n", " Calculates the projected potential of an atom of element\n", "\n", " The projected potential will be in units of V nm^2,\n", " however, internally we will use Angstrom instead of nm!\n", " The basis for these calculations are the atomic form factors of Kirkland 2𝑛𝑑 edition\n", " following the equation in Appendix C page 252.\n", "\n", " Parameter\n", " ---------\n", " element: str\n", " name of 'element\n", " r: numpy array [nxn]\n", " impact parameters (distances from atom position) in nm\n", "\n", " Returns\n", " -------\n", " numpy array (nxn)\n", " projected potential in units of V nm^2\n", "\n", " potential_2dim(element, nx, ny, n_cell_x, n_cell_y, lattice_parameter, base)\n", " Make a super-cell with potentials\n", "\n", " Limitation is that we only place atom potential with single pixel resolution\n", "\n", " read_poscar(filename)\n", " Deprecated - use pyTEMlib.file_tools.read_poscar\n", "\n", " ring_pattern_calculation(structure, verbose=False)\n", " Calculate the ring diffraction pattern of a crystal structure\n", "\n", " Parameters\n", " ----------\n", " structure: ase.Atoms or sidpy.Dataset\n", " crystal structure\n", " verbose: verbose print-outs\n", " set to False\n", " Returns\n", " -------\n", " tags: dict\n", " dictionary with diffraction information added\n", "\n", " scattering_matrix(tags, verbose_level=1)\n", " Scattering matrix\n", "\n", " scattering_profiles(diff_pattern, center)\n", " Determine scattering profiles from diffraction pattern\n", "\n", " Parameters\n", " ----------\n", " diff_pattern : Dataset\n", " 2D diffraction pattern\n", " center : tuple\n", " center of the diffraction pattern (x,y) in pixels\n", " Returns\n", " -------\n", " out_tags : dict\n", " dictionary with the following entries:\n", " 'center' : center of the diffraction pattern (x,y) in pixels\n", " 'polar_projection' : 2D array with the polar projection (r, theta)\n", " 'radial_average' : 1D array with the radial average\n", "\n", " set_center(main_dataset, center, scale=None)\n", " Set the u and v axes of a diffraction pattern dataset to center on origin\n", "\n", " stage_rotation_matrix(alpha, beta, gamma=0.0)\n", " Microscope stage coordinate system\n", "\n", " warp(diff, center)\n", " Define original polar grid\n", "\n", " Parameter:\n", " ----------\n", " diff: sidpy object or numpy ndarray of\n", " diffraction pattern\n", " center: list or numpy array of length 2\n", " coordinates of center in pixel\n", "\n", " Return:\n", " ------\n", " numpy array of diffraction pattern in polar coordinates\n", "\n", " zone_mistilt(zone, angles)\n", " Rotation of zone axis by mistilt\n", "\n", " Parameters\n", " ----------\n", " zone: list or numpy array of int\n", " zone axis in Miller indices\n", " angles: ist or numpy array of float\n", " list of mistilt angles in degree\n", "\n", " Returns\n", " -------\n", " new_zone_axis: np.ndarray (3)\n", " new tilted zone axis\n", "\n", "DATA\n", " __all__ = ['read_poscar', 'example', 'zone_mistilt', 'check_sanity', '...\n", "\n", "FILE\n", " c:\\users\\gduscher\\appdata\\local\\anaconda3\\lib\\site-packages\\pytemlib\\diffraction_tools\\__init__.py\n", "\n", "\n" ] } ], "source": [ "help(pyTEMlib.diffraction_tools)" ] }, { "cell_type": "markdown", "metadata": { "id": "nfhVcWJPlFyE" }, "source": [ "## Particle Flux and Current\n", "\n", "It is important todetermine the order of magitude of how many electrons are hitting the sample.\n", "\n", "The electron sources deliver in the order of $\\mu$A current, but most of these electrons are not used.\n", "\n", "In a modern electron microscope, we talk about a range of 1pA to 1nA in the electron beam.\n", "\n", "We start with the defition of an Ampere:\n", "$$A = \\frac{C}{s}$$\n", "\n", "That definition is enough to calculate the number ofelectron per time unit (flux)." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "-js6jZ1dlFyF", "outputId": "4191f46d-0552-4f1f-8175-630e1bc327a7" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " elementary charge: 1.6022e-19 C\n", "\n", " 1pA is 6.24e+06 electrons/s or 6242 electrons/ms\n", " 10pA is 6.24e+07 electrons/s\n", "100pA is 6.24e+08 electrons/s\n", "\n", " at 10pA an electron will hit the sample every 16.02 ns \n" ] } ], "source": [ "print(f\" elementary charge: {scipy.constants.physical_constants['elementary charge'][0]:.5g} {scipy.constants.physical_constants['elementary charge'][1]}\")\n", "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')\n", "print(f' 10pA is {10e-12/scipy.constants.elementary_charge:.3} electrons/s')\n", "print(f'100pA is {100e-12/scipy.constants.elementary_charge*1 :.3} electrons/s')\n", "\n", "print(f'\\n at 10pA an electron will hit the sample every {scipy.constants.elementary_charge/10e-12 * 1e9:.2f} ns ')" ] }, { "cell_type": "markdown", "metadata": { "id": "Ux_x_DjHlFyG" }, "source": [ "We see that we have much lower fluence in the TEM than in a laser (how could they do femtosecond pulses otherwise).\n" ] }, { "cell_type": "markdown", "metadata": { "id": "xWaZ3pTolFyH" }, "source": [ "### Question\n", "How long does one have to integrate a detector to register 1 electron with an electron beam of 1.6pA?" ] }, { "cell_type": "markdown", "metadata": { "id": "-VQWqMG5lFyH" }, "source": [ "## Navigation\n", "- **Back Chapter 1: [Introduction](../Introduction/CH1_00-Introduction.ipynb)** \n", "- **Next: [Atomic Form Factor](CH2_02-Atomic_Form_Factor.ipynb)** \n", "- **Chapter 2: [Diffraction](CH2_00-Diffraction.ipynb)** \n", "- **List of Content: [Front](../_MSE672_Intro_TEM.ipynb)** " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "f_nmEWBPlFyI" }, "outputs": [], "source": [] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.5" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "472.5px", "left": "204px", "top": "194.45px", "width": "168.5px" }, "toc_section_display": true, "toc_window_display": true }, "vscode": { "interpreter": { "hash": "838e0debddb5b6f29d3d8c39ba50ae8c51920a564d3bac000e89375a158a81de" } } }, "nbformat": 4, "nbformat_minor": 4 }