{ "cells": [ { "cell_type": "markdown", "metadata": { "nbsphinx": "hidden" }, "source": [ "This notebook is part of the `kikuchipy` documentation https://kikuchipy.org.\n", "Links to the documentation won't work from the notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Kikuchi pattern simulations\n", "\n", "This section explains how to inspect and visualize the results from EBSD\n", "indexing by plotting Kikuchi lines and zone axes onto an EBSD signal. We\n", "consider this a *geometrical* EBSD simulation, since it's only positions of\n", "Kikuchi lines and zone axes that are computed. These simulations are based on\n", "the work by Aimo Winkelmann in the supplementary material to\n", "Britton et al. (2016).\n", "\n", "We'll also show how to perform kinematical Kikuchi pattern simulations.\n", "\n", "Let's import the necessary libraries and a small (3, 3) Nickel EBSD test data\n", "set" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Exchange inline for notebook or qt5 (from pyqt) for interactive plotting\n", "%matplotlib inline\n", "\n", "import tempfile\n", "\n", "from diffpy.structure import Atom, Lattice, Structure\n", "from diffsims.crystallography import ReciprocalLatticeVector\n", "import hyperspy.api as hs\n", "import matplotlib\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from orix.crystal_map import Phase\n", "from orix.quaternion import Rotation\n", "import kikuchipy as kp\n", "import pyvista\n", "\n", "\n", "# Plotting parameters\n", "plt.rcParams.update(\n", " {\"figure.figsize\": (10, 10), \"font.size\": 20, \"lines.markersize\": 10}\n", ")\n", "pyvista.global_theme.window_size = [700, 700]\n", "pyvista.set_jupyter_backend(\"pythreejs\")\n", "\n", "s = kp.data.nickel_ebsd_small() # Use kp.load(\"data.h5\") to load your own data\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Geometrical simulations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's enhance the Kikuchi bands by removing the static and dynamic backgrounds" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s.remove_static_background()\n", "s.remove_dynamic_background()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_ = hs.plot.plot_images(\n", " s, axes_decor=None, label=None, colorbar=False, tight_layout=True\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To project Kikuchi lines and zone axes onto our detector, we need\n", "\n", "1. a description of the crystal phase\n", "\n", "2. the set of Kikuchi bands to consider, e.g. the sets of planes {111}, {200},\n", " {220}, and {311}\n", "\n", "3. the crystal orientations with respect to the reference frame\n", "\n", "4. the position of the detector with respect to the sample, in the form of a\n", " sample-detector model which includes the sample and detector tilt and the\n", " projection center (shortes distance from the source point on the\n", " sample to the detector), given here as (PC$_x$, PC$_y$, PC$_z$)\n", "\n", "We'll store the crystal phase information in an\n", "[orix.crystal_map.Phase](https://orix.readthedocs.io/en/stable/reference.html#orix.crystal_map.Phase)\n", "instance" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phase = Phase(\n", " space_group=225,\n", " structure=Structure(\n", " atoms=[Atom(\"Ni\", [0, 0, 0])], lattice=Lattice(3.52, 3.52, 3.52, 90, 90, 90)\n", " ),\n", ")\n", "\n", "print(phase)\n", "print(phase.structure)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll build up the reflector list using\n", "[diffsims.crystallography.ReciprocalLatticeVector](https://diffsims.readthedocs.io/en/latest/reference.html#diffsims.crystallography.ReciprocalLatticeVector)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref = ReciprocalLatticeVector(\n", " phase=phase, hkl=[[1, 1, 1], [2, 0, 0], [2, 2, 0], [3, 1, 1]]\n", ")\n", "ref" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll obtain the symmetrically equivalent vectors and plot each family of\n", "vectors in a distinct colour in the stereographic projection" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref = ref.symmetrise().unique()\n", "ref.size" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref.print_table()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Dictionary with {hkl} as key and indices into `ref` as values\n", "hkl_sets = ref.get_hkl_sets()\n", "hkl_sets" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hkl_colors = np.zeros((ref.size, 3))\n", "for idx, color in zip(\n", " hkl_sets.values(),\n", " [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0]], # Red, green, blue, yellow\n", "):\n", " hkl_colors[idx] = color" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hkl_labels = []\n", "for hkl in ref.hkl.round(0).astype(int):\n", " hkl_labels.append(str(hkl).replace(\"[\", \"(\").replace(\"]\", \")\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref.scatter(c=hkl_colors, grid=True, ec=\"k\", vector_labels=hkl_labels)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also plot the plane traces, i.e. the Kikuchi lines, in both hemispheres\n", "(they are identical for Ni)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref.draw_circle(\n", " color=hkl_colors, hemisphere=\"both\", figure_kwargs=dict(figsize=(15, 10))\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We know from [pattern matching](pattern_matching.ipynb) of these nine patterns\n", "to dynamically simulated patterns of orientations uniformly\n", "distributed in the orientation space of the proper point group $432$, that they\n", "come from two grains with orientations of about $(\\phi_1, \\Phi, \\phi_2) =\n", "(80^{\\circ}, 34^{\\circ}, -90^{\\circ})$ and $(\\phi_1, \\Phi, \\phi_2) =\n", "(115^{\\circ}, 27^{\\circ}, -95^{\\circ})$. We store these orientations in an\n", "[orix.quaternion.Rotation](https://orix.readthedocs.io/en/stable/reference.html#orix.quaternion.Rotation)\n", "instance" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "grain1 = np.deg2rad((80, 34, -90))\n", "grain2 = np.deg2rad((115, 27, -95))\n", "rot = Rotation.from_euler(\n", " [[grain1, grain2, grain2], [grain1, grain2, grain2], [grain1, grain2, grain2]]\n", ")\n", "rot" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We describe the sample-detector model in an\n", "[kikuchipy.detectors.EBSDDetector](../reference.rst#kikuchipy.detectors.EBSDDetector)\n", "instance. From Hough indexing we know the projection center to be, in the EDAX\n", "TSL convention (see the [reference frame](reference_frames.rst) guide for the\n", "various conventions and more details on the use of the sample-detector model),\n", "$(x^{*}, y^{*}, z^{*}) = (0.421, 0.7794, 0.5049)$. The sample was tilted\n", "$70^{\\circ}$ about the microscope X direction towards the detector, and the\n", "detector normal was orthogonal to the optical axis (beam direction)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "detector = kp.detectors.EBSDDetector(\n", " shape=s.axes_manager.signal_shape[::-1],\n", " sample_tilt=70,\n", " pc=[0.421, 0.7794, 0.5049],\n", " convention=\"edax\",\n", ")\n", "detector" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the projection center gets converted internally to the Bruker\n", "convention.\n", "\n", "Now we're ready to create geometrical simulations. We create simulations using\n", "the\n", "[kikuchipy.simulations.KikuchiPatternSimulator](../reference.rst#kikuchipy.simulations.KikuchiPatternSimulator),\n", "which takes the reflectors as input" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator = kp.simulations.KikuchiPatternSimulator(ref)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim = simulator.on_detector(detector, rot)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By passing the detector and crystal orientations to\n", "[KikuchiPatternSimulator.on_detector()](../reference.rst#kikuchipy.simulations.KikuchiPatternSimulator.on_detector),\n", "we've obtained a\n", "[kikuchipy.simulations.GeometricalKikuchiPatternSimulation](../reference.rst#kikuchipy.simulations.GeometricalKikuchiPatternSimulation),\n", "which stores the detector and gnomonic coordinates of the Kikuchi lines and\n", "zone axes for each crystal orientation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We see that not all 50 of the reflectors in the reflector list are present in\n", "some pattern.\n", "\n", "These geometrical simulations can be plotted one-by-one by themselves" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or, they be plotted on top of patterns in three ways: passing a pattern to\n", "[GeometricalKikuchiPatternSimulation.plot()](../reference.rst#kikuchipy.simulations.GeometricalKikuchiPatternSimulation.plot)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sim.plot(index=(1, 2), pattern=s.inav[2, 1].data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or obtaining a collection of lines, zone axes and zone axes labels as Matplotlib\n", "objects via\n", "[GeometricalKikuchiPatternSimulation.as_collections()](../reference.rst#kikuchipy.simulations.GeometricalKikuchiPatternSimulation.as_collections)\n", "and adding them to an existing Matplotlib axis" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(ncols=3, nrows=3, figsize=(15, 15))\n", "\n", "for idx in np.ndindex(s.axes_manager.navigation_shape[::-1]):\n", " ax[idx].imshow(s.data[idx], cmap=\"gray\")\n", " ax[idx].axis(\"off\")\n", "\n", " lines, zone_axes, zone_axes_labels = sim.as_collections(\n", " idx,\n", " zone_axes=True,\n", " zone_axes_labels=True,\n", " zone_axes_labels_kwargs=dict(fontsize=12),\n", " )\n", " ax[idx].add_collection(lines)\n", " ax[idx].add_collection(zone_axes)\n", " for label in zone_axes_labels:\n", " ax[idx].add_artist(label)\n", "\n", "fig.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or obtaining the lines, zone axes, zone axes labels and PCs as HyperSpy markers\n", "via\n", "[GeometricalKikuchiPatternSimulation.as_markers()](../reference.rst#kikuchipy.simulations.GeometricalKikuchiPatternSimulation.as_markers)\n", "and adding them to a signal of the same navigation shape as the simulation\n", "instance. This enables navigating the patterns *with* the geometrical simulations" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "markers = sim.as_markers()\n", "\n", "# To delete previously added permanent markers, do\n", "# del s.metadata.Markers\n", "\n", "s.add_marker(markers, plot_marker=False, permanent=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Kinematical simulations\n", "\n", "We can obtain kinematical master patterns using\n", "[KikuchiPatternSimulator.calculate_master_pattern()](../reference.rst#kikuchipy.simulations.KikuchiPatternSimulator.calculate_master_pattern),\n", "provided that the simulator is created from a\n", "[ReciprocalLatticeVector](https://diffsims.readthedocs.io/en/stable/reference.html#diffsims.crystallography.ReciprocalLatticeVector)\n", "instance that satisfy these conditions:\n", "\n", "1. The unit cell, i.e. the `structure` used to create the `phase` used in\n", " `ReciprocalLatticeVector`, must have all asymmetric atom positions filled,\n", " which can either be done by creating a `Phase` instance from a valid CIF file\n", " with\n", " [Phase.from_cif()](https://orix.readthedocs.io/en/stable/reference.html#orix.crystal_map.Phase.from_cif)\n", " or calling \n", " [ReciprocalLatticeVector.sanitise_phase()](https://diffsims.readthedocs.io/en/stable/reference.html#diffsims.crystallography.ReciprocalLatticeVector.sanitise_phase)\n", "\n", "2. The atoms in the `structure` have their elements described by the symbol\n", " (Ni), not by the atomic number (28)\n", "\n", "3. The lattice parameters are in given in Ångström.\n", "\n", "4. Kinematical structure factors $F_{hkl}$ have been calculated with\n", " [ReciprocalLatticeVector.calculate_structure_factor()](https://diffsims.readthedocs.io/en/stable/reference.html#diffsims.crystallography.ReciprocalLatticeVector.calculate_structure_factor)\n", "\n", "5. Bragg angles $\\theta_B$ have been calculated with\n", " [ReciprocalLatticeVector.calculate_theta()](https://diffsims.readthedocs.io/en/stable/reference.html#diffsims.crystallography.ReciprocalLatticeVector.calculate_theta)\n", "\n", "Let's simulate three master patterns:\n", "\n", "* nickel\n", "\n", "* variant of the $\\sigma$-phase (Fe, Cr) in steels\n", "\n", "* silicon carbide 6H." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Nickel\n", "\n", "We'll compare our kinematical simulations to dynamical simulations performed\n", "with EMsoft (see\n", "Callahan and De Graef (2013)),\n", "since we have a Ni master pattern available in the `kikuchipy.data` module" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_ni_dyn = kp.data.nickel_ebsd_master_pattern_small(projection=\"stereographic\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inspect phase" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phase_ni = mp_ni_dyn.phase.deepcopy()\n", "\n", "print(phase_ni)\n", "print(phase_ni.structure.lattice)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Change lattice parameters from nm to Ångström" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lat_ni = phase_ni.structure.lattice # Shallow copy\n", "lat_ni.setLatPar(lat_ni.a * 10, lat_ni.b * 10, lat_ni.c * 10)\n", "\n", "print(phase_ni.structure.lattice)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll build up the reflector list by:\n", "\n", "1. Finding all reflectors with a minimal interplanar spacing $d$\n", "\n", "2. Keeping those that have a structure factor above 0.5% of the reflector with\n", " the highest structure factor" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref_ni = ReciprocalLatticeVector.from_min_dspacing(phase_ni, 0.5)\n", "\n", "ref_ni = ref_ni[\n", " ref_ni.allowed\n", "] # Exclude non-allowed reflectors (not available for hexagonal or trigonal phases!)\n", "ref_ni = ref_ni.unique(use_symmetry=True).symmetrise()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sanitise `phase`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref_ni.phase.structure" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref_ni.sanitise_phase()\n", "ref_ni.phase.structure" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now calculate the structure factors. Two parametrizations are available,\n", "from Kirkland (1998) (`\"xtables\"`,\n", "the default) or\n", "Lobato and Van Dyck (2014) (`\"lobato\"`)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref_ni.calculate_structure_factor()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "structure_factor_ni = abs(ref_ni.structure_factor)\n", "ref_ni = ref_ni[structure_factor_ni > 0.05 * structure_factor_ni.max()]\n", "\n", "ref_ni.print_table()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref_ni.calculate_theta(20e3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now create our simulator and plot the simulation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_ni = kp.simulations.KikuchiPatternSimulator(ref_ni)\n", "simulator_ni.reflectors.size" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotting the band centers with intensities scaled by the structure factor" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_ni.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or no scaling (`scaling=\"square\"` for the structure factor squared)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_ni.plot(scaling=None)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also plot the Kikuchi bands, showing both hemispheres, also adding the\n", "crystal axes alignment" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "fig = simulator_ni.plot(hemisphere=\"both\", mode=\"bands\", return_figure=True)\n", "\n", "ax = fig.axes[0]\n", "ax.scatter(simulator_ni.phase.a_axis, c=\"r\")\n", "ax.scatter(simulator_ni.phase.b_axis, c=\"g\")\n", "ax.scatter(simulator_ni.phase.c_axis, c=\"b\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The simulation can be plotted in spherical projection as well using\n", "`Matplotlib`, or `PyVista` provided that it is [installed](../installation.rst#with-pip)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_ni.plot(\"spherical\", mode=\"bands\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Intensity scaling is not available when plotting in a notebook\n", "simulator_ni.plot(\"spherical\", mode=\"bands\", backend=\"pyvista\") # Interactive!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we're happy with the reflector list in the simulator, we can generate our\n", "kinematical master pattern" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_ni_kin = simulator_ni.calculate_master_pattern(half_size=200)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The returned master pattern is an instance of\n", "[EBSDMasterPattern](../reference.rst#kikuchipy.signals.EBSDMasterPattern) in the\n", "stereographic projection." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_ni_kin" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_ni_kin.plot_spherical(style=\"points\") # Interactive!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comparing kinematical and dynamical simulations" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Exclude outside equator\n", "ni_dyn_data = mp_ni_dyn.data.astype(np.float32)\n", "ni_kin_data = mp_ni_kin.data.astype(np.float32)\n", "mask = ni_dyn_data == 0\n", "ni_dyn_data[mask] = np.nan\n", "ni_kin_data[mask] = np.nan\n", "\n", "fig, ax = plt.subplots(ncols=2)\n", "ax[0].imshow(ni_kin_data, cmap=\"gray\")\n", "ax[1].imshow(ni_dyn_data, cmap=\"gray\")\n", "ax[0].axis(\"off\")\n", "ax[1].axis(\"off\")\n", "ax[0].set_title(\"Ni kinematical 20 kV\")\n", "ax[1].set_title(\"Ni dynamical 20 kV\")\n", "fig.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "Warning\n", " \n", "Use dynamical simulations when performing pattern matching, not kinematical\n", "simulations. The latter intensities are not realistic, as demonstrated in the\n", "above comparison.\n", "\n", "
\n", "\n", "Finally, we can transform the master pattern in the stereographic projection\n", "to one in the Lambert projection" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_ni_kin_lp = mp_ni_kin.as_lambert()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_ni_kin_lp.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then project parts of this pattern onto our EBSD detector using\n", "[get_patterns()](../reference.rst#kikuchipy.signals.EBSDMasterPattern.get_patterns)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s_kin = mp_ni_kin_lp.get_patterns(rot, detector, energy=20, compute=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_ = hs.plot.plot_images(\n", " s_kin, axes_decor=None, label=None, colorbar=False, tight_layout=True\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compare these to the ones the first plot!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### $\\sigma$-phase" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phase_sigma = Phase(\n", " name=\"sigma\",\n", " space_group=136,\n", " structure=Structure(\n", " atoms=[\n", " Atom(\"Cr\", [0, 0, 0], 0.5),\n", " Atom(\"Fe\", [0, 0, 0], 0.5),\n", " Atom(\"Cr\", [0.31773, 0.31773, 0], 0.5),\n", " Atom(\"Fe\", [0.31773, 0.31773, 0], 0.5),\n", " Atom(\"Cr\", [0.06609, 0.26067, 0], 0.5),\n", " Atom(\"Fe\", [0.06609, 0.26067, 0], 0.5),\n", " Atom(\"Cr\", [0.13122, 0.53651, 0], 0.5),\n", " Atom(\"Fe\", [0.13122, 0.53651, 0], 0.5),\n", " ],\n", " lattice=Lattice(8.802, 8.802, 4.548, 90, 90, 90),\n", " ),\n", ")\n", "phase_sigma" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref_sigma = ReciprocalLatticeVector.from_min_dspacing(phase_sigma, 1)\n", "\n", "ref_sigma.sanitise_phase()\n", "\n", "ref_sigma.calculate_structure_factor(\"lobato\")\n", "\n", "structure_factor = abs(ref_sigma.structure_factor)\n", "ref_sigma = ref_sigma[structure_factor > 0.05 * structure_factor.max()]\n", "\n", "ref_sigma.calculate_theta(20e3)\n", "\n", "ref_sigma.print_table()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_sigma = kp.simulations.KikuchiPatternSimulator(ref_sigma)\n", "simulator_sigma" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = simulator_sigma.plot(hemisphere=\"both\", mode=\"bands\", return_figure=True)\n", "\n", "ax = fig.axes[0]\n", "ax.scatter(simulator_sigma.phase.a_axis, c=\"r\")\n", "ax.scatter(simulator_sigma.phase.b_axis, c=\"g\")\n", "ax.scatter(simulator_sigma.phase.c_axis, c=\"b\")\n", "fig.tight_layout()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_sigma.plot(\"spherical\", mode=\"bands\", backend=\"pyvista\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_sigma = simulator_sigma.calculate_master_pattern()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "nbsphinx-thumbnail" ] }, "outputs": [], "source": [ "mp_sigma.plot()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_sigma.plot_spherical(style=\"points\") # Interactive!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Silicon carbide 6H" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phase_sic = Phase(\n", " name=\"sic_6h\",\n", " space_group=186,\n", " structure=Structure(\n", " atoms=[\n", " Atom(\"Si\", [1 / 3, 2 / 3, 0.20778]),\n", " Atom(\"C\", [1 / 3, 2 / 3, 0.33298]),\n", " Atom(\"Si\", [1 / 3, 2 / 3, 0.54134]),\n", " Atom(\"C\", [1 / 3, 2 / 3, 0.66647]),\n", " Atom(\"C\", [0, 0, 0]),\n", " Atom(\"Si\", [0, 0, 0.37461]),\n", " ],\n", " lattice=Lattice(3.081, 3.081, 15.2101, 90, 90, 120),\n", " ),\n", ")\n", "phase_sic" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ref_sic = ReciprocalLatticeVector.from_min_dspacing(phase_sic) # 0.7 Å, default\n", "ref_sic.sanitise_phase()\n", "\n", "ref_sic.calculate_structure_factor()\n", "\n", "structure_factor = abs(ref_sic.structure_factor)\n", "ref_sic = ref_sic[structure_factor > 0.05 * structure_factor.max()]\n", "\n", "ref_sic.calculate_theta(20e3)\n", "\n", "ref_sic.print_table()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_sic = kp.simulations.KikuchiPatternSimulator(ref_sic)\n", "simulator_sic" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = simulator_sic.plot(hemisphere=\"both\", mode=\"bands\", return_figure=True)\n", "\n", "ax = fig.axes[0]\n", "ax.scatter(simulator_sic.phase.a_axis, c=\"r\")\n", "ax.scatter(simulator_sic.phase.b_axis, c=\"g\")\n", "ax.scatter(simulator_sic.phase.c_axis, c=\"b\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "simulator_sic.plot(\"spherical\", mode=\"bands\", backend=\"pyvista\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_sic = simulator_sic.calculate_master_pattern(hemisphere=\"both\", half_size=200)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_sic" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_sic.plot(navigator=None)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp_sic.plot_spherical(style=\"points\") # Interactive!" ] } ], "metadata": { "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.9.13" } }, "nbformat": 4, "nbformat_minor": 4 }