#!/usr/bin/env python
# coding: utf-8
# This notebook is part of the `kikuchipy` documentation https://kikuchipy.org.
# Links to the documentation won't work from the notebook.
# # Virtual backscatter electron imaging
# ## Interactive plotting
#
# Angle resolved backscatter electron (BSE) imaging can be performed interactively
# with the method
# [plot_virtual_bse_intensity()](reference.rst#kikuchipy.signals.EBSD.plot_virtual_bse_intensity),
# adopted from [pyxem](https://github.com/pyxem/pyxem), by integrating the
# intensities within a part, e.g. a (10 x 10) pixel rectangular region of interest
# (ROI), of the stack of EBSD patterns. Let's first import necessary libraries
# and a 13 MB Nickel EBSD data set
# In[ ]:
# exchange inline for qt5 for interactive plotting from the pyqt package
get_ipython().run_line_magic('matplotlib', 'inline')
import tempfile
import hyperspy.api as hs
import matplotlib.pyplot as plt
plt.rcParams["font.size"] = 12
import numpy as np
import kikuchipy as kp
s = kp.data.nickel_ebsd_large(allow_download=True) # External download
s
# In[ ]:
roi = hs.roi.RectangularROI(left=0, top=0, right=10, bottom=10)
roi
# In[ ]:
s.plot_virtual_bse_intensity(roi)
# Below is an animation showing the output three output windows of the above
# method: navigator to the left (the navigator image created from *all*
# intensities on the detector, not just within an ROI), detector in the middle
# with the adjustable ROI, and the virtual BSE image generated from the
# intensities within the ROI to the right.
#
# Note that the position of the ROI on the detector is updated during the
# interactive plotting. See
# [HyperSpy's ROI user guide](http://hyperspy.org/hyperspy-doc/current/user_guide/interactive_operations_ROIs.html#region-of-interest-roi)
# for more detailed use of ROIs.
#
# The virtual image, created from integrating the intensities within the ROI, can
# then be written to an image file using
# [get_virtual_bse_intensity()](reference.rst#kikuchipy.signals.EBSD.get_virtual_bse_intensity)
# In[ ]:
vbse = s.get_virtual_bse_intensity(roi)
vbse
# In[ ]:
temp_dir = tempfile.mkdtemp()
plt.imsave(temp_dir + "vbse1.png", arr=vbse.data)
# A [VirtualBSEImage](reference.rst#kikuchipy.signals.VirtualBSEImage) instance is
# returned.
# ## Generate many virtual images
#
# Sometimes we want to get many images from parts of the detector, e.g. like what
# is demonstrated in the
# [xcdskd project](https://xcdskd.readthedocs.io/en/latest/bse_imaging.html) with
# the angle resolved virtual backscatter electron array (arbse/vbse array).
# Instead of keeping track of multiple
# [hyperspy.roi.BaseInteractiveROI](http://hyperspy.org/hyperspy-doc/current/api/hyperspy.roi.html#hyperspy.roi.BaseInteractiveROI)
# objects, we can create a detector grid of a certain shape, e.g. (5, 5), and
# obtain gray scale images, or combine multiple grid tiles in red, green and
# channels to obtain RGB images.
#
# First, we initialize a virtual BSE image generator,
# [kikuchipy.generators.VirtualBSEGenerator](reference.rst#kikuchipy.generators.VirtualBSEGenerator),
# with an [EBSD](reference.rst#kikuchipy.signals.EBSD) signal, in this case the
# raw EBSD patterns without any background correction or other processing
# In[ ]:
vbse_gen = kp.generators.VirtualBSEGenerator(s)
vbse_gen
# We can set and plot the detector grid on one of the EBSD patterns, also coloring
# one or more of the grid tiles red, green and blue, as is done in
# Nolze et al. (2017), by calling
# [VirtualBSEGenerator.plot_grid()](reference.rst#kikuchipy.generators.VirtualBSEGenerator.plot_grid)
# In[ ]:
vbse_gen.grid_shape
# In[ ]:
vbse_gen.grid_shape = (10, 10)
red = [(7, 1), (8, 1), (8, 2), (9, 1), (9, 2)]
green = [(8, 4), (8, 5), (9, 4), (9, 5)]
blue = [(7, 8), (8, 7), (8, 8), (9, 7), (9, 8)]
p = vbse_gen.plot_grid(
rgb_channels=[red, green, blue],
visible_indices=True, # Default
pattern_idx=(10, 20), # Default is (0, 0)
)
p
# As shown above, whether to show the grid tile indices or not is controlled with
# the `visible_indices` argument, and which signal pattern to superimpose the grid
# upon is controlled with the `pattern_idx` parameter.
# To obtain an RGB image from the detector grid tiles shown above, we use
# [get_rgb_image()](reference.rst#kikuchipy.generators.VirtualBSEGenerator.get_rgb_image)
# (see the docstring for all available parameters)
# In[ ]:
vbse_rgb_img = vbse_gen.get_rgb_image(r=red, g=green, b=blue)
vbse_rgb_img
# In[ ]:
vbse_rgb_img.plot(title="", axes_off=True)
# An RGB image formed from coloring three grey scale virtual BSE images red,
# green and blue.
# To obtain one grey scale virtual BSE image from each grid tile, we use
# [get_images_from_grid()](reference.rst#kikuchipy.generators.VirtualBSEGenerator.get_images_from_grid)
# In[ ]:
vbse_gen.grid_shape = (3, 3)
vbse_imgs = vbse_gen.get_images_from_grid()
vbse_imgs
# In[ ]:
vbse_imgs.plot()
# In[ ]:
fig, ax = plt.subplots(nrows=3, ncols=3, figsize=(20, 20))
for idx in np.ndindex(vbse_imgs.axes_manager.navigation_shape[::-1]):
ax[idx].imshow(vbse_imgs.inav[idx].data, cmap="gray")
ax[idx].axis("off")
fig.tight_layout(w_pad=0.5, h_pad=-24)
# It might be desirable to normalize, rescale or stretch the intensities in the
# images, as shown e.g. in Fig. 9 in
# Wright et al. (2015). This can be
# done with
# [VirtualBSEImage.normalize_intensity()](reference.rst#kikuchipy.signals.VirtualBSEImage.normalize_intensity)
# or
# [VirtualBSEImage.rescale_intensity()](reference.rst#kikuchipy.signals.VirtualBSEImage.rescale_intensity).
# Let's rescale the intensities in each image to the range [0, 1], while also
# excluding the intensities outside the lower and upper 0.5% percentile, per image
# In[ ]:
vbse_imgs.data.dtype
# In[ ]:
vbse_imgs2 = vbse_imgs.deepcopy()
vbse_imgs2.rescale_intensity(out_range=(0, 1), percentiles=(0.5, 99.5))
# In[ ]:
print(vbse_imgs.data.min(), vbse_imgs.data.max())
print(vbse_imgs2.data.min(), vbse_imgs2.data.max())
# In[ ]:
fig, ax = plt.subplots(nrows=3, ncols=3, figsize=(20, 20))
for idx in np.ndindex(vbse_imgs2.axes_manager.navigation_shape[::-1]):
ax[idx].imshow(vbse_imgs2.inav[idx].data, cmap="gray")
ax[idx].axis("off")
fig.tight_layout(w_pad=0.5, h_pad=-24)
# To obtain a rectangular ROI from the grid, we can use
# [VirtualBSEGenerator.roi_from_grid()](reference.rst#kikuchipy.generators.VirtualBSEGenerator.roi_from_grid)
# In[ ]:
roi2 = vbse_gen.roi_from_grid((3, 3)) # (Row, column)
roi2
# In[ ]:
import os
os.rmdir(temp_dir)