From d4fc96b1b40f27979362ff3d0f471be83c3468eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Wed, 25 Oct 2023 20:12:21 +0200 Subject: [PATCH] Test passing reflector list in various forms, start on test for check of phase lists compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- kikuchipy/indexing/_hough_indexing.py | 11 +- .../signals/tests/test_ebsd_hough_indexing.py | 109 +++++++++++------- 2 files changed, 75 insertions(+), 45 deletions(-) diff --git a/kikuchipy/indexing/_hough_indexing.py b/kikuchipy/indexing/_hough_indexing.py index 51b1bf6a..87cd7353 100644 --- a/kikuchipy/indexing/_hough_indexing.py +++ b/kikuchipy/indexing/_hough_indexing.py @@ -159,11 +159,10 @@ def _get_indexer_from_detector( dependency of kikuchipy. See :ref:`optional-dependencies` for details. """ - if not _pyebsdindex_installed: + if not _pyebsdindex_installed: # pragma: no cover raise ValueError( "pyebsdindex must be installed. Install with pip install pyebsdindex. " - "See https://kikuchipy.org/en/stable/user/installation.html for " - "details." + "See https://kikuchipy.org/en/stable/user/installation.html for details." ) from pyebsdindex.ebsd_index import EBSDIndexer @@ -293,9 +292,9 @@ def _get_pyebsdindex_phaselist( # Make list of reflectors iterable if reflectors is None: reflectors = [None] * phase_list.size - elif isinstance(reflectors, (np.ndarray, ReciprocalLatticeVector)): - reflectors = [reflectors] - elif isinstance(reflectors, (list, tuple)) and len(reflectors) != phase_list.size: + elif isinstance(reflectors, (np.ndarray, ReciprocalLatticeVector)) or ( + isinstance(reflectors, (list, tuple)) and len(reflectors) != phase_list.size + ): reflectors = [reflectors] if len(reflectors) != phase_list.size: diff --git a/kikuchipy/signals/tests/test_ebsd_hough_indexing.py b/kikuchipy/signals/tests/test_ebsd_hough_indexing.py index 136d1bb3..9008cd1d 100644 --- a/kikuchipy/signals/tests/test_ebsd_hough_indexing.py +++ b/kikuchipy/signals/tests/test_ebsd_hough_indexing.py @@ -15,7 +15,8 @@ # You should have received a copy of the GNU General Public License # along with kikuchipy. If not, see . -import matplotlib.pyplot as plt +from diffpy.structure import Lattice, Structure +from diffsims.crystallography import ReciprocalLatticeVector import numpy as np from orix.crystal_map import CrystalMap, PhaseList import pytest @@ -24,6 +25,7 @@ from kikuchipy.indexing._hough_indexing import ( _get_info_message, _indexer_is_compatible_with_kikuchipy, + _phase_lists_are_compatible, ) @@ -37,16 +39,13 @@ def setup_method(self): s.remove_dynamic_background() self.signal = s - self.xmap = s.xmap - self.phase_list = s.xmap.phases - self.detector = s.detector self.indexer = s.detector.get_indexer(s.xmap.phases) def test_hough_indexing_print_information(self): - det = self.detector + det = self.signal.detector det.shape = (4, 5) # Save time on indexer creation - indexer1 = det.get_indexer(self.phase_list) + indexer1 = det.get_indexer(self.signal.xmap.phases) info = _get_info_message( self.signal.axes_manager.navigation_size, chunksize=3, indexer=indexer1 @@ -61,7 +60,7 @@ def test_hough_indexing_print_information(self): det_pc_mean = det.deepcopy() det_pc_mean.pc = det_pc_mean.pc_average - indexer2 = det_pc_mean.get_indexer(self.phase_list) + indexer2 = det_pc_mean.get_indexer(self.signal.xmap.phases) info2 = _get_info_message( self.signal.axes_manager.navigation_size, chunksize=3, indexer=indexer2 ) @@ -70,9 +69,9 @@ def test_hough_indexing_print_information(self): def test_hough_indexing(self): # Reference results (Hough indexing + refinement) - xmap_ref = self.xmap + xmap_ref = self.signal.xmap - phase_list = self.phase_list + phase_list = xmap_ref.phases indexer = self.indexer xmap = self.signal.hough_indexing(phase_list, indexer) @@ -85,17 +84,18 @@ def test_hough_indexing(self): def test_hough_indexing_lazy(self): # pragma: no cover s = self.signal.as_lazy() + phase_list = self.signal.xmap.phases if kp._pyopencl_context_available: - xmap1 = s.hough_indexing(self.phase_list, self.indexer) - xmap2 = self.signal.hough_indexing(self.phase_list, self.indexer) + xmap1 = s.hough_indexing(phase_list, self.indexer) + xmap2 = self.signal.hough_indexing(phase_list, self.indexer) assert np.allclose(xmap1.rotations.data, xmap2.rotations.data) assert np.allclose(xmap1.fit, xmap2.fit) else: with pytest.raises(ValueError, match="Hough indexing of lazy signals must"): - _ = s.hough_indexing(self.phase_list, self.indexer, verbose=2) + _ = s.hough_indexing(phase_list, self.indexer, verbose=2) def test_hough_indexing_return_index_data(self): - phase_list = self.phase_list + phase_list = self.signal.xmap.phases xmap, index_data = self.signal.hough_indexing( phase_list, self.indexer, return_index_data=True ) @@ -114,9 +114,10 @@ def test_hough_indexing_return_index_data(self): assert np.allclose(xmap2.cm, xmap.cm) def test_hough_indexing_return_band_data(self): - indexer = self.detector.get_indexer(self.phase_list, nBands=8) + phase_list = self.signal.xmap.phases + indexer = self.signal.detector.get_indexer(phase_list, nBands=8) _, band_data = self.signal.hough_indexing( - self.phase_list, indexer, return_band_data=True + phase_list, indexer, return_band_data=True ) assert isinstance(band_data, np.ndarray) assert band_data.shape == ( @@ -125,7 +126,7 @@ def test_hough_indexing_return_band_data(self): ) _, index_data, band_data = self.signal.hough_indexing( - self.phase_list, self.indexer, return_index_data=True, return_band_data=True + phase_list, self.indexer, return_index_data=True, return_band_data=True ) assert isinstance(index_data, np.ndarray) assert isinstance(band_data, np.ndarray) @@ -151,9 +152,9 @@ def test_indexer_is_compatible_with_signal(self): assert not _indexer_is_compatible_with_kikuchipy(indexer, (60, 59), 9) with pytest.raises(ValueError, match=r"Indexer signal shape \(60, 60\) must "): _indexer_is_compatible_with_kikuchipy(indexer, (60, 59), raise_if_not=True) - det2 = self.detector.deepcopy() + det2 = self.signal.detector.deepcopy() det2.shape = (60, 59) - indexer2 = det2.get_indexer(self.phase_list) + indexer2 = det2.get_indexer(self.signal.xmap.phases) assert not _indexer_is_compatible_with_kikuchipy(indexer2, (60, 60), 9) with pytest.raises(ValueError, match=r"Indexer signal shape \(60, 59\) must "): _indexer_is_compatible_with_kikuchipy(indexer2, (60, 60), raise_if_not=True) @@ -174,7 +175,7 @@ def test_indexer_is_compatible_with_signal(self): ) def test_hough_indexing_get_xmap_from_index_data(self): - phase_list = self.phase_list + phase_list = self.signal.xmap.phases xmap, index_data = self.signal.hough_indexing( phase_list, self.indexer, return_index_data=True ) @@ -209,6 +210,36 @@ def test_hough_indexing_get_xmap_from_index_data(self): assert xmap2.dy == 2 assert xmap2.dx == 3 + def test_reflector_list(self): + phase_list = self.signal.xmap.phases + + hkl = [[2, 0, 0], [2, 2, 0], [1, 1, 1], [3, 1, 1], [3, 3, 1]] + + ref = ReciprocalLatticeVector(hkl=hkl, phase=phase_list[0]) + reflectors = [hkl, tuple(hkl), np.array(hkl), ref] + + indexers = [self.signal.detector.get_indexer(phase_list)] + for i in range(len(reflectors)): + indexer = self.signal.detector.get_indexer( + phase_list, reflectors=reflectors[i] + ) + indexers.append(indexer) + + assert np.allclose(indexer.phaselist[0].polefamilies, hkl) + + def test_compatible_phase_lists(self): + phase_list = PhaseList( + names=["a", "b"], + space_groups=[186, 225], + structures=[ + Structure(lattice=Lattice(1, 1, 2, 90, 90, 120)), + Structure(lattice=Lattice(1, 1, 1, 90, 90, 90)), + ], + ) + indexer = self.signal.detector.get_indexer(phase_list) + + assert _phase_lists_are_compatible(phase_list, indexer, True) + @pytest.mark.skipif( not kp._pyebsdindex_installed, reason="pyebsdindex is not installed" @@ -220,42 +251,41 @@ def setup_method(self): s.remove_dynamic_background() self.signal = s - self.xmap = s.xmap - self.phase_list = s.xmap.phases - self.detector = s.detector self.indexer = s.detector.get_indexer(s.xmap.phases) def test_optimize_pc(self): - det = self.signal.hough_indexing_optimize_pc( - self.detector.pc_average, self.indexer - ) + det0 = self.signal.detector + + det = self.signal.hough_indexing_optimize_pc(det0.pc_average, self.indexer) assert det.navigation_shape == (1,) - assert np.allclose(det.pc_average, self.detector.pc_average, atol=1e-2) + assert np.allclose(det.pc_average, det0.pc_average, atol=1e-2) # Batch with PC array with more than one dimension det2 = self.signal.hough_indexing_optimize_pc( - self.detector.pc_average, self.indexer, batch=True + det0.pc_average, self.indexer, batch=True ) assert det2.navigation_shape == (3, 3) assert np.allclose(det.pc_average, det2.pc_average, atol=1e-2) # Detector parameters - assert det.shape == self.detector.shape - assert np.isclose(det.sample_tilt, self.detector.sample_tilt) - assert np.isclose(det.tilt, self.detector.tilt) - assert np.isclose(det.px_size, self.detector.px_size) + assert det.shape == det0.shape + assert np.isclose(det.sample_tilt, det0.sample_tilt) + assert np.isclose(det.tilt, det0.tilt) + assert np.isclose(det.px_size, det0.px_size) def test_optimize_pc_pso(self, worker_id): + det0 = self.signal.detector + det = self.signal.hough_indexing_optimize_pc( - self.detector.pc_average, self.indexer, method="PSO" + det0.pc_average, self.indexer, method="PSO" ) # Results are not deterministic, so we give a wide range here... - assert abs(self.detector.pc_average - det.pc_average).max() < 0.03 + assert abs(det0.pc_average - det.pc_average).max() < 0.03 if worker_id == "master": # pragma: no cover # Batch with PC array with more than one dimension det2 = self.signal.hough_indexing_optimize_pc( - self.detector.pc_average, + det0.pc_average, self.indexer, batch=True, method="PSO", @@ -275,17 +305,18 @@ def test_optimize_pc_raises(self): def test_optimize_pc_lazy(self): # pragma: no cover s = self.signal.as_lazy() + det = self.signal.detector if kp._pyopencl_context_available: - det = s.hough_indexing_optimize_pc(self.detector.pc_average, self.indexer) - assert np.allclose(det.pc_average, self.detector.pc_average, atol=1e-2) + det = s.hough_indexing_optimize_pc(det.pc_average, self.indexer) + assert np.allclose(det.pc_average, det.pc_average, atol=1e-2) else: with pytest.raises(ValueError, match="Hough indexing of lazy signals must"): - _ = s.hough_indexing_optimize_pc(self.detector.pc_average, self.indexer) + _ = s.hough_indexing_optimize_pc(det.pc_average, self.indexer) @pytest.mark.skipif(kp._pyebsdindex_installed, reason="pyebsdindex is installed") -class TestHoughIndexingNoPyEBSDIndex: +class TestHoughIndexingNoPyEBSDIndex: # pragma: no cover def setup_method(self): s = kp.data.nickel_ebsd_small() @@ -295,7 +326,7 @@ def test_get_indexer(self): with pytest.raises(ValueError, match="pyebsdindex must be installed"): _ = self.signal.detector.get_indexer(None) - def test_hough_indexing_raises_pyebsdindex(self): # pragma: no cover + def test_hough_indexing_raises_pyebsdindex(self): with pytest.raises(ValueError, match="pyebsdindex to be installed"): _ = self.signal.hough_indexing(None, None)