{
"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
}