Compare commits
1 Commits
feat/add_f
...
fix/socket
| Author | SHA1 | Date | |
|---|---|---|---|
| eae967a04e |
@@ -37,21 +37,6 @@ mcs:
|
||||
readoutPriority: monitored
|
||||
softwareTrigger: false
|
||||
|
||||
|
||||
|
||||
##########################################################################
|
||||
########################### FAST SHUTTER #################################
|
||||
##########################################################################
|
||||
|
||||
fsh:
|
||||
description: Fast shutter manual control and readback
|
||||
deviceClass: csaxs_bec.devices.epics.fast_shutter.cSAXSFastEpicsShutter
|
||||
deviceConfig:
|
||||
prefix: 'X12SA-ES1-TTL:'
|
||||
onFailure: raise
|
||||
enabled: true
|
||||
readoutPriority: monitored
|
||||
|
||||
##########################################################################
|
||||
######################## SMARACT STAGES ##################################
|
||||
##########################################################################
|
||||
@@ -75,7 +60,6 @@ xbpm3x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -22.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -98,7 +82,6 @@ xbpm3y:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -2
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -121,7 +104,6 @@ sl3trxi:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -5.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -144,7 +126,6 @@ sl3trxo:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 6
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -167,7 +148,6 @@ sl3trxb:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -5.8
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -190,7 +170,6 @@ sl3trxt:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 5.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -213,7 +192,6 @@ fast_shutter_n1_x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -7
|
||||
in: 0
|
||||
@@ -237,7 +215,6 @@ fast_shutter_o1_x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -15.8
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -260,7 +237,6 @@ fast_shutter_o2_x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -15.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -283,7 +259,6 @@ filter_array_1_x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 25
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -306,7 +281,6 @@ filter_array_2_x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 25.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -329,7 +303,6 @@ filter_array_3_x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 25.8
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -352,7 +325,6 @@ filter_array_4_x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 25
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -375,7 +347,6 @@ sl4trxi:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -5.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -398,7 +369,6 @@ sl4trxo:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 6
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -421,7 +391,6 @@ sl4trxb:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -5.8
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -444,7 +413,6 @@ sl4trxt:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 5.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -457,7 +425,7 @@ sl5trxi:
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: C
|
||||
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 200
|
||||
@@ -469,7 +437,6 @@ sl5trxi:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -6
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -480,7 +447,7 @@ sl5trxo:
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: D
|
||||
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 200
|
||||
@@ -492,7 +459,6 @@ sl5trxo:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 5.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -503,7 +469,7 @@ sl5trxb:
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: E
|
||||
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 200
|
||||
@@ -515,7 +481,6 @@ sl5trxb:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -5.5
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -526,7 +491,7 @@ sl5trxt:
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: F
|
||||
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 200
|
||||
@@ -538,7 +503,6 @@ sl5trxt:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 6
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -549,7 +513,7 @@ xbimtrx:
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: A
|
||||
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 200
|
||||
@@ -561,7 +525,6 @@ xbimtrx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: -14.7
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
@@ -572,7 +535,7 @@ xbimtry:
|
||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||
deviceConfig:
|
||||
axis_Id: B
|
||||
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
||||
limits:
|
||||
- -200
|
||||
- 200
|
||||
@@ -584,7 +547,6 @@ xbimtry:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
init_position: 0
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
|
||||
@@ -89,7 +89,6 @@ xbpm2x:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
bl_smar_stage: 0
|
||||
@@ -109,7 +108,6 @@ xbpm2y:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
bl_smar_stage: 1
|
||||
@@ -129,7 +127,6 @@ cu_foilx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
bl_smar_stage: 2
|
||||
@@ -149,7 +146,6 @@ scinx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||
bl_smar_stage: 3
|
||||
|
||||
@@ -17,7 +17,6 @@ feyex:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -16.267
|
||||
out: -1
|
||||
@@ -36,7 +35,6 @@ feyey:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -10.467
|
||||
fheater:
|
||||
@@ -54,7 +52,6 @@ fheater:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
foptx:
|
||||
description: Optics X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
@@ -70,7 +67,6 @@ foptx:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -13.761
|
||||
fopty:
|
||||
@@ -88,7 +84,6 @@ fopty:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0.552
|
||||
out: 0.752
|
||||
@@ -107,7 +102,6 @@ foptz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 23
|
||||
fsamroy:
|
||||
@@ -125,7 +119,6 @@ fsamroy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
fsamx:
|
||||
description: Sample coarse X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
@@ -141,7 +134,6 @@ fsamx:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -1.1
|
||||
fsamy:
|
||||
@@ -159,7 +151,6 @@ fsamy:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 2.75
|
||||
ftracky:
|
||||
@@ -177,7 +168,6 @@ ftracky:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
ftrackz:
|
||||
description: Laser Tracker coarse Z
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
@@ -193,7 +183,6 @@ ftrackz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
ftransx:
|
||||
description: Sample transer X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
@@ -209,7 +198,6 @@ ftransx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
ftransy:
|
||||
description: Sample transer Y
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
@@ -225,7 +213,6 @@ ftransy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
sensor_voltage: -2.4
|
||||
ftransz:
|
||||
@@ -243,7 +230,6 @@ ftransz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
ftray:
|
||||
description: Sample transfer tray
|
||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||
@@ -259,7 +245,6 @@ ftray:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
|
||||
|
||||
############################################################
|
||||
@@ -294,7 +279,6 @@ fosax:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 9.124
|
||||
out: 5.3
|
||||
@@ -313,7 +297,6 @@ fosay:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0.367
|
||||
fosaz:
|
||||
@@ -331,7 +314,6 @@ fosaz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 8.5
|
||||
out: 6
|
||||
@@ -352,7 +334,6 @@ rtx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: on_request
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
low_signal: 10000
|
||||
min_signal: 9000
|
||||
@@ -369,7 +350,6 @@ rty:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: on_request
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
tomo_additional_offsety: 0
|
||||
rtz:
|
||||
@@ -384,7 +364,6 @@ rtz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: on_request
|
||||
connectionTimeout: 20
|
||||
|
||||
############################################################
|
||||
####################### Cameras ############################
|
||||
@@ -429,20 +408,20 @@ cam_xeye:
|
||||
readOnly: false
|
||||
readoutPriority: async
|
||||
|
||||
# cam_ids_rgb:
|
||||
# description: Camera flOMNI Xray eye ID203
|
||||
# deviceClass: csaxs_bec.devices.ids_cameras.ids_camera.IDSCamera
|
||||
# deviceConfig:
|
||||
# camera_id: 203
|
||||
# bits_per_pixel: 24
|
||||
# num_rotation_90: 3
|
||||
# transpose: false
|
||||
# force_monochrome: true
|
||||
# m_n_colormode: 1
|
||||
# enabled: true
|
||||
# onFailure: buffer
|
||||
# readOnly: false
|
||||
# readoutPriority: async
|
||||
cam_ids_rgb:
|
||||
description: Camera flOMNI Xray eye ID203
|
||||
deviceClass: csaxs_bec.devices.ids_cameras.ids_camera.IDSCamera
|
||||
deviceConfig:
|
||||
camera_id: 203
|
||||
bits_per_pixel: 24
|
||||
num_rotation_90: 3
|
||||
transpose: false
|
||||
force_monochrome: true
|
||||
m_n_colormode: 1
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: async
|
||||
|
||||
|
||||
# ############################################################
|
||||
@@ -460,8 +439,8 @@ flomni_temphum:
|
||||
# ########## OMNY / flOMNI / LamNI fast shutter ##############
|
||||
# ############################################################
|
||||
omnyfsh:
|
||||
description: omnyfsh connects to fast shutter at X12 if device fsh exists
|
||||
deviceClass: csaxs_bec.devices.omny.shutter.OMNYFastShutter
|
||||
description: omnyfsh connects to read fast shutter at X12 if in that network
|
||||
deviceClass: csaxs_bec.devices.omny.shutter.OMNYFastEpicsShutter
|
||||
deviceConfig: {}
|
||||
enabled: true
|
||||
onFailure: buffer
|
||||
|
||||
@@ -19,7 +19,6 @@ leyex:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 14.117
|
||||
leyey:
|
||||
@@ -39,7 +38,6 @@ leyey:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 48.069
|
||||
out: 0.5
|
||||
@@ -60,7 +58,6 @@ loptx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -0.244
|
||||
out: -0.699
|
||||
@@ -81,7 +78,6 @@ lopty:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 3.724
|
||||
out: 3.53
|
||||
@@ -102,7 +98,6 @@ loptz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
lsamrot:
|
||||
description: Sample rotation
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
@@ -120,7 +115,6 @@ lsamrot:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
lsamx:
|
||||
description: Sample coarse X
|
||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||
@@ -138,7 +132,6 @@ lsamx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
center: 8.768
|
||||
lsamy:
|
||||
@@ -158,7 +151,6 @@ lsamy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
center: 10.041
|
||||
|
||||
@@ -184,7 +176,6 @@ losax:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -1.442
|
||||
losay:
|
||||
@@ -204,7 +195,6 @@ losay:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -0.171
|
||||
out: 3.8
|
||||
@@ -225,7 +215,6 @@ losaz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -1
|
||||
out: -3
|
||||
@@ -249,7 +238,6 @@ rtx:
|
||||
deviceTags:
|
||||
- lamni
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
enabled: true
|
||||
readOnly: False
|
||||
rty:
|
||||
@@ -267,7 +255,6 @@ rty:
|
||||
deviceTags:
|
||||
- lamni
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
enabled: true
|
||||
readOnly: False
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ rtx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: on_request
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
low_signal: 8500
|
||||
min_signal: 8000
|
||||
@@ -85,7 +84,6 @@ rty:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: on_request
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
tomo_additional_offsety: 0
|
||||
rtz:
|
||||
@@ -100,7 +98,6 @@ rtz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: on_request
|
||||
connectionTimeout: 20
|
||||
|
||||
# ############################################################
|
||||
# ##################### OMNY samples #########################
|
||||
@@ -168,7 +165,6 @@ ofzpx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -0.4317
|
||||
ofzpy:
|
||||
@@ -188,7 +184,6 @@ ofzpy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0.7944
|
||||
out: 0.6377
|
||||
@@ -209,7 +204,6 @@ ofzpz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
otransx:
|
||||
@@ -229,7 +223,6 @@ otransx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
otransy:
|
||||
@@ -249,7 +242,6 @@ otransy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
up_position: -1.2
|
||||
gripper_sensorvoltagetarget: -2.30
|
||||
@@ -270,7 +262,6 @@ otransz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
osamx:
|
||||
@@ -290,7 +281,6 @@ osamx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: -0.1
|
||||
osamz:
|
||||
@@ -310,7 +300,6 @@ osamz:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
oosay:
|
||||
@@ -330,7 +319,6 @@ oosay:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
near_field_in: 0.531
|
||||
far_field_in: 0.4122
|
||||
@@ -351,7 +339,6 @@ oosax:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
near_field_in: 3.2044
|
||||
far_field_in: 3.022
|
||||
@@ -372,7 +359,6 @@ oosaz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
near_field_in: -0.4452
|
||||
far_field_in: 6.5
|
||||
@@ -393,7 +379,6 @@ oparkz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
oshuttleopen:
|
||||
@@ -413,7 +398,6 @@ oshuttleopen:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
oshuttlealign:
|
||||
@@ -433,7 +417,6 @@ oshuttlealign:
|
||||
onFailure: buffer
|
||||
readOnly: true
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
osamy:
|
||||
@@ -453,7 +436,6 @@ osamy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
otracky:
|
||||
@@ -473,7 +455,6 @@ otracky:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
start_pos: -4.3431
|
||||
osamroy:
|
||||
@@ -493,7 +474,6 @@ osamroy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
in: 0
|
||||
otrackz:
|
||||
@@ -513,7 +493,6 @@ otrackz:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
start_pos: -0.6948
|
||||
oeyex:
|
||||
@@ -533,7 +512,6 @@ oeyex:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
xray_in: -45.7394
|
||||
oeyez:
|
||||
@@ -553,7 +531,6 @@ oeyez:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
xray_in: -2
|
||||
oeyey:
|
||||
@@ -573,7 +550,6 @@ oeyey:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
xray_in: 0.0229
|
||||
|
||||
@@ -596,7 +572,6 @@ ocsx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
nothing: 0
|
||||
ocsy:
|
||||
@@ -614,7 +589,6 @@ ocsy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
nothing: 0
|
||||
oshield:
|
||||
@@ -632,6 +606,5 @@ oshield:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
userParameter:
|
||||
nothing: 0
|
||||
|
||||
@@ -64,7 +64,6 @@ npx:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
deviceTags:
|
||||
- npoint
|
||||
npy:
|
||||
@@ -82,6 +81,5 @@ npy:
|
||||
onFailure: buffer
|
||||
readOnly: false
|
||||
readoutPriority: baseline
|
||||
connectionTimeout: 20
|
||||
deviceTags:
|
||||
- npoint
|
||||
@@ -37,7 +37,7 @@ to interrupt and ongoing sequence if needed.
|
||||
- a = t0 + 2ms (2ms delay to allow the shutter to open)
|
||||
- b = a + 1us (short pulse)
|
||||
- c = t0
|
||||
- d = a + exp_time * burst_count
|
||||
- d = a + exp_time * burst_count + 1ms (to allow the shutter to close)
|
||||
- e = d
|
||||
- f = e + 1us (short pulse to OR gate for MCS triggering)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ DELAY CHANNELS:
|
||||
- a = t0 + 2ms (2ms delay to allow the shutter to open)
|
||||
- b = a + 1us (short pulse)
|
||||
- c = t0
|
||||
- d = a + exp_time * burst_count
|
||||
- d = a + exp_time * burst_count + 1ms (to allow the shutter to close)
|
||||
- e = d
|
||||
- f = e + 1us (short pulse to OR gate for MCS triggering)
|
||||
"""
|
||||
@@ -37,9 +37,7 @@ import traceback
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import EpicsSignalRO, Kind
|
||||
from ophyd_devices import CompareStatus, DeviceStatus, StatusBase, TransitionStatus
|
||||
from ophyd_devices import CompareStatus, DeviceStatus, TransitionStatus
|
||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||
|
||||
from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import (
|
||||
@@ -71,7 +69,7 @@ logger = bec_logger.logger
|
||||
# This can be adapted as needed, or fine-tuned per channel. On every reload of the
|
||||
# device configuration in BEC, these values will be set into the DDG1 device.
|
||||
_DEFAULT_CHANNEL_CONFIG: ChannelConfig = {
|
||||
"amplitude": 4.5,
|
||||
"amplitude": 5.0,
|
||||
"offset": 0.0,
|
||||
"polarity": OUTPUTPOLARITY.POSITIVE,
|
||||
"mode": "ttl",
|
||||
@@ -133,27 +131,6 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
device_manager (DeviceManagerBase | None, optional): Device manager. Defaults to None.
|
||||
"""
|
||||
|
||||
USER_ACCESS = ["keep_shutter_open_during_scan", "set_trigger"]
|
||||
|
||||
# TODO Consider using the 'fsh' device instead.
|
||||
fast_shutter_readback = Cpt(
|
||||
EpicsSignalRO,
|
||||
read_pv="X12SA-ES1-TTL:INP_01",
|
||||
add_prefix=("",), # Add this to prevent the prefix to be added to the signal
|
||||
kind=Kind.omitted,
|
||||
auto_monitor=True,
|
||||
)
|
||||
# The shutter control PV can indicate if the shutter is requested to be kept open. If that
|
||||
# is the case, we can not use the signal shutter_readback signal to check if the delay cycle
|
||||
# finishes but have to use the polling of the event status register to check if the burst finished.
|
||||
fast_shutter_control = Cpt(
|
||||
EpicsSignalRO,
|
||||
read_pv="X12SA-ES1-TTL:OUT_01",
|
||||
add_prefix=("",), # Add this to prevent the prefix to be added to the signal
|
||||
kind=Kind.omitted,
|
||||
auto_monitor=True,
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
@@ -165,7 +142,6 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
super().__init__(
|
||||
name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs
|
||||
)
|
||||
self._shutter_to_open_delay = 2e-3
|
||||
self.device_manager = device_manager
|
||||
self._poll_thread = threading.Thread(target=self._poll_event_status, daemon=True)
|
||||
self._poll_thread_run_event = threading.Event()
|
||||
@@ -216,21 +192,6 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
self.burst_delay.put(0)
|
||||
self.burst_count.put(1)
|
||||
|
||||
def keep_shutter_open_during_scan(self, open: True) -> None:
|
||||
"""
|
||||
Method to configure the delay generator for keeping the shutter open during a scans.
|
||||
This means that the additional delay to open the shutter needs to be removed (2e-3)
|
||||
from the timing of the signals.
|
||||
|
||||
Args:
|
||||
open (bool): If True, the shutter will be kept open during the scan.
|
||||
If False, the shutter will be opened and closed for each trigger cycle.
|
||||
"""
|
||||
if open is True:
|
||||
self._shutter_to_open_delay = 0
|
||||
else:
|
||||
self._shutter_to_open_delay = 2e-3
|
||||
|
||||
def on_stage(self) -> None:
|
||||
"""
|
||||
|
||||
@@ -269,18 +230,6 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
if self.burst_count.get() != 1:
|
||||
self.burst_count.put(1)
|
||||
|
||||
#####################################
|
||||
## Setup trigger source if needed ###
|
||||
#####################################
|
||||
|
||||
# NOTE Some scans may change the trigger source to an external trigger,
|
||||
# so we will make sure that the default trigger source is set for the DDG1
|
||||
# before each scan. If a scan requires a different trigger source, i.e.
|
||||
# external triggers then the scan should implement this change after the
|
||||
# on_stage method was called.
|
||||
if self.trigger_source.get() != DEFAULT_TRIGGER_SOURCE:
|
||||
self.set_trigger(DEFAULT_TRIGGER_SOURCE)
|
||||
|
||||
#########################################
|
||||
### Setup timing for burst and delays ###
|
||||
#########################################
|
||||
@@ -290,34 +239,27 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
|
||||
# Burst Period DDG1
|
||||
# Set burst_period to shutter width
|
||||
# c/t0 + self._shutter_to_open_delay + exp_time * burst_count
|
||||
shutter_width = (
|
||||
self._shutter_to_open_delay + exp_time * frames_per_trigger
|
||||
) # Shutter starts closing at end of exposure
|
||||
# c/t0 + 2ms + exp_time * burst_count + 1ms
|
||||
shutter_width = 2e-3 + exp_time * frames_per_trigger + 1e-3
|
||||
if self.burst_period.get() != shutter_width:
|
||||
self.burst_period.put(shutter_width)
|
||||
|
||||
# Trigger DDG2
|
||||
# a = t0 + 2ms, b = a + 1us
|
||||
# a has reference to t0, b has reference to a
|
||||
# Add delay of self._shutter_to_open_delay to allow shutter to open
|
||||
self.set_delay_pairs(channel="ab", delay=self._shutter_to_open_delay, width=1e-6)
|
||||
# Add delay of 2ms to allow shutter to open
|
||||
self.set_delay_pairs(channel="ab", delay=2e-3, width=1e-6)
|
||||
|
||||
# Trigger shutter
|
||||
# d = c/t0 + self._shutter_to_open_delay + exp_time * burst_count + 1ms
|
||||
# d = c/t0 + 2ms + exp_time * burst_count + 1ms
|
||||
# c has reference to t0, d has reference to c
|
||||
# Shutter opens without delay at t0, closes after exp_time * burst_count + 2ms (self._shutter_to_open_delay)
|
||||
# Shutter opens without delay at t0, closes after exp_time * burst_count + 3ms (2ms open, 1ms close)
|
||||
self.set_delay_pairs(channel="cd", delay=0, width=shutter_width)
|
||||
|
||||
self.set_delay_pairs(channel="gh", delay=self._shutter_to_open_delay, width=(shutter_width-self._shutter_to_open_delay))
|
||||
|
||||
# Trigger extra pulse for MCS OR gate
|
||||
# f = e + 1us
|
||||
# e has refernce to d, f has reference to e
|
||||
if self.scan_info.msg.scan_type == "fly":
|
||||
self.set_delay_pairs(channel="ef", delay=0, width=0)
|
||||
else:
|
||||
self.set_delay_pairs(channel="ef", delay=0, width=1e-6)
|
||||
self.set_delay_pairs(channel="ef", delay=0, width=1e-6)
|
||||
|
||||
# NOTE Add additional sleep to make sure that the IOC and DDG HW process the values properly
|
||||
# This value has been choosen empirically after testing with the HW. It's
|
||||
@@ -489,19 +431,7 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
|
||||
def on_trigger(self) -> DeviceStatus:
|
||||
"""
|
||||
This method is called from BEC as a software trigger. Here the logic is as follows:
|
||||
|
||||
We first check if the trigger_source is set to SINGLE_SHOT. Only then will we received,
|
||||
otherwise we return a status object directly as the DDG is triggered by an external
|
||||
source which will have to implement its own logic to wait for trigger signals to
|
||||
be received.
|
||||
|
||||
I SINGLE_SHOT, the implementation here will send a software trigger. Now there are
|
||||
two options to wait for the trigger (burst) cycle to be done. One is to rely on the
|
||||
signal of the "mcs" card if it is present. However, this is only possible if the
|
||||
scan_type is not "fly" as in fly scans the ef channel is not triggered to send the last
|
||||
pulse to the card (but the card is finishing its acquisition in complete itself). Then
|
||||
we rely on the polling of the event status register to check if the burst cycle is done.
|
||||
This method is called from BEC as a software trigger.
|
||||
|
||||
It follows a specific procedure to ensure that the DDG1 and MCS card are properly handled
|
||||
on a trigger event. The established logic is as follows:
|
||||
@@ -520,46 +450,33 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
- Return the status object to BEC which will automatically resolve once the status register has
|
||||
the END_OF_BURST bit set. The callback of the status object will also stop the polling loop.
|
||||
"""
|
||||
overall_start = time.time()
|
||||
self._stop_polling()
|
||||
|
||||
# NOTE If the trigger source is not SINGLE_SHOT, the DDG is triggered by an external source
|
||||
# thus we can not expect that trigger signals are meant to be awaited for. In this case,
|
||||
# we can directly return.
|
||||
if self.trigger_source.get() != TRIGGERSOURCE.SINGLE_SHOT.value:
|
||||
status = StatusBase(obj=self)
|
||||
status.set_finished()
|
||||
return status
|
||||
self._poll_thread_poll_loop_done.wait(timeout=1)
|
||||
# NOTE: This sleep is important to ensure that the HW is ready to process new commands.
|
||||
# It has been empirically determined after long testing that this improves stability.
|
||||
time.sleep(0.02)
|
||||
|
||||
# NOTE If the MCS card is present in the current session of BEC,
|
||||
# we prepare the card for the next trigger. The procedure is implemented
|
||||
# in the '_prepare_mcs_on_trigger' method. We will also use the mcs card
|
||||
# to indicate when the burst cycle is done. If no mcs card is available
|
||||
# the fallback is to use the polling of the DDG
|
||||
# in the '_prepare_mcs_on_trigger' method.
|
||||
# Prepare the MCS card for the next software trigger
|
||||
mcs = self.device_manager.devices.get("mcs", None)
|
||||
if mcs is None or mcs.enabled is False or self.scan_info.msg.scan_type == "fly":
|
||||
self._poll_thread_poll_loop_done.wait(timeout=1)
|
||||
logger.warning("Did not find mcs card with name 'mcs' in current session")
|
||||
time.sleep(0.02)
|
||||
# Shutter is kept open, we can only rely on the event status register
|
||||
status = self._prepare_trigger_status_event()
|
||||
# Start polling thread again to monitor event status
|
||||
self._start_polling()
|
||||
if mcs is None or mcs.enabled is False:
|
||||
logger.info("Did not find mcs card with name 'mcs' in current session")
|
||||
else:
|
||||
start_time = time.time()
|
||||
logger.debug(f"Preparing mcs card ")
|
||||
status_mcs = self._prepare_mcs_on_trigger(mcs)
|
||||
# NOTE Timeout of 3s should be plenty, any longer wait should checked. If this happens to crash
|
||||
# an acquisition regularly with a WaitTimeoutError, the timeout can be increased but it should
|
||||
# be investigated why the EPICS interface is slow to respond.
|
||||
status_mcs.wait(timeout=3)
|
||||
status = TransitionStatus(mcs.acquiring, [ACQUIRING.ACQUIRING, ACQUIRING.DONE])
|
||||
logger.debug(f"Finished preparing mcs card {time.time()-start_time}")
|
||||
|
||||
# Send trigger
|
||||
# Prepare StatusBitsCompareStatus to resolve once the END_OF_BURST bit was set.
|
||||
status = self._prepare_trigger_status_event()
|
||||
|
||||
# Start polling thread again to monitor event status
|
||||
self._start_polling()
|
||||
# Trigger the DDG1
|
||||
self.trigger_shot.put(1, use_complete=True)
|
||||
self.cancel_on_stop(status)
|
||||
logger.info(f"Configured ddg in {time.time()-overall_start}")
|
||||
return status
|
||||
|
||||
def on_stop(self) -> None:
|
||||
|
||||
@@ -37,7 +37,6 @@ from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import
|
||||
ChannelConfig,
|
||||
DelayGeneratorCSAXS,
|
||||
LiteralChannels,
|
||||
BURSTCONFIG,
|
||||
)
|
||||
|
||||
logger = bec_logger.logger
|
||||
@@ -48,7 +47,7 @@ logger = bec_logger.logger
|
||||
|
||||
# NOTE Default channel configuration for the DDG2 delay generator channels
|
||||
_DEFAULT_CHANNEL_CONFIG: ChannelConfig = {
|
||||
"amplitude": 4.5,
|
||||
"amplitude": 5.0,
|
||||
"offset": 0.0,
|
||||
"polarity": OUTPUTPOLARITY.POSITIVE,
|
||||
"mode": "ttl",
|
||||
@@ -135,9 +134,6 @@ class DDG2(PSIDeviceBase, DelayGeneratorCSAXS):
|
||||
self.set_trigger(DEFAULT_TRIGGER_SOURCE)
|
||||
self.set_references_for_channels(DEFAULT_REFERENCES)
|
||||
|
||||
# Set burst config
|
||||
self.burst_config.put(BURSTCONFIG.FIRST_CYCLE.value)
|
||||
|
||||
def on_stage(self) -> DeviceStatus | StatusBase | None:
|
||||
"""
|
||||
|
||||
|
||||
@@ -488,7 +488,6 @@ class DelayGeneratorCSAXS(Device):
|
||||
name="trigger_source",
|
||||
kind=Kind.omitted,
|
||||
doc="Trigger Source for the DDG, options in TRIGGERSOURCE",
|
||||
auto_monitor=True,
|
||||
)
|
||||
trigger_level = Cpt(
|
||||
EpicsSignal,
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
"""
|
||||
Shutter device for the cSAXS beamline with 2 PVs. One is connected to a
|
||||
signal can be set to control the shutter signal, and the other is a readback signal
|
||||
that can be monitored to check the shutter status as it may be controlled directly by
|
||||
the delay generator."""
|
||||
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, Kind
|
||||
|
||||
|
||||
class cSAXSFastEpicsShutter(Device):
|
||||
"""
|
||||
Fast EPICS shutter with automatic PV selection based on host subnet. IOC prefix is 'X12SA-ES1-TTL:'
|
||||
"""
|
||||
|
||||
USER_ACCESS = ["fshopen", "fshclose", "fshstatus", "fshinfo", "fshstatus_readback", "help"]
|
||||
SUB_VALUE = "value"
|
||||
_default_sub = SUB_VALUE
|
||||
|
||||
# PVs
|
||||
shutter = Cpt(EpicsSignal, "OUT_01", kind=Kind.normal, auto_monitor=True)
|
||||
shutter_readback = Cpt(EpicsSignalRO, "INP_01", kind=Kind.normal, auto_monitor=True)
|
||||
|
||||
# -----------------------------------------------------
|
||||
# User-facing shutter control functions
|
||||
# -----------------------------------------------------
|
||||
|
||||
# pylint: disable=protetced-access
|
||||
def fshopen(self) -> None:
|
||||
"""Open the fast shutter."""
|
||||
self.shutter.set(1).wait(timeout=self.shutter._timeout) # 2s default for ES
|
||||
|
||||
# pylint: disable=protetced-access
|
||||
def fshclose(self) -> None:
|
||||
"""Close the fast shutter."""
|
||||
self.shutter.set(0).wait(timeout=self.shutter._timeout) # 2s default for ES
|
||||
|
||||
def fshstatus(self) -> int:
|
||||
"""Return the fast shutter control status (0=closed, 1=open)."""
|
||||
return self.shutter.get() # Ensure we have the latest value from EPICS
|
||||
|
||||
def fshstatus_readback(self) -> int:
|
||||
"""Return the fast shutter status (0=closed, 1=open)."""
|
||||
return self.shutter_readback.get() # Ensure we have the latest value from EPICS
|
||||
|
||||
def fshinfo(self) -> None:
|
||||
"""Print information about which EPICS PV channel is being used."""
|
||||
pvname = self.shutter.pvname
|
||||
shutter_readback_pvname = self.shutter_readback.pvname
|
||||
print(
|
||||
f"Fast shutter connected to EPICS channel: {pvname} with shutter readback: {shutter_readback_pvname}"
|
||||
)
|
||||
|
||||
def stop(self, *, success: bool = False) -> None:
|
||||
"""Stop the shutter device. Make sure to close it."""
|
||||
self.shutter.put(0)
|
||||
super().stop(success=success)
|
||||
|
||||
def help(self):
|
||||
"""Display available user methods."""
|
||||
print("Available methods:")
|
||||
for method in self.USER_ACCESS:
|
||||
print(f" - {method}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
fsh = cSAXSFastEpicsShutter(name="fsh", prefix="X12SA-ES1-TTL:")
|
||||
@@ -22,13 +22,7 @@ import numpy as np
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import EpicsSignalRO, Kind
|
||||
from ophyd_devices import (
|
||||
AsyncMultiSignal,
|
||||
CompareStatus,
|
||||
ProgressSignal,
|
||||
StatusBase,
|
||||
TransitionStatus,
|
||||
)
|
||||
from ophyd_devices import AsyncMultiSignal, CompareStatus, ProgressSignal, StatusBase
|
||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||
|
||||
from csaxs_bec.devices.epics.mcs_card.mcs_card import (
|
||||
@@ -261,7 +255,6 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
**kwargs: Additional keyword arguments from the subscription, including 'obj' (the EpicsSignalRO instance).
|
||||
"""
|
||||
with self._rlock:
|
||||
logger.info(f"Received update on mcs card {self.name}")
|
||||
if self._omit_mca_callbacks.is_set():
|
||||
return # Suppress callbacks when erasing all channels
|
||||
self._mca_counter_index += 1
|
||||
@@ -293,7 +286,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
)
|
||||
|
||||
# Once we have received all channels, push data to BEC and reset for next accumulation
|
||||
logger.info(
|
||||
logger.debug(
|
||||
f"Received update for {attr_name}, index {self._mca_counter_index}/{self.NUM_MCA_CHANNELS}"
|
||||
)
|
||||
if len(self._current_data) == self.NUM_MCA_CHANNELS:
|
||||
@@ -370,10 +363,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
self._num_total_triggers = triggers * num_points
|
||||
self._acquisition_group = "monitored" if triggers == 1 else "burst_group"
|
||||
self.preset_real.set(0).wait(timeout=self._pv_timeout)
|
||||
if self.scan_info.msg.scan_type == "step":
|
||||
self.num_use_all.set(triggers).wait(timeout=self._pv_timeout)
|
||||
elif self.scan_info.msg.scan_type == "fly":
|
||||
self.num_use_all.set(self._num_total_triggers).wait(timeout=self._pv_timeout)
|
||||
self.num_use_all.set(triggers).wait(timeout=self._pv_timeout)
|
||||
|
||||
# Clear any previous data, just to be sure
|
||||
with self._rlock:
|
||||
@@ -395,21 +385,6 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
self._omit_mca_callbacks.clear()
|
||||
|
||||
logger.info(f"MCS Card {self.name} on_stage completed in {time.time() - start_time:.3f}s.")
|
||||
# For a fly scan we need to start the mcs card ourselves
|
||||
if self.scan_info.msg.scan_type == "fly":
|
||||
self.erase_start.put(1)
|
||||
|
||||
def on_prescan(self) -> None | StatusBase:
|
||||
"""
|
||||
This method is called after on_stage and before the scan starts. For the MCS card, we need to make sure
|
||||
that the card is properly started for fly scans. For step scans, this will be handled by the DDG,
|
||||
so no action is required here.
|
||||
"""
|
||||
if self.scan_info.msg.scan_type == "fly":
|
||||
status_acquiring = CompareStatus(self.acquiring, ACQUIRING.ACQUIRING)
|
||||
self.cancel_on_stop(status_acquiring)
|
||||
return status_acquiring
|
||||
return None
|
||||
|
||||
def on_unstage(self) -> None:
|
||||
"""
|
||||
@@ -447,16 +422,9 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
hasattr(self.scan_info.msg, "num_points")
|
||||
and self.scan_info.msg.num_points is not None
|
||||
):
|
||||
if self.scan_info.msg.scan_type == "step":
|
||||
if self._current_data_index == self.scan_info.msg.num_points:
|
||||
for callback in self._scan_done_callbacks:
|
||||
callback(exception=None)
|
||||
else:
|
||||
logger.info(f"Current data index is {self._current_data_index}")
|
||||
if self._current_data_index >= 1:
|
||||
for callback in self._scan_done_callbacks:
|
||||
callback(exception=None)
|
||||
|
||||
if self._current_data_index == self.scan_info.msg.num_points:
|
||||
for callback in self._scan_done_callbacks:
|
||||
callback(exception=None)
|
||||
time.sleep(0.02) # 20ms delay to avoid busy loop
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
content = traceback.format_exc()
|
||||
@@ -484,6 +452,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
"""Callback for status failure, the monitoring thread should be stopped."""
|
||||
# NOTE Check for status.done and status.success is important to avoid
|
||||
if status.done:
|
||||
|
||||
self._start_monitor_async_data_emission.clear() # Stop monitoring
|
||||
|
||||
def on_complete(self) -> CompareStatus:
|
||||
@@ -509,13 +478,6 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
monitoring thread is stopped properly.
|
||||
|
||||
"""
|
||||
# NOTE For fly scans with EXT/EN enabled triggering, the MCS card needs to receive an
|
||||
# additional trigger at the end of the scan to advance the channel. This will ensure
|
||||
# that the acquisition finishes on the card and that data is emitted to BEC. If the acquisition
|
||||
# was already finished (i.e. normal step scan sends 1 extra pulse per burst cycle), this will
|
||||
# not have any effect as the card will already be in DONE state and signal.
|
||||
self.software_channel_advance.put(1)
|
||||
|
||||
# Prepare and register status callback for the async monitoring loop
|
||||
status_async_data = StatusBase(obj=self)
|
||||
self._scan_done_callbacks.append(partial(self._status_callback, status_async_data))
|
||||
@@ -529,7 +491,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
||||
|
||||
# Combine both statuses
|
||||
ret_status = status & status_async_data
|
||||
# NOTE: Handle external stop/cancel, and stop monitoring
|
||||
# Handle external stop/cancel, and stop monitoring
|
||||
ret_status.add_callback(self._status_failed_callback)
|
||||
self.cancel_on_stop(ret_status)
|
||||
return ret_status
|
||||
|
||||
@@ -498,9 +498,6 @@ class RtFlomniController(Controller):
|
||||
)
|
||||
# while scan is running
|
||||
while mode > 0:
|
||||
|
||||
#TODO here?: scan abortion if no progress in scan *raise error
|
||||
|
||||
# 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)
|
||||
@@ -632,8 +629,6 @@ class RtFlomniMotor(Device, PositionerBase):
|
||||
SUB_CONNECTION_CHANGE = "connection_change"
|
||||
_default_sub = SUB_READBACK
|
||||
|
||||
connectionTimeout = 20
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
axis_Id,
|
||||
|
||||
@@ -1,87 +1,82 @@
|
||||
"""
|
||||
Fast Shutter control for OMNY setup. If started with a config file in which the device_manager
|
||||
has a 'fsh' device (cSAXSFastEpicsShutter), this device will be used as the shutter.
|
||||
Otherwise, the device will create a dummy shutter device that will log warnings when shutter
|
||||
methods are called, but will not raise exceptions.
|
||||
"""
|
||||
|
||||
from bec_lib.logger import bec_logger
|
||||
import time
|
||||
import socket
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import Device, Signal
|
||||
from ophyd_devices import PSIDeviceBase
|
||||
|
||||
logger = bec_logger.logger
|
||||
from ophyd import Device
|
||||
from ophyd import EpicsSignal
|
||||
|
||||
|
||||
class OMNYFastShutter(PSIDeviceBase, Device):
|
||||
class OMNYFastEpicsShutterError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _detect_host_pv():
|
||||
"""Detect host subnet and return appropriate PV name."""
|
||||
try:
|
||||
hostname = socket.gethostname()
|
||||
local_ip = socket.gethostbyname(hostname)
|
||||
if local_ip.startswith("129.129.122."):
|
||||
return "X12SA-ES1-TTL:OUT_01"
|
||||
else:
|
||||
return "XOMNYI-XEYE-DUMMYSHUTTER:0"
|
||||
except Exception as ex:
|
||||
print(f"Warning: could not detect IP subnet ({ex}), using dummy shutter.")
|
||||
return "XOMNYI-XEYE-DUMMYSHUTTER:0"
|
||||
|
||||
|
||||
class OMNYFastEpicsShutter(Device):
|
||||
"""
|
||||
Fast Shutter control for OMNY setup. If started with at the beamline, it will expose
|
||||
the shutter control methods (fshopen, fshclose, fshstatus, fshinfo) from the
|
||||
cSAXSFastEpicsShutter device. The device is identified by the 'fsh' name in the device manager.
|
||||
If the 'fsh' device is not found in the device manager, this device will create a dummy shutter
|
||||
and log warnings when shutter methods are called, but will not raise exceptions.
|
||||
Fast EPICS shutter with automatic PV selection based on host subnet.
|
||||
"""
|
||||
|
||||
USER_ACCESS = ["fshopen", "fshclose", "fshstatus", "fshinfo", "help", "fshstatus_readback"]
|
||||
USER_ACCESS = ["fshopen", "fshclose", "fshstatus", "fshinfo", "help"]
|
||||
SUB_VALUE = "value"
|
||||
_default_sub = SUB_VALUE
|
||||
|
||||
shutter = Cpt(Signal, name="shutter")
|
||||
# PV is detected dynamically at import time
|
||||
shutter = Cpt(EpicsSignal, name="shutter", read_pv=_detect_host_pv(), auto_monitor=True)
|
||||
|
||||
def __init__(self, prefix="", *, name, **kwargs):
|
||||
super().__init__(prefix, name=name, **kwargs)
|
||||
self.shutter.subscribe(self._emit_value)
|
||||
|
||||
def _emit_value(self, **kwargs):
|
||||
timestamp = kwargs.pop("timestamp", time.time())
|
||||
self.wait_for_connection()
|
||||
self._run_subs(sub_type=self.SUB_VALUE, timestamp=timestamp, obj=self)
|
||||
|
||||
# -----------------------------------------------------
|
||||
# User-facing shutter control functions
|
||||
# -----------------------------------------------------
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
def _check_if_cSAXS_shutter_exists_in_config(self) -> bool:
|
||||
"""
|
||||
Check on the device manager if the shutter device exists.
|
||||
|
||||
Returns:
|
||||
bool: True if the 'fsh' device exists in the device manager, False otherwise
|
||||
"""
|
||||
if self.device_manager.devices.get("fsh", None) is None:
|
||||
logger.warning(f"Fast shutter device not found for {self.name}.")
|
||||
return False
|
||||
return True
|
||||
|
||||
def fshopen(self):
|
||||
"""Open the fast shutter."""
|
||||
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||
return self.device_manager.devices["fsh"].fshopen()
|
||||
else:
|
||||
self.shutter.put(1)
|
||||
try:
|
||||
self.shutter.put(1, wait=True)
|
||||
except Exception as ex:
|
||||
raise OMNYFastEpicsShutterError(f"Failed to open shutter: {ex}")
|
||||
|
||||
def fshclose(self):
|
||||
"""Close the fast shutter."""
|
||||
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||
return self.device_manager.devices["fsh"].fshclose()
|
||||
else:
|
||||
self.shutter.put(0)
|
||||
try:
|
||||
self.shutter.put(0, wait=True)
|
||||
except Exception as ex:
|
||||
raise OMNYFastEpicsShutterError(f"Failed to close shutter: {ex}")
|
||||
|
||||
def fshstatus(self):
|
||||
"""Return the fast shutter status (0=closed, 1=open)."""
|
||||
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||
return self.device_manager.devices["fsh"].fshstatus()
|
||||
else:
|
||||
try:
|
||||
return self.shutter.get()
|
||||
except Exception as ex:
|
||||
raise OMNYFastEpicsShutterError(f"Failed to read shutter status: {ex}")
|
||||
|
||||
def fshinfo(self):
|
||||
"""Print information about which EPICS PV channel is being used."""
|
||||
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||
return self.device_manager.devices["fsh"].fshinfo()
|
||||
else:
|
||||
print("Using dummy fast shutter device. No EPICS channel is connected.")
|
||||
pvname = self.shutter.pvname
|
||||
print(f"Fast shutter connected to EPICS channel: {pvname}")
|
||||
return pvname
|
||||
|
||||
def help(self):
|
||||
"""Display available user methods."""
|
||||
print("Available methods:")
|
||||
for method in self.USER_ACCESS:
|
||||
print(f" - {method}")
|
||||
|
||||
def fshstatus_readback(self):
|
||||
"""Return the fast shutter status (0=closed, 1=open) from the readback signal."""
|
||||
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||
return self.device_manager.devices["fsh"].fshstatus_readback()
|
||||
else:
|
||||
self.shutter.get()
|
||||
|
||||
@@ -27,7 +27,6 @@ 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
|
||||
from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import TRIGGERSOURCE
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
@@ -74,13 +73,14 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
>>> scans.flomni_fermat_scan(fovx=20, fovy=25, cenx=0.02, ceny=0, zshift=0, angle=0, step=0.5, exp_time=0.01)
|
||||
"""
|
||||
|
||||
super().__init__(parameter=parameter, exp_time=exp_time, **kwargs)
|
||||
super().__init__(parameter=parameter, **kwargs)
|
||||
self.show_live_table = False
|
||||
self.axis = []
|
||||
self.fovx = fovx
|
||||
self.fovy = fovy
|
||||
self.cenx = cenx
|
||||
self.ceny = ceny
|
||||
self.exp_time = exp_time
|
||||
self.step = step
|
||||
self.zshift = zshift
|
||||
self.angle = angle
|
||||
@@ -151,9 +151,6 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
yield from self.stubs.send_rpc_and_wait("rty", "set", self.positions[0][1])
|
||||
|
||||
def _prepare_setup_part2(self):
|
||||
# Prepare DDG1 to use
|
||||
yield from self.stubs.send_rpc_and_wait("ddg1", "set_trigger", TRIGGERSOURCE.EXT_RISING_EDGE.value)
|
||||
|
||||
if self.flomni_rotation_status:
|
||||
self.flomni_rotation_status.wait()
|
||||
|
||||
@@ -310,10 +307,6 @@ class FlomniFermatScan(SyncFlyScanBase):
|
||||
|
||||
logger.warning("No positions found to return to start")
|
||||
|
||||
def cleanup(self):
|
||||
yield from self.stubs.send_rpc_and_wait("ddg1", "set_trigger", TRIGGERSOURCE.SINGLE_SHOT.value)
|
||||
yield from super().cleanup()
|
||||
|
||||
def run(self):
|
||||
self.initialize()
|
||||
yield from self.read_scan_motors()
|
||||
|
||||
14
tests/conftest.py
Normal file
14
tests/conftest.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
Conftest runs for all tests in this directory and subdirectories. Thereby, we know for
|
||||
certain that the SocketSignal.READBACK_TIMEOUT is set to 0 for all tests, which prevents
|
||||
hanging tests when a readback is attempted on a non-connected socket.
|
||||
"""
|
||||
|
||||
# conftest.py
|
||||
import pytest
|
||||
from ophyd_devices.utils.socket import SocketSignal
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def patch_socket_timeout(monkeypatch):
|
||||
monkeypatch.setattr(SocketSignal, "READBACK_TIMEOUT", 0.0)
|
||||
@@ -282,11 +282,10 @@ def test_ddg1_stage(mock_ddg1: DDG1):
|
||||
|
||||
mock_ddg1.scan_info.msg.scan_parameters["exp_time"] = exp_time
|
||||
mock_ddg1.scan_info.msg.scan_parameters["frames_per_trigger"] = frames_per_trigger
|
||||
mock_ddg1.fast_shutter_control._read_pv.mock_data = 0 # Simulate shutter control
|
||||
|
||||
mock_ddg1.stage()
|
||||
|
||||
shutter_width = mock_ddg1._shutter_to_open_delay + exp_time * frames_per_trigger
|
||||
shutter_width = 2e-3 + exp_time * frames_per_trigger + 1e-3
|
||||
|
||||
assert np.isclose(mock_ddg1.burst_mode.get(), 1) # burst mode is enabled
|
||||
assert np.isclose(mock_ddg1.burst_delay.get(), 0)
|
||||
@@ -303,25 +302,6 @@ def test_ddg1_stage(mock_ddg1: DDG1):
|
||||
assert np.isclose(mock_ddg1.ef.width.get(), 1e-6)
|
||||
|
||||
assert mock_ddg1.staged == ophyd.Staged.yes
|
||||
mock_ddg1.unstage()
|
||||
|
||||
# Test if shutter is kept open..
|
||||
mock_ddg1.fast_shutter_control._read_pv.mock_data = 1 # Simulate shutter control is kept open
|
||||
# Test method
|
||||
mock_ddg1.keep_shutter_open_during_scan(True)
|
||||
shutter_width = mock_ddg1._shutter_to_open_delay + exp_time * frames_per_trigger
|
||||
assert np.isclose(
|
||||
shutter_width, exp_time * frames_per_trigger
|
||||
) # Shutter to open delay is not added as shutter is kept open
|
||||
# Simulate fly scan, so no extra trigger for MCS card.
|
||||
mock_ddg1.scan_info.msg.scan_type = "fly"
|
||||
mock_ddg1.stage()
|
||||
# Shutter channel cd
|
||||
assert np.isclose(mock_ddg1.cd.delay.get(), 0)
|
||||
assert np.isclose(mock_ddg1.cd.width.get(), shutter_width)
|
||||
# MCS channel ef or gate
|
||||
assert np.isclose(mock_ddg1.ef.delay.get(), 0)
|
||||
assert np.isclose(mock_ddg1.ef.width.get(), 0) # No triggering of MCS due to shutter fly scan
|
||||
|
||||
|
||||
def test_ddg1_on_trigger(mock_ddg1: DDG1):
|
||||
@@ -351,28 +331,9 @@ def test_ddg1_on_trigger(mock_ddg1: DDG1):
|
||||
#################################
|
||||
with mock.patch.object(ddg, "_prepare_mcs_on_trigger") as mock_prepare_mcs:
|
||||
mock_prepare_mcs.return_value = ophyd.StatusBase(done=True, success=True)
|
||||
# MCS card is present and enabled, should call prepare_mcs_on_trigger
|
||||
# and the status should resolve once acuiring goes from 1 to 0.
|
||||
status = ddg.trigger()
|
||||
assert status.done is False
|
||||
mcs = ddg.device_manager.devices.get("mcs", None)
|
||||
assert mcs is not None
|
||||
mcs.acquiring._read_pv.mock_data = 1 # Simulate acquiring started
|
||||
assert status.done is False
|
||||
mcs.acquiring._read_pv.mock_data = 0 # Simulate acquiring stopped
|
||||
status.wait(timeout=1) # Wait for the status to be done
|
||||
assert status.done is True
|
||||
assert status.success is True
|
||||
mock_prepare_mcs.assert_called_once()
|
||||
|
||||
# Now we disable the mcs card, and trigger again. This should not call prepare_mcs_on_trigger
|
||||
# and should fallback to polling the DDG for END_OF_BURST status bit.
|
||||
|
||||
# Disable mcs card
|
||||
mcs.enabled = False
|
||||
status = ddg.trigger()
|
||||
# Check that the poll thread run event is set
|
||||
# Careful in debugger, there is a timeout based on the exp_time + 5s default
|
||||
assert ddg._poll_thread_run_event.is_set()
|
||||
assert not ddg._poll_thread_poll_loop_done.is_set()
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
"""Module to test epics devices."""
|
||||
|
||||
import pytest
|
||||
from ophyd_devices.tests.utils import patched_device
|
||||
|
||||
from csaxs_bec.devices.epics.fast_shutter import cSAXSFastEpicsShutter
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fast_shutter_device():
|
||||
"""Fixture to create a patched cSAXSFastEpicsShutter device for testing."""
|
||||
with patched_device(cSAXSFastEpicsShutter, name="fsh", prefix="X12SA-ES1-TTL:") as device:
|
||||
yield device
|
||||
|
||||
|
||||
def test_fast_shutter_methods(fast_shutter_device):
|
||||
"""Test the user-facing methods of the cSAXSFastEpicsShutter device."""
|
||||
assert fast_shutter_device.name == "fsh", "Device name should be 'fsh'"
|
||||
assert fast_shutter_device.prefix == "X12SA-ES1-TTL:", "Device prefix is 'X12SA-ES1-TTL:'"
|
||||
# Test fshopen and fshclose
|
||||
fast_shutter_device.fshopen()
|
||||
assert fast_shutter_device.shutter.get() == 1, "Shutter should be open (1) after fshopen()"
|
||||
assert fast_shutter_device.fshstatus() == 1, "fshstatus should return 1 when shutter is open"
|
||||
|
||||
fast_shutter_device.fshclose()
|
||||
assert fast_shutter_device.shutter.get() == 0, "Shutter should be closed (0) after fshclose()"
|
||||
assert fast_shutter_device.fshstatus() == 0, "fshstatus should return 0 when shutter is closed"
|
||||
|
||||
# shutter_readback is connected to separate PV.
|
||||
fast_shutter_device.shutter_readback._read_pv.mock_data = 1 # Simulate readback showing open
|
||||
assert (
|
||||
fast_shutter_device.fshstatus_readback() == 1
|
||||
), "fshstatus_readback should return 1 when shutter readback shows open"
|
||||
fast_shutter_device.shutter_readback._read_pv.mock_data = 0 # Simulate readback showing closed
|
||||
assert (
|
||||
fast_shutter_device.fshstatus_readback() == 0
|
||||
), "fshstatus_readback should return 0 when shutter readback shows closed"
|
||||
Reference in New Issue
Block a user