From b4b1bf2e7d203e69f33154dcd1432f2cdca7fcf6 Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 15 Feb 2018 18:39:35 +0000 Subject: [PATCH 01/11] commit test_OM --- tests/test_orientation_mapping.py | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 tests/test_orientation_mapping.py diff --git a/tests/test_orientation_mapping.py b/tests/test_orientation_mapping.py new file mode 100644 index 000000000..e81770f52 --- /dev/null +++ b/tests/test_orientation_mapping.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 The pyXem developers +# +# This file is part of pyXem. +# +# pyXem 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. +# +# pyXem 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 pyXem. If not, see . + +import numpy as np +import pytest +import pyxem as pxm +from pyxem.signals.diffraction_simulation import DiffractionSimulation +from pyxem.generators.indexation_generator import IndexationGenerator + +# This test suite is aimed at checking the basic functionality of the Omapping process, obviously to have a succesful OM process +# many other components will also need to be correct + +dps, dp_sim_list = [],[] + +# Create 4 random diffraction simulations +half_side_length = 72 +for alpha in [0,1,2,3]: + coords = (np.random.rand(5,2)-0.5)*2 #zero mean, range from -1 to +1 + dp_sim = DiffractionSimulation(coordinates=coords, + intensities=np.ones_like(coords[:,0]), + calibration=1/half_side_length) + dp_sim_list.append(dp_sim) #stores the simulations + dps.append(dp_sim.as_signal(2*half_side_length,0.075,1).data) #stores a numpy array of pattern + +dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) #now from a 2x2 array of patterns + + +library = dict() +half_shape = (half_side_length,half_side_length) +library["Phase"] = {} + +def create_library_entry(library,rotation,DiffractionSimulation): + library["Phase"][rotation] = {} + p = DiffractionSimulation #for concision + library["Phase"][rotation]['Sim'] = p + library["Phase"][rotation]['intensities'] = p.intensities + library["Phase"][rotation]['pixel_coords'] = (p.calibrated_coordinates[:,:2]+half_shape).astype(int) + library["Phase"][rotation]['pattern_norm'] = np.sum(p.intensities) + return library + + +for alpha in np.arange(0,5,1): + rotation = (alpha,0,0) + if rotation[0] < 4: + library = create_library_entry(library,rotation,dp_sim_list[rotation[0]]) + else: + local_cords = np.random.rand(5,2) + pat = DiffractionSimulation(coordinates=local_cords,intensities=np.ones_like(local_cords[:,0])) + library = create_library_entry(library,rotation,pat) + +indexer = IndexationGenerator(dp,library) +match_results = indexer.correlate() + +def test_match_results(): + # Note the random number generator may give a different assertion failure + # This should always work regardless of the RNG. + assert match_results.inav[0,0].data[0][1] == 0 + assert match_results.inav[1,0].data[0][1] == 1 + assert match_results.inav[0,1].data[0][1] == 2 + assert match_results.inav[1,1].data[0][1] == 3 + +""" Visualization Code + +peaks = match_results.map(peaks_from_best_template, + phase=["Phase"],library=library,inplace=False) +mmx,mmy = generate_marker_inputs_from_peaks(peaks) +dp.set_calibration(2/144) +dp.plot(cmap='viridis') +for mx,my in zip(mmx,mmy): + m = hs.markers.point(x=my,y=mx,color='red',marker='x') + dp.add_marker(m,plot_marker=True,permanent=True) +""" \ No newline at end of file From cc6d0998a44e98054b8116dd4f00c122a68c1721 Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 15 Feb 2018 18:41:30 +0000 Subject: [PATCH 02/11] switching x and y yet again --- pyxem/utils/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pyxem/utils/__init__.py b/pyxem/utils/__init__.py index 29afb00c2..8a2c89c4a 100644 --- a/pyxem/utils/__init__.py +++ b/pyxem/utils/__init__.py @@ -17,8 +17,6 @@ # along with pyXem. If not, see . import numpy as np -from scipy.interpolate import RectBivariateSpline - def correlate(image, pattern_dictionary): """The correlation between a diffraction pattern and a simulation. @@ -57,6 +55,6 @@ def correlate(image, pattern_dictionary): pixel_coordinates = pattern_dictionary['pixel_coords'] pattern_normalization = pattern_dictionary['pattern_norm'] - image_intensities = image[pixel_coordinates[:, 0], pixel_coordinates[:, 1]] + image_intensities = image[pixel_coordinates[:, 1], pixel_coordinates[:, 0]] - return np.dot(image_intensities,pattern_intensities)/pattern_normalization \ No newline at end of file + return np.dot(image_intensities,pattern_intensities)/pattern_normalization From 828e59bf56bd51c23291f22976c24bd26aa258d1 Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 15 Feb 2018 18:49:54 +0000 Subject: [PATCH 03/11] Increasing the number of wrong patterns under consideration --- tests/test_orientation_mapping.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_orientation_mapping.py b/tests/test_orientation_mapping.py index e81770f52..10509b5f8 100644 --- a/tests/test_orientation_mapping.py +++ b/tests/test_orientation_mapping.py @@ -54,7 +54,7 @@ def create_library_entry(library,rotation,DiffractionSimulation): return library -for alpha in np.arange(0,5,1): +for alpha in np.arange(0,10,1): rotation = (alpha,0,0) if rotation[0] < 4: library = create_library_entry(library,rotation,dp_sim_list[rotation[0]]) From a1a30e283c48eb9ba9ea1540cf47f20daf9d907c Mon Sep 17 00:00:00 2001 From: Phillip Date: Fri, 16 Feb 2018 14:01:11 +0000 Subject: [PATCH 04/11] Cleaning up the visualisation code --- tests/test_orientation_mapping.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_orientation_mapping.py b/tests/test_orientation_mapping.py index 10509b5f8..e23dd0b38 100644 --- a/tests/test_orientation_mapping.py +++ b/tests/test_orientation_mapping.py @@ -50,7 +50,7 @@ def create_library_entry(library,rotation,DiffractionSimulation): library["Phase"][rotation]['Sim'] = p library["Phase"][rotation]['intensities'] = p.intensities library["Phase"][rotation]['pixel_coords'] = (p.calibrated_coordinates[:,:2]+half_shape).astype(int) - library["Phase"][rotation]['pattern_norm'] = np.sum(p.intensities) + library["Phase"][rotation]['pattern_norm'] = np.sqrt(np.dot(p.intensities,p.intensities)) return library @@ -76,6 +76,10 @@ def test_match_results(): """ Visualization Code +from pyxem.utils.sim_utils import peaks_from_best_template +from pyxem.utils.plot import generate_marker_inputs_from_peaks +import hyperspy.api as hs + peaks = match_results.map(peaks_from_best_template, phase=["Phase"],library=library,inplace=False) mmx,mmy = generate_marker_inputs_from_peaks(peaks) @@ -84,4 +88,5 @@ def test_match_results(): for mx,my in zip(mmx,mmy): m = hs.markers.point(x=my,y=mx,color='red',marker='x') dp.add_marker(m,plot_marker=True,permanent=True) + """ \ No newline at end of file From 76c9a45e1cc25b52c22be0062a48f4f1984475b2 Mon Sep 17 00:00:00 2001 From: Phillip Date: Fri, 16 Feb 2018 18:28:05 +0000 Subject: [PATCH 05/11] Manual visualisation test for confidence --- tests/test_marker_plotting.py | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/test_marker_plotting.py diff --git a/tests/test_marker_plotting.py b/tests/test_marker_plotting.py new file mode 100644 index 000000000..b22aacf81 --- /dev/null +++ b/tests/test_marker_plotting.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 The pyXem developers +# +# This file is part of pyXem. +# +# pyXem 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. +# +# pyXem 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 pyXem. If not, see . + +import numpy as np +import pytest +import pyxem as pxm +import hyperspy.api as hs +from pyxem.signals.diffraction_simulation import DiffractionSimulation +from pyxem.utils.plot import generate_marker_inputs_from_peaks + +### When you run this the markers should land at the center of the peaks, simple as. + +dps, dp_cord_list = [],[] + +# Create 4 random diffraction simulations +half_side_length = 72 +for alpha in [0,1,2,3]: + coords = (np.random.rand(5,2)-0.5)*2 #zero mean, range from -1 to +1 + dp_sim = DiffractionSimulation(coordinates=coords, + intensities=np.ones_like(coords[:,0]), + calibration=1/half_side_length) + dp_cord_list.append(dp_sim.coordinates[:,:2]) #stores the simulations coords + dps.append(dp_sim.as_signal(2*half_side_length,0.075,1).data) #stores a numpy array of pattern + +dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) #now from a 2x2 array of patterns +peaks = hs.signals.Signal2D(np.array([dp_cord_list[0:2],dp_cord_list[2:]])) + +mmx,mmy = generate_marker_inputs_from_peaks(peaks) +dp.set_calibration(2/144) +dp.plot(cmap='viridis') +for mx,my in zip(mmx,mmy): + m = hs.markers.point(x=mx,y=my,color='red',marker='x') + dp.add_marker(m,plot_marker=True,permanent=True) + +def test_marker_placement_correct(): + #This is human assessed, if you see this comment, you should check it + assert True \ No newline at end of file From 02610730e82e29747ee67bae0f76d0b54812c4c2 Mon Sep 17 00:00:00 2001 From: Phillip Date: Fri, 16 Feb 2018 18:28:27 +0000 Subject: [PATCH 06/11] Refoldering --- tests/Orientation_mapping/OM_fixtures.py | 41 +++++++++ tests/Orientation_mapping/test_OM_twins.py | 81 ++++++++++++++++ .../test_orientation_mapping.py | 92 +++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 tests/Orientation_mapping/OM_fixtures.py create mode 100644 tests/Orientation_mapping/test_OM_twins.py create mode 100644 tests/Orientation_mapping/test_orientation_mapping.py diff --git a/tests/Orientation_mapping/OM_fixtures.py b/tests/Orientation_mapping/OM_fixtures.py new file mode 100644 index 000000000..5352c6269 --- /dev/null +++ b/tests/Orientation_mapping/OM_fixtures.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 The pyXem developers +# +# This file is part of pyXem. +# +# pyXem 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. +# +# pyXem 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 pyXem. If not, see . + +import pymatgen as pmg +import numpy as np + +half_side_length = 72 + +def create_GaAs(): + Ga = pmg.Element("Ga") + As = pmg.Element("As") + lattice = pmg.Lattice.cubic(5.6535) + return pmg.Structure.from_spacegroup("F23",lattice, [Ga,As], [[0, 0, 0],[0.25,0.25,0.25]]) + +def create_twin_angles(): + " Returns a list contains two sep by rotation of 20" + twin_angles_1 = [0,0,0] + twin_angles_2 = np.add(twin_angles_1,[20,0,0]) + return [twin_angles_1,twin_angles_2] + +def build_linear_grid_in_euler(alpha_max,beta_max,gamma_max,resolution): + a = np.arange(0,alpha_max,step=resolution) + b = np.arange(0,beta_max,step=resolution) + c = np.arange(0,gamma_max,step=resolution) + from itertools import product + return list(product(a,b,c)) \ No newline at end of file diff --git a/tests/Orientation_mapping/test_OM_twins.py b/tests/Orientation_mapping/test_OM_twins.py new file mode 100644 index 000000000..8fdf3a00f --- /dev/null +++ b/tests/Orientation_mapping/test_OM_twins.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 The pyXem developers +# +# This file is part of pyXem. +# +# pyXem 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. +# +# pyXem 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 pyXem. If not, see . + +import numpy as np +import pytest +import pyxem as pxm + +from pyxem.signals.diffraction_simulation import DiffractionSimulation +from pyxem.generators.indexation_generator import IndexationGenerator +from transforms3d.euler import euler2axangle +from pymatgen.transformations.standard_transformations import RotationTransformation +from OM_fixtures import create_GaAs,create_twin_angles,half_side_length, build_linear_grid_in_euler +from pyxem.utils.sim_utils import peaks_from_best_template +from pyxem.utils.plot import generate_marker_inputs_from_peaks +import hyperspy.api as hs + +structure = create_GaAs() +edc = pxm.DiffractionGenerator(300, 5e-2) + +dps = [] +for orientation in create_twin_angles()*2: + axis, angle = euler2axangle(orientation[0], orientation[1],orientation[2], 'rzxz') + rotation = RotationTransformation(axis, angle,angle_in_radians=True) + rotated_structure = rotation.apply_transformation(structure) + data = edc.calculate_ed_data(rotated_structure, + reciprocal_radius=0.9, #avoiding a reflection issue + with_direct_beam=False) + dps.append(data.as_signal(2*half_side_length,0.025,1).data) + +dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) +dp.set_calibration(1/half_side_length) + +diff_gen = pxm.DiffractionLibraryGenerator(edc) +rot_list = build_linear_grid_in_euler(20,5,5,1) +struc_lib = dict() +struc_lib["A"] = (structure,rot_list) +library = diff_gen.get_diffraction_library(struc_lib, + calibration=1/half_side_length, + reciprocal_radius=0.6, + half_shape=(half_side_length,half_side_length), + representation='euler', + with_direct_beam=False) + +indexer = IndexationGenerator(dp,library) +match_results = indexer.correlate() + +def test_match_results(): + assert np.all(match_results.inav[0,0].data[0,1:4] == np.array([0,0,0])) + assert match_results.inav[1,1].data[0,2] == 0 #no rotation in z for the twinning + +# Visualization Code + +peaks = match_results.map(peaks_from_best_template, + phase=["A"],library=library,inplace=False) + +def test_peak_from_best_template(): + # Will fail if top line of test_match_results failed + assert peaks.inav[0,0] == library["A"][(0,0,0)]['Sim'].coordinates[:,:2] + +mmx,mmy = generate_marker_inputs_from_peaks(peaks) +dp.plot(cmap='viridis') +for mx,my in zip(mmx,mmy): + ## THERE IS A GOTCHA HERE DUE TO WEAK REFLECTION + m = hs.markers.point(x=mx,y=my,color='red',marker='x') #see visual test + dp.add_marker(m,plot_marker=True,permanent=True) + diff --git a/tests/Orientation_mapping/test_orientation_mapping.py b/tests/Orientation_mapping/test_orientation_mapping.py new file mode 100644 index 000000000..ba9498a02 --- /dev/null +++ b/tests/Orientation_mapping/test_orientation_mapping.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 The pyXem developers +# +# This file is part of pyXem. +# +# pyXem 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. +# +# pyXem 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 pyXem. If not, see . + +import numpy as np +import pytest +import pyxem as pxm +from pyxem.signals.diffraction_simulation import DiffractionSimulation +from pyxem.generators.indexation_generator import IndexationGenerator + +# This test suite is aimed at checking the basic functionality of the Omapping process, obviously to have a succesful OM process +# many other components will also need to be correct + +dps, dp_sim_list = [],[] + +# Create 4 random diffraction simulations +half_side_length = 72 +for alpha in [0,1,2,3]: + coords = (np.random.rand(5,2)-0.5)*2 #zero mean, range from -1 to +1 + dp_sim = DiffractionSimulation(coordinates=coords, + intensities=np.ones_like(coords[:,0]), + calibration=1/half_side_length) + dp_sim_list.append(dp_sim) #stores the simulations + dps.append(dp_sim.as_signal(2*half_side_length,0.075,1).data) #stores a numpy array of pattern + +dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) #now from a 2x2 array of patterns + + +library = dict() +half_shape = (half_side_length,half_side_length) +library["Phase"] = {} + +def create_library_entry(library,rotation,DiffractionSimulation): + library["Phase"][rotation] = {} + p = DiffractionSimulation #for concision + library["Phase"][rotation]['Sim'] = p + library["Phase"][rotation]['intensities'] = p.intensities + library["Phase"][rotation]['pixel_coords'] = (p.calibrated_coordinates[:,:2]+half_shape).astype(int) + library["Phase"][rotation]['pattern_norm'] = np.sqrt(np.dot(p.intensities,p.intensities)) + return library + + +for alpha in np.arange(0,10,1): + rotation = (alpha,0,0) + if rotation[0] < 4: + library = create_library_entry(library,rotation,dp_sim_list[rotation[0]]) + else: + local_cords = np.random.rand(5,2) + pat = DiffractionSimulation(coordinates=local_cords,intensities=np.ones_like(local_cords[:,0])) + library = create_library_entry(library,rotation,pat) + +indexer = IndexationGenerator(dp,library) +match_results = indexer.correlate() + +def test_match_results(): + # Note the random number generator may give a different assertion failure + # This should always work regardless of the RNG. + assert match_results.inav[0,0].data[0][1] == 0 + assert match_results.inav[1,0].data[0][1] == 1 + assert match_results.inav[0,1].data[0][1] == 2 + assert match_results.inav[1,1].data[0][1] == 3 + + +# Visualization Code + +from pyxem.utils.sim_utils import peaks_from_best_template +from pyxem.utils.plot import generate_marker_inputs_from_peaks +import hyperspy.api as hs + +peaks = match_results.map(peaks_from_best_template, + phase=["Phase"],library=library,inplace=False) +mmx,mmy = generate_marker_inputs_from_peaks(peaks) +dp.set_calibration(2/144) +dp.plot(cmap='viridis') +for mx,my in zip(mmx,mmy): + m = hs.markers.point(x=mx,y=my,color='red',marker='x') + dp.add_marker(m,plot_marker=True,permanent=True) + From 3ba471eb20cb5ec4848e3444f64cc96f5e251274 Mon Sep 17 00:00:00 2001 From: Phillip Date: Fri, 16 Feb 2018 18:28:47 +0000 Subject: [PATCH 07/11] Deletion due to refoldering --- tests/test_orientation_mapping.py | 92 ------------------------------- 1 file changed, 92 deletions(-) delete mode 100644 tests/test_orientation_mapping.py diff --git a/tests/test_orientation_mapping.py b/tests/test_orientation_mapping.py deleted file mode 100644 index e23dd0b38..000000000 --- a/tests/test_orientation_mapping.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2018 The pyXem developers -# -# This file is part of pyXem. -# -# pyXem 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. -# -# pyXem 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 pyXem. If not, see . - -import numpy as np -import pytest -import pyxem as pxm -from pyxem.signals.diffraction_simulation import DiffractionSimulation -from pyxem.generators.indexation_generator import IndexationGenerator - -# This test suite is aimed at checking the basic functionality of the Omapping process, obviously to have a succesful OM process -# many other components will also need to be correct - -dps, dp_sim_list = [],[] - -# Create 4 random diffraction simulations -half_side_length = 72 -for alpha in [0,1,2,3]: - coords = (np.random.rand(5,2)-0.5)*2 #zero mean, range from -1 to +1 - dp_sim = DiffractionSimulation(coordinates=coords, - intensities=np.ones_like(coords[:,0]), - calibration=1/half_side_length) - dp_sim_list.append(dp_sim) #stores the simulations - dps.append(dp_sim.as_signal(2*half_side_length,0.075,1).data) #stores a numpy array of pattern - -dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) #now from a 2x2 array of patterns - - -library = dict() -half_shape = (half_side_length,half_side_length) -library["Phase"] = {} - -def create_library_entry(library,rotation,DiffractionSimulation): - library["Phase"][rotation] = {} - p = DiffractionSimulation #for concision - library["Phase"][rotation]['Sim'] = p - library["Phase"][rotation]['intensities'] = p.intensities - library["Phase"][rotation]['pixel_coords'] = (p.calibrated_coordinates[:,:2]+half_shape).astype(int) - library["Phase"][rotation]['pattern_norm'] = np.sqrt(np.dot(p.intensities,p.intensities)) - return library - - -for alpha in np.arange(0,10,1): - rotation = (alpha,0,0) - if rotation[0] < 4: - library = create_library_entry(library,rotation,dp_sim_list[rotation[0]]) - else: - local_cords = np.random.rand(5,2) - pat = DiffractionSimulation(coordinates=local_cords,intensities=np.ones_like(local_cords[:,0])) - library = create_library_entry(library,rotation,pat) - -indexer = IndexationGenerator(dp,library) -match_results = indexer.correlate() - -def test_match_results(): - # Note the random number generator may give a different assertion failure - # This should always work regardless of the RNG. - assert match_results.inav[0,0].data[0][1] == 0 - assert match_results.inav[1,0].data[0][1] == 1 - assert match_results.inav[0,1].data[0][1] == 2 - assert match_results.inav[1,1].data[0][1] == 3 - -""" Visualization Code - -from pyxem.utils.sim_utils import peaks_from_best_template -from pyxem.utils.plot import generate_marker_inputs_from_peaks -import hyperspy.api as hs - -peaks = match_results.map(peaks_from_best_template, - phase=["Phase"],library=library,inplace=False) -mmx,mmy = generate_marker_inputs_from_peaks(peaks) -dp.set_calibration(2/144) -dp.plot(cmap='viridis') -for mx,my in zip(mmx,mmy): - m = hs.markers.point(x=my,y=mx,color='red',marker='x') - dp.add_marker(m,plot_marker=True,permanent=True) - -""" \ No newline at end of file From a6f87d094d31cc120d3b9be7bd6a92633e9036a5 Mon Sep 17 00:00:00 2001 From: Phillip Date: Fri, 16 Feb 2018 18:29:30 +0000 Subject: [PATCH 08/11] These xy errors go all the way to the top, see tests for confirmation that we are back on a safer pathway --- pyxem/utils/plot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyxem/utils/plot.py b/pyxem/utils/plot.py index 756fb9552..021a7802e 100644 --- a/pyxem/utils/plot.py +++ b/pyxem/utils/plot.py @@ -117,7 +117,7 @@ def generate_marker_inputs_from_peaks(peaks): pad = np.array(list(itertools.zip_longest(*np.concatenate(peaks.data),fillvalue=[np.nan,np.nan]))) pad = pad.reshape((max_peak_len),peaks.data.shape[0],peaks.data.shape[1],2) xy_cords = np.transpose(pad,[3,0,1,2]) #move the x,y pairs to the front - x = xy_cords[1] - y = xy_cords[0] + x = xy_cords[0] + y = xy_cords[1] return x,y From 57cc3593e1be92b5c4f79b6c48b0ef6fe325984b Mon Sep 17 00:00:00 2001 From: pc494 Date: Sat, 17 Feb 2018 10:52:00 +0000 Subject: [PATCH 09/11] Updating build instructions --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5fe6c1365..602a47114 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,11 @@ language: python python: - - "3.5" - "3.6" sudo: false before_install: - - "pip install sphinx hyperspy pymatgen Cython transforms3d lxml" + - "pip install sphinx hyperspy pymatgen Cython transforms3d lxml ipywidgets" - "pip install sphinx_bootstrap_theme" install: From 2b43f15c1c6d780411fe71894a1d1d7534474c29 Mon Sep 17 00:00:00 2001 From: pc494 Date: Sat, 17 Feb 2018 16:39:54 +0000 Subject: [PATCH 10/11] Holding commit for a bad (albeit passing) test suite for OM --- tests/Orientation_mapping/OM_fixtures.py | 28 ++++- tests/Orientation_mapping/test_OM_twins.py | 81 ------------ ...py => test_orientation_mapping_nonphys.py} | 0 .../test_orientation_mapping_phys.py | 115 ++++++++++++++++++ 4 files changed, 137 insertions(+), 87 deletions(-) delete mode 100644 tests/Orientation_mapping/test_OM_twins.py rename tests/Orientation_mapping/{test_orientation_mapping.py => test_orientation_mapping_nonphys.py} (100%) create mode 100644 tests/Orientation_mapping/test_orientation_mapping_phys.py diff --git a/tests/Orientation_mapping/OM_fixtures.py b/tests/Orientation_mapping/OM_fixtures.py index 5352c6269..c58dda133 100644 --- a/tests/Orientation_mapping/OM_fixtures.py +++ b/tests/Orientation_mapping/OM_fixtures.py @@ -18,6 +18,9 @@ import pymatgen as pmg import numpy as np +import pyxem as pxm +from transforms3d.euler import euler2axangle +from pymatgen.transformations.standard_transformations import RotationTransformation half_side_length = 72 @@ -27,15 +30,28 @@ def create_GaAs(): lattice = pmg.Lattice.cubic(5.6535) return pmg.Structure.from_spacegroup("F23",lattice, [Ga,As], [[0, 0, 0],[0.25,0.25,0.25]]) -def create_twin_angles(): - " Returns a list contains two sep by rotation of 20" - twin_angles_1 = [0,0,0] - twin_angles_2 = np.add(twin_angles_1,[20,0,0]) - return [twin_angles_1,twin_angles_2] +def create_pair(angle_start,angle_change): + """ Lists for angles """ + angle_2 = np.add(angle_start,angle_change) + return [angle_start,angle_start,angle_2,angle_2] def build_linear_grid_in_euler(alpha_max,beta_max,gamma_max,resolution): a = np.arange(0,alpha_max,step=resolution) b = np.arange(0,beta_max,step=resolution) c = np.arange(0,gamma_max,step=resolution) from itertools import product - return list(product(a,b,c)) \ No newline at end of file + return list(product(a,b,c)) + +def create_sample(edc,structure,angle_start,angle_change): + dps = [] + for orientation in create_pair(angle_start,angle_change): + axis, angle = euler2axangle(orientation[0], orientation[1],orientation[2], 'rzxz') + rotation = RotationTransformation(axis, angle,angle_in_radians=True) + rotated_structure = rotation.apply_transformation(structure) + data = edc.calculate_ed_data(rotated_structure, + reciprocal_radius=0.9, #avoiding a reflection issue + with_direct_beam=False) + dps.append(data.as_signal(2*half_side_length,0.025,1).data) + dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) + dp.set_calibration(1/half_side_length) + return dp \ No newline at end of file diff --git a/tests/Orientation_mapping/test_OM_twins.py b/tests/Orientation_mapping/test_OM_twins.py deleted file mode 100644 index 8fdf3a00f..000000000 --- a/tests/Orientation_mapping/test_OM_twins.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2018 The pyXem developers -# -# This file is part of pyXem. -# -# pyXem 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. -# -# pyXem 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 pyXem. If not, see . - -import numpy as np -import pytest -import pyxem as pxm - -from pyxem.signals.diffraction_simulation import DiffractionSimulation -from pyxem.generators.indexation_generator import IndexationGenerator -from transforms3d.euler import euler2axangle -from pymatgen.transformations.standard_transformations import RotationTransformation -from OM_fixtures import create_GaAs,create_twin_angles,half_side_length, build_linear_grid_in_euler -from pyxem.utils.sim_utils import peaks_from_best_template -from pyxem.utils.plot import generate_marker_inputs_from_peaks -import hyperspy.api as hs - -structure = create_GaAs() -edc = pxm.DiffractionGenerator(300, 5e-2) - -dps = [] -for orientation in create_twin_angles()*2: - axis, angle = euler2axangle(orientation[0], orientation[1],orientation[2], 'rzxz') - rotation = RotationTransformation(axis, angle,angle_in_radians=True) - rotated_structure = rotation.apply_transformation(structure) - data = edc.calculate_ed_data(rotated_structure, - reciprocal_radius=0.9, #avoiding a reflection issue - with_direct_beam=False) - dps.append(data.as_signal(2*half_side_length,0.025,1).data) - -dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) -dp.set_calibration(1/half_side_length) - -diff_gen = pxm.DiffractionLibraryGenerator(edc) -rot_list = build_linear_grid_in_euler(20,5,5,1) -struc_lib = dict() -struc_lib["A"] = (structure,rot_list) -library = diff_gen.get_diffraction_library(struc_lib, - calibration=1/half_side_length, - reciprocal_radius=0.6, - half_shape=(half_side_length,half_side_length), - representation='euler', - with_direct_beam=False) - -indexer = IndexationGenerator(dp,library) -match_results = indexer.correlate() - -def test_match_results(): - assert np.all(match_results.inav[0,0].data[0,1:4] == np.array([0,0,0])) - assert match_results.inav[1,1].data[0,2] == 0 #no rotation in z for the twinning - -# Visualization Code - -peaks = match_results.map(peaks_from_best_template, - phase=["A"],library=library,inplace=False) - -def test_peak_from_best_template(): - # Will fail if top line of test_match_results failed - assert peaks.inav[0,0] == library["A"][(0,0,0)]['Sim'].coordinates[:,:2] - -mmx,mmy = generate_marker_inputs_from_peaks(peaks) -dp.plot(cmap='viridis') -for mx,my in zip(mmx,mmy): - ## THERE IS A GOTCHA HERE DUE TO WEAK REFLECTION - m = hs.markers.point(x=mx,y=my,color='red',marker='x') #see visual test - dp.add_marker(m,plot_marker=True,permanent=True) - diff --git a/tests/Orientation_mapping/test_orientation_mapping.py b/tests/Orientation_mapping/test_orientation_mapping_nonphys.py similarity index 100% rename from tests/Orientation_mapping/test_orientation_mapping.py rename to tests/Orientation_mapping/test_orientation_mapping_nonphys.py diff --git a/tests/Orientation_mapping/test_orientation_mapping_phys.py b/tests/Orientation_mapping/test_orientation_mapping_phys.py new file mode 100644 index 000000000..feb29762b --- /dev/null +++ b/tests/Orientation_mapping/test_orientation_mapping_phys.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 The pyXem developers +# +# This file is part of pyXem. +# +# pyXem 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. +# +# pyXem 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 pyXem. If not, see . + +import numpy as np +import pytest +import pyxem as pxm +import hyperspy.api as hs +from pyxem.signals.diffraction_simulation import DiffractionSimulation +from pyxem.generators.indexation_generator import IndexationGenerator +from OM_fixtures import create_GaAs, build_linear_grid_in_euler,half_side_length,create_sample +from pyxem.utils.sim_utils import peaks_from_best_template +from pyxem.utils.plot import generate_marker_inputs_from_peaks + +def build_structure_lib(structure,rot_list): + struc_lib = dict() + struc_lib["A"] = (structure,rot_list) + return struc_lib + +edc = pxm.DiffractionGenerator(300, 5e-2) +diff_gen = pxm.DiffractionLibraryGenerator(edc) +structure = create_GaAs() +rot_list = build_linear_grid_in_euler(12,10,5,1) +struc_lib = build_structure_lib(structure,rot_list) +library = diff_gen.get_diffraction_library(struc_lib, + calibration=1/half_side_length, + reciprocal_radius=0.6, + half_shape=(half_side_length,half_side_length), + representation='euler', + with_direct_beam=False) + +### Test two rotation direction on axis and an arbitary rotation direction + +""" +Case A - +We rotate about 4 on the first, z axis, as we don't rotate around x at all we can +then rotate again around the second z axis in a similar way +""" + +dp = create_sample(edc,structure,[0,0,0],[4,0,0]) +indexer = IndexationGenerator(dp,library) +match_results_A = indexer.correlate() + +def test_match_results_essential(): + assert np.all(match_results.inav[0,0] == match_results.inav[1,0]) + assert np.all(match_results.inav[0,1] == match_results.inav[1,1]) + +def test_peak_from_best_template(): + # Will fail if top line of test_match_results failed + peaks = match_results.map(peaks_from_best_template,phase=["A"],library=library,inplace=False) + assert peaks.inav[0,0] == library["A"][(0,0,0)]['Sim'].coordinates[:,:2] + +def test_match_results_caseA(): + assert np.all(match_results_A.inav[0,0].data[0,1:4] == np.array([0,0,0])) + assert match_results_A.inav[1,1].data[0,2] == 0 #no rotation in z for the twinning + #rotation totals must equal 4, and each must give the same coefficient + assert np.all(np.sum(match_results_A.inav[1,1].data[:,1:4],axis=1) == 4) + assert np.all(match_results_A.inav[1,1].data[:,4] == match_results_A.inav[1,1].data[0,4]) + +#test_match_results_essential() +#test_peak_from_best_template() +test_match_results_caseA() + +""" +Case B - +We rotate all 3 and test that we get good answers +""" + +dp = create_sample(edc,structure,[0,0,0],[3,7,1]) +indexer = IndexationGenerator(dp,library) +match_results = indexer.correlate() + +test_match_results_essential() + +def test_match_results_caseB(): + assert np.all(match_results.inav[1,1].data[0,1:4] == np.array([3,7,1])) + +test_match_results_caseB() + +""" Case C - Use non-integers """ + +dp = create_sample(edc,structure,[0,0,0],[3,7.01,0.99]) +indexer = IndexationGenerator(dp,library) +match_results = indexer.correlate() + +test_match_results_essential() + +def test_match_results_caseC(): + assert np.all(match_results.inav[1,1].data[0,1:4] == np.array([3,7,1])) + +test_match_results_caseC() + +# Visualization Code +peaks = match_results.map(peaks_from_best_template,phase=["A"],library=library,inplace=False) +mmx,mmy = generate_marker_inputs_from_peaks(peaks) +dp.plot(cmap='viridis') +for mx,my in zip(mmx,mmy): + ## THERE IS A GOTCHA HERE DUE TO WEAK REFLECTION + m = hs.markers.point(x=mx,y=my,color='red',marker='x') #see visual test + dp.add_marker(m,plot_marker=True,permanent=True) + From 47f2379c19e7358f320c8243a37f70c5f1b878a0 Mon Sep 17 00:00:00 2001 From: pc494 Date: Sat, 17 Feb 2018 17:56:11 +0000 Subject: [PATCH 11/11] Discovering a potential inter-machine conflict --- tests/test_marker_plotting.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/tests/test_marker_plotting.py b/tests/test_marker_plotting.py index b22aacf81..0cb58ae77 100644 --- a/tests/test_marker_plotting.py +++ b/tests/test_marker_plotting.py @@ -25,21 +25,43 @@ ### When you run this the markers should land at the center of the peaks, simple as. -dps, dp_cord_list = [],[] +dps, dp_cord_list, dp_calib_cord = [],[],[] # Create 4 random diffraction simulations half_side_length = 72 for alpha in [0,1,2,3]: - coords = (np.random.rand(5,2)-0.5)*2 #zero mean, range from -1 to +1 + coords = (np.random.rand(1,2)-0.5)*2 #zero mean, range from -1 to +1 dp_sim = DiffractionSimulation(coordinates=coords, intensities=np.ones_like(coords[:,0]), calibration=1/half_side_length) dp_cord_list.append(dp_sim.coordinates[:,:2]) #stores the simulations coords + dp_calib_cord.append(dp_sim.calibrated_coordinates[:,:2]) dps.append(dp_sim.as_signal(2*half_side_length,0.075,1).data) #stores a numpy array of pattern -dp = pxm.ElectronDiffraction([dps[0:2],dps[2:]]) #now from a 2x2 array of patterns +def test_calibrated_coords_are_correct(): + # Explicit is best + for i in [0,1,2,3]: + dp_single = dps[i] + x,y = dp_calib_cord[i][0][0].astype(int),dp_calib_cord[i][0][1].astype(int) + ### ALARM BELLS - you need to swap y and x here to get a pass + assert dp_single[y+half_side_length,x+half_side_length] > 0.3 + # This just tested that the peak is where it should be + +""" This is py36 on Toshibia Laptop +matplotlib 2.1.0 +numpy 1.13.3 +hyperspy 1.4.dev0+git.96.g2900677 +""" + +# See above +dp_cord_list = [np.flip(x,axis=1) for x in dp_cord_list ] + +# And onwards +dp = pxm.ElectronDiffraction(np.array([dps[0:2],dps[2:]])) #now from a 2x2 array of patterns peaks = hs.signals.Signal2D(np.array([dp_cord_list[0:2],dp_cord_list[2:]])) +### And plot! + mmx,mmy = generate_marker_inputs_from_peaks(peaks) dp.set_calibration(2/144) dp.plot(cmap='viridis') @@ -49,4 +71,4 @@ def test_marker_placement_correct(): #This is human assessed, if you see this comment, you should check it - assert True \ No newline at end of file + assert True