Live notebook
You can run this notebook in a live session or view it on Github.
Kinematical EBSD simulations#
In this tutorial, we will perform kinematical Kikuchi pattern simulations of nickel, a variant of the \(\sigma\)-phase (Fe, Cr) in steels, and silicon carbide 6H.
We can obtain kinematical master patterns using KikuchiPatternSimulator.calculate_master_pattern(), provided that the simulator is created from a ReciprocalLatticeVector instance that satisfy these conditions:
The unit cell, i.e. the
structure
used to create thephase
used inReciprocalLatticeVector
, must have all asymmetric atom positions filled, which can either be done by creating aPhase
instance from a valid CIF file with Phase.from_cif() or calling ReciprocalLatticeVector.sanitise_phase()The atoms in the
structure
have their elements described by the symbol (Ni), not by the atomic number (28)The lattice parameters are in given in Ångström.
Kinematical structure factors \(F_{hkl}\) have been calculated with ReciprocalLatticeVector.calculate_structure_factor()
Bragg angles \(\theta_B\) have been calculated with ReciprocalLatticeVector.calculate_theta()
Let’s import the necessary libraries
[1]:
# Exchange inline for notebook or qt5 (from pyqt) for interactive plotting
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pyvista
from diffpy.structure import Atom, Lattice, Structure
from diffsims.crystallography import ReciprocalLatticeVector
import hyperspy.api as hs
import kikuchipy as kp
from orix.crystal_map import Phase
# Plotting parameters
plt.rcParams.update(
{"figure.figsize": (10, 10), "font.size": 20, "lines.markersize": 10}
)
# See https://docs.pyvista.org/user-guide/jupyter/index.html
pyvista.set_jupyter_backend("panel")
2023-07-24 16:15:44,133 - numexpr.utils - INFO - NumExpr defaulting to 2 threads.
/tmp/ipykernel_3685/2172114549.py:20: PyVistaDeprecationWarning: `panel` backend is deprecated and is planned for future removal.
pyvista.set_jupyter_backend("panel")
Nickel#
We’ll compare our kinematical simulations to dynamical simulations performed with EMsoft (see [Callahan and De Graef, 2013]), since we have a Ni master pattern available in the kikuchipy.data module
[2]:
mp_ni_dyn = kp.data.nickel_ebsd_master_pattern_small(
projection="stereographic"
)
Inspect phase
<name: ni. space group: Fm-3m. point group: m-3m. proper point group: 432. color: tab:blue>
Lattice(a=0.35236, b=0.35236, c=0.35236, alpha=90, beta=90, gamma=90)
Change lattice parameters from nm to Ångström
[4]:
lat_ni = phase_ni.structure.lattice # Shallow copy
lat_ni.setLatPar(lat_ni.a * 10, lat_ni.b * 10, lat_ni.c * 10)
print(phase_ni.structure.lattice)
Lattice(a=3.5236, b=3.5236, c=3.5236, alpha=90, beta=90, gamma=90)
We’ll build up the reflector list by:
Finding all reflectors with a minimal interplanar spacing \(d\)
Keeping those that have a structure factor above 0.5% of the reflector with the highest structure factor
[5]:
rlv_ni = ReciprocalLatticeVector.from_min_dspacing(phase_ni, 0.5)
# Exclude non-allowed reflectors (not available for hexagonal or trigonal
# phases!)
rlv_ni = rlv_ni[rlv_ni.allowed]
rlv_ni = rlv_ni.unique(use_symmetry=True).symmetrise()
Sanitise phase
by completing the unit cell
[6]:
rlv_ni.phase.structure
[6]:
[28 0.000000 0.000000 0.000000 1.0000]
[7]:
rlv_ni.sanitise_phase()
rlv_ni.phase.structure
[7]:
[Ni 0.000000 0.000000 0.000000 1.0000,
Ni 0.000000 0.500000 0.500000 1.0000,
Ni 0.500000 0.000000 0.500000 1.0000,
Ni 0.500000 0.500000 0.000000 1.0000]
We can now calculate the structure factors. Two parametrizations are available, from [Kirkland, 1998] ("xtables"
, the default) or [Lobato and Van Dyck, 2014] ("lobato"
)
[8]:
rlv_ni.calculate_structure_factor()
[9]:
structure_factor_ni = abs(rlv_ni.structure_factor)
rlv_ni = rlv_ni[structure_factor_ni > 0.05 * structure_factor_ni.max()]
rlv_ni.print_table()
h k l d |F|_hkl |F|^2 |F|^2_rel Mult
1 1 1 2.034 11.8 140.0 100.0 8
2 0 0 1.762 10.4 108.2 77.3 6
2 2 0 1.246 7.4 55.0 39.3 12
3 1 1 1.062 6.2 38.6 27.6 24
2 2 2 1.017 5.9 34.7 24.8 8
4 0 0 0.881 4.9 23.9 17.1 6
3 3 1 0.808 4.3 18.8 13.4 24
4 2 0 0.788 4.2 17.4 12.5 24
4 2 2 0.719 3.6 13.3 9.5 24
5 1 1 0.678 3.3 11.1 8.0 24
3 3 3 0.678 3.3 11.1 8.0 8
4 4 0 0.623 2.9 8.6 6.1 12
5 3 1 0.596 2.7 7.4 5.3 48
6 0 0 0.587 2.7 7.1 5.1 6
4 4 2 0.587 2.7 7.1 5.1 24
6 2 0 0.557 2.4 6.0 4.3 24
5 3 3 0.537 2.3 5.3 3.8 24
6 2 2 0.531 2.3 5.1 3.7 24
4 4 4 0.509 2.1 4.4 3.2 8
[10]:
rlv_ni.calculate_theta(20e3)
We can now create our simulator and plot the simulation
[11]:
simulator_ni = kp.simulations.KikuchiPatternSimulator(rlv_ni)
simulator_ni.reflectors.size
[11]:
338
Plotting the band centers with intensities scaled by the structure factor
[12]:
simulator_ni.plot()

Or no scaling (scaling="square"
for the structure factor squared)
[13]:
simulator_ni.plot(scaling=None)

We can also plot the Kikuchi bands, showing both hemispheres, also adding the crystal axes alignment
[14]:
fig = simulator_ni.plot(hemisphere="both", mode="bands", return_figure=True)
ax = fig.axes[0]
ax.scatter(simulator_ni.phase.a_axis, c="r")
ax.scatter(simulator_ni.phase.b_axis, c="g")
ax.scatter(simulator_ni.phase.c_axis, c="b")

The simulation can be plotted in spherical projection as well using Matplotlib, or PyVista provided that it is installed
[15]:
simulator_ni.plot("spherical", mode="bands")

[16]:
# Interactive!
simulator_ni.plot("spherical", mode="bands", backend="pyvista")