mirror of
https://github.com/bec-project/ophyd_devices.git
synced 2025-05-24 17:30:41 +02:00
Merge branch 'virtual-motors-for-detector' into 'feature-first-epics-devices'
Virtual motors for detector See merge request bec/ophyd_devices!7
This commit is contained in:
commit
9c27f8f999
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,4 +5,6 @@
|
||||
.DS_Store
|
||||
**/out
|
||||
**/.vscode
|
||||
**/.pytest_cache
|
||||
**/.pytest_cache
|
||||
*.egg-info
|
||||
|
||||
|
@ -53,10 +53,14 @@ def createProxy(name: str, connect=True) -> OphydObject:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
num_errors = 0
|
||||
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)
|
||||
print(ex)
|
||||
print(f"\nTotal number of errors: {num_errors}")
|
||||
|
@ -145,104 +145,43 @@ fi3try:
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motry:
|
||||
desc: 'OpticsHutch optical table vertical movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motry, prefix: 'X12SA-OP-OT:TRY'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motrz1:
|
||||
desc: 'Monochromator crystal 1 axial movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motrz1, prefix: 'X12SA-OP-MO:TRZ1'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
mopush1:
|
||||
desc: 'Monochromator crystal 1 angle'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mopush1, prefix: 'X12SA-OP-MO:ROX1'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
moroll1:
|
||||
desc: 'Monochromator crystal 1 roll'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moroll1, prefix: 'X12SA-OP-MO:ROZ1'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motrx2:
|
||||
desc: 'Monochromator crystal 2 horizontal movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motrx2, prefix: 'X12SA-OP-MO:TRX2'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motry2:
|
||||
desc: 'Monochromator crystal 2 vertical movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motry2, prefix: 'X12SA-OP-MO:TRY2'}
|
||||
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
|
||||
#monot:
|
||||
# desc: 'Monochromator temperature'
|
||||
# acquisition: {schedule: sync}
|
||||
# config: {name: monot, read_pv: 'X12SA-OP-MO:TC3'}
|
||||
# deviceGroup: monitor
|
||||
# status: {enabled: true}
|
||||
# type: EpicsSignalRO
|
||||
moyaw2:
|
||||
desc: 'Monochromator crystal 2 yaw movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moyaw2, prefix: 'X12SA-OP-MO:ROY2'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
moroll2:
|
||||
desc: 'Monochromator crystal 2 roll movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moroll2, prefix: 'X12SA-OP-MO:ROZ2'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
|
||||
mobdai:
|
||||
desc: 'Monochromator ??? inner motor'
|
||||
desc: 'Monochromator bender inner motor'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mobdai, prefix: 'X12SA-OP-MO:TRYA'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
mobdbo:
|
||||
desc: 'Monochromator ??? outer motor'
|
||||
desc: 'Monochromator bender outer motor'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mobdbo, prefix: 'X12SA-OP-MO:TRYB'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
mobdco:
|
||||
desc: 'Monochromator ??? outer motor'
|
||||
desc: 'Monochromator bender outer motor'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mobdco, prefix: 'X12SA-OP-MO:TRYC'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
mobddi:
|
||||
desc: 'Monochromator ??? inner motor'
|
||||
desc: 'Monochromator bender inner motor'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mobddi, prefix: 'X12SA-OP-MO:TRYD'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
mobd:
|
||||
desc: 'Monochromator bender virtual motor'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mobd, prefix: 'X12SA-OP-MO:'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: PmMonoBender
|
||||
|
||||
bm4trx:
|
||||
desc: 'OpticsHutch XBPM 2 horizontal movement'
|
||||
acquisition: {schedule: sync}
|
||||
@ -475,12 +414,19 @@ dttrz:
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
dtpush:
|
||||
desc: 'Detector tower motion'
|
||||
desc: 'Detector tower tilt pusher'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: dtpush, prefix: 'X12SA-ES1-DETT:ROX1'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
dtth:
|
||||
desc: 'Detector tower tilt rotation'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: dtth, prefix: 'X12SA-ES1-DETT:ROX1'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: PmDetectorRotation
|
||||
dettrx:
|
||||
desc: 'Detector tower motion'
|
||||
acquisition: {schedule: sync}
|
||||
@ -841,3 +787,158 @@ FBPMUY:
|
||||
deviceGroup: monitor
|
||||
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
|
||||
motry:
|
||||
desc: 'OpticsHutch optical table vertical movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motry, prefix: 'X12SA-OP-OT:TRY'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motrz1:
|
||||
desc: 'Monochromator crystal 1 axial movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motrz1, prefix: 'X12SA-OP-MO:TRZ1'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motrz1e:
|
||||
desc: 'Monochromator crystal 1 axial movement encoder'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motrz1e, read_pv: 'X12SA-OP-MO:ECZ1'}
|
||||
deviceGroup: monitor
|
||||
status: {enabled: true}
|
||||
type: EpicsSignalRO
|
||||
|
||||
|
||||
moroll1:
|
||||
desc: 'Monochromator crystal 1 roll'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moroll1, prefix: 'X12SA-OP-MO:ROZ1'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motrx2:
|
||||
desc: 'Monochromator crystal 2 horizontal movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motrx2, prefix: 'X12SA-OP-MO:TRX2'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
motry2:
|
||||
desc: 'Monochromator crystal 2 vertical movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: motry2, prefix: 'X12SA-OP-MO:TRY2'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
|
||||
|
||||
#monot:
|
||||
# desc: 'Monochromator temperature'
|
||||
# acquisition: {schedule: sync}
|
||||
# config: {name: monot, read_pv: 'X12SA-OP-MO:TC3'}
|
||||
# deviceGroup: monitor
|
||||
# status: {enabled: true}
|
||||
# type: EpicsSignalRO
|
||||
moyaw2:
|
||||
desc: 'Monochromator crystal 2 yaw movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moyaw2, prefix: 'X12SA-OP-MO:ROY2'}
|
||||
deviceGroup: beamlineMotor
|
||||
status: {enabled: true}
|
||||
type: EpicsMotor
|
||||
moroll2:
|
||||
desc: 'Monochromator crystal 2 roll movement'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moroll2, prefix: 'X12SA-OP-MO:ROZ2'}
|
||||
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
|
||||
moth1:
|
||||
desc: 'Monochromator Theta 1'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moth1, read_pv: 'X12SA-OP-MO:ROX1'}
|
||||
deviceGroup: monitor
|
||||
status: {enabled: true}
|
||||
type: MonoTheta1
|
||||
moth1e:
|
||||
desc: 'Monochromator crystal 1 theta encoder'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moth1e, read_pv: 'X12SA-OP-MO:ECX1'}
|
||||
deviceGroup: monitor
|
||||
status: {enabled: true}
|
||||
type: EpicsSignalRO
|
||||
mopush2:
|
||||
desc: 'Monochromator crystal 2 angle'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mopush2, read_pv: 'X12SA-OP-MO:ROX2'}
|
||||
deviceGroup: monitor
|
||||
status: {enabled: true}
|
||||
type: EpicsSignalRO
|
||||
moth2:
|
||||
desc: 'Monochromator Theta 2'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moth1, read_pv: 'X12SA-OP-MO:ROX2'}
|
||||
deviceGroup: monitor
|
||||
status: {enabled: true}
|
||||
type: MonoTheta2
|
||||
moth2e:
|
||||
desc: 'Monochromator crystal 2 theta encoder'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: moth2e, read_pv: 'X12SA-OP-MO:ECX2'}
|
||||
deviceGroup: monitor
|
||||
status: {enabled: true}
|
||||
type: EpicsSignalRO
|
||||
mokev:
|
||||
desc: 'Monochromator energy in keV'
|
||||
acquisition: {schedule: sync}
|
||||
config: {name: mokev, read_pv: 'X12SA-OP-MO:ROX2'}
|
||||
deviceGroup: monitor
|
||||
status: {enabled: true}
|
||||
type: EnergyKev
|
||||
|
||||
|
||||
|
@ -58,7 +58,7 @@ class SpmSim(SpmBase):
|
||||
# Define normalized 2D gaussian
|
||||
def gaus2d(x=0, y=0, mx=0, my=0, sx=1, sy=1):
|
||||
return np.exp(
|
||||
-((x - mx) ** 2.0 / (2.0 * sx**2.0) + (y - my) ** 2.0 / (2.0 * sy**2.0))
|
||||
-((x - mx) ** 2.0 / (2.0 * sx ** 2.0) + (y - my) ** 2.0 / (2.0 * sy ** 2.0))
|
||||
)
|
||||
|
||||
# Generator for dynamic values
|
||||
@ -74,10 +74,10 @@ class SpmSim(SpmBase):
|
||||
beam = self._simFrame()
|
||||
total = np.sum(beam) - np.sum(beam[24:48, :])
|
||||
rnge = np.floor(np.log10(total) - 0.0)
|
||||
s1 = np.sum(beam[0:16, :]) / 10**rnge
|
||||
s2 = np.sum(beam[16:24, :]) / 10**rnge
|
||||
s3 = np.sum(beam[40:48, :]) / 10**rnge
|
||||
s4 = np.sum(beam[48:64, :]) / 10**rnge
|
||||
s1 = np.sum(beam[0:16, :]) / 10 ** rnge
|
||||
s2 = np.sum(beam[16:24, :]) / 10 ** rnge
|
||||
s3 = np.sum(beam[40:48, :]) / 10 ** rnge
|
||||
s4 = np.sum(beam[48:64, :]) / 10 ** rnge
|
||||
|
||||
self.s1w.set(s1).wait()
|
||||
self.s2w.set(s2).wait()
|
||||
|
@ -88,7 +88,7 @@ class XbpmSim(XbpmBase):
|
||||
# define normalized 2D gaussian
|
||||
def gaus2d(x=0, y=0, mx=0, my=0, sx=1, sy=1):
|
||||
return np.exp(
|
||||
-((x - mx) ** 2.0 / (2.0 * sx**2.0) + (y - my) ** 2.0 / (2.0 * sy**2.0))
|
||||
-((x - mx) ** 2.0 / (2.0 * sx ** 2.0) + (y - my) ** 2.0 / (2.0 * sy ** 2.0))
|
||||
)
|
||||
|
||||
# Generator for dynamic values
|
||||
@ -104,10 +104,10 @@ class XbpmSim(XbpmBase):
|
||||
beam = self._simFrame()
|
||||
total = np.sum(beam)
|
||||
rnge = np.floor(np.log10(total) - 0.0)
|
||||
s1 = np.sum(beam[32:64, 32:64]) / 10**rnge
|
||||
s2 = np.sum(beam[0:32, 32:64]) / 10**rnge
|
||||
s3 = np.sum(beam[32:64, 0:32]) / 10**rnge
|
||||
s4 = np.sum(beam[0:32, 0:32]) / 10**rnge
|
||||
s1 = np.sum(beam[32:64, 32:64]) / 10 ** rnge
|
||||
s2 = np.sum(beam[0:32, 32:64]) / 10 ** rnge
|
||||
s3 = np.sum(beam[32:64, 0:32]) / 10 ** rnge
|
||||
s4 = np.sum(beam[0:32, 0:32]) / 10 ** rnge
|
||||
|
||||
self.s1w.set(s1).wait()
|
||||
self.s2w.set(s2).wait()
|
||||
|
@ -3,6 +3,19 @@ from .slits import SlitH, SlitV
|
||||
from .XbpmBase import XbpmBase, XbpmCsaxsOp
|
||||
from .SpmBase import SpmBase
|
||||
from .InsertionDevice import InsertionDevice
|
||||
from .specMotors import (
|
||||
PmMonoBender,
|
||||
PmDetectorRotation,
|
||||
GirderMotorX1,
|
||||
GirderMotorY1,
|
||||
GirderMotorROLL,
|
||||
GirderMotorYAW,
|
||||
GirderMotorPITCH,
|
||||
MonoTheta1,
|
||||
MonoTheta2,
|
||||
EnergyKev,
|
||||
)
|
||||
|
||||
|
||||
# Standard ophyd classes
|
||||
from ophyd import EpicsSignal, EpicsSignalRO, EpicsMotor
|
||||
|
30
ophyd_devices/epics/devices/cSaxsVirtualMotors.py
Normal file
30
ophyd_devices/epics/devices/cSaxsVirtualMotors.py
Normal file
@ -0,0 +1,30 @@
|
||||
TABLES_DT_PUSH_DIST_MM = 890
|
||||
|
||||
|
||||
class DetectorTableTheta(PseudoPositioner):
|
||||
"""Detector table tilt motor
|
||||
|
||||
Small wrapper to adjust the detector table tilt as angle.
|
||||
The table is pushed from one side by a single vertical motor.
|
||||
|
||||
Note: Rarely used!
|
||||
"""
|
||||
|
||||
# Real axis (in degrees)
|
||||
pusher = Component(EpicsMotor, "", name="pusher")
|
||||
# Virtual axis
|
||||
theta = Component(PseudoSingle, name="theta")
|
||||
|
||||
_real = ["pusher"]
|
||||
|
||||
@pseudo_position_argument
|
||||
def forward(self, pseudo_pos):
|
||||
return self.RealPosition(
|
||||
pusher=tan(pseudo_pos.theta * 3.141592 / 180.0) * TABLES_DT_PUSH_DIST_MM
|
||||
)
|
||||
|
||||
@real_position_argument
|
||||
def inverse(self, real_pos):
|
||||
return self.PseudoPosition(
|
||||
theta=-180 * atan(real_pos.pusher / TABLES_DT_PUSH_DIST_MM) / 3.141592
|
||||
)
|
212
ophyd_devices/epics/devices/specMotors.py
Normal file
212
ophyd_devices/epics/devices/specMotors.py
Normal file
@ -0,0 +1,212 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Oct 13 18:06:15 2021
|
||||
|
||||
@author: mohacsi_i
|
||||
|
||||
IMPORTANT: Virtual monochromator axes should be implemented already in EPICS!!!
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
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):
|
||||
"""Monochromator bender
|
||||
|
||||
Small wrapper to combine the four monochromator bender motors.
|
||||
"""
|
||||
|
||||
# Real axes
|
||||
ai = Component(EpicsMotor, "TRYA", name="ai")
|
||||
bo = Component(EpicsMotor, "TRYB", name="bo")
|
||||
co = Component(EpicsMotor, "TRYC", name="co")
|
||||
di = Component(EpicsMotor, "TRYD", name="di")
|
||||
|
||||
# Virtual axis
|
||||
bend = Component(PseudoSingle, name="bend")
|
||||
|
||||
_real = ["ai", "bo", "co", "di"]
|
||||
|
||||
@pseudo_position_argument
|
||||
def forward(self, pseudo_pos):
|
||||
delta = pseudo_pos.bend - 0.25 * (
|
||||
self.ai.position + self.bo.position + self.co.position + self.di.position
|
||||
)
|
||||
return self.RealPosition(
|
||||
ai=self.ai.position + delta,
|
||||
bo=self.bo.position + delta,
|
||||
co=self.co.position + delta,
|
||||
di=self.di.position + delta,
|
||||
)
|
||||
|
||||
@real_position_argument
|
||||
def inverse(self, real_pos):
|
||||
return self.PseudoPosition(
|
||||
bend=0.25 * (real_pos.ai + real_pos.bo + real_pos.co + real_pos.di)
|
||||
)
|
||||
|
||||
|
||||
def r2d(radians):
|
||||
return radians * 180 / 3.141592
|
||||
|
||||
|
||||
def d2r(degrees):
|
||||
return degrees * 3.141592 / 180.0
|
||||
|
||||
|
||||
class PmDetectorRotation(PseudoPositioner):
|
||||
"""Detector rotation pseudo motor
|
||||
|
||||
Small wrapper to convert detector pusher position to rotation angle.
|
||||
"""
|
||||
|
||||
_tables_dt_push_dist_mm = 890
|
||||
# Real axes
|
||||
dtpush = Component(EpicsMotor, "", name="dtpush")
|
||||
|
||||
# Virtual axis
|
||||
dtth = Component(PseudoSingle, name="dtth")
|
||||
|
||||
_real = ["dtpush"]
|
||||
|
||||
@pseudo_position_argument
|
||||
def forward(self, pseudo_pos):
|
||||
return self.RealPosition(
|
||||
dtpush=d2r(tan(-3.14 / 180 * pseudo_pos.dtth)) * self._tables_dt_push_dist_mm
|
||||
)
|
||||
|
||||
@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 VirtualEpicsSignalRO(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(VirtualEpicsSignalRO):
|
||||
"""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(VirtualEpicsSignalRO):
|
||||
"""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(VirtualEpicsSignalRO):
|
||||
"""Converts the pusher motor position to energy in keV
|
||||
"""
|
||||
|
||||
_mono_a3_enc_offs2 = -19.7072
|
||||
_mono_a2_pusher_offs2 = 5.93905
|
||||
_mono_a1_lever_length2 = 206.572
|
||||
_mono_a0_enc_scale2 = -1.0
|
||||
_mono_hce = 12.39852066
|
||||
_mono_2d2 = 2 * 5.43102 / sqrt(3)
|
||||
|
||||
def calc(self, val):
|
||||
asin_arg = (val - self._mono_a2_pusher_offs2) / self._mono_a1_lever_length2
|
||||
theta2_deg = (
|
||||
self._mono_a0_enc_scale2 * asin(asin_arg) / 3.141592 * 180.0 + self._mono_a3_enc_offs2
|
||||
)
|
||||
E_keV = -self._mono_hce / self._mono_2d2 / sin(theta2_deg / 180.0 * 3.14152)
|
||||
return E_keV
|
Loading…
x
Reference in New Issue
Block a user