Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transforms Testcases #651

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dde7c58
Some test cases
kevindlewis23 Jun 18, 2024
f3a6fab
Some test cases
kevindlewis23 Jun 19, 2024
86e1f4e
Not functioning, committing to change branches
kevindlewis23 Jun 20, 2024
35104e4
gvec to xy and inverse
kevindlewis23 Jun 24, 2024
e8c5511
Merge branch 'master' of https://github.com/Verdant-Evolution/hexrd i…
kevindlewis23 Jun 24, 2024
0b873eb
Merge branch 'docstrings' of https://github.com/Verdant-Evolution/hex…
kevindlewis23 Jun 24, 2024
da5e1b2
Reformat for PR
kevindlewis23 Jun 24, 2024
ee4458e
more pep 8 reformatting
kevindlewis23 Jun 24, 2024
ee11a49
Fix data locations
kevindlewis23 Jun 24, 2024
07d997d
Update xy to gvec with new signature
kevindlewis23 Jun 24, 2024
026b018
More test cases, make omega optional on angles_to_dvec
kevindlewis23 Jun 24, 2024
0f5266b
Add new version messages on old capi
kevindlewis23 Jun 24, 2024
e798b6b
fix angles_to_dvec_test
kevindlewis23 Jun 24, 2024
b3fcdc4
make_sample_rmat
kevindlewis23 Jun 24, 2024
e93d0e0
Some more test cases
kevindlewis23 Jun 25, 2024
95cabd8
pep8 fixes
kevindlewis23 Jun 25, 2024
ada45c9
Update gvec_to_xy test
kevindlewis23 Jun 25, 2024
6b4c194
More PEP 8 style fixes
kevindlewis23 Jun 25, 2024
3beb807
Last PEP8 fix?
kevindlewis23 Jun 25, 2024
cad4d9d
Actual last PEP8 change
kevindlewis23 Jun 25, 2024
d3f1e49
Cleaned up test cases
kevindlewis23 Jun 25, 2024
dd1f74b
PEP* fix
kevindlewis23 Jun 25, 2024
df92e82
Wrong file location fix
kevindlewis23 Jun 25, 2024
44fca0f
typo fix
kevindlewis23 Jun 27, 2024
0c71087
Merge branch 'master' of https://github.com/Verdant-Evolution/hexrd i…
kevindlewis23 Jun 27, 2024
9578be4
Add code-coverage workflow
kevindlewis23 Jun 27, 2024
f3f35b1
Undo codecov, moving to a different branch
kevindlewis23 Jun 27, 2024
7dc33b7
Merge branch 'master' of https://github.com/Verdant-Evolution/hexrd i…
kevindlewis23 Jul 2, 2024
58533cb
Remove unused import
kevindlewis23 Jul 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,6 @@ dmypy.json

# MacOSX dir index files
.DS_Store


.vscode/
20 changes: 11 additions & 9 deletions hexrd/transforms/new_capi/transforms_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,11 @@ class DEF_xy_to_gvec(DEF_Func):
(3, ) translation vector connecting LAB FRAME to SAMPLE FRAME
tvec_c : array_like
(3, ) translation vector connecting SAMPLE FRAME to CRYSTAL FRAME
rmat_b : array_like, optional
(3, 3) COB matrix taking components in the BEAM FRAME to the LAB FRAME;
defaults to None, which implies the standard setting of identity.
beam_vec : ndarray, optional
Unit vector pointing towards the X-ray source in the lab frame.
Defaults to [0,0,-1]
eta_vec : ndarray, optional
Vector defining eta=0 in the lab frame. Defaults to [1,0,0]
distortion : distortion class, optional
Default is None
output_ref : bool, optional
Expand All @@ -245,12 +247,12 @@ class DEF_xy_to_gvec(DEF_Func):
-----
???: is there a need to flatten the tvec inputs?
???: include optional wavelength input for returning G with magnitude?
???: is there a need to check that rmat_b is orthogonal if spec'd?
"""
def _signature(xy_d,
rmat_d, rmat_s,
tvec_d, tvec_s, tvec_c,
rmat_b=None,
beam_vec=None,
eta_vec=None,
distortion=None,
output_ref=False):
pass
Expand Down Expand Up @@ -516,7 +518,7 @@ def _signature(vec_in):
class DEF_make_sample_rmat(DEF_Func):
"""
Make SAMPLE frame rotation matrices as composition of
rotation of ome about the axis
rotation of omega about the axis

[0., cos(chi), sin(chi)]

Expand All @@ -526,16 +528,16 @@ class DEF_make_sample_rmat(DEF_Func):
----------
chi : float
The inclination angle of the goniometer axis (standard coords)
ome : array_like
omega : array_like
(n) angles to generate rotation matrices from.

Returns
-------
array_like
(n, 3, 3) a vector of the n rotation matrices along the
axis defined by chi, one for each ome.
axis defined by chi, one for each omega.
"""
def _signature(chi, ome):
def _signature(chi, omega):
pass


Expand Down
65 changes: 34 additions & 31 deletions hexrd/transforms/new_capi/xf_new_capi.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
def angles_to_gvec(angs, beam_vec=None, eta_vec=None, chi=None, rmat_c=None):
"""

Takes triplets of angles in the beam frame (2*theta, eta, optional omega)
Takes triplets of angles in the beam frame (2*theta, eta[, omega])
to components of unit G-vectors in the LAB frame. If the omega
values are not trivial (i.e. angs[:, 2] = 0.), then the components
are in the SAMPLE frame. If the crystal rmat is specified and
Expand All @@ -46,12 +46,12 @@ def angles_to_gvec(angs, beam_vec=None, eta_vec=None, chi=None, rmat_c=None):
----------
angs : ndarray
The euler angles of diffraction. The last dimension must be 2 or 3. In
(2*theta, eta, omega) or (2*theta, eta) format.
(2*theta, eta[, omega]) format. omega is optional.
beam_vec : ndarray, optional
Unit vector pointing towards the X-ray source in the lab frame.
Defaults to [0,0,-1]
eta_vec : ndarray, optional
Vector defining eta=0 in the lab frame. Defaults to [1,0,0]
Unit vector defining eta=0 in the lab frame. Defaults to [1,0,0]
chi : float, optional
The inclination angle of the sample frame about the lab frame X.
rmat_c : ndarray, optional
Expand Down Expand Up @@ -91,7 +91,7 @@ def angles_to_gvec(angs, beam_vec=None, eta_vec=None, chi=None, rmat_c=None):
def angles_to_dvec(angs, beam_vec=None, eta_vec=None, chi=None, rmat_c=None):
"""

Takes triplets of angles in the beam frame (2*theta, eta, omega)
Takes triplets of angles in the beam frame (2*theta, eta[, omega])
to components of unit diffraction vectors in the LAB frame. If the omega
values are not trivial (i.e. angs[:, 2] = 0.), then the components
are in the SAMPLE frame. If the crystal rmat is specified and
Expand All @@ -101,13 +101,13 @@ def angles_to_dvec(angs, beam_vec=None, eta_vec=None, chi=None, rmat_c=None):
Parameters
----------
angs : ndarray
The euler angles of diffraction. The last dimension must be 3. In
(2*theta, eta, omega) format.
The euler angles of diffraction. The last dimension must be 2 or 3. In
(2*theta, eta[, omega]) format. omega is optional.
beam_vec : ndarray, optional
Unit vector pointing towards the X-ray source in the lab frame.
Defaults to [0,0,-1]
eta_vec : ndarray, optional
Vector defining eta=0 in the lab frame. Defaults to [1,0,0]
Unit vector defining eta=0 in the lab frame. Defaults to [1,0,0]
chi : float, optional
The inclination angle of the sample frame about the lab frame X.
rmat_c : ndarray, optional
Expand All @@ -124,6 +124,10 @@ def angles_to_dvec(angs, beam_vec=None, eta_vec=None, chi=None, rmat_c=None):
beam_vec = beam_vec if beam_vec is not None else cnst.beam_vec
eta_vec = eta_vec if eta_vec is not None else cnst.eta_vec

# if only a pair is provided... convert to a triplet with omegas == 0
# so that behavior is preserved.
if angs.shape[-1] == 2:
angs = np.hstack((angs, np.zeros(angs.shape[:-1] + (1,))))
angs = np.ascontiguousarray(np.atleast_2d(angs))
beam_vec = np.ascontiguousarray(beam_vec.flatten())
eta_vec = np.ascontiguousarray(eta_vec.flatten())
Expand Down Expand Up @@ -160,7 +164,7 @@ def makeGVector(hkl, bMat):

"""
assert hkl.shape[0] == 3, 'hkl input must be (3, n)'
return unitVector(np.dot(bMat, hkl))
return unit_vector(np.dot(bMat, hkl))


@xf_api
Expand Down Expand Up @@ -268,7 +272,8 @@ def xy_to_gvec(
tvec_d,
tvec_s,
tvec_c,
rmat_b=None,
beam_vec=None,
eta_vec=None,
distortion=None,
output_ref=False,
):
Expand All @@ -294,9 +299,11 @@ def xy_to_gvec(
(3, ) translation vector connecting LAB FRAME to SAMPLE FRAME
tvec_c : array_like
(3, ) translation vector connecting SAMPLE FRAME to CRYSTAL FRAME
rmat_b : array_like, optional
(3, 3) COB matrix taking components in the BEAM FRAME to the LAB FRAME;
defaults to None, which implies the standard setting of identity.
beam_vec : ndarray, optional
Unit vector pointing towards the X-ray source in the lab frame.
Defaults to [0,0,-1]
eta_vec : ndarray, optional
Unit vector defining eta=0 in the lab frame. Defaults to [1,0,0]
distortion : distortion class, optional
Default is None
output_ref : bool, optional
Expand All @@ -306,21 +313,14 @@ def xy_to_gvec(
Returns
-------
array_like
(n, 2) ndarray containing the (tth, eta) pairs associated with each
(n, 2) ndarray containing the (2th, eta) pairs associated with each
(x, y) associated with gVecs
array_like
(n, 3) ndarray containing the associated G vector directions in the
LAB FRAME
array_like, optional
if output_ref is True
"""
# TODO: in the C library beam vector and eta vector are expected. However
# we receive rmat_b. Please check this!
#
# It also seems that the output_ref version is not present as the argument
# gets ignored

rmat_b = rmat_b if rmat_b is not None else cnst.identity_3x3

# the code seems to ignore this argument, assume output_ref == True not
# implemented
Expand All @@ -335,8 +335,9 @@ def xy_to_gvec(
tvec_d = np.ascontiguousarray(tvec_d.flatten())
tvec_s = np.ascontiguousarray(tvec_s.flatten())
tvec_c = np.ascontiguousarray(tvec_c.flatten())
beam_vec = np.ascontiguousarray((-rmat_b[:, 2]).flatten())
eta_vec = np.ascontiguousarray(rmat_b[:, 0].flatten()) # check this!
beam_vec = beam_vec if beam_vec is not None else cnst.beam_vec
eta_vec = eta_vec if eta_vec is not None else cnst.eta_vec

return _impl.detectorXYToGvec(
xy_d, rmat_d, rmat_s, tvec_d, tvec_s, tvec_c, beam_vec, eta_vec
)
Expand Down Expand Up @@ -425,27 +426,28 @@ def make_oscill_rot_mat_array(chi, omeArray):


@xf_api
def make_sample_rmat(chi, ome):
def make_sample_rmat(chi, omega):
# TODO: Check this docstring
"""
Make a rotation matrix representing the COB from sample frame to the lab
frame.
frame, or multiple at the same time.

Parameters
----------
chi : float
The inclination angle of the sample frame about the lab frame Y.
ome : float or ndarray
omega : float or ndarray
The oscillation angle(s) about the sample frame Y.

Returns
-------
ndarray
A 3x3 rotation matrix representing the input oscillation angles.
A 3x3 rotation matrix representing the input oscillation angles if
omega is one value, or N 3x3 rotation matrices if omega is a list.

"""
ome_array = np.atleast_1d(ome)
if ome is ome_array:
ome_array = np.atleast_1d(omega)
if omega is ome_array:
ome_array = np.ascontiguousarray(ome_array)
result = _impl.makeOscillRotMat(chi, ome_array)
else:
Expand Down Expand Up @@ -498,7 +500,7 @@ def make_beam_rmat(bvec_l, evec_l):
vector components in the lab frame.
the default is [0, 0, -1], which is the standard setting.
evec_l : ndarray
Vector defining eta=0 in the lab frame. Defaults to [1,0,0]
Unit vector defining eta=0 in the lab frame. Defaults to [1,0,0]
"""
arg1 = np.ascontiguousarray(bvec_l.flatten())
arg2 = np.ascontiguousarray(evec_l.flatten())
Expand All @@ -508,7 +510,8 @@ def make_beam_rmat(bvec_l, evec_l):
@xf_api
def validate_angle_ranges(ang_list, start_angs, stop_angs, ccw=True):
"""
Find out if angles are in the CCW or CW range from start to stop
Find out if angles are in the CCW or CW range any of the start to stop
ranges

Parameters
----------
Expand All @@ -525,7 +528,7 @@ def validate_angle_ranges(ang_list, start_angs, stop_angs, ccw=True):
Returns
-------
ndarray
List of bools indicating if the angles are in the correct range
List of bools indicating if the angles are in any of the correct ranges

"""
ang_list = ang_list.astype(np.double, order="C")
Expand Down
20 changes: 12 additions & 8 deletions hexrd/transforms/xfcapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@
# and hexrdgui. This is so that we can see clearly what is in use.
from .old_xfcapi import (
# Old transform functions still in use
anglesToDVec,
anglesToDVec, # new version provided below
anglesToGVec, # new version provided below
detectorXYToGvec,
detectorXYToGvec, # new version provided below
gvecToDetectorXY, # new version provided below
gvecToDetectorXYArray, # new version provided below
oscillAnglesOfHKLs,
# Utility functions
angularDifference,
quat_distance,
# quat_distance, # new version provided below
makeDetectorRotMat,
makeEtaFrameRotMat,
makeOscillRotMat, # new version provided below
makeOscillRotMatArray, # new version provided below
makeRotMatOfExpMap,
makeEtaFrameRotMat, # new version provided below (make_beam_rmat)
makeOscillRotMat, # new version provided below (make_sample_rmat)
makeOscillRotMatArray, # new version provided below (make_sample_rmat)
makeRotMatOfExpMap, # new version provided below
makeRotMatOfQuat,
mapAngle,
rowNorm,
unitRowVector,
unitRowVector, # new version provided below (unit_vector)
# Constants,
bVec_ref,
eta_ref,
Expand All @@ -35,5 +35,9 @@
angles_to_gvec,
angles_to_dvec,
gvec_to_xy, # this is gvecToDetectorXY and gvecToDetectorXYArray
xy_to_gvec,
make_sample_rmat, # this is makeOscillRotMat and makeOscillRotMatArray
make_beam_rmat,
unit_vector,
quat_distance
)
Binary file added tests/data/test_correct_angles_to_dvec.npy
Binary file not shown.
Binary file added tests/data/test_correct_angles_to_gvec.npy
Binary file not shown.
Binary file added tests/data/test_correct_gvec_to_xy.npy
Binary file not shown.
Binary file added tests/data/test_correct_make_beam_rmat.npy
Binary file not shown.
Binary file added tests/data/test_correct_make_rmat_of_expmap.npy
Binary file not shown.
Binary file added tests/data/test_correct_make_sample_rmat.npy
Binary file not shown.
Binary file added tests/data/test_correct_quat_distance.npy
Binary file not shown.
Binary file added tests/data/test_correct_validate_angle_ranges.npy
Binary file not shown.
Binary file added tests/data/test_correct_xy_to_gvec.npy
Binary file not shown.
80 changes: 80 additions & 0 deletions tests/transforms/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import math

import numpy as np

import hexrd.constants as ct
from hexrd.transforms.new_capi.xf_new_capi import unit_vector


def convert_axis_angle_to_rmat(axis, angle):
# Copied from: https://github.com/ovillellas/xrd-transforms/blob/b94f8b2d7839d883829d00a2adc5bec9c80e0116/test_xrd_transforms/common.py#L59 # noqa
# This is based on
# https://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/ # noqa

angle = float(angle)
axis = np.array(axis, dtype=float)
assert axis.shape == (3,)

if abs(angle) < ct.epsf:
return ct.identity_3x3

axis_norm = np.linalg.norm(axis)
if axis_norm < ct.epsf:
raise ValueError("axis is zero")

axis /= axis_norm

m = np.empty((3, 3), dtype=float)

c = math.cos(angle)
s = math.sin(angle)
t = 1.0 - c

m[0, 0] = c + axis[0]*axis[0]*t
m[0, 1] = axis[0]*axis[1]*t - axis[2]*s
m[0, 2] = axis[0]*axis[2]*t + axis[1]*s
m[1, 0] = axis[0]*axis[1]*t + axis[2]*s
m[1, 1] = c + axis[1]*axis[1]*t
m[1, 2] = axis[1]*axis[2]*t - axis[0]*s
m[2, 0] = axis[0]*axis[2]*t - axis[1]*s
m[2, 1] = axis[1]*axis[2]*t + axis[0]*s
m[2, 2] = c + axis[2]*axis[2]*t

return m


def random_rotation_matrix():
# Generate a random unit quaternion
q = np.random.rand(4) * 2 - 1
q /= np.linalg.norm(q)
q0 = q[0]
q1 = q[1]
q2 = q[2]
q3 = q[3]

# First row of the rotation matrix
r00 = 2 * (q0 * q0 + q1 * q1) - 1
r01 = 2 * (q1 * q2 - q0 * q3)
r02 = 2 * (q1 * q3 + q0 * q2)

# Second row of the rotation matrix
r10 = 2 * (q1 * q2 + q0 * q3)
r11 = 2 * (q0 * q0 + q2 * q2) - 1
r12 = 2 * (q2 * q3 - q0 * q1)

# Third row of the rotation matrix
r20 = 2 * (q1 * q3 - q0 * q2)
r21 = 2 * (q2 * q3 + q0 * q1)
r22 = 2 * (q0 * q0 + q3 * q3) - 1

# 3x3 rotation matrix
rot_matrix = np.array([[r00, r01, r02],
[r10, r11, r12],
[r20, r21, r22]])
return rot_matrix


def random_unit_vectors(shape1=3, shape2=None):
if shape2 is None:
return unit_vector(np.random.rand(shape1) * 2 - 1)
return unit_vector(np.random.rand(shape1, shape2) * 2 - 1)
Loading
Loading