Mono motors in read only mode

This commit is contained in:
Mohacsi Istvan 2022-11-22 17:52:45 +01:00
parent fd7208ed3e
commit bbf53a3e64
4 changed files with 186 additions and 19 deletions

View File

@ -57,8 +57,8 @@ if __name__ == "__main__":
for key in lut_db:
try:
dut = createProxy(str(key))
# print(f"{key}\t: {type(dut)}\t{dut.read()}")
print(f"{key}\t: {type(dut)}")
print(f"{key}\t: {type(dut)}\t{dut.read()}")
# print(f"{key}\t: {type(dut)}")
except Exception as ex:
num_errors += 1
print(key)

View File

@ -166,13 +166,13 @@ motrz1e:
deviceGroup: monitor
status: {enabled: true}
type: EpicsSignalRO
#mopush1:
# desc: 'Monochromator crystal 1 angle'
# acquisition: {schedule: sync}
# config: {name: mopush1, prefix: 'X12SA-OP-MO:ROX1'}
# deviceGroup: beamlineMotor
# status: {enabled: true}
# type: EpicsMotor
mopush1:
desc: 'Monochromator crystal 1 angle'
acquisition: {schedule: sync}
config: {name: mopush1, read_pv: 'X12SA-OP-MO:ROX1'}
deviceGroup: monitor
status: {enabled: true}
type: EpicsSignalRO
moth1e:
desc: 'Monochromator crystal 1 theta encoder'
acquisition: {schedule: sync}
@ -201,13 +201,13 @@ motry2:
deviceGroup: beamlineMotor
status: {enabled: true}
type: EpicsMotor
#mopush2:
# desc: 'Monochromator crystal 2 angle'
# acquisition: {schedule: sync}
# config: {name: mopush2, prefix: 'X12SA-OP-MO:ROX2'}
# deviceGroup: beamlineMotor
# status: {enabled: true}
# type: EpicsMotor
mopush2:
desc: 'Monochromator crystal 2 angle'
acquisition: {schedule: sync}
config: {name: mopush2, read_pv: 'X12SA-OP-MO:ROX2.VAL'}
deviceGroup: monitor
status: {enabled: true}
type: EpicsSignalRO
moth2e:
desc: 'Monochromator crystal 2 theta encoder'
acquisition: {schedule: sync}
@ -878,3 +878,63 @@ FBPMUY:
status: {enabled: true}
type: EpicsSignalRO
sttrx:
desc: 'Girder X translation'
acquisition: {schedule: sync}
config: {name: sttrx, prefix: 'X12SA-HG'}
deviceGroup: beamlineMotor
status: {enabled: true}
type: GirderMotorX1
sttry:
desc: 'Girder Y translation'
acquisition: {schedule: sync}
config: {name: sttry, prefix: 'X12SA-HG'}
deviceGroup: beamlineMotor
status: {enabled: true}
type: GirderMotorY1
strox:
desc: 'Girder virtual pitch'
acquisition: {schedule: sync}
config: {name: strox, prefix: 'X12SA-HG'}
deviceGroup: beamlineMotor
status: {enabled: true}
type: GirderMotorPITCH
stroy:
desc: 'Girder virtual yaw'
acquisition: {schedule: sync}
config: {name: stroy, prefix: 'X12SA-HG'}
deviceGroup: beamlineMotor
status: {enabled: true}
type: GirderMotorYAW
stroz:
desc: 'Girder virtual roll'
acquisition: {schedule: sync}
config: {name: stroz, prefix: 'X12SA-HG'}
deviceGroup: beamlineMotor
status: {enabled: true}
type: GirderMotorROLL
mokev:
desc: 'Monochromator energy in keV'
acquisition: {schedule: sync}
config: {name: mokev, read_pv: 'X12SA-OP-MO:ROX2.VAL'}
deviceGroup: monitor
status: {enabled: true}
type: EnergyKev
moth1:
desc: 'Monochromator Theta 1'
acquisition: {schedule: sync}
config: {name: moth1, read_pv: 'X12SA-OP-MO:ECX1'}
deviceGroup: monitor
status: {enabled: true}
type: MonoTheta1
moth2:
desc: 'Monochromator Theta 2'
acquisition: {schedule: sync}
config: {name: moth1, read_pv: 'X12SA-OP-MO:ECX2'}
deviceGroup: monitor
status: {enabled: true}
type: MonoTheta2

View File

@ -3,7 +3,7 @@ from .slits import SlitH, SlitV
from .XbpmBase import XbpmBase, XbpmCsaxsOp
from .SpmBase import SpmBase
from .InsertionDevice import InsertionDevice
from .specMotors import PmMonoBender, PmDetectorRotation
from .specMotors import PmMonoBender, PmDetectorRotation, GirderMotorX1, GirderMotorY1, GirderMotorROLL, GirderMotorYAW, GirderMotorPITCH, MonoTheta1, MonoTheta2, EnergyKev
# Standard ophyd classes

View File

@ -8,19 +8,20 @@ IMPORTANT: Virtual monochromator axes should be implemented already in EPICS!!!
"""
import numpy as np
from math import isclose, tan, atan
from math import isclose, tan, atan, sqrt, sin, asin
from ophyd import (
EpicsSignal,
EpicsSignalRO,
EpicsMotor,
PseudoPositioner,
PseudoSingle,
PVPositioner,
Device,
Component,
Kind,
)
from ophyd.pseudopos import pseudo_position_argument, real_position_argument
from ophyd.utils.epics_pvs import data_type
class PmMonoBender(PseudoPositioner):
@ -91,3 +92,109 @@ class PmDetectorRotation(PseudoPositioner):
@real_position_argument
def inverse(self, real_pos):
return self.PseudoPosition(dtth=r2d(-atan(real_pos.dtpush / self._tables_dt_push_dist_mm)))
class GirderMotorX1(PVPositioner):
"""Girder X translation pseudo motor
"""
setpoint = Component(EpicsSignal, ":X_SET", name="sp")
readback = Component(EpicsSignalRO, ":X1", name="rbv")
done = Component(EpicsSignal, ":M-DMOV", name="dmov")
class GirderMotorY1(PVPositioner):
"""Girder Y translation pseudo motor
"""
setpoint = Component(EpicsSignal, ":Y_SET", name="sp")
readback = Component(EpicsSignalRO, ":Y1", name="rbv")
done = Component(EpicsSignal, ":M-DMOV", name="dmov")
class GirderMotorYAW(PVPositioner):
"""Girder YAW pseudo motor
"""
setpoint = Component(EpicsSignal, ":YAW_SET", name="sp")
readback = Component(EpicsSignalRO, ":YAW1", name="rbv")
done = Component(EpicsSignal, ":M-DMOV", name="dmov")
class GirderMotorROLL(PVPositioner):
"""Girder ROLL pseudo motor
"""
setpoint = Component(EpicsSignal, ":ROLL_SET", name="sp")
readback = Component(EpicsSignalRO, ":ROLL1", name="rbv")
done = Component(EpicsSignal, ":M-DMOV", name="dmov")
class GirderMotorPITCH(PVPositioner):
"""Girder YAW pseudo motor
"""
setpoint = Component(EpicsSignal, ":PITCH_SET", name="sp")
readback = Component(EpicsSignalRO, ":PITCH1", name="rbv")
done = Component(EpicsSignal, ":M-DMOV", name="dmov")
class VirtualSignalBase(EpicsSignalRO):
"""This is a test class to create derives signals from one or
multiple original signals...
"""
def calc(self, val):
return val
def get(self, *args, **kwargs):
raw = super().get(*args, **kwargs)
return self.calc(raw)
def describe(self):
val = self.get()
d = super().describe()
d[self.name]["dtype"] = data_type(val)
return d
class MonoTheta1(VirtualSignalBase):
"""Converts the pusher motor position to theta angle
"""
_mono_a0_enc_scale1 = -1.0
_mono_a1_lever_length1 = 206.706
_mono_a2_pusher_offs1 = 6.85858
_mono_a3_enc_offs1 = -16.9731
def calc(self, val):
asin_arg = (val - self._mono_a2_pusher_offs1) / self._mono_a1_lever_length1
theta1 = self._mono_a0_enc_scale1 * asin( asin_arg ) / 3.141592 * 180.0 + self._mono_a3_enc_offs1
return theta1
class MonoTheta2(VirtualSignalBase):
"""Converts the pusher motor position to theta angle
"""
_mono_a3_enc_offs2 = -19.7072
_mono_a2_pusher_offs2 = 5.93905
_mono_a1_lever_length2 = 206.572
_mono_a0_enc_scale2 = -1.0
def calc(self, val):
asin_arg = (val - self._mono_a2_pusher_offs2) / self._mono_a1_lever_length2
theta2 = self._mono_a0_enc_scale2 * asin( asin_arg ) / 3.141592 * 180.0 + self._mono_a3_enc_offs2
return theta2
class EnergyKev(VirtualSignalBase):
"""Converts the pusher motor position to energy in keV
"""
_mono_hce = 12.39852066
_mono_2d2 = 2*5.43102/sqrt(3)
def calc(self, val):
theta_deg = atan(50 / val) / 2.0 * 180.0 / 3.141592
E_keV = -self._mono_hce / self._mono_2d2 / sin(theta_deg/180.0*3.14152)
return E_keV