# Feature maps¶

This section details methods for extracting information from pattern intensities, called feature maps (for lack of a better description).

Let’s import the necessary libraries and a Nickel EBSD test data set:

[1]:
# exchange inline for qt5 for interactive plotting from the pyqt package
%matplotlib inline

import matplotlib.pyplot as plt
plt.rcParams["font.size"] = 15
import numpy as np
import kikuchipy as kp

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.
100%|█████████████████████████████████████| 13.0M/13.0M [00:00<00:00, 3.91GB/s]
[1]:
<EBSD, title: patterns Scan 1, dimensions: (75, 55|60, 60)>

## Image quality¶

The image quality metric $$Q$$ presented by Krieger Lassen [Las94] can be calculated for an EBSD signal with get_image_quality(), or, for a single pattern (numpy.ndarray), with get_image_quality(). Following the notation in [MDeGraefS+17], it is given by

\begin{split}\begin{align} Q &= 1 - \frac{J}{J_{\mathrm{res}}w_{\mathrm{tot}}},\\ J &= \sum_{h = -N/2}^{N/2} \sum_{k = -N/2}^{N/2} w(h, k) \left|\mathbf{q}\right|^2,\\ J_{\mathrm{res}} &= \frac{1}{N^2} \sum_{h = -N/2}^{N/2} \sum_{k = -N/2}^{N/2} \left|\mathbf{q}\right|^2,\\ w_{\mathrm{tot}} &= \sum_{h = -N/2}^{N/2} \sum_{k = -N/2}^{N/2} w(h, k). \end{align}\end{split}

The function $$w(h, k)$$ is the Fast Fourier Transform (FFT) power spectrum of the EBSD pattern, and the vectors $$\mathbf{q}$$ are the frequency vectors with components $$(h, k)$$. The sharper the Kikuchi bands, the greater the high frequency content of the power spectrum, and thus the closer $$Q$$ will be to unity.

Since we want to use the image quality metric to determine how pronounced the Kikuchi bands in our patterns are, we first remove the static and dynamic background:

[2]:
s.remove_static_background()
s.remove_dynamic_background()
Removing the static background:
[########################################] | 100% Completed |  1.0s
Removing the dynamic background:
[########################################] | 100% Completed |  2.5s

To visualize parts of the computation, we compute the power spectrum of a pattern in the Nickel EBSD data set and the frequency vectors, shift the zero-frequency components to the centre, and plot them:

[3]:
p = s.inav[20, 11].data
p_fft = kp.pattern.fft(p, shift=True)
q = kp.pattern.fft_frequency_vectors(shape=p.shape)

fig, ax = plt.subplots(figsize=(22, 6), ncols=3)

im0 = ax[0].imshow(p, cmap="gray")
ax[0].set_title("Pattern", **title_kwargs)
fig.colorbar(im0, ax=ax[0])

im1 = ax[1].imshow(np.log(kp.pattern.fft_spectrum(p_fft)), cmap="gray")
ax[1].set_title("Log of shifted power spectrum of FFT", **title_kwargs)
fig.colorbar(im1, ax=ax[1])

im2 = ax[2].imshow(np.fft.fftshift(q), cmap="gray")
ax[2].set_title(r"Shifted frequency vectors $q$", **title_kwargs)
_ = fig.colorbar(im2, ax=ax[2])

If we don’t want the EBSD patterns to be zero-mean normalized before computing $$Q$$, we must pass get_image_quality(normalize=False).

Let’s compute the image quality $$Q$$ and plot it for the entire data set:

[4]:
iq = s.get_image_quality(normalize=True)  # Default

plt.figure(figsize=(10, 6))
plt.imshow(iq, cmap="gray")
_ = plt.colorbar(label=r"Image quality, $Q$")
Calculating the image quality:
[########################################] | 100% Completed |  1.6s

If we want to use this map to navigate around in when plotting patterns, we can easily do that as explained in the visualizing patterns guide.