From 0c1018c5906d1ef9d14931ccc6be6e3f123e34cb Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 30 Jan 2020 18:19:24 +0000 Subject: [PATCH 01/47] First commit of zap_map_generator --- diffsims/generators/zap_map_generator.py | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 diffsims/generators/zap_map_generator.py diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py new file mode 100644 index 00000000..a2b42a7a --- /dev/null +++ b/diffsims/generators/zap_map_generator.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2017-2019 The diffsims developers +# +# This file is part of diffsims. +# +# diffsims 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. +# +# diffsims 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 diffsims. If not, see . + + +def generate_zap_map(structure,simulator,density): + """ + Produces a number of zone axis patterns for a structure + + Parameters + ---------- + structure : diffpy.structure + + simulator : diffsims.diffraction_generator + + density : str + '3' for the corners or '7' (corners + 3 midpoints + 1 centroid) + + Returns + ------- + zap_dictionary : dict + Keys are zone axes, values are simulations + """ + pass From 6c412b5564171c25b51fd70e558bf4eb814b8a7e Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 30 Jan 2020 18:20:50 +0000 Subject: [PATCH 02/47] Copy+Paste of developmental rotation_finder --- diffsims/generators/zap_map_generator.py | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index a2b42a7a..2c0a98a4 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -16,6 +16,40 @@ # You should have received a copy of the GNU General Public License # along with diffsims. If not, see . +import numpy as np +from transforms3d.euler import axangle2euler + +def get_rotation_from_z(structure,d): + """ + Finds the rotation that takes [001] to a given zone axis. + + Parameters + ---------- + structure : + + d : + + + Returns + ------- + euler_angles : tuple + 'rzxz' in degrees + + See Also + -------- + generate_zap_map + get_grid_around_beam_direction + """ + + if np.dot(d,[0,0,1]) == np.linalg.norm(d): + return (0,0,1) + + cd = structure.lattice.cartesian(d) + cd = cd / np.linalg.norm(cd) + v = np.cross(d,cd) + angle = np.arccos(np.dot([0,0,1],cd)) + euler = axangle2euler(v,angle,axes='rzxz') + return np.rad2deg(euler) def generate_zap_map(structure,simulator,density): """ From 104e869aa9a78edf4d4f4ef97202516316605efc Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 30 Jan 2020 18:26:24 +0000 Subject: [PATCH 03/47] Tidying the scope up a bit --- diffsims/generators/zap_map_generator.py | 28 +++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 2c0a98a4..2134b4d0 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -19,16 +19,16 @@ import numpy as np from transforms3d.euler import axangle2euler -def get_rotation_from_z(structure,d): +def get_rotation_from_z(structure,direction): """ Finds the rotation that takes [001] to a given zone axis. Parameters ---------- - structure : - - d : + structure : diffpy.structure + direction : array like + [UVW] Returns ------- @@ -41,14 +41,17 @@ def get_rotation_from_z(structure,d): get_grid_around_beam_direction """ - if np.dot(d,[0,0,1]) == np.linalg.norm(d): + # Case where we don't need a rotation + if np.dot(direction,[0,0,1]) == np.linalg.norm(d): return (0,0,1) - cd = structure.lattice.cartesian(d) - cd = cd / np.linalg.norm(cd) - v = np.cross(d,cd) - angle = np.arccos(np.dot([0,0,1],cd)) - euler = axangle2euler(v,angle,axes='rzxz') + # Normalize our directions + cartesian_direction = structure.lattice.cartesian(direction) + cartesian_direction = cartesian_direction / np.linalg.norm(cartesian_direction) + + rotation_axis = np.cross([0,0,1],cartesian_direction) + rotation_angle = np.arccos(np.dot([0,0,1],cartesian_direction)) + euler = axangle2euler(rotation_axis,rotation_angle,axes='rzxz') return np.rad2deg(euler) def generate_zap_map(structure,simulator,density): @@ -69,4 +72,9 @@ def generate_zap_map(structure,simulator,density): zap_dictionary : dict Keys are zone axes, values are simulations """ + # generate list of zone axes directions + # run a loop over these that + # (a) extracts the rotation + # (b) calculates the simulation + pass From 178a6944ad0f150306f98caa53488677fbcd59da Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 30 Jan 2020 23:54:54 +0000 Subject: [PATCH 04/47] Scopes out tests for get_rotation_from_z --- .../test_generators/test_zap_map_generator.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 diffsims/tests/test_generators/test_zap_map_generator.py diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py new file mode 100644 index 00000000..98ea2d95 --- /dev/null +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2017-2019 The diffsims developers +# +# This file is part of diffsims. +# +# diffsims 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. +# +# diffsims 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 diffsims. If not, see . + +import pytest + +from diffsims.generators.zap_map_generator import get_rotation_from_z + +@pytest.mark.parametrize("sample_system",[cubic]) +def test_zero_rotation_cases(sample_system): + r_test = get_rotation_from_z(sample_system,[0,0,2]) + assert r_test == (0,0,0) + +class TestOrthonormals: + + def test_rotation_to_x_axis(self): + r_to_x = get_rotation_from_z(sample_system,[0,1,0]) + assert r_test == + + def test_rotation_to_y_axis(self): + r_to_y = get_rotation_from_z(sample_system,[1,0,0]) + assert r_test + + def test_rotations_to_yz(self): + """ We rotate from z towards y, in the cubic case the angle + will be 45, ---- """ + r_to_yz = get_rotation_from_z(sample_system,[0,1,1]) + cos_angle = np.cos(np.deg2rad(r_to_yz[2])) + cos_lattice = sample_system.b / sample_system.c + assert cos_angle == cos_lattice + + def test_rotation_to_111(self): + """ Cubic case is known Z for 45° and around X by 54.74° """ + +class TestHexagonal: + """ Results are taken from """ + + def test_rotation_to_streographic_corner_a(): + pass + def test_rotation_to_streographic_corner_b(): + pass From 2fce4a0b279d8ae56f677530de97e8eb15c85be4 Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 30 Jan 2020 23:55:09 +0000 Subject: [PATCH 05/47] [skip ci] fix typo --- diffsims/generators/zap_map_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 2134b4d0..32659049 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -43,7 +43,7 @@ def get_rotation_from_z(structure,direction): # Case where we don't need a rotation if np.dot(direction,[0,0,1]) == np.linalg.norm(d): - return (0,0,1) + return (0,0,0) # Normalize our directions cartesian_direction = structure.lattice.cartesian(direction) From fc052f640b7eff3265f4db909437632fe8d3db7b Mon Sep 17 00:00:00 2001 From: pc494 Date: Fri, 31 Jan 2020 00:02:13 +0000 Subject: [PATCH 06/47] Expanding the zap_map_generator a little --- diffsims/generators/zap_map_generator.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 32659049..a388a0c5 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -67,14 +67,22 @@ def generate_zap_map(structure,simulator,density): density : str '3' for the corners or '7' (corners + 3 midpoints + 1 centroid) + **kwargs : + keyword arguments to be passed to simulator.calculate_ed_data() Returns ------- zap_dictionary : dict Keys are zone axes, values are simulations """ + if reciprocal_radius not in kwargs.keys(): + # make sensible guess using the lattice parameters of structure + # generate list of zone axes directions # run a loop over these that - # (a) extracts the rotation - # (b) calculates the simulation + zap_dictionary = {} + for direction in direction_list: + rotation_rzxz = get_rotation_from_z(structure,direction) + simulation = simulator.calculate_ed_data(structure,reciprocal_radius,rotation=rotation_rzxz,**kwargs) + # adds the direction and simulation to dictionary pass From 4fba6f0c0da9567ae6572016a6de82fae0154f57 Mon Sep 17 00:00:00 2001 From: pc494 Date: Fri, 31 Jan 2020 00:16:41 +0000 Subject: [PATCH 07/47] [skip ci] Sizeable scope for zap_map_generator --- diffsims/generators/zap_map_generator.py | 36 ++++++++++++++++++------ 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index a388a0c5..b1b0956d 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -54,6 +54,27 @@ def get_rotation_from_z(structure,direction): euler = axangle2euler(rotation_axis,rotation_angle,axes='rzxz') return np.rad2deg(euler) +def get_three_on_widest_dimension(structure): + # make sensible guess using the lattice parameters of structure + # gets three on spots (100) (200) and (300) for the longest (real space) cell direction + return reciprocal_radius + +def generate_directional_patterns(structure,simulator,direction_list): + """ + """ + + if reciprocal_radius not in kwargs.keys(): + reciprocal_radius = get_three_on_widest_dimension(structure) + else: + reciprocal_radius = kwargs['reciprocal_radius'] + + direction_dictionary = {} + for direction in direction_list: + rotation_rzxz = get_rotation_from_z(structure,direction) + simulation = simulator.calculate_ed_data(structure,reciprocal_radius,rotation=rotation_rzxz,**kwargs) + # adds the direction and simulation to dictionary + return direction_dictionary + def generate_zap_map(structure,simulator,density): """ Produces a number of zone axis patterns for a structure @@ -69,20 +90,19 @@ def generate_zap_map(structure,simulator,density): **kwargs : keyword arguments to be passed to simulator.calculate_ed_data() + Returns ------- zap_dictionary : dict Keys are zone axes, values are simulations """ - if reciprocal_radius not in kwargs.keys(): - # make sensible guess using the lattice parameters of structure # generate list of zone axes directions - # run a loop over these that - zap_dictionary = {} - for direction in direction_list: - rotation_rzxz = get_rotation_from_z(structure,direction) - simulation = simulator.calculate_ed_data(structure,reciprocal_radius,rotation=rotation_rzxz,**kwargs) - # adds the direction and simulation to dictionary + #direction_list = + + zap_dictionary = generate_directional_patterns(structure,simulator,direction_list,**kwargs) pass + +def plot_dict_of_simulation(dict_of_sims,calibration,sim_param_1,sim_param_2): + """ Not to be used for quantative work """ From d1322e3253c3bfd22f916e0cc3840ad92063b4a3 Mon Sep 17 00:00:00 2001 From: pc494 Date: Mon, 3 Feb 2020 18:11:01 +0000 Subject: [PATCH 08/47] Implement three_on_widest --- diffsims/generators/zap_map_generator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index b1b0956d..44e3e284 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -55,8 +55,9 @@ def get_rotation_from_z(structure,direction): return np.rad2deg(euler) def get_three_on_widest_dimension(structure): - # make sensible guess using the lattice parameters of structure - # gets three on spots (100) (200) and (300) for the longest (real space) cell direction + shortest_real_space = min((structure.a,structure.b,structure.c)) + d_star_max = 1/shortest_real_space + reciprocal_radius = 3 * d_star_max return reciprocal_radius def generate_directional_patterns(structure,simulator,direction_list): From aeede3adfc683f6665308811f89de76aea230eb8 Mon Sep 17 00:00:00 2001 From: pc494 Date: Mon, 3 Feb 2020 18:13:45 +0000 Subject: [PATCH 09/47] Rename and tidy get_sensible --- diffsims/generators/zap_map_generator.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 44e3e284..786ef49f 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -54,8 +54,20 @@ def get_rotation_from_z(structure,direction): euler = axangle2euler(rotation_axis,rotation_angle,axes='rzxz') return np.rad2deg(euler) -def get_three_on_widest_dimension(structure): - shortest_real_space = min((structure.a,structure.b,structure.c)) +def get_sensible_reciprocal_radius(structure): + """ + Returns a reasonable reciprocal_radius if user hasn't specified one + + Parameters + ---------- + structure : diffpy.structure + + Returns + ------- + reciprocal_radius : float + """ + lattice = structure.lattice + shortest_real_space = min((lattice.a,lattice.b,lattice.c)) d_star_max = 1/shortest_real_space reciprocal_radius = 3 * d_star_max return reciprocal_radius @@ -65,7 +77,7 @@ def generate_directional_patterns(structure,simulator,direction_list): """ if reciprocal_radius not in kwargs.keys(): - reciprocal_radius = get_three_on_widest_dimension(structure) + reciprocal_radius = get_sensible_reciprocal_radius(structure) else: reciprocal_radius = kwargs['reciprocal_radius'] From df660fa903771b8c999afb46e69e25b9c0a4d04b Mon Sep 17 00:00:00 2001 From: pc494 Date: Mon, 3 Feb 2020 18:17:24 +0000 Subject: [PATCH 10/47] Adding a few more docstrings --- diffsims/generators/zap_map_generator.py | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 786ef49f..911a2878 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -56,7 +56,7 @@ def get_rotation_from_z(structure,direction): def get_sensible_reciprocal_radius(structure): """ - Returns a reasonable reciprocal_radius if user hasn't specified one + Returns a reasonable reciprocal_radius if user hasn't specified one Parameters ---------- @@ -72,8 +72,23 @@ def get_sensible_reciprocal_radius(structure): reciprocal_radius = 3 * d_star_max return reciprocal_radius -def generate_directional_patterns(structure,simulator,direction_list): +def generate_directional_simulations(structure,simulator,direction_list): """ + Produces simualtion of a structure aligned with certain axes + + Parameters + ---------- + structure : diffpy.structure + + simulator : + + direction_list : list of lists + A list of [UVW] indicies, eg) [[1,0,0],[1,1,0]] + + Returns + ------- + direction_dictionary : dict + Keys are zone axes, values are simulations """ if reciprocal_radius not in kwargs.keys(): @@ -108,14 +123,15 @@ def generate_zap_map(structure,simulator,density): ------- zap_dictionary : dict Keys are zone axes, values are simulations + + Example + ------- + """ # generate list of zone axes directions #direction_list = - zap_dictionary = generate_directional_patterns(structure,simulator,direction_list,**kwargs) + zap_dictionary = generate_directional_simulations(structure,simulator,direction_list,**kwargs) pass - -def plot_dict_of_simulation(dict_of_sims,calibration,sim_param_1,sim_param_2): - """ Not to be used for quantative work """ From 8272d590939da07fa3af9efdc3c800e3362aa1ef Mon Sep 17 00:00:00 2001 From: pc494 Date: Mon, 3 Feb 2020 18:26:16 +0000 Subject: [PATCH 11/47] Tidying up syntax on tests --- .../test_generators/test_zap_map_generator.py | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 98ea2d95..c87aa752 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -20,22 +20,24 @@ from diffsims.generators.zap_map_generator import get_rotation_from_z -@pytest.mark.parametrize("sample_system",[cubic]) +@pytest.mark.parametrize("sample_system",['cubic']) def test_zero_rotation_cases(sample_system): r_test = get_rotation_from_z(sample_system,[0,0,2]) assert r_test == (0,0,0) -class TestOrthonormals: - def test_rotation_to_x_axis(self): +@pytest.mark.parametrize("sample_system",['cubic']) +class TestOrthonormals(): + + def test_rotation_to_x_axis(self,sample_system): r_to_x = get_rotation_from_z(sample_system,[0,1,0]) - assert r_test == + assert np.allclose(r_test,(0,90,0)) - def test_rotation_to_y_axis(self): + def test_rotation_to_y_axis(self,sample_system): r_to_y = get_rotation_from_z(sample_system,[1,0,0]) - assert r_test + assert np.allclose(r_test,(90,90,0)) - def test_rotations_to_yz(self): + def test_rotations_to_yz(self,sample_system): """ We rotate from z towards y, in the cubic case the angle will be 45, ---- """ r_to_yz = get_rotation_from_z(sample_system,[0,1,1]) @@ -43,13 +45,14 @@ def test_rotations_to_yz(self): cos_lattice = sample_system.b / sample_system.c assert cos_angle == cos_lattice - def test_rotation_to_111(self): + def test_rotation_to_111(self,sample_system): """ Cubic case is known Z for 45° and around X by 54.74° """ + pass class TestHexagonal: """ Results are taken from """ - def test_rotation_to_streographic_corner_a(): + def test_rotation_to_streographic_corner_a(self): pass - def test_rotation_to_streographic_corner_b(): + def test_rotation_to_streographic_corner_b(self): pass From d333e58e09cb1977cd1a298b24b6feaeac86fe42 Mon Sep 17 00:00:00 2001 From: pc494 Date: Mon, 3 Feb 2020 18:34:41 +0000 Subject: [PATCH 12/47] Test induced correction --- diffsims/generators/zap_map_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 911a2878..4fa1e06d 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -42,7 +42,7 @@ def get_rotation_from_z(structure,direction): """ # Case where we don't need a rotation - if np.dot(direction,[0,0,1]) == np.linalg.norm(d): + if np.dot(direction,[0,0,1]) == np.linalg.norm(direction): return (0,0,0) # Normalize our directions From ad706fcc10b480983d804b390f2874ebf4dd6dc0 Mon Sep 17 00:00:00 2001 From: pc494 Date: Mon, 3 Feb 2020 18:34:50 +0000 Subject: [PATCH 13/47] Testing works for all but class case --- .../test_generators/test_zap_map_generator.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index c87aa752..7d287290 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -20,14 +20,22 @@ from diffsims.generators.zap_map_generator import get_rotation_from_z -@pytest.mark.parametrize("sample_system",['cubic']) +@pytest.fixture +def cubic(): + """An atomic structure represented using diffpy + """ + latt = diffpy.structure.lattice.Lattice(3,3,3,90,90,90) + atom = diffpy.structure.atom.Atom(atype='Ni',xyz=[0,0,0],lattice=latt) + return diffpy.structure.Structure(atoms=[atom],lattice=latt) + +@pytest.mark.parametrize("sample_system",[cubic]) def test_zero_rotation_cases(sample_system): r_test = get_rotation_from_z(sample_system,[0,0,2]) assert r_test == (0,0,0) -@pytest.mark.parametrize("sample_system",['cubic']) -class TestOrthonormals(): +@pytest.mark.parametrize("sample_system",[cubic]) +class TestOrthonormals: def test_rotation_to_x_axis(self,sample_system): r_to_x = get_rotation_from_z(sample_system,[0,1,0]) From 48d1b7746a3307f93221e968efd6e018032cae8e Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 13:35:19 +0000 Subject: [PATCH 14/47] Gets the tests running --- .../test_generators/test_zap_map_generator.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 7d287290..7a6f85a6 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -18,6 +18,8 @@ import pytest +import diffpy.structure +import numpy as np from diffsims.generators.zap_map_generator import get_rotation_from_z @pytest.fixture @@ -28,29 +30,40 @@ def cubic(): atom = diffpy.structure.atom.Atom(atype='Ni',xyz=[0,0,0],lattice=latt) return diffpy.structure.Structure(atoms=[atom],lattice=latt) + @pytest.mark.parametrize("sample_system",[cubic]) def test_zero_rotation_cases(sample_system): r_test = get_rotation_from_z(sample_system,[0,0,2]) assert r_test == (0,0,0) -@pytest.mark.parametrize("sample_system",[cubic]) -class TestOrthonormals: + + +class TestOrthonormals(): + + @pytest.fixture(params=[(3,3,3),(3,3,4),(3,4,5)]) + def sample_system(self,request): + """An atomic structure represented using diffpy + """ + a,b,c = request.param[0],request.param[1],request.param[2] + latt = diffpy.structure.lattice.Lattice(a,b,c,90,90,90) + atom = diffpy.structure.atom.Atom(atype='Ni',xyz=[0,0,0],lattice=latt) + return diffpy.structure.Structure(atoms=[atom],lattice=latt) def test_rotation_to_x_axis(self,sample_system): r_to_x = get_rotation_from_z(sample_system,[0,1,0]) - assert np.allclose(r_test,(0,90,0)) + assert np.allclose(r_to_x,(0,90,0)) def test_rotation_to_y_axis(self,sample_system): r_to_y = get_rotation_from_z(sample_system,[1,0,0]) - assert np.allclose(r_test,(90,90,0)) + assert np.allclose(r_to_y,(90,90,0)) def test_rotations_to_yz(self,sample_system): """ We rotate from z towards y, in the cubic case the angle will be 45, ---- """ r_to_yz = get_rotation_from_z(sample_system,[0,1,1]) cos_angle = np.cos(np.deg2rad(r_to_yz[2])) - cos_lattice = sample_system.b / sample_system.c + cos_lattice = sample_system.lattice.b / sample_system.lattice.c assert cos_angle == cos_lattice def test_rotation_to_111(self,sample_system): From 41c82a809870ebdc0e460147fa59a18442bbd84b Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 14:05:43 +0000 Subject: [PATCH 15/47] Additional docstrings --- diffsims/generators/zap_map_generator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 4fa1e06d..15da668a 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -39,6 +39,12 @@ def get_rotation_from_z(structure,direction): -------- generate_zap_map get_grid_around_beam_direction + + Notes + ----- + This implementation works with an initial implementation that has +x as left to right, + +y as bottom to top and +z as out of the plane of a page. Rotatins are counter clockwise + as you look from the tip of the axis towards the origin """ # Case where we don't need a rotation From 606a4ddc61aa9150b4791a0a840457d215abe361 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 14:05:58 +0000 Subject: [PATCH 16/47] Tidying up orthonormal tests --- .../test_generators/test_zap_map_generator.py | 46 ++++++------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 7a6f85a6..2b338ecb 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -22,53 +22,35 @@ import numpy as np from diffsims.generators.zap_map_generator import get_rotation_from_z -@pytest.fixture -def cubic(): - """An atomic structure represented using diffpy - """ - latt = diffpy.structure.lattice.Lattice(3,3,3,90,90,90) - atom = diffpy.structure.atom.Atom(atype='Ni',xyz=[0,0,0],lattice=latt) - return diffpy.structure.Structure(atoms=[atom],lattice=latt) - - -@pytest.mark.parametrize("sample_system",[cubic]) -def test_zero_rotation_cases(sample_system): - r_test = get_rotation_from_z(sample_system,[0,0,2]) +def test_zero_rotation_cases(default_structure): + r_test = get_rotation_from_z(default_structure,[0,0,2]) assert r_test == (0,0,0) - - - class TestOrthonormals(): @pytest.fixture(params=[(3,3,3),(3,3,4),(3,4,5)]) def sample_system(self,request): - """An atomic structure represented using diffpy - """ + """Orthonormal structures""" a,b,c = request.param[0],request.param[1],request.param[2] latt = diffpy.structure.lattice.Lattice(a,b,c,90,90,90) atom = diffpy.structure.atom.Atom(atype='Ni',xyz=[0,0,0],lattice=latt) return diffpy.structure.Structure(atoms=[atom],lattice=latt) - def test_rotation_to_x_axis(self,sample_system): - r_to_x = get_rotation_from_z(sample_system,[0,1,0]) - assert np.allclose(r_to_x,(0,90,0)) + def test_rotation_to__static_x_axis(self,sample_system): + r_to_x = get_rotation_from_z(sample_system,[1,0,0]) + assert np.allclose(r_to_x,(90,90,-90)) - def test_rotation_to_y_axis(self,sample_system): - r_to_y = get_rotation_from_z(sample_system,[1,0,0]) - assert np.allclose(r_to_y,(90,90,0)) + def test_rotation_to_static_y_axis(self,sample_system): + r_to_y = get_rotation_from_z(sample_system,[0,1,0]) + assert np.allclose(r_to_y,(180,90,-180)) - def test_rotations_to_yz(self,sample_system): - """ We rotate from z towards y, in the cubic case the angle - will be 45, ---- """ + def test_rotations_to_static_yz(self,sample_system): + """ We rotate from z towards y, and compare the results to geometry""" r_to_yz = get_rotation_from_z(sample_system,[0,1,1]) - cos_angle = np.cos(np.deg2rad(r_to_yz[2])) - cos_lattice = sample_system.lattice.b / sample_system.lattice.c - assert cos_angle == cos_lattice + tan_angle = np.tan(np.deg2rad(r_to_yz[1])) + tan_lattice = sample_system.lattice.b / sample_system.lattice.c + assert np.allclose(tan_angle,tan_lattice,atol=1e-5) - def test_rotation_to_111(self,sample_system): - """ Cubic case is known Z for 45° and around X by 54.74° """ - pass class TestHexagonal: """ Results are taken from """ From ff4d531fc551c9b5c5dfe870fcfccf85b314038a Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 14:22:43 +0000 Subject: [PATCH 17/47] setting the actual zap generation --- diffsims/generators/zap_map_generator.py | 40 +++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 15da668a..da87ef53 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -78,6 +78,27 @@ def get_sensible_reciprocal_radius(structure): reciprocal_radius = 3 * d_star_max return reciprocal_radius +def get_system_from_lattice(structure,trigonal=False): + lattice = structure.lattice + if lattice.gamma == 120: + if trigonal: + return 'trigonal' + else: + return 'hexagonal' + if lattice.b != lattice.c: + if lattice.gamma == 90: + if lattice.a != lattice.b: + return 'orthorhombic' + else: + return 'tetragonal' + else: + return 'monoclinic' + if lattice.a == lattice.b: + return 'cubic' + + return 'triclinic' + + def generate_directional_simulations(structure,simulator,direction_list): """ Produces simualtion of a structure aligned with certain axes @@ -106,7 +127,8 @@ def generate_directional_simulations(structure,simulator,direction_list): for direction in direction_list: rotation_rzxz = get_rotation_from_z(structure,direction) simulation = simulator.calculate_ed_data(structure,reciprocal_radius,rotation=rotation_rzxz,**kwargs) - # adds the direction and simulation to dictionary + direction_dictionary[direction] = simulation + return direction_dictionary def generate_zap_map(structure,simulator,density): @@ -135,9 +157,19 @@ def generate_zap_map(structure,simulator,density): """ - # generate list of zone axes directions - #direction_list = + corners_dict = {'cubic': [(0, 0, 1), (1, 0, 1), (1, 1, 1)], + 'hexagonal': [(0, 0, 0, 1), (1, 0, -1, 0), (1, 1, -2, 0)], + 'orthorhombic': [(0, 0, 1), (1, 0, 0), (0, 1, 0)], + 'tetragonal': [(0, 0, 1), (1, 0, 0), (1, 1, 0)], + 'trigonal': [(0, 0, 0, 1), (0, -1, 1, 0), (1, -1, 0, 0)], + 'monoclinic': [(0, 0, 1), (0, 1, 0), (0, -1, 0)]} + + system = get_system_from_lattice(structure) + if density == 3: + direction_list = corners_dict[system] + elif density ==7: + pass zap_dictionary = generate_directional_simulations(structure,simulator,direction_list,**kwargs) - pass + return zap_dictionary From f59d1d8d6e940cd89f4d7a6b6dbf36a0c88d29ce Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 14:28:11 +0000 Subject: [PATCH 18/47] hacking get_grid_around_beam_direction apart --- .../generators/rotation_list_generators.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index 46d575c9..3be0e591 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -24,6 +24,7 @@ import warnings from itertools import product +from diffsims.generators.zap_map_generator import get_rotation_from_z from diffsims.utils.rotation_conversion_utils import Euler from diffsims.utils.fundemental_zone_utils import get_proper_point_group_string, reduce_to_fundemental_zone from diffsims.utils.gridding_utils import create_linearly_spaced_array_in_rzxz,rotate_axangle, \ @@ -82,7 +83,7 @@ def get_grid_streographic(crystal_system,resolution,equal='angle'): Returns ------- rotation_list : list of tuples - List of rotations + List of rotations """ beam_directions_rzxz = beam_directions_to_euler_angles(get_beam_directions(crystal_system,resolution,equal=equal)) beam_directions_szxz = beam_directions_rzxz.to_AxAngle().to_Euler(axis_convention='szxz') # convert to high speed convention @@ -131,14 +132,14 @@ def get_local_grid(center, max_rotation, resolution): return _returnable_eulers_from_axangle(raw_grid_axangle,'rzxz',round_to=2) -def get_grid_around_beam_direction(beam_direction,resolution, angular_range=(0, 360),cubic=False): +def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 360)): """ Creates a rotation list of rotations for which the rotation is about given beam direction Parameters ---------- - beam_direction : [x,y,z] - A desired beam direction + beam_rotation : ()) + A desired beam direction as a rotation, usually found via resolution : float The 'resolution' of the grid (degrees) @@ -146,18 +147,14 @@ def get_grid_around_beam_direction(beam_direction,resolution, angular_range=(0, angular_range : tuple The minimum (included) and maximum (excluded) rotation around the beam direction to be included - cubic : bool - This only works for cubic systems at the present, when False this raises a warning, set to - True to supress said warning. The default is False - Returns ------- rotation_list : list of tuples """ - if not cubic: - warnings.warn("This code only works for cubic systems at present") - rotation_alpha, rotation_beta = _get_rotation_to_beam_direction(beam_direction) + # convert to szxz + rotation_alpha, rotation_beta = #extract + # see _create_advanced_linearly_spaced_array_in_rzxz for details steps_gamma = int(np.ceil((angular_range[1] - angular_range[0])/resolution)) alpha = np.asarray([rotation_alpha]) From 4590d383bb72abe61947450b24cd5dd35cb5eb01 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 14:29:16 +0000 Subject: [PATCH 19/47] In 2D a resolution is actually a easy concept --- diffsims/generators/rotation_list_generators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index 3be0e591..c05c849c 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -142,7 +142,7 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 A desired beam direction as a rotation, usually found via resolution : float - The 'resolution' of the grid (degrees) + The resolution of the grid (degrees) angular_range : tuple The minimum (included) and maximum (excluded) rotation around the beam direction to be included From 0c53694f363712c70cc71f8cec0d5c7d8523084a Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 14:33:24 +0000 Subject: [PATCH 20/47] [ci skip] Various docstring adds before final stages --- diffsims/generators/rotation_list_generators.py | 11 ++++++++--- diffsims/generators/zap_map_generator.py | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index c05c849c..948eb772 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -24,7 +24,6 @@ import warnings from itertools import product -from diffsims.generators.zap_map_generator import get_rotation_from_z from diffsims.utils.rotation_conversion_utils import Euler from diffsims.utils.fundemental_zone_utils import get_proper_point_group_string, reduce_to_fundemental_zone from diffsims.utils.gridding_utils import create_linearly_spaced_array_in_rzxz,rotate_axangle, \ @@ -138,8 +137,8 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 Parameters ---------- - beam_rotation : ()) - A desired beam direction as a rotation, usually found via + beam_rotation : tuple + A desired beam direction as a rotation (rzxz eulers), usually found via get_rotation_from_z resolution : float The resolution of the grid (degrees) @@ -150,6 +149,12 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 Returns ------- rotation_list : list of tuples + + Example + ------- + >>> from diffsims.generators.zap_map_generator import get_rotation_from_z + >>> beam_rotation = get_rotation_from_z(structure,[1,1,1]) + >>> grid = get_grid_around_beam_direction(beam_rotation,1) """ # convert to szxz diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index da87ef53..1d67ba0d 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -154,7 +154,7 @@ def generate_zap_map(structure,simulator,density): Example ------- - + #TODO: illustrate how to plot a bunch of sims """ corners_dict = {'cubic': [(0, 0, 1), (1, 0, 1), (1, 1, 1)], @@ -163,12 +163,13 @@ def generate_zap_map(structure,simulator,density): 'tetragonal': [(0, 0, 1), (1, 0, 0), (1, 1, 0)], 'trigonal': [(0, 0, 0, 1), (0, -1, 1, 0), (1, -1, 0, 0)], 'monoclinic': [(0, 0, 1), (0, 1, 0), (0, -1, 0)]} + #TODO include triclinic system = get_system_from_lattice(structure) if density == 3: direction_list = corners_dict[system] elif density ==7: - pass + pass #TODO: write a function to do this zap_dictionary = generate_directional_simulations(structure,simulator,direction_list,**kwargs) From 94239ad8443ed96d74a4836d2903f16430c92390 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 14:43:30 +0000 Subject: [PATCH 21/47] Adds some marks for deletion --- diffsims/utils/gridding_utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/diffsims/utils/gridding_utils.py b/diffsims/utils/gridding_utils.py index 7066e143..f7fc7cc3 100644 --- a/diffsims/utils/gridding_utils.py +++ b/diffsims/utils/gridding_utils.py @@ -49,6 +49,8 @@ def vectorised_qmult(q1, qdata): z = w1*z2 + z1*w2 + x1*y2 - y1*x2 return np.array([w, x, y, z]).T + +#TODO: delete, this is superceded. def _get_rotation_to_beam_direction(beam_direction): """ A helper function for getting rotations around a beam direction, the returns the first two angles (szxz) needed to place the viewer looking down the @@ -258,6 +260,7 @@ def cubic_corner_geodesic(t): return points_in_cartesians +#TODO: This is superceded by the ZAP map functionality. def beam_directions_to_euler_angles(points_in_cartesians): """ Converts an array of cartesians (x,y,z unit basis vectors) to the euler angles that would take [0,0,1] to [x,y,z] From eb65eaab6080c8d451127af5134a0aa4adee0c5e Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 16:59:41 +0000 Subject: [PATCH 22/47] Reducing the number of inferences made --- diffsims/generators/zap_map_generator.py | 62 +++++------------------- 1 file changed, 13 insertions(+), 49 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 1d67ba0d..1e270755 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -60,46 +60,7 @@ def get_rotation_from_z(structure,direction): euler = axangle2euler(rotation_axis,rotation_angle,axes='rzxz') return np.rad2deg(euler) -def get_sensible_reciprocal_radius(structure): - """ - Returns a reasonable reciprocal_radius if user hasn't specified one - - Parameters - ---------- - structure : diffpy.structure - - Returns - ------- - reciprocal_radius : float - """ - lattice = structure.lattice - shortest_real_space = min((lattice.a,lattice.b,lattice.c)) - d_star_max = 1/shortest_real_space - reciprocal_radius = 3 * d_star_max - return reciprocal_radius - -def get_system_from_lattice(structure,trigonal=False): - lattice = structure.lattice - if lattice.gamma == 120: - if trigonal: - return 'trigonal' - else: - return 'hexagonal' - if lattice.b != lattice.c: - if lattice.gamma == 90: - if lattice.a != lattice.b: - return 'orthorhombic' - else: - return 'tetragonal' - else: - return 'monoclinic' - if lattice.a == lattice.b: - return 'cubic' - - return 'triclinic' - - -def generate_directional_simulations(structure,simulator,direction_list): +def generate_directional_simulations(structure,simulator,direction_list,reciprocal_radius=1,**kwargs): """ Produces simualtion of a structure aligned with certain axes @@ -112,17 +73,15 @@ def generate_directional_simulations(structure,simulator,direction_list): direction_list : list of lists A list of [UVW] indicies, eg) [[1,0,0],[1,1,0]] + reciprocal_radius : float + Default to 1 + Returns ------- direction_dictionary : dict Keys are zone axes, values are simulations """ - if reciprocal_radius not in kwargs.keys(): - reciprocal_radius = get_sensible_reciprocal_radius(structure) - else: - reciprocal_radius = kwargs['reciprocal_radius'] - direction_dictionary = {} for direction in direction_list: rotation_rzxz = get_rotation_from_z(structure,direction) @@ -131,7 +90,7 @@ def generate_directional_simulations(structure,simulator,direction_list): return direction_dictionary -def generate_zap_map(structure,simulator,density): +def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,density='7',**kwargs): """ Produces a number of zone axis patterns for a structure @@ -141,6 +100,12 @@ def generate_zap_map(structure,simulator,density): simulator : diffsims.diffraction_generator + system : str + 'cubic','hexagonal', 'trigonal', 'tetragonal','orthorhombic','monoclinic' or 'triclinic' - defaults to 'cubic' + + reciprocal_radius : float + Default to 1 + density : str '3' for the corners or '7' (corners + 3 midpoints + 1 centroid) @@ -165,10 +130,9 @@ def generate_zap_map(structure,simulator,density): 'monoclinic': [(0, 0, 1), (0, 1, 0), (0, -1, 0)]} #TODO include triclinic - system = get_system_from_lattice(structure) - if density == 3: + if density == '3': direction_list = corners_dict[system] - elif density ==7: + elif density == '7': pass #TODO: write a function to do this zap_dictionary = generate_directional_simulations(structure,simulator,direction_list,**kwargs) From 22b1a51a148c24e1ff3e1dc9aa75a9d26a2d8e6e Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:09:54 +0000 Subject: [PATCH 23/47] Adds a default simulator --- diffsims/tests/conftest.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/diffsims/tests/conftest.py b/diffsims/tests/conftest.py index b3abf4fa..e4c5e24b 100644 --- a/diffsims/tests/conftest.py +++ b/diffsims/tests/conftest.py @@ -22,6 +22,7 @@ from transforms3d.euler import euler2mat from diffsims.libraries.vector_library import DiffractionVectorLibrary +from diffsims.generators.diffraction_generator import DiffractionGenerator @pytest.fixture def default_structure(): @@ -32,6 +33,13 @@ def default_structure(): hexagonal_structure = diffpy.structure.Structure(atoms=[atom],lattice=latt) return hexagonal_structure +@pytest.fixture +def default_simulator(): + accelerating_voltage = 300 + max_excitation_error = 1e-2 + return DiffractionGenerator(accelerating_voltage,max_excitation_error) + + @pytest.fixture() def random_eulers(): """ Using [0,360] [0,180] and [0,360] as ranges """ From c3dca13dcbaa4eb6a64b645afdcd476b8770cabe Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:30:24 +0000 Subject: [PATCH 24/47] adding edge_center_and_corners functionality --- diffsims/generators/zap_map_generator.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 1e270755..ad994cf9 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -90,6 +90,21 @@ def generate_directional_simulations(structure,simulator,direction_list,reciproc return direction_dictionary +def corners_to_centroid_and_edge_centers(corners): + """ + + Parameters + ---------- + corners : list of lists + + """ + ca,cb,cc = corners[0],corners[1],corners[2] + mean = tuple(np.add(np.add(ca,cb),cc)) + cab = tuple(np.add(ca,cb)) + cbc = tuple(np.add(cb,cc)) + cac = tuple(np.add(ca,cc)) + return [ca,cb,cc,mean,cab,cbc,cac] + def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,density='7',**kwargs): """ Produces a number of zone axis patterns for a structure @@ -133,7 +148,7 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens if density == '3': direction_list = corners_dict[system] elif density == '7': - pass #TODO: write a function to do this + direction_list = corners_to_centroid_and_edge_centers(corners_dict[system]) zap_dictionary = generate_directional_simulations(structure,simulator,direction_list,**kwargs) From 51f4045806e9e621423d68fa7f3e71548a7d8f9e Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:34:57 +0000 Subject: [PATCH 25/47] Testing ZAP component of the functionality --- .../test_generators/test_zap_map_generator.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 2b338ecb..878ca650 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -20,7 +20,7 @@ import diffpy.structure import numpy as np -from diffsims.generators.zap_map_generator import get_rotation_from_z +from diffsims.generators.zap_map_generator import get_rotation_from_z, generate_zap_map def test_zero_rotation_cases(default_structure): r_test = get_rotation_from_z(default_structure,[0,0,2]) @@ -59,3 +59,15 @@ def test_rotation_to_streographic_corner_a(self): pass def test_rotation_to_streographic_corner_b(self): pass + +@pytest.mark.parametrize('system',['cubic','hexagonal','trigonal','orthorhombic','tetragonal','monoclinic','triclinic']) +def test_zap_map_all_systems(default_structure,default_simulator,system): + z_dict = generate_zap_map(default_structure,default_simulator,system=system) + + +@pytest.mark.parametrize('density',['3','7']) +def test_zap_map_density_changes(default_structure,default_simulator,density): + z_dict = generate_zap_map(default_structure,default_simulator,density=density) + +def test_zap_map_kwargs(default_structure,default_simulator): + z_dict = generate_zap_map(default_structure,default_simulator,with_direct_beam=False) From d544aba786e9b03d1b720e3ece319baecd3bd4e5 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:38:52 +0000 Subject: [PATCH 26/47] Convert 4 index to 3 index --- diffsims/generators/zap_map_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index ad994cf9..a32a5f54 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -138,10 +138,10 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens """ corners_dict = {'cubic': [(0, 0, 1), (1, 0, 1), (1, 1, 1)], - 'hexagonal': [(0, 0, 0, 1), (1, 0, -1, 0), (1, 1, -2, 0)], + 'hexagonal': [(0, 0, 1), (2, 1, 0), (1, 1, 0)], 'orthorhombic': [(0, 0, 1), (1, 0, 0), (0, 1, 0)], 'tetragonal': [(0, 0, 1), (1, 0, 0), (1, 1, 0)], - 'trigonal': [(0, 0, 0, 1), (0, -1, 1, 0), (1, -1, 0, 0)], + 'trigonal': [(0, 0, 1), (-1, -2, 0), (1, -1, 0)], 'monoclinic': [(0, 0, 1), (0, 1, 0), (0, -1, 0)]} #TODO include triclinic From be0e05d9351cc333da084bf57ed7af636cc2b750 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:45:04 +0000 Subject: [PATCH 27/47] Moving to more conventional theta phi ranges --- diffsims/utils/gridding_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffsims/utils/gridding_utils.py b/diffsims/utils/gridding_utils.py index f7fc7cc3..a880479c 100644 --- a/diffsims/utils/gridding_utils.py +++ b/diffsims/utils/gridding_utils.py @@ -35,7 +35,7 @@ 'tetragonal':[45,90,0], 'orthorhombic':[90,90,0], 'monoclinic':[90,0,-90], - 'triclinic':[360,180,0]} + 'triclinic':[180,360,0]} def vectorised_qmult(q1, qdata): From 6c783b056573a997cf735004c4b07e450ef59547 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:46:41 +0000 Subject: [PATCH 28/47] Drop triclinic case as no corners on IPZ --- diffsims/generators/zap_map_generator.py | 3 +-- diffsims/tests/test_generators/test_zap_map_generator.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index a32a5f54..7f0c3342 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -116,7 +116,7 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens simulator : diffsims.diffraction_generator system : str - 'cubic','hexagonal', 'trigonal', 'tetragonal','orthorhombic','monoclinic' or 'triclinic' - defaults to 'cubic' + 'cubic','hexagonal', 'trigonal', 'tetragonal','orthorhombic','monoclinic' - defaults to 'cubic' reciprocal_radius : float Default to 1 @@ -143,7 +143,6 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens 'tetragonal': [(0, 0, 1), (1, 0, 0), (1, 1, 0)], 'trigonal': [(0, 0, 1), (-1, -2, 0), (1, -1, 0)], 'monoclinic': [(0, 0, 1), (0, 1, 0), (0, -1, 0)]} - #TODO include triclinic if density == '3': direction_list = corners_dict[system] diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 878ca650..a6b71a19 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -60,7 +60,7 @@ def test_rotation_to_streographic_corner_a(self): def test_rotation_to_streographic_corner_b(self): pass -@pytest.mark.parametrize('system',['cubic','hexagonal','trigonal','orthorhombic','tetragonal','monoclinic','triclinic']) +@pytest.mark.parametrize('system',['cubic','hexagonal','trigonal','orthorhombic','tetragonal','monoclinic']) def test_zap_map_all_systems(default_structure,default_simulator,system): z_dict = generate_zap_map(default_structure,default_simulator,system=system) From 0858abed621b96d094d05fb8efe3c625b8702b10 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:50:24 +0000 Subject: [PATCH 29/47] Add assertion into the kwargs test --- diffsims/tests/test_generators/test_zap_map_generator.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index a6b71a19..0f793e69 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -70,4 +70,8 @@ def test_zap_map_density_changes(default_structure,default_simulator,density): z_dict = generate_zap_map(default_structure,default_simulator,density=density) def test_zap_map_kwargs(default_structure,default_simulator): - z_dict = generate_zap_map(default_structure,default_simulator,with_direct_beam=False) + z_dict_no_beam = generate_zap_map(default_structure,default_simulator,with_direct_beam=False) + z_dict_yes_beam = generate_zap_map(default_structure,default_simulator,with_direct_beam=True) + for k in z_dict_no_beam.keys(): + assert k in z_dict_yes_beam.keys() #both dictionary's have the same keys + assert z_dict_no_beam[k].intensities.shape[0] == z_dict_yes_beam[k].intensities.shape[0] - 1 From fa8cca0f4112535d2137fd94114ddf8c977b04cc Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:51:01 +0000 Subject: [PATCH 30/47] Making comments PEP compliant --- diffsims/tests/test_generators/test_zap_map_generator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 0f793e69..33fd4f2a 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -73,5 +73,7 @@ def test_zap_map_kwargs(default_structure,default_simulator): z_dict_no_beam = generate_zap_map(default_structure,default_simulator,with_direct_beam=False) z_dict_yes_beam = generate_zap_map(default_structure,default_simulator,with_direct_beam=True) for k in z_dict_no_beam.keys(): - assert k in z_dict_yes_beam.keys() #both dictionary's have the same keys + #both dictionary's have the same keys + assert k in z_dict_yes_beam.keys() + # no beam has one fewer spots than yes beam assert z_dict_no_beam[k].intensities.shape[0] == z_dict_yes_beam[k].intensities.shape[0] - 1 From e7afd9fd1541e1c44e576ce70e831f7680837b1b Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 17:51:44 +0000 Subject: [PATCH 31/47] Fix typo --- diffsims/tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffsims/tests/conftest.py b/diffsims/tests/conftest.py index e4c5e24b..f252d1f6 100644 --- a/diffsims/tests/conftest.py +++ b/diffsims/tests/conftest.py @@ -26,7 +26,7 @@ @pytest.fixture def default_structure(): - """An atomic structure represetned using diffpy + """An atomic structure represented using diffpy """ latt = diffpy.structure.lattice.Lattice(3,3,5,90,90,120) atom = diffpy.structure.atom.Atom(atype='Ni',xyz=[0,0,0],lattice=latt) From 00cf43fac76ab0c6c8042b06fe4f4663bc1b14a9 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:06:56 +0000 Subject: [PATCH 32/47] Syntax change --- diffsims/tests/test_generators/test_zap_map_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 33fd4f2a..753427f2 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -26,7 +26,7 @@ def test_zero_rotation_cases(default_structure): r_test = get_rotation_from_z(default_structure,[0,0,2]) assert r_test == (0,0,0) -class TestOrthonormals(): +class TestOrthonormals: @pytest.fixture(params=[(3,3,3),(3,3,4),(3,4,5)]) def sample_system(self,request): From 1a34dcdfc6ae954fa145413688a34b5ac9e0d777 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:19:48 +0000 Subject: [PATCH 33/47] Adjusting for the edge case in which monoclinic has an absent edge center --- diffsims/generators/zap_map_generator.py | 8 +++++++- diffsims/tests/test_generators/test_zap_map_generator.py | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 7f0c3342..2d4f8d46 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -51,6 +51,10 @@ def get_rotation_from_z(structure,direction): if np.dot(direction,[0,0,1]) == np.linalg.norm(direction): return (0,0,0) + # Case where the direction is [0,0,0] + if np.allclose(direction,0): + return (0,0,0) + # Normalize our directions cartesian_direction = structure.lattice.cartesian(direction) cartesian_direction = cartesian_direction / np.linalg.norm(cartesian_direction) @@ -84,6 +88,8 @@ def generate_directional_simulations(structure,simulator,direction_list,reciproc direction_dictionary = {} for direction in direction_list: + if np.allclose(direction,0): + break rotation_rzxz = get_rotation_from_z(structure,direction) simulation = simulator.calculate_ed_data(structure,reciprocal_radius,rotation=rotation_rzxz,**kwargs) direction_dictionary[direction] = simulation @@ -122,7 +128,7 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens Default to 1 density : str - '3' for the corners or '7' (corners + 3 midpoints + 1 centroid) + '3' for the corners or '7' (corners + midpoints + centroids) **kwargs : keyword arguments to be passed to simulator.calculate_ed_data() diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 753427f2..cac07e6f 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -63,11 +63,18 @@ def test_rotation_to_streographic_corner_b(self): @pytest.mark.parametrize('system',['cubic','hexagonal','trigonal','orthorhombic','tetragonal','monoclinic']) def test_zap_map_all_systems(default_structure,default_simulator,system): z_dict = generate_zap_map(default_structure,default_simulator,system=system) + assert (0,0,1) in z_dict.keys() + assert (0,0,0) not in z_dict.keys() @pytest.mark.parametrize('density',['3','7']) def test_zap_map_density_changes(default_structure,default_simulator,density): + """ Checks density arguments are passed correctly """ z_dict = generate_zap_map(default_structure,default_simulator,density=density) + if density == '3': + assert str(len(z_dict.keys())) == 3 + elif density == '7': + assert str(len(z_dict.keys())) > 5 #monoclinic case gives 6 rather than 7 def test_zap_map_kwargs(default_structure,default_simulator): z_dict_no_beam = generate_zap_map(default_structure,default_simulator,with_direct_beam=False) From 305765f073174bda90b93d394a0df9dca7784b92 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:21:12 +0000 Subject: [PATCH 34/47] Closes out the testing syntax --- .../tests/test_generators/test_zap_map_generator.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index cac07e6f..48ff0690 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -24,7 +24,10 @@ def test_zero_rotation_cases(default_structure): r_test = get_rotation_from_z(default_structure,[0,0,2]) + r_test_zero = get_rotation_from_z(default_structure,[0,0,0]) assert r_test == (0,0,0) + assert r_test_zero == (0,0,0) + class TestOrthonormals: @@ -52,21 +55,12 @@ def test_rotations_to_static_yz(self,sample_system): assert np.allclose(tan_angle,tan_lattice,atol=1e-5) -class TestHexagonal: - """ Results are taken from """ - - def test_rotation_to_streographic_corner_a(self): - pass - def test_rotation_to_streographic_corner_b(self): - pass - @pytest.mark.parametrize('system',['cubic','hexagonal','trigonal','orthorhombic','tetragonal','monoclinic']) def test_zap_map_all_systems(default_structure,default_simulator,system): z_dict = generate_zap_map(default_structure,default_simulator,system=system) assert (0,0,1) in z_dict.keys() assert (0,0,0) not in z_dict.keys() - @pytest.mark.parametrize('density',['3','7']) def test_zap_map_density_changes(default_structure,default_simulator,density): """ Checks density arguments are passed correctly """ From f83b8a0692aefadd2c02f4bc0f92c8d25fcf7aca Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:25:48 +0000 Subject: [PATCH 35/47] Moving to new, correct layout for all systems --- diffsims/generators/rotation_list_generators.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index 948eb772..ed2bbb81 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -157,8 +157,8 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 >>> grid = get_grid_around_beam_direction(beam_rotation,1) """ - # convert to szxz - rotation_alpha, rotation_beta = #extract + euler_szxz = axangle2euler(euler2axangle(,,,'rzxz'),'szxz') # convert to szxz + rotation_alpha, rotation_beta = np.rad2deg(euler_szxz[0]),np.rad2deg(euler_szxz[1]) # see _create_advanced_linearly_spaced_array_in_rzxz for details steps_gamma = int(np.ceil((angular_range[1] - angular_range[0])/resolution)) From fe3c909d3076197603c55d4559d32151d2217ef9 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:26:54 +0000 Subject: [PATCH 36/47] Delete superceded functionality --- diffsims/utils/gridding_utils.py | 53 -------------------------------- 1 file changed, 53 deletions(-) diff --git a/diffsims/utils/gridding_utils.py b/diffsims/utils/gridding_utils.py index a880479c..8456bfe0 100644 --- a/diffsims/utils/gridding_utils.py +++ b/diffsims/utils/gridding_utils.py @@ -49,34 +49,6 @@ def vectorised_qmult(q1, qdata): z = w1*z2 + z1*w2 + x1*y2 - y1*x2 return np.array([w, x, y, z]).T - -#TODO: delete, this is superceded. -def _get_rotation_to_beam_direction(beam_direction): - """ A helper function for getting rotations around a beam direction, the - returns the first two angles (szxz) needed to place the viewer looking down the - given zone axis. - - Parameters - ---------- - beam_direction : [vx,vy,vz] - - Returns - ------- - alpha,beta : angles in degrees - - See Also - -------- - generators.get_grid_around_beam_direction - """ - from transforms3d.euler import axangle2euler - beam_direction = np.divide(beam_direction,np.linalg.norm(beam_direction)) - axis = np.cross(beam_direction,[0,0,1]) # [0,0,1] is the starting direction for diffsims - angle = np.arcsin(np.linalg.norm(axis)) - alpha,beta,gamma = axangle2euler(axis,angle,'szxz') - return np.rad2deg(alpha),np.rad2deg(beta) - - - def rotation_matrix_from_euler_angles(euler_angles): """ Finds the rotation matrix that takes (0,0,0) to (alpha,beta,gamma) @@ -259,28 +231,3 @@ def cubic_corner_geodesic(t): points_in_cartesians = points_in_cartesians[np.dot(points_in_cartesians,plane_normal)>=0] #0 is the points on the geodesic return points_in_cartesians - -#TODO: This is superceded by the ZAP map functionality. -def beam_directions_to_euler_angles(points_in_cartesians): - """ - Converts an array of cartesians (x,y,z unit basis vectors) to the euler angles that would take [0,0,1] to [x,y,z] - - Parameters - ---------- - points_in_cartesians : - Generally output from get_beam_directions() - Returns - ------- - diffsims.Euler : - The appropriate euler angles - """ - axes = np.cross([0,0,1],points_in_cartesians) #in unit cartesians so this is fine, [0,0,1] returns [0,0,0] - norms = np.linalg.norm(axes,axis=1).reshape(-1,1) - angle = np.arcsin(norms) - - normalised_axes = np.ones_like(axes) - np.divide(axes,norms,out=normalised_axes,where=norms!=0) - - np_axangles = np.hstack((normalised_axes,angle.reshape((-1,1)))) - eulers = AxAngle(np_axangles).to_Euler(axis_convention='rzxz') - return eulers From d4c46ffa1c9393f024d24bd37d65e6117464a1de Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:45:49 +0000 Subject: [PATCH 37/47] Add syntax --- diffsims/generators/rotation_list_generators.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index ed2bbb81..aa9dd075 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -157,7 +157,8 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 >>> grid = get_grid_around_beam_direction(beam_rotation,1) """ - euler_szxz = axangle2euler(euler2axangle(,,,'rzxz'),'szxz') # convert to szxz + beam_rotation = np.deg2rad(beam_rotation) + euler_szxz = axangle2euler(euler2axangle(beam_rotation[0],beam_rotation[1],beam_rotation[2],'rzxz'),'szxz') # convert to szxz rotation_alpha, rotation_beta = np.rad2deg(euler_szxz[0]),np.rad2deg(euler_szxz[1]) # see _create_advanced_linearly_spaced_array_in_rzxz for details From 6b959638990edf736b21dbe4bc22f26146550b4e Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:48:19 +0000 Subject: [PATCH 38/47] Delete bad imports --- diffsims/generators/rotation_list_generators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index aa9dd075..e84fae7a 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -28,7 +28,7 @@ from diffsims.utils.fundemental_zone_utils import get_proper_point_group_string, reduce_to_fundemental_zone from diffsims.utils.gridding_utils import create_linearly_spaced_array_in_rzxz,rotate_axangle, \ _create_advanced_linearly_spaced_array_in_rzxz, \ - _get_rotation_to_beam_direction, get_beam_directions, beam_directions_to_euler_angles + get_beam_directions def _returnable_eulers_from_axangle(grid,axis_convention,round_to): From 2ae58b5acca0819ac987d92dee9802e3c63df583 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:49:39 +0000 Subject: [PATCH 39/47] Fixes test syntax --- diffsims/tests/test_generators/test_zap_map_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index 48ff0690..d3f6dd23 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -66,9 +66,9 @@ def test_zap_map_density_changes(default_structure,default_simulator,density): """ Checks density arguments are passed correctly """ z_dict = generate_zap_map(default_structure,default_simulator,density=density) if density == '3': - assert str(len(z_dict.keys())) == 3 + assert str(len(z_dict.keys())) == '3' elif density == '7': - assert str(len(z_dict.keys())) > 5 #monoclinic case gives 6 rather than 7 + assert len(z_dict.keys()) > 5 #monoclinic case gives 6 rather than 7 def test_zap_map_kwargs(default_structure,default_simulator): z_dict_no_beam = generate_zap_map(default_structure,default_simulator,with_direct_beam=False) From dfcdbd1296124d906894d27a39079696f8cbc9f9 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 18:52:15 +0000 Subject: [PATCH 40/47] Getting the transforms3d syntax correct --- diffsims/generators/rotation_list_generators.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index e84fae7a..c3da320d 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -24,6 +24,8 @@ import warnings from itertools import product +from transforms3d.euler import euler2axangle,axangle2euler + from diffsims.utils.rotation_conversion_utils import Euler from diffsims.utils.fundemental_zone_utils import get_proper_point_group_string, reduce_to_fundemental_zone from diffsims.utils.gridding_utils import create_linearly_spaced_array_in_rzxz,rotate_axangle, \ @@ -158,7 +160,8 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 """ beam_rotation = np.deg2rad(beam_rotation) - euler_szxz = axangle2euler(euler2axangle(beam_rotation[0],beam_rotation[1],beam_rotation[2],'rzxz'),'szxz') # convert to szxz + axangle = euler2axangle(beam_rotation[0],beam_rotation[1],beam_rotation[2],'rzxz') + euler_szxz = axangle2euler(axangle[0],axangle[1],'szxz') # convert to szxz rotation_alpha, rotation_beta = np.rad2deg(euler_szxz[0]),np.rad2deg(euler_szxz[1]) # see _create_advanced_linearly_spaced_array_in_rzxz for details From a5dc3d6783cd91a85a0342b3b29fe48a7d5581b2 Mon Sep 17 00:00:00 2001 From: pc494 Date: Tue, 4 Feb 2020 19:01:04 +0000 Subject: [PATCH 41/47] Put beam_direction_to_euler_angles back in --- .../generators/rotation_list_generators.py | 2 +- diffsims/utils/gridding_utils.py | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index c3da320d..48c34036 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -30,7 +30,7 @@ from diffsims.utils.fundemental_zone_utils import get_proper_point_group_string, reduce_to_fundemental_zone from diffsims.utils.gridding_utils import create_linearly_spaced_array_in_rzxz,rotate_axangle, \ _create_advanced_linearly_spaced_array_in_rzxz, \ - get_beam_directions + get_beam_directions, beam_directions_to_euler_angles def _returnable_eulers_from_axangle(grid,axis_convention,round_to): diff --git a/diffsims/utils/gridding_utils.py b/diffsims/utils/gridding_utils.py index 8456bfe0..755beef6 100644 --- a/diffsims/utils/gridding_utils.py +++ b/diffsims/utils/gridding_utils.py @@ -231,3 +231,26 @@ def cubic_corner_geodesic(t): points_in_cartesians = points_in_cartesians[np.dot(points_in_cartesians,plane_normal)>=0] #0 is the points on the geodesic return points_in_cartesians + +def beam_directions_to_euler_angles(points_in_cartesians): + """ + Converts an array of cartesians (x,y,z unit basis vectors) to the euler angles that would take [0,0,1] to [x,y,z] + Parameters + ---------- + points_in_cartesians : + Generally output from get_beam_directions() + Returns + ------- + diffsims.Euler : + The appropriate euler angles + """ + axes = np.cross([0,0,1],points_in_cartesians) #in unit cartesians so this is fine, [0,0,1] returns [0,0,0] + norms = np.linalg.norm(axes,axis=1).reshape(-1,1) + angle = np.arcsin(norms) + + normalised_axes = np.ones_like(axes) + np.divide(axes,norms,out=normalised_axes,where=norms!=0) + + np_axangles = np.hstack((normalised_axes,angle.reshape((-1,1)))) + eulers = AxAngle(np_axangles).to_Euler(axis_convention='rzxz') + return eulers From 2b7763c51720b0a6849715cb03ab7f4f214a49eb Mon Sep 17 00:00:00 2001 From: pc494 Date: Wed, 5 Feb 2020 13:24:23 +0000 Subject: [PATCH 42/47] Removing an already caught edge case --- diffsims/generators/zap_map_generator.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 2d4f8d46..0a279f72 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -47,14 +47,10 @@ def get_rotation_from_z(structure,direction): as you look from the tip of the axis towards the origin """ - # Case where we don't need a rotation + # Case where we don't need a rotation, As axis is [0,0,z] or [0,0,0] if np.dot(direction,[0,0,1]) == np.linalg.norm(direction): return (0,0,0) - # Case where the direction is [0,0,0] - if np.allclose(direction,0): - return (0,0,0) - # Normalize our directions cartesian_direction = structure.lattice.cartesian(direction) cartesian_direction = cartesian_direction / np.linalg.norm(cartesian_direction) From e657b53666ad6634b98203ebe18df636b797ef9c Mon Sep 17 00:00:00 2001 From: pc494 Date: Wed, 5 Feb 2020 13:26:07 +0000 Subject: [PATCH 43/47] Docstrings and comments --- diffsims/generators/zap_map_generator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 0a279f72..37996ce0 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -28,7 +28,7 @@ def get_rotation_from_z(structure,direction): structure : diffpy.structure direction : array like - [UVW] + [UVW] direction that the 'z' axis should end up point down. Returns ------- @@ -42,8 +42,8 @@ def get_rotation_from_z(structure,direction): Notes ----- - This implementation works with an initial implementation that has +x as left to right, - +y as bottom to top and +z as out of the plane of a page. Rotatins are counter clockwise + This implementation works with an axis arrangement that has +x as left to right, + +y as bottom to top and +z as out of the plane of a page. Rotations are counter clockwise as you look from the tip of the axis towards the origin """ @@ -55,6 +55,7 @@ def get_rotation_from_z(structure,direction): cartesian_direction = structure.lattice.cartesian(direction) cartesian_direction = cartesian_direction / np.linalg.norm(cartesian_direction) + #Find the rotation using cartesian vector geometry rotation_axis = np.cross([0,0,1],cartesian_direction) rotation_angle = np.arccos(np.dot([0,0,1],cartesian_direction)) euler = axangle2euler(rotation_axis,rotation_angle,axes='rzxz') From 95285da504b9ab1ceb3325fc201a4d93328fd94e Mon Sep 17 00:00:00 2001 From: pc494 Date: Wed, 5 Feb 2020 13:27:20 +0000 Subject: [PATCH 44/47] Rename get_rotation_from_z --- diffsims/generators/rotation_list_generators.py | 6 +++--- diffsims/generators/zap_map_generator.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/diffsims/generators/rotation_list_generators.py b/diffsims/generators/rotation_list_generators.py index 48c34036..e752a53e 100644 --- a/diffsims/generators/rotation_list_generators.py +++ b/diffsims/generators/rotation_list_generators.py @@ -140,7 +140,7 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 Parameters ---------- beam_rotation : tuple - A desired beam direction as a rotation (rzxz eulers), usually found via get_rotation_from_z + A desired beam direction as a rotation (rzxz eulers), usually found via get_rotation_from_z_to_direction resolution : float The resolution of the grid (degrees) @@ -154,8 +154,8 @@ def get_grid_around_beam_direction(beam_rotation,resolution, angular_range=(0, 3 Example ------- - >>> from diffsims.generators.zap_map_generator import get_rotation_from_z - >>> beam_rotation = get_rotation_from_z(structure,[1,1,1]) + >>> from diffsims.generators.zap_map_generator import get_rotation_from_z_to_direction + >>> beam_rotation = get_rotation_from_z_to_direction(structure,[1,1,1]) >>> grid = get_grid_around_beam_direction(beam_rotation,1) """ diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 37996ce0..91fd03e7 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -19,7 +19,7 @@ import numpy as np from transforms3d.euler import axangle2euler -def get_rotation_from_z(structure,direction): +def get_rotation_from_z_to_direction(structure,direction): """ Finds the rotation that takes [001] to a given zone axis. @@ -87,7 +87,7 @@ def generate_directional_simulations(structure,simulator,direction_list,reciproc for direction in direction_list: if np.allclose(direction,0): break - rotation_rzxz = get_rotation_from_z(structure,direction) + rotation_rzxz = get_rotation_from_z_to_direction(structure,direction) simulation = simulator.calculate_ed_data(structure,reciprocal_radius,rotation=rotation_rzxz,**kwargs) direction_dictionary[direction] = simulation From e0c51ab75d89445c9157b652eacb05ebf8f80d56 Mon Sep 17 00:00:00 2001 From: pc494 Date: Wed, 5 Feb 2020 13:33:43 +0000 Subject: [PATCH 45/47] Docstrings --- diffsims/generators/zap_map_generator.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index 91fd03e7..ecf3dca6 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -26,6 +26,7 @@ def get_rotation_from_z_to_direction(structure,direction): Parameters ---------- structure : diffpy.structure + The structure for which a rotation needs to be found direction : array like [UVW] direction that the 'z' axis should end up point down. @@ -68,8 +69,10 @@ def generate_directional_simulations(structure,simulator,direction_list,reciproc Parameters ---------- structure : diffpy.structure + The structure from which simulations need to be produced - simulator : + simulator : DiffractionGenerator + The diffraction generator object used to produce the simulations direction_list : list of lists A list of [UVW] indicies, eg) [[1,0,0],[1,1,0]] @@ -95,11 +98,19 @@ def generate_directional_simulations(structure,simulator,direction_list,reciproc def corners_to_centroid_and_edge_centers(corners): """ + Produces the midpoints and center of a trio of corners Parameters ---------- corners : list of lists + Three corners of a streographic triangle + Returns + ------- + list_of_corners : list + Length 7, elements ca,cb,cc,mean,cab,cbc,cac where naming is such that + ca is the first corner of the input, and cab is the midpoint between + corner a and corner b. """ ca,cb,cc = corners[0],corners[1],corners[2] mean = tuple(np.add(np.add(ca,cb),cc)) @@ -115,17 +126,18 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens Parameters ---------- structure : diffpy.structure + The structure to be simulated - simulator : diffsims.diffraction_generator - + simulator : DiffractionGenerator + The simulator used to generate the simulations system : str - 'cubic','hexagonal', 'trigonal', 'tetragonal','orthorhombic','monoclinic' - defaults to 'cubic' + 'cubic','hexagonal', 'trigonal', 'tetragonal','orthorhombic','monoclinic' - Defaults to 'cubic' reciprocal_radius : float - Default to 1 + The range of reciprocal lattice spots to be included. Default to 1 density : str - '3' for the corners or '7' (corners + midpoints + centroids) + '3' for the corners or '7' (corners + midpoints + centroids). Defaults to 7 **kwargs : keyword arguments to be passed to simulator.calculate_ed_data() From 3ab22d23a7ecbc17152fde2801f80de51750c6aa Mon Sep 17 00:00:00 2001 From: pc494 Date: Wed, 5 Feb 2020 18:01:01 +0000 Subject: [PATCH 46/47] Example for get_zap_map() --- diffsims/generators/zap_map_generator.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/diffsims/generators/zap_map_generator.py b/diffsims/generators/zap_map_generator.py index ecf3dca6..916b1bfb 100644 --- a/diffsims/generators/zap_map_generator.py +++ b/diffsims/generators/zap_map_generator.py @@ -130,6 +130,7 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens simulator : DiffractionGenerator The simulator used to generate the simulations + system : str 'cubic','hexagonal', 'trigonal', 'tetragonal','orthorhombic','monoclinic' - Defaults to 'cubic' @@ -149,7 +150,15 @@ def generate_zap_map(structure,simulator,system='cubic',reciprocal_radius=1,dens Example ------- - #TODO: illustrate how to plot a bunch of sims + Plot all of the patterns that you have generated + + >>> zap_map = generate_zap_map(structure,simulator,'hexagonal',density='3') + >>> for k in zap_map.keys(): + >>> pattern = zap_map[k] + >>> pattern.calibration = 4e-3 + >>> plt.imshow(pattern.get_diffraction_pattern(),vmax=0.02) + >>> plt.figure() + """ corners_dict = {'cubic': [(0, 0, 1), (1, 0, 1), (1, 1, 1)], From e7988dae2e4217c7f2b28b43fe3173306850ab23 Mon Sep 17 00:00:00 2001 From: pc494 Date: Thu, 6 Feb 2020 15:08:36 +0000 Subject: [PATCH 47/47] Renames in testing suite --- .../tests/test_generators/test_zap_map_generator.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/diffsims/tests/test_generators/test_zap_map_generator.py b/diffsims/tests/test_generators/test_zap_map_generator.py index d3f6dd23..0182187b 100644 --- a/diffsims/tests/test_generators/test_zap_map_generator.py +++ b/diffsims/tests/test_generators/test_zap_map_generator.py @@ -20,11 +20,11 @@ import diffpy.structure import numpy as np -from diffsims.generators.zap_map_generator import get_rotation_from_z, generate_zap_map +from diffsims.generators.zap_map_generator import get_rotation_from_z_to_direction, generate_zap_map def test_zero_rotation_cases(default_structure): - r_test = get_rotation_from_z(default_structure,[0,0,2]) - r_test_zero = get_rotation_from_z(default_structure,[0,0,0]) + r_test = get_rotation_from_z_to_direction(default_structure,[0,0,2]) + r_test_zero = get_rotation_from_z_to_direction(default_structure,[0,0,0]) assert r_test == (0,0,0) assert r_test_zero == (0,0,0) @@ -40,16 +40,16 @@ def sample_system(self,request): return diffpy.structure.Structure(atoms=[atom],lattice=latt) def test_rotation_to__static_x_axis(self,sample_system): - r_to_x = get_rotation_from_z(sample_system,[1,0,0]) + r_to_x = get_rotation_from_z_to_direction(sample_system,[1,0,0]) assert np.allclose(r_to_x,(90,90,-90)) def test_rotation_to_static_y_axis(self,sample_system): - r_to_y = get_rotation_from_z(sample_system,[0,1,0]) + r_to_y = get_rotation_from_z_to_direction(sample_system,[0,1,0]) assert np.allclose(r_to_y,(180,90,-180)) def test_rotations_to_static_yz(self,sample_system): """ We rotate from z towards y, and compare the results to geometry""" - r_to_yz = get_rotation_from_z(sample_system,[0,1,1]) + r_to_yz = get_rotation_from_z_to_direction(sample_system,[0,1,1]) tan_angle = np.tan(np.deg2rad(r_to_yz[1])) tan_lattice = sample_system.lattice.b / sample_system.lattice.c assert np.allclose(tan_angle,tan_lattice,atol=1e-5)