Compare commits
24 Commits
fix/socket
...
feat/eps_d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ab763ad38
|
||
|
fa35ddf1a9
|
|||
|
501bc52867
|
|||
|
f35c51efa7
|
|||
|
0c81c718d8
|
|||
|
|
ce88310125
|
||
|
|
e860571a64
|
||
|
|
24bd5a71bc
|
||
|
|
541eb97096
|
||
|
|
7911717142
|
||
|
|
bdf94533a5
|
||
|
5784331073
|
|||
|
|
7a2c6629f7 | ||
| 75cc672f08 | |||
| 67ef20cfc8 | |||
| f8d2af4c5b | |||
| 8195c12a35 | |||
| a45aa094ef | |||
|
|
2814add2de | ||
| 32b4c39659 | |||
| 8849b9ffea | |||
| c3aa882b1d | |||
| 6fad4f2034 | |||
|
|
ed8d012632 |
@@ -37,6 +37,21 @@ mcs:
|
|||||||
readoutPriority: monitored
|
readoutPriority: monitored
|
||||||
softwareTrigger: false
|
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 ##################################
|
######################## SMARACT STAGES ##################################
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@@ -60,6 +75,7 @@ xbpm3x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -22.5
|
init_position: -22.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -82,6 +98,7 @@ xbpm3y:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -2
|
init_position: -2
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -104,6 +121,7 @@ sl3trxi:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -5.5
|
init_position: -5.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -126,6 +144,7 @@ sl3trxo:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 6
|
init_position: 6
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -148,6 +167,7 @@ sl3trxb:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -5.8
|
init_position: -5.8
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -170,6 +190,7 @@ sl3trxt:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 5.5
|
init_position: 5.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -192,6 +213,7 @@ fast_shutter_n1_x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -7
|
init_position: -7
|
||||||
in: 0
|
in: 0
|
||||||
@@ -215,6 +237,7 @@ fast_shutter_o1_x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -15.8
|
init_position: -15.8
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -237,6 +260,7 @@ fast_shutter_o2_x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -15.5
|
init_position: -15.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -259,6 +283,7 @@ filter_array_1_x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 25
|
init_position: 25
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -281,6 +306,7 @@ filter_array_2_x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 25.5
|
init_position: 25.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -303,6 +329,7 @@ filter_array_3_x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 25.8
|
init_position: 25.8
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -325,6 +352,7 @@ filter_array_4_x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 25
|
init_position: 25
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -347,6 +375,7 @@ sl4trxi:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -5.5
|
init_position: -5.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -369,6 +398,7 @@ sl4trxo:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 6
|
init_position: 6
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -391,6 +421,7 @@ sl4trxb:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -5.8
|
init_position: -5.8
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -413,6 +444,7 @@ sl4trxt:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 5.5
|
init_position: 5.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -425,7 +457,7 @@ sl5trxi:
|
|||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: C
|
axis_Id: C
|
||||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||||
limits:
|
limits:
|
||||||
- -200
|
- -200
|
||||||
- 200
|
- 200
|
||||||
@@ -437,6 +469,7 @@ sl5trxi:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -6
|
init_position: -6
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -447,7 +480,7 @@ sl5trxo:
|
|||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: D
|
axis_Id: D
|
||||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||||
limits:
|
limits:
|
||||||
- -200
|
- -200
|
||||||
- 200
|
- 200
|
||||||
@@ -459,6 +492,7 @@ sl5trxo:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 5.5
|
init_position: 5.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -469,7 +503,7 @@ sl5trxb:
|
|||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: E
|
axis_Id: E
|
||||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||||
limits:
|
limits:
|
||||||
- -200
|
- -200
|
||||||
- 200
|
- 200
|
||||||
@@ -481,6 +515,7 @@ sl5trxb:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -5.5
|
init_position: -5.5
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -491,7 +526,7 @@ sl5trxt:
|
|||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: F
|
axis_Id: F
|
||||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||||
limits:
|
limits:
|
||||||
- -200
|
- -200
|
||||||
- 200
|
- 200
|
||||||
@@ -503,6 +538,7 @@ sl5trxt:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 6
|
init_position: 6
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -513,7 +549,7 @@ xbimtrx:
|
|||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: A
|
axis_Id: A
|
||||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||||
limits:
|
limits:
|
||||||
- -200
|
- -200
|
||||||
- 200
|
- 200
|
||||||
@@ -525,6 +561,7 @@ xbimtrx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: -14.7
|
init_position: -14.7
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
@@ -535,7 +572,7 @@ xbimtry:
|
|||||||
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
deviceClass: csaxs_bec.devices.smaract.smaract_ophyd.SmaractMotor
|
||||||
deviceConfig:
|
deviceConfig:
|
||||||
axis_Id: B
|
axis_Id: B
|
||||||
host: x12sa-eb-smaract-mcs-02.psi.ch
|
host: x12sa-eb-smaract-mcs-05.psi.ch
|
||||||
limits:
|
limits:
|
||||||
- -200
|
- -200
|
||||||
- 200
|
- 200
|
||||||
@@ -547,6 +584,7 @@ xbimtry:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
init_position: 0
|
init_position: 0
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ xbpm2x:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
bl_smar_stage: 0
|
bl_smar_stage: 0
|
||||||
@@ -108,6 +109,7 @@ xbpm2y:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
bl_smar_stage: 1
|
bl_smar_stage: 1
|
||||||
@@ -127,6 +129,7 @@ cu_foilx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
bl_smar_stage: 2
|
bl_smar_stage: 2
|
||||||
@@ -146,6 +149,7 @@ scinx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
# bl_smar_stage to use csaxs reference method. assign number according to axis channel
|
||||||
bl_smar_stage: 3
|
bl_smar_stage: 3
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ feyex:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -16.267
|
in: -16.267
|
||||||
out: -1
|
out: -1
|
||||||
@@ -35,6 +36,7 @@ feyey:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -10.467
|
in: -10.467
|
||||||
fheater:
|
fheater:
|
||||||
@@ -52,6 +54,7 @@ fheater:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
foptx:
|
foptx:
|
||||||
description: Optics X
|
description: Optics X
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
@@ -67,6 +70,7 @@ foptx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -13.761
|
in: -13.761
|
||||||
fopty:
|
fopty:
|
||||||
@@ -84,6 +88,7 @@ fopty:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0.552
|
in: 0.552
|
||||||
out: 0.752
|
out: 0.752
|
||||||
@@ -102,6 +107,7 @@ foptz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 23
|
in: 23
|
||||||
fsamroy:
|
fsamroy:
|
||||||
@@ -119,6 +125,7 @@ fsamroy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
fsamx:
|
fsamx:
|
||||||
description: Sample coarse X
|
description: Sample coarse X
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
@@ -134,6 +141,7 @@ fsamx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -1.1
|
in: -1.1
|
||||||
fsamy:
|
fsamy:
|
||||||
@@ -151,6 +159,7 @@ fsamy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 2.75
|
in: 2.75
|
||||||
ftracky:
|
ftracky:
|
||||||
@@ -168,6 +177,7 @@ ftracky:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
ftrackz:
|
ftrackz:
|
||||||
description: Laser Tracker coarse Z
|
description: Laser Tracker coarse Z
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
@@ -183,6 +193,7 @@ ftrackz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
ftransx:
|
ftransx:
|
||||||
description: Sample transer X
|
description: Sample transer X
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
@@ -198,6 +209,7 @@ ftransx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
ftransy:
|
ftransy:
|
||||||
description: Sample transer Y
|
description: Sample transer Y
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
@@ -213,6 +225,7 @@ ftransy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
sensor_voltage: -2.4
|
sensor_voltage: -2.4
|
||||||
ftransz:
|
ftransz:
|
||||||
@@ -230,6 +243,7 @@ ftransz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
ftray:
|
ftray:
|
||||||
description: Sample transfer tray
|
description: Sample transfer tray
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.fgalil_ophyd.FlomniGalilMotor
|
||||||
@@ -245,6 +259,7 @@ ftray:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
@@ -279,6 +294,7 @@ fosax:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 9.124
|
in: 9.124
|
||||||
out: 5.3
|
out: 5.3
|
||||||
@@ -297,6 +313,7 @@ fosay:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0.367
|
in: 0.367
|
||||||
fosaz:
|
fosaz:
|
||||||
@@ -314,6 +331,7 @@ fosaz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 8.5
|
in: 8.5
|
||||||
out: 6
|
out: 6
|
||||||
@@ -334,6 +352,7 @@ rtx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
low_signal: 10000
|
low_signal: 10000
|
||||||
min_signal: 9000
|
min_signal: 9000
|
||||||
@@ -350,6 +369,7 @@ rty:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
tomo_additional_offsety: 0
|
tomo_additional_offsety: 0
|
||||||
rtz:
|
rtz:
|
||||||
@@ -364,6 +384,7 @@ rtz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
|
connectionTimeout: 20
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
####################### Cameras ############################
|
####################### Cameras ############################
|
||||||
@@ -408,20 +429,20 @@ cam_xeye:
|
|||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: async
|
readoutPriority: async
|
||||||
|
|
||||||
cam_ids_rgb:
|
# cam_ids_rgb:
|
||||||
description: Camera flOMNI Xray eye ID203
|
# description: Camera flOMNI Xray eye ID203
|
||||||
deviceClass: csaxs_bec.devices.ids_cameras.ids_camera.IDSCamera
|
# deviceClass: csaxs_bec.devices.ids_cameras.ids_camera.IDSCamera
|
||||||
deviceConfig:
|
# deviceConfig:
|
||||||
camera_id: 203
|
# camera_id: 203
|
||||||
bits_per_pixel: 24
|
# bits_per_pixel: 24
|
||||||
num_rotation_90: 3
|
# num_rotation_90: 3
|
||||||
transpose: false
|
# transpose: false
|
||||||
force_monochrome: true
|
# force_monochrome: true
|
||||||
m_n_colormode: 1
|
# m_n_colormode: 1
|
||||||
enabled: true
|
# enabled: true
|
||||||
onFailure: buffer
|
# onFailure: buffer
|
||||||
readOnly: false
|
# readOnly: false
|
||||||
readoutPriority: async
|
# readoutPriority: async
|
||||||
|
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
@@ -439,8 +460,8 @@ flomni_temphum:
|
|||||||
# ########## OMNY / flOMNI / LamNI fast shutter ##############
|
# ########## OMNY / flOMNI / LamNI fast shutter ##############
|
||||||
# ############################################################
|
# ############################################################
|
||||||
omnyfsh:
|
omnyfsh:
|
||||||
description: omnyfsh connects to read fast shutter at X12 if in that network
|
description: omnyfsh connects to fast shutter at X12 if device fsh exists
|
||||||
deviceClass: csaxs_bec.devices.omny.shutter.OMNYFastEpicsShutter
|
deviceClass: csaxs_bec.devices.omny.shutter.OMNYFastShutter
|
||||||
deviceConfig: {}
|
deviceConfig: {}
|
||||||
enabled: true
|
enabled: true
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ leyex:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 14.117
|
in: 14.117
|
||||||
leyey:
|
leyey:
|
||||||
@@ -38,6 +39,7 @@ leyey:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 48.069
|
in: 48.069
|
||||||
out: 0.5
|
out: 0.5
|
||||||
@@ -58,6 +60,7 @@ loptx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -0.244
|
in: -0.244
|
||||||
out: -0.699
|
out: -0.699
|
||||||
@@ -78,6 +81,7 @@ lopty:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 3.724
|
in: 3.724
|
||||||
out: 3.53
|
out: 3.53
|
||||||
@@ -98,6 +102,7 @@ loptz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
lsamrot:
|
lsamrot:
|
||||||
description: Sample rotation
|
description: Sample rotation
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
@@ -115,6 +120,7 @@ lsamrot:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
lsamx:
|
lsamx:
|
||||||
description: Sample coarse X
|
description: Sample coarse X
|
||||||
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
deviceClass: csaxs_bec.devices.omny.galil.lgalil_ophyd.LamniGalilMotor
|
||||||
@@ -132,6 +138,7 @@ lsamx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
center: 8.768
|
center: 8.768
|
||||||
lsamy:
|
lsamy:
|
||||||
@@ -151,6 +158,7 @@ lsamy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
center: 10.041
|
center: 10.041
|
||||||
|
|
||||||
@@ -176,6 +184,7 @@ losax:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -1.442
|
in: -1.442
|
||||||
losay:
|
losay:
|
||||||
@@ -195,6 +204,7 @@ losay:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -0.171
|
in: -0.171
|
||||||
out: 3.8
|
out: 3.8
|
||||||
@@ -215,6 +225,7 @@ losaz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -1
|
in: -1
|
||||||
out: -3
|
out: -3
|
||||||
@@ -238,6 +249,7 @@ rtx:
|
|||||||
deviceTags:
|
deviceTags:
|
||||||
- lamni
|
- lamni
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
enabled: true
|
enabled: true
|
||||||
readOnly: False
|
readOnly: False
|
||||||
rty:
|
rty:
|
||||||
@@ -255,6 +267,7 @@ rty:
|
|||||||
deviceTags:
|
deviceTags:
|
||||||
- lamni
|
- lamni
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
enabled: true
|
enabled: true
|
||||||
readOnly: False
|
readOnly: False
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ rtx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
low_signal: 8500
|
low_signal: 8500
|
||||||
min_signal: 8000
|
min_signal: 8000
|
||||||
@@ -84,6 +85,7 @@ rty:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
tomo_additional_offsety: 0
|
tomo_additional_offsety: 0
|
||||||
rtz:
|
rtz:
|
||||||
@@ -98,6 +100,7 @@ rtz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: on_request
|
readoutPriority: on_request
|
||||||
|
connectionTimeout: 20
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
# ##################### OMNY samples #########################
|
# ##################### OMNY samples #########################
|
||||||
@@ -165,6 +168,7 @@ ofzpx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -0.4317
|
in: -0.4317
|
||||||
ofzpy:
|
ofzpy:
|
||||||
@@ -184,6 +188,7 @@ ofzpy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0.7944
|
in: 0.7944
|
||||||
out: 0.6377
|
out: 0.6377
|
||||||
@@ -204,6 +209,7 @@ ofzpz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
otransx:
|
otransx:
|
||||||
@@ -223,6 +229,7 @@ otransx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
otransy:
|
otransy:
|
||||||
@@ -242,6 +249,7 @@ otransy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
up_position: -1.2
|
up_position: -1.2
|
||||||
gripper_sensorvoltagetarget: -2.30
|
gripper_sensorvoltagetarget: -2.30
|
||||||
@@ -262,6 +270,7 @@ otransz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
osamx:
|
osamx:
|
||||||
@@ -281,6 +290,7 @@ osamx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: -0.1
|
in: -0.1
|
||||||
osamz:
|
osamz:
|
||||||
@@ -300,6 +310,7 @@ osamz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
oosay:
|
oosay:
|
||||||
@@ -319,6 +330,7 @@ oosay:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
near_field_in: 0.531
|
near_field_in: 0.531
|
||||||
far_field_in: 0.4122
|
far_field_in: 0.4122
|
||||||
@@ -339,6 +351,7 @@ oosax:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
near_field_in: 3.2044
|
near_field_in: 3.2044
|
||||||
far_field_in: 3.022
|
far_field_in: 3.022
|
||||||
@@ -359,6 +372,7 @@ oosaz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
near_field_in: -0.4452
|
near_field_in: -0.4452
|
||||||
far_field_in: 6.5
|
far_field_in: 6.5
|
||||||
@@ -379,6 +393,7 @@ oparkz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
oshuttleopen:
|
oshuttleopen:
|
||||||
@@ -398,6 +413,7 @@ oshuttleopen:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
oshuttlealign:
|
oshuttlealign:
|
||||||
@@ -417,6 +433,7 @@ oshuttlealign:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
osamy:
|
osamy:
|
||||||
@@ -436,6 +453,7 @@ osamy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
otracky:
|
otracky:
|
||||||
@@ -455,6 +473,7 @@ otracky:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
start_pos: -4.3431
|
start_pos: -4.3431
|
||||||
osamroy:
|
osamroy:
|
||||||
@@ -474,6 +493,7 @@ osamroy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
in: 0
|
in: 0
|
||||||
otrackz:
|
otrackz:
|
||||||
@@ -493,6 +513,7 @@ otrackz:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
start_pos: -0.6948
|
start_pos: -0.6948
|
||||||
oeyex:
|
oeyex:
|
||||||
@@ -512,6 +533,7 @@ oeyex:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
xray_in: -45.7394
|
xray_in: -45.7394
|
||||||
oeyez:
|
oeyez:
|
||||||
@@ -531,6 +553,7 @@ oeyez:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
xray_in: -2
|
xray_in: -2
|
||||||
oeyey:
|
oeyey:
|
||||||
@@ -550,6 +573,7 @@ oeyey:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
xray_in: 0.0229
|
xray_in: 0.0229
|
||||||
|
|
||||||
@@ -572,6 +596,7 @@ ocsx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
nothing: 0
|
nothing: 0
|
||||||
ocsy:
|
ocsy:
|
||||||
@@ -589,6 +614,7 @@ ocsy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
nothing: 0
|
nothing: 0
|
||||||
oshield:
|
oshield:
|
||||||
@@ -606,5 +632,6 @@ oshield:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
userParameter:
|
userParameter:
|
||||||
nothing: 0
|
nothing: 0
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
##################### EPS ##################################
|
||||||
|
############################################################
|
||||||
|
x12saEPS:
|
||||||
|
description: X12SA EPS info and control
|
||||||
|
deviceClass: csaxs_bec.devices.epics.eps.EPS
|
||||||
|
deviceConfig: {}
|
||||||
|
enabled: true
|
||||||
|
onFailure: buffer
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
@@ -64,6 +64,7 @@ npx:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
deviceTags:
|
deviceTags:
|
||||||
- npoint
|
- npoint
|
||||||
npy:
|
npy:
|
||||||
@@ -81,5 +82,6 @@ npy:
|
|||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
readOnly: false
|
readOnly: false
|
||||||
readoutPriority: baseline
|
readoutPriority: baseline
|
||||||
|
connectionTimeout: 20
|
||||||
deviceTags:
|
deviceTags:
|
||||||
- npoint
|
- npoint
|
||||||
@@ -37,7 +37,7 @@ to interrupt and ongoing sequence if needed.
|
|||||||
- a = t0 + 2ms (2ms delay to allow the shutter to open)
|
- a = t0 + 2ms (2ms delay to allow the shutter to open)
|
||||||
- b = a + 1us (short pulse)
|
- b = a + 1us (short pulse)
|
||||||
- c = t0
|
- c = t0
|
||||||
- d = a + exp_time * burst_count + 1ms (to allow the shutter to close)
|
- d = a + exp_time * burst_count
|
||||||
- e = d
|
- e = d
|
||||||
- f = e + 1us (short pulse to OR gate for MCS triggering)
|
- 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)
|
- a = t0 + 2ms (2ms delay to allow the shutter to open)
|
||||||
- b = a + 1us (short pulse)
|
- b = a + 1us (short pulse)
|
||||||
- c = t0
|
- c = t0
|
||||||
- d = a + exp_time * burst_count + 1ms (to allow the shutter to close)
|
- d = a + exp_time * burst_count
|
||||||
- e = d
|
- e = d
|
||||||
- f = e + 1us (short pulse to OR gate for MCS triggering)
|
- f = e + 1us (short pulse to OR gate for MCS triggering)
|
||||||
"""
|
"""
|
||||||
@@ -37,7 +37,9 @@ import traceback
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from bec_lib.logger import bec_logger
|
from bec_lib.logger import bec_logger
|
||||||
from ophyd_devices import CompareStatus, DeviceStatus, TransitionStatus
|
from ophyd import Component as Cpt
|
||||||
|
from ophyd import EpicsSignalRO, Kind
|
||||||
|
from ophyd_devices import CompareStatus, DeviceStatus, StatusBase, TransitionStatus
|
||||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||||
|
|
||||||
from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import (
|
from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import (
|
||||||
@@ -69,7 +71,7 @@ logger = bec_logger.logger
|
|||||||
# This can be adapted as needed, or fine-tuned per channel. On every reload of the
|
# 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.
|
# device configuration in BEC, these values will be set into the DDG1 device.
|
||||||
_DEFAULT_CHANNEL_CONFIG: ChannelConfig = {
|
_DEFAULT_CHANNEL_CONFIG: ChannelConfig = {
|
||||||
"amplitude": 5.0,
|
"amplitude": 4.5,
|
||||||
"offset": 0.0,
|
"offset": 0.0,
|
||||||
"polarity": OUTPUTPOLARITY.POSITIVE,
|
"polarity": OUTPUTPOLARITY.POSITIVE,
|
||||||
"mode": "ttl",
|
"mode": "ttl",
|
||||||
@@ -131,6 +133,27 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
device_manager (DeviceManagerBase | None, optional): Device manager. Defaults to None.
|
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__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
@@ -142,6 +165,7 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
super().__init__(
|
super().__init__(
|
||||||
name=name, prefix=prefix, scan_info=scan_info, device_manager=device_manager, **kwargs
|
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.device_manager = device_manager
|
||||||
self._poll_thread = threading.Thread(target=self._poll_event_status, daemon=True)
|
self._poll_thread = threading.Thread(target=self._poll_event_status, daemon=True)
|
||||||
self._poll_thread_run_event = threading.Event()
|
self._poll_thread_run_event = threading.Event()
|
||||||
@@ -192,6 +216,21 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
self.burst_delay.put(0)
|
self.burst_delay.put(0)
|
||||||
self.burst_count.put(1)
|
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:
|
def on_stage(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -230,6 +269,18 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
if self.burst_count.get() != 1:
|
if self.burst_count.get() != 1:
|
||||||
self.burst_count.put(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 ###
|
### Setup timing for burst and delays ###
|
||||||
#########################################
|
#########################################
|
||||||
@@ -239,27 +290,34 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
|
|
||||||
# Burst Period DDG1
|
# Burst Period DDG1
|
||||||
# Set burst_period to shutter width
|
# Set burst_period to shutter width
|
||||||
# c/t0 + 2ms + exp_time * burst_count + 1ms
|
# c/t0 + self._shutter_to_open_delay + exp_time * burst_count
|
||||||
shutter_width = 2e-3 + exp_time * frames_per_trigger + 1e-3
|
shutter_width = (
|
||||||
|
self._shutter_to_open_delay + exp_time * frames_per_trigger
|
||||||
|
) # Shutter starts closing at end of exposure
|
||||||
if self.burst_period.get() != shutter_width:
|
if self.burst_period.get() != shutter_width:
|
||||||
self.burst_period.put(shutter_width)
|
self.burst_period.put(shutter_width)
|
||||||
|
|
||||||
# Trigger DDG2
|
# Trigger DDG2
|
||||||
# a = t0 + 2ms, b = a + 1us
|
# a = t0 + 2ms, b = a + 1us
|
||||||
# a has reference to t0, b has reference to a
|
# a has reference to t0, b has reference to a
|
||||||
# Add delay of 2ms to allow shutter to open
|
# Add delay of self._shutter_to_open_delay to allow shutter to open
|
||||||
self.set_delay_pairs(channel="ab", delay=2e-3, width=1e-6)
|
self.set_delay_pairs(channel="ab", delay=self._shutter_to_open_delay, width=1e-6)
|
||||||
|
|
||||||
# Trigger shutter
|
# Trigger shutter
|
||||||
# d = c/t0 + 2ms + exp_time * burst_count + 1ms
|
# d = c/t0 + self._shutter_to_open_delay + exp_time * burst_count + 1ms
|
||||||
# c has reference to t0, d has reference to c
|
# c has reference to t0, d has reference to c
|
||||||
# Shutter opens without delay at t0, closes after exp_time * burst_count + 3ms (2ms open, 1ms close)
|
# Shutter opens without delay at t0, closes after exp_time * burst_count + 2ms (self._shutter_to_open_delay)
|
||||||
self.set_delay_pairs(channel="cd", delay=0, width=shutter_width)
|
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
|
# Trigger extra pulse for MCS OR gate
|
||||||
# f = e + 1us
|
# f = e + 1us
|
||||||
# e has refernce to d, f has reference to e
|
# e has refernce to d, f has reference to e
|
||||||
self.set_delay_pairs(channel="ef", delay=0, width=1e-6)
|
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)
|
||||||
|
|
||||||
# NOTE Add additional sleep to make sure that the IOC and DDG HW process the values properly
|
# 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
|
# This value has been choosen empirically after testing with the HW. It's
|
||||||
@@ -431,7 +489,19 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
|
|
||||||
def on_trigger(self) -> DeviceStatus:
|
def on_trigger(self) -> DeviceStatus:
|
||||||
"""
|
"""
|
||||||
This method is called from BEC as a software trigger.
|
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.
|
||||||
|
|
||||||
It follows a specific procedure to ensure that the DDG1 and MCS card are properly handled
|
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:
|
on a trigger event. The established logic is as follows:
|
||||||
@@ -450,33 +520,46 @@ class DDG1(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
- Return the status object to BEC which will automatically resolve once the status register has
|
- 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.
|
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()
|
self._stop_polling()
|
||||||
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.
|
# NOTE If the trigger source is not SINGLE_SHOT, the DDG is triggered by an external source
|
||||||
# It has been empirically determined after long testing that this improves stability.
|
# thus we can not expect that trigger signals are meant to be awaited for. In this case,
|
||||||
time.sleep(0.02)
|
# we can directly return.
|
||||||
|
if self.trigger_source.get() != TRIGGERSOURCE.SINGLE_SHOT.value:
|
||||||
|
status = StatusBase(obj=self)
|
||||||
|
status.set_finished()
|
||||||
|
return status
|
||||||
|
|
||||||
# NOTE If the MCS card is present in the current session of BEC,
|
# 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
|
# we prepare the card for the next trigger. The procedure is implemented
|
||||||
# in the '_prepare_mcs_on_trigger' method.
|
# in the '_prepare_mcs_on_trigger' method. We will also use the mcs card
|
||||||
# Prepare the MCS card for the next software trigger
|
# to indicate when the burst cycle is done. If no mcs card is available
|
||||||
|
# the fallback is to use the polling of the DDG
|
||||||
mcs = self.device_manager.devices.get("mcs", None)
|
mcs = self.device_manager.devices.get("mcs", None)
|
||||||
if mcs is None or mcs.enabled is False:
|
if mcs is None or mcs.enabled is False or self.scan_info.msg.scan_type == "fly":
|
||||||
logger.info("Did not find mcs card with name 'mcs' in current session")
|
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()
|
||||||
else:
|
else:
|
||||||
|
start_time = time.time()
|
||||||
|
logger.debug(f"Preparing mcs card ")
|
||||||
status_mcs = self._prepare_mcs_on_trigger(mcs)
|
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
|
# 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
|
# an acquisition regularly with a WaitTimeoutError, the timeout can be increased but it should
|
||||||
# be investigated why the EPICS interface is slow to respond.
|
# be investigated why the EPICS interface is slow to respond.
|
||||||
status_mcs.wait(timeout=3)
|
status_mcs.wait(timeout=3)
|
||||||
|
status = TransitionStatus(mcs.acquiring, [ACQUIRING.ACQUIRING, ACQUIRING.DONE])
|
||||||
|
logger.debug(f"Finished preparing mcs card {time.time()-start_time}")
|
||||||
|
|
||||||
# Prepare StatusBitsCompareStatus to resolve once the END_OF_BURST bit was set.
|
# Send trigger
|
||||||
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.trigger_shot.put(1, use_complete=True)
|
||||||
|
self.cancel_on_stop(status)
|
||||||
|
logger.info(f"Configured ddg in {time.time()-overall_start}")
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def on_stop(self) -> None:
|
def on_stop(self) -> None:
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ from csaxs_bec.devices.epics.delay_generator_csaxs.delay_generator_csaxs import
|
|||||||
ChannelConfig,
|
ChannelConfig,
|
||||||
DelayGeneratorCSAXS,
|
DelayGeneratorCSAXS,
|
||||||
LiteralChannels,
|
LiteralChannels,
|
||||||
|
BURSTCONFIG,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
||||||
@@ -47,7 +48,7 @@ logger = bec_logger.logger
|
|||||||
|
|
||||||
# NOTE Default channel configuration for the DDG2 delay generator channels
|
# NOTE Default channel configuration for the DDG2 delay generator channels
|
||||||
_DEFAULT_CHANNEL_CONFIG: ChannelConfig = {
|
_DEFAULT_CHANNEL_CONFIG: ChannelConfig = {
|
||||||
"amplitude": 5.0,
|
"amplitude": 4.5,
|
||||||
"offset": 0.0,
|
"offset": 0.0,
|
||||||
"polarity": OUTPUTPOLARITY.POSITIVE,
|
"polarity": OUTPUTPOLARITY.POSITIVE,
|
||||||
"mode": "ttl",
|
"mode": "ttl",
|
||||||
@@ -134,6 +135,9 @@ class DDG2(PSIDeviceBase, DelayGeneratorCSAXS):
|
|||||||
self.set_trigger(DEFAULT_TRIGGER_SOURCE)
|
self.set_trigger(DEFAULT_TRIGGER_SOURCE)
|
||||||
self.set_references_for_channels(DEFAULT_REFERENCES)
|
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:
|
def on_stage(self) -> DeviceStatus | StatusBase | None:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -488,6 +488,7 @@ class DelayGeneratorCSAXS(Device):
|
|||||||
name="trigger_source",
|
name="trigger_source",
|
||||||
kind=Kind.omitted,
|
kind=Kind.omitted,
|
||||||
doc="Trigger Source for the DDG, options in TRIGGERSOURCE",
|
doc="Trigger Source for the DDG, options in TRIGGERSOURCE",
|
||||||
|
auto_monitor=True,
|
||||||
)
|
)
|
||||||
trigger_level = Cpt(
|
trigger_level = Cpt(
|
||||||
EpicsSignal,
|
EpicsSignal,
|
||||||
|
|||||||
435
csaxs_bec/devices/epics/eps.py
Normal file
435
csaxs_bec/devices/epics/eps.py
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
"""EPS module for cSAXS beamline: defines the EPS device with its components and methods."""
|
||||||
|
|
||||||
|
# fmt: off
|
||||||
|
# Disable Black formatting for this file to preserve an easier readable structure for the component definitions.
|
||||||
|
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from bec_lib.logger import bec_logger
|
||||||
|
from ophyd import Component as Cpt
|
||||||
|
from ophyd import Device, EpicsSignal, EpicsSignalRO, Kind
|
||||||
|
from ophyd_devices import PSIDeviceBase
|
||||||
|
|
||||||
|
logger = bec_logger.logger
|
||||||
|
|
||||||
|
# ---------------------------
|
||||||
|
# Registry: sections/channels
|
||||||
|
# ---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class EPSSubDevices(Device):
|
||||||
|
"""Base class for EPS sub-device components (e.g. alarms, valves, shutters). with common methods if needed."""
|
||||||
|
|
||||||
|
def describe(self) -> dict:
|
||||||
|
desc = super().describe()
|
||||||
|
for walk in self.walk_signals():
|
||||||
|
if walk.item.attr_name not in desc:
|
||||||
|
desc[walk.item.attr_name] = walk.item.describe()
|
||||||
|
return desc
|
||||||
|
|
||||||
|
|
||||||
|
class EPSAlarms(EPSSubDevices):
|
||||||
|
"""EPS alarms at the cSAXS beamline."""
|
||||||
|
|
||||||
|
eps_alarm_cnt = Cpt(EpicsSignalRO, read_pv="X12SA-EPS-PLC:AlarmCnt_EPS", add_prefix=("",), name="eps_alarm_cnt", kind=Kind.omitted, doc="X12SA EPS Alarm count", auto_monitor=True, labels={"alarm"})
|
||||||
|
mis_alarm_cnt = Cpt(EpicsSignalRO, read_pv="ARS00-MIS-PLC-01:AlarmCnt_Frontends", add_prefix=("",), name="mis_alarm_cnt", kind=Kind.omitted, doc="FrontEnd MIS Alarm count", auto_monitor=True, labels={"alarm"})
|
||||||
|
|
||||||
|
|
||||||
|
class ValvesFrontend(EPSSubDevices):
|
||||||
|
"""Valves frontend at the cSAXS beamline."""
|
||||||
|
|
||||||
|
|
||||||
|
fe_vvpg_0000 = Cpt(EpicsSignalRO, read_pv="X12SA-FE-VVPG-0000:PLC_OPEN", add_prefix=("",), name="fevvpg0000", kind=Kind.omitted, doc="FE-VVPG-0000", auto_monitor=True, labels={"valve"})
|
||||||
|
fe_vvpg_1010 = Cpt(EpicsSignalRO, read_pv="X12SA-FE-VVPG-1010:PLC_OPEN", add_prefix=("",), name="fevvpg1010", kind=Kind.omitted, doc="FE-VVPG-1010", auto_monitor=True, labels={"valve"})
|
||||||
|
fe_vvfv_2010 = Cpt(EpicsSignalRO, read_pv="X12SA-FE-VVFV-2010:PLC_OPEN", add_prefix=("",), name="fevvfv2010", kind=Kind.omitted, doc="FE-VVFV-2010", auto_monitor=True, labels={"valve"})
|
||||||
|
fe_vvpg_2010 = Cpt(EpicsSignalRO, read_pv="X12SA-FE-VVPG-2010:PLC_OPEN", add_prefix=("",), name="fevvpg2010", kind=Kind.omitted, doc="FE-VVPG-2010", auto_monitor=True, labels={"valve"})
|
||||||
|
|
||||||
|
class ValvesOptics(EPSSubDevices):
|
||||||
|
"""Valves at the optics hutch."""
|
||||||
|
|
||||||
|
op_vvpg_1010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-1010:PLC_OPEN", add_prefix=("",), name="opvvpg1010", kind=Kind.omitted, doc="OP-VVPG-1010", auto_monitor=True, labels={"valve"})
|
||||||
|
op_vvpg_2010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-2010:PLC_OPEN", add_prefix=("",), name="opvvpg2010", kind=Kind.omitted, doc="OP-VVPG-2010", auto_monitor=True, labels={"valve"})
|
||||||
|
op_vvpg_3010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-3010:PLC_OPEN", add_prefix=("",), name="opvvpg3010", kind=Kind.omitted, doc="OP-VVPG-3010", auto_monitor=True, labels={"valve"})
|
||||||
|
op_vvpg_3020 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-3020:PLC_OPEN", add_prefix=("",), name="opvvpg3020", kind=Kind.omitted, doc="OP-VVPG-3020", auto_monitor=True, labels={"valve"})
|
||||||
|
op_vvpg_4010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-4010:PLC_OPEN", add_prefix=("",), name="opvvpg4010", kind=Kind.omitted, doc="OP-VVPG-4010", auto_monitor=True, labels={"valve"})
|
||||||
|
op_vvpg_5010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-5010:PLC_OPEN", add_prefix=("",), name="opvvpg5010", kind=Kind.omitted, doc="OP-VVPG-5010", auto_monitor=True, labels={"valve"})
|
||||||
|
op_vvpg_6010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-6010:PLC_OPEN", add_prefix=("",), name="opvvpg6010", kind=Kind.omitted, doc="OP-VVPG-6010", auto_monitor=True, labels={"valve"})
|
||||||
|
op_vvpg_7010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-VVPG-7010:PLC_OPEN", add_prefix=("",), name="opvvpg7010", kind=Kind.omitted, doc="OP-VVPG-7010", auto_monitor=True, labels={"valve"})
|
||||||
|
|
||||||
|
|
||||||
|
class ValvesEndstation(EPSSubDevices):
|
||||||
|
"""Endstation valves at the cSAXS beamline."""
|
||||||
|
|
||||||
|
es_vvpg_1010 = Cpt(EpicsSignalRO, read_pv="X12SA-ES-VVPG-1010:PLC_OPEN", add_prefix=("",), name="esvvpg1010", kind=Kind.omitted, doc="ES-VVPG-1010", auto_monitor=True, labels={"valve"})
|
||||||
|
|
||||||
|
|
||||||
|
class ShuttersFrontend(EPSSubDevices):
|
||||||
|
"""Shutters frontend."""
|
||||||
|
|
||||||
|
fe_psh1 = Cpt(EpicsSignalRO, read_pv="X12SA-FE-PSH1-EMLS-0010:OPEN", add_prefix=("",), name="fepsh1", kind=Kind.omitted, doc="FE-PSH1-EMLS-0010", auto_monitor=True, labels={"shutter"})
|
||||||
|
fe_sto1 = Cpt(EpicsSignalRO, read_pv="X12SA-FE-STO1-EMLS-0010:OPEN", add_prefix=("",), name="festo1", kind=Kind.omitted, doc="FE-STO1-EMLS-0010", auto_monitor=True, labels={"shutter"})
|
||||||
|
|
||||||
|
|
||||||
|
class ShuttersEndstation(EPSSubDevices):
|
||||||
|
"""Shutters at the endstation."""
|
||||||
|
|
||||||
|
es_psh17010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-PSH1-EMLS-7010:OPEN", add_prefix=("",), name="espsh17010", kind=Kind.omitted, doc="OP-PSH1-EMLS-7010", auto_monitor=True, labels={"shutter"})
|
||||||
|
|
||||||
|
|
||||||
|
class DMMMonochromator(EPSSubDevices):
|
||||||
|
"""DMM monochromator signals at the cSAXS beamline."""
|
||||||
|
|
||||||
|
dmm_temp_surface_1 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-ETTC-3010:TEMP", add_prefix=("",), name="dmm_temp_surface_1", kind=Kind.omitted, doc="DMM Temp Surface 1", auto_monitor=True, labels={"temp"})
|
||||||
|
dmm_temp_surface_2 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-ETTC-3020:TEMP", add_prefix=("",), name="dmm_temp_surface_2", kind=Kind.omitted, doc="DMM Temp Surface 2", auto_monitor=True, labels={"temp"})
|
||||||
|
dmm_temp_shield_1_disaster = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-ETTC-3030:TEMP", add_prefix=("",), name="dmm_temp_shield_1_disaster", kind=Kind.omitted, doc="DMM Temp Shield 1 (disaster)", auto_monitor=True, labels={"temp"})
|
||||||
|
dmm_temp_shield_2_disaster = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-ETTC-3040:TEMP", add_prefix=("",), name="dmm_temp_shield_2_disaster", kind=Kind.omitted, doc="DMM Temp Shield 2 (disaster)", auto_monitor=True, labels={"temp"})
|
||||||
|
|
||||||
|
dmm_translation_thru = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-EMLS-3010:THRU", add_prefix=("",), name="dmm_translation_thru", kind=Kind.omitted, doc="DMM Translation ThruPos", auto_monitor=True, labels={"switch"})
|
||||||
|
dmm_translation_in = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-EMLS-3020:IN", add_prefix=("",), name="dmm_translation_in", kind=Kind.omitted, doc="DMM Translation InPos", auto_monitor=True, labels={"switch"})
|
||||||
|
dmm_bragg_thru = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-EMLS-3030:THRU", add_prefix=("",), name="dmm_bragg_thru", kind=Kind.omitted, doc="DMM Bragg ThruPos", auto_monitor=True, labels={"switch"})
|
||||||
|
dmm_bragg_in = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-EMLS-3040:IN", add_prefix=("",), name="dmm_bragg_in", kind=Kind.omitted, doc="DMM Bragg InPos", auto_monitor=True, labels={"switch"})
|
||||||
|
|
||||||
|
dmm_heater_fault_xtal_1 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-EMSW-3050:SWITCH", add_prefix=("",), name="dmm_heater_fault_xtal_1", kind=Kind.omitted, doc="DMM Heater Fault XTAL 1", auto_monitor=True, labels={"fault"})
|
||||||
|
dmm_heater_fault_xtal_2 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-EMSW-3060:SWITCH", add_prefix=("",), name="dmm_heater_fault_xtal_2", kind=Kind.omitted, doc="DMM Heater Fault XTAL 2", auto_monitor=True, labels={"fault"})
|
||||||
|
dmm_heater_fault_support_1 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM-EMSW-3070:SWITCH", add_prefix=("",), name="dmm_heater_fault_support_1", kind=Kind.omitted, doc="DMM Heater Fault Support 1", auto_monitor=True, labels={"fault"})
|
||||||
|
|
||||||
|
dmm_energy = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM1:ENERGY-GET", add_prefix=("",), name="dmm_energy", kind=Kind.omitted, doc="DMM Energy", auto_monitor=True, labels={"energy"})
|
||||||
|
dmm_position = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM1:POSITION", add_prefix=("",), name="dmm_position", kind=Kind.omitted, doc="DMM Position", auto_monitor=True, labels={"string"})
|
||||||
|
dmm_stripe = Cpt(EpicsSignalRO, read_pv="X12SA-OP-DMM1:STRIPE", add_prefix=("",), name="dmm_stripe", kind=Kind.omitted, doc="DMM Stripe", auto_monitor=True, labels={"string"})
|
||||||
|
|
||||||
|
|
||||||
|
class CCMMonochromator(EPSSubDevices):
|
||||||
|
"""CCM monochromator signals at the cSAXS beamline."""
|
||||||
|
|
||||||
|
ccm_temp_crystal = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CCM-ETTC-4010:TEMP", add_prefix=("",), name="ccm_temp_crystal", kind=Kind.omitted, doc="CCM Temp Crystal", auto_monitor=True, labels={"temp"})
|
||||||
|
ccm_temp_shield_disaster = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CCM-ETTC-4020:TEMP", add_prefix=("",), name="ccm_temp_shield_disaster", kind=Kind.omitted, doc="CCM Temp Shield (disaster)", auto_monitor=True, labels={"temp"})
|
||||||
|
|
||||||
|
ccm_heater_fault_1 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CCM-EMSW-4010:SWITCH", add_prefix=("",), name="ccm_heater_fault_1", kind=Kind.omitted, doc="CCM Heater Fault 1", auto_monitor=True, labels={"fault"})
|
||||||
|
ccm_heater_fault_2 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CCM-EMSW-4020:SWITCH", add_prefix=("",), name="ccm_heater_fault_2", kind=Kind.omitted, doc="CCM Heater Fault 2", auto_monitor=True, labels={"fault"})
|
||||||
|
ccm_heater_fault_3 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CCM-EMSW-4030:SWITCH", add_prefix=("",), name="ccm_heater_fault_3", kind=Kind.omitted, doc="CCM Heater Fault 3", auto_monitor=True, labels={"fault"})
|
||||||
|
|
||||||
|
ccm_energy = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CCM1:ENERGY-GET", add_prefix=("",), name="ccm_energy", kind=Kind.omitted, doc="CCM Energy", auto_monitor=True, labels={"energy"})
|
||||||
|
ccm_position = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CCM1:POSITION", add_prefix=("",), name="ccm_position", kind=Kind.omitted, doc="CCM Position", auto_monitor=True, labels={"string"})
|
||||||
|
|
||||||
|
|
||||||
|
class CoolingWater(EPSSubDevices):
|
||||||
|
"""Cooling water signals at the cSAXS beamline."""
|
||||||
|
|
||||||
|
op_sl1_efsw_2010_flow = Cpt(EpicsSignalRO, read_pv="X12SA-OP-SL1-EFSW-2010:FLOW", add_prefix=("",), name="op_sl1_efsw_2010_flow", kind=Kind.omitted, doc="OP-SL1-EFSW-2010", auto_monitor=True, labels={"flow"})
|
||||||
|
op_sl2_efsw_2010_flow = Cpt(EpicsSignalRO, read_pv="X12SA-OP-SL2-EFSW-2010:FLOW", add_prefix=("",), name="op_sl2_efsw_2010_flow", kind=Kind.omitted, doc="OP-SL2-EFSW-2010", auto_monitor=True, labels={"flow"})
|
||||||
|
op_eb1_efsw_5010_flow = Cpt(EpicsSignalRO, read_pv="X12SA-OP-EB1-EFSW-5010:FLOW", add_prefix=("",), name="op_eb1_efsw_5010_flow", kind=Kind.omitted, doc="OP-EB1-EFSW-5010", auto_monitor=True, labels={"flow"})
|
||||||
|
op_eb1_efsw_5020_flow = Cpt(EpicsSignalRO, read_pv="X12SA-OP-EB1-EFSW-5020:FLOW", add_prefix=("",), name="op_eb1_efsw_5020_flow", kind=Kind.omitted, doc="OP-EB1-EFSW-5020", auto_monitor=True, labels={"flow"})
|
||||||
|
op_sl3_efsw_5010_flow = Cpt(EpicsSignalRO, read_pv="X12SA-OP-SL3-EFSW-5010:FLOW", add_prefix=("",), name="op_sl3_efsw_5010_flow", kind=Kind.omitted, doc="OP-SL3-EFSW-5010", auto_monitor=True, labels={"flow"})
|
||||||
|
op_kb_efsw_6010_flow = Cpt(EpicsSignalRO, read_pv="X12SA-OP-KB-EFSW-6010:FLOW", add_prefix=("",), name="op_kb_efsw_6010_flow", kind=Kind.omitted, doc="OP-KB-EFSW-6010", auto_monitor=True, labels={"flow"})
|
||||||
|
op_psh1_efsw_7010_flow = Cpt(EpicsSignalRO, read_pv="X12SA-OP-PSH1-EFSW-7010:FLOW", add_prefix=("",), name="op_psh1_efsw_7010_flow", kind=Kind.omitted, doc="OP-PSH1-EFSW-7010", auto_monitor=True, labels={"flow"})
|
||||||
|
es_eb2_efsw_1010_flow = Cpt(EpicsSignalRO, read_pv="X12SA-ES-EB2-EFSW-1010:FLOW", add_prefix=("",), name="es_eb2_efsw_1010_flow", kind=Kind.omitted, doc="ES-EB2-EFSW-1010", auto_monitor=True, labels={"flow"})
|
||||||
|
|
||||||
|
op_cs_ecvw_0010 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CS-ECVW-0010:PLC_OPEN", add_prefix=("",), name="op_cs_ecvw_0010", kind=Kind.omitted, doc="OP-CS-ECVW-0010", auto_monitor=True, labels={"valve"})
|
||||||
|
op_cs_ecvw_0020 = Cpt(EpicsSignalRO, read_pv="X12SA-OP-CS-ECVW-0020:PLC_OPEN", add_prefix=("",), name="op_cs_ecvw_0020", kind=Kind.omitted, doc="OP-CS-ECVW-0020", auto_monitor=True, labels={"valve"})
|
||||||
|
|
||||||
|
|
||||||
|
class EPS(PSIDeviceBase):
|
||||||
|
"""EPS device for the cSAXS beamline."""
|
||||||
|
USER_ACCESS = [
|
||||||
|
"show_all",
|
||||||
|
"water_cooling_op",
|
||||||
|
]
|
||||||
|
alarms = Cpt(EPSAlarms, name="alarms", doc="EPS Alarms")
|
||||||
|
valves_frontend = Cpt(ValvesFrontend, name="valves_frontend", doc="Valves Frontend")
|
||||||
|
valves_optics = Cpt(ValvesOptics, name="valves_optics", doc="Valves Optics Hutch")
|
||||||
|
valves_es = Cpt(ValvesEndstation, name="valves_es", doc="Valves ES Hutch")
|
||||||
|
shutters_frontend = Cpt(ShuttersFrontend, name="shutters_frontend", doc="Shutters Frontend")
|
||||||
|
shutters_es = Cpt(ShuttersEndstation, name="shutters_es", doc="Shutters Endstation")
|
||||||
|
dmm_monochromator = Cpt(DMMMonochromator, name="dmm_monochromator", doc="DMM Monochromator")
|
||||||
|
ccm_monochromator = Cpt(CCMMonochromator, name="ccm_monochromator", doc="CCM Monochromator")
|
||||||
|
cooling_water = Cpt(CoolingWater, name="cooling_water", doc="Cooling Water")
|
||||||
|
|
||||||
|
# Acknowledgment signals for PLC communication (if needed for future use)
|
||||||
|
ackerr = Cpt(EpicsSignal, read_pv="X12SA-EPS-PLC:ACKERR-REQUEST", add_prefix=("",), name="ackerr", kind=Kind.omitted, doc="ACKERR request - OP-CS-ECVW-0020", auto_monitor=True, labels={"request"})
|
||||||
|
request = Cpt(EpicsSignal, read_pv="X12SA-OP-CS-ECVW:PLC_REQUEST", add_prefix=("",), name="op_cs_ecvw_request", kind=Kind.omitted, doc="PLC request - OP-CS-ECVW-PLC_REQUEST", auto_monitor=True, labels={"request"})
|
||||||
|
|
||||||
|
def _notify(self, msg: str, show_as_client_msg: bool = True):
|
||||||
|
"""Utility method to print a message, and optionally send it to the client UI if it should be shown also as a client message."""
|
||||||
|
try:
|
||||||
|
if show_as_client_msg:
|
||||||
|
self.device_manager.connector.send_client_info(msg, scope="", show_asap=True)
|
||||||
|
else:
|
||||||
|
print(msg)
|
||||||
|
except Exception:
|
||||||
|
logger.error(f"Failed to send client message, falling back to print: {msg}")
|
||||||
|
print(str(msg))
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Water cooling operation
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
|
||||||
|
def safe_get(self, sig, default=None):
|
||||||
|
"""Helper method to safely get a signal value, returning a default if there's an error."""
|
||||||
|
try:
|
||||||
|
return sig.get()
|
||||||
|
except Exception as ex:
|
||||||
|
logger.warning(f"Failed to get signal {sig.pvname}: {ex}")
|
||||||
|
return default
|
||||||
|
|
||||||
|
def water_cooling_op(self):
|
||||||
|
"""
|
||||||
|
Open ECVW valves, reset EPS alarms, monitor for 20s,
|
||||||
|
then ensure stability (valves remain open) for 10s.
|
||||||
|
All messages sent to client.
|
||||||
|
"""
|
||||||
|
|
||||||
|
POLL_PERIOD = 2
|
||||||
|
TIMEOUT = 20
|
||||||
|
STABILITY = 15
|
||||||
|
|
||||||
|
self._notify("=== Water Cooling Operation ===")
|
||||||
|
|
||||||
|
# --- Signals ---
|
||||||
|
eps_alarm_sig = self.alarms.eps_alarm_cnt
|
||||||
|
ackerr = self.ackerr
|
||||||
|
request = self.request
|
||||||
|
|
||||||
|
valves = [self.cooling_water.op_cs_ecvw_0010, self.cooling_water.op_cs_ecvw_0020]
|
||||||
|
|
||||||
|
# Flow channels list extracted from CHANNELS
|
||||||
|
flow_items = [walk.item for walk in self.cooling_water.walk_signals() if "flow" in walk.item._ophyd_labels_]
|
||||||
|
|
||||||
|
# --- Step 1: EPS alarm reset ---
|
||||||
|
alarm_value = self.safe_get(eps_alarm_sig, 0)
|
||||||
|
if alarm_value and alarm_value > 0:
|
||||||
|
self._notify(f"[WaterCooling] EPS alarms present ({alarm_value}) → resetting…")
|
||||||
|
try:
|
||||||
|
ackerr.put(1)
|
||||||
|
except Exception as ex:
|
||||||
|
self._notify(f"[WaterCooling] WARNING: ACKERR write failed: {ex}")
|
||||||
|
time.sleep(0.3)
|
||||||
|
else:
|
||||||
|
self._notify("[WaterCooling] No EPS alarms detected.")
|
||||||
|
|
||||||
|
# --- Step 2: Issue open request ---
|
||||||
|
self._notify("[WaterCooling] Sending cooling-valve OPEN request…")
|
||||||
|
try:
|
||||||
|
request.put(1)
|
||||||
|
except Exception as ex:
|
||||||
|
self._notify(f"[WaterCooling] ERROR: Failed to send OPEN request: {ex}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# --- Step 3: Monitoring loop (clean client table output) ---
|
||||||
|
start = time.time()
|
||||||
|
end = start + TIMEOUT
|
||||||
|
stable_until = None
|
||||||
|
|
||||||
|
# Print (server-side) header once
|
||||||
|
print("Monitoring valves and flow sensors...")
|
||||||
|
print(f" Valves: {valves[0].attr_name[-4:]}, {valves[1].attr_name[-4:]}")
|
||||||
|
print(f" Note: stability requires valves to remain OPEN for {STABILITY} seconds.")
|
||||||
|
|
||||||
|
# One table header to the client (via device manager)
|
||||||
|
# Fixed-width columns for alignment in monospaced UI
|
||||||
|
table_header = f"{'Time':>6} | {'Valves':<21} | {'Flows (OK/FAIL/N/A)':<20}"
|
||||||
|
self._notify(table_header)
|
||||||
|
|
||||||
|
def snapshot():
|
||||||
|
# Valve snapshot
|
||||||
|
v_states = [self.safe_get(v, None) for v in valves]
|
||||||
|
v1 = f"{valves[0].attr_name[-4:]}=" + ("OPEN " if v_states[0] is True or v_states[0] == 1 else "CLOSED" if v_states[0] is False or v_states[0] == 0 else "N/A ")
|
||||||
|
v2 = f"{valves[1].attr_name[-4:]}=" + ("OPEN " if v_states[1] is True or v_states[1] == 1 else "CLOSED" if v_states[1] is False or v_states[1] == 0 else "N/A ")
|
||||||
|
# 2 valves with a single space between => width ~ 21
|
||||||
|
valve_str = f"{v1} {v2}"
|
||||||
|
|
||||||
|
# Flow summary: OK/FAIL/N/A counts (compact)
|
||||||
|
flow_states = []
|
||||||
|
for fsig in flow_items:
|
||||||
|
fval = self.safe_get(fsig, None)
|
||||||
|
flow_states.append(True if fval in (1, True) else False if fval in (0, False) else None)
|
||||||
|
|
||||||
|
ok = sum(1 for f in flow_states if f is True)
|
||||||
|
fail = sum(1 for f in flow_states if f is False)
|
||||||
|
na = sum(1 for f in flow_states if f is None)
|
||||||
|
flow_summary = f"{ok:>2} / {fail:>2} / {na:>2}"
|
||||||
|
|
||||||
|
return v_states, valve_str, flow_summary
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# TODO Consider adding a timeout to avoid infinite loop.
|
||||||
|
now = time.time()
|
||||||
|
elapsed = int(now - start)
|
||||||
|
|
||||||
|
if now > end:
|
||||||
|
# One last line to client
|
||||||
|
v_states, valves_s, flows_s = snapshot()
|
||||||
|
self._notify(f"{elapsed:>6}s | {valves_s:<21} | {flows_s:<20}")
|
||||||
|
print("→ TIMEOUT: Cooling valves failed to remain OPEN.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Live snapshot
|
||||||
|
v_states, valves_s, flows_s = snapshot()
|
||||||
|
# Exactly one concise line to client per cycle
|
||||||
|
self._notify(f"{elapsed:>6}s | {valves_s:<21} | {flows_s:<20}")
|
||||||
|
|
||||||
|
both_open = all(s is not None and bool(s) for s in v_states)
|
||||||
|
|
||||||
|
if both_open:
|
||||||
|
if stable_until is None:
|
||||||
|
stable_until = now + STABILITY
|
||||||
|
print(f"[WaterCooling] Both valves OPEN → starting {STABILITY}s stability window…")
|
||||||
|
else:
|
||||||
|
if now >= stable_until:
|
||||||
|
print("→ SUCCESS: Valves remained OPEN during stability window.")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
if stable_until is not None:
|
||||||
|
print("[WaterCooling] Valve closed again → restarting stability window.")
|
||||||
|
stable_until = None
|
||||||
|
|
||||||
|
time.sleep(POLL_PERIOD)
|
||||||
|
|
||||||
|
def show_all(self):
|
||||||
|
red = "\x1b[91m"
|
||||||
|
green = "\x1b[92m"
|
||||||
|
white = "\x1b[0m"
|
||||||
|
bold = "\x1b[1m"
|
||||||
|
cyan = "\x1b[96m"
|
||||||
|
|
||||||
|
# ---- New: enum maps for numeric -> string rendering ----
|
||||||
|
POSITION_ENUM = {0: "out of beam", 1: "in beam"}
|
||||||
|
STRIPE_ENUM = {0: "Stripe 1 W/B4C", 1: "Stripe 2 NiV/B4C"}
|
||||||
|
POSITION_ATTRS = {self.dmm_monochromator.dmm_position.attr_name, self.ccm_monochromator.ccm_position.attr_name}
|
||||||
|
STRIPE_ATTRS = {self.dmm_monochromator.dmm_stripe.attr_name}
|
||||||
|
|
||||||
|
def is_bool_like(v):
|
||||||
|
return isinstance(v, (bool, int)) and v in (0, 1, True, False)
|
||||||
|
|
||||||
|
# ---- Changed: accept attr in formatter so we can apply enum mapping ----
|
||||||
|
def fmt_value(value: any, signal: EpicsSignalRO):
|
||||||
|
if value is None:
|
||||||
|
return f"{red}MISSING{white}"
|
||||||
|
|
||||||
|
attr = signal.attr_name
|
||||||
|
|
||||||
|
# ---------- Explicit enum mappings by attribute ----------
|
||||||
|
if attr in POSITION_ATTRS:
|
||||||
|
# Position comes as numeric 0/1
|
||||||
|
try:
|
||||||
|
iv = int(value)
|
||||||
|
return POSITION_ENUM.get(iv, f"{iv}")
|
||||||
|
except Exception:
|
||||||
|
# Fallback if it’s already a string or unexpected
|
||||||
|
return f"{value}"
|
||||||
|
|
||||||
|
if attr in STRIPE_ATTRS:
|
||||||
|
# Stripe comes as numeric 0/1
|
||||||
|
try:
|
||||||
|
iv = int(value)
|
||||||
|
return STRIPE_ENUM.get(iv, f"{iv}")
|
||||||
|
except Exception:
|
||||||
|
return f"{value}"
|
||||||
|
|
||||||
|
# ------------------- TEMPERATURE -------------------
|
||||||
|
if "temp" in signal._ophyd_labels_ and isinstance(value, (int, float)):
|
||||||
|
return f"{value:.1f}"
|
||||||
|
|
||||||
|
# ------------------- ENERGY ------------------------
|
||||||
|
if "energy" in signal._ophyd_labels_ and isinstance(value, (int, float)):
|
||||||
|
return f"{value:.4f}"
|
||||||
|
|
||||||
|
# ------------------- STRINGS -----------------------
|
||||||
|
if "string" in signal._ophyd_labels_ or "position" in signal._ophyd_labels_:
|
||||||
|
# For other strings, just echo the value
|
||||||
|
return f"{value}"
|
||||||
|
|
||||||
|
# ------------------- SWITCH (ACTIVE/INACTIVE) ------
|
||||||
|
if "switch" in signal._ophyd_labels_ and is_bool_like(value):
|
||||||
|
return f"{green+'ACTIVE'+white if value else red+'INACTIVE'+white}"
|
||||||
|
|
||||||
|
# ------------------- FAULT (OK/FAULT) --------------
|
||||||
|
if "fault" in signal._ophyd_labels_ and is_bool_like(value):
|
||||||
|
return f"{green+'OK'+white if not value else red+'FAULT'+white}"
|
||||||
|
|
||||||
|
# ------------------- VALVE/SHUTTER -----------------
|
||||||
|
if ("valve" in signal._ophyd_labels_ or "shutter" in signal._ophyd_labels_) and is_bool_like(value):
|
||||||
|
return f"{green+'OPEN'+white if value else red+'CLOSED'+white}"
|
||||||
|
|
||||||
|
# ------------------- FLOW (OK/FAIL) ----------------
|
||||||
|
if "flow" in signal._ophyd_labels_ and is_bool_like(value):
|
||||||
|
return f"{green}OK{white}" if bool(value) else f"{red}FAIL{white}"
|
||||||
|
|
||||||
|
# ------------------- FALLBACK -----------------------
|
||||||
|
return f"{value}"
|
||||||
|
|
||||||
|
# ------------------- PRINT START ---------------------
|
||||||
|
print(f"{bold}X12SA EPS status{white}")
|
||||||
|
|
||||||
|
for name, component in self._sig_attrs.items():
|
||||||
|
sub_device = getattr(self, name)
|
||||||
|
rows = []
|
||||||
|
# Only print sub-devices, not individual request signals
|
||||||
|
if not isinstance(sub_device, Device):
|
||||||
|
continue
|
||||||
|
print(f"\n{bold}{component.doc}{white}")
|
||||||
|
for sub_walk in sub_device.walk_components():
|
||||||
|
cpt: Cpt = sub_walk.item
|
||||||
|
it: EpicsSignalRO = getattr(sub_device, cpt.attr)
|
||||||
|
val = self.safe_get(it)
|
||||||
|
rows.append((cpt.doc, val, it))
|
||||||
|
|
||||||
|
label_width = max(32, *(len(label) for (label, _, _) in rows))
|
||||||
|
|
||||||
|
for label, value, it in rows:
|
||||||
|
fv = fmt_value(value, it) # <-- pass attr to formatter
|
||||||
|
print(f" - {label:<{label_width}} {fv}")
|
||||||
|
|
||||||
|
if sub_device.attr_name == "cooling_water":
|
||||||
|
v1 = self.safe_get(self.cooling_water.op_cs_ecvw_0010)
|
||||||
|
v2 = self.safe_get(self.cooling_water.op_cs_ecvw_0020)
|
||||||
|
|
||||||
|
def closed(v):
|
||||||
|
return is_bool_like(v) and not bool(v)
|
||||||
|
|
||||||
|
if closed(v1) and closed(v2):
|
||||||
|
print(f"\n{cyan}Hint:{white} Both water cooling valves are CLOSED.\n" f"You can open them using: {bold}dev.x12saEPS.water_cooling_op(){white}")
|
||||||
|
|
||||||
|
# fmt: on
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Consistency report
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# def consistency_report(self, *, verbose=True):
|
||||||
|
# missing = []
|
||||||
|
# dupes = []
|
||||||
|
# seen = {}
|
||||||
|
|
||||||
|
# for sub_device in self.walk_components():
|
||||||
|
# section = sub_device.name
|
||||||
|
# for walk in sub_device.walk_components():
|
||||||
|
# cpt: Cpt = walk.ancestors[-1]
|
||||||
|
# it: EpicsSignalRO = walk.item
|
||||||
|
# if not hasattr(self, it["attr"]):
|
||||||
|
# missing.append((section, it["attr"], it["label"], it["pv"]))
|
||||||
|
|
||||||
|
# pv = it["pv"]
|
||||||
|
# if pv in seen:
|
||||||
|
# dupes.append((pv, seen[pv], (section, it["attr"], it["label"])))
|
||||||
|
# else:
|
||||||
|
# seen[pv] = (section, it["attr"], it["label"])
|
||||||
|
|
||||||
|
# if verbose:
|
||||||
|
# print("=== Consistency Report ===")
|
||||||
|
|
||||||
|
# if missing:
|
||||||
|
# print("\nMissing attributes:")
|
||||||
|
# for sec, a, lbl, pv in missing:
|
||||||
|
# print(f" - [{sec}] {a} {lbl} pv={pv}")
|
||||||
|
# else:
|
||||||
|
# print("\nNo missing attributes.")
|
||||||
|
|
||||||
|
# if dupes:
|
||||||
|
# print("\nDuplicate PVs:")
|
||||||
|
# for pv, f1, f2 in dupes:
|
||||||
|
# print(f" {pv} → {f1} AND {f2}")
|
||||||
|
# else:
|
||||||
|
# print("\nNo duplicate PVs.")
|
||||||
|
|
||||||
|
# return {"missing_attrs": missing, "duplicate_pvs": dupes}
|
||||||
67
csaxs_bec/devices/epics/fast_shutter.py
Normal file
67
csaxs_bec/devices/epics/fast_shutter.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
"""
|
||||||
|
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,7 +22,13 @@ import numpy as np
|
|||||||
from bec_lib.logger import bec_logger
|
from bec_lib.logger import bec_logger
|
||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import EpicsSignalRO, Kind
|
from ophyd import EpicsSignalRO, Kind
|
||||||
from ophyd_devices import AsyncMultiSignal, CompareStatus, ProgressSignal, StatusBase
|
from ophyd_devices import (
|
||||||
|
AsyncMultiSignal,
|
||||||
|
CompareStatus,
|
||||||
|
ProgressSignal,
|
||||||
|
StatusBase,
|
||||||
|
TransitionStatus,
|
||||||
|
)
|
||||||
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase
|
||||||
|
|
||||||
from csaxs_bec.devices.epics.mcs_card.mcs_card import (
|
from csaxs_bec.devices.epics.mcs_card.mcs_card import (
|
||||||
@@ -255,6 +261,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
**kwargs: Additional keyword arguments from the subscription, including 'obj' (the EpicsSignalRO instance).
|
**kwargs: Additional keyword arguments from the subscription, including 'obj' (the EpicsSignalRO instance).
|
||||||
"""
|
"""
|
||||||
with self._rlock:
|
with self._rlock:
|
||||||
|
logger.info(f"Received update on mcs card {self.name}")
|
||||||
if self._omit_mca_callbacks.is_set():
|
if self._omit_mca_callbacks.is_set():
|
||||||
return # Suppress callbacks when erasing all channels
|
return # Suppress callbacks when erasing all channels
|
||||||
self._mca_counter_index += 1
|
self._mca_counter_index += 1
|
||||||
@@ -286,7 +293,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Once we have received all channels, push data to BEC and reset for next accumulation
|
# Once we have received all channels, push data to BEC and reset for next accumulation
|
||||||
logger.debug(
|
logger.info(
|
||||||
f"Received update for {attr_name}, index {self._mca_counter_index}/{self.NUM_MCA_CHANNELS}"
|
f"Received update for {attr_name}, index {self._mca_counter_index}/{self.NUM_MCA_CHANNELS}"
|
||||||
)
|
)
|
||||||
if len(self._current_data) == self.NUM_MCA_CHANNELS:
|
if len(self._current_data) == self.NUM_MCA_CHANNELS:
|
||||||
@@ -363,7 +370,10 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
self._num_total_triggers = triggers * num_points
|
self._num_total_triggers = triggers * num_points
|
||||||
self._acquisition_group = "monitored" if triggers == 1 else "burst_group"
|
self._acquisition_group = "monitored" if triggers == 1 else "burst_group"
|
||||||
self.preset_real.set(0).wait(timeout=self._pv_timeout)
|
self.preset_real.set(0).wait(timeout=self._pv_timeout)
|
||||||
self.num_use_all.set(triggers).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)
|
||||||
|
|
||||||
# Clear any previous data, just to be sure
|
# Clear any previous data, just to be sure
|
||||||
with self._rlock:
|
with self._rlock:
|
||||||
@@ -385,6 +395,21 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
self._omit_mca_callbacks.clear()
|
self._omit_mca_callbacks.clear()
|
||||||
|
|
||||||
logger.info(f"MCS Card {self.name} on_stage completed in {time.time() - start_time:.3f}s.")
|
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:
|
def on_unstage(self) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -422,9 +447,16 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
hasattr(self.scan_info.msg, "num_points")
|
hasattr(self.scan_info.msg, "num_points")
|
||||||
and self.scan_info.msg.num_points is not None
|
and self.scan_info.msg.num_points is not None
|
||||||
):
|
):
|
||||||
if self._current_data_index == self.scan_info.msg.num_points:
|
if self.scan_info.msg.scan_type == "step":
|
||||||
for callback in self._scan_done_callbacks:
|
if self._current_data_index == self.scan_info.msg.num_points:
|
||||||
callback(exception=None)
|
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)
|
||||||
|
|
||||||
time.sleep(0.02) # 20ms delay to avoid busy loop
|
time.sleep(0.02) # 20ms delay to avoid busy loop
|
||||||
except Exception as exc: # pylint: disable=broad-except
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
content = traceback.format_exc()
|
content = traceback.format_exc()
|
||||||
@@ -452,7 +484,6 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
"""Callback for status failure, the monitoring thread should be stopped."""
|
"""Callback for status failure, the monitoring thread should be stopped."""
|
||||||
# NOTE Check for status.done and status.success is important to avoid
|
# NOTE Check for status.done and status.success is important to avoid
|
||||||
if status.done:
|
if status.done:
|
||||||
|
|
||||||
self._start_monitor_async_data_emission.clear() # Stop monitoring
|
self._start_monitor_async_data_emission.clear() # Stop monitoring
|
||||||
|
|
||||||
def on_complete(self) -> CompareStatus:
|
def on_complete(self) -> CompareStatus:
|
||||||
@@ -478,6 +509,13 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
monitoring thread is stopped properly.
|
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
|
# Prepare and register status callback for the async monitoring loop
|
||||||
status_async_data = StatusBase(obj=self)
|
status_async_data = StatusBase(obj=self)
|
||||||
self._scan_done_callbacks.append(partial(self._status_callback, status_async_data))
|
self._scan_done_callbacks.append(partial(self._status_callback, status_async_data))
|
||||||
@@ -491,7 +529,7 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard):
|
|||||||
|
|
||||||
# Combine both statuses
|
# Combine both statuses
|
||||||
ret_status = status & status_async_data
|
ret_status = status & status_async_data
|
||||||
# Handle external stop/cancel, and stop monitoring
|
# NOTE: Handle external stop/cancel, and stop monitoring
|
||||||
ret_status.add_callback(self._status_failed_callback)
|
ret_status.add_callback(self._status_failed_callback)
|
||||||
self.cancel_on_stop(ret_status)
|
self.cancel_on_stop(ret_status)
|
||||||
return ret_status
|
return ret_status
|
||||||
|
|||||||
@@ -498,6 +498,9 @@ class RtFlomniController(Controller):
|
|||||||
)
|
)
|
||||||
# while scan is running
|
# while scan is running
|
||||||
while mode > 0:
|
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}")
|
# 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()
|
mode, number_of_positions_planned, current_position_in_scan = self.get_scan_status()
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
@@ -629,6 +632,8 @@ class RtFlomniMotor(Device, PositionerBase):
|
|||||||
SUB_CONNECTION_CHANGE = "connection_change"
|
SUB_CONNECTION_CHANGE = "connection_change"
|
||||||
_default_sub = SUB_READBACK
|
_default_sub = SUB_READBACK
|
||||||
|
|
||||||
|
connectionTimeout = 20
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
axis_Id,
|
axis_Id,
|
||||||
|
|||||||
@@ -1,82 +1,87 @@
|
|||||||
import time
|
"""
|
||||||
import socket
|
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
|
||||||
from ophyd import Component as Cpt
|
from ophyd import Component as Cpt
|
||||||
from ophyd import Device
|
from ophyd import Device, Signal
|
||||||
from ophyd import EpicsSignal
|
from ophyd_devices import PSIDeviceBase
|
||||||
|
|
||||||
|
logger = bec_logger.logger
|
||||||
|
|
||||||
|
|
||||||
class OMNYFastEpicsShutterError(Exception):
|
class OMNYFastShutter(PSIDeviceBase, Device):
|
||||||
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 EPICS shutter with automatic PV selection based on host subnet.
|
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.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
USER_ACCESS = ["fshopen", "fshclose", "fshstatus", "fshinfo", "help"]
|
USER_ACCESS = ["fshopen", "fshclose", "fshstatus", "fshinfo", "help", "fshstatus_readback"]
|
||||||
SUB_VALUE = "value"
|
SUB_VALUE = "value"
|
||||||
_default_sub = SUB_VALUE
|
_default_sub = SUB_VALUE
|
||||||
|
|
||||||
# PV is detected dynamically at import time
|
shutter = Cpt(Signal, name="shutter")
|
||||||
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
|
# 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):
|
def fshopen(self):
|
||||||
"""Open the fast shutter."""
|
"""Open the fast shutter."""
|
||||||
try:
|
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||||
self.shutter.put(1, wait=True)
|
return self.device_manager.devices["fsh"].fshopen()
|
||||||
except Exception as ex:
|
else:
|
||||||
raise OMNYFastEpicsShutterError(f"Failed to open shutter: {ex}")
|
self.shutter.put(1)
|
||||||
|
|
||||||
def fshclose(self):
|
def fshclose(self):
|
||||||
"""Close the fast shutter."""
|
"""Close the fast shutter."""
|
||||||
try:
|
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||||
self.shutter.put(0, wait=True)
|
return self.device_manager.devices["fsh"].fshclose()
|
||||||
except Exception as ex:
|
else:
|
||||||
raise OMNYFastEpicsShutterError(f"Failed to close shutter: {ex}")
|
self.shutter.put(0)
|
||||||
|
|
||||||
def fshstatus(self):
|
def fshstatus(self):
|
||||||
"""Return the fast shutter status (0=closed, 1=open)."""
|
"""Return the fast shutter status (0=closed, 1=open)."""
|
||||||
try:
|
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||||
|
return self.device_manager.devices["fsh"].fshstatus()
|
||||||
|
else:
|
||||||
return self.shutter.get()
|
return self.shutter.get()
|
||||||
except Exception as ex:
|
|
||||||
raise OMNYFastEpicsShutterError(f"Failed to read shutter status: {ex}")
|
|
||||||
|
|
||||||
def fshinfo(self):
|
def fshinfo(self):
|
||||||
"""Print information about which EPICS PV channel is being used."""
|
"""Print information about which EPICS PV channel is being used."""
|
||||||
pvname = self.shutter.pvname
|
if self._check_if_cSAXS_shutter_exists_in_config():
|
||||||
print(f"Fast shutter connected to EPICS channel: {pvname}")
|
return self.device_manager.devices["fsh"].fshinfo()
|
||||||
return pvname
|
else:
|
||||||
|
print("Using dummy fast shutter device. No EPICS channel is connected.")
|
||||||
|
|
||||||
def help(self):
|
def help(self):
|
||||||
"""Display available user methods."""
|
"""Display available user methods."""
|
||||||
print("Available methods:")
|
print("Available methods:")
|
||||||
for method in self.USER_ACCESS:
|
for method in self.USER_ACCESS:
|
||||||
print(f" - {method}")
|
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,6 +27,7 @@ from bec_lib import bec_logger, messages
|
|||||||
from bec_lib.endpoints import MessageEndpoints
|
from bec_lib.endpoints import MessageEndpoints
|
||||||
from bec_server.scan_server.errors import ScanAbortion
|
from bec_server.scan_server.errors import ScanAbortion
|
||||||
from bec_server.scan_server.scans import SyncFlyScanBase
|
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
|
logger = bec_logger.logger
|
||||||
|
|
||||||
@@ -73,14 +74,13 @@ 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)
|
>>> 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, **kwargs)
|
super().__init__(parameter=parameter, exp_time=exp_time, **kwargs)
|
||||||
self.show_live_table = False
|
self.show_live_table = False
|
||||||
self.axis = []
|
self.axis = []
|
||||||
self.fovx = fovx
|
self.fovx = fovx
|
||||||
self.fovy = fovy
|
self.fovy = fovy
|
||||||
self.cenx = cenx
|
self.cenx = cenx
|
||||||
self.ceny = ceny
|
self.ceny = ceny
|
||||||
self.exp_time = exp_time
|
|
||||||
self.step = step
|
self.step = step
|
||||||
self.zshift = zshift
|
self.zshift = zshift
|
||||||
self.angle = angle
|
self.angle = angle
|
||||||
@@ -151,6 +151,9 @@ class FlomniFermatScan(SyncFlyScanBase):
|
|||||||
yield from self.stubs.send_rpc_and_wait("rty", "set", self.positions[0][1])
|
yield from self.stubs.send_rpc_and_wait("rty", "set", self.positions[0][1])
|
||||||
|
|
||||||
def _prepare_setup_part2(self):
|
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:
|
if self.flomni_rotation_status:
|
||||||
self.flomni_rotation_status.wait()
|
self.flomni_rotation_status.wait()
|
||||||
|
|
||||||
@@ -307,6 +310,10 @@ class FlomniFermatScan(SyncFlyScanBase):
|
|||||||
|
|
||||||
logger.warning("No positions found to return to start")
|
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):
|
def run(self):
|
||||||
self.initialize()
|
self.initialize()
|
||||||
yield from self.read_scan_motors()
|
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,10 +282,11 @@ 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["exp_time"] = exp_time
|
||||||
mock_ddg1.scan_info.msg.scan_parameters["frames_per_trigger"] = frames_per_trigger
|
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()
|
mock_ddg1.stage()
|
||||||
|
|
||||||
shutter_width = 2e-3 + exp_time * frames_per_trigger + 1e-3
|
shutter_width = mock_ddg1._shutter_to_open_delay + exp_time * frames_per_trigger
|
||||||
|
|
||||||
assert np.isclose(mock_ddg1.burst_mode.get(), 1) # burst mode is enabled
|
assert np.isclose(mock_ddg1.burst_mode.get(), 1) # burst mode is enabled
|
||||||
assert np.isclose(mock_ddg1.burst_delay.get(), 0)
|
assert np.isclose(mock_ddg1.burst_delay.get(), 0)
|
||||||
@@ -302,6 +303,25 @@ def test_ddg1_stage(mock_ddg1: DDG1):
|
|||||||
assert np.isclose(mock_ddg1.ef.width.get(), 1e-6)
|
assert np.isclose(mock_ddg1.ef.width.get(), 1e-6)
|
||||||
|
|
||||||
assert mock_ddg1.staged == ophyd.Staged.yes
|
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):
|
def test_ddg1_on_trigger(mock_ddg1: DDG1):
|
||||||
@@ -331,9 +351,28 @@ def test_ddg1_on_trigger(mock_ddg1: DDG1):
|
|||||||
#################################
|
#################################
|
||||||
with mock.patch.object(ddg, "_prepare_mcs_on_trigger") as mock_prepare_mcs:
|
with mock.patch.object(ddg, "_prepare_mcs_on_trigger") as mock_prepare_mcs:
|
||||||
mock_prepare_mcs.return_value = ophyd.StatusBase(done=True, success=True)
|
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()
|
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
|
# 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 ddg._poll_thread_run_event.is_set()
|
||||||
assert not ddg._poll_thread_poll_loop_done.is_set()
|
assert not ddg._poll_thread_poll_loop_done.is_set()
|
||||||
|
|
||||||
|
|||||||
37
tests/tests_devices/test_epics_devices.py
Normal file
37
tests/tests_devices/test_epics_devices.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
"""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"
|
||||||
99
tests/tests_devices/test_eps.py
Normal file
99
tests/tests_devices/test_eps.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# pylint: skip-file
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from ophyd_devices.tests.utils import patched_device
|
||||||
|
|
||||||
|
from csaxs_bec.devices.epics.eps import EPS
|
||||||
|
|
||||||
|
ALL_PVS = [
|
||||||
|
# ALARMS
|
||||||
|
"X12SA-EPS-PLC:AlarmCnt_EPS",
|
||||||
|
"ARS00-MIS-PLC-01:AlarmCnt_Frontends",
|
||||||
|
# FRONTEND VALVES
|
||||||
|
"X12SA-FE-VVPG-0000:PLC_OPEN",
|
||||||
|
"X12SA-FE-VVPG-1010:PLC_OPEN",
|
||||||
|
"X12SA-FE-VVFV-2010:PLC_OPEN",
|
||||||
|
"X12SA-FE-VVPG-2010:PLC_OPEN",
|
||||||
|
# Optics VALVES
|
||||||
|
"X12SA-OP-VVPG-1010:PLC_OPEN",
|
||||||
|
"X12SA-OP-VVPG-2010:PLC_OPEN",
|
||||||
|
"X12SA-OP-VVPG-3010:PLC_OPEN",
|
||||||
|
"X12SA-OP-VVPG-3020:PLC_OPEN",
|
||||||
|
"X12SA-OP-VVPG-4010:PLC_OPEN",
|
||||||
|
"X12SA-OP-VVPG-5010:PLC_OPEN",
|
||||||
|
"X12SA-OP-VVPG-6010:PLC_OPEN",
|
||||||
|
"X12SA-OP-VVPG-7010:PLC_OPEN",
|
||||||
|
# Endstation VALVES
|
||||||
|
"X12SA-ES-VVPG-1010:PLC_OPEN",
|
||||||
|
# Frontend SHUTTERS
|
||||||
|
"X12SA-FE-PSH1-EMLS-0010:OPEN",
|
||||||
|
"X12SA-FE-STO1-EMLS-0010:OPEN",
|
||||||
|
# Optics SHUTTERS
|
||||||
|
"X12SA-OP-PSH1-EMLS-7010:OPEN",
|
||||||
|
# DMM Monochromator
|
||||||
|
"X12SA-OP-DMM-ETTC-3010:TEMP",
|
||||||
|
"X12SA-OP-DMM-ETTC-3020:TEMP",
|
||||||
|
"X12SA-OP-DMM-ETTC-3030:TEMP",
|
||||||
|
"X12SA-OP-DMM-ETTC-3040:TEMP",
|
||||||
|
"X12SA-OP-DMM-EMLS-3010:THRU",
|
||||||
|
"X12SA-OP-DMM-EMLS-3020:IN",
|
||||||
|
"X12SA-OP-DMM-EMLS-3030:THRU",
|
||||||
|
"X12SA-OP-DMM-EMLS-3040:IN",
|
||||||
|
"X12SA-OP-DMM-EMSW-3050:SWITCH",
|
||||||
|
"X12SA-OP-DMM-EMSW-3060:SWITCH",
|
||||||
|
"X12SA-OP-DMM-EMSW-3070:SWITCH",
|
||||||
|
"X12SA-OP-DMM1:ENERGY-GET",
|
||||||
|
"X12SA-OP-DMM1:POSITION",
|
||||||
|
"X12SA-OP-DMM1:STRIPE",
|
||||||
|
# CCM Monochromator
|
||||||
|
"X12SA-OP-CCM-ETTC-4010:TEMP",
|
||||||
|
"X12SA-OP-CCM-ETTC-4020:TEMP",
|
||||||
|
"X12SA-OP-CCM-EMSW-4010:SWITCH",
|
||||||
|
"X12SA-OP-CCM-EMSW-4020:SWITCH",
|
||||||
|
"X12SA-OP-CCM-EMSW-4030:SWITCH",
|
||||||
|
"X12SA-OP-CCM1:ENERGY-GET",
|
||||||
|
"X12SA-OP-CCM1:POSITION",
|
||||||
|
# Water Cooling
|
||||||
|
"X12SA-OP-SL1-EFSW-2010:FLOW",
|
||||||
|
"X12SA-OP-SL2-EFSW-2010:FLOW",
|
||||||
|
"X12SA-OP-EB1-EFSW-5010:FLOW",
|
||||||
|
"X12SA-OP-EB1-EFSW-5020:FLOW",
|
||||||
|
"X12SA-OP-SL3-EFSW-5010:FLOW",
|
||||||
|
"X12SA-OP-KB-EFSW-6010:FLOW",
|
||||||
|
"X12SA-OP-PSH1-EFSW-7010:FLOW",
|
||||||
|
"X12SA-ES-EB2-EFSW-1010:FLOW",
|
||||||
|
"X12SA-OP-CS-ECVW-0010:PLC_OPEN",
|
||||||
|
"X12SA-OP-CS-ECVW-0020:PLC_OPEN",
|
||||||
|
# Request PVs
|
||||||
|
"X12SA-EPS-PLC:ACKERR-REQUEST",
|
||||||
|
"X12SA-OP-CS-ECVW:PLC_REQUEST",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def eps():
|
||||||
|
dev_name = "EPS"
|
||||||
|
with patched_device(EPS, name=dev_name) as eps:
|
||||||
|
yield eps
|
||||||
|
|
||||||
|
|
||||||
|
def test_eps_has_signals(eps):
|
||||||
|
"""Test that all expected PVs are present in the eps device."""
|
||||||
|
found_pvs = [walk.item._read_pv.pvname for walk in eps.walk_signals()]
|
||||||
|
assert set(found_pvs) == set(
|
||||||
|
ALL_PVS
|
||||||
|
), f"Expected PVs {ALL_PVS} but found {set(ALL_PVS) - set(found_pvs)}"
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
expected_show_all_output = "\x1b[1mX12SA EPS status\x1b[0m\n\n\x1b[1mEPS Alarms\x1b[0m\n - X12SA EPS Alarm count 0\n - FrontEnd MIS Alarm count 0\n\n\x1b[1mValves Frontend\x1b[0m\n - FE-VVPG-0000 \x1b[91mCLOSED\x1b[0m\n - FE-VVPG-1010 \x1b[91mCLOSED\x1b[0m\n - FE-VVFV-2010 \x1b[91mCLOSED\x1b[0m\n - FE-VVPG-2010 \x1b[91mCLOSED\x1b[0m\n\n\x1b[1mValves Optics Hutch\x1b[0m\n - OP-VVPG-1010 \x1b[91mCLOSED\x1b[0m\n - OP-VVPG-2010 \x1b[91mCLOSED\x1b[0m\n - OP-VVPG-3010 \x1b[91mCLOSED\x1b[0m\n - OP-VVPG-3020 \x1b[91mCLOSED\x1b[0m\n - OP-VVPG-4010 \x1b[91mCLOSED\x1b[0m\n - OP-VVPG-5010 \x1b[91mCLOSED\x1b[0m\n - OP-VVPG-6010 \x1b[91mCLOSED\x1b[0m\n - OP-VVPG-7010 \x1b[91mCLOSED\x1b[0m\n\n\x1b[1mValves ES Hutch\x1b[0m\n - ES-VVPG-1010 \x1b[91mCLOSED\x1b[0m\n\n\x1b[1mShutters Frontend\x1b[0m\n - FE-PSH1-EMLS-0010 \x1b[91mCLOSED\x1b[0m\n - FE-STO1-EMLS-0010 \x1b[91mCLOSED\x1b[0m\n\n\x1b[1mShutters Endstation\x1b[0m\n - OP-PSH1-EMLS-7010 \x1b[91mCLOSED\x1b[0m\n\n\x1b[1mDMM Monochromator\x1b[0m\n - DMM Temp Surface 1 0.0\n - DMM Temp Surface 2 0.0\n - DMM Temp Shield 1 (disaster) 0.0\n - DMM Temp Shield 2 (disaster) 0.0\n - DMM Translation ThruPos \x1b[91mINACTIVE\x1b[0m\n - DMM Translation InPos \x1b[91mINACTIVE\x1b[0m\n - DMM Bragg ThruPos \x1b[91mINACTIVE\x1b[0m\n - DMM Bragg InPos \x1b[91mINACTIVE\x1b[0m\n - DMM Heater Fault XTAL 1 \x1b[92mOK\x1b[0m\n - DMM Heater Fault XTAL 2 \x1b[92mOK\x1b[0m\n - DMM Heater Fault Support 1 \x1b[92mOK\x1b[0m\n - DMM Energy 0.0000\n - DMM Position out of beam\n - DMM Stripe Stripe 1 W/B4C\n\n\x1b[1mCCM Monochromator\x1b[0m\n - CCM Temp Crystal 0.0\n - CCM Temp Shield (disaster) 0.0\n - CCM Heater Fault 1 \x1b[92mOK\x1b[0m\n - CCM Heater Fault 2 \x1b[92mOK\x1b[0m\n - CCM Heater Fault 3 \x1b[92mOK\x1b[0m\n - CCM Energy 0.0000\n - CCM Position out of beam\n\n\x1b[1mCooling Water\x1b[0m\n - OP-SL1-EFSW-2010 \x1b[91mFAIL\x1b[0m\n - OP-SL2-EFSW-2010 \x1b[91mFAIL\x1b[0m\n - OP-EB1-EFSW-5010 \x1b[91mFAIL\x1b[0m\n - OP-EB1-EFSW-5020 \x1b[91mFAIL\x1b[0m\n - OP-SL3-EFSW-5010 \x1b[91mFAIL\x1b[0m\n - OP-KB-EFSW-6010 \x1b[91mFAIL\x1b[0m\n - OP-PSH1-EFSW-7010 \x1b[91mFAIL\x1b[0m\n - ES-EB2-EFSW-1010 \x1b[91mFAIL\x1b[0m\n - OP-CS-ECVW-0010 \x1b[91mCLOSED\x1b[0m\n - OP-CS-ECVW-0020 \x1b[91mCLOSED\x1b[0m\n\n\x1b[96mHint:\x1b[0m Both water cooling valves are CLOSED.\nYou can open them using: \x1b[1mdev.x12saEPS.water_cooling_op()\x1b[0m\n"
|
||||||
|
|
||||||
|
|
||||||
|
def test_eps_show_all(eps, capsys):
|
||||||
|
"""Test that the show_all method outputs the expected status."""
|
||||||
|
eps.show_all()
|
||||||
|
output = capsys.readouterr().out
|
||||||
|
assert (
|
||||||
|
output == expected_show_all_output
|
||||||
|
), f"Expected output does not match actual output.\nExpected:\n{expected_show_all_output}\nActual:\n{output}"
|
||||||
Reference in New Issue
Block a user