Skip to content

Commit

Permalink
Merge 47f2379 into 734466f
Browse files Browse the repository at this point in the history
  • Loading branch information
pc494 committed Feb 17, 2018
2 parents 734466f + 47f2379 commit e0bb162
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 292 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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"
- "pip install pytest pytest-cov"
- "pip install coveralls"
Expand Down
6 changes: 2 additions & 4 deletions pyxem/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
# along with pyXem. If not, see <http://www.gnu.org/licenses/>.

import numpy as np
from scipy.interpolate import RectBivariateSpline


def correlate(image, pattern_dictionary):
"""The correlation between a diffraction pattern and a simulation.
Expand Down Expand Up @@ -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
return np.dot(image_intensities,pattern_intensities)/pattern_normalization
4 changes: 2 additions & 2 deletions pyxem/utils/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
57 changes: 57 additions & 0 deletions tests/Orientation_mapping/OM_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# -*- 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 <http://www.gnu.org/licenses/>.

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

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_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))

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
92 changes: 92 additions & 0 deletions tests/Orientation_mapping/test_orientation_mapping_nonphys.py
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

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)

115 changes: 115 additions & 0 deletions tests/Orientation_mapping/test_orientation_mapping_phys.py
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

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)

0 comments on commit e0bb162

Please sign in to comment.