Example 4-circle diffractometer using creator()#

Similar to Example 4-circle diffractometer custom Python class, this example builds a custom 4-circle. This version uses the creator() function.

import hklpy2
from ophyd import Kind

NORMAL_HINTED = Kind.hinted | Kind.normal

fourc = hklpy2.creator(
    prefix="gp:",
    name="fourc",
    solver="hkl_soleil",
    geometry="E4CV",
    pseudos="h k l h2 k2 l2".split(),
    reals=dict(
        theta="m30",
        chi="m31",
        phi="m32",
        ttheta="m29",
        psi=None,
        temperature=None,
    ),
    beam_kwargs={
        "class": "hklpy2.incident.EpicsMonochromatorRO",
        "prefix": "gp:",
        "source_type": "Simulated read-only EPICS Monochromator",
        "pv_energy": "BraggERdbkAO",  # the energy readback PV
        "energy_units": "keV",
        "pv_wavelength": "BraggLambdaRdbkAO",  # the wavelength readback PV
        "wavelength_units": "angstrom",
        "wavelength_deadband": 0.000_150,
        "kind": NORMAL_HINTED,
    },
)
fourc.wait_for_connection()  # Recommended when connecting to control system.
fourc
Hklpy2Diffractometer(prefix='gp:', name='fourc', settle_time=0.0, timeout=None, egu='', limits=(0, 0), source='computed', read_attrs=['beam', 'beam.wavelength', 'beam.energy', 'h', 'h.readback', 'h.setpoint', 'k', 'k.readback', 'k.setpoint', 'l', 'l.readback', 'l.setpoint', 'h2', 'h2.readback', 'h2.setpoint', 'k2', 'k2.readback', 'k2.setpoint', 'l2', 'l2.readback', 'l2.setpoint', 'theta', 'theta.user_readback', 'theta.user_setpoint', 'chi', 'chi.user_readback', 'chi.user_setpoint', 'phi', 'phi.user_readback', 'phi.user_setpoint', 'ttheta', 'ttheta.user_readback', 'ttheta.user_setpoint', 'psi', 'temperature'], configuration_attrs=['beam', 'beam.source_type', 'beam.wavelength_units', 'beam.wavelength_deadband', 'beam.energy_units', 'h', 'k', 'l', 'h2', 'k2', 'l2', 'theta', 'theta.user_offset', 'theta.user_offset_dir', 'theta.velocity', 'theta.acceleration', 'theta.motor_egu', 'chi', 'chi.user_offset', 'chi.user_offset_dir', 'chi.velocity', 'chi.acceleration', 'chi.motor_egu', 'phi', 'phi.user_offset', 'phi.user_offset_dir', 'phi.velocity', 'phi.acceleration', 'phi.motor_egu', 'ttheta', 'ttheta.user_offset', 'ttheta.user_offset_dir', 'ttheta.velocity', 'ttheta.acceleration', 'ttheta.motor_egu'], concurrent=True)

Most features can be implemented using the creator(). Only the limits and initial values of the temperature Component cannot be specified.

Continuing with the same Python commands…

fourc.wh()
wavelength=0.5466
pseudos: h=0, k=0, l=0
reals: theta=0, chi=0, phi=0, ttheta=0
positioners: h2=0, k2=0, l2=0, psi=0, temperature=0
fourc.wh(full=True)
diffractometer='fourc'
HklSolver(name='hkl_soleil', version='5.1.2', geometry='E4CV', engine_name='hkl', mode='bissector')
Sample(name='sample', lattice=Lattice(a=1, system='cubic'))
Orienting reflections: []
U=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
UB=[[6.2832, 0.0, 0.0], [0.0, 6.2832, 0.0], [0.0, 0.0, 6.2832]]
constraint: -180.0 <= theta <= 180.0
constraint: -180.0 <= chi <= 180.0
constraint: -180.0 <= phi <= 180.0
constraint: -180.0 <= ttheta <= 180.0
Mode: bissector
beam={'class': 'EpicsMonochromatorRO', 'source_type': 'Simulated read-only EPICS Monochromator', 'energy': 22.684, 'wavelength': 0.5466, 'energy_units': 'keV', 'wavelength_units': 'angstrom', 'wavelength_PV': 'gp:BraggLambdaRdbkAO', 'energy_PV': 'gp:BraggERdbkAO'}
pseudos: h=0, k=0, l=0
reals: theta=0, chi=0, phi=0, ttheta=0
positioners: h2=0, k2=0, l2=0, psi=0, temperature=0
fourc.forward(1, 0, 0)  # Shows the default choice.
Hklpy2DiffractometerRealPos(theta=-15.8598649004, chi=-1.3090364e-05, phi=-90.000002688413, ttheta=-31.7197298008)
fourc.core.forward(dict(h=1, k=0, l=0))  # Shows ALL the possibilities.
[Hklpy2DiffractometerRealPos(theta=-15.8598649004, chi=-1.3090364e-05, phi=-90.000002688413, ttheta=-31.7197298008),
 Hklpy2DiffractometerRealPos(theta=15.8598649004, chi=1.3090364e-05, phi=89.999997311587, ttheta=31.7197298008),
 Hklpy2DiffractometerRealPos(theta=-164.1401350996, chi=-1.3090364e-05, phi=-90.000002688413, ttheta=31.7197298008),
 Hklpy2DiffractometerRealPos(theta=-15.8598649004, chi=-179.999986909636, phi=89.999997311587, ttheta=-31.7197298008),
 Hklpy2DiffractometerRealPos(theta=15.8598649004, chi=179.999986909636, phi=-90.000002688413, ttheta=31.7197298008),
 Hklpy2DiffractometerRealPos(theta=-164.1401350996, chi=-179.999986909636, phi=89.999997311587, ttheta=31.7197298008)]
fourc.core.inverse(dict(ttheta=60, theta=30, chi=0, phi=90))
{'h': 1.829588727167, 'k': -4.18052e-07, 'l': -8.6387e-08}