Compare commits
44 Commits
progress
...
docs/csaxs
| Author | SHA1 | Date | |
|---|---|---|---|
| ca40a8eb3d | |||
| f476b210f1 | |||
|
|
fad8b516a6 | ||
| a9ff092a66 | |||
| 37d80e9a7b | |||
| ed335dc308 | |||
| 78d2dd2436 | |||
|
|
bf2e6baba5 | ||
| fcf9ee4545 | |||
|
|
53a200928f | ||
|
|
1572dd4484 | ||
|
|
f72be7ab70 | ||
|
|
8aee3e3c0d | ||
|
|
6a517d3ac5 | ||
|
|
b6b2850853 | ||
|
|
5841a56255 | ||
|
|
333b4f1dd2 | ||
|
|
97e09cf622 | ||
|
|
174c0689bc | ||
|
|
a3899bf7a5 | ||
|
|
d4c12a3c9c | ||
|
|
8f0ed4e250 | ||
|
|
0359f1f431 | ||
|
|
b45070332d | ||
|
|
35e4ea0916 | ||
| ae86fbd329 | |||
| a195be64e7 | |||
| e980bf2ee6 | |||
| ce876f58d6 | |||
|
|
b0a1c32b47 | ||
| 11ed6e112f | |||
| 8a24692e82 | |||
| 1d266c5da9 | |||
| 7d93154761 | |||
| c85c6ec5ab | |||
|
|
d567e49b53 | ||
| 73ce61dd96 | |||
| 8410b3ceec | |||
| 477567e61a | |||
| 7da1bddef8 | |||
| 5007b182ca | |||
| 063308042d | |||
| 0180e4a3f9 | |||
| fc37892ea1 |
@@ -4,4 +4,5 @@ include:
|
||||
inputs:
|
||||
name: "csaxs"
|
||||
target: "csaxs_bec"
|
||||
branch: $CHILD_PIPELINE_BRANCH
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ from __future__ import annotations
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from bec_lib import MessageEndpoints, RedisConnector, bec_logger, messages
|
||||
from bec_lib.redis_connector import MessageObject
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_lib.redis_connector import MessageObject, RedisConnector
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
@@ -27,7 +28,7 @@ class PilatusConverter:
|
||||
message (MessageObject): Message object
|
||||
parent (PilatusConverter): Parent object
|
||||
"""
|
||||
msg = messages.MessageReader.loads(message.value)
|
||||
msg = message.value
|
||||
print(msg)
|
||||
if not msg:
|
||||
return
|
||||
|
||||
@@ -22,7 +22,7 @@ class LaMNIInitStagesMixin:
|
||||
user_input = input("Starting initialization of LamNI stages. OK? [y/n]")
|
||||
if user_input == "y":
|
||||
print("staring...")
|
||||
dev.lsamrot.enabled=True
|
||||
dev.lsamrot.enabled = True
|
||||
else:
|
||||
return
|
||||
|
||||
@@ -42,7 +42,7 @@ class LaMNIInitStagesMixin:
|
||||
return
|
||||
|
||||
self.drive_axis_to_limit(dev.lsamrot, "forward")
|
||||
dev.lsamrot.enabled=False
|
||||
dev.lsamrot.enabled = False
|
||||
print("Now hard reboot the controller and run the initialization routine again.")
|
||||
print("The controller will be disabled in bec. To enable dev.lsamrot.enabled=True")
|
||||
return
|
||||
@@ -108,10 +108,10 @@ class LaMNIInitStagesMixin:
|
||||
time.sleep(1)
|
||||
dev.losax.controller.find_reference_mark(1, 0, 1000, 1)
|
||||
time.sleep(1)
|
||||
#dev.losax.controller.find_reference_mark(3, 1, 1000, 1)
|
||||
#time.sleep(1)
|
||||
#dev.losax.controller.find_reference_mark(4, 1, 1000, 1)
|
||||
#time.sleep(1)
|
||||
# dev.losax.controller.find_reference_mark(3, 1, 1000, 1)
|
||||
# time.sleep(1)
|
||||
# dev.losax.controller.find_reference_mark(4, 1, 1000, 1)
|
||||
# time.sleep(1)
|
||||
|
||||
# set_lm losax -1.5 0.25
|
||||
# set_lm losay -2.5 4.1
|
||||
|
||||
@@ -16,8 +16,7 @@ from typeguard import typechecked
|
||||
|
||||
from csaxs_bec.bec_ipython_client.plugins.cSAXS import epics_get, epics_put, fshopen
|
||||
|
||||
from .lamni_optics_mixin import LamNIOpticsMixin
|
||||
from .lamni_optics_mixin import LaMNIInitStagesMixin
|
||||
from .lamni_optics_mixin import LaMNIInitStagesMixin, LamNIOpticsMixin
|
||||
|
||||
logger = bec_logger.logger
|
||||
bec = builtins.__dict__.get("bec")
|
||||
@@ -587,6 +586,27 @@ class LamNI(LamNIOpticsMixin):
|
||||
def tomo_circfov(self, val: float):
|
||||
self.client.set_global_var("tomo_circfov", val)
|
||||
|
||||
@property
|
||||
def tomo_type(self):
|
||||
val = self.client.get_global_var("tomo_type")
|
||||
if val is None:
|
||||
return 1
|
||||
return val
|
||||
|
||||
@tomo_type.setter
|
||||
def tomo_type(self, val: float):
|
||||
if val == 1:
|
||||
# equally spaced tomography with 8 sub tomograms
|
||||
self.client.set_global_var("tomo_type", val)
|
||||
# elif val == 2:
|
||||
# # golden ratio tomography (sorted bunches)
|
||||
# self.client.set_global_var("tomo_type", val)
|
||||
# elif val == 3:
|
||||
# # equally spaced tomography with starting angles shifted by golden ratio
|
||||
# self.client.set_global_var("tomo_type", val)
|
||||
else:
|
||||
raise ValueError("Unknown tomo_type.")
|
||||
|
||||
@property
|
||||
def tomo_countingtime(self):
|
||||
val = self.client.get_global_var("tomo_countingtime")
|
||||
@@ -949,25 +969,63 @@ class LamNI(LamNIOpticsMixin):
|
||||
# _tomo_shift_angles (potential global variable)
|
||||
_tomo_shift_angles = 0
|
||||
angle_end = start_angle + 360
|
||||
for angle in np.linspace(
|
||||
angles = np.linspace(
|
||||
start_angle + _tomo_shift_angles,
|
||||
angle_end,
|
||||
num=int(360 / self.tomo_angle_stepsize) + 1,
|
||||
endpoint=True,
|
||||
):
|
||||
successful = False
|
||||
error_caught = False
|
||||
if 0 <= angle < 360.05:
|
||||
print(f"Starting LamNI scan for angle {angle}")
|
||||
while not successful:
|
||||
self._start_beam_check()
|
||||
if not self.special_angles:
|
||||
self._current_special_angles = []
|
||||
if self._current_special_angles:
|
||||
next_special_angle = self._current_special_angles[0]
|
||||
if np.isclose(angle, next_special_angle, atol=0.5):
|
||||
self._current_special_angles.pop(0)
|
||||
num_repeats = self.special_angle_repeats
|
||||
)
|
||||
|
||||
# reverse even sub-tomograms
|
||||
if not (subtomo_number % 2):
|
||||
angles = np.flip(angles)
|
||||
for angle in angles:
|
||||
self.progress["subtomo"] = subtomo_number
|
||||
self.progress["subtomo_projection"] = angles.index(angle)
|
||||
self.progress["subtomo_total_projections"] = 180 / self.tomo_angle_stepsize
|
||||
self.progress["projection"] = (subtomo_number - 1) * self.progress[
|
||||
"subtomo_total_projections"
|
||||
] + self.progress["subtomo_projection"]
|
||||
self.progress["total_projections"] = 180 / self.tomo_angle_stepsize * 8
|
||||
self.progress["angle"] = angle
|
||||
self._tomo_scan_at_angle(angle, subtomo_number)
|
||||
|
||||
def _print_progress(self):
|
||||
print("\x1b[95mProgress report:")
|
||||
print(f"Tomo type: ....................... {self.progress['tomo_type']}")
|
||||
print(f"Projection: ...................... {self.progress['projection']}")
|
||||
print(f"Total projections expected ....... {self.progress['total_projections']}")
|
||||
print(f"Angle: ........................... {self.progress['angle']}")
|
||||
print(f"Current subtomo: ................. {self.progress['subtomo']}")
|
||||
print(f"Current projection within subtomo: {self.progress['subtomo_projection']}\x1b[0m")
|
||||
|
||||
def _tomo_scan_at_angle(self, angle, subtomo_number):
|
||||
successful = False
|
||||
error_caught = False
|
||||
if 0 <= angle < 360.05:
|
||||
print(f"Starting LamNI scan for angle {angle} in subtomo {subtomo_number}")
|
||||
self._print_progress()
|
||||
while not successful:
|
||||
self._start_beam_check()
|
||||
if not self.special_angles:
|
||||
self._current_special_angles = []
|
||||
if self._current_special_angles:
|
||||
next_special_angle = self._current_special_angles[0]
|
||||
if np.isclose(angle, next_special_angle, atol=0.5):
|
||||
self._current_special_angles.pop(0)
|
||||
num_repeats = self.special_angle_repeats
|
||||
else:
|
||||
num_repeats = 1
|
||||
try:
|
||||
start_scan_number = bec.queue.next_scan_number
|
||||
for i in range(num_repeats):
|
||||
self._at_each_angle(angle)
|
||||
error_caught = False
|
||||
except AlarmBase as exc:
|
||||
if exc.alarm_type == "TimeoutError":
|
||||
bec.queue.request_queue_reset()
|
||||
time.sleep(2)
|
||||
error_caught = True
|
||||
else:
|
||||
num_repeats = 1
|
||||
try:
|
||||
@@ -1007,7 +1065,7 @@ class LamNI(LamNIOpticsMixin):
|
||||
scans = builtins.__dict__.get("scans")
|
||||
self._current_special_angles = self.special_angles.copy()
|
||||
|
||||
if subtomo_start == 1 and start_angle is None:
|
||||
if self.tomo_type == 1 and subtomo_start == 1 and start_angle is None:
|
||||
# pylint: disable=undefined-variable
|
||||
self.tomo_id = self.add_sample_database(
|
||||
self.sample_name,
|
||||
|
||||
@@ -309,6 +309,7 @@ class FlomniInitStagesMixin:
|
||||
else:
|
||||
print("Stopping.")
|
||||
return
|
||||
dev.rtx.controller.feedback_disable()
|
||||
# positions for optics out and 50 mm distance to sample
|
||||
umv(dev.ftrackz, 4.73, dev.ftracky, 2.5170, dev.foptx, -14.3, dev.fopty, 3.87)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ bpm4i:
|
||||
softwareTrigger: false
|
||||
mokev:
|
||||
description: Monochromator energy in keV
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.EnergyKev
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.EnergyKev
|
||||
deviceConfig:
|
||||
read_pv: X12SA-OP-MO:ROX2
|
||||
deviceTags:
|
||||
@@ -29,7 +29,7 @@ mokev:
|
||||
softwareTrigger: false
|
||||
mcs:
|
||||
description: Mcs scalar card for transmission readout
|
||||
deviceClass: csaxs_bec.devices.epics.devices.MCScSAXS
|
||||
deviceClass: csaxs_bec.devices.epics.mcs_csaxs.MCScSAXS
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-MCS:'
|
||||
mcs_config:
|
||||
@@ -43,7 +43,7 @@ mcs:
|
||||
softwareTrigger: false
|
||||
eiger9m:
|
||||
description: Eiger9m HPC area detector 9M
|
||||
deviceClass: csaxs_bec.devices.epics.devices.Eiger9McSAXS
|
||||
deviceClass: csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9McSAXS
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-ES-EIGER9M:'
|
||||
deviceTags:
|
||||
@@ -55,7 +55,7 @@ eiger9m:
|
||||
softwareTrigger: false
|
||||
ddg_detectors:
|
||||
description: DelayGenerator for detector triggering
|
||||
deviceClass: csaxs_bec.devices.epics.devices.DelayGeneratorcSAXS
|
||||
deviceClass: csaxs_bec.devices.epics.delay_generator_csaxs.DelayGeneratorcSAXS
|
||||
deviceConfig:
|
||||
prefix: 'delaygen:DG1:'
|
||||
ddg_config:
|
||||
@@ -82,7 +82,7 @@ ddg_detectors:
|
||||
softwareTrigger: false
|
||||
ddg_mcs:
|
||||
description: DelayGenerator for mcs triggering
|
||||
deviceClass: csaxs_bec.devices.epics.devices.DelayGeneratorcSAXS
|
||||
deviceClass: csaxs_bec.devices.epics.delay_generator_csaxs.DelayGeneratorcSAXS
|
||||
deviceConfig:
|
||||
prefix: 'delaygen:DG2:'
|
||||
ddg_config:
|
||||
@@ -111,7 +111,7 @@ ddg_mcs:
|
||||
softwareTrigger: false
|
||||
ddg_fsh:
|
||||
description: DelayGenerator for fast shutter control
|
||||
deviceClass: csaxs_bec.devices.epics.devices.DelayGeneratorcSAXS
|
||||
deviceClass: csaxs_bec.devices.epics.delay_generator_csaxs.DelayGeneratorcSAXS
|
||||
deviceConfig:
|
||||
prefix: 'delaygen:DG3:'
|
||||
ddg_config:
|
||||
@@ -138,7 +138,7 @@ ddg_fsh:
|
||||
softwareTrigger: false
|
||||
falcon:
|
||||
description: Falcon detector x-ray fluoresence
|
||||
deviceClass: csaxs_bec.devices.epics.devices.FalconcSAXS
|
||||
deviceClass: csaxs_bec.devices.epics.falcon_csaxs.FalconcSAXS
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-SITORO:'
|
||||
deviceTags:
|
||||
@@ -150,7 +150,7 @@ falcon:
|
||||
softwareTrigger: false
|
||||
pilatus_2:
|
||||
description: Pilatus2 HPC area detector 300k
|
||||
deviceClass: csaxs_bec.devices.epics.devices.PilatuscSAXS
|
||||
deviceClass: csaxs_bec.devices.epics.pilatus_csaxs.PilatuscSAXS
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-ES-PILATUS300K:'
|
||||
deviceTags:
|
||||
@@ -162,7 +162,7 @@ pilatus_2:
|
||||
softwareTrigger: false
|
||||
samx:
|
||||
description: SGalil motor stage
|
||||
deviceClass: csaxs_bec.devices.galil.SGalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.SGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: "E"
|
||||
host: '129.129.122.26'
|
||||
@@ -180,7 +180,7 @@ samx:
|
||||
softwareTrigger: false
|
||||
samy:
|
||||
description: SGalil motor stage
|
||||
deviceClass: csaxs_bec.devices.galil.SGalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.SGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: "C"
|
||||
host: '129.129.122.26'
|
||||
@@ -198,7 +198,7 @@ samy:
|
||||
softwareTrigger: false
|
||||
micfoc:
|
||||
description: Focusing motor of Microscope stage
|
||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
||||
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES06
|
||||
motor_resolution: 0.00125
|
||||
@@ -216,7 +216,7 @@ micfoc:
|
||||
softwareTrigger: false
|
||||
owis_samx:
|
||||
description: Owis motor stage samx
|
||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
||||
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES01
|
||||
motor_resolution: 0.00125
|
||||
@@ -234,7 +234,7 @@ owis_samx:
|
||||
softwareTrigger: false
|
||||
owis_samy:
|
||||
description: Owis motor stage samx
|
||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
||||
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES02
|
||||
motor_resolution: 0.00125
|
||||
@@ -252,7 +252,7 @@ owis_samy:
|
||||
softwareTrigger: false
|
||||
rotx:
|
||||
description: Rotation stage rotx
|
||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
||||
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES05
|
||||
motor_resolution: 0.0025
|
||||
@@ -273,7 +273,7 @@ rotx:
|
||||
softwareTrigger: false
|
||||
roty:
|
||||
description: Rotation stage rotx
|
||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorEx
|
||||
deviceClass: ophyd_devices.devices.EpicsMotorEx
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES2-ES04
|
||||
motor_resolution: 0.0025
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
############################################################
|
||||
leyex:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: G
|
||||
host: mpc2680.psi.ch
|
||||
@@ -22,7 +22,7 @@ leyex:
|
||||
in: 14.117
|
||||
leyey:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: H
|
||||
host: mpc2680.psi.ch
|
||||
@@ -42,7 +42,7 @@ leyey:
|
||||
out: 0.5
|
||||
loptx:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: mpc2680.psi.ch
|
||||
@@ -62,7 +62,7 @@ loptx:
|
||||
out: -0.699
|
||||
lopty:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: mpc2680.psi.ch
|
||||
@@ -82,7 +82,7 @@ lopty:
|
||||
out: 3.53
|
||||
loptz:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: mpc2680.psi.ch
|
||||
@@ -99,7 +99,7 @@ loptz:
|
||||
readoutPriority: baseline
|
||||
lsamrot:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2680.psi.ch
|
||||
@@ -116,7 +116,7 @@ lsamrot:
|
||||
readoutPriority: baseline
|
||||
lsamx:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2680.psi.ch
|
||||
@@ -135,7 +135,7 @@ lsamx:
|
||||
center: 8.768
|
||||
lsamy:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.galil_ophyd.GalilMotor
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2680.psi.ch
|
||||
@@ -162,7 +162,7 @@ lsamy:
|
||||
############################################################
|
||||
|
||||
rtx:
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_lamni_ophyd.RtLamniMotor
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
device_access: true
|
||||
@@ -179,7 +179,7 @@ rtx:
|
||||
enabled: true
|
||||
readOnly: False
|
||||
rty:
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_lamni_ophyd.RtLamniMotor
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
device_access: true
|
||||
@@ -293,7 +293,7 @@ losaz:
|
||||
|
||||
eiger1p5m:
|
||||
description: Eiger 1.5M in vacuum detector, in-house developed, PSI
|
||||
deviceClass: csaxs_bec.devices.eiger1p5m_csaxs.eiger1p5m.Eiger1p5MDetector
|
||||
deviceClass: csaxs_bec.devices.omny.eiger1p5m.Eiger1p5MDetector
|
||||
deviceConfig:
|
||||
device_access: true
|
||||
deviceTags:
|
||||
@@ -504,7 +504,7 @@ sls_filling_pattern:
|
||||
readOnly: True
|
||||
sls_info:
|
||||
readoutPriority: on_request
|
||||
deviceClass: ophyd_devices.sls_devices.sls_devices.SLSInfo
|
||||
deviceClass: ophyd_devices.devices.sls_devices.SLSInfo
|
||||
deviceConfig:
|
||||
deviceTags:
|
||||
- SLS status
|
||||
@@ -537,7 +537,7 @@ sls_machine_status:
|
||||
readOnly: True
|
||||
sls_operator:
|
||||
readoutPriority: on_request
|
||||
deviceClass: ophyd_devices.sls_devices.sls_devices.SLSOperatorMessages
|
||||
deviceClass: ophyd_devices.devices.sls_devices.SLSOperatorMessages
|
||||
deviceConfig:
|
||||
auto_monitor: true
|
||||
read_pv: ARIDI-BPM:OFB-MODE
|
||||
@@ -802,7 +802,7 @@ bm5try:
|
||||
softwareTrigger: false
|
||||
bpm1:
|
||||
description: 'XBPM 1: Somewhere around mono (VME)'
|
||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
||||
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-BPM2:'
|
||||
deviceTags:
|
||||
@@ -824,7 +824,7 @@ bpm1i:
|
||||
softwareTrigger: false
|
||||
bpm2:
|
||||
description: 'XBPM 2: Somewhere around mono (VME)'
|
||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
||||
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-BPM2:'
|
||||
deviceTags:
|
||||
@@ -1187,7 +1187,7 @@ dtpush:
|
||||
softwareTrigger: false
|
||||
dtth:
|
||||
description: Detector tower tilt rotation
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmDetectorRotation
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.PmDetectorRotation
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES1-DETT:ROX1
|
||||
deviceTags:
|
||||
@@ -1462,7 +1462,7 @@ fttrz:
|
||||
softwareTrigger: false
|
||||
idgap:
|
||||
description: Undulator gap size [mm]
|
||||
deviceClass: csaxs_bec.devices.epics.devices.InsertionDevice
|
||||
deviceClass: csaxs_bec.devices.epics.InsertionDevice.InsertionDevice
|
||||
deviceConfig:
|
||||
prefix: X12SA-ID
|
||||
deviceTags:
|
||||
@@ -1561,7 +1561,7 @@ mitry3:
|
||||
softwareTrigger: false
|
||||
mobd:
|
||||
description: Monochromator bender virtual motor
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmMonoBender
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.PmMonoBender
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-MO:'
|
||||
deviceTags:
|
||||
@@ -1616,7 +1616,7 @@ mobddi:
|
||||
softwareTrigger: false
|
||||
mokev:
|
||||
description: Monochromator energy in keV
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.EnergyKev
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.EnergyKev
|
||||
deviceConfig:
|
||||
read_pv: X12SA-OP-MO:ROX2
|
||||
deviceTags:
|
||||
@@ -1671,7 +1671,7 @@ moroll2:
|
||||
softwareTrigger: false
|
||||
moth1:
|
||||
description: Monochromator Theta 1
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta1
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta1
|
||||
deviceConfig:
|
||||
read_pv: X12SA-OP-MO:ROX1
|
||||
deviceTags:
|
||||
@@ -1693,7 +1693,7 @@ moth1e:
|
||||
softwareTrigger: false
|
||||
moth2:
|
||||
description: Monochromator Theta 2
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta2
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta2
|
||||
deviceConfig:
|
||||
read_pv: X12SA-OP-MO:ROX2
|
||||
deviceTags:
|
||||
@@ -1812,17 +1812,17 @@ sec:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl0h:
|
||||
description: FrontEnd slit virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-FE-SH1:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl0h:
|
||||
# description: FrontEnd slit virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitH
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-FE-SH1:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
sl0trxi:
|
||||
description: FrontEnd slit inner blade movement
|
||||
deviceClass: ophyd.EpicsMotor
|
||||
@@ -1845,17 +1845,17 @@ sl0trxo:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl1h:
|
||||
description: OpticsHutch slit virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SH1:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl1h:
|
||||
# description: OpticsHutch slit virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitH
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SH1:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
sl1trxi:
|
||||
description: OpticsHutch slit inner blade movement
|
||||
deviceClass: ophyd.EpicsMotor
|
||||
@@ -1900,28 +1900,28 @@ sl1tryt:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl1v:
|
||||
description: OpticsHutch slit virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SV1:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl2h:
|
||||
description: OpticsHutch slit 2 virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SH2:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl1v:
|
||||
# description: OpticsHutch slit virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitV
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SV1:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# sl2h:
|
||||
# description: OpticsHutch slit 2 virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitH
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SH2:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
sl2trxi:
|
||||
description: OpticsHutch slit 2 inner blade movement
|
||||
deviceClass: ophyd.EpicsMotor
|
||||
@@ -1966,72 +1966,72 @@ sl2tryt:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl2v:
|
||||
description: OpticsHutch slit 2 virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SV2:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
strox:
|
||||
description: Girder virtual pitch
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorPITCH
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
stroy:
|
||||
description: Girder virtual yaw
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorYAW
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
stroz:
|
||||
description: Girder virtual roll
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorROLL
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sttrx:
|
||||
description: Girder X translation
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorX1
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sttry:
|
||||
description: Girder Y translation
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorY1
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl2v:
|
||||
# description: OpticsHutch slit 2 virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitV
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SV2:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# strox:
|
||||
# description: Girder virtual pitch
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorPITCH
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# stroy:
|
||||
# description: Girder virtual yaw
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorYAW
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# stroz:
|
||||
# description: Girder virtual roll
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorROLL
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# sttrx:
|
||||
# description: Girder X translation
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorX1
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# sttry:
|
||||
# description: Girder Y translation
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorY1
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
transd:
|
||||
description: Transmission diode
|
||||
deviceClass: ophyd.EpicsSignalRO
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
############################################################
|
||||
#################### flOMNI Galil motors ###################
|
||||
############################################################
|
||||
|
||||
feyex:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
description: Xray eye X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: mpc2844.psi.ch
|
||||
@@ -17,8 +21,8 @@ feyex:
|
||||
in: -16.267
|
||||
out: -1
|
||||
feyey:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
description: Xray eye Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: mpc2844.psi.ch
|
||||
@@ -34,8 +38,8 @@ feyey:
|
||||
userParameter:
|
||||
in: -10.467
|
||||
fheater:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
description: Heater Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
@@ -48,17 +52,9 @@ fheater:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
flomni_samples:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.epics.devices.flomni_sample_storage.FlomniSampleStorage
|
||||
deviceConfig: {}
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
foptx:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
description: Optics X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
@@ -74,8 +70,8 @@ foptx:
|
||||
userParameter:
|
||||
in: -13.761
|
||||
fopty:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
description: Optics Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: mpc2844.psi.ch
|
||||
@@ -92,8 +88,8 @@ fopty:
|
||||
in: 0.552
|
||||
out: 0.752
|
||||
foptz:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
description: Optics Z
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
@@ -108,8 +104,166 @@ foptz:
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 23
|
||||
fsamroy:
|
||||
description: Sample rotation
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fupr_ophyd.FuprGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -5
|
||||
- 365
|
||||
port: 8084
|
||||
sign: -1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
fsamx:
|
||||
description: Sample coarse X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -162
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: -1.1
|
||||
fsamy:
|
||||
description: Sample coarse Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 2
|
||||
- 3.1
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 2.75
|
||||
ftracky:
|
||||
description: Laser Tracker coarse Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: H
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 2.2
|
||||
- 2.8
|
||||
port: 8082
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftrackz:
|
||||
description: Laser Tracker coarse Z
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: G
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 4.5
|
||||
- 5.5
|
||||
port: 8082
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftransx:
|
||||
description: Sample transer X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 50
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftransy:
|
||||
description: Sample transer Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -100
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftransz:
|
||||
description: Sample transer Z
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 145
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftray:
|
||||
description: Sample transfer tray
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 0
|
||||
port: 8081
|
||||
sign: -1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
|
||||
|
||||
############################################################
|
||||
#################### flOMNI Sample Names ###################
|
||||
############################################################
|
||||
|
||||
flomni_samples:
|
||||
description: Sample names and storage
|
||||
deviceClass: csaxs_bec.devices.omny.flomni_sample_storage.FlomniSampleStorage
|
||||
deviceConfig: {}
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
|
||||
############################################################
|
||||
#################### flOMNI Smaract motors #################
|
||||
############################################################
|
||||
|
||||
fosax:
|
||||
description: phase plate angle
|
||||
description: OSA X
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
@@ -127,7 +281,7 @@ fosax:
|
||||
in: 9.124
|
||||
out: 5.3
|
||||
fosay:
|
||||
description: phase plate angle
|
||||
description: OSA Y
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
@@ -144,7 +298,7 @@ fosay:
|
||||
userParameter:
|
||||
in: 0.367
|
||||
fosaz:
|
||||
description: phase plate angle
|
||||
description: OSA Z
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
@@ -161,148 +315,14 @@ fosaz:
|
||||
userParameter:
|
||||
in: 8.5
|
||||
out: 6
|
||||
fsamroy:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fupr_ophyd.FuprGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -5
|
||||
- 365
|
||||
port: 8084
|
||||
sign: -1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
fsamx:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -162
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: -1.1
|
||||
fsamy:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 2
|
||||
- 3.1
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 2.75
|
||||
ftracky:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: H
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 2.2
|
||||
- 2.8
|
||||
port: 8082
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftrackz:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: G
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 4.5
|
||||
- 5.5
|
||||
port: 8082
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftransx:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 50
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftransy:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -100
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftransz:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 145
|
||||
port: 8081
|
||||
sign: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
ftray:
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 0
|
||||
port: 8081
|
||||
sign: -1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
|
||||
############################################################
|
||||
#################### flOMNI RT motors ######################
|
||||
############################################################
|
||||
|
||||
rtx:
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
@@ -318,7 +338,7 @@ rtx:
|
||||
rt_pid_voltage: -0.06219
|
||||
rty:
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
@@ -332,7 +352,7 @@ rty:
|
||||
tomo_additional_offsety: 0
|
||||
rtz:
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
|
||||
@@ -1,340 +0,0 @@
|
||||
fheater:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -15
|
||||
- 0
|
||||
port: 8082
|
||||
sign: -1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
feyex:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -30
|
||||
- -1
|
||||
port: 8082
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: -16.267
|
||||
out: -1
|
||||
enabled: true
|
||||
readOnly: false
|
||||
feyey:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -1
|
||||
- -10
|
||||
port: 8082
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: -10.467
|
||||
enabled: true
|
||||
readOnly: false
|
||||
foptx:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -17
|
||||
- -12
|
||||
port: 8082
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: -13.761
|
||||
enabled: true
|
||||
readOnly: false
|
||||
fopty:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 4
|
||||
port: 8082
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: 0.552
|
||||
out: 0.752
|
||||
enabled: true
|
||||
readOnly: false
|
||||
foptz:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 27
|
||||
port: 8082
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: 23
|
||||
enabled: true
|
||||
readOnly: false
|
||||
fosax:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 10.2
|
||||
- 10.6
|
||||
port: 3334
|
||||
sign: -1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: 9.124
|
||||
out: 5.3
|
||||
enabled: true
|
||||
readOnly: false
|
||||
fosay:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -3.1
|
||||
- -2.9
|
||||
port: 3334
|
||||
sign: -1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: 0.367
|
||||
enabled: true
|
||||
readOnly: false
|
||||
fosaz:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -6
|
||||
- -4
|
||||
port: 3334
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
userParameter:
|
||||
in: 8.5
|
||||
out: 6
|
||||
enabled: true
|
||||
readOnly: false
|
||||
fsamroy:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fupr_ophyd.FuprGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -5
|
||||
- 365
|
||||
port: 8084
|
||||
sign: -1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
fsamx:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -162
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
userParameter:
|
||||
in: -1.1
|
||||
fsamy:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 2
|
||||
- 3.1
|
||||
port: 8081
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
userParameter:
|
||||
in: 2.75
|
||||
ftracky:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: H
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 2.2
|
||||
- 2.8
|
||||
port: 8082
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
ftrackz:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: G
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 4.5
|
||||
- 5.5
|
||||
port: 8082
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
ftransx:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 50
|
||||
port: 8081
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
ftransy:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -100
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
ftransz:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 145
|
||||
port: 8081
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
ftray:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: mpc2844.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 0
|
||||
port: 8081
|
||||
sign: -1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
|
||||
flomni_samples:
|
||||
readoutPriority: baseline
|
||||
description: phase plate angle
|
||||
deviceClass: csaxs_bec.devices.epics.devices.FlomniSampleStorage
|
||||
deviceConfig:
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
|
||||
rtx:
|
||||
readoutPriority: on_request
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2844.psi.ch
|
||||
port: 2222
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
rty:
|
||||
readoutPriority: on_request
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2844.psi.ch
|
||||
port: 2222
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
rtz:
|
||||
readoutPriority: on_request
|
||||
description: flomni rt
|
||||
deviceClass: csaxs_bec.devices.rt_lamni.rt_flomni_ophyd.RtFlomniMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2844.psi.ch
|
||||
port: 2222
|
||||
sign: 1
|
||||
onFailure: buffer
|
||||
enabled: true
|
||||
readOnly: false
|
||||
261
csaxs_bec/device_configs/lamni_config.yaml
Normal file
261
csaxs_bec/device_configs/lamni_config.yaml
Normal file
@@ -0,0 +1,261 @@
|
||||
############################################################
|
||||
#################### LamNI Galil motors ####################
|
||||
############################################################
|
||||
|
||||
leyex:
|
||||
description: Xray eye X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: G
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: -1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 14.117
|
||||
leyey:
|
||||
description: Xray eye Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: H
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: -1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 48.069
|
||||
out: 0.5
|
||||
loptx:
|
||||
description: Optics X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: -0.244
|
||||
out: -0.699
|
||||
lopty:
|
||||
description: Optics Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: 3.724
|
||||
out: 3.53
|
||||
loptz:
|
||||
description: Optics Z
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: -1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
lsamrot:
|
||||
description: Sample rotation
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
lsamx:
|
||||
description: Sample coarse X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: -1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
center: 8.768
|
||||
lsamy:
|
||||
description: Sample coarse Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8081
|
||||
sign: 1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
center: 10.041
|
||||
|
||||
|
||||
############################################################
|
||||
################ LamNI Smaract motors ######################
|
||||
############################################################
|
||||
|
||||
losax:
|
||||
description: OSA X
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8085
|
||||
sign: -1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: -1.442
|
||||
losay:
|
||||
description: OSA Y
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8085
|
||||
sign: -1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: -0.171
|
||||
out: 3.8
|
||||
losaz:
|
||||
description: OSA Z
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: mpc2680.psi.ch
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 8085
|
||||
sign: 1
|
||||
deviceTags:
|
||||
- lamni
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
userParameter:
|
||||
in: -1
|
||||
out: -3
|
||||
|
||||
############################################################
|
||||
#################### flOMNI RT motors ######################
|
||||
############################################################
|
||||
|
||||
rtx:
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
device_access: true
|
||||
host: mpc2680.psi.ch
|
||||
labels: rtx
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 3333
|
||||
sign: 1
|
||||
deviceTags:
|
||||
- lamni
|
||||
readoutPriority: baseline
|
||||
enabled: true
|
||||
readOnly: False
|
||||
rty:
|
||||
deviceClass: csaxs_bec.devices.omny.rt.rt_lamni_ophyd.RtLamniMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
device_access: true
|
||||
host: mpc2680.psi.ch
|
||||
labels: rty
|
||||
limits:
|
||||
- 0
|
||||
- 0
|
||||
port: 3333
|
||||
sign: 1
|
||||
deviceTags:
|
||||
- lamni
|
||||
readoutPriority: baseline
|
||||
enabled: true
|
||||
readOnly: False
|
||||
|
||||
|
||||
8
csaxs_bec/device_configs/omny_config.yaml
Normal file
8
csaxs_bec/device_configs/omny_config.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
omny_samples:
|
||||
description: OMNYSampleStorage
|
||||
deviceClass: csaxs_bec.devices.omny.omny_sample_storage.OMNYSampleStorage
|
||||
deviceConfig: {}
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
@@ -220,7 +220,7 @@ bm5try:
|
||||
softwareTrigger: false
|
||||
bpm1:
|
||||
description: 'XBPM 1: Somewhere around mono (VME)'
|
||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
||||
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-BPM2:'
|
||||
deviceTags:
|
||||
@@ -242,7 +242,7 @@ bpm1i:
|
||||
softwareTrigger: false
|
||||
bpm2:
|
||||
description: 'XBPM 2: Somewhere around mono (VME)'
|
||||
deviceClass: csaxs_bec.devices.epics.devices.XbpmBase.XbpmCsaxsOp
|
||||
deviceClass: csaxs_bec.devices.epics.XbpmBase.XbpmCsaxsOp
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-BPM2:'
|
||||
deviceTags:
|
||||
@@ -605,7 +605,7 @@ dtpush:
|
||||
softwareTrigger: false
|
||||
dtth:
|
||||
description: Detector tower tilt rotation
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmDetectorRotation
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.PmDetectorRotation
|
||||
deviceConfig:
|
||||
prefix: X12SA-ES1-DETT:ROX1
|
||||
deviceTags:
|
||||
@@ -880,7 +880,7 @@ fttrz:
|
||||
softwareTrigger: false
|
||||
idgap:
|
||||
description: Undulator gap size [mm]
|
||||
deviceClass: csaxs_bec.devices.epics.devices.InsertionDevice.InsertionDevice
|
||||
deviceClass: csaxs_bec.devices.epics.InsertionDevice.InsertionDevice
|
||||
deviceConfig:
|
||||
prefix: X12SA-ID
|
||||
deviceTags:
|
||||
@@ -979,7 +979,7 @@ mitry3:
|
||||
softwareTrigger: false
|
||||
mobd:
|
||||
description: Monochromator bender virtual motor
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.PmMonoBender
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.PmMonoBender
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-MO:'
|
||||
deviceTags:
|
||||
@@ -1034,7 +1034,7 @@ mobddi:
|
||||
softwareTrigger: false
|
||||
mokev:
|
||||
description: Monochromator energy in keV
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.EnergyKev
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.EnergyKev
|
||||
deviceConfig:
|
||||
read_pv: X12SA-OP-MO:ROX2
|
||||
deviceTags:
|
||||
@@ -1089,7 +1089,7 @@ moroll2:
|
||||
softwareTrigger: false
|
||||
moth1:
|
||||
description: Monochromator Theta 1
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta1
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta1
|
||||
deviceConfig:
|
||||
read_pv: X12SA-OP-MO:ROX1
|
||||
deviceTags:
|
||||
@@ -1111,7 +1111,7 @@ moth1e:
|
||||
softwareTrigger: false
|
||||
moth2:
|
||||
description: Monochromator Theta 2
|
||||
deviceClass: csaxs_bec.devices.epics.devices.specMotors.MonoTheta2
|
||||
deviceClass: csaxs_bec.devices.epics.specMotors.MonoTheta2
|
||||
deviceConfig:
|
||||
read_pv: X12SA-OP-MO:ROX2
|
||||
deviceTags:
|
||||
@@ -1230,17 +1230,17 @@ sec:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl0h:
|
||||
description: FrontEnd slit virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-FE-SH1:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl0h:
|
||||
# description: FrontEnd slit virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitH
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-FE-SH1:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
sl0trxi:
|
||||
description: FrontEnd slit inner blade movement
|
||||
deviceClass: ophyd.EpicsMotor
|
||||
@@ -1263,17 +1263,17 @@ sl0trxo:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl1h:
|
||||
description: OpticsHutch slit virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SH1:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl1h:
|
||||
# description: OpticsHutch slit virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitH
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SH1:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
sl1trxi:
|
||||
description: OpticsHutch slit inner blade movement
|
||||
deviceClass: ophyd.EpicsMotor
|
||||
@@ -1318,28 +1318,28 @@ sl1tryt:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl1v:
|
||||
description: OpticsHutch slit virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SV1:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl2h:
|
||||
description: OpticsHutch slit 2 virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitH
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SH2:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl1v:
|
||||
# description: OpticsHutch slit virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitV
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SV1:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# sl2h:
|
||||
# description: OpticsHutch slit 2 virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitH
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SH2:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
sl2trxi:
|
||||
description: OpticsHutch slit 2 inner blade movement
|
||||
deviceClass: ophyd.EpicsMotor
|
||||
@@ -1384,72 +1384,72 @@ sl2tryt:
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sl2v:
|
||||
description: OpticsHutch slit 2 virtual movement
|
||||
deviceClass: ophyd_devices.epics.devices.SlitV
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-OP-SV2:'
|
||||
deviceTags:
|
||||
- epicsDevice
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
strox:
|
||||
description: Girder virtual pitch
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorPITCH
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
stroy:
|
||||
description: Girder virtual yaw
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorYAW
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
stroz:
|
||||
description: Girder virtual roll
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorROLL
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sttrx:
|
||||
description: Girder X translation
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorX1
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
sttry:
|
||||
description: Girder Y translation
|
||||
deviceClass: ophyd_devices.epics.devices.GirderMotorY1
|
||||
deviceConfig:
|
||||
prefix: X12SA-HG
|
||||
deviceTags:
|
||||
- beamlineMotor
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readoutPriority: baseline
|
||||
softwareTrigger: false
|
||||
# sl2v:
|
||||
# description: OpticsHutch slit 2 virtual movement
|
||||
# deviceClass: ophyd_devices.devices.SlitV
|
||||
# deviceConfig:
|
||||
# prefix: 'X12SA-OP-SV2:'
|
||||
# deviceTags:
|
||||
# - epicsDevice
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# strox:
|
||||
# description: Girder virtual pitch
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorPITCH
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# stroy:
|
||||
# description: Girder virtual yaw
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorYAW
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# stroz:
|
||||
# description: Girder virtual roll
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorROLL
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# sttrx:
|
||||
# description: Girder X translation
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorX1
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
# sttry:
|
||||
# description: Girder Y translation
|
||||
# deviceClass: ophyd_devices.devices.GirderMotorY1
|
||||
# deviceConfig:
|
||||
# prefix: X12SA-HG
|
||||
# deviceTags:
|
||||
# - beamlineMotor
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readoutPriority: baseline
|
||||
# softwareTrigger: false
|
||||
transd:
|
||||
description: Transmission diode
|
||||
deviceClass: ophyd.EpicsSignalRO
|
||||
|
||||
37
csaxs_bec/devices/device_list.md
Normal file
37
csaxs_bec/devices/device_list.md
Normal file
@@ -0,0 +1,37 @@
|
||||
// This file was autogenerated. Do not edit it manually.
|
||||
## Device List
|
||||
### csaxs_bec
|
||||
| Device | Documentation | Module |
|
||||
| :----- | :------------- | :------ |
|
||||
| InsertionDevice | Python wrapper for the CSAXS insertion device control<br><br> This wrapper provides a positioner interface for the ID control.<br> is completely custom XBPM with templates directly in the<br> VME repo. Thus it needs a custom ophyd template as well...<br><br> WARN: The x and y are not updated by the IOC<br> | [csaxs_bec.devices.epics.InsertionDevice](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/InsertionDevice.py) |
|
||||
| XbpmBase | Python wrapper for X-ray Beam Position Monitors<br><br> XBPM's consist of a metal-coated diamond window that ejects<br> photoelectrons from the incoming X-ray beam. These electons<br> are collected and their current is measured. Effectively<br> they act as four quadrant photodiodes and are used as BPMs<br> at the undulator beamlines of SLS.<br><br> Note: EPICS provided signals are read only, but the user can<br> change the beam position offset.<br> | [csaxs_bec.devices.epics.XbpmBase](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/XbpmBase.py) |
|
||||
| XbpmCsaxsOp | Python wrapper for custom XBPMs in the cSAXS optics hutch<br><br> This is completely custom XBPM with templates directly in the<br> VME repo. Thus it needs a custom ophyd template as well...<br><br> WARN: The x and y are not updated by the IOC<br> | [csaxs_bec.devices.epics.XbpmBase](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/XbpmBase.py) |
|
||||
| XbpmSim | Python wrapper for simulated X-ray Beam Position Monitors<br><br> XBPM's consist of a metal-coated diamond window that ejects<br> photoelectrons from the incoming X-ray beam. These electons<br> are collected and their current is measured. Effectively<br> they act as four quadrant photodiodes and are used as BPMs<br> at the undulator beamlines of SLS.<br><br> Note: EPICS provided signals are read only, but the user can<br> change the beam position offset.<br><br> This simulation device extends the basic proxy with a script that<br> fills signals with quasi-randomized values.<br> | [csaxs_bec.devices.epics.XbpmBase](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/XbpmBase.py) |
|
||||
| DelayGeneratorcSAXS | <br> DG645 delay generator at cSAXS (multiple can be in use depending on the setup)<br><br> Default values for setting up DDG.<br> Note: checks of set calues are not (only partially) included, check manual for details on possible settings.<br> https://www.thinksrs.com/downloads/pdfs/manuals/DG645m.pdf<br><br> - delay_burst : (float >=0) Delay between trigger and first pulse in burst mode<br> - delta_width : (float >= 0) Add width to fast shutter signal to make sure its open during acquisition<br> - additional_triggers : (int) add additional triggers to burst mode (mcs card needs +1 triggers per line)<br> - polarity : (list of 0/1) polarity for different channels<br> - amplitude : (float) amplitude voltage of TTLs<br> - offset : (float) offset for ampltitude<br> - thres_trig_level : (float) threshold of trigger amplitude<br><br> Custom signals for logic in different DDGs during scans (for custom_prepare.prepare_ddg):<br><br> - set_high_on_exposure : (bool): if True, then TTL signal should go high during the full acquisition time of a scan.<br> # TODO trigger_width and fixed_ttl could be combined into single list.<br> - fixed_ttl_width : (list of either 1 or 0), one for each channel.<br> - trigger_width : (float) if fixed_ttl_width is True, then the width of the TTL pulse is set to this value.<br> - set_trigger_source : (TriggerSource) specifies the default trigger source for the DDG.<br> - premove_trigger : (bool) if True, then a trigger should be executed before the scan starts (to be implemented in on_pre_scan).<br> - set_high_on_stage : (bool) if True, then TTL signal should go high already on stage.<br> | [csaxs_bec.devices.epics.delay_generator_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/delay_generator_csaxs.py) |
|
||||
| Eiger9McSAXS | <br> Eiger9M detector for CSAXS<br><br> Parent class: PSIDetectorBase<br><br> class attributes:<br> custom_prepare_cls (FalconSetup) : Custom detector setup class for cSAXS,<br> inherits from CustomDetectorMixin<br> PSIDetectorBase.set_min_readout (float) : Minimum readout time for the detector<br> Various EpicsPVs for controlling the detector<br> | [csaxs_bec.devices.epics.eiger9m_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/eiger9m_csaxs.py) |
|
||||
| SLSDetectorCam | SLS Detector Camera - Pilatus<br><br> Base class to map EPICS PVs to ophyd signals.<br> | [csaxs_bec.devices.epics.pilatus_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/pilatus_csaxs.py) |
|
||||
| EpicsDXPFalcon | <br> DXP parameters for Falcon detector<br><br> Base class to map EPICS PVs from DXP parameters to ophyd signals.<br> | [csaxs_bec.devices.epics.falcon_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/falcon_csaxs.py) |
|
||||
| FalconHDF5Plugins | <br> HDF5 parameters for Falcon detector<br><br> Base class to map EPICS PVs from HDF5 Plugin to ophyd signals.<br> | [csaxs_bec.devices.epics.falcon_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/falcon_csaxs.py) |
|
||||
| FalconcSAXS | <br> Falcon Sitoro detector for CSAXS<br><br> Parent class: PSIDetectorBase<br><br> class attributes:<br> custom_prepare_cls (FalconSetup) : Custom detector setup class for cSAXS,<br> inherits from CustomDetectorMixin<br> PSIDetectorBase.set_min_readout (float) : Minimum readout time for the detector<br> dxp (EpicsDXPFalcon) : DXP parameters for Falcon detector<br> mca (EpicsMCARecord) : MCA parameters for Falcon detector<br> hdf5 (FalconHDF5Plugins) : HDF5 parameters for Falcon detector<br> MIN_READOUT (float) : Minimum readout time for the detector<br> | [csaxs_bec.devices.epics.falcon_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/falcon_csaxs.py) |
|
||||
| MCScSAXS | MCS card for cSAXS for implementation at cSAXS beamline | [csaxs_bec.devices.epics.mcs_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/mcs_csaxs.py) |
|
||||
| SIS38XX | SIS38XX card for access to EPICs PVs at cSAXS beamline | [csaxs_bec.devices.epics.mcs_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/mcs_csaxs.py) |
|
||||
| PilatuscSAXS | Pilatus_2 300k detector for CSAXS<br><br> Parent class: PSIDetectorBase<br><br> class attributes:<br> custom_prepare_cls (Eiger9MSetup) : Custom detector setup class for cSAXS,<br> inherits from CustomDetectorMixin<br> cam (SLSDetectorCam) : Detector camera<br> MIN_READOUT (float) : Minimum readout time for the detector<br><br> | [csaxs_bec.devices.epics.pilatus_csaxs](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/pilatus_csaxs.py) |
|
||||
| Bpm4i | | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| GirderMotorPITCH | Girder YAW pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| GirderMotorROLL | Girder ROLL pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| GirderMotorX1 | Girder X translation pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| GirderMotorY1 | Girder Y translation pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| GirderMotorYAW | Girder YAW pseudo motor | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| PmDetectorRotation | Detector rotation pseudo motor<br><br> Small wrapper to convert detector pusher position to rotation angle.<br> | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| PmMonoBender | Monochromator bender<br><br> Small wrapper to combine the four monochromator bender motors.<br> | [csaxs_bec.devices.epics.specMotors](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/epics/specMotors.py) |
|
||||
| Xeye | | [csaxs_bec.devices.sls_devices.cSAXS.xeye](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/sls_devices/cSAXS/xeye.py) |
|
||||
| SmaractMotor | | [csaxs_bec.devices.smaract.smaract_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/smaract/smaract_ophyd.py) |
|
||||
| Eiger1p5MDetector | | [csaxs_bec.devices.omny.eiger1p5m](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/eiger1p5m.py) |
|
||||
| FlomniSampleStorage | | [csaxs_bec.devices.omny.flomni_sample_storage](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/flomni_sample_storage.py) |
|
||||
| OMNYSampleStorage | | [csaxs_bec.devices.omny.omny_sample_storage](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/omny_sample_storage.py) |
|
||||
| FlomniGalilMotor | | [csaxs_bec.devices.omny.galil.fgalil_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/fgalil_ophyd.py) |
|
||||
| FuprGalilMotor | | [csaxs_bec.devices.omny.galil.fupr_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/fupr_ophyd.py) |
|
||||
| LamniGalilMotor | | [csaxs_bec.devices.omny.galil.lgalil_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/lgalil_ophyd.py) |
|
||||
| SGalilMotor | "SGalil Motors at cSAXS have a<br> DC motor (y axis - vertical) - implemented as C<br> and a step motor (x-axis horizontal) - implemented as E<br> that require different communication for control<br> | [csaxs_bec.devices.omny.galil.sgalil_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/galil/sgalil_ophyd.py) |
|
||||
| RtFlomniMotor | | [csaxs_bec.devices.omny.rt.rt_flomni_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/rt/rt_flomni_ophyd.py) |
|
||||
| RtLamniMotor | | [csaxs_bec.devices.omny.rt.rt_lamni_ophyd](https://gitlab.psi.ch/bec/csaxs_bec/-/blob/main/csaxs_bec/devices/omny/rt/rt_lamni_ophyd.py) |
|
||||
@@ -1,8 +1 @@
|
||||
# Standard ophyd classes
|
||||
from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO
|
||||
from ophyd.quadem import QuadEM
|
||||
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
||||
|
||||
from .devices.delay_generator_csaxs import DelayGeneratorcSAXS
|
||||
from .devices.flomni_sample_storage import FlomniSampleStorage
|
||||
from .devices.InsertionDevice import InsertionDevice
|
||||
|
||||
32
csaxs_bec/devices/epics/cSaxsVirtualMotors.py
Normal file
32
csaxs_bec/devices/epics/cSaxsVirtualMotors.py
Normal file
@@ -0,0 +1,32 @@
|
||||
""" TODO This class seems to be missing various imports and appears to have not been tested in motion yet."""
|
||||
|
||||
# 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
|
||||
# )
|
||||
@@ -1,6 +1,6 @@
|
||||
from bec_lib import bec_logger
|
||||
from ophyd import Component
|
||||
from ophyd_devices.epics.devices.psi_delay_generator_base import (
|
||||
from ophyd_devices.interfaces.base_classes.psi_delay_generator_base import (
|
||||
DDGCustomMixin,
|
||||
PSIDelayGeneratorBase,
|
||||
TriggerSource,
|
||||
@@ -1,14 +0,0 @@
|
||||
# Standard ophyd classes
|
||||
from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO
|
||||
from ophyd.quadem import QuadEM
|
||||
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
||||
|
||||
from .delay_generator_csaxs import DelayGeneratorcSAXS
|
||||
from .eiger9m_csaxs import Eiger9McSAXS
|
||||
|
||||
# cSAXS
|
||||
from .falcon_csaxs import FalconcSAXS
|
||||
from .flomni_sample_storage import FlomniSampleStorage
|
||||
from .InsertionDevice import InsertionDevice
|
||||
from .mcs_csaxs import MCScSAXS
|
||||
from .pilatus_csaxs import PilatuscSAXS
|
||||
@@ -1,32 +0,0 @@
|
||||
""" TODO This class seems to be missing various imports and appears to have not been tested in motion yet."""
|
||||
|
||||
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
|
||||
)
|
||||
@@ -5,12 +5,15 @@ import time
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import messages, threadlocked
|
||||
from bec_lib import messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import ADComponent as ADCpt
|
||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
|
||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
||||
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||
CustomDetectorMixin,
|
||||
PSIDetectorBase,
|
||||
)
|
||||
from std_daq_client import StdDaqClient
|
||||
|
||||
logger = bec_logger.logger
|
||||
@@ -305,33 +308,35 @@ class Eiger9MSetup(CustomDetectorMixin):
|
||||
)
|
||||
pipe.execute()
|
||||
|
||||
@threadlocked
|
||||
def finished(self):
|
||||
"""Check if acquisition is finished."""
|
||||
signal_conditions = [
|
||||
(
|
||||
lambda: self.parent.cam.acquire.read()[self.parent.cam.acquire.name]["value"],
|
||||
DetectorState.IDLE,
|
||||
),
|
||||
(lambda: self.std_client.get_status()["acquisition"]["state"], "FINISHED"),
|
||||
(
|
||||
lambda: self.std_client.get_status()["acquisition"]["stats"]["n_write_completed"],
|
||||
int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger),
|
||||
),
|
||||
]
|
||||
if not self.wait_for_signals(
|
||||
signal_conditions=signal_conditions,
|
||||
timeout=self.parent.timeout,
|
||||
check_stopped=True,
|
||||
all_signals=True,
|
||||
):
|
||||
raise EigerTimeoutError(
|
||||
f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state"
|
||||
f" {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for"
|
||||
" the file writer"
|
||||
)
|
||||
self.stop_detector()
|
||||
self.stop_detector_backend()
|
||||
with self._lock:
|
||||
signal_conditions = [
|
||||
(
|
||||
lambda: self.parent.cam.acquire.read()[self.parent.cam.acquire.name]["value"],
|
||||
DetectorState.IDLE,
|
||||
),
|
||||
(lambda: self.std_client.get_status()["acquisition"]["state"], "FINISHED"),
|
||||
(
|
||||
lambda: self.std_client.get_status()["acquisition"]["stats"][
|
||||
"n_write_completed"
|
||||
],
|
||||
int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger),
|
||||
),
|
||||
]
|
||||
if not self.wait_for_signals(
|
||||
signal_conditions=signal_conditions,
|
||||
timeout=self.parent.timeout,
|
||||
check_stopped=True,
|
||||
all_signals=True,
|
||||
):
|
||||
raise EigerTimeoutError(
|
||||
f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state"
|
||||
f" {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for"
|
||||
" the file writer"
|
||||
)
|
||||
self.stop_detector()
|
||||
self.stop_detector_backend()
|
||||
|
||||
|
||||
class SLSDetectorCam(Device):
|
||||
@@ -7,7 +7,10 @@ from bec_lib.logger import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
|
||||
from ophyd.mca import EpicsMCARecord
|
||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
||||
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||
CustomDetectorMixin,
|
||||
PSIDetectorBase,
|
||||
)
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
@@ -3,10 +3,14 @@ import threading
|
||||
from collections import defaultdict
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import MessageEndpoints, bec_logger, messages, threadlocked
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, EpicsSignal, EpicsSignalRO
|
||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
||||
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||
CustomDetectorMixin,
|
||||
PSIDetectorBase,
|
||||
)
|
||||
from ophyd_devices.utils import bec_utils
|
||||
|
||||
logger = bec_logger.logger
|
||||
@@ -109,17 +113,17 @@ class MCSSetup(CustomDetectorMixin):
|
||||
done=bool(max_value == value), # == self.counter),
|
||||
)
|
||||
|
||||
@threadlocked
|
||||
def _on_mca_data(self, *args, obj=None, value=None, **kwargs) -> None:
|
||||
"""Callback function for scan progress"""
|
||||
if not isinstance(value, (list, np.ndarray)):
|
||||
return
|
||||
self.mca_data[obj.attr_name] = value
|
||||
if len(self.mca_names) != len(self.mca_data):
|
||||
return
|
||||
self.acquisition_done = True
|
||||
self._send_data_to_bec()
|
||||
self.mca_data = defaultdict(lambda: [])
|
||||
with self._lock:
|
||||
if not isinstance(value, (list, np.ndarray)):
|
||||
return
|
||||
self.mca_data[obj.attr_name] = value
|
||||
if len(self.mca_names) != len(self.mca_data):
|
||||
return
|
||||
self.acquisition_done = True
|
||||
self._send_data_to_bec()
|
||||
self.mca_data = defaultdict(lambda: [])
|
||||
|
||||
def _send_data_to_bec(self) -> None:
|
||||
"""Sends bundled data to BEC"""
|
||||
@@ -5,10 +5,14 @@ import time
|
||||
|
||||
import numpy as np
|
||||
import requests
|
||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from ophyd import ADComponent as ADCpt
|
||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV, Staged
|
||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
||||
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
|
||||
CustomDetectorMixin,
|
||||
PSIDetectorBase,
|
||||
)
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import os
|
||||
import time
|
||||
|
||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, DeviceStatus, EpicsSignal, EpicsSignalRO, Signal
|
||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, Signal
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from .fgalil_ophyd import FlomniGalilController, FlomniGalilMotor
|
||||
from .fupr_ophyd import FuprGalilController, FuprGalilMotor
|
||||
from .galil_ophyd import GalilController, GalilMotor
|
||||
from .lgalil_ophyd import LamniGalilController, LamniGalilMotor
|
||||
from .sgalil_ophyd import SGalilMotor
|
||||
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 157 KiB |
@@ -10,7 +10,7 @@ from ophyd.utils import LimitError
|
||||
from ophyd_devices.utils.controller import threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||
|
||||
from csaxs_bec.devices.galil.galil_ophyd import (
|
||||
from csaxs_bec.devices.omny.galil.galil_ophyd import (
|
||||
BECConfigError,
|
||||
GalilAxesReferenced,
|
||||
GalilController,
|
||||
@@ -1,4 +1,3 @@
|
||||
import functools
|
||||
import threading
|
||||
import time
|
||||
|
||||
@@ -7,15 +6,13 @@ from bec_lib import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, PositionerBase, Signal
|
||||
from ophyd.status import wait as status_wait
|
||||
from ophyd.utils import LimitError, ReadOnlyError
|
||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
||||
from prettytable import PrettyTable
|
||||
from ophyd.utils import LimitError
|
||||
from ophyd_devices.utils.controller import threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||
|
||||
from csaxs_bec.devices.galil.galil_ophyd import (
|
||||
from csaxs_bec.devices.omny.galil.galil_ophyd import (
|
||||
BECConfigError,
|
||||
GalilAxesReferenced,
|
||||
GalilCommunicationError,
|
||||
GalilController,
|
||||
GalilError,
|
||||
GalilMotorIsMoving,
|
||||
@@ -1,15 +1,14 @@
|
||||
"""
|
||||
This module contains the base class for Galil controllers as well as the signals used for Galil devices.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import threading
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, PositionerBase, Signal
|
||||
from ophyd.status import wait as status_wait
|
||||
from ophyd.utils import LimitError, ReadOnlyError
|
||||
from ophyd.utils import ReadOnlyError
|
||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
||||
from ophyd_devices.utils.socket import SocketSignal
|
||||
from prettytable import PrettyTable
|
||||
|
||||
logger = bec_logger.logger
|
||||
@@ -42,6 +41,10 @@ def retry_once(fcn):
|
||||
|
||||
|
||||
class GalilController(Controller):
|
||||
"""
|
||||
Base class for Galil controllers. This class provides the basic functionality for Galil controllers and should be subclassed for specific devices.
|
||||
"""
|
||||
|
||||
_axes_per_controller = 8
|
||||
USER_ACCESS = [
|
||||
"describe",
|
||||
@@ -49,7 +52,6 @@ class GalilController(Controller):
|
||||
"galil_show_all",
|
||||
"socket_put_and_receive",
|
||||
"socket_put_confirmed",
|
||||
"lgalil_is_air_off_and_orchestra_enabled",
|
||||
"drive_axis_to_limit",
|
||||
"find_reference",
|
||||
"get_motor_limit_switch",
|
||||
@@ -61,18 +63,6 @@ class GalilController(Controller):
|
||||
def socket_put(self, val: str) -> None:
|
||||
self.sock.put(f"{val}\r".encode())
|
||||
|
||||
@threadlocked
|
||||
def socket_get(self) -> str:
|
||||
return self.sock.receive().decode()
|
||||
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def socket_put_and_receive(self, val: str, remove_trailing_chars=True) -> str:
|
||||
self.socket_put(val)
|
||||
if remove_trailing_chars:
|
||||
return self._remove_trailing_characters(self.sock.receive().decode())
|
||||
return self.socket_get()
|
||||
|
||||
@retry_once
|
||||
def socket_put_confirmed(self, val: str) -> None:
|
||||
"""Send message to controller and ensure that it is received by checking that the socket receives a colon.
|
||||
@@ -94,7 +84,9 @@ class GalilController(Controller):
|
||||
if axis_Id is None and axis_Id_numeric is not None:
|
||||
axis_Id = self.axis_Id_numeric_to_alpha(axis_Id_numeric)
|
||||
is_moving = bool(float(self.socket_put_and_receive(f"MG_BG{axis_Id}")) != 0)
|
||||
backlash_is_active = bool(float(self.socket_put_and_receive(f"MGbcklact[{axis_Id_numeric}]")) != 0)
|
||||
backlash_is_active = bool(
|
||||
float(self.socket_put_and_receive(f"MGbcklact[{axis_Id_numeric}]")) != 0
|
||||
)
|
||||
return bool(
|
||||
is_moving or backlash_is_active or self.is_thread_active(0) or self.is_thread_active(2)
|
||||
)
|
||||
@@ -105,21 +97,10 @@ class GalilController(Controller):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _remove_trailing_characters(self, var) -> str:
|
||||
if len(var) > 1:
|
||||
return var.split("\r\n")[0]
|
||||
return var
|
||||
|
||||
def stop_all_axes(self) -> str:
|
||||
return self.socket_put_and_receive(f"XQ#STOP,1")
|
||||
return self.socket_put_and_receive("XQ#STOP,1")
|
||||
|
||||
def lgalil_is_air_off_and_orchestra_enabled(self) -> bool:
|
||||
# TODO: move this to the LamNI-specific controller
|
||||
rt_not_blocked_by_galil = bool(self.socket_put_and_receive(f"MG@OUT[9]"))
|
||||
air_off = bool(self.socket_put_and_receive(f"MG@OUT[13]"))
|
||||
return rt_not_blocked_by_galil and air_off
|
||||
|
||||
def get_digital_input(self,channel):
|
||||
def get_digital_input(self, channel):
|
||||
return bool(float(self.socket_put_and_receive(f"MG @IN[{channel}]").strip()))
|
||||
|
||||
def axis_is_referenced(self, axis_Id_numeric) -> bool:
|
||||
@@ -248,40 +229,17 @@ class GalilController(Controller):
|
||||
self.show_running_threads()
|
||||
self.show_status_other()
|
||||
|
||||
def show_status_other(self):
|
||||
#Todo: move to lgalil specific section
|
||||
if(self.get_digital_input(5)):
|
||||
print("Emergency stop is not pushed.")
|
||||
else:
|
||||
print("Emergency stop is pushed.")
|
||||
if(self.get_digital_input(6)):
|
||||
print("Driver axis 2 error.")
|
||||
if(self.get_digital_input(13)):
|
||||
print("No air pressure at inner rotation.")
|
||||
else:
|
||||
print("There is air pressure at the inner rotation.")
|
||||
if(self.get_digital_input(14)):
|
||||
print("No air pressure at outer rotation axial.")
|
||||
else:
|
||||
print("There is air pressure at the outer rotation axial.")
|
||||
if(self.get_digital_input(15)):
|
||||
print("No air pressure at outer rotation radial.")
|
||||
else:
|
||||
print("There is air pressure at the outer rotation radial.")
|
||||
swver = float(self.socket_put_and_receive("MGswver"))
|
||||
print(f"Lgalil LAMNI firmware version {swver:2.0f}.")
|
||||
def show_status_other(self) -> None:
|
||||
"""
|
||||
Show additional device-specific status information.
|
||||
Override in subclasses.
|
||||
"""
|
||||
|
||||
def galil_show_all(self) -> None:
|
||||
for controller in self._controller_instances.values():
|
||||
if isinstance(controller, GalilController):
|
||||
controller.describe()
|
||||
|
||||
def lamni_lights_off(self):
|
||||
self.socket_put_confirmed("SB1")
|
||||
|
||||
def lamni_lights_on(self):
|
||||
self.socket_put_confirmed("CB1")
|
||||
|
||||
@staticmethod
|
||||
def axis_Id_to_numeric(axis_Id: str) -> int:
|
||||
return ord(axis_Id.lower()) - 97
|
||||
@@ -378,7 +336,9 @@ class GalilSetpointSignal(GalilSignalBase):
|
||||
if angle_status:
|
||||
self.controller.socket_put_confirmed("angintf=1")
|
||||
except KeyError:
|
||||
logger.warning("RT is disabled. Failed to update RT angle interferometer status to galil.")
|
||||
logger.warning(
|
||||
"RT is disabled. Failed to update RT angle interferometer status to galil."
|
||||
)
|
||||
|
||||
self.controller.socket_put_confirmed(f"naxis={self.parent.axis_Id_numeric}")
|
||||
self.controller.socket_put_confirmed(f"ntarget={target_val:.3f}")
|
||||
@@ -415,229 +375,3 @@ class GalilAxesReferenced(GalilSignalRO):
|
||||
@threadlocked
|
||||
def _socket_get(self):
|
||||
return self.controller.all_axes_referenced()
|
||||
|
||||
|
||||
class GalilMotor(Device, PositionerBase):
|
||||
USER_ACCESS = ["controller"]
|
||||
readback = Cpt(GalilReadbackSignal, signal_name="readback", kind="hinted")
|
||||
user_setpoint = Cpt(GalilSetpointSignal, signal_name="setpoint")
|
||||
motor_resolution = Cpt(GalilMotorResolution, signal_name="resolution", kind="config")
|
||||
motor_is_moving = Cpt(GalilMotorIsMoving, signal_name="motor_is_moving", kind="normal")
|
||||
all_axes_referenced = Cpt(GalilAxesReferenced, signal_name="all_axes_referenced", kind="config")
|
||||
high_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||
low_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||
|
||||
SUB_READBACK = "readback"
|
||||
SUB_CONNECTION_CHANGE = "connection_change"
|
||||
_default_sub = SUB_READBACK
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
axis_Id,
|
||||
prefix="",
|
||||
*,
|
||||
name,
|
||||
kind=None,
|
||||
read_attrs=None,
|
||||
configuration_attrs=None,
|
||||
parent=None,
|
||||
host="mpc2680.psi.ch",
|
||||
port=8081,
|
||||
limits=None,
|
||||
sign=1,
|
||||
socket_cls=SocketIO,
|
||||
device_manager=None,
|
||||
**kwargs,
|
||||
):
|
||||
self.controller = GalilController(socket_cls=socket_cls, socket_host=host, socket_port=port)
|
||||
self.axis_Id = axis_Id
|
||||
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
||||
self.sign = sign
|
||||
self.tolerance = kwargs.pop("tolerance", 0.5)
|
||||
self.device_mapping = kwargs.pop("device_mapping", {})
|
||||
self.device_manager = device_manager
|
||||
|
||||
if len(self.device_mapping) > 0 and self.device_manager is None:
|
||||
raise BECConfigError(
|
||||
"device_mapping has been specified but the device_manager cannot be accessed."
|
||||
)
|
||||
self.rt = self.device_mapping.get("rt")
|
||||
|
||||
super().__init__(
|
||||
prefix,
|
||||
name=name,
|
||||
kind=kind,
|
||||
read_attrs=read_attrs,
|
||||
configuration_attrs=configuration_attrs,
|
||||
parent=parent,
|
||||
**kwargs,
|
||||
)
|
||||
self.readback.name = self.name
|
||||
self.controller.subscribe(
|
||||
self._update_connection_state, event_type=self.SUB_CONNECTION_CHANGE
|
||||
)
|
||||
self._update_connection_state()
|
||||
# self.readback.subscribe(self._forward_readback, event_type=self.readback.SUB_VALUE)
|
||||
|
||||
if limits is not None:
|
||||
assert len(limits) == 2
|
||||
self.low_limit_travel.put(limits[0])
|
||||
self.high_limit_travel.put(limits[1])
|
||||
|
||||
@property
|
||||
def limits(self):
|
||||
return (self.low_limit_travel.get(), self.high_limit_travel.get())
|
||||
|
||||
@property
|
||||
def low_limit(self):
|
||||
return self.limits[0]
|
||||
|
||||
@property
|
||||
def high_limit(self):
|
||||
return self.limits[1]
|
||||
|
||||
def check_value(self, pos):
|
||||
"""Check that the position is within the soft limits"""
|
||||
low_limit, high_limit = self.limits
|
||||
|
||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
||||
|
||||
def _update_connection_state(self, **kwargs):
|
||||
for walk in self.walk_signals():
|
||||
walk.item._metadata["connected"] = self.controller.connected
|
||||
|
||||
def _forward_readback(self, **kwargs):
|
||||
kwargs.pop("sub_type")
|
||||
self._run_subs(sub_type="readback", **kwargs)
|
||||
|
||||
@raise_if_disconnected
|
||||
def move(self, position, wait=True, **kwargs):
|
||||
"""Move to a specified position, optionally waiting for motion to
|
||||
complete.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
position
|
||||
Position to move to
|
||||
moved_cb : callable
|
||||
Call this callback when movement has finished. This callback must
|
||||
accept one keyword argument: 'obj' which will be set to this
|
||||
positioner instance.
|
||||
timeout : float, optional
|
||||
Maximum time to wait for the motion. If None, the default timeout
|
||||
for this positioner is used.
|
||||
|
||||
Returns
|
||||
-------
|
||||
status : MoveStatus
|
||||
|
||||
Raises
|
||||
------
|
||||
TimeoutError
|
||||
When motion takes longer than `timeout`
|
||||
ValueError
|
||||
On invalid positions
|
||||
RuntimeError
|
||||
If motion fails other than timing out
|
||||
"""
|
||||
self._started_moving = False
|
||||
timeout = kwargs.pop("timeout", 100)
|
||||
status = super().move(position, timeout=timeout, **kwargs)
|
||||
self.user_setpoint.put(position, wait=False)
|
||||
|
||||
def move_and_finish():
|
||||
while self.motor_is_moving.get():
|
||||
logger.info("motor is moving")
|
||||
val = self.readback.read()
|
||||
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
|
||||
time.sleep(0.1)
|
||||
val = self.readback.read()
|
||||
success = np.isclose(val[self.name]["value"], position, atol=self.tolerance)
|
||||
|
||||
if not success:
|
||||
print(" stop")
|
||||
self._done_moving(success=success)
|
||||
logger.info("Move finished")
|
||||
|
||||
threading.Thread(target=move_and_finish, daemon=True).start()
|
||||
try:
|
||||
if wait:
|
||||
status_wait(status)
|
||||
except KeyboardInterrupt:
|
||||
self.stop()
|
||||
raise
|
||||
|
||||
return status
|
||||
|
||||
@property
|
||||
def axis_Id(self):
|
||||
return self._axis_Id_alpha
|
||||
|
||||
@axis_Id.setter
|
||||
def axis_Id(self, val):
|
||||
if isinstance(val, str):
|
||||
if len(val) != 1:
|
||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = self.controller.axis_Id_to_numeric(val)
|
||||
else:
|
||||
raise TypeError(f"Expected value of type str but received {type(val)}")
|
||||
|
||||
@property
|
||||
def axis_Id_numeric(self):
|
||||
return self._axis_Id_numeric
|
||||
|
||||
@axis_Id_numeric.setter
|
||||
def axis_Id_numeric(self, val):
|
||||
if isinstance(val, int):
|
||||
if val > 26:
|
||||
raise ValueError(f"Numeric value exceeds supported range.")
|
||||
self._axis_Id_alpha = self.controller.axis_Id_numeric_to_alpha(val)
|
||||
self._axis_Id_numeric = val
|
||||
else:
|
||||
raise TypeError(f"Expected value of type int but received {type(val)}")
|
||||
|
||||
@property
|
||||
def egu(self):
|
||||
"""The engineering units (EGU) for positions"""
|
||||
return "mm"
|
||||
|
||||
def stage(self) -> list[object]:
|
||||
return super().stage()
|
||||
|
||||
def unstage(self) -> list[object]:
|
||||
return super().unstage()
|
||||
|
||||
def stop(self, *, success=False):
|
||||
self.controller.stop_all_axes()
|
||||
return super().stop(success=success)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# pytest: skip-file
|
||||
mock = False
|
||||
if not mock:
|
||||
leyey = GalilMotor("H", name="leyey", host="mpc2680.psi.ch", port=8081, sign=-1)
|
||||
leyey.stage()
|
||||
status = leyey.move(0, wait=True)
|
||||
status = leyey.move(10, wait=True)
|
||||
leyey.read()
|
||||
|
||||
leyey.get()
|
||||
leyey.describe()
|
||||
|
||||
leyey.unstage()
|
||||
else:
|
||||
from ophyd_devices.utils.socket import SocketMock
|
||||
|
||||
leyex = GalilMotor(
|
||||
"G", name="leyex", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
||||
)
|
||||
leyey = GalilMotor(
|
||||
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
||||
)
|
||||
leyex.stage()
|
||||
# leyey.stage()
|
||||
|
||||
leyex.controller.galil_show_all()
|
||||
265
csaxs_bec/devices/omny/galil/lgalil_ophyd.py
Normal file
265
csaxs_bec/devices/omny/galil/lgalil_ophyd.py
Normal file
@@ -0,0 +1,265 @@
|
||||
import threading
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, PositionerBase, Signal
|
||||
from ophyd.status import wait as status_wait
|
||||
from ophyd.utils import LimitError
|
||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||
|
||||
from csaxs_bec.devices.omny.galil.galil_ophyd import (
|
||||
BECConfigError,
|
||||
GalilAxesReferenced,
|
||||
GalilController,
|
||||
GalilMotorIsMoving,
|
||||
GalilMotorResolution,
|
||||
GalilReadbackSignal,
|
||||
GalilSetpointSignal,
|
||||
)
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
class LamniGalilController(GalilController):
|
||||
USER_ACCESS = [
|
||||
"describe",
|
||||
"show_running_threads",
|
||||
"galil_show_all",
|
||||
"socket_put_and_receive",
|
||||
"socket_put_confirmed",
|
||||
"lgalil_is_air_off_and_orchestra_enabled",
|
||||
"drive_axis_to_limit",
|
||||
"find_reference",
|
||||
"get_motor_limit_switch",
|
||||
"is_motor_on",
|
||||
"all_axes_referenced",
|
||||
]
|
||||
|
||||
def show_status_other(self):
|
||||
if self.get_digital_input(5):
|
||||
print("Emergency stop is not pushed.")
|
||||
else:
|
||||
print("Emergency stop is pushed.")
|
||||
if self.get_digital_input(6):
|
||||
print("Driver axis 2 error.")
|
||||
if self.get_digital_input(13):
|
||||
print("No air pressure at inner rotation.")
|
||||
else:
|
||||
print("There is air pressure at the inner rotation.")
|
||||
if self.get_digital_input(14):
|
||||
print("No air pressure at outer rotation axial.")
|
||||
else:
|
||||
print("There is air pressure at the outer rotation axial.")
|
||||
if self.get_digital_input(15):
|
||||
print("No air pressure at outer rotation radial.")
|
||||
else:
|
||||
print("There is air pressure at the outer rotation radial.")
|
||||
swver = float(self.socket_put_and_receive("MGswver"))
|
||||
print(f"Lgalil LAMNI firmware version {swver:2.0f}.")
|
||||
|
||||
def lamni_lights_off(self):
|
||||
self.socket_put_confirmed("SB1")
|
||||
|
||||
def lamni_lights_on(self):
|
||||
self.socket_put_confirmed("CB1")
|
||||
|
||||
def lgalil_is_air_off_and_orchestra_enabled(self) -> bool:
|
||||
# TODO: move this to the LamNI-specific controller
|
||||
rt_not_blocked_by_galil = bool(self.socket_put_and_receive("MG@OUT[9]"))
|
||||
air_off = bool(self.socket_put_and_receive("MG@OUT[13]"))
|
||||
return rt_not_blocked_by_galil and air_off
|
||||
|
||||
|
||||
class LamniGalilMotor(Device, PositionerBase):
|
||||
USER_ACCESS = ["controller"]
|
||||
readback = Cpt(GalilReadbackSignal, signal_name="readback", kind="hinted")
|
||||
user_setpoint = Cpt(GalilSetpointSignal, signal_name="setpoint")
|
||||
motor_resolution = Cpt(GalilMotorResolution, signal_name="resolution", kind="config")
|
||||
motor_is_moving = Cpt(GalilMotorIsMoving, signal_name="motor_is_moving", kind="normal")
|
||||
all_axes_referenced = Cpt(GalilAxesReferenced, signal_name="all_axes_referenced", kind="config")
|
||||
high_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||
low_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||
|
||||
SUB_READBACK = "readback"
|
||||
SUB_CONNECTION_CHANGE = "connection_change"
|
||||
_default_sub = SUB_READBACK
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
axis_Id,
|
||||
prefix="",
|
||||
*,
|
||||
name,
|
||||
kind=None,
|
||||
read_attrs=None,
|
||||
configuration_attrs=None,
|
||||
parent=None,
|
||||
host="mpc2680.psi.ch",
|
||||
port=8081,
|
||||
limits=None,
|
||||
sign=1,
|
||||
socket_cls=SocketIO,
|
||||
device_manager=None,
|
||||
**kwargs,
|
||||
):
|
||||
self.controller = LamniGalilController(
|
||||
socket_cls=socket_cls, socket_host=host, socket_port=port
|
||||
)
|
||||
self.axis_Id = axis_Id
|
||||
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
||||
self.sign = sign
|
||||
self.tolerance = kwargs.pop("tolerance", 0.5)
|
||||
self.device_mapping = kwargs.pop("device_mapping", {})
|
||||
self.device_manager = device_manager
|
||||
|
||||
if len(self.device_mapping) > 0 and self.device_manager is None:
|
||||
raise BECConfigError(
|
||||
"device_mapping has been specified but the device_manager cannot be accessed."
|
||||
)
|
||||
self.rt = self.device_mapping.get("rt")
|
||||
|
||||
super().__init__(
|
||||
prefix,
|
||||
name=name,
|
||||
kind=kind,
|
||||
read_attrs=read_attrs,
|
||||
configuration_attrs=configuration_attrs,
|
||||
parent=parent,
|
||||
**kwargs,
|
||||
)
|
||||
self.readback.name = self.name
|
||||
self.controller.subscribe(
|
||||
self._update_connection_state, event_type=self.SUB_CONNECTION_CHANGE
|
||||
)
|
||||
self._update_connection_state()
|
||||
# self.readback.subscribe(self._forward_readback, event_type=self.readback.SUB_VALUE)
|
||||
|
||||
if limits is not None:
|
||||
assert len(limits) == 2
|
||||
self.low_limit_travel.put(limits[0])
|
||||
self.high_limit_travel.put(limits[1])
|
||||
|
||||
@property
|
||||
def limits(self):
|
||||
return (self.low_limit_travel.get(), self.high_limit_travel.get())
|
||||
|
||||
@property
|
||||
def low_limit(self):
|
||||
return self.limits[0]
|
||||
|
||||
@property
|
||||
def high_limit(self):
|
||||
return self.limits[1]
|
||||
|
||||
def check_value(self, pos):
|
||||
"""Check that the position is within the soft limits"""
|
||||
low_limit, high_limit = self.limits
|
||||
|
||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
||||
|
||||
def _update_connection_state(self, **kwargs):
|
||||
for walk in self.walk_signals():
|
||||
walk.item._metadata["connected"] = self.controller.connected
|
||||
|
||||
def _forward_readback(self, **kwargs):
|
||||
kwargs.pop("sub_type")
|
||||
self._run_subs(sub_type="readback", **kwargs)
|
||||
|
||||
@raise_if_disconnected
|
||||
def move(self, position, wait=True, **kwargs):
|
||||
"""Move to a specified position, optionally waiting for motion to
|
||||
complete.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
position
|
||||
Position to move to
|
||||
moved_cb : callable
|
||||
Call this callback when movement has finished. This callback must
|
||||
accept one keyword argument: 'obj' which will be set to this
|
||||
positioner instance.
|
||||
timeout : float, optional
|
||||
Maximum time to wait for the motion. If None, the default timeout
|
||||
for this positioner is used.
|
||||
|
||||
Returns
|
||||
-------
|
||||
status : MoveStatus
|
||||
|
||||
Raises
|
||||
------
|
||||
TimeoutError
|
||||
When motion takes longer than `timeout`
|
||||
ValueError
|
||||
On invalid positions
|
||||
RuntimeError
|
||||
If motion fails other than timing out
|
||||
"""
|
||||
self._started_moving = False
|
||||
timeout = kwargs.pop("timeout", 100)
|
||||
status = super().move(position, timeout=timeout, **kwargs)
|
||||
self.user_setpoint.put(position, wait=False)
|
||||
|
||||
def move_and_finish():
|
||||
while self.motor_is_moving.get():
|
||||
logger.info("motor is moving")
|
||||
val = self.readback.read()
|
||||
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
|
||||
time.sleep(0.1)
|
||||
val = self.readback.read()
|
||||
success = np.isclose(val[self.name]["value"], position, atol=self.tolerance)
|
||||
|
||||
if not success:
|
||||
print(" stop")
|
||||
self._done_moving(success=success)
|
||||
logger.info("Move finished")
|
||||
|
||||
threading.Thread(target=move_and_finish, daemon=True).start()
|
||||
try:
|
||||
if wait:
|
||||
status_wait(status)
|
||||
except KeyboardInterrupt:
|
||||
self.stop()
|
||||
raise
|
||||
|
||||
return status
|
||||
|
||||
@property
|
||||
def axis_Id(self):
|
||||
return self._axis_Id_alpha
|
||||
|
||||
@axis_Id.setter
|
||||
def axis_Id(self, val):
|
||||
if isinstance(val, str):
|
||||
if len(val) != 1:
|
||||
raise ValueError("Only single-character axis_Ids are supported.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = self.controller.axis_Id_to_numeric(val)
|
||||
else:
|
||||
raise TypeError(f"Expected value of type str but received {type(val)}")
|
||||
|
||||
@property
|
||||
def axis_Id_numeric(self):
|
||||
return self._axis_Id_numeric
|
||||
|
||||
@axis_Id_numeric.setter
|
||||
def axis_Id_numeric(self, val):
|
||||
if isinstance(val, int):
|
||||
if val > 26:
|
||||
raise ValueError("Numeric value exceeds supported range.")
|
||||
self._axis_Id_alpha = self.controller.axis_Id_numeric_to_alpha(val)
|
||||
self._axis_Id_numeric = val
|
||||
else:
|
||||
raise TypeError(f"Expected value of type int but received {type(val)}")
|
||||
|
||||
@property
|
||||
def egu(self):
|
||||
"""The engineering units (EGU) for positions"""
|
||||
return "mm"
|
||||
|
||||
def stop(self, *, success=False):
|
||||
self.controller.stop_all_axes()
|
||||
return super().stop(success=success)
|
||||
@@ -4,7 +4,7 @@ Ophyd wrapper for the SGalil controller and stages.
|
||||
## Integration of the device in IPython kernel
|
||||
BEC needs to be able to reach the host TCP to initiate a connection to the device.
|
||||
```Python
|
||||
from csaxs_bec.devices.galil.sgalil_ophyd import SGalilMotor
|
||||
from csaxs_bec.devices.omny.galil.sgalil_ophyd import SGalilMotor
|
||||
samx = SGalilMotor("E", name="samx", host="129.129.122.26", port=23, sign=-1)
|
||||
samy = SGalilMotor("C", name="samy", host="129.129.122.26", port=23, sign=-1)
|
||||
# connect to the controller
|
||||
@@ -4,7 +4,7 @@ from ophyd import Component as Cpt
|
||||
from ophyd import Device
|
||||
from ophyd import DynamicDeviceComponent as Dcpt
|
||||
from ophyd import EpicsSignal
|
||||
from prettytable import PrettyTable, FRAME
|
||||
from prettytable import FRAME, PrettyTable
|
||||
|
||||
|
||||
class OMNYSampleStorageError(Exception):
|
||||
@@ -3,29 +3,31 @@ import time
|
||||
from typing import List
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, PositionerBase, Signal
|
||||
from ophyd.status import wait as status_wait
|
||||
from ophyd.utils import LimitError
|
||||
from csaxs_bec.devices.rt_lamni.rt_ophyd import (
|
||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||
from prettytable import PrettyTable
|
||||
|
||||
from csaxs_bec.devices.omny.rt.rt_ophyd import (
|
||||
BECConfigError,
|
||||
RtCommunicationError,
|
||||
RtController,
|
||||
RtError,
|
||||
RtReadbackSignal,
|
||||
RtSetpointSignal,
|
||||
RtSignalRO,
|
||||
retry_once,
|
||||
)
|
||||
from ophyd_devices.utils.controller import threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, raise_if_disconnected
|
||||
from prettytable import PrettyTable
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
class RtFlomniController(RtController):
|
||||
class RtFlomniController(Controller):
|
||||
_axes_per_controller = 3
|
||||
USER_ACCESS = [
|
||||
"socket_put_and_receive",
|
||||
"set_rotation_angle",
|
||||
@@ -50,7 +52,7 @@ class RtFlomniController(RtController):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
name=None,
|
||||
name="RtFlomniController",
|
||||
socket_cls=None,
|
||||
socket_host=None,
|
||||
socket_port=None,
|
||||
@@ -73,6 +75,15 @@ class RtFlomniController(RtController):
|
||||
self._min_scan_buffer_reached = False
|
||||
self.rt_pid_voltage = None
|
||||
|
||||
def is_axis_moving(self, axis_Id) -> bool:
|
||||
# this checks that axis is on target
|
||||
axis_is_on_target = bool(float(self.socket_put_and_receive("o")))
|
||||
return not axis_is_on_target
|
||||
|
||||
@threadlocked
|
||||
def stop_all_axes(self):
|
||||
self.socket_put("sc")
|
||||
|
||||
def add_pos_to_scan(self, positions) -> None:
|
||||
def send_positions(parent, positions):
|
||||
parent._min_scan_buffer_reached = False
|
||||
@@ -487,7 +498,7 @@ class RtFlomniController(RtController):
|
||||
MessageEndpoints.device_status("rt_scan"),
|
||||
messages.DeviceStatusMessage(
|
||||
device="rt_scan", status=1, metadata=self.readout_metadata
|
||||
).dumps(),
|
||||
),
|
||||
)
|
||||
# while scan is running
|
||||
while mode > 0:
|
||||
@@ -522,7 +533,7 @@ class RtFlomniController(RtController):
|
||||
MessageEndpoints.device_status("rt_scan"),
|
||||
messages.DeviceStatusMessage(
|
||||
device="rt_scan", status=0, metadata=self.readout_metadata
|
||||
).dumps(),
|
||||
),
|
||||
)
|
||||
|
||||
logger.info(
|
||||
@@ -536,7 +547,7 @@ class RtFlomniController(RtController):
|
||||
MessageEndpoints.device_read("rt_flomni"),
|
||||
messages.DeviceMessage(
|
||||
signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
|
||||
).dumps(),
|
||||
),
|
||||
)
|
||||
|
||||
def start_readout(self):
|
||||
@@ -683,15 +694,16 @@ class RtFlomniMotor(Device, PositionerBase):
|
||||
def high_limit(self):
|
||||
return self.limits[1]
|
||||
|
||||
def check_value(self, pos):
|
||||
def check_value(self, value, **kwargs):
|
||||
"""Check that the position is within the soft limits"""
|
||||
low_limit, high_limit = self.limits
|
||||
|
||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
||||
if low_limit < high_limit and not (low_limit <= value <= high_limit):
|
||||
raise LimitError(f"position={value} not within limits {self.limits}")
|
||||
|
||||
def _update_connection_state(self, **kwargs):
|
||||
for walk in self.walk_signals():
|
||||
# pylint: disable=protected-access
|
||||
walk.item._metadata["connected"] = self.controller.connected
|
||||
|
||||
def _forward_readback(self, **kwargs):
|
||||
@@ -761,7 +773,7 @@ class RtFlomniMotor(Device, PositionerBase):
|
||||
def axis_Id(self, val):
|
||||
if isinstance(val, str):
|
||||
if len(val) != 1:
|
||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
||||
raise ValueError("Only single-character axis_Ids are supported.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = ord(val.lower()) - 97
|
||||
else:
|
||||
@@ -775,7 +787,7 @@ class RtFlomniMotor(Device, PositionerBase):
|
||||
def axis_Id_numeric(self, val):
|
||||
if isinstance(val, int):
|
||||
if val > 26:
|
||||
raise ValueError(f"Numeric value exceeds supported range.")
|
||||
raise ValueError("Numeric value exceeds supported range.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
||||
else:
|
||||
@@ -789,14 +801,6 @@ class RtFlomniMotor(Device, PositionerBase):
|
||||
"""The engineering units (EGU) for positions"""
|
||||
return "um"
|
||||
|
||||
# how is this used later?
|
||||
|
||||
def stage(self) -> List[object]:
|
||||
return super().stage()
|
||||
|
||||
def unstage(self) -> List[object]:
|
||||
return super().unstage()
|
||||
|
||||
def stop(self, *, success=False):
|
||||
self.controller.stop_all_axes()
|
||||
self._stopped = True
|
||||
@@ -3,7 +3,8 @@ import threading
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, PositionerBase, Signal
|
||||
from ophyd.status import wait as status_wait
|
||||
@@ -11,6 +12,8 @@ from ophyd.utils import LimitError, ReadOnlyError
|
||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
||||
|
||||
from csaxs_bec.devices.omny.rt.rt_ophyd import RtCommunicationError, RtError
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
@@ -41,6 +44,11 @@ def retry_once(fcn):
|
||||
|
||||
|
||||
class RtLamniController(Controller):
|
||||
"""
|
||||
RT-Lamni controller class for all rt devices.
|
||||
"""
|
||||
|
||||
_axes_per_controller = 3
|
||||
USER_ACCESS = [
|
||||
"socket_put_and_receive",
|
||||
"set_rotation_angle",
|
||||
@@ -60,110 +68,25 @@ class RtLamniController(Controller):
|
||||
self,
|
||||
*,
|
||||
name="RtLamniController",
|
||||
kind=None,
|
||||
parent=None,
|
||||
socket=None,
|
||||
socket_cls=None,
|
||||
socket_host=None,
|
||||
socket_port=None,
|
||||
attr_name="",
|
||||
parent=None,
|
||||
labels=None,
|
||||
kind=None,
|
||||
):
|
||||
if not hasattr(self, "_initialized") or not self._initialized:
|
||||
self._rtlamni_axis_per_controller = 3
|
||||
self._axis = [None for axis_num in range(self._rtlamni_axis_per_controller)]
|
||||
self._min_scan_buffer_reached = False
|
||||
super().__init__(
|
||||
name=name,
|
||||
socket=socket,
|
||||
attr_name=attr_name,
|
||||
parent=parent,
|
||||
labels=labels,
|
||||
kind=kind,
|
||||
)
|
||||
self.readout_metadata = {}
|
||||
|
||||
def on(self, controller_num=0) -> None:
|
||||
"""Open a new socket connection to the controller"""
|
||||
if not self.connected:
|
||||
try:
|
||||
self.sock.open()
|
||||
# discuss - after disconnect takes a while for the server to be ready again
|
||||
max_retries = 10
|
||||
tries = 0
|
||||
while not self.connected:
|
||||
try:
|
||||
welcome_message = self.sock.receive()
|
||||
self.connected = True
|
||||
except ConnectionResetError as conn_reset:
|
||||
if tries > max_retries:
|
||||
raise conn_reset
|
||||
tries += 1
|
||||
time.sleep(2)
|
||||
except ConnectionRefusedError as conn_error:
|
||||
logger.error("Failed to open a connection to RTLamNI.")
|
||||
raise RtLamniCommunicationError from conn_error
|
||||
|
||||
else:
|
||||
logger.info("The connection has already been established.")
|
||||
# warnings.warn(f"The connection has already been established.", stacklevel=2)
|
||||
|
||||
self._update_flyer_device_info()
|
||||
|
||||
def off(self) -> None:
|
||||
"""Close the socket connection to the controller"""
|
||||
if self.connected:
|
||||
self.sock.close()
|
||||
self.connected = False
|
||||
else:
|
||||
logger.info("The connection is already closed.")
|
||||
|
||||
def set_axis(self, axis: Device, axis_nr: int) -> None:
|
||||
"""Assign an axis to a device instance.
|
||||
|
||||
Args:
|
||||
axis (Device): Device instance (e.g. GalilMotor)
|
||||
axis_nr (int): Controller axis number
|
||||
|
||||
"""
|
||||
self._axis[axis_nr] = axis
|
||||
|
||||
@threadlocked
|
||||
def socket_put(self, val: str) -> None:
|
||||
self.sock.put(f"{val}\n".encode())
|
||||
|
||||
@threadlocked
|
||||
def socket_get(self) -> str:
|
||||
return self.sock.receive().decode()
|
||||
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def socket_put_and_receive(self, val: str, remove_trailing_chars=True) -> str:
|
||||
self.socket_put(val)
|
||||
if remove_trailing_chars:
|
||||
return self._remove_trailing_characters(self.sock.receive().decode())
|
||||
return self.socket_get()
|
||||
|
||||
def is_axis_moving(self, axis_Id) -> bool:
|
||||
# this checks that axis is on target
|
||||
axis_is_on_target = bool(float(self.socket_put_and_receive(f"o")))
|
||||
return not axis_is_on_target
|
||||
|
||||
# def is_thread_active(self, thread_id: int) -> bool:
|
||||
# val = float(self.socket_put_and_receive(f"MG_XQ{thread_id}"))
|
||||
# if val == -1:
|
||||
# return False
|
||||
# return True
|
||||
|
||||
def _remove_trailing_characters(self, var) -> str:
|
||||
if len(var) > 1:
|
||||
return var.split("\r\n")[0]
|
||||
return var
|
||||
|
||||
@threadlocked
|
||||
def set_rotation_angle(self, val: float):
|
||||
self.socket_put(f"a{(val-300+30.538)/180*np.pi}")
|
||||
|
||||
@threadlocked
|
||||
def stop_all_axes(self):
|
||||
self.socket_put("sc")
|
||||
super().__init__(
|
||||
name=name,
|
||||
socket_cls=socket_cls,
|
||||
socket_host=socket_host,
|
||||
socket_port=socket_port,
|
||||
attr_name=attr_name,
|
||||
parent=parent,
|
||||
labels=labels,
|
||||
kind=kind,
|
||||
)
|
||||
self._min_scan_buffer_reached = False
|
||||
|
||||
@threadlocked
|
||||
def feedback_disable(self):
|
||||
@@ -175,6 +98,19 @@ class RtLamniController(Controller):
|
||||
self.set_device_enabled("lopty", True)
|
||||
self.set_device_enabled("loptz", True)
|
||||
|
||||
def is_axis_moving(self, axis_Id) -> bool:
|
||||
# this checks that axis is on target
|
||||
axis_is_on_target = bool(float(self.socket_put_and_receive("o")))
|
||||
return not axis_is_on_target
|
||||
|
||||
@threadlocked
|
||||
def stop_all_axes(self):
|
||||
self.socket_put("sc")
|
||||
|
||||
@threadlocked
|
||||
def set_rotation_angle(self, val: float):
|
||||
self.socket_put(f"a{(val-300+30.538)/180*np.pi}")
|
||||
|
||||
@threadlocked
|
||||
def _set_axis_velocity(self, um_per_s):
|
||||
self.socket_put(f"V{um_per_s}")
|
||||
@@ -234,19 +170,6 @@ class RtLamniController(Controller):
|
||||
self.set_device_enabled("lopty", True)
|
||||
self.set_device_enabled("loptz", True)
|
||||
|
||||
def get_device_manager(self):
|
||||
for axis in self._axis:
|
||||
if hasattr(axis, "device_manager") and axis.device_manager:
|
||||
return axis.device_manager
|
||||
raise BECConfigError("Could not access the device_manager")
|
||||
|
||||
def get_axis_by_name(self, name):
|
||||
for axis in self._axis:
|
||||
if axis:
|
||||
if axis.name == name:
|
||||
return axis
|
||||
raise RuntimeError(f"Could not find an axis with name {name}")
|
||||
|
||||
@threadlocked
|
||||
def clear_trajectory_generator(self):
|
||||
self.socket_put("sc")
|
||||
@@ -256,7 +179,7 @@ class RtLamniController(Controller):
|
||||
def send_positions(parent, positions):
|
||||
parent._min_scan_buffer_reached = False
|
||||
for pos_index, pos in enumerate(positions):
|
||||
parent.socket_put_and_receive(f"s{pos[0]:.05f},{pos[1]:05f},0")
|
||||
parent.socket_put_and_receive(f"s{pos[0]:.05f},{pos[1]:.05f},0")
|
||||
if pos_index > 100:
|
||||
parent._min_scan_buffer_reached = True
|
||||
parent._min_scan_buffer_reached = True
|
||||
@@ -268,7 +191,7 @@ class RtLamniController(Controller):
|
||||
def get_scan_status(self):
|
||||
return_table = (self.socket_put_and_receive(f"sr")).split(",")
|
||||
if len(return_table) != 3:
|
||||
raise RtLamniCommunicationError(
|
||||
raise RtCommunicationError(
|
||||
f"Expected to receive 3 return values. Instead received {return_table}"
|
||||
)
|
||||
mode = int(return_table[0])
|
||||
@@ -288,7 +211,7 @@ class RtLamniController(Controller):
|
||||
logger.error(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
raise RtLamniError(
|
||||
raise RtError(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
# here exception
|
||||
@@ -296,7 +219,7 @@ class RtLamniController(Controller):
|
||||
|
||||
if number_of_positions_planned == 0:
|
||||
logger.error("Cannot start scan because no target positions are planned.")
|
||||
raise RtLamniError("Cannot start scan because no target positions are planned.")
|
||||
raise RtError("Cannot start scan because no target positions are planned.")
|
||||
# hier exception
|
||||
# start a point-by-point scan (for cont scan in flomni it would be "sa")
|
||||
self.socket_put_and_receive("sd")
|
||||
@@ -305,29 +228,6 @@ class RtLamniController(Controller):
|
||||
readout = threading.Thread(target=self.read_positions_from_sampler)
|
||||
readout.start()
|
||||
|
||||
def _update_flyer_device_info(self):
|
||||
flyer_info = self._get_flyer_device_info()
|
||||
self.get_device_manager().connector.set(
|
||||
MessageEndpoints.device_info("rt_scan"),
|
||||
messages.DeviceInfoMessage(device="rt_scan", info=flyer_info),
|
||||
)
|
||||
|
||||
def _get_flyer_device_info(self) -> dict:
|
||||
return {
|
||||
"device_name": self.name,
|
||||
"device_attr_name": getattr(self, "attr_name", ""),
|
||||
"device_dotted_name": getattr(self, "dotted_name", ""),
|
||||
"device_info": {
|
||||
"device_base_class": "ophydobject",
|
||||
"signals": [],
|
||||
"hints": {"fields": ["average_x_st_fzp", "average_y_st_fzp"]},
|
||||
"describe": {},
|
||||
"describe_configuration": {},
|
||||
"sub_devices": [],
|
||||
"custom_user_access": [],
|
||||
},
|
||||
}
|
||||
|
||||
def kickoff(self, metadata):
|
||||
self.readout_metadata = metadata
|
||||
while not self._min_scan_buffer_reached:
|
||||
@@ -439,7 +339,7 @@ class RtLamniController(Controller):
|
||||
)
|
||||
|
||||
def feedback_status_angle_lamni(self) -> bool:
|
||||
return_table = (self.socket_put_and_receive(f"J7")).split(",")
|
||||
return_table = (self.socket_put_and_receive("J7")).split(",")
|
||||
logger.debug(
|
||||
f"LamNI angle interferomter status {bool(return_table[0])}, position {float(return_table[1])}, signal {float(return_table[2])}"
|
||||
)
|
||||
@@ -448,21 +348,21 @@ class RtLamniController(Controller):
|
||||
def feedback_enable_with_reset(self):
|
||||
if not self.feedback_status_angle_lamni():
|
||||
self.feedback_disable_and_even_reset_lamni_angle_interferometer()
|
||||
logger.info(f"LamNI resetting interferometer inclusive angular interferomter.")
|
||||
logger.info("LamNI resetting interferometer inclusive angular interferomter.")
|
||||
else:
|
||||
self.feedback_disable()
|
||||
logger.info(
|
||||
f"LamNI resetting interferomter except angular interferometer which is already running."
|
||||
"LamNI resetting interferomter except angular interferometer which is already running."
|
||||
)
|
||||
|
||||
# set these as closed loop target position
|
||||
|
||||
self.socket_put(f"pa0,0")
|
||||
self.socket_put("pa0,0")
|
||||
self.get_axis_by_name("rtx").user_setpoint.setpoint = 0
|
||||
self.socket_put(f"pa1,0")
|
||||
self.socket_put("pa1,0")
|
||||
self.get_axis_by_name("rty").user_setpoint.setpoint = 0
|
||||
self.socket_put(
|
||||
f"pa2,0"
|
||||
"pa2,0"
|
||||
) # we set all three outputs of the traj. gen. although in LamNI case only 0,1 are used
|
||||
self.clear_trajectory_generator()
|
||||
|
||||
@@ -476,7 +376,7 @@ class RtLamniController(Controller):
|
||||
logger.error(
|
||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
||||
)
|
||||
raise RtLamniError(
|
||||
raise RtError(
|
||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
||||
)
|
||||
|
||||
@@ -515,7 +415,7 @@ class RtLamniController(Controller):
|
||||
logger.error(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
raise RtLamniError(
|
||||
raise RtError(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
|
||||
@@ -523,15 +423,6 @@ class RtLamniController(Controller):
|
||||
|
||||
# ptychography_alignment_done = 0
|
||||
|
||||
def set_device_enabled(self, device_name: str, enabled: bool) -> None:
|
||||
"""enable / disable a device"""
|
||||
if device_name not in self.get_device_manager().devices:
|
||||
logger.warning(
|
||||
f"Device {device_name} is not configured and cannot be enabled/disabled."
|
||||
)
|
||||
return
|
||||
self.get_device_manager().devices[device_name].read_only = not enabled
|
||||
|
||||
|
||||
class RtLamniSignalBase(SocketSignal):
|
||||
def __init__(self, signal_name, **kwargs):
|
||||
@@ -567,7 +458,7 @@ class RtLamniReadbackSignal(RtLamniSignalRO):
|
||||
readback_index = 1
|
||||
else:
|
||||
raise RtLamniError("Currently, only two axes are supported.")
|
||||
|
||||
print(return_table)
|
||||
current_pos = float(return_table[readback_index])
|
||||
|
||||
current_pos *= self.parent.sign
|
||||
@@ -667,7 +558,9 @@ class RtLamniMotor(Device, PositionerBase):
|
||||
):
|
||||
self.axis_Id = axis_Id
|
||||
self.sign = sign
|
||||
self.controller = RtLamniController(socket=socket_cls(host=host, port=port))
|
||||
self.controller = RtLamniController(
|
||||
socket_cls=socket_cls, socket_host=host, socket_port=port
|
||||
)
|
||||
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
||||
self.device_manager = device_manager
|
||||
self.tolerance = kwargs.pop("tolerance", 0.5)
|
||||
@@ -705,15 +598,16 @@ class RtLamniMotor(Device, PositionerBase):
|
||||
def high_limit(self):
|
||||
return self.limits[1]
|
||||
|
||||
def check_value(self, pos):
|
||||
def check_value(self, value, **kwargs):
|
||||
"""Check that the position is within the soft limits"""
|
||||
low_limit, high_limit = self.limits
|
||||
|
||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
||||
if low_limit < high_limit and not (low_limit <= value <= high_limit):
|
||||
raise LimitError(f"position={value} not within limits {self.limits}")
|
||||
|
||||
def _update_connection_state(self, **kwargs):
|
||||
for walk in self.walk_signals():
|
||||
# pylint: disable=protected-access
|
||||
walk.item._metadata["connected"] = self.controller.connected
|
||||
|
||||
def _forward_readback(self, **kwargs):
|
||||
@@ -782,7 +676,7 @@ class RtLamniMotor(Device, PositionerBase):
|
||||
def axis_Id(self, val):
|
||||
if isinstance(val, str):
|
||||
if len(val) != 1:
|
||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
||||
raise ValueError("Only single-character axis_Ids are supported.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = ord(val.lower()) - 97
|
||||
else:
|
||||
@@ -796,7 +690,7 @@ class RtLamniMotor(Device, PositionerBase):
|
||||
def axis_Id_numeric(self, val):
|
||||
if isinstance(val, int):
|
||||
if val > 26:
|
||||
raise ValueError(f"Numeric value exceeds supported range.")
|
||||
raise ValueError("Numeric value exceeds supported range.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
||||
else:
|
||||
@@ -823,9 +717,7 @@ class RtLamniMotor(Device, PositionerBase):
|
||||
return super().stop(success=success)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
mock = False
|
||||
if not mock:
|
||||
rty = RtLamniMotor("B", name="rty", host="mpc2680.psi.ch", port=3333, sign=1)
|
||||
140
csaxs_bec/devices/omny/rt/rt_ophyd.py
Normal file
140
csaxs_bec/devices/omny/rt/rt_ophyd.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""
|
||||
This module contains base signals for RT devices. Controller and motors are implemented in the
|
||||
bespoke modules such as `rt_flomni_ophyd.py` or `rt_lamni_ophyd.py`.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import time
|
||||
|
||||
from bec_lib import bec_logger
|
||||
from ophyd.utils import ReadOnlyError
|
||||
from ophyd_devices.utils.controller import ControllerCommunicationError, threadlocked
|
||||
from ophyd_devices.utils.socket import SocketSignal
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
class RtCommunicationError(ControllerCommunicationError):
|
||||
pass
|
||||
|
||||
|
||||
class RtError(ControllerCommunicationError):
|
||||
pass
|
||||
|
||||
|
||||
class BECConfigError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def retry_once(fcn):
|
||||
"""Decorator to rerun a function in case a CommunicationError was raised. This may happen if the buffer was not empty."""
|
||||
|
||||
@functools.wraps(fcn)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
val = fcn(self, *args, **kwargs)
|
||||
except (RtCommunicationError, RtError):
|
||||
val = fcn(self, *args, **kwargs)
|
||||
return val
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class RtSignalBase(SocketSignal):
|
||||
def __init__(self, signal_name, **kwargs):
|
||||
self.signal_name = signal_name
|
||||
super().__init__(**kwargs)
|
||||
self.controller = self.parent.controller
|
||||
self.sock = self.parent.controller.sock
|
||||
|
||||
|
||||
class RtSignalRO(RtSignalBase):
|
||||
def __init__(self, signal_name, **kwargs):
|
||||
super().__init__(signal_name, **kwargs)
|
||||
self._metadata["write_access"] = False
|
||||
|
||||
def _socket_set(self, val):
|
||||
raise ReadOnlyError("Read-only signals cannot be set")
|
||||
|
||||
|
||||
class RtReadbackSignal(RtSignalRO):
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def _socket_get(self) -> float:
|
||||
"""Get command for the readback signal
|
||||
|
||||
Returns:
|
||||
float: Readback value after adjusting for sign and motor resolution.
|
||||
"""
|
||||
return_table = (self.controller.socket_put_and_receive("J4")).split(",")
|
||||
if self.parent.axis_Id_numeric == 0:
|
||||
readback_index = 2
|
||||
elif self.parent.axis_Id_numeric == 1:
|
||||
readback_index = 1
|
||||
else:
|
||||
raise RtError("Currently, only two axes are supported.")
|
||||
|
||||
current_pos = float(return_table[readback_index])
|
||||
|
||||
current_pos *= self.parent.sign
|
||||
return current_pos
|
||||
|
||||
|
||||
class RtSetpointSignal(RtSignalBase):
|
||||
setpoint = 0
|
||||
|
||||
def _socket_get(self) -> float:
|
||||
"""Get command for receiving the setpoint / target value.
|
||||
The value is not pulled from the controller but instead just the last setpoint used.
|
||||
|
||||
Returns:
|
||||
float: setpoint / target value
|
||||
"""
|
||||
return self.setpoint
|
||||
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def _socket_set(self, val: float) -> None:
|
||||
"""Set a new target value / setpoint value. Before submission, the target value is adjusted for the axis' sign.
|
||||
Furthermore, it is ensured that all axes are referenced before a new setpoint is submitted.
|
||||
|
||||
Args:
|
||||
val (float): Target value / setpoint value
|
||||
|
||||
Raises:
|
||||
RtError: Raised if interferometer feedback is disabled.
|
||||
|
||||
"""
|
||||
interferometer_feedback_not_running = int(
|
||||
(self.controller.socket_put_and_receive("J2")).split(",")[0]
|
||||
)
|
||||
if interferometer_feedback_not_running != 0:
|
||||
raise RtError(
|
||||
"The interferometer feedback is not running. Either it is turned off or and interferometer error occured."
|
||||
)
|
||||
self.set_with_feedback_disabled(val)
|
||||
|
||||
def set_with_feedback_disabled(self, val):
|
||||
target_val = val * self.parent.sign
|
||||
self.setpoint = target_val
|
||||
self.controller.socket_put(f"pa{self.parent.axis_Id_numeric},{target_val:.4f}")
|
||||
|
||||
|
||||
class RtMotorIsMoving(RtSignalRO):
|
||||
def _socket_get(self):
|
||||
return self.controller.is_axis_moving(self.parent.axis_Id_numeric)
|
||||
|
||||
def get(self):
|
||||
val = super().get()
|
||||
if val is not None:
|
||||
self._run_subs(sub_type=self.SUB_VALUE, value=val, timestamp=time.time())
|
||||
return val
|
||||
|
||||
|
||||
class RtFeedbackRunning(RtSignalRO):
|
||||
@threadlocked
|
||||
def _socket_get(self):
|
||||
if int((self.controller.socket_put_and_receive("J2")).split(",")[0]) == 0:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
@@ -1,817 +0,0 @@
|
||||
import functools
|
||||
import threading
|
||||
import time
|
||||
from typing import List
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, PositionerBase, Signal
|
||||
from ophyd.status import wait as status_wait
|
||||
from ophyd.utils import LimitError, ReadOnlyError
|
||||
from ophyd_devices.utils.controller import Controller, threadlocked
|
||||
from ophyd_devices.utils.socket import SocketIO, SocketSignal, raise_if_disconnected
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
|
||||
class RtCommunicationError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class RtError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BECConfigError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def retry_once(fcn):
|
||||
"""Decorator to rerun a function in case a CommunicationError was raised. This may happen if the buffer was not empty."""
|
||||
|
||||
@functools.wraps(fcn)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
val = fcn(self, *args, **kwargs)
|
||||
except (RtCommunicationError, RtError):
|
||||
val = fcn(self, *args, **kwargs)
|
||||
return val
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class RtController(Controller):
|
||||
_axes_per_controller = 3
|
||||
USER_ACCESS = [
|
||||
"socket_put_and_receive",
|
||||
"set_rotation_angle",
|
||||
"feedback_disable",
|
||||
"feedback_enable_without_reset",
|
||||
"feedback_disable_and_even_reset_lamni_angle_interferometer",
|
||||
"feedback_enable_with_reset",
|
||||
"add_pos_to_scan",
|
||||
"clear_trajectory_generator",
|
||||
"_set_axis_velocity",
|
||||
"_set_axis_velocity_maximum_speed",
|
||||
"_position_sampling_single_read",
|
||||
"_position_sampling_single_reset_and_start_sampling",
|
||||
]
|
||||
|
||||
def on(self, controller_num=0) -> None:
|
||||
"""Open a new socket connection to the controller"""
|
||||
# if not self.connected:
|
||||
# try:
|
||||
# self.sock.open()
|
||||
# # discuss - after disconnect takes a while for the server to be ready again
|
||||
# max_retries = 10
|
||||
# tries = 0
|
||||
# while not self.connected:
|
||||
# try:
|
||||
# welcome_message = self.sock.receive()
|
||||
# self.connected = True
|
||||
# except ConnectionResetError as conn_reset:
|
||||
# if tries > max_retries:
|
||||
# raise conn_reset
|
||||
# tries += 1
|
||||
# time.sleep(2)
|
||||
# except ConnectionRefusedError as conn_error:
|
||||
# logger.error("Failed to open a connection to RTLamNI.")
|
||||
# raise RtCommunicationError from conn_error
|
||||
|
||||
# else:
|
||||
# logger.info("The connection has already been established.")
|
||||
# # warnings.warn(f"The connection has already been established.", stacklevel=2)
|
||||
super().on()
|
||||
# self._update_flyer_device_info()
|
||||
|
||||
def set_axis(self, axis: Device, axis_nr: int) -> None:
|
||||
"""Assign an axis to a device instance.
|
||||
|
||||
Args:
|
||||
axis (Device): Device instance (e.g. GalilMotor)
|
||||
axis_nr (int): Controller axis number
|
||||
|
||||
"""
|
||||
self._axis[axis_nr] = axis
|
||||
|
||||
@threadlocked
|
||||
def socket_put(self, val: str) -> None:
|
||||
self.sock.put(f"{val}\n".encode())
|
||||
|
||||
@threadlocked
|
||||
def socket_get(self) -> str:
|
||||
return self.sock.receive().decode()
|
||||
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def socket_put_and_receive(self, val: str, remove_trailing_chars=True) -> str:
|
||||
self.socket_put(val)
|
||||
if remove_trailing_chars:
|
||||
return self._remove_trailing_characters(self.sock.receive().decode())
|
||||
return self.socket_get()
|
||||
|
||||
def is_axis_moving(self, axis_Id) -> bool:
|
||||
# this checks that axis is on target
|
||||
axis_is_on_target = bool(float(self.socket_put_and_receive(f"o")))
|
||||
return not axis_is_on_target
|
||||
|
||||
# def is_thread_active(self, thread_id: int) -> bool:
|
||||
# val = float(self.socket_put_and_receive(f"MG_XQ{thread_id}"))
|
||||
# if val == -1:
|
||||
# return False
|
||||
# return True
|
||||
|
||||
def _remove_trailing_characters(self, var) -> str:
|
||||
if len(var) > 1:
|
||||
return var.split("\r\n")[0]
|
||||
return var
|
||||
|
||||
@threadlocked
|
||||
def set_rotation_angle(self, val: float):
|
||||
self.socket_put(f"a{(val-300+30.538)/180*np.pi}")
|
||||
|
||||
@threadlocked
|
||||
def stop_all_axes(self):
|
||||
self.socket_put("sc")
|
||||
|
||||
@threadlocked
|
||||
def feedback_disable(self):
|
||||
self.socket_put("J0")
|
||||
logger.info("LamNI Feedback disabled.")
|
||||
self.set_device_enabled("lsamx", True)
|
||||
self.set_device_enabled("lsamy", True)
|
||||
self.set_device_enabled("loptx", True)
|
||||
self.set_device_enabled("lopty", True)
|
||||
self.set_device_enabled("loptz", True)
|
||||
|
||||
@threadlocked
|
||||
def _set_axis_velocity(self, um_per_s):
|
||||
self.socket_put(f"V{um_per_s}")
|
||||
|
||||
@threadlocked
|
||||
def _set_axis_velocity_maximum_speed(self):
|
||||
self.socket_put(f"V0")
|
||||
|
||||
# for developement of soft continuous scanning
|
||||
@threadlocked
|
||||
def _position_sampling_single_reset_and_start_sampling(self):
|
||||
self.socket_put(f"Ss")
|
||||
|
||||
@threadlocked
|
||||
def _position_sampling_single_read(self):
|
||||
(number_of_samples, sum0, sum0_2, sum1, sum1_2, sum2, sum2_2) = self.socket_put_and_receive(
|
||||
f"Sr"
|
||||
).split(",")
|
||||
avg_x = float(sum1) / int(number_of_samples)
|
||||
avg_y = float(sum0) / int(number_of_samples)
|
||||
stdev_x = np.sqrt(
|
||||
float(sum1_2) / int(number_of_samples)
|
||||
- np.power(float(sum1) / int(number_of_samples), 2)
|
||||
)
|
||||
stdev_y = np.sqrt(
|
||||
float(sum0_2) / int(number_of_samples)
|
||||
- np.power(float(sum0) / int(number_of_samples), 2)
|
||||
)
|
||||
return (avg_x, avg_y, stdev_x, stdev_y)
|
||||
|
||||
@threadlocked
|
||||
def feedback_enable_without_reset(self):
|
||||
# read current interferometer position
|
||||
return_table = (self.socket_put_and_receive(f"J4")).split(",")
|
||||
x_curr = float(return_table[2])
|
||||
y_curr = float(return_table[1])
|
||||
# set these as closed loop target position
|
||||
self.socket_put(f"pa0,{x_curr:.4f}")
|
||||
self.socket_put(f"pa1,{y_curr:.4f}")
|
||||
self.get_device_manager().devices.rtx.obj.user_setpoint.set_with_feedback_disabled(x_curr)
|
||||
self.get_device_manager().devices.rty.obj.user_setpoint.set_with_feedback_disabled(y_curr)
|
||||
self.socket_put("J5")
|
||||
logger.info("LamNI Feedback enabled (without reset).")
|
||||
self.set_device_enabled("lsamx", False)
|
||||
self.set_device_enabled("lsamy", False)
|
||||
self.set_device_enabled("loptx", False)
|
||||
self.set_device_enabled("lopty", False)
|
||||
self.set_device_enabled("loptz", False)
|
||||
|
||||
@threadlocked
|
||||
def feedback_disable_and_even_reset_lamni_angle_interferometer(self):
|
||||
self.socket_put("J6")
|
||||
logger.info("LamNI Feedback disabled including the angular interferometer.")
|
||||
self.set_device_enabled("lsamx", True)
|
||||
self.set_device_enabled("lsamy", True)
|
||||
self.set_device_enabled("loptx", True)
|
||||
self.set_device_enabled("lopty", True)
|
||||
self.set_device_enabled("loptz", True)
|
||||
|
||||
def get_device_manager(self):
|
||||
for axis in self._axis:
|
||||
if hasattr(axis, "device_manager") and axis.device_manager:
|
||||
return axis.device_manager
|
||||
raise BECConfigError("Could not access the device_manager")
|
||||
|
||||
def get_axis_by_name(self, name):
|
||||
for axis in self._axis:
|
||||
if axis:
|
||||
if axis.name == name:
|
||||
return axis
|
||||
raise RuntimeError(f"Could not find an axis with name {name}")
|
||||
|
||||
@threadlocked
|
||||
def clear_trajectory_generator(self):
|
||||
self.socket_put("sc")
|
||||
logger.info("LamNI scan stopped and deleted, moving to start position")
|
||||
|
||||
def add_pos_to_scan(self, positions) -> None:
|
||||
def send_positions(parent, positions):
|
||||
parent._min_scan_buffer_reached = False
|
||||
for pos_index, pos in enumerate(positions):
|
||||
parent.socket_put_and_receive(f"s{pos[0]},{pos[1]},0")
|
||||
if pos_index > 100:
|
||||
parent._min_scan_buffer_reached = True
|
||||
parent._min_scan_buffer_reached = True
|
||||
|
||||
threading.Thread(target=send_positions, args=(self, positions), daemon=True).start()
|
||||
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def get_scan_status(self):
|
||||
return_table = (self.socket_put_and_receive(f"sr")).split(",")
|
||||
if len(return_table) != 3:
|
||||
raise RtCommunicationError(
|
||||
f"Expected to receive 3 return values. Instead received {return_table}"
|
||||
)
|
||||
mode = int(return_table[0])
|
||||
# mode 0: direct positioning
|
||||
# mode 1: running internal timer (not tested/used anymore)
|
||||
# mode 2: rt point scan running
|
||||
# mode 3: rt point scan starting
|
||||
# mode 5/6: rt continuous scanning (not available in LamNI)
|
||||
number_of_positions_planned = int(return_table[1])
|
||||
current_position_in_scan = int(return_table[2])
|
||||
return (mode, number_of_positions_planned, current_position_in_scan)
|
||||
|
||||
@threadlocked
|
||||
def start_scan(self):
|
||||
interferometer_feedback_not_running = int((self.socket_put_and_receive("J2")).split(",")[0])
|
||||
if interferometer_feedback_not_running == 1:
|
||||
logger.error(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
raise RtError(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
# here exception
|
||||
(mode, number_of_positions_planned, current_position_in_scan) = self.get_scan_status()
|
||||
|
||||
if number_of_positions_planned == 0:
|
||||
logger.error("Cannot start scan because no target positions are planned.")
|
||||
raise RtError("Cannot start scan because no target positions are planned.")
|
||||
# hier exception
|
||||
# start a point-by-point scan (for cont scan in flomni it would be "sa")
|
||||
self.socket_put_and_receive("sd")
|
||||
|
||||
def start_readout(self):
|
||||
readout = threading.Thread(target=self.read_positions_from_sampler)
|
||||
readout.start()
|
||||
|
||||
def _update_flyer_device_info(self):
|
||||
flyer_info = self._get_flyer_device_info()
|
||||
self.get_device_manager().connector.set(
|
||||
MessageEndpoints.device_info("rt_scan"),
|
||||
messages.DeviceInfoMessage(device="rt_scan", info=flyer_info).dumps(),
|
||||
)
|
||||
|
||||
def _get_flyer_device_info(self) -> dict:
|
||||
return {
|
||||
"device_name": self.name,
|
||||
"device_attr_name": getattr(self, "attr_name", ""),
|
||||
"device_dotted_name": getattr(self, "dotted_name", ""),
|
||||
"device_info": {
|
||||
"device_base_class": "ophydobject",
|
||||
"signals": [],
|
||||
"hints": {"fields": ["average_x_st_fzp", "average_y_st_fzp"]},
|
||||
"describe": {},
|
||||
"describe_configuration": {},
|
||||
"sub_devices": [],
|
||||
"custom_user_access": [],
|
||||
},
|
||||
}
|
||||
|
||||
def kickoff(self, metadata):
|
||||
self.readout_metadata = metadata
|
||||
while not self._min_scan_buffer_reached:
|
||||
time.sleep(0.001)
|
||||
self.start_scan()
|
||||
time.sleep(0.1)
|
||||
self.start_readout()
|
||||
|
||||
def _get_signals_from_table(self, return_table) -> dict:
|
||||
self.average_stdeviations_x_st_fzp += float(return_table[5])
|
||||
self.average_stdeviations_y_st_fzp += float(return_table[8])
|
||||
self.average_lamni_angle += float(return_table[19])
|
||||
signals = {
|
||||
"target_x": {"value": float(return_table[3])},
|
||||
"average_x_st_fzp": {"value": float(return_table[4])},
|
||||
"stdev_x_st_fzp": {"value": float(return_table[5])},
|
||||
"target_y": {"value": float(return_table[6])},
|
||||
"average_y_st_fzp": {"value": float(return_table[7])},
|
||||
"stdev_y_st_fzp": {"value": float(return_table[8])},
|
||||
"average_cap1": {"value": float(return_table[9])},
|
||||
"stdev_cap1": {"value": float(return_table[10])},
|
||||
"average_cap2": {"value": float(return_table[11])},
|
||||
"stdev_cap2": {"value": float(return_table[12])},
|
||||
"average_cap3": {"value": float(return_table[13])},
|
||||
"stdev_cap3": {"value": float(return_table[14])},
|
||||
"average_cap4": {"value": float(return_table[15])},
|
||||
"stdev_cap4": {"value": float(return_table[16])},
|
||||
"average_cap5": {"value": float(return_table[17])},
|
||||
"stdev_cap5": {"value": float(return_table[18])},
|
||||
"average_angle_interf_ST": {"value": float(return_table[19])},
|
||||
"stdev_angle_interf_ST": {"value": float(return_table[20])},
|
||||
"average_stdeviations_x_st_fzp": {
|
||||
"value": self.average_stdeviations_x_st_fzp / (int(return_table[0]) + 1)
|
||||
},
|
||||
"average_stdeviations_y_st_fzp": {
|
||||
"value": self.average_stdeviations_y_st_fzp / (int(return_table[0]) + 1)
|
||||
},
|
||||
"average_lamni_angle": {"value": self.average_lamni_angle / (int(return_table[0]) + 1)},
|
||||
}
|
||||
return signals
|
||||
|
||||
def read_positions_from_sampler(self):
|
||||
# this was for reading after the scan completed
|
||||
number_of_samples_to_read = 1 # self.get_scan_status()[1] #number of valid samples, will be updated upon first data read
|
||||
|
||||
read_counter = 0
|
||||
previous_point_in_scan = 0
|
||||
|
||||
self.average_stdeviations_x_st_fzp = 0
|
||||
self.average_stdeviations_y_st_fzp = 0
|
||||
self.average_lamni_angle = 0
|
||||
|
||||
mode, number_of_positions_planned, current_position_in_scan = self.get_scan_status()
|
||||
|
||||
# if not (mode==2 or mode==3):
|
||||
# error
|
||||
self.get_device_manager().connector.set(
|
||||
MessageEndpoints.device_status("rt_scan"),
|
||||
messages.DeviceStatusMessage(
|
||||
device="rt_scan", status=1, metadata=self.readout_metadata
|
||||
).dumps(),
|
||||
)
|
||||
# while scan is running
|
||||
while mode > 0:
|
||||
# logger.info(f"Current scan position {current_position_in_scan} out of {number_of_positions_planned}")
|
||||
mode, number_of_positions_planned, current_position_in_scan = self.get_scan_status()
|
||||
time.sleep(0.01)
|
||||
if current_position_in_scan > 5:
|
||||
while current_position_in_scan > read_counter + 1:
|
||||
return_table = (self.socket_put_and_receive(f"r{read_counter}")).split(",")
|
||||
# logger.info(f"{return_table}")
|
||||
logger.info(f"Read {read_counter} out of {number_of_positions_planned}")
|
||||
|
||||
read_counter = read_counter + 1
|
||||
|
||||
signals = self._get_signals_from_table(return_table)
|
||||
|
||||
self.publish_device_data(signals=signals, point_id=int(return_table[0]))
|
||||
|
||||
time.sleep(0.05)
|
||||
|
||||
# read the last samples even though scan is finished already
|
||||
while number_of_positions_planned > read_counter:
|
||||
return_table = (self.socket_put_and_receive(f"r{read_counter}")).split(",")
|
||||
logger.info(f"Read {read_counter} out of {number_of_positions_planned}")
|
||||
# logger.info(f"{return_table}")
|
||||
read_counter = read_counter + 1
|
||||
|
||||
signals = self._get_signals_from_table(return_table)
|
||||
self.publish_device_data(signals=signals, point_id=int(return_table[0]))
|
||||
|
||||
self.get_device_manager().connector.set(
|
||||
MessageEndpoints.device_status("rt_scan"),
|
||||
messages.DeviceStatusMessage(
|
||||
device="rt_scan", status=0, metadata=self.readout_metadata
|
||||
).dumps(),
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"LamNI statistics: Average of all standard deviations: x {self.average_stdeviations_x_st_fzp/number_of_samples_to_read}, y {self.average_stdeviations_y_st_fzp/number_of_samples_to_read}, angle {self.average_lamni_angle/number_of_samples_to_read}."
|
||||
)
|
||||
|
||||
def publish_device_data(self, signals, point_id):
|
||||
self.get_device_manager().connector.set_and_publish(
|
||||
MessageEndpoints.device_read("rt_lamni"),
|
||||
messages.DeviceMessage(
|
||||
signals=signals, metadata={"point_id": point_id, **self.readout_metadata}
|
||||
).dumps(),
|
||||
)
|
||||
|
||||
def feedback_status_angle_lamni(self) -> bool:
|
||||
return_table = (self.socket_put_and_receive(f"J7")).split(",")
|
||||
logger.debug(
|
||||
f"LamNI angle interferomter status {bool(return_table[0])}, position {float(return_table[1])}, signal {float(return_table[2])}"
|
||||
)
|
||||
return bool(return_table[0])
|
||||
|
||||
def feedback_enable_with_reset(self):
|
||||
if not self.feedback_status_angle_lamni():
|
||||
self.feedback_disable_and_even_reset_lamni_angle_interferometer()
|
||||
logger.info(f"LamNI resetting interferometer inclusive angular interferomter.")
|
||||
else:
|
||||
self.feedback_disable()
|
||||
logger.info(
|
||||
f"LamNI resetting interferomter except angular interferometer which is already running."
|
||||
)
|
||||
|
||||
# set these as closed loop target position
|
||||
|
||||
self.socket_put(f"pa0,0")
|
||||
self.get_axis_by_name("rtx").user_setpoint.setpoint = 0
|
||||
self.socket_put(f"pa1,0")
|
||||
self.get_axis_by_name("rty").user_setpoint.setpoint = 0
|
||||
self.socket_put(
|
||||
f"pa2,0"
|
||||
) # we set all three outputs of the traj. gen. although in LamNI case only 0,1 are used
|
||||
self.clear_trajectory_generator()
|
||||
|
||||
self.get_device_manager().devices.lsamrot.obj.move(0, wait=True)
|
||||
|
||||
galil_controller_rt_status = (
|
||||
self.get_device_manager().devices.lsamx.obj.controller.lgalil_is_air_off_and_orchestra_enabled()
|
||||
)
|
||||
|
||||
if galil_controller_rt_status == 0:
|
||||
logger.error(
|
||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
||||
)
|
||||
raise RtError(
|
||||
"Cannot enable feedback. The small rotation air is on and/or orchestra disabled by the motor controller."
|
||||
)
|
||||
|
||||
time.sleep(0.03)
|
||||
|
||||
lsamx_user_params = self.get_device_manager().devices.lsamx.user_parameter
|
||||
if lsamx_user_params is None or lsamx_user_params.get("center") is None:
|
||||
raise RuntimeError("lsamx center is not defined")
|
||||
lsamy_user_params = self.get_device_manager().devices.lsamy.user_parameter
|
||||
if lsamy_user_params is None or lsamy_user_params.get("center") is None:
|
||||
raise RuntimeError("lsamy center is not defined")
|
||||
lsamx_center = lsamx_user_params.get("center")
|
||||
lsamy_center = lsamy_user_params.get("center")
|
||||
self.get_device_manager().devices.lsamx.obj.move(lsamx_center, wait=True)
|
||||
self.get_device_manager().devices.lsamy.obj.move(lsamy_center, wait=True)
|
||||
self.socket_put("J1")
|
||||
|
||||
_waitforfeedbackctr = 0
|
||||
|
||||
interferometer_feedback_not_running = int((self.socket_put_and_receive("J2")).split(",")[0])
|
||||
|
||||
while interferometer_feedback_not_running == 1 and _waitforfeedbackctr < 100:
|
||||
time.sleep(0.01)
|
||||
_waitforfeedbackctr = _waitforfeedbackctr + 1
|
||||
interferometer_feedback_not_running = int(
|
||||
(self.socket_put_and_receive("J2")).split(",")[0]
|
||||
)
|
||||
|
||||
self.set_device_enabled("lsamx", False)
|
||||
self.set_device_enabled("lsamy", False)
|
||||
self.set_device_enabled("loptx", False)
|
||||
self.set_device_enabled("lopty", False)
|
||||
self.set_device_enabled("loptz", False)
|
||||
|
||||
if interferometer_feedback_not_running == 1:
|
||||
logger.error(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
raise RtError(
|
||||
"Cannot start scan because feedback loop is not running or there is an interferometer error."
|
||||
)
|
||||
|
||||
time.sleep(0.01)
|
||||
|
||||
# ptychography_alignment_done = 0
|
||||
|
||||
def set_device_enabled(self, device_name: str, enabled: bool) -> None:
|
||||
"""enable / disable a device"""
|
||||
if device_name not in self.get_device_manager().devices:
|
||||
logger.warning(
|
||||
f"Device {device_name} is not configured and cannot be enabled/disabled."
|
||||
)
|
||||
return
|
||||
self.get_device_manager().devices[device_name].read_only = not enabled
|
||||
|
||||
|
||||
class RtSignalBase(SocketSignal):
|
||||
def __init__(self, signal_name, **kwargs):
|
||||
self.signal_name = signal_name
|
||||
super().__init__(**kwargs)
|
||||
self.controller = self.parent.controller
|
||||
self.sock = self.parent.controller.sock
|
||||
|
||||
|
||||
class RtSignalRO(RtSignalBase):
|
||||
def __init__(self, signal_name, **kwargs):
|
||||
super().__init__(signal_name, **kwargs)
|
||||
self._metadata["write_access"] = False
|
||||
|
||||
def _socket_set(self, val):
|
||||
raise ReadOnlyError("Read-only signals cannot be set")
|
||||
|
||||
|
||||
class RtReadbackSignal(RtSignalRO):
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def _socket_get(self) -> float:
|
||||
"""Get command for the readback signal
|
||||
|
||||
Returns:
|
||||
float: Readback value after adjusting for sign and motor resolution.
|
||||
"""
|
||||
return_table = (self.controller.socket_put_and_receive(f"J4")).split(",")
|
||||
print(return_table)
|
||||
if self.parent.axis_Id_numeric == 0:
|
||||
readback_index = 2
|
||||
elif self.parent.axis_Id_numeric == 1:
|
||||
readback_index = 1
|
||||
else:
|
||||
raise RtError("Currently, only two axes are supported.")
|
||||
|
||||
current_pos = float(return_table[readback_index])
|
||||
|
||||
current_pos *= self.parent.sign
|
||||
return current_pos
|
||||
|
||||
|
||||
class RtSetpointSignal(RtSignalBase):
|
||||
setpoint = 0
|
||||
|
||||
def _socket_get(self) -> float:
|
||||
"""Get command for receiving the setpoint / target value.
|
||||
The value is not pulled from the controller but instead just the last setpoint used.
|
||||
|
||||
Returns:
|
||||
float: setpoint / target value
|
||||
"""
|
||||
return self.setpoint
|
||||
|
||||
@retry_once
|
||||
@threadlocked
|
||||
def _socket_set(self, val: float) -> None:
|
||||
"""Set a new target value / setpoint value. Before submission, the target value is adjusted for the axis' sign.
|
||||
Furthermore, it is ensured that all axes are referenced before a new setpoint is submitted.
|
||||
|
||||
Args:
|
||||
val (float): Target value / setpoint value
|
||||
|
||||
Raises:
|
||||
RtError: Raised if interferometer feedback is disabled.
|
||||
|
||||
"""
|
||||
interferometer_feedback_not_running = int(
|
||||
(self.controller.socket_put_and_receive("J2")).split(",")[0]
|
||||
)
|
||||
if interferometer_feedback_not_running != 0:
|
||||
raise RtError(
|
||||
"The interferometer feedback is not running. Either it is turned off or and interferometer error occured."
|
||||
)
|
||||
self.set_with_feedback_disabled(val)
|
||||
|
||||
def set_with_feedback_disabled(self, val):
|
||||
target_val = val * self.parent.sign
|
||||
self.setpoint = target_val
|
||||
self.controller.socket_put(f"pa{self.parent.axis_Id_numeric},{target_val:.4f}")
|
||||
|
||||
|
||||
class RtMotorIsMoving(RtSignalRO):
|
||||
def _socket_get(self):
|
||||
return self.controller.is_axis_moving(self.parent.axis_Id_numeric)
|
||||
|
||||
def get(self):
|
||||
val = super().get()
|
||||
if val is not None:
|
||||
self._run_subs(sub_type=self.SUB_VALUE, value=val, timestamp=time.time())
|
||||
return val
|
||||
|
||||
|
||||
class RtFeedbackRunning(RtSignalRO):
|
||||
@threadlocked
|
||||
def _socket_get(self):
|
||||
if int((self.controller.socket_put_and_receive("J2")).split(",")[0]) == 0:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
class RtMotor(Device, PositionerBase):
|
||||
USER_ACCESS = ["controller"]
|
||||
readback = Cpt(RtReadbackSignal, signal_name="readback", kind="hinted")
|
||||
user_setpoint = Cpt(RtSetpointSignal, signal_name="setpoint")
|
||||
|
||||
motor_is_moving = Cpt(RtMotorIsMoving, signal_name="motor_is_moving", kind="normal")
|
||||
high_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||
low_limit_travel = Cpt(Signal, value=0, kind="omitted")
|
||||
|
||||
SUB_READBACK = "readback"
|
||||
SUB_CONNECTION_CHANGE = "connection_change"
|
||||
_default_sub = SUB_READBACK
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
axis_Id,
|
||||
prefix="",
|
||||
*,
|
||||
name,
|
||||
kind=None,
|
||||
read_attrs=None,
|
||||
configuration_attrs=None,
|
||||
parent=None,
|
||||
host="mpc2680.psi.ch",
|
||||
port=3333,
|
||||
sign=1,
|
||||
socket_cls=SocketIO,
|
||||
device_manager=None,
|
||||
limits=None,
|
||||
**kwargs,
|
||||
):
|
||||
self.axis_Id = axis_Id
|
||||
self.sign = sign
|
||||
self.controller = RtController(socket=socket_cls(host=host, port=port))
|
||||
self.controller.set_axis(axis=self, axis_nr=self.axis_Id_numeric)
|
||||
self.device_manager = device_manager
|
||||
self.tolerance = kwargs.pop("tolerance", 0.5)
|
||||
|
||||
super().__init__(
|
||||
prefix,
|
||||
name=name,
|
||||
kind=kind,
|
||||
read_attrs=read_attrs,
|
||||
configuration_attrs=configuration_attrs,
|
||||
parent=parent,
|
||||
**kwargs,
|
||||
)
|
||||
self.readback.name = self.name
|
||||
self.controller.subscribe(
|
||||
self._update_connection_state, event_type=self.SUB_CONNECTION_CHANGE
|
||||
)
|
||||
self._update_connection_state()
|
||||
|
||||
# self.readback.subscribe(self._forward_readback, event_type=self.readback.SUB_VALUE)
|
||||
if limits is not None:
|
||||
assert len(limits) == 2
|
||||
self.low_limit_travel.put(limits[0])
|
||||
self.high_limit_travel.put(limits[1])
|
||||
|
||||
@property
|
||||
def limits(self):
|
||||
return (self.low_limit_travel.get(), self.high_limit_travel.get())
|
||||
|
||||
@property
|
||||
def low_limit(self):
|
||||
return self.limits[0]
|
||||
|
||||
@property
|
||||
def high_limit(self):
|
||||
return self.limits[1]
|
||||
|
||||
def check_value(self, pos):
|
||||
"""Check that the position is within the soft limits"""
|
||||
low_limit, high_limit = self.limits
|
||||
|
||||
if low_limit < high_limit and not (low_limit <= pos <= high_limit):
|
||||
raise LimitError(f"position={pos} not within limits {self.limits}")
|
||||
|
||||
def _update_connection_state(self, **kwargs):
|
||||
for walk in self.walk_signals():
|
||||
walk.item._metadata["connected"] = self.controller.connected
|
||||
|
||||
def _forward_readback(self, **kwargs):
|
||||
kwargs.pop("sub_type")
|
||||
self._run_subs(sub_type="readback", **kwargs)
|
||||
|
||||
@raise_if_disconnected
|
||||
def move(self, position, wait=True, **kwargs):
|
||||
"""Move to a specified position, optionally waiting for motion to
|
||||
complete.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
position
|
||||
Position to move to
|
||||
moved_cb : callable
|
||||
Call this callback when movement has finished. This callback must
|
||||
accept one keyword argument: 'obj' which will be set to this
|
||||
positioner instance.
|
||||
timeout : float, optional
|
||||
Maximum time to wait for the motion. If None, the default timeout
|
||||
for this positioner is used.
|
||||
|
||||
Returns
|
||||
-------
|
||||
status : MoveStatus
|
||||
|
||||
Raises
|
||||
------
|
||||
TimeoutError
|
||||
When motion takes longer than `timeout`
|
||||
ValueError
|
||||
On invalid positions
|
||||
RuntimeError
|
||||
If motion fails other than timing out
|
||||
"""
|
||||
self._started_moving = False
|
||||
timeout = kwargs.pop("timeout", 100)
|
||||
status = super().move(position, timeout=timeout, **kwargs)
|
||||
self.user_setpoint.put(position, wait=False)
|
||||
|
||||
def move_and_finish():
|
||||
while self.motor_is_moving.get():
|
||||
print("motor is moving")
|
||||
val = self.readback.read()
|
||||
self._run_subs(sub_type=self.SUB_READBACK, value=val, timestamp=time.time())
|
||||
time.sleep(0.01)
|
||||
print("Move finished")
|
||||
self._done_moving()
|
||||
|
||||
threading.Thread(target=move_and_finish, daemon=True).start()
|
||||
try:
|
||||
if wait:
|
||||
status_wait(status)
|
||||
except KeyboardInterrupt:
|
||||
self.stop()
|
||||
raise
|
||||
|
||||
return status
|
||||
|
||||
@property
|
||||
def axis_Id(self):
|
||||
return self._axis_Id_alpha
|
||||
|
||||
@axis_Id.setter
|
||||
def axis_Id(self, val):
|
||||
if isinstance(val, str):
|
||||
if len(val) != 1:
|
||||
raise ValueError(f"Only single-character axis_Ids are supported.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = ord(val.lower()) - 97
|
||||
else:
|
||||
raise TypeError(f"Expected value of type str but received {type(val)}")
|
||||
|
||||
@property
|
||||
def axis_Id_numeric(self):
|
||||
return self._axis_Id_numeric
|
||||
|
||||
@axis_Id_numeric.setter
|
||||
def axis_Id_numeric(self, val):
|
||||
if isinstance(val, int):
|
||||
if val > 26:
|
||||
raise ValueError(f"Numeric value exceeds supported range.")
|
||||
self._axis_Id_alpha = val
|
||||
self._axis_Id_numeric = (chr(val + 97)).capitalize()
|
||||
else:
|
||||
raise TypeError(f"Expected value of type int but received {type(val)}")
|
||||
|
||||
def kickoff(self, metadata, **kwargs) -> None:
|
||||
self.controller.kickoff(metadata)
|
||||
|
||||
@property
|
||||
def egu(self):
|
||||
"""The engineering units (EGU) for positions"""
|
||||
return "um"
|
||||
|
||||
# how is this used later?
|
||||
|
||||
def stage(self) -> List[object]:
|
||||
return super().stage()
|
||||
|
||||
def unstage(self) -> List[object]:
|
||||
return super().unstage()
|
||||
|
||||
def stop(self, *, success=False):
|
||||
self.controller.stop_all_axes()
|
||||
return super().stop(success=success)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
mock = False
|
||||
if not mock:
|
||||
rty = RtLamniMotor("B", name="rty", host="mpc2680.psi.ch", port=3333, sign=1)
|
||||
rty.stage()
|
||||
status = rty.move(0, wait=True)
|
||||
status = rty.move(10, wait=True)
|
||||
rty.read()
|
||||
|
||||
rty.get()
|
||||
rty.describe()
|
||||
|
||||
rty.unstage()
|
||||
else:
|
||||
from ophyd_devices.utils.socket import SocketMock
|
||||
|
||||
rtx = RtLamniMotor("A", name="rtx", host="mpc2680.psi.ch", port=3333, socket_cls=SocketMock)
|
||||
rty = RtLamniMotor("B", name="rty", host="mpc2680.psi.ch", port=3333, socket_cls=SocketMock)
|
||||
rtx.stage()
|
||||
# rty.stage()
|
||||
@@ -111,10 +111,6 @@ class SmaractController(Controller):
|
||||
def socket_put(self, val: str):
|
||||
self.sock.put(f":{val}\n".encode())
|
||||
|
||||
@threadlocked
|
||||
def socket_get(self):
|
||||
return self.sock.receive().decode()
|
||||
|
||||
@threadlocked
|
||||
def socket_put_and_receive(
|
||||
self, val: str, remove_trailing_chars=True, check_for_errors=True, raise_if_not_status=False
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any
|
||||
import numpy as np
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bec_lib import DeviceManagerBase
|
||||
from bec_lib.devicemanager import DeviceManagerBase
|
||||
from bec_server.file_writer.file_writer import HDF5Storage
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ but they are executed in a specific order:
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import MessageEndpoints, bec_logger
|
||||
from bec_lib import bec_logger
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.scan_server.errors import ScanAbortion
|
||||
from bec_server.scan_server.scans import RequestBase, ScanArgType, ScanBase
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ but they are executed in a specific order:
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from bec_lib import MessageEndpoints, bec_logger, messages
|
||||
from bec_lib import bec_logger, messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.scan_server.errors import ScanAbortion
|
||||
from bec_server.scan_server.scans import SyncFlyScanBase
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ but they are executed in a specific order:
|
||||
|
||||
import time
|
||||
|
||||
from bec_lib import MessageEndpoints, bec_logger
|
||||
from bec_lib import bec_logger
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.scan_server.scans import AsyncFlyScanBase, ScanAbortion
|
||||
|
||||
logger = bec_logger.logger
|
||||
@@ -32,7 +33,7 @@ class OwisGrid(AsyncFlyScanBase):
|
||||
"""Owis-based grid scan."""
|
||||
|
||||
scan_name = "owis_grid"
|
||||
scan_report_hint = "scan_progress"
|
||||
scan_report_hint = "device_progress"
|
||||
required_kwargs = []
|
||||
arg_input = {}
|
||||
arg_bundle_size = {"bundle": len(arg_input), "min": None, "max": None}
|
||||
@@ -153,11 +154,11 @@ class OwisGrid(AsyncFlyScanBase):
|
||||
if not self.scan_report_hint:
|
||||
yield None
|
||||
return
|
||||
yield from self.stubs.scan_report_instruction({"scan_progress": ["mcs"]})
|
||||
yield from self.stubs.scan_report_instruction({"device_progress": ["mcs"]})
|
||||
|
||||
def pre_scan(self):
|
||||
"""Pre scan instructions, move to start position"""
|
||||
yield from self._move_and_wait([self.start_x, self.start_y])
|
||||
yield from self._move_scan_motors_and_wait([self.start_x, self.start_y])
|
||||
yield from self.stubs.pre_scan()
|
||||
|
||||
def scan_progress(self) -> int:
|
||||
@@ -307,3 +308,11 @@ class OwisGrid(AsyncFlyScanBase):
|
||||
yield from self.stubs.send_rpc_and_wait("samy", "velocity.put", self.high_velocity)
|
||||
yield from self.stubs.send_rpc_and_wait("samy", "acceleration.put", self.high_acc_time)
|
||||
super().finalize()
|
||||
|
||||
def _move_scan_motors_and_wait(self, pos):
|
||||
# TODO: remove this method once BEC MR 637 is merged
|
||||
# pylint: disable=no-member
|
||||
if hasattr(super(), "_move_scan_motors_and_wait"):
|
||||
yield from super()._move_scan_motors_and_wait(pos)
|
||||
else:
|
||||
yield from self._move_and_wait(pos)
|
||||
|
||||
@@ -25,7 +25,8 @@ but they are executed in a specific order:
|
||||
|
||||
# import numpy as np
|
||||
|
||||
# from bec_lib import MessageEndpoints, bec_logger, messages
|
||||
# from bec_lib import bec_logger, messages
|
||||
# from bec_lib.endpoints import MessageEndpoints
|
||||
# from bec_server.scan_server.errors import ScanAbortion
|
||||
# from bec_server.scan_server.scans import FlyScanBase, RequestBase, ScanArgType, ScanBase
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ but they are executed in a specific order:
|
||||
|
||||
import time
|
||||
|
||||
from bec_lib import MessageEndpoints, bec_logger
|
||||
from bec_lib import bec_logger
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.scan_server.scans import AsyncFlyScanBase
|
||||
|
||||
logger = bec_logger.logger
|
||||
@@ -30,7 +31,7 @@ logger = bec_logger.logger
|
||||
|
||||
class SgalilGrid(AsyncFlyScanBase):
|
||||
scan_name = "sgalil_grid"
|
||||
scan_report_hint = "scan_progress"
|
||||
scan_report_hint = "device_progress"
|
||||
required_kwargs = []
|
||||
arg_input = {}
|
||||
arg_bundle_size = {"bundle": len(arg_input), "min": None, "max": None}
|
||||
@@ -96,10 +97,10 @@ class SgalilGrid(AsyncFlyScanBase):
|
||||
if not self.scan_report_hint:
|
||||
yield None
|
||||
return
|
||||
yield from self.stubs.scan_report_instruction({"scan_progress": ["mcs"]})
|
||||
yield from self.stubs.scan_report_instruction({"device_progress": ["mcs"]})
|
||||
|
||||
def pre_scan(self):
|
||||
yield from self._move_and_wait([self.start_x, self.start_y])
|
||||
yield from self._move_scan_motors_and_wait([self.start_x, self.start_y])
|
||||
yield from self.stubs.pre_scan()
|
||||
# TODO move to start position
|
||||
|
||||
@@ -214,3 +215,11 @@ class SgalilGrid(AsyncFlyScanBase):
|
||||
# logger.info('Testing Scan abortion, would have raised here!')
|
||||
# except Exception as exc:
|
||||
# logger.info(f'{exc}')
|
||||
|
||||
def _move_scan_motors_and_wait(self, pos):
|
||||
# TODO: remove this method once BEC MR 637 is merged
|
||||
# pylint: disable=no-member
|
||||
if hasattr(super(), "_move_scan_motors_and_wait"):
|
||||
yield from super()._move_scan_motors_and_wait(pos)
|
||||
else:
|
||||
yield from self._move_and_wait(pos)
|
||||
|
||||
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
34
docs/_templates/custom-class-template.rst
vendored
Normal file
34
docs/_templates/custom-class-template.rst
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
{{ fullname | escape | underline}}
|
||||
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
.. autoclass:: {{ objname }}
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:inherited-members:
|
||||
:special-members: __call__, __add__, __mul__
|
||||
|
||||
{% block methods %}
|
||||
{% if methods %}
|
||||
.. rubric:: {{ _('Methods') }}
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
{% for item in methods %}
|
||||
{%- if not item.startswith('_') %}
|
||||
~{{ name }}.{{ item }}
|
||||
{%- endif -%}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block attributes %}
|
||||
{% if attributes %}
|
||||
.. rubric:: {{ _('Attributes') }}
|
||||
|
||||
.. autosummary::
|
||||
{% for item in attributes %}
|
||||
~{{ name }}.{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
66
docs/_templates/custom-module-template.rst
vendored
Normal file
66
docs/_templates/custom-module-template.rst
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
{{ fullname | escape | underline}}
|
||||
|
||||
.. automodule:: {{ fullname }}
|
||||
|
||||
{% block attributes %}
|
||||
{% if attributes %}
|
||||
.. rubric:: Module attributes
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
{% for item in attributes %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block functions %}
|
||||
{% if functions %}
|
||||
.. rubric:: {{ _('Functions') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:nosignatures:
|
||||
{% for item in functions %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block classes %}
|
||||
{% if classes %}
|
||||
.. rubric:: {{ _('Classes') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:template: custom-class-template.rst
|
||||
:nosignatures:
|
||||
{% for item in classes %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block exceptions %}
|
||||
{% if exceptions %}
|
||||
.. rubric:: {{ _('Exceptions') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
{% for item in exceptions %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block modules %}
|
||||
{% if modules %}
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:template: custom-module-template.rst
|
||||
:recursive:
|
||||
{% for item in modules %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
81
docs/conf.py
Normal file
81
docs/conf.py
Normal file
@@ -0,0 +1,81 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# For the full list of built-in configuration values, see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
import tomli
|
||||
|
||||
project = "cSAXS"
|
||||
copyright = "2023, Paul Scherrer Institute"
|
||||
author = "Paul Scherrer Institute"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
current_path = pathlib.Path(__file__).parent.parent.resolve()
|
||||
version_path = f"{current_path}/pyproject.toml"
|
||||
|
||||
|
||||
def get_version():
|
||||
"""load the version from the version file"""
|
||||
with open(version_path, "r", encoding="utf-8") as file:
|
||||
res = tomli.loads(file.read())
|
||||
return res["project"]["version"]
|
||||
|
||||
|
||||
release = get_version()
|
||||
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.autosummary",
|
||||
# "sphinx.ext.coverage",
|
||||
"sphinx.ext.viewcode",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx_toolbox.collapse",
|
||||
"sphinx_copybutton",
|
||||
"myst_parser",
|
||||
"sphinx_design",
|
||||
]
|
||||
|
||||
myst_enable_extensions = [
|
||||
"amsmath",
|
||||
"attrs_inline",
|
||||
"colon_fence",
|
||||
"deflist",
|
||||
"dollarmath",
|
||||
"fieldlist",
|
||||
"html_admonition",
|
||||
"html_image",
|
||||
"replacements",
|
||||
"smartquotes",
|
||||
"strikethrough",
|
||||
"substitution",
|
||||
"tasklist",
|
||||
]
|
||||
|
||||
autosummary_generate = True # Turn on sphinx.ext.autosummary
|
||||
add_module_names = False # Remove namespaces from class/method signatures
|
||||
autodoc_inherit_docstrings = True # If no docstring, inherit from base class
|
||||
set_type_checking_flag = True # Enable 'expensive' imports for sphinx_autodoc_typehints
|
||||
autoclass_content = "both" # Include both class docstring and __init__
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
language = "Python"
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
html_theme = "pydata_sphinx_theme"
|
||||
html_static_path = ["_static"]
|
||||
html_css_files = ["css/custom.css"]
|
||||
html_logo = "_static/bec.png"
|
||||
html_theme_options = {"show_nav_level": 1, "navbar_align": "content"}
|
||||
11
docs/developer/developer.md
Normal file
11
docs/developer/developer.md
Normal file
@@ -0,0 +1,11 @@
|
||||
(developer)=
|
||||
# Development
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 1
|
||||
hidden: true
|
||||
---
|
||||
reference/
|
||||
```
|
||||
|
||||
10
docs/developer/reference.md
Normal file
10
docs/developer/reference.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## API Reference
|
||||
|
||||
```{eval-rst}
|
||||
.. autosummary::
|
||||
:toctree: _autosummary
|
||||
:template: custom-module-template.rst
|
||||
:recursive:
|
||||
|
||||
csaxs_bec
|
||||
```
|
||||
39
docs/index.md
Normal file
39
docs/index.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# cSAXS documentation
|
||||
|
||||
<br><br>
|
||||
|
||||
````{grid} 3
|
||||
:gutter: 5
|
||||
|
||||
```{grid-item-card} Introduction
|
||||
:link: introduction
|
||||
:link-type: ref
|
||||
|
||||
General information.
|
||||
```
|
||||
|
||||
```{grid-item-card} User
|
||||
:link: user
|
||||
:link-type: ref
|
||||
|
||||
Information for users.
|
||||
```
|
||||
|
||||
```{grid-item-card} Developer
|
||||
:link: developer
|
||||
:link-type: ref
|
||||
|
||||
Information for developers.
|
||||
```
|
||||
````
|
||||
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
numbered: true
|
||||
maxdepth: 1
|
||||
---
|
||||
|
||||
introduction/introduction
|
||||
user/user
|
||||
developer/developer
|
||||
2
docs/introduction/introduction.md
Normal file
2
docs/introduction/introduction.md
Normal file
@@ -0,0 +1,2 @@
|
||||
(introduction)=
|
||||
# Introduction
|
||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.https://www.sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
9
docs/requirements.txt
Normal file
9
docs/requirements.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
sphinx
|
||||
sphinx_copybutton
|
||||
recommonmark
|
||||
sphinx-toolbox
|
||||
pydata-sphinx-theme
|
||||
sphinx-copybutton
|
||||
myst-parser
|
||||
sphinx-design
|
||||
tomli
|
||||
2
docs/user/user.md
Normal file
2
docs/user/user.md
Normal file
@@ -0,0 +1,2 @@
|
||||
(user)=
|
||||
# User
|
||||
@@ -2,9 +2,9 @@
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from ophyd_devices.epics.devices.psi_delay_generator_base import TriggerSource
|
||||
from ophyd_devices.interfaces.base_classes.psi_delay_generator_base import TriggerSource
|
||||
|
||||
from csaxs_bec.devices.epics.devices.delay_generator_csaxs import DDGSetup
|
||||
from csaxs_bec.devices.epics.delay_generator_csaxs import DDGSetup
|
||||
|
||||
|
||||
def patch_dual_pvs(device):
|
||||
|
||||
@@ -4,11 +4,12 @@ from unittest import mock
|
||||
|
||||
import ophyd
|
||||
import pytest
|
||||
from bec_lib import MessageEndpoints, messages
|
||||
from bec_lib import messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.device_server.tests.utils import DMMock
|
||||
from ophyd_devices.tests.utils import MockPV
|
||||
|
||||
from csaxs_bec.devices.epics.devices.eiger9m_csaxs import Eiger9McSAXS
|
||||
from csaxs_bec.devices.epics.eiger9m_csaxs import Eiger9McSAXS
|
||||
|
||||
|
||||
def patch_dual_pvs(device):
|
||||
@@ -29,9 +30,9 @@ def mock_det():
|
||||
dm = DMMock()
|
||||
with mock.patch.object(dm, "connector"):
|
||||
with (
|
||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
||||
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||
mock.patch(
|
||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
),
|
||||
):
|
||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||
@@ -53,22 +54,22 @@ def test_init():
|
||||
dm = DMMock()
|
||||
with mock.patch.object(dm, "connector"):
|
||||
with (
|
||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
||||
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||
mock.patch(
|
||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
),
|
||||
):
|
||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||
mock_cl.get_pv = MockPV
|
||||
with (
|
||||
mock.patch(
|
||||
"csaxs_bec.devices.epics.devices.eiger9m_csaxs.Eiger9MSetup.initialize_default_parameter"
|
||||
"csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9MSetup.initialize_default_parameter"
|
||||
) as mock_default,
|
||||
mock.patch(
|
||||
"csaxs_bec.devices.epics.devices.eiger9m_csaxs.Eiger9MSetup.initialize_detector"
|
||||
"csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9MSetup.initialize_detector"
|
||||
) as mock_init_det,
|
||||
mock.patch(
|
||||
"csaxs_bec.devices.epics.devices.eiger9m_csaxs.Eiger9MSetup.initialize_detector_backend"
|
||||
"csaxs_bec.devices.epics.eiger9m_csaxs.Eiger9MSetup.initialize_detector_backend"
|
||||
) as mock_init_backend,
|
||||
):
|
||||
Eiger9McSAXS(name=name, prefix=prefix, device_manager=dm, sim_mode=sim_mode)
|
||||
@@ -146,7 +147,7 @@ def test_initialize_detector_backend(
|
||||
|
||||
Validation upon checking set values in mocked std_daq instance
|
||||
"""
|
||||
with mock.patch("csaxs_bec.devices.epics.devices.eiger9m_csaxs.StdDaqClient") as mock_std_daq:
|
||||
with mock.patch("csaxs_bec.devices.epics.eiger9m_csaxs.StdDaqClient") as mock_std_daq:
|
||||
instance = mock_std_daq.return_value
|
||||
instance.stop_writer.return_value = None
|
||||
instance.get_status.return_value = daq_status
|
||||
|
||||
@@ -5,11 +5,12 @@ from unittest import mock
|
||||
|
||||
import ophyd
|
||||
import pytest
|
||||
from bec_lib import MessageEndpoints, messages
|
||||
from bec_lib import messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.device_server.tests.utils import DMMock
|
||||
from ophyd_devices.tests.utils import MockPV
|
||||
|
||||
from csaxs_bec.devices.epics.devices.falcon_csaxs import FalconcSAXS, FalconTimeoutError
|
||||
from csaxs_bec.devices.epics.falcon_csaxs import FalconcSAXS, FalconTimeoutError
|
||||
|
||||
|
||||
def patch_dual_pvs(device):
|
||||
@@ -30,9 +31,11 @@ def mock_det():
|
||||
dm = DMMock()
|
||||
with mock.patch.object(dm, "connector"):
|
||||
with (
|
||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter") as filemixin,
|
||||
mock.patch(
|
||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"
|
||||
) as filemixin,
|
||||
mock.patch(
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
) as mock_service_config,
|
||||
):
|
||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||
|
||||
@@ -3,7 +3,7 @@ from unittest import mock
|
||||
import pytest
|
||||
from ophyd_devices.tests.utils import SocketMock
|
||||
|
||||
from csaxs_bec.devices.galil.fupr_ophyd import FuprGalilController, FuprGalilMotor
|
||||
from csaxs_bec.devices.omny.galil.fupr_ophyd import FuprGalilController, FuprGalilMotor
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import copy
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from ophyd_devices.tests.utils import SocketMock
|
||||
|
||||
from csaxs_bec.devices.galil.galil_ophyd import GalilController, GalilMotor
|
||||
from csaxs_bec.devices.omny.galil.lgalil_ophyd import LamniGalilController, LamniGalilMotor
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def leyey():
|
||||
GalilController._reset_controller()
|
||||
leyey_motor = GalilMotor(
|
||||
LamniGalilController._reset_controller()
|
||||
leyey_motor = LamniGalilMotor(
|
||||
"H", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
||||
)
|
||||
leyey_motor.controller.on()
|
||||
@@ -20,8 +21,8 @@ def leyey():
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def leyex():
|
||||
GalilController._reset_controller()
|
||||
leyex_motor = GalilMotor(
|
||||
LamniGalilController._reset_controller()
|
||||
leyex_motor = LamniGalilMotor(
|
||||
"A", name="leyey", host="mpc2680.psi.ch", port=8081, socket_cls=SocketMock
|
||||
)
|
||||
leyex_motor.controller.on()
|
||||
@@ -60,7 +61,7 @@ def test_axis_get(leyey, pos, msg, sign):
|
||||
)
|
||||
def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
||||
leyey.controller.sock.flush_buffer()
|
||||
leyey.controller.sock.buffer_recv = socket_get_messages
|
||||
leyey.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||
leyey.user_setpoint.put(target_pos)
|
||||
assert leyey.controller.sock.buffer_put == socket_put_messages
|
||||
|
||||
@@ -104,7 +105,7 @@ def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
||||
)
|
||||
def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, socket_get_messages):
|
||||
leyex.controller.sock.flush_buffer()
|
||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
||||
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||
leyex.controller.drive_axis_to_limit(axis_nr, direction)
|
||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||
|
||||
@@ -144,6 +145,9 @@ def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, soc
|
||||
)
|
||||
def test_find_reference(leyex, axis_nr, socket_put_messages, socket_get_messages):
|
||||
leyex.controller.sock.flush_buffer()
|
||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
||||
leyex.controller.find_reference(axis_nr)
|
||||
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||
try:
|
||||
leyex.controller.find_reference(axis_nr)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from unittest import mock
|
||||
import copy
|
||||
|
||||
import pytest
|
||||
from ophyd_devices.tests.utils import SocketMock
|
||||
|
||||
from csaxs_bec.devices.galil.fgalil_ophyd import FlomniGalilController, FlomniGalilMotor
|
||||
from csaxs_bec.devices.omny.galil.fgalil_ophyd import FlomniGalilController, FlomniGalilMotor
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
@@ -60,7 +60,7 @@ def test_axis_get(leyey, pos, msg, sign):
|
||||
)
|
||||
def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
||||
leyey.controller.sock.flush_buffer()
|
||||
leyey.controller.sock.buffer_recv = socket_get_messages
|
||||
leyey.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||
leyey.user_setpoint.put(target_pos)
|
||||
assert leyey.controller.sock.buffer_put == socket_put_messages
|
||||
|
||||
@@ -104,7 +104,7 @@ def test_axis_put(leyey, target_pos, socket_put_messages, socket_get_messages):
|
||||
)
|
||||
def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, socket_get_messages):
|
||||
leyex.controller.sock.flush_buffer()
|
||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
||||
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||
leyex.controller.drive_axis_to_limit(axis_nr, direction)
|
||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||
|
||||
@@ -144,7 +144,7 @@ def test_drive_axis_to_limit(leyex, axis_nr, direction, socket_put_messages, soc
|
||||
)
|
||||
def test_find_reference(leyex, axis_nr, socket_put_messages, socket_get_messages):
|
||||
leyex.controller.sock.flush_buffer()
|
||||
leyex.controller.sock.buffer_recv = socket_get_messages
|
||||
leyex.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||
leyex.controller.find_reference(axis_nr)
|
||||
assert leyex.controller.sock.buffer_put == socket_put_messages
|
||||
|
||||
@@ -165,7 +165,7 @@ def test_fosaz_light_curtain_is_triggered(
|
||||
)
|
||||
fosaz.controller.on()
|
||||
fosaz.controller.sock.flush_buffer()
|
||||
fosaz.controller.sock.buffer_recv = socket_get_messages
|
||||
fosaz.controller.sock.buffer_recv = copy.deepcopy(socket_get_messages)
|
||||
assert fosaz.controller.fosaz_light_curtain_is_triggered() == triggered
|
||||
assert fosaz.controller.sock.buffer_put == socket_put_messages
|
||||
fosaz.controller.off()
|
||||
|
||||
@@ -4,11 +4,12 @@ from unittest import mock
|
||||
|
||||
import ophyd
|
||||
import pytest
|
||||
from bec_lib import MessageEndpoints, messages
|
||||
from bec_lib import messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.device_server.tests.utils import DMMock
|
||||
from ophyd_devices.tests.utils import MockPV
|
||||
|
||||
from csaxs_bec.devices.epics.devices.mcs_csaxs import (
|
||||
from csaxs_bec.devices.epics.mcs_csaxs import (
|
||||
MCScSAXS,
|
||||
MCSError,
|
||||
MCSTimeoutError,
|
||||
@@ -35,9 +36,11 @@ def mock_det():
|
||||
dm = DMMock()
|
||||
with mock.patch.object(dm, "connector"):
|
||||
with (
|
||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter") as filemixin,
|
||||
mock.patch(
|
||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"
|
||||
) as filemixin,
|
||||
mock.patch(
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
) as mock_service_config,
|
||||
):
|
||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||
@@ -57,22 +60,22 @@ def test_init():
|
||||
dm = DMMock()
|
||||
with mock.patch.object(dm, "connector"):
|
||||
with (
|
||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
||||
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||
mock.patch(
|
||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
),
|
||||
):
|
||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||
mock_cl.get_pv = MockPV
|
||||
with (
|
||||
mock.patch(
|
||||
"csaxs_bec.devices.epics.devices.mcs_csaxs.MCSSetup.initialize_default_parameter"
|
||||
"csaxs_bec.devices.epics.mcs_csaxs.MCSSetup.initialize_default_parameter"
|
||||
) as mock_default,
|
||||
mock.patch(
|
||||
"csaxs_bec.devices.epics.devices.mcs_csaxs.MCSSetup.initialize_detector"
|
||||
"csaxs_bec.devices.epics.mcs_csaxs.MCSSetup.initialize_detector"
|
||||
) as mock_init_det,
|
||||
mock.patch(
|
||||
"csaxs_bec.devices.epics.devices.mcs_csaxs.MCSSetup.initialize_detector_backend"
|
||||
"csaxs_bec.devices.epics.mcs_csaxs.MCSSetup.initialize_detector_backend"
|
||||
) as mock_init_backend,
|
||||
):
|
||||
MCScSAXS(name=name, prefix=prefix, device_manager=dm, sim_mode=sim_mode)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import copy
|
||||
|
||||
import pytest
|
||||
|
||||
from csaxs_bec.devices.npoint import NPointAxis, NPointController
|
||||
@@ -121,7 +123,12 @@ def test_set_axis_out_of_range():
|
||||
],
|
||||
)
|
||||
def test_hex_list_to_int(in_buffer, byteorder, signed, val):
|
||||
assert NPointController._hex_list_to_int(in_buffer, byteorder=byteorder, signed=signed) == val
|
||||
assert (
|
||||
NPointController._hex_list_to_int(
|
||||
copy.deepcopy(in_buffer), byteorder=byteorder, signed=signed
|
||||
)
|
||||
== val
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
@@ -5,11 +5,12 @@ from unittest import mock
|
||||
|
||||
import ophyd
|
||||
import pytest
|
||||
from bec_lib import MessageEndpoints, messages
|
||||
from bec_lib import messages
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from bec_server.device_server.tests.utils import DMMock
|
||||
from ophyd_devices.tests.utils import MockPV
|
||||
|
||||
from csaxs_bec.devices.epics.devices.pilatus_csaxs import PilatuscSAXS
|
||||
from csaxs_bec.devices.epics.pilatus_csaxs import PilatuscSAXS
|
||||
|
||||
|
||||
def patch_dual_pvs(device):
|
||||
@@ -30,9 +31,9 @@ def mock_det():
|
||||
dm = DMMock()
|
||||
with mock.patch.object(dm, "connector"):
|
||||
with (
|
||||
mock.patch("ophyd_devices.epics.devices.psi_detector_base.FileWriter"),
|
||||
mock.patch("ophyd_devices.interfaces.base_classes.psi_detector_base.FileWriter"),
|
||||
mock.patch(
|
||||
"ophyd_devices.epics.devices.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
"ophyd_devices.interfaces.base_classes.psi_detector_base.PSIDetectorBase._update_service_config"
|
||||
),
|
||||
):
|
||||
with mock.patch.object(ophyd, "cl") as mock_cl:
|
||||
|
||||
@@ -3,12 +3,13 @@ from unittest import mock
|
||||
import pytest
|
||||
from ophyd_devices.tests.utils import SocketMock
|
||||
|
||||
from csaxs_bec.devices.rt_lamni import RtFlomniController, RtFlomniMotor
|
||||
from csaxs_bec.devices.rt_lamni.rt_ophyd import RtError
|
||||
from csaxs_bec.devices.omny.rt import RtFlomniController, RtFlomniMotor
|
||||
from csaxs_bec.devices.omny.rt.rt_ophyd import RtError
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def rt_flomni():
|
||||
RtFlomniController._reset_controller()
|
||||
rt_flomni = RtFlomniController(
|
||||
name="rt_flomni", socket_cls=SocketMock, socket_host="localhost", socket_port=8081
|
||||
)
|
||||
@@ -16,14 +17,21 @@ def rt_flomni():
|
||||
with mock.patch.object(rt_flomni, "sock"):
|
||||
rtx = mock.MagicMock(spec=RtFlomniMotor)
|
||||
rtx.name = "rtx"
|
||||
rtx.axis_Id = "A"
|
||||
rtx.axis_Id_numeric = 0
|
||||
rty = mock.MagicMock(spec=RtFlomniMotor)
|
||||
rty.name = "rty"
|
||||
rty.axis_Id = "B"
|
||||
rty.axis_Id_numeric = 1
|
||||
rtz = mock.MagicMock(spec=RtFlomniMotor)
|
||||
rtz.name = "rtz"
|
||||
rt_flomni.set_axis(rtx, 0)
|
||||
rt_flomni.set_axis(rty, 1)
|
||||
rt_flomni.set_axis(rtz, 2)
|
||||
rtz.axis_Id = "C"
|
||||
rtz.axis_Id_numeric = 2
|
||||
rt_flomni.set_axis(axis=rtx, axis_nr=0)
|
||||
rt_flomni.set_axis(axis=rty, axis_nr=1)
|
||||
rt_flomni.set_axis(axis=rtz, axis_nr=2)
|
||||
yield rt_flomni
|
||||
RtFlomniController._reset_controller()
|
||||
|
||||
|
||||
def test_rt_flomni_move_to_zero(rt_flomni):
|
||||
|
||||
Reference in New Issue
Block a user