hkl_soleil E6C test of calculations#

Non-exhaustive tests of hkl_soleil E6C computations of orientation, U, UB, and rotation directions, with the aid of Yong Chu’s mental math.

TL;DR E6C appears to function as documented and as expected.

Create a simulated diffractometer for calculations#

These tests use a simulated diffractometer to test the solver’s calculation.

import hklpy2

e6c = hklpy2.creator(name="e6c", geometry="E6C")
e6c.core.solver.mode = 'constant_chi_vertical'
e6c.wavelength.put(1.)  # Angstrom

Setup the crystal lattice#

Use the default sample.

print(f"{e6c.sample=}")
e6c.wh()
e6c.sample=Sample(name='sample', lattice=Lattice(a=1, system='cubic'))
h=0, k=0, l=0
wavelength=1.0
mu=0, omega=0, chi=0, phi=0, gamma=0, delta=0

Compute the UB matrix from two reflections#

# checking orientation of delta
r1p = dict(mu=0.0, omega=30.0, chi=0.0, phi=0.0, gamma=0., delta=60.)
r1 = e6c.add_reflection((0, 0, 1), r1p)
r2p = dict(mu=0.0, omega=120.0, chi=0.0, phi=0.0, gamma=0, delta=60.)
r2 = e6c.add_reflection((1, 0, 0), r2p)
e6c.core.calc_UB(r1, r2)
[[6.283183866345, 2.367192e-06, 0.0],
 [0.0, 6.28318625087, 0.0],
 [2.66395e-07, -1.611768e-06, 6.283184307075]]

Show the computed U matrix#

Note: Here, $U=I$, where $I$ is the identity matrix.

e6c.sample.U
[[1.0, 0.0, -4.2398e-08],
 [0.0, 1.0, 2.56521e-07],
 [4.2398e-08, -2.56521e-07, 1.0]]

Show the computed UB matrix#

Note: Here, $UB=2\pi\cdot I$.

e6c.sample.UB
[[6.283183866345, 2.367192e-06, 0.0],
 [0.0, 6.28318625087, 0.0],
 [2.66395e-07, -1.611768e-06, 6.283184307075]]

Calculate various (hkl) given motor positions#

This is the inverse() transformation.

(010)#

pos = e6c.inverse(dict(mu=0.0, omega=30.0, chi=90.0, phi=0.0, gamma=0, delta=60.))
print('expecting (0,1,0)=', pos)
expecting (0,1,0)= Hklpy2DiffractometerPseudoPos(h=-3.7675e-07, k=0.999999849807, l=2.56521e-07)
# alternate settings for same reflection
pos = e6c.inverse(dict(mu=30.0, omega=0.0, chi=0.0, phi=0.0, gamma=60., delta=0.))
print('expecting (0,1,0)=', pos)
expecting (0,1,0)= Hklpy2DiffractometerPseudoPos(h=-3.7675e-07, k=0.999999849807, l=2.56521e-07)

(0 -1 0)#

pos = e6c.inverse(dict(mu=0, omega=30., chi=-90.0, phi=0.0, gamma=0., delta=60.))
print('expecting (0,-1,0)=', pos)
expecting (0,-1,0)= Hklpy2DiffractometerPseudoPos(h=3.7675e-07, k=-0.999999849807, l=-2.56521e-07)

(-1 0 0)#

pos = e6c.inverse(dict(mu=0.0, omega=-60.0, chi=0.0, phi=0.0, gamma=0, delta=60.))
print('expecting (-1,0,0)=', pos)
expecting (-1,0,0)= Hklpy2DiffractometerPseudoPos(h=-1.000000229316, k=0, l=4.2398e-08)

Diffracting upside-down now#

Note that omega and phi only need to sum to +/-120 ($\omega+\varphi = \pm |120|$), which reflects what the inverse calculations from the library give.

(100)#

pos = e6c.inverse(dict(mu=0.0, omega=-50.0, chi=0.0, phi=-70.0, gamma=0, delta=-60.))
print('expecting (1,0,0)=', pos)

pos = e6c.inverse(dict(mu=0.0, omega=-100.0, chi=0.0, phi=-20.0, gamma=0, delta=-60.))
print('expecting (1,0,0)=', pos)

pos = e6c.inverse(dict(mu=0.0, omega=100.0, chi=0.0, phi=-220.0, gamma=0, delta=-60.))
print('expecting (1,0,0)=', pos)
expecting (1,0,0)= Hklpy2DiffractometerPseudoPos(h=1.000000229316, k=0, l=-4.2398e-08)
expecting (1,0,0)= Hklpy2DiffractometerPseudoPos(h=1.000000229316, k=0, l=-4.2398e-08)
expecting (1,0,0)= Hklpy2DiffractometerPseudoPos(h=1.000000229316, k=0, l=-4.2398e-08)

(011)#

pos = e6c.inverse(dict(mu=0.0, omega=45.0, chi=45.0, phi=0.0, gamma=0, delta=90.))
print('expecting (0,1,1)=', pos)
expecting (0,1,1)= Hklpy2DiffractometerPseudoPos(h=-3.7675e-07, k=0.999999849807, l=1.000000415693)

Verify that $\omega+\varphi = \pm 120$ is kept.#

Calculate all allowed combinations of motor positions, given $hkl$.

print("expecting either omega+phi = 120 or -120 (approximately)")
solutions = e6c.core.forward([1, 0, 0])
for i, sol in enumerate(solutions):
    print(i, sol)
expecting either omega+phi = 120 or -120 (approximately)
0 Hklpy2DiffractometerRealPos(mu=0, omega=119.999992124449, chi=45.0, phi=-2.429236e-06, gamma=0, delta=59.999984419525)
1 Hklpy2DiffractometerRealPos(mu=0, omega=-119.999992124449, chi=45.0, phi=-2.429236e-06, gamma=0, delta=-59.999984419525)
2 Hklpy2DiffractometerRealPos(mu=0, omega=-60.000007875551, chi=45.0, phi=-179.999997570764, gamma=0, delta=59.999984419525)
3 Hklpy2DiffractometerRealPos(mu=0, omega=60.000007875551, chi=45.0, phi=-179.999997570764, gamma=0, delta=-59.999984419525)