Use E4CV’s $Q$ calculation engine#

Many of the diffractometer geometries support different calculation engines. By default, many geometries in hklpy2 provide h, k, & l pseudo positioners (the hkl engine) since this is the most common case. For example, E4CV supports several calculation engines:

engine

pseudo(s)

real(s)

hkl

h, k, l

omega, chi, phi, tth

psi

psi

omega, chi, phi, tth

q

q

tth

incidence

incidence, azimuth

omega, chi, phi

emergence

emergence, azimuth

omega, chi, phi, tth


NOTE: The choice of calculation engine is set when creating an instance of the DiffractometerBase() class. Once the diffractometer object is created, the calculation engine cannot be changed.


Objective#

We’ll demonstrate the q calculation engine of the E4CV (4-circle Eulerian in vertical scattering) geometry.

q engine#

The q engine is easy to demonstrate since it only involves the actions of the tth circle ($q=4\pi\sin(\theta)/\lambda$ where $\theta$ is half of tth) and no crystal orientation reflections are necessary.

Create the diffractometer object.#

Specify the q calculation engine (engine="q") when you create the diffractometer object. (The default is the hkl engine.) Once the object is created, the calculation engine cannot be changed.

import hklpy2

fourcq = hklpy2.creator(
    name="fourcq",
    geometry="E4CV",
    solver="hkl_soleil",
    solver_kwargs=dict(engine="q")
)
fourcq.wh()
q=0
wavelength=1.0
omega=0, chi=0, phi=0, tth=0

Test the q engine by calculating the angles associated with $Q=1.00$ 1/angstrom. There is only one pseudo positioner so only one value is provided to the forward() calculation. Notice that only the tth position is computed.

print(f"q to angle: {fourcq.forward(1) = }")
q to angle: fourcq.forward(1) = Hklpy2DiffractometerRealPos(omega=0, chi=0, phi=0, tth=9.128558416066)

Calculate the $q$ associated with tth=1.0 degrees. While four real motors are defined, only tth is used for the calculation so only one value is provided to the inverse() calculation.

print(f"angle to q: {fourcq.inverse(1) = }")
angle to q: fourcq.inverse(1) = Hklpy2DiffractometerPseudoPos(q=0)

Show the position of the fourcq diffractometer.

fourcq.wh()
q=0
wavelength=1.0
omega=0, chi=0, phi=0, tth=0

Move fourcq to $Q=1.0$ 1/Angstrom and show the settings again.

fourcq.move(1, wait=True)
fourcq.wh()
q=1.0
wavelength=1.0
omega=0, chi=0, phi=0, tth=9.1286

Show all the fourcq diffractometer settings.

fourcq.wh(full=True)
diffractometer='fourcq'
HklSolver(name='hkl_soleil', version='5.1.2', geometry='E4CV', engine_name='q', mode='q')
Sample(name='sample', lattice=Lattice(a=1, system='cubic'))
Orienting reflections: []
U=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
UB=[[6.283185307179586, 0.0, 0.0], [0.0, 6.283185307179586, 0.0], [0.0, 0.0, 6.283185307179586]]
constraint: -180.0 <= omega <= 180.0
constraint: -180.0 <= chi <= 180.0
constraint: -180.0 <= phi <= 180.0
constraint: -180.0 <= tth <= 180.0
q=1.0
wavelength=1.0
omega=0, chi=0, phi=0, tth=9.1286

Move to a different wavelength (0.5 Angstrom) and move back to the same $Q$ of 1.000 1/Angstrom.

fourcq.wavelength.set(0.5)
fourcq.move(1, wait=True)
fourcq.wh()
q=1.0
wavelength=0.5
omega=0, chi=0, phi=0, tth=9.1286