Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Håkon Wiik Ånes <hwaanes@gmail.com>
- Loading branch information
Showing
2 changed files
with
243 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Pattern processing\n", | ||
"\n", | ||
"The raw EBSD signal can be empirically evaluated as a superposition of a Kikuchi\n", | ||
"diffraction pattern and a smooth background intensity. For pattern indexing, the\n", | ||
"latter intensity is usually undesirable, while for [virtual backscatter electron\n", | ||
"(VBSE) imaging](virtual_backscatter_electron_imaging.rst), this intensity\n", | ||
"can reveal topographical, compositional or diffraction contrast. This section\n", | ||
"details methods to enhance the Kikuchi diffraction pattern and manipulate\n", | ||
"detector intensities in patterns in an [EBSD](reference.rst#kikuchipy.signals.EBSD)\n", | ||
"object.\n", | ||
"\n", | ||
"Most of the methods operating on EBSD objects use functions that operate on the\n", | ||
"individual patterns (`numpy.ndarray`). These single pattern functions are\n", | ||
"available in the [kikuchipy.pattern](reference.rst#pattern) module.\n", | ||
"\n", | ||
"Let's import necessary libraries and read the Nickel EBSD data set:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#%matplotlib qt5\n", | ||
"%matplotlib inline\n", | ||
"\n", | ||
"import os\n", | ||
"import matplotlib.pyplot as plt\n", | ||
"import numpy as np\n", | ||
"import kikuchipy as kp\n", | ||
"\n", | ||
"\n", | ||
"datadir = \"../../kikuchipy_data/ni/nordif\"\n", | ||
"s = kp.load(os.path.join(datadir, \"Pattern.dat\"))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Almost all methods operate inplace (indicated in their docstrings), meaning it\n", | ||
"overwrites the patterns in the EBSD object. If instead we want a new object,\n", | ||
"we create a [deepcopy](http://hyperspy.org/hyperspy-doc/current/api/hyperspy.signal.html#hyperspy.signal.BaseSignal.deepcopy)\n", | ||
"of the original object and perform our operations on this. To demonstrate this,\n", | ||
"we create a new EBSD signal from a small part of the original signal:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"x0, x1 = (156, 159)\n", | ||
"y0, y1 = (77, 80)\n", | ||
"s2 = s.inav[x0:x1, y0:y1].deepcopy()\n", | ||
"np.may_share_memory(s.data, s2.data)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Rescale intensity\n", | ||
"\n", | ||
"Vendors usually write patterns to file with 8 (``uint8``) or 16 (``uint16``) bit\n", | ||
"integer depth, holding [0, 2$^8$] or [0, 2$^{16}$] gray levels, respectively. To\n", | ||
"avoid losing intensity information when processing, we often change data types\n", | ||
"to e.g. 32 bit floating point (``float32``). However, only changing the data\n", | ||
"type with [change_dtype](http://hyperspy.org/hyperspy-doc/current/api/hyperspy.signal.html#hyperspy.signal.BaseSignal.change_dtype) does not\n", | ||
"rescale pattern intensities, leading to patterns not using the full available\n", | ||
"data type range:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"print(s2.data.dtype, s2.data.max())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"s2.change_dtype(np.uint16)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"print(s2.data.dtype, s2.data.max())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"s2.plot(vmax=1000)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"In these cases it is convenient to rescale intensities to a desired data type\n", | ||
"range, either keeping relative intensities between patterns in a scan or not. We\n", | ||
"can do this for all patterns in a scan\n", | ||
"([EBSD](reference.rst#kikuchipy.signals.EBSD) object) with [kikuchipy.signals.EBSD.rescale_intensity](reference.rst#kikuchipy.signals.EBSD.rescale_intensity):" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"s2.rescale_intensity(relative=True)\n", | ||
"print(s2.data.dtype, s2.data.max())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"s2.plot(vmax=65535)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Or, we can do it for a single pattern (`numpy.ndarray`) with\n", | ||
"[kikuchipy.pattern.rescale_intensity](reference.rst#kikuchipy.pattern.rescale_intensity):" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"p = s.inav[x0, y0].data\n", | ||
"print(p.min(), p.max())\n", | ||
"p2 = kp.pattern.rescale_intensity(p, dtype_out=np.uint16)\n", | ||
"print(p2.min(), p2.max())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"We can also stretch the pattern contrast by removing intensities outside a range\n", | ||
"passed to `in_range` or at certain percentiles by passing percents to\n", | ||
"`percentiles`:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"s3 = s.inav[x0:x1, y0:y1].deepcopy()\n", | ||
"s3.rescale_intensity(in_range=(5, 250))\n", | ||
"print(s3.data.min(), s3.data.max())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"s3.rescale_intensity(percentiles=(0.5, 99.5))\n", | ||
"print(s3.data.min(), s3.data.max())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"This can reduce the influence of outliers with exceptionally high or low\n", | ||
"intensities, like hot or dead pixels." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"fig, ax = plt.subplots(figsize=(11, 4), ncols=2)\n", | ||
"im0 = ax[0].imshow(s2.inav[0, 0].data, cmap=\"gray\")\n", | ||
"fig.colorbar(im0, ax=ax[0])\n", | ||
"im1 = ax[1].imshow(s3.inav[0, 0].data, cmap=\"gray\")\n", | ||
"fig.colorbar(im1, ax=ax[1])" | ||
] | ||
} | ||
], | ||
"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.5" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |