This commit is contained in:
mohacsi_i 2022-11-15 19:09:21 +01:00
parent 5f251db891
commit cb1549cf2d

View File

@ -9,8 +9,16 @@ IMPORTANT: Virtual monochromator axes should be implemented already in EPICS!!!
import numpy as np import numpy as np
from math import isclose from math import isclose
from ophyd import (EpicsSignal, EpicsSignalRO, EpicsMotor, PseudoPositioner, from ophyd import (
PseudoSingle, Device, Component, Kind) EpicsSignal,
EpicsSignalRO,
EpicsMotor,
PseudoPositioner,
PseudoSingle,
Device,
Component,
Kind,
)
from ophyd.pseudopos import pseudo_position_argument, real_position_argument from ophyd.pseudopos import pseudo_position_argument, real_position_argument
from ophyd.sim import SynAxis, Syn2DGauss from ophyd.sim import SynAxis, Syn2DGauss
@ -31,14 +39,12 @@ def a2e(angle, hkl=[1, 1, 1], lnc=False, bent=False, deg=False):
def e2w(energy): def e2w(energy):
"""Convert between energy and wavelength """Convert between energy and wavelength"""
"""
return 0.1 * 12398.42 / energy return 0.1 * 12398.42 / energy
def w2e(wwl): def w2e(wwl):
"""Convert between wavelength and energy """Convert between wavelength and energy"""
"""
return 12398.42 * 0.1 / wwl return 12398.42 * 0.1 / wwl
@ -68,12 +74,13 @@ class MonoMotor(PseudoPositioner):
Small wrapper to combine a real angular axis with the corresponding energy. Small wrapper to combine a real angular axis with the corresponding energy.
ATTENTION: 'angle' is in degrees, at least for PXIII ATTENTION: 'angle' is in degrees, at least for PXIII
""" """
# Real axis (in degrees)
angle = Component(EpicsMotor, "", name='angle')
# Virtual axis
energy = Component(PseudoSingle, name='energy')
_real = ['angle'] # Real axis (in degrees)
angle = Component(EpicsMotor, "", name="angle")
# Virtual axis
energy = Component(PseudoSingle, name="energy")
_real = ["angle"]
@pseudo_position_argument @pseudo_position_argument
def forward(self, pseudo_pos): def forward(self, pseudo_pos):
@ -94,13 +101,13 @@ class MonoDccm(PseudoPositioner):
""" """
# Real axis (in degrees) # Real axis (in degrees)
th1 = Component(EpicsMotor, "ROX1", name='theta1') th1 = Component(EpicsMotor, "ROX1", name="theta1")
th2 = Component(EpicsMotor, "ROX2", name='theta2') th2 = Component(EpicsMotor, "ROX2", name="theta2")
# Virtual axes # Virtual axes
en1 = Component(PseudoSingle, name='en1') en1 = Component(PseudoSingle, name="en1")
en2 = Component(PseudoSingle, name='en2') en2 = Component(PseudoSingle, name="en2")
energy = Component(PseudoSingle, name='energy', kind=Kind.hinted) energy = Component(PseudoSingle, name="energy", kind=Kind.hinted)
# Other parameters # Other parameters
# feedback = Component(EpicsSignal, "MONOBEAM", name="feedback") # feedback = Component(EpicsSignal, "MONOBEAM", name="feedback")
@ -110,17 +117,21 @@ class MonoDccm(PseudoPositioner):
@pseudo_position_argument @pseudo_position_argument
def forward(self, pseudo_pos): def forward(self, pseudo_pos):
"""WARNING: We have an overdefined system! Not sure if common crystal movement is reliable without retuning""" """WARNING: We have an overdefined system! Not sure if common crystal movement is reliable without retuning"""
if abs(pseudo_pos.energy-self.energy.position) > 0.0001 and abs(pseudo_pos.en1-self.en1.position) < 0.0001 and abs(pseudo_pos.en2-self.en2.position) < 0.0001: if (
abs(pseudo_pos.energy - self.energy.position) > 0.0001
and abs(pseudo_pos.en1 - self.en1.position) < 0.0001
and abs(pseudo_pos.en2 - self.en2.position) < 0.0001
):
# Probably the common energy was changed # Probably the common energy was changed
return self.RealPosition( return self.RealPosition(
th1=-180.0 * e2a(pseudo_pos.energy) / 3.141592, th1=-180.0 * e2a(pseudo_pos.energy) / 3.141592,
th2=180.0 * e2a(pseudo_pos.energy) / 3.141592 th2=180.0 * e2a(pseudo_pos.energy) / 3.141592,
) )
else: else:
# Probably the individual axes was changes # Probably the individual axes was changes
return self.RealPosition( return self.RealPosition(
th1=-180.0 * e2a(pseudo_pos.en1 / 3.141592, th1=-180.0 * e2a(pseudo_pos.en1) / 3.141592,
th2=180.0 * e2a(pseudo_pos.en2) / 3.141592 th2=180.0 * e2a(pseudo_pos.en2) / 3.141592,
) )
@real_position_argument @real_position_argument
@ -128,5 +139,5 @@ class MonoDccm(PseudoPositioner):
return self.PseudoPosition( return self.PseudoPosition(
en1=-a2e(3.141592 * real_pos.th1 / 180.0), en1=-a2e(3.141592 * real_pos.th1 / 180.0),
en2=a2e(3.141592 * real_pos.th2 / 180.0), en2=a2e(3.141592 * real_pos.th2 / 180.0),
energy=-a2e(3.141592 * real_pos.th1 / 180.0) energy=-a2e(3.141592 * real_pos.th1 / 180.0),
) )