This page was generated from doc/virtual_backscatter_electron_imaging.ipynb. Interactive online version: Binder badge.

Virtual backscatter electron imaging

Interactive plotting

Angle resolved backscatter electron (BSE) imaging can be performed interactively with the method plot_virtual_bse_intensity(), adopted from 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

[1]:
# exchange inline for qt5 for interactive plotting from the pyqt package
%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
WARNING:hyperspy.api:The ipywidgets GUI elements are not available, probably because the hyperspy_gui_ipywidgets package is not installed.
WARNING:hyperspy.api:The traitsui GUI elements are not available, probably because the hyperspy_gui_traitsui package is not installed.
[1]:
<EBSD, title: patterns Scan 1, dimensions: (75, 55|60, 60)>

We create a rectangular ROI by specifying the upper left and lower right coordinates of the rectangle in units of the detector pixel size (scale of dx and dy in the signal axes manager)

[2]:
s.axes_manager
[2]:

< Axes manager, axes: (75, 55|60, 60) >

Navigation axis name size index offset scale units
x 75 0 0.0 1.5 um
y 55 0 0.0 1.5 um
Signal axis name size offset scale units
dx 60 0.0 1.0 um
dy 60 0.0 1.0 um
[3]:
roi = hs.roi.RectangularROI(left=0, top=0, right=10, bottom=10)
s.plot_virtual_bse_intensity(roi)
_images/virtual_backscatter_electron_imaging_6_0.png
_images/virtual_backscatter_electron_imaging_6_1.png
_images/virtual_backscatter_electron_imaging_6_2.png

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.

9f056e56c9ad468a860c1db2eb02ba31

Note that the position of the ROI on the detector is updated during the interactive plotting. See HyperSpy’s ROI user guide 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()

[4]:
vbse = s.get_virtual_bse_intensity(roi)
vbse
[4]:
<VirtualBSEImage, title: Virtual backscatter electron image, dimensions: (|75, 55)>
[5]:
temp_dir = tempfile.mkdtemp() + "/"
plt.imsave(temp_dir + "vbse1.png", arr=vbse.data)

A 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 with the angle resolved virtual backscatter electron array (arbse/vbse array). Instead of keeping track of multiple 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, with an EBSD signal, in this case the raw EBSD patterns without any background correction or other processing

[6]:
vbse_gen = kp.generators.VirtualBSEGenerator(s)
vbse_gen
[6]:
VirtualBSEGenerator for <EBSD, title: patterns Scan 1, dimensions: (75, 55|60, 60)>

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 [NHW17], by calling VirtualBSEGenerator.plot_grid()

[7]:
vbse_gen.grid_shape
[7]:
(5, 5)
[8]:
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
[8]:
<EBSD, title: patterns Scan 1, dimensions: (|60, 60)>
_images/virtual_backscatter_electron_imaging_17_1.png

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() (see the docstring for all available parameters)

[9]:
vbse_rgb_img = vbse_gen.get_rgb_image(r=red, g=green, b=blue)
vbse_rgb_img
[9]:
<VirtualBSEImage, title: , dimensions: (|75, 55)>
[10]:
vbse_rgb_img.plot(title="", axes_off=True)
_images/virtual_backscatter_electron_imaging_21_0.png

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()

[11]:
vbse_gen.grid_shape = (3, 3)
vbse_imgs = vbse_gen.get_images_from_grid()
vbse_imgs
[11]:
<VirtualBSEImage, title: , dimensions: (3, 3|75, 55)>
[12]:
vbse_imgs.plot()
_images/virtual_backscatter_electron_imaging_25_0.png
_images/virtual_backscatter_electron_imaging_25_1.png
[13]:
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)
_images/virtual_backscatter_electron_imaging_26_0.png

It might be desirable to normalize, rescale or stretch the intensities in the images, as shown e.g. in Fig. 9 in [WNDeKloe+15]. This can be done with VirtualBSEImage.normalize_intensity() or 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

[14]:
vbse_imgs.data.dtype
[14]:
dtype('float32')
[15]:
vbse_imgs2 = vbse_imgs.deepcopy()
vbse_imgs2.rescale_intensity(out_range=(0, 1), percentiles=(0.5, 99.5))
Rescaling the image intensities:
[########################################] | 100% Completed |  0.3s
[16]:
print(vbse_imgs.data.min(), vbse_imgs.data.max())
print(vbse_imgs2.data.min(), vbse_imgs2.data.max())
21321.0 84168.0
-7.962798e-07 1.0000005
[17]:
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)
_images/virtual_backscatter_electron_imaging_31_0.png

To obtain a rectangular ROI from the grid, we can use VirtualBSEGenerator.roi_from_grid()

[18]:
roi2 = vbse_gen.roi_from_grid((3, 3))  # (Row, column)
roi2
[18]:
RectangularROI(left=60, top=60, right=80, bottom=80)