Closed prjemian closed 4 years ago
In https://github.com/bluesky/hklpy/issues/29#issuecomment-700155456, it was shown how to get photon energy from beam line controls. The same steps could be used to get wavelength instead.
Internally, the calc
module stores only the wavelength (angstroms). It converts energy to wavelength when energy is set. Here's the code: https://github.com/bluesky/hklpy/blob/14463c40d956f73768a3a4494ea1af3fba98dd85/hkl/calc.py#L136-L152
example
This user operation sets the energy: fourc.calc.energy = 8.04
(the units are keV). The setter
part sets the internal wavelength fourc.calc._wavelength
by calculating A_KEV/energy
. When the users asks for the current energy, it is recalculated from the internal wavelength (A_KEV/wavelength
).
It is recommended to get either the energy or wavelength from the beam line controls, but not both. This is always a local customization to the specific instrument so it is not appropriate to add into the code here. (This example could be part of the documentation, however.)
There is already code in place to use an energy ophyd.Signal
(and a default Diffractometer._energy_changed()
method) to set energy and wavelength in the calc
attribute. Override the energy
Signal
with an ophyd.EpicsSignal
and connect to the desired energy PV. An example is provided (from https://github.com/bluesky/hklpy/issues/29#issuecomment-700097970 & https://github.com/bluesky/hklpy/issues/29#issuecomment-700155456). The example also shows unit conversion (using thepint package) and a Signal
for energy offset (as requested in #25). (If the offset is an EPICS PV, then use EpicsSignal
and the PV instead).
import gi
gi.require_version('Hkl', '5.0')
import hkl.diffract
from ophyd import Component, EpicsSignal, Signal
import pint
class LocalDiffractometer(hkl.diffract.Diffractometer):
# ...
energy = Component(EpicsSignal, "EPICS:diffractometer:energy")
energy_EGU = Component(EpicsSignal, "EPICS:diffractometer:energy.EGU")
energy_update_calc = Component(EpicsSignal, "EPICS:diffractometer:energy_update_hkl")
energy_offset = Component(Signal, value=0)
# ...
def _energy_changed(self, value=None, **kwargs):
'''
Callback indicating that the energy signal was updated
'''
if energy_update_calc.get() in (1, "Yes", "locked", "OK"):
local_energy = value + self.energy_offset.get()
units = self.energy_EGU.get() # get units from EPICS
# units = "eV" # alternative: from control system always gives "eV"
logger.debug(
'{0.name} energy changed: {1} {2}'.format(
self, value, units))
keV = pint.Quantity(local_energy, units).to("keV")
self._calc.energy = keV
self._update_position()
Originally posted by @ambarb in https://github.com/bluesky/hklpy/issues/17#issuecomment-591471108