diff --git a/pxiii_bec/device_configs/DbGenerator.py b/pxiii_bec/device_configs/DbGenerator.py deleted file mode 100644 index 62b95f8..0000000 --- a/pxiii_bec/device_configs/DbGenerator.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Wed Aug 31 10:27:18 2022 - -Database migration from a sensible format to the BEC YAML file format - -@author: mohacsi_i -""" - -import yaml -import yaml.representer - - - -def MigrateYamlFile(filein, fileout): - """ Migrates an absolutely minimal YAML config file to the format - required by the BEC (i.e. adding default fields). - """ - fp = open(filein, "r") - lut = yaml.load(fp, Loader=yaml.Loader) - - # Allocate empty database - db = dict() - - for k,v in lut.items(): - new = v - - # Adding defaults - if 'onFailure' not in new: - new['onFailure'] = "buffer" - if 'enabled' not in new: - new['enabled'] = True - if 'readoutPriority' not in new: - new['readoutPriority'] = "monitored" - if 'readOnly' not in new: - new['readOnly'] = bool(new['deviceClass'] in ('ophyd.EpicsSignalRO')) - if 'softwareTrigger' not in new: - new['softwareTrigger'] = False - - if new['deviceClass'] == "ophyd.EpicsSignalRO": - if "read_pv" not in new['deviceConfig']: - new["deviceConfig"]["read_pv"] = new["deviceConfig"]["prefix"] - del new["deviceConfig"]["prefix"] - - - db[k] = new - - with open(fileout, 'w') as stream: - yaml.dump(db, stream, default_flow_style=None, sort_keys=False) - - - -# Automatically start simulation if directly invoked -if __name__ == "__main__": - MigrateYamlFile("./x06da_compact.lmay", "x06da_device_config.yaml") diff --git a/pxiii_bec/device_configs/x06da_compact.lmay b/pxiii_bec/device_configs/x06da_compact.lmay deleted file mode 100644 index 7ad90d4..0000000 --- a/pxiii_bec/device_configs/x06da_compact.lmay +++ /dev/null @@ -1,206 +0,0 @@ -# OP before mono -slh_trxr: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-SLH:TRXR' -slh_trxw: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-SLH:TRXW' -fi1_try: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-FI1:TRY' - -# DCCM crystal 1 -dccm_pitch1: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-DCCM:PITCH1' -dccm_energy1: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-DCCM:ENERGY1' -dccm_diode: - deviceClass: ophyd.EpicsSignalRO - deviceConfig: - prefix: 'X06DA-OP-XPM1:BOT:READOUT' - -# DCCM crystal 2 -dccm_pitch2: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-DCCM:PITCH2' -dccm_energy2: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-DCCM:ENERGY2' -dccm_xbpm: - deviceClass: ophyd.EpicsSignalRO - deviceConfig: - prefix: 'X06DA-OP-XBPM1:SumAll:MeanValue_RBV' - -# DCCM common - -dccm_energy: - description: Monochromator energy using ECMC virtual motors - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-DCCM:_ENERGY' -dccm_eoffset: - description: Monochromator energy offset for ECMC virtual motors - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-OP-DCCM:_EOFFSET' - -# Secondary source XBPM -ssxbpm_trx: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSBPM1:TRX' -ssxbpm_try: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSBPM1:TRY' - -ssslit_trxr: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSSLH1:TRXR' -ssslit_trxw: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSSLH1:TRXW' -ssslit_tryt: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSSLV1:TRYT' -ssslit_tryb: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSSLV1:TRYB' -ssxi1_trx: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSXI1:TRX' -ssxi1_try: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES-SSXI1:TRY' - -# Vertical focusing mirror -vfm_trxu: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:TRXU' - enabled: false -vfm_trxd: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:TRXD' - enabled: false -vfm_tryuw: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:TRYUW' -vfm_tryr: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:TRYR' -vfm_trydw: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:TRYDW' -vfm_pitch: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:PITCH' -vfm_yaw: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:YAW' - enabled: false -vfm_roll: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:ROLL' - enabled: false -vfm_trx: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:TRX' - enabled: false -vfm_try: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-VFM:TRY' - -# Horizontal focusing mirror -hfm_trxu: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:TRXU' - enabled: false -hfm_trxd: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:TRXD' - enabled: false -hfm_tryur: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:TRYUR' -hfm_tryw: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:TRYW' -hfm_trydr: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:TRYDR' -hfm_pitch: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:PITCH' - enabled: false -hfm_yaw: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:YAW' - enabled: false -hfm_roll: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:ROLL' - enabled: false -hfm_trx: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:TRX' - enabled: false -hfm_try: - deviceClass: ophyd.EpicsMotor - deviceConfig: - prefix: 'X06DA-ES1-HFM:TRY' - - -# Exposure box signals -xbox_diode: - deviceClass: ophyd.EpicsSignalRO - deviceConfig: - prefix: 'X06DA-ES-DI1:READOUT' -bstop_diode: - deviceClass: ophyd.EpicsSignalRO - deviceConfig: - prefix: 'X06DA-ES-BS:READOUT' - - -# End station -omega: - deviceClass: pxiii_bec.devices.A3200Axis - deviceConfig: - prefix: 'X06DA-ES-DF1:OMEGA' -abr: - deviceClass: pxiii_bec.devices.AerotechAbrStage - deviceConfig: - prefix: 'X06DA-ES' diff --git a/pxiii_bec/device_configs/x06da_device_config.yaml b/pxiii_bec/device_configs/x06da_device_config.yaml index 039b5e7..00c4f8b 100644 --- a/pxiii_bec/device_configs/x06da_device_config.yaml +++ b/pxiii_bec/device_configs/x06da_device_config.yaml @@ -1,4 +1,5 @@ slh_trxr: + description: OP slit inner blade motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-OP-SLH:TRXR'} onFailure: buffer @@ -7,6 +8,7 @@ slh_trxr: readOnly: false softwareTrigger: false slh_trxw: + description: OP slit outer blade motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-OP-SLH:TRXW'} onFailure: buffer @@ -15,15 +17,16 @@ slh_trxw: readOnly: false softwareTrigger: false fi1_try: - description: Beam attenuator in OP + description: Beam attenuator motion before mono deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-OP-FI1:TRY'} + deviceConfig: {prefix: 'X06DA-OP-FI1:TRY1'} onFailure: buffer enabled: true readoutPriority: monitored readOnly: false softwareTrigger: false dccm_pitch1: + description: Monochromator pitch 1 deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-OP-DCCM:PITCH1'} onFailure: buffer @@ -32,6 +35,7 @@ dccm_pitch1: readOnly: false softwareTrigger: false dccm_energy1: + description: Monochromator energy 1 deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-OP-DCCM:ENERGY1'} onFailure: buffer @@ -40,6 +44,7 @@ dccm_energy1: readOnly: false softwareTrigger: false dccm_diode: + description: Diode between mono crystals deviceClass: ophyd.EpicsSignalRO deviceConfig: {read_pv: 'X06DA-OP-XPM1:BOT:READOUT'} onFailure: buffer @@ -48,6 +53,7 @@ dccm_diode: readOnly: true softwareTrigger: false dccm_pitch2: + description: Monochromator pitch 2 deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-OP-DCCM:PITCH2'} onFailure: buffer @@ -56,6 +62,7 @@ dccm_pitch2: readOnly: false softwareTrigger: false dccm_energy2: + description: Monochromator energy 2 deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-OP-DCCM:ENERGY2'} onFailure: buffer @@ -64,6 +71,7 @@ dccm_energy2: readOnly: false softwareTrigger: false dccm_xbpm: + description: XBPM total intensity after monochromator deviceClass: ophyd.EpicsSignalRO deviceConfig: {read_pv: 'X06DA-OP-XBPM1:SumAll:MeanValue_RBV'} onFailure: buffer @@ -71,25 +79,26 @@ dccm_xbpm: readoutPriority: monitored readOnly: true softwareTrigger: false -dccm_energy: - description: Monochromator energy using ECMC virtual motors - deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-OP-DCCM:_ENERGY'} - onFailure: buffer - enabled: true - readoutPriority: monitored - readOnly: false - softwareTrigger: false -dccm_eoffset: - description: Monochromator energy offset for ECMC virtual motors - deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-OP-DCCM:_EOFFSET'} - onFailure: buffer - enabled: true - readoutPriority: monitored - readOnly: false - softwareTrigger: false +# dccm_energy: +# description: Monochromator energy using ECMC virtual motors +# deviceClass: ophyd.EpicsMotor +# deviceConfig: {prefix: 'X06DA-OP-DCCM:_ENERGY'} +# onFailure: buffer +# enabled: true +# readoutPriority: monitored +# readOnly: false +# softwareTrigger: false +# dccm_eoffset: +# description: Monochromator energy offset for ECMC virtual motors +# deviceClass: ophyd.EpicsMotor +# deviceConfig: {prefix: 'X06DA-OP-DCCM:_EOFFSET'} +# onFailure: buffer +# enabled: true +# readoutPriority: monitored +# readOnly: false +# softwareTrigger: false ssxbpm_trx: + description: XBPM motion before secondary source deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSBPM1:TRX'} onFailure: buffer @@ -98,6 +107,7 @@ ssxbpm_trx: readOnly: false softwareTrigger: false ssxbpm_try: + description: XBPM motion before secondary source deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSBPM1:TRY'} onFailure: buffer @@ -105,7 +115,17 @@ ssxbpm_try: readoutPriority: monitored readOnly: false softwareTrigger: false +# ssxbpm: +# description: XBPM before secondary source +# deviceClass: ophyd.EpicsSignalRO +# deviceConfig: {read_pv: 'X06DA-ES-SSBPM1:SumAll:MeanValue_RBV'} +# onFailure: buffer +# enabled: true +# readoutPriority: monitored +# readOnly: true +# softwareTrigger: false ssslit_trxr: + description: Secondary source blade motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSSLH1:TRXR'} onFailure: buffer @@ -114,6 +134,7 @@ ssslit_trxr: readOnly: false softwareTrigger: false ssslit_trxw: + description: Secondary source blade motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSSLH1:TRXW'} onFailure: buffer @@ -122,6 +143,7 @@ ssslit_trxw: readOnly: false softwareTrigger: false ssslit_tryt: + description: Secondary source blade motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSSLV1:TRYT'} onFailure: buffer @@ -130,6 +152,7 @@ ssslit_tryt: readOnly: false softwareTrigger: false ssslit_tryb: + description: Secondary source blade motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSSLV1:TRYB'} onFailure: buffer @@ -138,6 +161,7 @@ ssslit_tryb: readOnly: false softwareTrigger: false ssxi1_trx: + description: Secondary source diagnostic screen motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSXI1:TRX'} onFailure: buffer @@ -146,6 +170,7 @@ ssxi1_trx: readOnly: false softwareTrigger: false ssxi1_try: + description: Secondary source diagnostic screen motion deviceClass: ophyd.EpicsMotor deviceConfig: {prefix: 'X06DA-ES-SSXI1:TRY'} onFailure: buffer @@ -155,7 +180,7 @@ ssxi1_try: softwareTrigger: false vfm_trxu: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-VFM:TRXU'} + deviceConfig: {prefix: 'X06DA-ES-VFM:TRXU'} enabled: false onFailure: buffer readoutPriority: monitored @@ -163,7 +188,7 @@ vfm_trxu: softwareTrigger: false vfm_trxd: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-VFM:TRXD'} + deviceConfig: {prefix: 'X06DA-ES-VFM:TRXD'} enabled: false onFailure: buffer readoutPriority: monitored @@ -171,7 +196,7 @@ vfm_trxd: softwareTrigger: false vfm_tryuw: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-VFM:TRYUW'} + deviceConfig: {prefix: 'X06DA-ES-VFM:TRYUW'} onFailure: buffer enabled: true readoutPriority: monitored @@ -179,7 +204,7 @@ vfm_tryuw: softwareTrigger: false vfm_tryr: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-VFM:TRYR'} + deviceConfig: {prefix: 'X06DA-ES-VFM:TRYR'} onFailure: buffer enabled: true readoutPriority: monitored @@ -187,7 +212,7 @@ vfm_tryr: softwareTrigger: false vfm_trydw: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-VFM:TRYDW'} + deviceConfig: {prefix: 'X06DA-ES-VFM:TRYDW'} onFailure: buffer enabled: true readoutPriority: monitored @@ -236,7 +261,7 @@ vfm_try: softwareTrigger: false hfm_trxu: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-HFM:TRXU'} + deviceConfig: {prefix: 'X06DA-ES-HFM:TRXU'} enabled: false onFailure: buffer readoutPriority: monitored @@ -244,7 +269,7 @@ hfm_trxu: softwareTrigger: false hfm_trxd: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-HFM:TRXD'} + deviceConfig: {prefix: 'X06DA-ES-HFM:TRXD'} enabled: false onFailure: buffer readoutPriority: monitored @@ -252,7 +277,7 @@ hfm_trxd: softwareTrigger: false hfm_tryur: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-HFM:TRYUR'} + deviceConfig: {prefix: 'X06DA-ES-HFM:TRYUR'} onFailure: buffer enabled: true readoutPriority: monitored @@ -260,7 +285,7 @@ hfm_tryur: softwareTrigger: false hfm_tryw: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-HFM:TRYW'} + deviceConfig: {prefix: 'X06DA-ES-HFM:TRYW'} onFailure: buffer enabled: true readoutPriority: monitored @@ -268,7 +293,7 @@ hfm_tryw: softwareTrigger: false hfm_trydr: deviceClass: ophyd.EpicsMotor - deviceConfig: {prefix: 'X06DA-ES1-HFM:TRYDR'} + deviceConfig: {prefix: 'X06DA-ES-HFM:TRYDR'} onFailure: buffer enabled: true readoutPriority: monitored @@ -315,6 +340,51 @@ hfm_try: readoutPriority: monitored readOnly: false softwareTrigger: false +# xbox_xbpm: +# description: Exposure box XBPM +# deviceClass: ophyd.EpicsSignalRO +# deviceConfig: {read_pv: 'X06DA-ES-XBBPM1:SumAll:MeanValue_RBV'} +# onFailure: buffer +# enabled: true +# readoutPriority: monitored +# readOnly: true +# softwareTrigger: false +xbox_fil1: + description: Exposure box filter wheel 1 + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-FI1:ROZ1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +xbox_fil2: + description: Exposure box filter wheel 2 + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-FI2:ROZ1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +xbox_fil3: + description: Exposure box filter wheel 3 + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-FI3:ROZ1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +xbox_fil4: + description: Exposure box filter wheel 4 + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-FI4:ROZ1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false xbox_diode: description: Exposure box diode deviceClass: ophyd.EpicsSignalRO @@ -324,6 +394,71 @@ xbox_diode: readoutPriority: monitored readOnly: true softwareTrigger: false +ms_focus: + description: Sample microscope focus + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-MS:FOCUS'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +ms_zoom: + description: Sample microscope zoom + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-MS:ZOOM'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +ms_try: + description: Sample microscope translation + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-MS:TRY1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false + + +bstop_pneum: + description: Beamstop pneumatic in-out + deviceClass: ophyd.EpicsSignal + deviceConfig: {read_pv: 'X06DA-ES-BS:GET-POS', write_pv: 'X06DA-ES-BS:SET-POS'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +bstop_x: + description: Beamstop translation + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-BS:TRX1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +bstop_y: + description: Beamstop translation + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-BS:TRY1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false +bstop_z: + description: Beamstop translation + deviceClass: ophyd.EpicsMotor + deviceConfig: {prefix: 'X06DA-ES-BS:TRZ1'} + onFailure: buffer + enabled: true + readoutPriority: monitored + readOnly: false + softwareTrigger: false bstop_diode: description: Beamstop diode deviceClass: ophyd.EpicsSignalRO diff --git a/pxiii_bec/devices/A3200.py b/pxiii_bec/devices/A3200.py index b43f18f..7dff5bd 100644 --- a/pxiii_bec/devices/A3200.py +++ b/pxiii_bec/devices/A3200.py @@ -79,12 +79,9 @@ Examples """ import time -import math - -from ophyd import Component, Device, EpicsSignal, EpicsSignalRO, Kind, SignalRO +from ophyd import Component, Device, EpicsSignal, EpicsSignalRO, Kind from ophyd.status import MoveStatus, SubscriptionStatus, DeviceStatus - from .A3200utils import A3200Axis, A3200RasterScanner, A3200Oscillator @@ -147,13 +144,18 @@ class AerotechAbrStage(Device): """ USER_ACCESS = ['reset', 'kickoff', 'complete'] - taskStop = Component(EpicsSignal, "-AERO:TSK-STOP", put_complete=True, kind=Kind.omitted) - status = Component(EpicsSignal, "-AERO:STAT", put_complete=True, kind=Kind.omitted) + taskStop = Component( + EpicsSignal, "-AERO:TSK-STOP", put_complete=True, kind=Kind.omitted) + status = Component( + EpicsSignal, "-AERO:STAT", put_complete=True, kind=Kind.omitted) # Enable/disable motor movement via the IOC (i.e. make it task-only) - axisModeLocked = Component(EpicsSignal, "-DF1:LOCK", put_complete=True, kind=Kind.omitted) - axisModeDirect = Component(EpicsSignal, "-DF1:MODE-DIRECT", put_complete=True, kind=Kind.omitted) - axisAxesMode = Component(EpicsSignal, "-DF1:AXES-MODE", put_complete=True, kind=Kind.omitted) + axisModeLocked = Component( + EpicsSignal, "-DF1:LOCK", put_complete=True, kind=Kind.omitted) + axisModeDirect = Component( + EpicsSignal, "-DF1:MODE-DIRECT", put_complete=True, kind=Kind.omitted) + axisAxesMode = Component( + EpicsSignal, "-DF1:AXES-MODE", put_complete=True, kind=Kind.omitted) # Shutter box is missing readback so the -GET signal is installed on the VME # _shutter = Component( @@ -169,9 +171,12 @@ class AerotechAbrStage(Device): gmy = Component(A3200Axis, "-DF1:GMY", kind=Kind.hinted) gmz = Component(A3200Axis, "-DF1:GMZ", kind=Kind.hinted) - scan_command = Component(EpicsSignal, "-PSO:CMD", put_complete=True, kind=Kind.omitted) - start_command = Component(EpicsSignal, "-PSO:START-TEST.PROC", put_complete=True, kind=Kind.omitted) - stop_command = Component(EpicsSignal, "-PSO:STOP-TEST.PROC", put_complete=True, kind=Kind.omitted) + scan_command = Component( + EpicsSignal, "-PSO:CMD", put_complete=True, kind=Kind.omitted) + start_command = Component( + EpicsSignal, "-PSO:START-TEST.PROC", put_complete=True, kind=Kind.omitted) + stop_command = Component( + EpicsSignal, "-PSO:STOP-TEST.PROC", put_complete=True, kind=Kind.omitted) # Global variables to controll AeroBasic scripts _var_1 = Component(EpicsSignal, "-PSO:VAR-1", put_complete=True, kind=Kind.omitted) @@ -186,7 +191,8 @@ class AerotechAbrStage(Device): _var_10 = Component(EpicsSignal, "-PSO:VAR-10", put_complete=True, kind=Kind.omitted) # Task status PVs (programs always run on task 1) - task1 = Component(EpicsSignalRO, "-AERO:TSK1-DONE", auto_monitor=True, kind=Kind.hinted) + task1 = Component( + EpicsSignalRO, "-AERO:TSK1-DONE", auto_monitor=True, kind=Kind.hinted) task2 = Component(EpicsSignalRO, "-AERO:TSK2-DONE", auto_monitor=True) task3 = Component(EpicsSignalRO, "-AERO:TSK3-DONE", auto_monitor=True) task4 = Component(EpicsSignalRO, "-AERO:TSK4-DONE", auto_monitor=True) @@ -196,6 +202,14 @@ class AerotechAbrStage(Device): raster_num_rows = Component(EpicsSignal, "-GRD:ROW-DONE", kind=Kind.config) def set_axis_mode(self, mode: str, settle_time=0.1) -> None: + """ Set acix mode to direct/measurement mode. + Measurement mode blocks axis commands from the IOC. + + Parameters: + ----------- + mode : str + Valid values are 'direct' and 'measuring'. + """ if mode=="direct": self.axisModeDirect.set(37, settle_time=settle_time).wait() if mode=="measuring": @@ -259,20 +273,20 @@ class AerotechAbrStage(Device): def complete(self, timeout=None) -> DeviceStatus: """ ToDo: WTF was this device doing here? Whatever... """ - return self.raster.complete() + return self.raster.complete() def complete(self, timeout=None) -> SubscriptionStatus: """ Waits for task execution - + NOTE: Original complete was raster scanner complete... """ # Define wait until the busy flag goes down (excluding initial update) - def isIdle(*args, old_value, value, timestamp, **kwargs): - return bool(value==1) - + def is_idle(*args, old_value, value, timestamp, **kwargs): + return bool(value==1) + # Subscribe and wait for update - status = SubscriptionStatus(self.task1, isIdle, timeout=timeout, settle_time=0.5) + status = SubscriptionStatus(self.task1, is_idle, timeout=timeout, settle_time=0.5) return status def reset(self, settle_time=0.1): @@ -442,13 +456,15 @@ class AerotechAbrStage(Device): print("%s --- trying start again.", str(e)) self.osc.kickoff() - def move(self, position, wait=False, velocity=None, relative=None, direct=False, **kwargs) -> MoveStatus: + def move(self, position, wait=False, velocity=None, relative=None, direct=False, + **kwargs) -> MoveStatus: """ Move the omega axis """ - return self.omega.move(position, wait=wait, velocity=velocity, relative=relative, direct=direct, **kwargs) + return self.omega.move(position, wait=wait, velocity=velocity, relative=relative, + direct=direct, **kwargs) if __name__ == "__main__": abr = AerotechAbrStage(prefix="X06DA-ES", name="abr") - abr.wait_for_connection() \ No newline at end of file + abr.wait_for_connection() diff --git a/pxiii_bec/devices/A3200utils.py b/pxiii_bec/devices/A3200utils.py index 4ab5af8..07242a9 100644 --- a/pxiii_bec/devices/A3200utils.py +++ b/pxiii_bec/devices/A3200utils.py @@ -5,7 +5,8 @@ Created on Tue Jun 11 11:28:38 2024 @author: mohacsi_i """ import types -from ophyd import Component, PVPositioner, Device, Signal, EpicsSignal, EpicsSignalRO, Kind, PositionerBase +from ophyd import (Component, PVPositioner, Device, Signal, EpicsSignal, EpicsSignalRO, Kind, + PositionerBase) from ophyd.status import Status, MoveStatus, SubscriptionStatus, DeviceStatus @@ -51,8 +52,10 @@ class A3200Axis(PVPositioner): """ USER_ACCESS = ['omove'] - abr_mode_direct = Component(EpicsSignal, "-DF1:MODE-DIRECT", put_complete=True, kind=Kind.omitted) - abr_mode = Component(EpicsSignal, "-DF1:AXES-MODE", auto_monitor=True, put_complete=True, kind=Kind.omitted) + abr_mode_direct = Component( + EpicsSignal, "-DF1:MODE-DIRECT", put_complete=True, kind=Kind.omitted) + abr_mode = Component( + EpicsSignal, "-DF1:AXES-MODE", auto_monitor=True, put_complete=True, kind=Kind.omitted) # Basic PV positioner interface done = Component(EpicsSignalRO, "-DONE", auto_monitor=True, kind=Kind.config) @@ -87,34 +90,41 @@ class A3200Axis(PVPositioner): vmax = Component(Signal, kind=Kind.config) offset = Component(EpicsSignal, "-OFF", put_complete=True, kind=Kind.config) - def __init__(self, prefix="", *, name, base_pv="", kind=None, read_attrs=None, configuration_attrs=None, parent=None, llm=0, hlm=0, vmin=0, vmax=0, **kwargs): + def __init__(self, prefix="", *, name, base_pv="", kind=None, read_attrs=None, + configuration_attrs=None, parent=None, llm=0, hlm=0, vmin=0, vmax=0, **kwargs): """ __init__ MUST have a full argument list""" - """ Patching the parent's PVs into the axis class to check for direct/locked mode""" + # Patching the parent's PVs into the axis class to check for direct/locked mode if parent is None: def maybe_add_prefix(self, instance, kw, suffix): - """ Patched not to enforce parent prefix when no parent""" + # Patched not to enforce parent prefix when no parent if kw in self.add_prefix: return suffix return suffix - self.__class__.__dict__["abr_mode"].maybe_add_prefix = types.MethodType(maybe_add_prefix, self.__class__.__dict__["abr_mode"]) - self.__class__.__dict__["abr_mode_direct"].maybe_add_prefix = types.MethodType(maybe_add_prefix, self.__class__.__dict__["abr_mode_direct"]) + self.__class__.__dict__["abr_mode"].maybe_add_prefix = types.MethodType( + maybe_add_prefix, + self.__class__.__dict__["abr_mode"]) + self.__class__.__dict__["abr_mode_direct"].maybe_add_prefix = types.MethodType( + maybe_add_prefix, + self.__class__.__dict__["abr_mode_direct"]) logger.info(self.__class__.__dict__["abr_mode"].kwargs) self.__class__.__dict__["abr_mode"].suffix = base_pv + "-DF1:AXES-MODE" self.__class__.__dict__["abr_mode_direct"].suffix = base_pv + "-DF1:MODE-DIRECT" - super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs) + super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, + configuration_attrs=configuration_attrs, parent=parent, **kwargs) self.llm.set(llm).wait() self.hlm.set(hlm).wait() self.vmin.set(vmin).wait() self.vmax.set(vmax).wait() - def move(self, position, velocity=None, wait=True, relative=False, direct=False, timeout=None, **kwargs) -> MoveStatus: + def move(self, position, velocity=None, wait=True, relative=False, direct=False, timeout=None, + **kwargs) -> MoveStatus: """ Native absolute/relative movement on the A3200 """ # Check if we're in direct movement mode if self.abr_mode.value not in (DIRECT_MODE, "DIRECT"): - if direct: + if direct: self.abr_mode_direct.set(1).wait() else: raise RuntimeError(f"ABR axis not in direct mode: {self.abr_mode.value}") @@ -150,11 +160,12 @@ class A3200Axis(PVPositioner): status.wait() except KeyboardInterrupt: self.stop() - raise + raise return status - def omove(self, position, velocity=None, wait=True, relative=False, direct=False, **kwargs) -> MoveStatus: + def omove(self, position, velocity=None, wait=True, relative=False, direct=False, + **kwargs) -> MoveStatus: """ Exposes the ophyd move command through BEC abstraction""" return self.move(position, velocity, wait, relative, direct, **kwargs) @@ -210,8 +221,10 @@ class A3200RasterScanner(Device): # Also needs the command interface _zcmd = Component(EpicsSignal, "-PSO:CMD", put_complete=True, kind=Kind.omitted) - _start_command = Component(EpicsSignal, "-PSO:START-TEST.PROC", put_complete=True, kind=Kind.omitted) - _stop_command = Component(EpicsSignal, "-PSO:STOP-TEST.PROC", put_complete=True, kind=Kind.omitted) + _start_command = Component( + EpicsSignal, "-PSO:START-TEST.PROC", put_complete=True, kind=Kind.omitted) + _stop_command = Component( + EpicsSignal, "-PSO:STOP-TEST.PROC", put_complete=True, kind=Kind.omitted) def raster_setup(self, positions, columns, angle, etime): @@ -276,8 +289,7 @@ class A3200RasterScanner(Device): if r < self._raster_num_rows: return (y, z) - else: - return (None, None) + return (None, None) def next_row(self): """start rastering a new row""" @@ -289,19 +301,19 @@ class A3200RasterScanner(Device): """ self.get_ready.set(1).wait() - for n in range(10): + for _ in range(10): try: # Define wait until the busy flag goes down (excluding initial update) timestamp_ = 0 def isReady(*args, old_value, value, timestamp, **kwargs): - nonlocal timestamp_ - result = False if (timestamp_== 0) else bool(value==ABR_READY) + nonlocal timestamp_ + result = False if (timestamp_== 0) else bool(value==ABR_READY) print(f"Old {old_value}\tNew: {value}\tResult: {result}") timestamp_ = timestamp return result - + # Subscribe and wait for update - status = SubscriptionStatus(self.grid_done, isReady, timeout=2, settle_time=0.5) + status = SubscriptionStatus(self.grid_done, isReady, timeout=2, settle_time=0.5) status.wait() except TimeoutError as e: print(str(e), end=" ") @@ -315,22 +327,21 @@ class A3200RasterScanner(Device): else: self.grid_next.set(1) - def is_scan_done(self): - return 1 == scan_done.get() + return 1 == self.scan_done.get() def wait_scan_done(self, timeout=60.0) -> SubscriptionStatus: # Define wait until the busy flag goes down (excluding initial update) timestamp_ = 0 def isReady(*args, old_value, value, timestamp, **kwargs): - nonlocal timestamp_ - result = False if (timestamp_== 0) else bool(value==1) + nonlocal timestamp_ + result = False if (timestamp_== 0) else bool(value==1) print(f"Old {old_value}\tNew: {value}\tResult: {result}") timestamp_ = timestamp return result - + # Subscribe and wait for update - status = SubscriptionStatus(self.scan_done, isReady, timeout=timeout, settle_time=0.5) + status = SubscriptionStatus(self.scan_done, isReady, timeout=timeout, settle_time=0.5) status.wait() return status @@ -341,32 +352,36 @@ class A3200RasterScanner(Device): def raster_wait_for_row(self, timeout=60) -> SubscriptionStatus: # Define wait subscription timestamp_ = 0 - def isReady(*args, old_value, value, timestamp, **kwargs): - nonlocal timestamp_ - result = False if (timestamp_== 0) else bool(value==1) + def is_ready(*args, old_value, value, timestamp, **kwargs): + nonlocal timestamp_ + result = False if (timestamp_== 0) else bool(value==1) print(f"Old {old_value}\tNew: {value}\tResult: {result}") timestamp_ = timestamp return result - + # Subscribe and wait for update - status = SubscriptionStatus(self.row_done, isReady, timeout=timeout, settle_time=0.5) + status = SubscriptionStatus(self.row_done, is_ready, timeout=timeout, settle_time=0.5) status.wait() return status def complete(self, timeout=None) -> DeviceStatus: + """ Wait for the grid scanner to finish + + TODO: Probably redundant with task status wait? + """ if timeout is not None: # Define wait until the busy flag goes down (excluding initial update) timestamp_ = 0 def isReady(*args, old_value, value, timestamp, **kwargs): - nonlocal timestamp_ - result = False if (timestamp_== 0) else bool(value==GRID_SCAN_DONE) + nonlocal timestamp_ + result = False if (timestamp_== 0) else bool(value==GRID_SCAN_DONE) print(f"Old {old_value}\tNew: {value}\tResult: {result}") timestamp_ = timestamp return result - + # Subscribe and wait for update - status = SubscriptionStatus(self.scan_done, isReady, timeout=timeout, settle_time=0.5) + status = SubscriptionStatus(self.scan_done, isReady, timeout=timeout, settle_time=0.5) return status status = DeviceStatus(self, settle_time=0.5) status.set_finished() @@ -374,14 +389,9 @@ class A3200RasterScanner(Device): - - - - class A3200Oscillator(Device): """No clue what this does, seems to be redundant with the task based grid scanners... """ - ostart_pos = Component(EpicsSignal, "-OSC:START-POS", put_complete=True, kind=Kind.config) orange = Component(EpicsSignal, "-OSC:RANGE", put_complete=True, kind=Kind.config) etime = Component(EpicsSignal, "-OSC:ETIME", put_complete=True, kind=Kind.config) @@ -415,27 +425,16 @@ class A3200Oscillator(Device): """ # Define wait until the busy flag goes down (excluding initial update) def inStatus(*args, old_value, value, timestamp, **kwargs): - result = bool(value==target) + result = bool(value==target) print(f"Old {old_value}\tNew: {value}\tResult: {result}") return result - + # Subscribe and wait for update - status = SubscriptionStatus(self.phase, inStatus, timeout=timeout, settle_time=0.5) + status = SubscriptionStatus(self.phase, inStatus, timeout=timeout, settle_time=0.5) return status - - - - - - - - - - - # Automatically start an axis if directly invoked if __name__ == "__main__": omega = A3200Axis(prefix="X06DA-ES-DF1:OMEGA", name="omega") diff --git a/pxiii_bec/scans/__init__.py b/pxiii_bec/scans/__init__.py index 2b4690a..6d3422d 100644 --- a/pxiii_bec/scans/__init__.py +++ b/pxiii_bec/scans/__init__.py @@ -1 +1,3 @@ -from .mx_measurements import MeasureFastOmega, MeasureStandardWedge, MeasureVerticalLine, MeasureScanSlits, MeasureRasterSimple, MeasureScreening, MeasureRepeatedOscillation, MeasureMSOX, MeasureGrid \ No newline at end of file +from .mx_measurements import (MeasureFastOmega, MeasureStandardWedge, MeasureVerticalLine, + MeasureScanSlits, MeasureRasterSimple, MeasureScreening, MeasureRepeatedOscillation, + MeasureMSOX, MeasureGrid) diff --git a/pxiii_bec/scans/mx_measurements.py b/pxiii_bec/scans/mx_measurements.py index 5cd99a7..dbb4348 100644 --- a/pxiii_bec/scans/mx_measurements.py +++ b/pxiii_bec/scans/mx_measurements.py @@ -1,4 +1,8 @@ -import time +""" MX measurements module + +Scan primitives for standard BEC scans at the PX beamlines at SLS. +Theese scans define the event model and can be called from higher levels. +""" import numpy as np from bec_lib import bec_logger @@ -10,13 +14,9 @@ logger = bec_logger.logger FULL_PERIOD = 0 HALF_PERIOD = 1 -class SasttSnakeMode: - SNAKE_SINGLE = 0 - UNIDIRECTIONAL = 1 - SNAKE_DOUBLE_PSO = 2 - class AbrCmd: + """ Valid Aerotech ABR scan commands from the AeroBasic files""" NONE = 0 RASTER_SCAN_SIMPLE = 1 MEASURE_STANDARD = 2 @@ -69,12 +69,13 @@ class AerotechFlyscanBase(AsyncFlyScanBase): abr_raster_reset =False abr_complete = False abr_timeout = None + pointID = 0 + num_pos = 0 def __init__(self, *args, parameter: dict = None, **kwargs): """ Just set num_pos=0 to avoid hanging and override defaults if explicitly set from parameters. """ - self.num_pos = 0 super().__init__(parameter=parameter, **kwargs) # Override if explicitly passed as parameter @@ -104,7 +105,7 @@ class AerotechFlyscanBase(AsyncFlyScanBase): # Reset the raster scan engine if self.abr_raster_reset: - yield from self.stubs.command("abr", "raster_scan_done.set", 0) + yield from self.stubs.send_rpc_and_wait("abr", "raster_scan_done.set", 0) # Configure the global variables d = {"scan_command" : self.abr_command} @@ -116,14 +117,13 @@ class AerotechFlyscanBase(AsyncFlyScanBase): # Call super yield from super().pre_scan() - def stage(self): - """ ToDo: Sot sure if we should call super() here as it'd stage the whole beamline""" - return super().stage() + # def stage(self): + # """ ToDo: Sot sure if we should call super() here as it'd stage the whole beamline""" + # return super().stage() def scan_core(self): """ The actual scan logic comes here. """ - self.pointID = 0 # Kick off the run yield from self.stubs.send_rpc_and_wait("abr", "start_command.set", 1) logger.info("Measurement launched on the ABR stage...") @@ -836,7 +836,7 @@ class MeasureGrid(AerotechFlyscanBase): if len(self.scan_positions)==1: raise RuntimeWarning("Raster scan with one cell makes no sense") - + # Call base class super().__init__(parameter=parameter, **kwargs) @@ -893,7 +893,8 @@ class MeasureGridStill(AerotechFlyscanBase): Example ------- - >>> scans.measure_raster(positions=[[11, 2, 3.4], [11, 2, 3.5], ...], steps_x=20, steps_y=20, exp_time=0.1, delay=0.05) + >>> pts = [[11, 2, 3.4], [11, 2, 3.5], ...] + >>> scans.measure_raster(positions=pts, steps_x=20, steps_y=20, exp_time=0.1, delay=0.05) Parameters ---------- @@ -1012,7 +1013,9 @@ class MeasureJungfrau(AerotechFlyscanBase): self.scan_stepsize_y = self.scan_range_y / self.scan_stepnum_y self.scan_exp_time = parameter['kwargs'].get("exp_time") self.scan_sleep = parameter['kwargs'].get("sleep", 0.1) - self.abr_timeout = None if self.scan_sleep <= 0 else 5.0 + (self.scan_num_rows * self.scan_sleep) + (self.scan_num_cols * self.scan_num_rows * self.scan_exp_time) + sleep_time = 5.0 + (self.scan_stepnum_y * self.scan_sleep) + ( + self.scan_stepnum_x * self.scan_stepnum_y * self.scan_exp_time) + self.abr_timeout = None if self.scan_sleep <= 0 else sleep_time self.abr_command = AbrCmd.JUNGFRAU self.abr_complete = True self.abr_globals = { @@ -1024,7 +1027,7 @@ class MeasureJungfrau(AerotechFlyscanBase): "var_6" : self.scan_sleep, "var_7" : 0, "var_8" : 0, - } + } # Call base class super().__init__(parameter=parameter, **kwargs) @@ -1035,7 +1038,4 @@ class MeasureJungfrau(AerotechFlyscanBase): # Go back to direct mode st = yield from self.stubs.send_rpc_and_wait("abr", "set_axis_mode", "direct") - st.wait() - - - + st.wait() \ No newline at end of file