{ "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": [ "# Visualizing patterns\n", "\n", "The [EBSD](reference.rst#kikuchipy.signals.EBSD) and\n", "[EBSDMasterPattern](reference.rst#kikuchipy.signals.EBSDMasterPattern) signals\n", "have a powerful and versatile\n", "[plot()](http://hyperspy.org/hyperspy-doc/current/api/hyperspy.signal.html#hyperspy.signal.BaseSignal.plot)\n", "method provided by HyperSpy. Its uses are greatly detailed in HyperSpy's\n", "[visualisation user guide](http://hyperspy.org/hyperspy-doc/current/user_guide/visualisation.html).\n", "This section details example uses specific to EBSD and EBSDMasterPattern\n", "signals.\n", "\n", "Let's import the necessary libraries and a Nickel EBSD test data set\n", "Ă…nes et al. (2019):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# exchange inline for qt5 for interactive plotting from the pyqt package\n", "%matplotlib inline\n", "\n", "import hyperspy.api as hs\n", "import kikuchipy as kp\n", "import matplotlib.pyplot as plt\n", "plt.rcParams[\"font.size\"] = 15\n", "import numpy as np\n", "from orix import io, plot, quaternion, vector\n", "import skimage.exposure as ske\n", "import skimage.transform as skt\n", "\n", "\n", "# Use kp.load(\"data.h5\") to load your own data\n", "s = kp.data.nickel_ebsd_large(allow_download=True) # External download\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Navigate in custom map\n", "\n", "Correlating results from e.g. crystal and phase structure determination, i.e.\n", "indexing, with experimental patterns can inform their interpretation. When\n", "calling `plot()` without any input parameters, the navigator map is a grey scale\n", "image with pixel values corresponding to the sum of all detector intensities\n", "within that pattern:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The upper panel shows the navigation axes, in this case 2D, with the current\n", "beam position in the upper left corner shown as a red square the size of one\n", "pixel. This square can be made larger/smaller with +/-.\n", "The square can be moved either by the keyboard arrows or the mouse. The lower\n", "panel shows the image on the detector in the current beam position." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Any\n", "[BaseSignal](http://hyperspy.org/hyperspy-doc/current/api/hyperspy.signal.html#hyperspy.signal.BaseSignal)\n", "signal with a 2D `signal_shape` corresponding to the scan\n", "`navigation_shape` can be passed in to the `navgiator` parameter in\n", "[plot()](http://hyperspy.org/hyperspy-doc/current/api/hyperspy.signal.html#hyperspy.signal.BaseSignal.plot),\n", "including a virtual image showing diffraction contrast, any quality metric map,\n", "or an orientation map or a phase map." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Virtual image" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A virtual backscatter electron (VBSE) image created from any detector region of\n", "interest with the\n", "[get_virtual_bse_intensity()](reference.rst#kikuchipy.signals.EBSD.get_virtual_bse_intensity)\n", "method or\n", "[get_rgb_image()](reference.rst#kikuchipy.generators.VirtualBSEGenerator.get_rgb_image)\n", "explained in the\n", "[virtual backscatter electron imaging](virtual_backscatter_electron_imaging.rst)\n", "section, can be used as a navigator for a scan `s`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "vbse_gen = kp.generators.VirtualBSEGenerator(s)\n", "print(vbse_gen)\n", "print(vbse_gen.grid_shape)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "vbse_rgb = vbse_gen.get_rgb_image(r=(3, 1), b=(3, 2), g=(3, 3))\n", "vbse_rgb" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s.plot(navigator=vbse_rgb, cmap=\"viridis\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Any image\n", "\n", "Images loaded into a\n", "[Signal2D](http://hyperspy.org/hyperspy-doc/current/api/hyperspy._signals.signal2d.html#hyperspy._signals.signal2d.Signal2D)\n", "can be used as navigators, like a quality metric map like the\n", "[image quality map](feature_maps.ipynb#Image-quality) calculated using\n", "[get_image_quality()](reference.rst#kikuchipy.signals.EBSD.get_image_quality):" ] }, { "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": [ "iq = s.get_image_quality()\n", "s_iq = hs.signals.Signal2D(iq)\n", "s.plot(navigator=s_iq, scalebar=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using colour images (apart from creating RGB virtual BSE images, as shown\n", "above), e.g. an orientation map, `om`, or phase map, is a bit more involved\n", "(especially when the image doesn't have the correct pixel shape, as is the case\n", "for our orientation map below, exported from MTEX):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "om = plt.imread('_static/image/visualizing_patterns/om.png')\n", "print(om.shape, om.dtype)\n", "om_resized = skt.resize(\n", " om,\n", " output_shape=s.axes_manager.navigation_shape[::-1] + (3,),\n", " anti_aliasing=False\n", ")\n", "om_scaled = ske.rescale_intensity(om_resized, out_range=np.uint8)\n", "s_om = hs.signals.Signal2D(om_scaled)\n", "s_om" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s_om = s_om.transpose(signal_axes=1)\n", "print(s_om, s_om.data.dtype)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s_om.change_dtype('rgb8')\n", "print(s_om, s_om.data.dtype)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s.plot(navigator=s_om, colorbar=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot multiple signals\n", "\n", "HyperSpy provides the function\n", "[plot_signals()](http://hyperspy.org/hyperspy-doc/current/api/hyperspy.drawing.utils.html#hyperspy.drawing.utils.plot_signals)\n", "to plot multiple signals with the same navigator, as explained in their\n", "[user guide](http://hyperspy.org/hyperspy-doc/current/user_guide/visualisation.html#plotting-several-signals).\n", "This enables e.g. plotting of experimental and best matching simulated patterns\n", "side-by-side as a visual inspection of the results of\n", "[pattern matching](pattern_matching.ipynb). To demonstrate this, we'll load\n", "a [CrystalMap](https://orix.readthedocs.io/en/stable/reference.html#crystalmap)\n", "with the best matching orientations of dynamically simulated Ni patterns to\n", "Nickel test data set, and project these patterns onto our detector from a master\n", "pattern" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xmap = io.load(\"_static/data/ni_large.h5\")\n", "xmap" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mp = kp.data.nickel_ebsd_master_pattern_small(projection=\"lambert\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s_best = mp.get_patterns(\n", " rotations=xmap.rotations,\n", " detector=kp.detectors.EBSDDetector(\n", " shape=s.axes_manager.signal_shape[::-1],\n", " pc=[0.421, 0.7794, 0.5049],\n", " sample_tilt=70,\n", " convention=\"tsl\"\n", " ),\n", " energy=20,\n", " dtype_out=s.data.dtype,\n", " compute=True\n", ")\n", "s_best = kp.signals.EBSD(s_best.data.reshape(s.data.shape))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's create a navigator map from the normalized cross-correlation scores" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ncc = xmap.get_map_data(xmap.scores[:, 0])\n", "s_ncc = hs.signals.Signal2D(ncc)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hs.plot.plot_signals([s, s_best], navigator=s_ncc)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We've made an animation to show this interactive plotting in action." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot master patterns\n", "\n", "[EBSDMasterPattern](reference.rst#kikuchipy.signals.EBSDMasterPattern) signals\n", "can be navigated along their energy axis and/or the their northern/southern\n", "hemisphere. Let's reload the Nickel master pattern used in the previous section,\n", "but this time in the stereographic projection." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Only a single energy, 20 keV\n", "mp_stereo = kp.data.nickel_ebsd_master_pattern_small(\n", " projection=\"stereographic\", hemisphere=\"both\"\n", ")\n", "mp_stereo.axes_manager" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As can be seen from the axes manager, the master pattern has two navigation\n", "axes, a north and south hemisphere, thus, when plotting, we get a slider as a\n", "navigator when plotting:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbsphinx-thumbnail": { "tooltip": "Ways to visualize the navigation (scan) and signal (detector) dimensions" }, "tags": [ "nbsphinx-thumbnail" ] }, "outputs": [], "source": [ "mp_stereo.plot()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.8.6" } }, "nbformat": 4, "nbformat_minor": 4 }