diff --git a/MANIFEST.in b/MANIFEST.in index c2994548..a99e5e6d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,13 +1,13 @@ +include kikuchipy/hyperspy_extension.yaml include LICENSE include MANIFEST.in include pyproject.toml include setup.cfg include README.rst +include RELEASE.rst include readthedocs.yml include setup.py -include kikuchipy/hyperspy_extension.yaml -recursive-include doc Makefile make.bat -recursive-include doc *.rst *.py *.ipynb -recursive-include doc/_static *.png *.jpg *.svg *.gif *.sh +recursive-include doc Makefile make.bat *.rst *.py *.ipynb +recursive-include doc/_static *.png *.jpg *.svg *.gif recursive-include kikuchipy/data * diff --git a/doc/changelog.rst b/doc/changelog.rst index d20aced6..cd1b114a 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -32,6 +32,12 @@ Added - Reading of NORDIF calibration patterns specified in a setting file into an EBSD signal. (`#317 `_) +Fixed +----- +- Scaling of region of interest coordinates used in virtual backscatter electron + imaging to physical coordinates + (`#349 `_) + 0.3.3 (2021-04-18) ================== diff --git a/doc/virtual_backscatter_electron_imaging.ipynb b/doc/virtual_backscatter_electron_imaging.ipynb index 400f40f0..fa8c96b8 100644 --- a/doc/virtual_backscatter_electron_imaging.ipynb +++ b/doc/virtual_backscatter_electron_imaging.ipynb @@ -53,14 +53,22 @@ "s" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We create a rectangular ROI by specifying the upper left and lower right\n", + "coordinates of the rectangle in units of the detector pixel size (scale of `dx`\n", + "and `dy` in the signal axes manager)" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "roi = hs.roi.RectangularROI(left=0, top=0, right=10, bottom=10)\n", - "roi" + "s.axes_manager" ] }, { @@ -69,6 +77,7 @@ "metadata": {}, "outputs": [], "source": [ + "roi = hs.roi.RectangularROI(left=0, top=0, right=10, bottom=10)\n", "s.plot_virtual_bse_intensity(roi)" ] }, @@ -400,7 +409,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.6" + "version": "3.8.8" } }, "nbformat": 4, diff --git a/kikuchipy/data/bruker/create_bruker_h5ebsd_file.py b/kikuchipy/data/bruker/create_bruker_h5ebsd_file.py index bbf447d9..beedb41e 100644 --- a/kikuchipy/data/bruker/create_bruker_h5ebsd_file.py +++ b/kikuchipy/data/bruker/create_bruker_h5ebsd_file.py @@ -193,8 +193,12 @@ # Header ebsd_header = ebsd.create_group("Header") ebsd_header.create_dataset("CameraTilt", dtype=float, data=0) -ebsd_header.create_dataset("DetectorFullHeightMicrons", dtype=np.int32, data=sy) -ebsd_header.create_dataset("DetectorFullWidthMicrons", dtype=np.int32, data=sx) +ebsd_header.create_dataset( + "DetectorFullHeightMicrons", dtype=np.int32, data=23700 +) +ebsd_header.create_dataset( + "DetectorFullWidthMicrons", dtype=np.int32, data=31600 +) grid_type = ebsd_header.create_dataset("Grid Type", shape=(1,), dtype="|S9") grid_type[()] = b"isometric" ebsd_header.create_dataset("KV", dtype=float, data=20) diff --git a/kikuchipy/data/bruker/patterns.h5 b/kikuchipy/data/bruker/patterns.h5 index 6e593abf..e3cb6f73 100644 Binary files a/kikuchipy/data/bruker/patterns.h5 and b/kikuchipy/data/bruker/patterns.h5 differ diff --git a/kikuchipy/data/bruker/patterns_roi.h5 b/kikuchipy/data/bruker/patterns_roi.h5 index 9dfe3b90..8bae4d8a 100644 Binary files a/kikuchipy/data/bruker/patterns_roi.h5 and b/kikuchipy/data/bruker/patterns_roi.h5 differ diff --git a/kikuchipy/data/bruker/patterns_roi_nonrectangular.h5 b/kikuchipy/data/bruker/patterns_roi_nonrectangular.h5 index 83da462d..c65fe7b0 100644 Binary files a/kikuchipy/data/bruker/patterns_roi_nonrectangular.h5 and b/kikuchipy/data/bruker/patterns_roi_nonrectangular.h5 differ diff --git a/kikuchipy/generators/virtual_bse_generator.py b/kikuchipy/generators/virtual_bse_generator.py index b0dc3e78..ee695f37 100644 --- a/kikuchipy/generators/virtual_bse_generator.py +++ b/kikuchipy/generators/virtual_bse_generator.py @@ -217,8 +217,8 @@ def get_images_from_grid( images[row, col] = self.signal.get_virtual_bse_intensity(roi).data vbse_images = VirtualBSEImage(images) - # TODO: Transfer signal's detector axes to new navigation axes with - # proper binning + # TODO: Transfer signal's detector axes to new navigation axes + # with proper binning vbse_images.axes_manager = _transfer_navigation_axes_to_signal_axes( new_axes=vbse_images.axes_manager, old_axes=self.signal.axes_manager ) @@ -243,15 +243,16 @@ def roi_from_grid(self, index: Union[Tuple, List[Tuple]]) -> RectangularROI: """ rows = self.grid_rows cols = self.grid_cols + dc, dr = [i.scale for i in self.signal.axes_manager.signal_axes] if isinstance(index, tuple): index = (index,) index = np.array(index) - min_col = cols[min(index[:, 1])] - max_col = cols[max(index[:, 1])] + cols[1] - min_row = rows[min(index[:, 0])] - max_row = rows[max(index[:, 0])] + rows[1] + min_col = cols[min(index[:, 1])] * dc + max_col = (cols[max(index[:, 1])] + cols[1]) * dc + min_row = rows[min(index[:, 0])] * dr + max_row = (rows[max(index[:, 0])] + rows[1]) * dr return RectangularROI( left=min_col, top=min_row, right=max_col, bottom=max_row, @@ -289,9 +290,9 @@ def plot_grid( pattern : kikuchipy.signals.EBSD A single pattern with the markers added. """ - # Get detector scales + # Get detector scales (column, row) axes_manager = self.signal.axes_manager - dx, dy = [i.scale for i in axes_manager.signal_axes] + dc, dr = [i.scale for i in axes_manager.signal_axes] rows = self.grid_rows cols = self.grid_cols @@ -303,8 +304,8 @@ def plot_grid( for row, col in np.ndindex(self.grid_shape): markers.append( Text( - x=cols[col], - y=rows[row] + (0.1 * rows[1]), + x=cols[col] * dc, + y=(rows[row] + (0.1 * rows[1])) * dr, text=f"{row,col}", color=color, ) @@ -312,8 +313,8 @@ def plot_grid( # Set lines kwargs.setdefault("color", "w") - markers += [HorizontalLine((i - 0.5) * dy, **kwargs) for i in rows] - markers += [VerticalLine((j - 0.5) * dx, **kwargs) for j in cols] + markers += [HorizontalLine((i - 0.5) * dr, **kwargs) for i in rows] + markers += [VerticalLine((j - 0.5) * dc, **kwargs) for j in cols] # Color RGB tiles if rgb_channels is not None: @@ -325,10 +326,10 @@ def plot_grid( roi = self.roi_from_grid((row, col)) markers += [ Rectangle( - x1=(roi.left - 0.5) * dx, - y1=(roi.top - 0.5) * dx, - x2=(roi.right - 0.5) * dy, - y2=(roi.bottom - 0.5) * dy, + x1=(roi.left - 0.5) * dc, + y1=(roi.top - 0.5) * dc, + x2=(roi.right - 0.5) * dr, + y2=(roi.bottom - 0.5) * dr, **kwargs, ) ] diff --git a/kikuchipy/indexing/tests/__init__.py b/kikuchipy/indexing/tests/__init__.py new file mode 100644 index 00000000..c8719dac --- /dev/null +++ b/kikuchipy/indexing/tests/__init__.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# Copyright 2019-2021 The kikuchipy developers +# +# This file is part of kikuchipy. +# +# kikuchipy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# kikuchipy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kikuchipy. If not, see . diff --git a/kikuchipy/io/plugins/h5ebsd.py b/kikuchipy/io/plugins/h5ebsd.py index 8c1b2d0b..3d5aba43 100644 --- a/kikuchipy/io/plugins/h5ebsd.py +++ b/kikuchipy/io/plugins/h5ebsd.py @@ -749,21 +749,21 @@ def brukerheader2dicts( # Get region of interest (ROI, only rectangular shape supported) try: sd = hdf5group2dict(group=scan_group["EBSD/SEM"]) - iy = sd["IY"][()] - ix = sd["IX"][()] + ir = sd["IY"][()] + ic = sd["IX"][()] roi = True except KeyError: roi = False - ny = hd["NROWS"] - nx = hd["NCOLS"] + nr = hd["NROWS"] + nc = hd["NCOLS"] if roi: - ny_roi, nx_roi, is_rectangular = _bruker_roi_is_rectangular(iy, ix) + nr_roi, nc_roi, is_rectangular = _bruker_roi_is_rectangular(ir, ic) if is_rectangular: - ny = ny_roi - nx = nx_roi + nr = nr_roi + nc = nc_roi # Get indices of patterns in the 2D map - idx = np.array([iy - np.min(iy), ix - np.min(ix)]) - scan_size["indices"] = np.ravel_multi_index(idx, (ny, nx)).argsort() + idx = np.array([ir - np.min(ir), ic - np.min(ic)]) + scan_size["indices"] = np.ravel_multi_index(idx, (nr, nc)).argsort() else: raise ValueError( "Only a rectangular region of interest is supported" @@ -772,8 +772,8 @@ def brukerheader2dicts( # Populate scan size dictionary scan_size.set_item("sx", hd["PatternWidth"]) scan_size.set_item("sy", hd["PatternHeight"]) - scan_size.set_item("nx", nx) - scan_size.set_item("ny", ny) + scan_size.set_item("nx", nc) + scan_size.set_item("ny", nr) scan_size.set_item("step_x", hd["XSTEP"]) scan_size.set_item("step_y", hd["YSTEP"]) scan_size.set_item( @@ -783,18 +783,27 @@ def brukerheader2dicts( return md, omd, scan_size -def _bruker_roi_is_rectangular(iy, ix): - iy_unique, iy_unique_counts = np.unique(iy, return_counts=True) - ix_unique, ix_unique_counts = np.unique(ix, return_counts=True) +def _bruker_roi_is_rectangular(ir, ic): + ir_unique, ir_unique_counts = np.unique(ir, return_counts=True) + ic_unique, ic_unique_counts = np.unique(ic, return_counts=True) is_rectangular = ( - np.all(np.diff(np.sort(iy_unique)) == 1) - and np.all(np.diff(np.sort(ix_unique)) == 1) - and np.unique(iy_unique_counts).size == 1 - and np.unique(ix_unique_counts).size == 1 + np.all(np.diff(np.sort(ir_unique)) == 1) + and np.all(np.diff(np.sort(ic_unique)) == 1) + and np.unique(ir_unique_counts).size == 1 + and np.unique(ic_unique_counts).size == 1 ) - iy2 = np.max(iy) - np.min(iy) + 1 - ix2 = np.max(ix) - np.min(ix) + 1 - return iy2, ix2, is_rectangular + ir2 = np.max(ir) - np.min(ir) + 1 + ic2 = np.max(ic) - np.min(ic) + 1 + return ir2, ic2, is_rectangular + + +# (n rows, n columns). Source: internet +BRUKER_DETECTOR_MODEL_RESOLUTION = dict( + eflash_fs=(480, 640), + eflash_hd=(1200, 1600), + eflash_hr=(1200, 1600), + eflash_xs=(540, 720), +) def file_writer( diff --git a/kikuchipy/pattern/tests/__init__.py b/kikuchipy/pattern/tests/__init__.py new file mode 100644 index 00000000..c8719dac --- /dev/null +++ b/kikuchipy/pattern/tests/__init__.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +# Copyright 2019-2021 The kikuchipy developers +# +# This file is part of kikuchipy. +# +# kikuchipy is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# kikuchipy is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kikuchipy. If not, see . diff --git a/kikuchipy/signals/ebsd.py b/kikuchipy/signals/ebsd.py index 2c2e5242..afc36939 100644 --- a/kikuchipy/signals/ebsd.py +++ b/kikuchipy/signals/ebsd.py @@ -1430,7 +1430,7 @@ def plot_virtual_bse_intensity( # Create the interactive signal interactive( - f=sliced_signal.sum, + f=sliced_signal.nansum, axis=sliced_signal.axes_manager.signal_axes, event=roi.events.changed, recompute_out_event=None, @@ -1442,7 +1442,7 @@ def plot_virtual_bse_intensity( @staticmethod def _get_sum_signal(signal, out_signal_axes: Optional[List] = None): - out = signal.sum(signal.axes_manager.signal_axes) + out = signal.nansum(signal.axes_manager.signal_axes) if out_signal_axes is None: out_signal_axes = list( np.arange(min(signal.axes_manager.navigation_dimension, 2)) diff --git a/setup.cfg b/setup.cfg index dc2c88a6..99d714f5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,5 @@ +# Note that Black does not support setup.cfg + [tool:pytest] addopts = -ra @@ -11,4 +13,12 @@ relative_files = True [coverage:report] precision = 2 -# Note that Black does not support setup.cfg +[manifix] +known_excludes = + .* + .*/** + .git/** + **/*.pyc + doc/build* + htmlcov/** + *.code-workspace