mirror of
https://github.com/bec-project/ophyd_devices.git
synced 2025-06-05 19:30:41 +02:00
refactor!: moved to new ophyd_devices repo structure
BREAKING CHANGE: cleaned up and migrated to the new repo structure. Only shared devices will be hosted in ophyd_devices. Everything else will be in the beamline-specific repositories
This commit is contained in:
parent
be689baa29
commit
3415ae2007
@ -138,7 +138,7 @@ pytest:
|
|||||||
config_test:
|
config_test:
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- ophyd_test --config ./ophyd_devices/epics/db/ --output ./config_tests
|
- ophyd_test --config ./ophyd_devices/configs/ --output ./config_tests
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- ./config_tests
|
- ./config_tests
|
||||||
|
@ -2,7 +2,7 @@ from .ophyd_patch import monkey_patch_ophyd
|
|||||||
|
|
||||||
monkey_patch_ophyd()
|
monkey_patch_ophyd()
|
||||||
|
|
||||||
from .epics import *
|
from .devices.sls_devices import SLSInfo, SLSOperatorMessages
|
||||||
from .sim.sim import SimCamera
|
from .sim.sim import SimCamera
|
||||||
from .sim.sim import SimFlyer
|
from .sim.sim import SimFlyer
|
||||||
from .sim.sim import SimFlyer as SynFlyer
|
from .sim.sim import SimFlyer as SynFlyer
|
||||||
@ -15,7 +15,6 @@ from .sim.sim import SimWaveform, SynDeviceOPAAS
|
|||||||
from .sim.sim_frameworks import DeviceProxy, H5ImageReplayProxy, SlitProxy
|
from .sim.sim_frameworks import DeviceProxy, H5ImageReplayProxy, SlitProxy
|
||||||
from .sim.sim_signals import ReadOnlySignal
|
from .sim.sim_signals import ReadOnlySignal
|
||||||
from .sim.sim_signals import ReadOnlySignal as SynSignalRO
|
from .sim.sim_signals import ReadOnlySignal as SynSignalRO
|
||||||
from .sls_devices.sls_devices import SLSInfo, SLSOperatorMessages
|
|
||||||
from .utils.bec_device_base import BECDeviceBase
|
from .utils.bec_device_base import BECDeviceBase
|
||||||
from .utils.dynamic_pseudo import ComputedSignal
|
from .utils.dynamic_pseudo import ComputedSignal
|
||||||
from .utils.static_device_test import launch
|
from .utils.static_device_test import launch
|
||||||
|
91
ophyd_devices/configs/ophyd_devices_simulation.yaml
Normal file
91
ophyd_devices/configs/ophyd_devices_simulation.yaml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
eiger:
|
||||||
|
readoutPriority: monitored
|
||||||
|
deviceClass: ophyd_devices.SimCamera
|
||||||
|
deviceConfig:
|
||||||
|
device_access: true
|
||||||
|
deviceTags:
|
||||||
|
- detector
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
softwareTrigger: true
|
||||||
|
|
||||||
|
dyn_signals:
|
||||||
|
readoutPriority: baseline
|
||||||
|
deviceClass: ophyd_devices.sim.sim.SynDynamicComponents
|
||||||
|
deviceConfig:
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
|
||||||
|
pseudo_signal1:
|
||||||
|
deviceClass: ophyd_devices.ComputedSignal
|
||||||
|
deviceConfig:
|
||||||
|
compute_method: "def compute_signals(signal1, signal2):\n return signal1.get()*signal2.get()\n"
|
||||||
|
input_signals:
|
||||||
|
- "bpm4i_readback"
|
||||||
|
- "bpm5i_readback"
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
readoutPriority: baseline
|
||||||
|
|
||||||
|
hexapod:
|
||||||
|
readoutPriority: baseline
|
||||||
|
deviceClass: ophyd_devices.SynDeviceOPAAS
|
||||||
|
deviceConfig:
|
||||||
|
deviceTags:
|
||||||
|
- user motors
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
|
||||||
|
eyefoc:
|
||||||
|
readoutPriority: baseline
|
||||||
|
deviceClass: ophyd_devices.SimPositioner
|
||||||
|
deviceConfig:
|
||||||
|
delay: 1
|
||||||
|
limits:
|
||||||
|
- -50
|
||||||
|
- 50
|
||||||
|
tolerance: 0.01
|
||||||
|
update_frequency: 400
|
||||||
|
deviceTags:
|
||||||
|
- user motors
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
|
||||||
|
flyer_sim:
|
||||||
|
readoutPriority: on_request
|
||||||
|
deviceClass: ophyd_devices.SynFlyer
|
||||||
|
deviceConfig:
|
||||||
|
delay: 1
|
||||||
|
device_access: true
|
||||||
|
update_frequency: 400
|
||||||
|
deviceTags:
|
||||||
|
- flyer
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
|
||||||
|
bpm4i:
|
||||||
|
readoutPriority: monitored
|
||||||
|
deviceClass: ophyd_devices.SimMonitor
|
||||||
|
deviceConfig:
|
||||||
|
deviceTags:
|
||||||
|
- beamline
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
|
||||||
|
bpm5i:
|
||||||
|
readoutPriority: monitored
|
||||||
|
deviceClass: ophyd_devices.SimMonitor
|
||||||
|
deviceConfig:
|
||||||
|
deviceTags:
|
||||||
|
- beamline
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
|
||||||
|
ring_current_sim:
|
||||||
|
readoutPriority: monitored
|
||||||
|
deviceClass: ophyd_devices.ReadOnlySignal
|
||||||
|
deviceConfig:
|
||||||
|
deviceTags:
|
||||||
|
- beamline
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
19
ophyd_devices/configs/sls_devices.yaml
Normal file
19
ophyd_devices/configs/sls_devices.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
sls_info:
|
||||||
|
readoutPriority: on_request
|
||||||
|
description: 'sls info'
|
||||||
|
deviceClass: ophyd_devices.SLSInfo
|
||||||
|
deviceConfig: {}
|
||||||
|
onFailure: buffer
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
softwareTrigger: false
|
||||||
|
|
||||||
|
sls_operator:
|
||||||
|
readoutPriority: on_request
|
||||||
|
description: 'sls operator messages'
|
||||||
|
deviceClass: ophyd_devices.SLSOperatorMessages
|
||||||
|
deviceConfig: {}
|
||||||
|
onFailure: buffer
|
||||||
|
enabled: true
|
||||||
|
readOnly: false
|
||||||
|
softwareTrigger: false
|
@ -1,10 +1,11 @@
|
|||||||
# Standard ophyd classes
|
|
||||||
from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO
|
from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO
|
||||||
from ophyd.quadem import QuadEM
|
from ophyd.quadem import QuadEM
|
||||||
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
||||||
|
|
||||||
from .devices.slits import SlitH, SlitV
|
from .epics_motor_ex import EpicsMotorEx
|
||||||
from .devices.specMotors import (
|
from .slits import SlitH, SlitV
|
||||||
|
from .sls_devices import SLSInfo, SLSOperatorMessages
|
||||||
|
from .specMotors import (
|
||||||
Bpm4i,
|
Bpm4i,
|
||||||
EnergyKev,
|
EnergyKev,
|
||||||
GirderMotorPITCH,
|
GirderMotorPITCH,
|
||||||
@ -17,8 +18,4 @@ from .devices.specMotors import (
|
|||||||
PmDetectorRotation,
|
PmDetectorRotation,
|
||||||
PmMonoBender,
|
PmMonoBender,
|
||||||
)
|
)
|
||||||
from .devices.SpmBase import SpmBase
|
from .SpmBase import SpmBase
|
||||||
|
|
||||||
# X07MA specific devices
|
|
||||||
from .devices.X07MADevices import *
|
|
||||||
from .devices.XbpmBase import XbpmBase, XbpmCsaxsOp
|
|
@ -1,66 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
Created on Wed Oct 13 17:06:51 2021
|
|
||||||
|
|
||||||
@author: mohacsi_i
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import yaml
|
|
||||||
from devices import *
|
|
||||||
from ophyd.ophydobj import OphydObject
|
|
||||||
|
|
||||||
# ####################################################
|
|
||||||
# Test connection to beamline devices
|
|
||||||
# ####################################################
|
|
||||||
# Current file path
|
|
||||||
path = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
# Load simulated device database
|
|
||||||
fp = open(f"{path}/db/test_database.yml", "r")
|
|
||||||
lut_db = yaml.load(fp, Loader=yaml.Loader)
|
|
||||||
|
|
||||||
# Load beamline specific database
|
|
||||||
bl = os.getenv("BEAMLINE_XNAME", "TESTENV")
|
|
||||||
if bl != "TESTENV":
|
|
||||||
fp = open(f"{path}/db/{bl.lower()}_database.yml", "r")
|
|
||||||
lut_db.update(yaml.load(fp, Loader=yaml.Loader))
|
|
||||||
|
|
||||||
|
|
||||||
def createProxy(name: str, connect=True) -> OphydObject:
|
|
||||||
"""Create an ophyd device from its alias
|
|
||||||
|
|
||||||
Factory routine that uses the beamline database to instantiate
|
|
||||||
ophyd devices from their alias and pre-defined configuration.
|
|
||||||
Does nothing if the device is already an OphydObject!
|
|
||||||
"""
|
|
||||||
if issubclass(type(name), OphydObject):
|
|
||||||
return name
|
|
||||||
|
|
||||||
entry = lut_db[name]
|
|
||||||
# Yeah, using global namespace
|
|
||||||
cls_candidate = globals()[entry["type"]]
|
|
||||||
# print(f"Class candidate: {cls_candidate}")
|
|
||||||
|
|
||||||
if issubclass(cls_candidate, OphydObject):
|
|
||||||
ret = cls_candidate(**entry["config"])
|
|
||||||
if connect:
|
|
||||||
ret.wait_for_connection(timeout=5)
|
|
||||||
return ret
|
|
||||||
else:
|
|
||||||
raise RuntimeError(f"Unsupported return class: {entry['type']}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
num_errors = 0
|
|
||||||
for key in lut_db:
|
|
||||||
try:
|
|
||||||
dut = createProxy(str(key))
|
|
||||||
print(f"{key}\t: {type(dut)}\t{dut.read()}")
|
|
||||||
# print(f"{key}\t: {type(dut)}")
|
|
||||||
except Exception as ex:
|
|
||||||
num_errors += 1
|
|
||||||
print(key)
|
|
||||||
print(ex)
|
|
||||||
print(f"\nTotal number of errors: {num_errors}")
|
|
@ -1,56 +0,0 @@
|
|||||||
es1_roty:
|
|
||||||
description: 'Test rotation stage'
|
|
||||||
# deviceClass: EpicsMotor
|
|
||||||
deviceClass: ophyd_devices.epics.devices.EpicsMotorX
|
|
||||||
deviceConfig: {prefix: 'X02DA-ES1-SMP1:ROTY'}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readoutPriority: monitored
|
|
||||||
|
|
||||||
es1_aa1:
|
|
||||||
description: 'Rotation stage controller status'
|
|
||||||
deviceClass: ophyd_devices.epics.devices.aa1Controller
|
|
||||||
deviceConfig: {prefix: 'X02DA-ES1-SMP1:CTRL:'}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readoutPriority: monitored
|
|
||||||
|
|
||||||
es1_aa1Tasks:
|
|
||||||
description: 'AA1 task management interface'
|
|
||||||
deviceClass: ophyd_devices.epics.devices.aa1Tasks
|
|
||||||
deviceConfig: {prefix: 'X02DA-ES1-SMP1:TASK:'}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readoutPriority: monitored
|
|
||||||
|
|
||||||
es1_aa1GlobalVar:
|
|
||||||
description: 'AA1 global variables interface'
|
|
||||||
deviceClass: ophyd_devices.epics.devices.aa1GlobalVariables
|
|
||||||
deviceConfig: {prefix: 'X02DA-ES1-SMP1:VAR:'}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readoutPriority: monitored
|
|
||||||
|
|
||||||
es1_aa1GlobalMon:
|
|
||||||
description: 'AA1 polled global variable interface'
|
|
||||||
deviceClass: ophyd_devices.epics.devices.aa1GlobalVariableBindings
|
|
||||||
deviceConfig: {prefix: 'X02DA-ES1-SMP1:VAR:'}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readoutPriority: monitored
|
|
||||||
|
|
||||||
es1_psod:
|
|
||||||
description: 'AA1 PSO output interface'
|
|
||||||
deviceClass: ophyd_devices.epics.devices.aa1AxisPsoDistance
|
|
||||||
deviceConfig: {prefix: 'X02DA-ES1-SMP1:ROTY:PSO:'}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readoutPriority: monitored
|
|
||||||
|
|
||||||
es1_ddaq:
|
|
||||||
description: 'AA1 drive data collection interface'
|
|
||||||
deviceClass: ophyd_devices.epics.devices.aa1AxisDriveDataCollection
|
|
||||||
deviceConfig: {prefix: 'X02DA-ES1-SMP1:ROTY:DDC:'}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readoutPriority: monitored
|
|
@ -1,274 +0,0 @@
|
|||||||
slsinfo:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'SLS beam info'
|
|
||||||
deviceClass: ophyd_devices.SLSInfo
|
|
||||||
deviceConfig: {}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
undulator:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Undulator'
|
|
||||||
deviceClass: ophyd_devices.X07MAUndulator
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-ID:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
aperture:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Frontend aperture'
|
|
||||||
deviceClass: ophyd.EpicsSignal
|
|
||||||
deviceConfig:
|
|
||||||
read_pv: 'X07MA-FE-DSAPER'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
mono:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'PGM Monochromator'
|
|
||||||
deviceClass: ophyd_devices.PGMMonochromator
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
otf:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'PGM on-the-fly scan'
|
|
||||||
deviceClass: ophyd_devices.PGMOtFScan
|
|
||||||
deviceConfig: {}
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
valve:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Endstation valve'
|
|
||||||
deviceClass: ophyd_devices.VacuumValve
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-OP-VG13:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
exit_slit:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Exit slit'
|
|
||||||
deviceClass: ophyd_devices.X07MAExitSlit
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-OP-SL1SV1:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
goldmesh1:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Gold mesh 1'
|
|
||||||
deviceClass: ophyd.EpicsMotor
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-OP-IO1:TR1'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
goldmesh2:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Gold mesh 2'
|
|
||||||
deviceClass: ophyd.EpicsMotor
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-OP-IO2:TR1'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
field_x:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Magnetic field x'
|
|
||||||
deviceClass: ophyd_devices.X07MAMagnetAxis
|
|
||||||
deviceConfig:
|
|
||||||
axis_id: X
|
|
||||||
ps_prefix: "X07MA-PC-PS2:"
|
|
||||||
prefix: 'X07MA-PC-MAG:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
field_z:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Magnetic field z'
|
|
||||||
deviceClass: ophyd_devices.X07MAMagnetAxis
|
|
||||||
deviceConfig:
|
|
||||||
axis_id: Z
|
|
||||||
ps_prefix: "X07MA-PC-PS1:"
|
|
||||||
prefix: 'X07MA-PC-MAG:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
signals:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'ADC signals'
|
|
||||||
deviceClass: ophyd_devices.X07MAAnalogSignals
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-ES1-AI:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
sample_hor:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Horizontal sample position'
|
|
||||||
deviceClass: ophyd.EpicsMotor
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-ES1-MAG:TRZS'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
sample_vert:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Horizontal sample position'
|
|
||||||
deviceClass: ophyd.EpicsMotor
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-ES1-MAG:TRY1'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
sample_rot:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Horizontal sample position'
|
|
||||||
deviceClass: ophyd.EpicsMotor
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-ES1-MAG:ROY1'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
harmonic:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'ID harmonic'
|
|
||||||
deviceClass: ophyd.EpicsSignal
|
|
||||||
deviceConfig:
|
|
||||||
read_pv: 'X07MA-ID:HARMONIC'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
energy:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Energy in eV'
|
|
||||||
deviceClass: ophyd.EpicsSignal
|
|
||||||
deviceConfig:
|
|
||||||
read_pv: 'X07MA-PHS-E:GO.A'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
energy_mode:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Energy mode. Either PGM = 0 or PGM+ID = 1'
|
|
||||||
deviceClass: ophyd.EpicsSignal
|
|
||||||
deviceConfig:
|
|
||||||
read_pv: 'X07MA-PHS-E:OPT'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
keithley_1:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Keithley 1 / 428 tey'
|
|
||||||
deviceClass: ophyd.EpicsSignal
|
|
||||||
deviceConfig:
|
|
||||||
read_pv: 'X07MA-PC-K428:1:setGain'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
keithley_2:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Keithley 2 / 428 i0'
|
|
||||||
deviceClass: ophyd.EpicsSignal
|
|
||||||
deviceConfig:
|
|
||||||
read_pv: 'X07MA-PC-K428:2:setGain'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
keithley_3:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Keithley 3 / 428 diode'
|
|
||||||
deviceClass: ophyd.EpicsSignal
|
|
||||||
deviceConfig:
|
|
||||||
read_pv: 'X07MA-PC-K428:3:setGain'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
temperature:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Temperature controller'
|
|
||||||
deviceClass: ophyd_devices.X07MATemperatureController
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-PC-TC:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
tcontrol:
|
|
||||||
readoutPriority: baseline
|
|
||||||
description: 'Automatic temperature control'
|
|
||||||
deviceClass: ophyd_devices.X07MAAutoTemperatureControl
|
|
||||||
deviceConfig:
|
|
||||||
prefix: 'X07MA-ES1-TEMP:'
|
|
||||||
onFailure: retry
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
sls_info:
|
|
||||||
readoutPriority: on_request
|
|
||||||
description: 'sls info'
|
|
||||||
deviceClass: ophyd_devices.SLSInfo
|
|
||||||
deviceConfig: {}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
||||||
|
|
||||||
sls_operator:
|
|
||||||
readoutPriority: on_request
|
|
||||||
description: 'sls operator messages'
|
|
||||||
deviceClass: ophyd_devices.SLSOperatorMessages
|
|
||||||
deviceConfig: {}
|
|
||||||
onFailure: buffer
|
|
||||||
enabled: true
|
|
||||||
readOnly: false
|
|
||||||
softwareTrigger: false
|
|
@ -1,410 +0,0 @@
|
|||||||
"""
|
|
||||||
ophyd device classes for X07MA beamline
|
|
||||||
"""
|
|
||||||
|
|
||||||
import time
|
|
||||||
import traceback
|
|
||||||
from collections import OrderedDict
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from bec_lib import bec_logger
|
|
||||||
from ophyd import Component as Cpt
|
|
||||||
from ophyd import Device, EpicsMotor, EpicsSignal, EpicsSignalRO
|
|
||||||
from ophyd import FormattedComponent as FCpt
|
|
||||||
from ophyd import Kind, PVPositioner, Signal
|
|
||||||
from ophyd.flyers import FlyerInterface
|
|
||||||
from ophyd.pv_positioner import PVPositionerComparator
|
|
||||||
from ophyd.status import DeviceStatus, SubscriptionStatus
|
|
||||||
|
|
||||||
logger = bec_logger.logger
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"X07MAUndulator",
|
|
||||||
"PGMMonochromator",
|
|
||||||
"PGMOtFScan",
|
|
||||||
"VacuumValve",
|
|
||||||
"X07MAExitSlit",
|
|
||||||
"X07MAMagnetAxis",
|
|
||||||
"X07MAAnalogSignals",
|
|
||||||
"X07MASampleManipulator",
|
|
||||||
"X07MATemperatureController",
|
|
||||||
"X07MAAutoTemperatureControl",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class X07MAUndulator(PVPositioner):
|
|
||||||
"""
|
|
||||||
X07MA undulator
|
|
||||||
"""
|
|
||||||
|
|
||||||
setpoint = Cpt(EpicsSignal, "ENERGY", auto_monitor=True)
|
|
||||||
readback = Cpt(EpicsSignalRO, "ENERGY-READ", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
done = Cpt(EpicsSignalRO, "DONE", kind=Kind.omitted, auto_monitor=True)
|
|
||||||
stop_signal = Cpt(EpicsSignal, "STOP", kind=Kind.omitted)
|
|
||||||
|
|
||||||
energy_offset = Cpt(EpicsSignal, "ENERGY-OFFS", kind=Kind.config)
|
|
||||||
pol_mode = Cpt(EpicsSignal, "MODE")
|
|
||||||
pol_angle = Cpt(EpicsSignal, "ALPHA")
|
|
||||||
harmonic = Cpt(EpicsSignal, "HARMONIC")
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
prefix="",
|
|
||||||
*,
|
|
||||||
limits=None,
|
|
||||||
name=None,
|
|
||||||
read_attrs=None,
|
|
||||||
configuration_attrs=None,
|
|
||||||
parent=None,
|
|
||||||
egu="",
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
super().__init__(
|
|
||||||
prefix,
|
|
||||||
limits=limits,
|
|
||||||
name=name,
|
|
||||||
read_attrs=read_attrs,
|
|
||||||
configuration_attrs=configuration_attrs,
|
|
||||||
parent=parent,
|
|
||||||
egu=egu,
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
self.readback.name = self.name
|
|
||||||
|
|
||||||
|
|
||||||
class PGMMonochromator(PVPositioner):
|
|
||||||
"""
|
|
||||||
PGM monochromator
|
|
||||||
"""
|
|
||||||
|
|
||||||
setpoint = Cpt(EpicsSignal, "PHS-E:GO.A", auto_monitor=True)
|
|
||||||
readback = Cpt(EpicsSignalRO, "PGM:CERBK", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
done = Cpt(EpicsSignalRO, "PHS:alldone", kind=Kind.omitted, auto_monitor=True)
|
|
||||||
stop_signal = Cpt(EpicsSignal, "PGM:stop", kind=Kind.omitted)
|
|
||||||
|
|
||||||
cff = Cpt(EpicsSignal, "PGM:rbkcff", write_pv="PGM:cff.A", kind=Kind.config)
|
|
||||||
with_undulator = Cpt(EpicsSignal, "PHS-E:OPT", kind=Kind.config)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
prefix="",
|
|
||||||
*,
|
|
||||||
limits=None,
|
|
||||||
name=None,
|
|
||||||
read_attrs=None,
|
|
||||||
configuration_attrs=None,
|
|
||||||
parent=None,
|
|
||||||
egu="",
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
super().__init__(
|
|
||||||
prefix,
|
|
||||||
limits=limits,
|
|
||||||
name=name,
|
|
||||||
read_attrs=read_attrs,
|
|
||||||
configuration_attrs=configuration_attrs,
|
|
||||||
parent=parent,
|
|
||||||
egu=egu,
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
self.readback.name = self.name
|
|
||||||
|
|
||||||
|
|
||||||
class PGMOtFScan(FlyerInterface, Device):
|
|
||||||
"""
|
|
||||||
PGM on-the-fly scan
|
|
||||||
"""
|
|
||||||
|
|
||||||
SUB_VALUE = "value"
|
|
||||||
SUB_FLYER = "flyer"
|
|
||||||
_default_sub = SUB_VALUE
|
|
||||||
|
|
||||||
e1 = Cpt(EpicsSignal, "E1", kind=Kind.config)
|
|
||||||
e2 = Cpt(EpicsSignal, "E2", kind=Kind.config)
|
|
||||||
time = Cpt(EpicsSignal, "TIME", kind=Kind.config)
|
|
||||||
folder = Cpt(EpicsSignal, "FOLDER", kind=Kind.config)
|
|
||||||
file = Cpt(EpicsSignal, "FILE", kind=Kind.config)
|
|
||||||
acquire = Cpt(EpicsSignal, "START", auto_monitor=True)
|
|
||||||
edata = Cpt(EpicsSignalRO, "EDATA", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
data = Cpt(EpicsSignalRO, "DATA", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
idata = Cpt(EpicsSignalRO, "IDATA", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
fdata = Cpt(EpicsSignalRO, "FDATA", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
count = Cpt(EpicsSignalRO, "COUNT", kind=Kind.omitted, auto_monitor=True)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self._start_time = 0
|
|
||||||
self.acquire.subscribe(self._update_status, run=False)
|
|
||||||
self.count.subscribe(self._update_data, run=False)
|
|
||||||
|
|
||||||
def kickoff(self):
|
|
||||||
self._start_time = time.time()
|
|
||||||
self.acquire.put(1, use_complete=True)
|
|
||||||
status = DeviceStatus(self)
|
|
||||||
status.set_finished()
|
|
||||||
return status
|
|
||||||
|
|
||||||
def complete(self):
|
|
||||||
def check_value(*, old_value, value, **kwargs):
|
|
||||||
return old_value == 1 and value == 0
|
|
||||||
|
|
||||||
status = SubscriptionStatus(self.acquire, check_value, event_type=self.acquire.SUB_VALUE)
|
|
||||||
return status
|
|
||||||
|
|
||||||
def collect(self):
|
|
||||||
data = {"time": self._start_time, "data": {}, "timestamps": {}}
|
|
||||||
for attr in ("edata", "data", "idata", "fdata"):
|
|
||||||
obj = getattr(self, attr)
|
|
||||||
data["data"][obj.name] = obj.get()
|
|
||||||
data["timestamps"][obj.name] = obj.timestamp
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def describe_collect(self):
|
|
||||||
desc = OrderedDict()
|
|
||||||
for attr in ("edata", "data", "idata", "fdata"):
|
|
||||||
desc.update(getattr(self, attr).describe())
|
|
||||||
return desc
|
|
||||||
|
|
||||||
def _update_status(self, *, old_value, value, **kwargs):
|
|
||||||
if old_value == 1 and value == 0:
|
|
||||||
self._update_data(100) # make sure that the last entries are also emitted
|
|
||||||
self._done_acquiring()
|
|
||||||
|
|
||||||
def _update_data(self, value, **kwargs):
|
|
||||||
try:
|
|
||||||
if value == 0:
|
|
||||||
return
|
|
||||||
data = self.collect()
|
|
||||||
|
|
||||||
# FIXME: to avoid emitting outdated / stale data, wait until all signals report > 10 entries
|
|
||||||
if any(len(val) < 10 for val in data["data"].values()) or value < 10:
|
|
||||||
return
|
|
||||||
self._run_subs(sub_type=self.SUB_FLYER, value=data)
|
|
||||||
except Exception as exc:
|
|
||||||
content = traceback.format_exc()
|
|
||||||
logger.error(content)
|
|
||||||
|
|
||||||
|
|
||||||
class VacuumValve(PVPositionerComparator):
|
|
||||||
"""
|
|
||||||
EPS vacuum valve.
|
|
||||||
|
|
||||||
The setpoint is of 2 choices
|
|
||||||
0 - Close
|
|
||||||
1 - Try open
|
|
||||||
|
|
||||||
The readback is of 8 choices
|
|
||||||
0 - TO CONNECT
|
|
||||||
1 - MAN OPEN
|
|
||||||
2 - CLOSED
|
|
||||||
3 - ERROR
|
|
||||||
4 - MOVING
|
|
||||||
5 - OPEN
|
|
||||||
6 - ERROR
|
|
||||||
7 - ERROR
|
|
||||||
"""
|
|
||||||
|
|
||||||
setpoint = Cpt(EpicsSignal, "WT_SET")
|
|
||||||
readback = Cpt(EpicsSignalRO, "POSITION")
|
|
||||||
|
|
||||||
def __init__(self, prefix: str, *, name: str, **kwargs):
|
|
||||||
kwargs.update({"limits": (0, 1)})
|
|
||||||
super().__init__(prefix, name=name, **kwargs)
|
|
||||||
self.readback.name = self.name
|
|
||||||
|
|
||||||
def done_comparator(self, readback: Any, setpoint: Any) -> bool:
|
|
||||||
return readback != 4
|
|
||||||
|
|
||||||
|
|
||||||
class X07MAExitSlit(PVPositioner):
|
|
||||||
"""
|
|
||||||
Exit slit
|
|
||||||
"""
|
|
||||||
|
|
||||||
setpoint = Cpt(EpicsSignal, "TR_AP")
|
|
||||||
readback = Cpt(EpicsSignalRO, "TR_ISAP", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
done = Cpt(EpicsSignalRO, "TR.DMOV", kind=Kind.omitted, auto_monitor=True)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
prefix="",
|
|
||||||
*,
|
|
||||||
limits=None,
|
|
||||||
name=None,
|
|
||||||
read_attrs=None,
|
|
||||||
configuration_attrs=None,
|
|
||||||
parent=None,
|
|
||||||
egu="",
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
super().__init__(
|
|
||||||
prefix,
|
|
||||||
limits=limits,
|
|
||||||
name=name,
|
|
||||||
read_attrs=read_attrs,
|
|
||||||
configuration_attrs=configuration_attrs,
|
|
||||||
parent=parent,
|
|
||||||
egu=egu,
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
self.readback.name = self.name
|
|
||||||
|
|
||||||
|
|
||||||
# class X07MAMagnet(Device):
|
|
||||||
# """
|
|
||||||
# Magnet fields.
|
|
||||||
# """
|
|
||||||
|
|
||||||
|
|
||||||
class X07MAMagnetAxis(PVPositioner):
|
|
||||||
"""
|
|
||||||
A single magnet field axis.
|
|
||||||
"""
|
|
||||||
|
|
||||||
done_value = 1
|
|
||||||
actuate_value = 1
|
|
||||||
setpoint = FCpt(EpicsSignal, "{prefix}{_axis_id}:DMD")
|
|
||||||
readback = FCpt(EpicsSignalRO, "{prefix}{_axis_id}:RBV", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
actuate = Cpt(EpicsSignal, "STARTRAMP.PROC", kind=Kind.omitted)
|
|
||||||
done = FCpt(EpicsSignalRO, "{prefix}{_axis_id}:RAMP:DONE", auto_monitor=True)
|
|
||||||
ramprate = FCpt(
|
|
||||||
EpicsSignal, "{_ps_prefix}STS:RAMPRATE:TPM", write_pv="{_ps_prefix}SET:DMD:RAMPRATE:TPM"
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, prefix="", axis_id="", ps_prefix="", *, name=None, **kwargs):
|
|
||||||
self._axis_id = axis_id
|
|
||||||
self._ps_prefix = ps_prefix
|
|
||||||
super().__init__(prefix, name=name, **kwargs)
|
|
||||||
self.readback.name = self.name
|
|
||||||
|
|
||||||
def _setup_move(self, position):
|
|
||||||
# If the setpoint is close to the current readback, the controller will not do anything,
|
|
||||||
# and the done value will not change. So we simply say is done.
|
|
||||||
if abs(position - self.readback.get()) < max(0.004, position * 0.0025):
|
|
||||||
self._done_moving(success=True, time=time.ctime(), value=position)
|
|
||||||
else:
|
|
||||||
super()._setup_move(position)
|
|
||||||
|
|
||||||
# x = Cpt(MagnetAxis, "", axis_id="X", ps_prefix="X07MA-PC-PS2:", name="x")
|
|
||||||
# z = Cpt(MagnetAxis, "", axis_id="Z", ps_prefix="X07MA-PC-PS1:", name="z")
|
|
||||||
|
|
||||||
|
|
||||||
class NormSignal(Signal):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self._metadata.update(write_access=False)
|
|
||||||
|
|
||||||
def wait_for_connection(self, timeout=0):
|
|
||||||
super().wait_for_connection(timeout)
|
|
||||||
self._metadata.update(connected=True)
|
|
||||||
|
|
||||||
def get(self, **kwargs):
|
|
||||||
val1 = self.parent.signal1.get()
|
|
||||||
val2 = self.parent.signal2.get()
|
|
||||||
return val1 / val2 if val2 != 0 else 0
|
|
||||||
|
|
||||||
def describe(self):
|
|
||||||
desc = {
|
|
||||||
"shape": [],
|
|
||||||
"dtype": "number",
|
|
||||||
"source": "PV: {} / {}".format(self.parent.signal1.pvname, self.parent.signal2.pvname),
|
|
||||||
"units": "",
|
|
||||||
"precision": self.parent.signal1.precision,
|
|
||||||
}
|
|
||||||
return desc
|
|
||||||
|
|
||||||
|
|
||||||
class NormTEYSignals(Device):
|
|
||||||
signal1 = Cpt(EpicsSignalRO, name="signal1", read_pv="X07MA-ES1-AI:SIGNAL1", kind="omitted")
|
|
||||||
signal2 = Cpt(EpicsSignalRO, name="signal2", read_pv="X07MA-ES1-AI:SIGNAL2", kind="omitted")
|
|
||||||
norm = Cpt(NormSignal, name="norm", kind="hinted")
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.norm.name = self.name
|
|
||||||
|
|
||||||
|
|
||||||
class NormDIODESignals(Device):
|
|
||||||
signal1 = Cpt(EpicsSignalRO, name="signal1", read_pv="X07MA-ES1-AI:SIGNAL3", kind="omitted")
|
|
||||||
signal2 = Cpt(EpicsSignalRO, name="signal2", read_pv="X07MA-ES1-AI:SIGNAL2", kind="omitted")
|
|
||||||
norm = Cpt(NormSignal, name="norm", kind="hinted")
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.norm.name = self.name
|
|
||||||
|
|
||||||
|
|
||||||
class X07MAAnalogSignals(Device):
|
|
||||||
"""
|
|
||||||
ADC inputs
|
|
||||||
"""
|
|
||||||
|
|
||||||
s1 = Cpt(EpicsSignalRO, "SIGNAL0", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
s2 = Cpt(EpicsSignalRO, "SIGNAL1", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
s3 = Cpt(EpicsSignalRO, "SIGNAL2", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
s4 = Cpt(EpicsSignalRO, "SIGNAL3", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
s5 = Cpt(EpicsSignalRO, "SIGNAL4", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
s6 = Cpt(EpicsSignalRO, "SIGNAL5", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
s7 = Cpt(EpicsSignalRO, "SIGNAL6", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
norm_tey = Cpt(NormTEYSignals, name="norm_tey", kind=Kind.hinted)
|
|
||||||
norm_diode = Cpt(NormDIODESignals, name="norm_tey", kind=Kind.hinted)
|
|
||||||
|
|
||||||
# Aliases
|
|
||||||
# tey = s1
|
|
||||||
# i0 = s2
|
|
||||||
# trans = s3
|
|
||||||
# field_z = s4
|
|
||||||
# field_x = s5
|
|
||||||
|
|
||||||
|
|
||||||
class X07MASampleManipulator(Device):
|
|
||||||
"""
|
|
||||||
Sample manipulator
|
|
||||||
"""
|
|
||||||
|
|
||||||
hor = Cpt(EpicsMotor, "TRZS")
|
|
||||||
vert = Cpt(EpicsMotor, "TRY1")
|
|
||||||
rot = Cpt(EpicsMotor, "ROY1")
|
|
||||||
|
|
||||||
|
|
||||||
class X07MATemperatureController(Device):
|
|
||||||
"""
|
|
||||||
Temperature controller
|
|
||||||
"""
|
|
||||||
|
|
||||||
needle_valve = Cpt(EpicsSignal, "STS:LOOP2:MANUAL", write_pv="DMD:LOOP2:MANUAL")
|
|
||||||
setpoint = Cpt(EpicsSignal, "STS:LOOP1:SETPOINT", write_pv="DMD:LOOP1:SETPOINT")
|
|
||||||
readback = Cpt(EpicsSignalRO, "STS:T1", kind=Kind.hinted, auto_monitor=True)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
prefix="",
|
|
||||||
*,
|
|
||||||
name,
|
|
||||||
kind=None,
|
|
||||||
read_attrs=None,
|
|
||||||
configuration_attrs=None,
|
|
||||||
parent=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
super().__init__(
|
|
||||||
prefix,
|
|
||||||
name=name,
|
|
||||||
kind=kind,
|
|
||||||
read_attrs=read_attrs,
|
|
||||||
configuration_attrs=configuration_attrs,
|
|
||||||
parent=parent,
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
self.readback.name = self.name
|
|
||||||
|
|
||||||
|
|
||||||
class X07MAAutoTemperatureControl(Device):
|
|
||||||
"""
|
|
||||||
Automatic temperature control.
|
|
||||||
"""
|
|
||||||
|
|
||||||
control = Cpt(EpicsSignal, "CONTROL")
|
|
||||||
status = Cpt(EpicsSignalRO, "STATUS", string=True, auto_monitor=True)
|
|
@ -1,34 +0,0 @@
|
|||||||
# Standard ophyd classes
|
|
||||||
from ophyd import EpicsMotor, EpicsSignal, EpicsSignalRO
|
|
||||||
from ophyd.quadem import QuadEM
|
|
||||||
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
|
||||||
|
|
||||||
from .aerotech.AerotechAutomation1 import (
|
|
||||||
EpicsMotorX,
|
|
||||||
aa1AxisDriveDataCollection,
|
|
||||||
aa1AxisPsoDistance,
|
|
||||||
aa1Controller,
|
|
||||||
aa1GlobalVariableBindings,
|
|
||||||
aa1GlobalVariables,
|
|
||||||
aa1Tasks,
|
|
||||||
)
|
|
||||||
|
|
||||||
# cSAXS
|
|
||||||
from .epics_motor_ex import EpicsMotorEx
|
|
||||||
from .grashopper_tomcat import GrashopperTOMCAT
|
|
||||||
from .psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
|
||||||
from .slits import SlitH, SlitV
|
|
||||||
from .specMotors import (
|
|
||||||
Bpm4i,
|
|
||||||
EnergyKev,
|
|
||||||
GirderMotorPITCH,
|
|
||||||
GirderMotorROLL,
|
|
||||||
GirderMotorX1,
|
|
||||||
GirderMotorY1,
|
|
||||||
GirderMotorYAW,
|
|
||||||
MonoTheta1,
|
|
||||||
MonoTheta2,
|
|
||||||
PmDetectorRotation,
|
|
||||||
PmMonoBender,
|
|
||||||
)
|
|
||||||
from .SpmBase import SpmBase
|
|
File diff suppressed because it is too large
Load Diff
@ -1,901 +0,0 @@
|
|||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class TomcatSequencerState:
|
|
||||||
IDLE = 0
|
|
||||||
READY = 1
|
|
||||||
ARMED = 2
|
|
||||||
RUNNING = 3
|
|
||||||
CHANGING = 4
|
|
||||||
ERROR = 15
|
|
||||||
|
|
||||||
|
|
||||||
class AxisDataSignal:
|
|
||||||
PositionFeedback = 0
|
|
||||||
PositionCommand = 1
|
|
||||||
PositionError = 2
|
|
||||||
VelocityFeedback = 3
|
|
||||||
VelocityCommand = 4
|
|
||||||
VelocityError = 5
|
|
||||||
AccelerationCommand = 6
|
|
||||||
CurrentError = 9
|
|
||||||
PositionCommandRaw = 12
|
|
||||||
VelocityCommandRaw = 13
|
|
||||||
AuxiliaryFeedback = 14
|
|
||||||
DigitalInput = 15
|
|
||||||
DigitalOutput = 16
|
|
||||||
FixtureOffset = 18
|
|
||||||
CoordinatedPositionTarget = 41
|
|
||||||
DriveStatus = 42
|
|
||||||
AxisStatus = 43
|
|
||||||
AxisFault = 44
|
|
||||||
AccelerationCommandRaw = 45
|
|
||||||
PositionCalibrationAll = 50
|
|
||||||
PositionFeedbackRollover = 63
|
|
||||||
PositionCommandRollover = 64
|
|
||||||
VelocityFeedbackAverage = 65
|
|
||||||
CurrentFeedbackAverage = 66
|
|
||||||
AxisParameter = 68
|
|
||||||
Backlash = 72
|
|
||||||
HomeState = 73
|
|
||||||
PositionCalibration2D = 74
|
|
||||||
NormalcyDebug = 75
|
|
||||||
TotalMoveTime = 76
|
|
||||||
JerkCommandRaw = 78
|
|
||||||
ProgramPositionCommand = 79
|
|
||||||
PositionOffset = 80
|
|
||||||
PositionCommandRawBackwardsDiff = 82
|
|
||||||
VelocityCommandRawBackwardsDiffDelta = 83
|
|
||||||
DriveStatusActual = 85
|
|
||||||
ProgramPositionFeedback = 89
|
|
||||||
JogTrajectoryStatus = 94
|
|
||||||
PingTest = 95
|
|
||||||
AccelerationTime = 109
|
|
||||||
DecelerationTime = 110
|
|
||||||
AccelerationRate = 111
|
|
||||||
DecelerationRate = 112
|
|
||||||
AccelerationType = 113
|
|
||||||
DecelerationType = 114
|
|
||||||
AccelerationMode = 115
|
|
||||||
DecelerationMode = 116
|
|
||||||
ProgramPosition = 124
|
|
||||||
SpeedTarget = 128
|
|
||||||
PositionCommandPacket = 131
|
|
||||||
DriveSmcMotionState = 132
|
|
||||||
PositionCommandRawCal = 140
|
|
||||||
VelocityCommandRawCal = 141
|
|
||||||
VelocityCommandDrive = 142
|
|
||||||
AccelerationCommandDrive = 143
|
|
||||||
GalvoLaserOutputRaw = 144
|
|
||||||
DriveInterfacePacketInt32 = 147
|
|
||||||
DriveInterfacePacketInt16 = 148
|
|
||||||
DriveInterfacePacketInt8 = 149
|
|
||||||
DriveInterfacePacketDouble = 150
|
|
||||||
DriveInterfacePacketFloat = 151
|
|
||||||
DriveInterfaceCommandCode = 152
|
|
||||||
AccelerationFeedback = 153
|
|
||||||
AccelerationCommandRawCal = 154
|
|
||||||
PositionCalibrationAllDrive = 155
|
|
||||||
BacklashTarget = 156
|
|
||||||
DriveMotionRate = 158
|
|
||||||
DriveMotionDelay = 159
|
|
||||||
CalibrationAdjustmentValue = 160
|
|
||||||
ServoRounding = 161
|
|
||||||
FeedforwardCurrent = 162
|
|
||||||
DriveInterfacePacketInfoBitValue = 164
|
|
||||||
AccelerationError = 165
|
|
||||||
SuppressedFaults = 167
|
|
||||||
DriveInterfacePacketStreamingData = 168
|
|
||||||
PositionCommandRawUnfiltered = 169
|
|
||||||
TransitionOffsetErrors = 170
|
|
||||||
FreezeVelocityCommand = 179
|
|
||||||
FreezeVelocityFeedback = 180
|
|
||||||
InternalPositionOffsets = 181
|
|
||||||
StatusHighLevelOffsetsLastMsec = 182
|
|
||||||
ProgramVelocityCommand = 183
|
|
||||||
ProgramVelocityFeedback = 184
|
|
||||||
DriveMotionDelayLive = 185
|
|
||||||
DriveCommunicationDelay = 186
|
|
||||||
DriveCommunicationDelayLive = 187
|
|
||||||
DriveInterfacePacketResponseInt32 = 189
|
|
||||||
DriveInterfacePacketResponseInt16 = 190
|
|
||||||
DriveInterfacePacketResponseInt8 = 191
|
|
||||||
DriveInterfacePacketResponseDouble = 192
|
|
||||||
DriveInterfacePacketResponseFloat = 193
|
|
||||||
DriveInterfacePacketBit = 194
|
|
||||||
DriveInterfacePacketResponseBit = 195
|
|
||||||
SpeedTargetActual = 196
|
|
||||||
CoordinatedDistanceRemaining = 199
|
|
||||||
SafeZoneState = 230
|
|
||||||
PositionErrorGalvo = 235
|
|
||||||
MoveReferencePosition = 237
|
|
||||||
MoveReferenceCutterOffset = 250
|
|
||||||
MoveReferenceCornerOffset = 251
|
|
||||||
MoveReferenceTotalOffset = 252
|
|
||||||
DistanceLog = 264
|
|
||||||
AutoFocusError = 295
|
|
||||||
GalvoLaserOutputRawAdvance = 296
|
|
||||||
GalvoLaserOnDelay = 297
|
|
||||||
GalvoLaserOffDelay = 298
|
|
||||||
CalibrationAdjustmentState = 301
|
|
||||||
AccuracyCorrectionStartingPosition = 302
|
|
||||||
AccuracyCorrectionEndingPosition = 303
|
|
||||||
DriveCommandsDelayed = 309
|
|
||||||
DriveCommandsLost = 310
|
|
||||||
StoStatus = 327
|
|
||||||
DriveAssert = 336
|
|
||||||
PrimaryFeedback = 366
|
|
||||||
AccelerationSCurvePercentage = 371
|
|
||||||
DecelerationSCurvePercentage = 372
|
|
||||||
GantryMarkerDifference = 390
|
|
||||||
PrimaryFeedbackStatus = 392
|
|
||||||
HomeTargetPosition = 398
|
|
||||||
GantryRealignmentMoveTargetPosition = 399
|
|
||||||
GantryDriveControlRealignmentState = 400
|
|
||||||
DriveInterfacePositionCommandPhysical = 434
|
|
||||||
DriveControlReason = 435
|
|
||||||
CurrentFeedback = 7
|
|
||||||
CurrentCommand = 8
|
|
||||||
AnalogInput0 = 10
|
|
||||||
AnalogInput1 = 11
|
|
||||||
PhaseACurrentFeedback = 19
|
|
||||||
PhaseBCurrentFeedback = 20
|
|
||||||
EncoderSine = 21
|
|
||||||
EncoderCosine = 22
|
|
||||||
AnalogInput2 = 23
|
|
||||||
AnalogInput3 = 24
|
|
||||||
FrequencyResponseBefore = 25
|
|
||||||
FrequencyResponseAfter = 26
|
|
||||||
AnalogOutput0 = 31
|
|
||||||
AnalogOutput1 = 32
|
|
||||||
AnalogOutput2 = 33
|
|
||||||
AnalogOutput3 = 34
|
|
||||||
DriveMemoryInt32 = 35
|
|
||||||
DriveMemoryFloat = 36
|
|
||||||
DriveMemoryDouble = 37
|
|
||||||
PsoStatus = 38
|
|
||||||
DriveTimerDebug = 39
|
|
||||||
PositionFeedbackDrive = 77
|
|
||||||
PositionCommandDrive = 84
|
|
||||||
DriveMemoryInt16 = 125
|
|
||||||
DriveMemoryInt8 = 126
|
|
||||||
PsoCounter0 = 171
|
|
||||||
PsoCounter1 = 172
|
|
||||||
PsoCounter2 = 173
|
|
||||||
PsoWindow0 = 174
|
|
||||||
PsoWindow1 = 175
|
|
||||||
DriveDataCaptureSamples = 176
|
|
||||||
PositionCommandGalvo = 178
|
|
||||||
PrimaryEnDatAbsolutePosition = 197
|
|
||||||
ControlEffort = 201
|
|
||||||
PhaseAVoltageCommand = 208
|
|
||||||
PhaseBVoltageCommand = 209
|
|
||||||
PhaseCVoltageCommand = 210
|
|
||||||
AmplifierPeakCurrent = 211
|
|
||||||
FpgaVersion = 212
|
|
||||||
DriveTypeId = 213
|
|
||||||
PsoWindow0ArrayIndex = 214
|
|
||||||
PsoWindow1ArrayIndex = 215
|
|
||||||
PsoDistanceArrayIndex = 216
|
|
||||||
AmplifierTemperature = 217
|
|
||||||
PsoBitArrayIndex = 218
|
|
||||||
MxAbsolutePosition = 219
|
|
||||||
ServoUpdateRate = 220
|
|
||||||
SettlingTime = 221
|
|
||||||
InternalStatusCode = 222
|
|
||||||
FirmwareVersionMajor = 223
|
|
||||||
FirmwareVersionMinor = 224
|
|
||||||
FirmwareVersionPatch = 225
|
|
||||||
FirmwareVersionBuild = 226
|
|
||||||
DriveTimerDebugMax = 227
|
|
||||||
MarkerSearchDistance = 228
|
|
||||||
PositionFeedbackGalvo = 234
|
|
||||||
LatchedMarkerPosition = 236
|
|
||||||
PrimaryBissAbsolutePosition = 255
|
|
||||||
FaultPositionFeedback = 258
|
|
||||||
MotorCommutationAngle = 259
|
|
||||||
ExpansionBoardOption = 260
|
|
||||||
BusVoltage = 261
|
|
||||||
PiezoVoltageCommand = 262
|
|
||||||
PiezoVoltageFeedback = 263
|
|
||||||
TimeSinceReset = 273
|
|
||||||
MaximumVoltage = 274
|
|
||||||
CommandOutputType = 275
|
|
||||||
DriveFeedforwardOutput = 290
|
|
||||||
LastTickCounter = 291
|
|
||||||
BoardRevision = 292
|
|
||||||
GalvoLaserOutput = 294
|
|
||||||
GalvoLaserPowerCorrectionOutput = 299
|
|
||||||
CapacitanceSensorRawPosition = 300
|
|
||||||
PositionCalibrationGalvo = 304
|
|
||||||
BusVoltageNegative = 325
|
|
||||||
ProcessorTemperature = 326
|
|
||||||
InternalStatusTimestamp = 328
|
|
||||||
AnalogSensorInput = 329
|
|
||||||
MotorTemperature = 330
|
|
||||||
PrimaryBissStatus = 332
|
|
||||||
PsoExternalSyncFrequency = 337
|
|
||||||
EncoderSineRaw = 346
|
|
||||||
EncoderCosineRaw = 347
|
|
||||||
FpgaTemperature = 353
|
|
||||||
PrimaryEnDatStatus = 355
|
|
||||||
DriveTimerHighPriorityThread = 356
|
|
||||||
DriveTimerLowPriorityThread = 357
|
|
||||||
DriveTimerLowPriorityPacket = 358
|
|
||||||
DriveTimerServoPacket = 359
|
|
||||||
DriveTimerServoThread = 360
|
|
||||||
DriveTimerCurrentPacket = 361
|
|
||||||
DriveTimerCommonCoreThread = 362
|
|
||||||
DriveTimerServoCorePacket0 = 363
|
|
||||||
DriveTimerServoCorePacket1 = 364
|
|
||||||
MultiplierOption = 365
|
|
||||||
ServoLoopFeedbackInput0 = 367
|
|
||||||
ServoLoopFeedbackInput1 = 368
|
|
||||||
FaultSubcode = 376
|
|
||||||
ProcessorTemperatureMax = 378
|
|
||||||
DriveTimerHyperWireDma = 381
|
|
||||||
AmplifierTemperatureMax = 382
|
|
||||||
AuxiliaryEnDatAbsolutePosition = 383
|
|
||||||
AuxiliaryEnDatStatus = 384
|
|
||||||
AuxiliaryBissAbsolutePosition = 385
|
|
||||||
AuxiliaryBissStatus = 386
|
|
||||||
PsoOption = 387
|
|
||||||
DriveArraySize = 388
|
|
||||||
RatedMotorSupplyVoltageOption = 389
|
|
||||||
AbsoluteEncoderOption = 391
|
|
||||||
AuxiliaryFeedbackStatus = 393
|
|
||||||
AmplifierStatus = 394
|
|
||||||
LatchedCwLimitPosition = 395
|
|
||||||
LatchedCcwLimitPosition = 396
|
|
||||||
GalvoLaserFpgaTransitionDelay = 397
|
|
||||||
PiezoAccumulatedCharge = 401
|
|
||||||
PiezoChargingTime = 402
|
|
||||||
PrimarySsiAbsolutePosition = 403
|
|
||||||
PrimarySsiStatus = 404
|
|
||||||
AuxiliarySsiAbsolutePosition = 405
|
|
||||||
AuxiliarySsiStatus = 406
|
|
||||||
PsoDistanceActiveDistance = 407
|
|
||||||
PsoWindow0ActiveLowerBound = 408
|
|
||||||
PsoWindow0ActiveUpperBound = 409
|
|
||||||
PsoWindow1ActiveLowerBound = 410
|
|
||||||
PsoWindow1ActiveUpperBound = 411
|
|
||||||
PsoWaveformActiveTotalTime = 412
|
|
||||||
PsoWaveformActiveOnTime = 413
|
|
||||||
PsoWaveformActivePulseCount = 414
|
|
||||||
PsoEventActiveBitValue = 415
|
|
||||||
DriveTimerDriveBasedControllerOutputDma = 419
|
|
||||||
DriveTimerPcieInboundFsm = 420
|
|
||||||
PrimaryFeedbackServo = 425
|
|
||||||
AuxiliaryFeedbackServo = 426
|
|
||||||
DriveStackUsage = 427
|
|
||||||
ShuntResistorTemperature = 436
|
|
||||||
|
|
||||||
|
|
||||||
class TaskDataSignal:
|
|
||||||
ProgramLineNumber = 17
|
|
||||||
CoordinatedFlags = 40
|
|
||||||
CoordinatedArcStartAngle = 53
|
|
||||||
CoordinatedArcEndAngle = 54
|
|
||||||
CoordinatedArcRadius = 55
|
|
||||||
CoordinatedArcRadiusError = 56
|
|
||||||
CoordinatedPositionCommand = 57
|
|
||||||
CoordinatedSpeedCommand = 58
|
|
||||||
CoordinatedAccelerationCommand = 59
|
|
||||||
CoordinatedTotalDistance = 60
|
|
||||||
CoordinatedPercentDone = 61
|
|
||||||
CoordinatedPositionCommandBackwardsDiff = 62
|
|
||||||
TaskParameter = 69
|
|
||||||
TaskError = 70
|
|
||||||
TaskWarning = 71
|
|
||||||
CoordinatedSpeedTargetActual = 86
|
|
||||||
DependentCoordinatedSpeedTargetActual = 87
|
|
||||||
ActiveFixtureOffset = 88
|
|
||||||
TaskStatus0 = 90
|
|
||||||
TaskStatus1 = 91
|
|
||||||
TaskStatus2 = 92
|
|
||||||
SpindleSpeedTarget = 93
|
|
||||||
CoordinateSystem1I = 96
|
|
||||||
CoordinateSystem1J = 97
|
|
||||||
CoordinateSystem1K = 98
|
|
||||||
CoordinateSystem1Plane = 99
|
|
||||||
ToolNumberActive = 100
|
|
||||||
Mfo = 101
|
|
||||||
CoordinatedSpeedTarget = 102
|
|
||||||
DependentCoordinatedSpeedTarget = 103
|
|
||||||
CoordinatedAccelerationRate = 104
|
|
||||||
CoordinatedDecelerationRate = 105
|
|
||||||
CoordinatedAccelerationTime = 106
|
|
||||||
CoordinatedDecelerationTime = 107
|
|
||||||
TaskMode = 108
|
|
||||||
TaskState = 117
|
|
||||||
TaskStateInternal = 118
|
|
||||||
ExecutionMode = 121
|
|
||||||
EnableAlignmentAxes = 127
|
|
||||||
CoordinatedGalvoLaserOutput = 133
|
|
||||||
CoordinatedMotionRate = 145
|
|
||||||
CoordinatedTaskCommand = 146
|
|
||||||
EnableState = 166
|
|
||||||
LookaheadMovesExamined = 200
|
|
||||||
ProfileControlMask = 231
|
|
||||||
CoordinatedArcRadiusReciprocal = 253
|
|
||||||
MotionEngineStage = 254
|
|
||||||
CoordinatedTimeScale = 256
|
|
||||||
CoordinatedTimeScaleDerivative = 257
|
|
||||||
IfovSpeedScale = 266
|
|
||||||
IfovSpeedScaleAverage = 267
|
|
||||||
IfovGenerationFrameCounter = 268
|
|
||||||
IfovGenerationTimeOriginal = 269
|
|
||||||
IfovGenerationTimeModified = 270
|
|
||||||
IfovCoordinatedPositionCommand = 271
|
|
||||||
IfovCoordinatedSpeedCommand = 272
|
|
||||||
IfovCenterPointH = 276
|
|
||||||
IfovCenterPointV = 277
|
|
||||||
IfovTrajectoryCount = 278
|
|
||||||
IfovTrajectoryIndex = 279
|
|
||||||
IfovAttemptCode = 280
|
|
||||||
IfovGenerationFrameIndex = 281
|
|
||||||
IfovMaximumVelocity = 282
|
|
||||||
IfovIdealVelocity = 283
|
|
||||||
TaskInternalDebug = 284
|
|
||||||
IfovCoordinatedAccelerationCommand = 285
|
|
||||||
IfovFovPositionH = 286
|
|
||||||
IfovFovPositionV = 287
|
|
||||||
IfovFovDimensionH = 288
|
|
||||||
IfovFovDimensionV = 289
|
|
||||||
MotionBufferElements = 311
|
|
||||||
MotionBufferMoves = 312
|
|
||||||
MotionLineNumber = 313
|
|
||||||
MotionBufferRetraceMoves = 314
|
|
||||||
MotionBufferRetraceElements = 315
|
|
||||||
MotionBufferIndex = 316
|
|
||||||
MotionBufferIndexLookahead = 317
|
|
||||||
MotionBufferProcessingBlocked = 318
|
|
||||||
ActiveMoveValid = 319
|
|
||||||
TaskExecutionLines = 320
|
|
||||||
SchedulerTaskHolds = 321
|
|
||||||
SchedulerProgramLoopRuns = 322
|
|
||||||
SchedulerTaskBlocked = 323
|
|
||||||
CriticalSectionsActive = 324
|
|
||||||
AxesSlowdownReason = 331
|
|
||||||
TaskExecutionTime = 333
|
|
||||||
TaskExecutionTimeMaximum = 334
|
|
||||||
TaskExecutionLinesMaximum = 335
|
|
||||||
LookaheadDecelReason = 338
|
|
||||||
LookaheadDecelMoves = 339
|
|
||||||
LookaheadDecelDistance = 340
|
|
||||||
ProgramCounter = 341
|
|
||||||
StackPointer = 342
|
|
||||||
FramePointer = 343
|
|
||||||
StringStackPointer = 344
|
|
||||||
ProgramLineNumberSourceFileId = 349
|
|
||||||
MotionLineNumberSourceFileId = 350
|
|
||||||
ProgramLineNumberSourcePathId = 351
|
|
||||||
MotionLineNumberSourcePathId = 352
|
|
||||||
StringArgumentStackPointer = 354
|
|
||||||
CoordinatedAccelerationSCurvePercentage = 369
|
|
||||||
CoordinatedDecelerationSCurvePercentage = 370
|
|
||||||
DependentCoordinatedAccelerationRate = 373
|
|
||||||
DependentCoordinatedDecelerationRate = 374
|
|
||||||
CriticalSectionTimeout = 375
|
|
||||||
CommandQueueCapacity = 421
|
|
||||||
CommandQueueUnexecutedCount = 422
|
|
||||||
CommandQueueTimesEmptied = 423
|
|
||||||
CommandQueueExecutedCount = 424
|
|
||||||
|
|
||||||
|
|
||||||
class SystemDataSignal:
|
|
||||||
VirtualBinaryInput = 46
|
|
||||||
VirtualBinaryOutput = 47
|
|
||||||
VirtualRegisterInput = 48
|
|
||||||
VirtualRegisterOutput = 49
|
|
||||||
Timer = 51
|
|
||||||
TimerPerformance = 52
|
|
||||||
GlobalReal = 67
|
|
||||||
CommunicationRealTimeErrors = 81
|
|
||||||
LibraryCommand = 119
|
|
||||||
DataCollectionSampleTime = 120
|
|
||||||
DataCollectionSampleIndex = 129
|
|
||||||
ModbusClientConnected = 134
|
|
||||||
ModbusServerConnected = 135
|
|
||||||
ModbusClientError = 136
|
|
||||||
ModbusServerError = 137
|
|
||||||
StopWatchTimer = 157
|
|
||||||
ScopetrigId = 163
|
|
||||||
EstimatedProcessorUsage = 177
|
|
||||||
DataCollectionStatus = 188
|
|
||||||
SignalLogState = 198
|
|
||||||
SafeZoneViolationMask = 207
|
|
||||||
SafeZoneActiveMask = 229
|
|
||||||
ModbusClientInputWords = 240
|
|
||||||
ModbusClientOutputWords = 241
|
|
||||||
ModbusClientInputBits = 242
|
|
||||||
ModbusClientOutputBits = 243
|
|
||||||
ModbusClientOutputBitsStatus = 244
|
|
||||||
ModbusClientOutputWordsStatus = 245
|
|
||||||
ModbusServerInputWords = 246
|
|
||||||
ModbusServerOutputWords = 247
|
|
||||||
ModbusServerInputBits = 248
|
|
||||||
ModbusServerOutputBits = 249
|
|
||||||
SystemParameter = 265
|
|
||||||
ThermoCompSensorTemperature = 305
|
|
||||||
ThermoCompControllingTemperature = 306
|
|
||||||
ThermoCompCompensatingTemperature = 307
|
|
||||||
ThermoCompStatus = 308
|
|
||||||
GlobalInteger = 345
|
|
||||||
AliveAxesMask = 348
|
|
||||||
SignalLogPointsStored = 377
|
|
||||||
ControllerInitializationWarning = 379
|
|
||||||
StopWatchTimerMin = 416
|
|
||||||
StopWatchTimerMax = 417
|
|
||||||
StopWatchTimerAvg = 418
|
|
||||||
EthercatEnabled = 428
|
|
||||||
EthercatError = 429
|
|
||||||
EthercatTxPdo = 430
|
|
||||||
EthercatTxPdoSize = 431
|
|
||||||
EthercatRxPdo = 432
|
|
||||||
EthercatRxPdoSize = 433
|
|
||||||
EthercatState = 437
|
|
||||||
ModbusClientEnabled = 438
|
|
||||||
ModbusServerEnabled = 439
|
|
||||||
|
|
||||||
|
|
||||||
class DataCollectionFrequency:
|
|
||||||
Undefined = 0
|
|
||||||
Fixed1kHz = 1
|
|
||||||
Fixed10kHz = 2
|
|
||||||
Fixed20kHz = 3
|
|
||||||
Fixed100kHz = 4
|
|
||||||
Fixed200kHz = 5
|
|
||||||
|
|
||||||
|
|
||||||
class DataCollectionMode:
|
|
||||||
Snapshot = 0
|
|
||||||
Continouous = 1
|
|
||||||
|
|
||||||
|
|
||||||
# Specifies the PSO distance input settings for the XC4e drive.
|
|
||||||
class PsoDistanceInput:
|
|
||||||
XC4PrimaryFeedback = 130
|
|
||||||
XC4AuxiliaryFeedback = 131
|
|
||||||
XC4SyncPortA = 132
|
|
||||||
XC4SyncPortB = 133
|
|
||||||
XC4DrivePulseStream = 134
|
|
||||||
XC4ePrimaryFeedback = 135
|
|
||||||
XC4eAuxiliaryFeedback = 136
|
|
||||||
XC4eSyncPortA = 137
|
|
||||||
XC4eSyncPortB = 138
|
|
||||||
XC4eDrivePulseStream = 139
|
|
||||||
|
|
||||||
|
|
||||||
class PsoWindowInput:
|
|
||||||
XC4PrimaryFeedback = 130
|
|
||||||
XC4AuxiliaryFeedback = 131
|
|
||||||
XC4SyncPortA = 132
|
|
||||||
XC4SyncPortB = 133
|
|
||||||
XC4DrivePulseStream = 134
|
|
||||||
XC4ePrimaryFeedback = 135
|
|
||||||
XC4eAuxiliaryFeedback = 136
|
|
||||||
XC4eSyncPortA = 137
|
|
||||||
XC4eSyncPortB = 138
|
|
||||||
XC4eDrivePulseStream = 139
|
|
||||||
XL5ePrimaryFeedback = (145,)
|
|
||||||
XL5eAuxiliaryFeedback = (146,)
|
|
||||||
XL5eSyncPortA = (147,)
|
|
||||||
XL5eSyncPortB = (148,)
|
|
||||||
XL5eDrivePulseStream = (149,)
|
|
||||||
|
|
||||||
|
|
||||||
# @brief Specifies the PSO output pin settings for each drive.
|
|
||||||
class XC4ePsoOutputPin:
|
|
||||||
DedicatedOutput = 111
|
|
||||||
AuxiliaryMarkerDifferential = 112
|
|
||||||
AuxiliaryMarkerSingleEnded = 113
|
|
||||||
|
|
||||||
|
|
||||||
class XC4PsoOutputPin:
|
|
||||||
DedicatedOutput = 108
|
|
||||||
AuxiliaryMarkerDifferential = 109
|
|
||||||
AuxiliaryMarkerSingleEnded = 110
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
# @brief Specifies the PSO distance input settings for each drive.
|
|
||||||
class Automation1PsoDistanceInput:
|
|
||||||
Automation1PsoDistanceInput_GL4PrimaryFeedbackAxis1 = 100,
|
|
||||||
Automation1PsoDistanceInput_GL4PrimaryFeedbackAxis2 = 101,
|
|
||||||
Automation1PsoDistanceInput_GL4IfovFeedbackAxis1 = 102,
|
|
||||||
Automation1PsoDistanceInput_GL4IfovFeedbackAxis2 = 103,
|
|
||||||
Automation1PsoDistanceInput_GL4AuxiliaryFeedbackAxis1 = 104,
|
|
||||||
Automation1PsoDistanceInput_GL4AuxiliaryFeedbackAxis2 = 105,
|
|
||||||
Automation1PsoDistanceInput_GL4SyncPortA = 106,
|
|
||||||
Automation1PsoDistanceInput_GL4SyncPortB = 107,
|
|
||||||
Automation1PsoDistanceInput_GL4DrivePulseStreamAxis1 = 108,
|
|
||||||
Automation1PsoDistanceInput_GL4DrivePulseStreamAxis2 = 109,
|
|
||||||
Automation1PsoDistanceInput_XL4sPrimaryFeedback = 110,
|
|
||||||
Automation1PsoDistanceInput_XL4sAuxiliaryFeedback = 111,
|
|
||||||
Automation1PsoDistanceInput_XL4sSyncPortA = 112,
|
|
||||||
Automation1PsoDistanceInput_XL4sSyncPortB = 113,
|
|
||||||
Automation1PsoDistanceInput_XL4sDrivePulseStream = 114,
|
|
||||||
Automation1PsoDistanceInput_XR3PrimaryFeedbackAxis1 = 115,
|
|
||||||
Automation1PsoDistanceInput_XR3PrimaryFeedbackAxis2 = 116,
|
|
||||||
Automation1PsoDistanceInput_XR3PrimaryFeedbackAxis3 = 117,
|
|
||||||
Automation1PsoDistanceInput_XR3PrimaryFeedbackAxis4 = 118,
|
|
||||||
Automation1PsoDistanceInput_XR3PrimaryFeedbackAxis5 = 119,
|
|
||||||
Automation1PsoDistanceInput_XR3PrimaryFeedbackAxis6 = 120,
|
|
||||||
Automation1PsoDistanceInput_XR3AuxiliaryFeedbackAxis1 = 121,
|
|
||||||
Automation1PsoDistanceInput_XR3AuxiliaryFeedbackAxis2 = 122,
|
|
||||||
Automation1PsoDistanceInput_XR3AuxiliaryFeedbackAxis3 = 123,
|
|
||||||
Automation1PsoDistanceInput_XR3AuxiliaryFeedbackAxis4 = 124,
|
|
||||||
Automation1PsoDistanceInput_XR3AuxiliaryFeedbackAxis5 = 125,
|
|
||||||
Automation1PsoDistanceInput_XR3AuxiliaryFeedbackAxis6 = 126,
|
|
||||||
Automation1PsoDistanceInput_XR3SyncPortA = 127,
|
|
||||||
Automation1PsoDistanceInput_XR3SyncPortB = 128,
|
|
||||||
Automation1PsoDistanceInput_XR3DrivePulseStream = 129,
|
|
||||||
Automation1PsoDistanceInput_XC4PrimaryFeedback = 130,
|
|
||||||
Automation1PsoDistanceInput_XC4AuxiliaryFeedback = 131,
|
|
||||||
Automation1PsoDistanceInput_XC4SyncPortA = 132,
|
|
||||||
Automation1PsoDistanceInput_XC4SyncPortB = 133,
|
|
||||||
Automation1PsoDistanceInput_XC4DrivePulseStream = 134,
|
|
||||||
XC4ePrimaryFeedback = 135,
|
|
||||||
XC4eAuxiliaryFeedback = 136,
|
|
||||||
XC4eSyncPortA = 137,
|
|
||||||
XC4eSyncPortB = 138,
|
|
||||||
XC4eDrivePulseStream = 139,
|
|
||||||
Automation1PsoDistanceInput_XC6ePrimaryFeedback = 140,
|
|
||||||
Automation1PsoDistanceInput_XC6eAuxiliaryFeedback = 141,
|
|
||||||
Automation1PsoDistanceInput_XC6eSyncPortA = 142,
|
|
||||||
Automation1PsoDistanceInput_XC6eSyncPortB = 143,
|
|
||||||
Automation1PsoDistanceInput_XC6eDrivePulseStream = 144,
|
|
||||||
Automation1PsoDistanceInput_XL5ePrimaryFeedback = 145,
|
|
||||||
Automation1PsoDistanceInput_XL5eAuxiliaryFeedback = 146,
|
|
||||||
Automation1PsoDistanceInput_XL5eSyncPortA = 147,
|
|
||||||
Automation1PsoDistanceInput_XL5eSyncPortB = 148,
|
|
||||||
Automation1PsoDistanceInput_XL5eDrivePulseStream = 149,
|
|
||||||
Automation1PsoDistanceInput_XC2PrimaryFeedback = 150,
|
|
||||||
Automation1PsoDistanceInput_XC2AuxiliaryFeedback = 151,
|
|
||||||
Automation1PsoDistanceInput_XC2DrivePulseStream = 152,
|
|
||||||
Automation1PsoDistanceInput_XC2ePrimaryFeedback = 153,
|
|
||||||
Automation1PsoDistanceInput_XC2eAuxiliaryFeedback = 154,
|
|
||||||
Automation1PsoDistanceInput_XC2eDrivePulseStream = 155,
|
|
||||||
Automation1PsoDistanceInput_XL2ePrimaryFeedback = 156,
|
|
||||||
Automation1PsoDistanceInput_XL2eAuxiliaryFeedback = 157,
|
|
||||||
Automation1PsoDistanceInput_XL2eSyncPortA = 158,
|
|
||||||
Automation1PsoDistanceInput_XL2eSyncPortB = 159,
|
|
||||||
Automation1PsoDistanceInput_XL2eDrivePulseStream = 160,
|
|
||||||
Automation1PsoDistanceInput_XI4PrimaryFeedbackAxis1 = 161,
|
|
||||||
Automation1PsoDistanceInput_XI4PrimaryFeedbackAxis2 = 162,
|
|
||||||
Automation1PsoDistanceInput_XI4PrimaryFeedbackAxis3 = 163,
|
|
||||||
Automation1PsoDistanceInput_XI4PrimaryFeedbackAxis4 = 164,
|
|
||||||
Automation1PsoDistanceInput_XI4AuxiliaryFeedback1 = 165,
|
|
||||||
Automation1PsoDistanceInput_XI4AuxiliaryFeedback2 = 166,
|
|
||||||
Automation1PsoDistanceInput_XI4AuxiliaryFeedback3 = 167,
|
|
||||||
Automation1PsoDistanceInput_XI4AuxiliaryFeedback4 = 168,
|
|
||||||
Automation1PsoDistanceInput_XI4SyncPortA = 169,
|
|
||||||
Automation1PsoDistanceInput_XI4SyncPortB = 170,
|
|
||||||
Automation1PsoDistanceInput_XI4DrivePulseStreamAxis1 = 171,
|
|
||||||
Automation1PsoDistanceInput_XI4DrivePulseStreamAxis2 = 172,
|
|
||||||
Automation1PsoDistanceInput_XI4DrivePulseStreamAxis3 = 173,
|
|
||||||
Automation1PsoDistanceInput_XI4DrivePulseStreamAxis4 = 174,
|
|
||||||
Automation1PsoDistanceInput_iXC4PrimaryFeedback = 175,
|
|
||||||
Automation1PsoDistanceInput_iXC4AuxiliaryFeedback = 176,
|
|
||||||
Automation1PsoDistanceInput_iXC4SyncPortA = 177,
|
|
||||||
Automation1PsoDistanceInput_iXC4SyncPortB = 178,
|
|
||||||
Automation1PsoDistanceInput_iXC4DrivePulseStream = 179,
|
|
||||||
Automation1PsoDistanceInput_iXC4ePrimaryFeedback = 180,
|
|
||||||
Automation1PsoDistanceInput_iXC4eAuxiliaryFeedback = 181,
|
|
||||||
Automation1PsoDistanceInput_iXC4eSyncPortA = 182,
|
|
||||||
Automation1PsoDistanceInput_iXC4eSyncPortB = 183,
|
|
||||||
Automation1PsoDistanceInput_iXC4eDrivePulseStream = 184,
|
|
||||||
Automation1PsoDistanceInput_iXC6ePrimaryFeedback = 185,
|
|
||||||
Automation1PsoDistanceInput_iXC6eAuxiliaryFeedback = 186,
|
|
||||||
Automation1PsoDistanceInput_iXC6eSyncPortA = 187,
|
|
||||||
Automation1PsoDistanceInput_iXC6eSyncPortB = 188,
|
|
||||||
Automation1PsoDistanceInput_iXC6eDrivePulseStream = 189,
|
|
||||||
Automation1PsoDistanceInput_iXL5ePrimaryFeedback = 190,
|
|
||||||
Automation1PsoDistanceInput_iXL5eAuxiliaryFeedback = 191,
|
|
||||||
Automation1PsoDistanceInput_iXL5eSyncPortA = 192,
|
|
||||||
Automation1PsoDistanceInput_iXL5eSyncPortB = 193,
|
|
||||||
Automation1PsoDistanceInput_iXL5eDrivePulseStream = 194,
|
|
||||||
Automation1PsoDistanceInput_iXR3PrimaryFeedbackAxis1 = 195,
|
|
||||||
Automation1PsoDistanceInput_iXR3PrimaryFeedbackAxis2 = 196,
|
|
||||||
Automation1PsoDistanceInput_iXR3PrimaryFeedbackAxis3 = 197,
|
|
||||||
Automation1PsoDistanceInput_iXR3PrimaryFeedbackAxis4 = 198,
|
|
||||||
Automation1PsoDistanceInput_iXR3PrimaryFeedbackAxis5 = 199,
|
|
||||||
Automation1PsoDistanceInput_iXR3PrimaryFeedbackAxis6 = 200,
|
|
||||||
Automation1PsoDistanceInput_iXR3AuxiliaryFeedbackAxis1 = 201,
|
|
||||||
Automation1PsoDistanceInput_iXR3AuxiliaryFeedbackAxis2 = 202,
|
|
||||||
Automation1PsoDistanceInput_iXR3AuxiliaryFeedbackAxis3 = 203,
|
|
||||||
Automation1PsoDistanceInput_iXR3AuxiliaryFeedbackAxis4 = 204,
|
|
||||||
Automation1PsoDistanceInput_iXR3AuxiliaryFeedbackAxis5 = 205,
|
|
||||||
Automation1PsoDistanceInput_iXR3AuxiliaryFeedbackAxis6 = 206,
|
|
||||||
Automation1PsoDistanceInput_iXR3SyncPortA = 207,
|
|
||||||
Automation1PsoDistanceInput_iXR3SyncPortB = 208,
|
|
||||||
Automation1PsoDistanceInput_iXR3DrivePulseStream = 209,
|
|
||||||
Automation1PsoDistanceInput_GI4DrivePulseStreamAxis1 = 210,
|
|
||||||
Automation1PsoDistanceInput_GI4DrivePulseStreamAxis2 = 211,
|
|
||||||
Automation1PsoDistanceInput_GI4DrivePulseStreamAxis3 = 212,
|
|
||||||
Automation1PsoDistanceInput_iXC2PrimaryFeedback = 213,
|
|
||||||
Automation1PsoDistanceInput_iXC2AuxiliaryFeedback = 214,
|
|
||||||
Automation1PsoDistanceInput_iXC2DrivePulseStream = 215,
|
|
||||||
Automation1PsoDistanceInput_iXC2ePrimaryFeedback = 216,
|
|
||||||
Automation1PsoDistanceInput_iXC2eAuxiliaryFeedback = 217,
|
|
||||||
Automation1PsoDistanceInput_iXC2eDrivePulseStream = 218,
|
|
||||||
Automation1PsoDistanceInput_iXL2ePrimaryFeedback = 219,
|
|
||||||
Automation1PsoDistanceInput_iXL2eAuxiliaryFeedback = 220,
|
|
||||||
Automation1PsoDistanceInput_iXL2eSyncPortA = 221,
|
|
||||||
Automation1PsoDistanceInput_iXL2eSyncPortB = 222,
|
|
||||||
Automation1PsoDistanceInput_iXL2eDrivePulseStream = 223,
|
|
||||||
Automation1PsoDistanceInput_iXI4PrimaryFeedbackAxis1 = 224,
|
|
||||||
Automation1PsoDistanceInput_iXI4PrimaryFeedbackAxis2 = 225,
|
|
||||||
Automation1PsoDistanceInput_iXI4PrimaryFeedbackAxis3 = 226,
|
|
||||||
Automation1PsoDistanceInput_iXI4PrimaryFeedbackAxis4 = 227,
|
|
||||||
Automation1PsoDistanceInput_iXI4AuxiliaryFeedback1 = 228,
|
|
||||||
Automation1PsoDistanceInput_iXI4AuxiliaryFeedback2 = 229,
|
|
||||||
Automation1PsoDistanceInput_iXI4AuxiliaryFeedback3 = 230,
|
|
||||||
Automation1PsoDistanceInput_iXI4AuxiliaryFeedback4 = 231,
|
|
||||||
Automation1PsoDistanceInput_iXI4SyncPortA = 232,
|
|
||||||
Automation1PsoDistanceInput_iXI4SyncPortB = 233,
|
|
||||||
Automation1PsoDistanceInput_iXI4DrivePulseStreamAxis1 = 234,
|
|
||||||
Automation1PsoDistanceInput_iXI4DrivePulseStreamAxis2 = 235,
|
|
||||||
Automation1PsoDistanceInput_iXI4DrivePulseStreamAxis3 = 236,
|
|
||||||
Automation1PsoDistanceInput_iXI4DrivePulseStreamAxis4 = 237,
|
|
||||||
|
|
||||||
# @brief Specifies the PSO window input settings for each drive.
|
|
||||||
class Automation1PsoWindowInput:
|
|
||||||
Automation1PsoWindowInput_GL4PrimaryFeedbackAxis1 = 100,
|
|
||||||
Automation1PsoWindowInput_GL4PrimaryFeedbackAxis2 = 101,
|
|
||||||
Automation1PsoWindowInput_GL4IfovFeedbackAxis1 = 102,
|
|
||||||
Automation1PsoWindowInput_GL4IfovFeedbackAxis2 = 103,
|
|
||||||
Automation1PsoWindowInput_GL4AuxiliaryFeedbackAxis1 = 104,
|
|
||||||
Automation1PsoWindowInput_GL4AuxiliaryFeedbackAxis2 = 105,
|
|
||||||
Automation1PsoWindowInput_GL4SyncPortA = 106,
|
|
||||||
Automation1PsoWindowInput_GL4SyncPortB = 107,
|
|
||||||
Automation1PsoWindowInput_GL4DrivePulseStreamAxis1 = 108,
|
|
||||||
Automation1PsoWindowInput_GL4DrivePulseStreamAxis2 = 109,
|
|
||||||
Automation1PsoWindowInput_XL4sPrimaryFeedback = 110,
|
|
||||||
Automation1PsoWindowInput_XL4sAuxiliaryFeedback = 111,
|
|
||||||
Automation1PsoWindowInput_XL4sSyncPortA = 112,
|
|
||||||
Automation1PsoWindowInput_XL4sSyncPortB = 113,
|
|
||||||
Automation1PsoWindowInput_XL4sDrivePulseStream = 114,
|
|
||||||
Automation1PsoWindowInput_XR3PrimaryFeedbackAxis1 = 115,
|
|
||||||
Automation1PsoWindowInput_XR3PrimaryFeedbackAxis2 = 116,
|
|
||||||
Automation1PsoWindowInput_XR3PrimaryFeedbackAxis3 = 117,
|
|
||||||
Automation1PsoWindowInput_XR3PrimaryFeedbackAxis4 = 118,
|
|
||||||
Automation1PsoWindowInput_XR3PrimaryFeedbackAxis5 = 119,
|
|
||||||
Automation1PsoWindowInput_XR3PrimaryFeedbackAxis6 = 120,
|
|
||||||
Automation1PsoWindowInput_XR3AuxiliaryFeedbackAxis1 = 121,
|
|
||||||
Automation1PsoWindowInput_XR3AuxiliaryFeedbackAxis2 = 122,
|
|
||||||
Automation1PsoWindowInput_XR3AuxiliaryFeedbackAxis3 = 123,
|
|
||||||
Automation1PsoWindowInput_XR3AuxiliaryFeedbackAxis4 = 124,
|
|
||||||
Automation1PsoWindowInput_XR3AuxiliaryFeedbackAxis5 = 125,
|
|
||||||
Automation1PsoWindowInput_XR3AuxiliaryFeedbackAxis6 = 126,
|
|
||||||
Automation1PsoWindowInput_XR3SyncPortA = 127,
|
|
||||||
Automation1PsoWindowInput_XR3SyncPortB = 128,
|
|
||||||
Automation1PsoWindowInput_XR3DrivePulseStream = 129,
|
|
||||||
Automation1PsoWindowInput_XC4PrimaryFeedback = 130,
|
|
||||||
Automation1PsoWindowInput_XC4AuxiliaryFeedback = 131,
|
|
||||||
Automation1PsoWindowInput_XC4SyncPortA = 132,
|
|
||||||
Automation1PsoWindowInput_XC4SyncPortB = 133,
|
|
||||||
Automation1PsoWindowInput_XC4DrivePulseStream = 134,
|
|
||||||
XC4ePrimaryFeedback = 135,
|
|
||||||
XC4eAuxiliaryFeedback = 136,
|
|
||||||
XC4eSyncPortA = 137,
|
|
||||||
XC4eSyncPortB = 138,
|
|
||||||
XC4eDrivePulseStream = 139,
|
|
||||||
Automation1PsoWindowInput_XC6ePrimaryFeedback = 140,
|
|
||||||
Automation1PsoWindowInput_XC6eAuxiliaryFeedback = 141,
|
|
||||||
Automation1PsoWindowInput_XC6eSyncPortA = 142,
|
|
||||||
Automation1PsoWindowInput_XC6eSyncPortB = 143,
|
|
||||||
Automation1PsoWindowInput_XC6eDrivePulseStream = 144,
|
|
||||||
Automation1PsoWindowInput_XL5ePrimaryFeedback = 145,
|
|
||||||
Automation1PsoWindowInput_XL5eAuxiliaryFeedback = 146,
|
|
||||||
Automation1PsoWindowInput_XL5eSyncPortA = 147,
|
|
||||||
Automation1PsoWindowInput_XL5eSyncPortB = 148,
|
|
||||||
Automation1PsoWindowInput_XL5eDrivePulseStream = 149,
|
|
||||||
Automation1PsoWindowInput_XC2PrimaryFeedback = 150,
|
|
||||||
Automation1PsoWindowInput_XC2AuxiliaryFeedback = 151,
|
|
||||||
Automation1PsoWindowInput_XC2DrivePulseStream = 152,
|
|
||||||
Automation1PsoWindowInput_XC2ePrimaryFeedback = 153,
|
|
||||||
Automation1PsoWindowInput_XC2eAuxiliaryFeedback = 154,
|
|
||||||
Automation1PsoWindowInput_XC2eDrivePulseStream = 155,
|
|
||||||
Automation1PsoWindowInput_XL2ePrimaryFeedback = 156,
|
|
||||||
Automation1PsoWindowInput_XL2eAuxiliaryFeedback = 157,
|
|
||||||
Automation1PsoWindowInput_XL2eSyncPortA = 158,
|
|
||||||
Automation1PsoWindowInput_XL2eSyncPortB = 159,
|
|
||||||
Automation1PsoWindowInput_XL2eDrivePulseStream = 160,
|
|
||||||
Automation1PsoWindowInput_XI4PrimaryFeedbackAxis1 = 161,
|
|
||||||
Automation1PsoWindowInput_XI4PrimaryFeedbackAxis2 = 162,
|
|
||||||
Automation1PsoWindowInput_XI4PrimaryFeedbackAxis3 = 163,
|
|
||||||
Automation1PsoWindowInput_XI4PrimaryFeedbackAxis4 = 164,
|
|
||||||
Automation1PsoWindowInput_XI4AuxiliaryFeedback1 = 165,
|
|
||||||
Automation1PsoWindowInput_XI4AuxiliaryFeedback2 = 166,
|
|
||||||
Automation1PsoWindowInput_XI4AuxiliaryFeedback3 = 167,
|
|
||||||
Automation1PsoWindowInput_XI4AuxiliaryFeedback4 = 168,
|
|
||||||
Automation1PsoWindowInput_XI4SyncPortA = 169,
|
|
||||||
Automation1PsoWindowInput_XI4SyncPortB = 170,
|
|
||||||
Automation1PsoWindowInput_XI4DrivePulseStreamAxis1 = 171,
|
|
||||||
Automation1PsoWindowInput_XI4DrivePulseStreamAxis2 = 172,
|
|
||||||
Automation1PsoWindowInput_XI4DrivePulseStreamAxis3 = 173,
|
|
||||||
Automation1PsoWindowInput_XI4DrivePulseStreamAxis4 = 174,
|
|
||||||
Automation1PsoWindowInput_iXC4PrimaryFeedback = 175,
|
|
||||||
Automation1PsoWindowInput_iXC4AuxiliaryFeedback = 176,
|
|
||||||
Automation1PsoWindowInput_iXC4SyncPortA = 177,
|
|
||||||
Automation1PsoWindowInput_iXC4SyncPortB = 178,
|
|
||||||
Automation1PsoWindowInput_iXC4DrivePulseStream = 179,
|
|
||||||
Automation1PsoWindowInput_iXC4ePrimaryFeedback = 180,
|
|
||||||
Automation1PsoWindowInput_iXC4eAuxiliaryFeedback = 181,
|
|
||||||
Automation1PsoWindowInput_iXC4eSyncPortA = 182,
|
|
||||||
Automation1PsoWindowInput_iXC4eSyncPortB = 183,
|
|
||||||
Automation1PsoWindowInput_iXC4eDrivePulseStream = 184,
|
|
||||||
Automation1PsoWindowInput_iXC6ePrimaryFeedback = 185,
|
|
||||||
Automation1PsoWindowInput_iXC6eAuxiliaryFeedback = 186,
|
|
||||||
Automation1PsoWindowInput_iXC6eSyncPortA = 187,
|
|
||||||
Automation1PsoWindowInput_iXC6eSyncPortB = 188,
|
|
||||||
Automation1PsoWindowInput_iXC6eDrivePulseStream = 189,
|
|
||||||
Automation1PsoWindowInput_iXL5ePrimaryFeedback = 190,
|
|
||||||
Automation1PsoWindowInput_iXL5eAuxiliaryFeedback = 191,
|
|
||||||
Automation1PsoWindowInput_iXL5eSyncPortA = 192,
|
|
||||||
Automation1PsoWindowInput_iXL5eSyncPortB = 193,
|
|
||||||
Automation1PsoWindowInput_iXL5eDrivePulseStream = 194,
|
|
||||||
Automation1PsoWindowInput_iXR3PrimaryFeedbackAxis1 = 195,
|
|
||||||
Automation1PsoWindowInput_iXR3PrimaryFeedbackAxis2 = 196,
|
|
||||||
Automation1PsoWindowInput_iXR3PrimaryFeedbackAxis3 = 197,
|
|
||||||
Automation1PsoWindowInput_iXR3PrimaryFeedbackAxis4 = 198,
|
|
||||||
Automation1PsoWindowInput_iXR3PrimaryFeedbackAxis5 = 199,
|
|
||||||
Automation1PsoWindowInput_iXR3PrimaryFeedbackAxis6 = 200,
|
|
||||||
Automation1PsoWindowInput_iXR3AuxiliaryFeedbackAxis1 = 201,
|
|
||||||
Automation1PsoWindowInput_iXR3AuxiliaryFeedbackAxis2 = 202,
|
|
||||||
Automation1PsoWindowInput_iXR3AuxiliaryFeedbackAxis3 = 203,
|
|
||||||
Automation1PsoWindowInput_iXR3AuxiliaryFeedbackAxis4 = 204,
|
|
||||||
Automation1PsoWindowInput_iXR3AuxiliaryFeedbackAxis5 = 205,
|
|
||||||
Automation1PsoWindowInput_iXR3AuxiliaryFeedbackAxis6 = 206,
|
|
||||||
Automation1PsoWindowInput_iXR3SyncPortA = 207,
|
|
||||||
Automation1PsoWindowInput_iXR3SyncPortB = 208,
|
|
||||||
Automation1PsoWindowInput_iXR3DrivePulseStream = 209,
|
|
||||||
Automation1PsoWindowInput_GI4DrivePulseStreamAxis1 = 210,
|
|
||||||
Automation1PsoWindowInput_GI4DrivePulseStreamAxis2 = 211,
|
|
||||||
Automation1PsoWindowInput_GI4DrivePulseStreamAxis3 = 212,
|
|
||||||
Automation1PsoWindowInput_iXC2PrimaryFeedback = 213,
|
|
||||||
Automation1PsoWindowInput_iXC2AuxiliaryFeedback = 214,
|
|
||||||
Automation1PsoWindowInput_iXC2DrivePulseStream = 215,
|
|
||||||
Automation1PsoWindowInput_iXC2ePrimaryFeedback = 216,
|
|
||||||
Automation1PsoWindowInput_iXC2eAuxiliaryFeedback = 217,
|
|
||||||
Automation1PsoWindowInput_iXC2eDrivePulseStream = 218,
|
|
||||||
Automation1PsoWindowInput_iXL2ePrimaryFeedback = 219,
|
|
||||||
Automation1PsoWindowInput_iXL2eAuxiliaryFeedback = 220,
|
|
||||||
Automation1PsoWindowInput_iXL2eSyncPortA = 221,
|
|
||||||
Automation1PsoWindowInput_iXL2eSyncPortB = 222,
|
|
||||||
Automation1PsoWindowInput_iXL2eDrivePulseStream = 223,
|
|
||||||
Automation1PsoWindowInput_iXI4PrimaryFeedbackAxis1 = 224,
|
|
||||||
Automation1PsoWindowInput_iXI4PrimaryFeedbackAxis2 = 225,
|
|
||||||
Automation1PsoWindowInput_iXI4PrimaryFeedbackAxis3 = 226,
|
|
||||||
Automation1PsoWindowInput_iXI4PrimaryFeedbackAxis4 = 227,
|
|
||||||
Automation1PsoWindowInput_iXI4AuxiliaryFeedback1 = 228,
|
|
||||||
Automation1PsoWindowInput_iXI4AuxiliaryFeedback2 = 229,
|
|
||||||
Automation1PsoWindowInput_iXI4AuxiliaryFeedback3 = 230,
|
|
||||||
Automation1PsoWindowInput_iXI4AuxiliaryFeedback4 = 231,
|
|
||||||
Automation1PsoWindowInput_iXI4SyncPortA = 232,
|
|
||||||
Automation1PsoWindowInput_iXI4SyncPortB = 233,
|
|
||||||
Automation1PsoWindowInput_iXI4DrivePulseStreamAxis1 = 234,
|
|
||||||
Automation1PsoWindowInput_iXI4DrivePulseStreamAxis2 = 235,
|
|
||||||
Automation1PsoWindowInput_iXI4DrivePulseStreamAxis3 = 236,
|
|
||||||
Automation1PsoWindowInput_iXI4DrivePulseStreamAxis4 = 237,
|
|
||||||
|
|
||||||
# @brief Specifies the PSO output pin settings for each drive.
|
|
||||||
class Automation1PsoOutputPin:
|
|
||||||
Automation1PsoOutputPin_GL4None = 100,
|
|
||||||
Automation1PsoOutputPin_GL4LaserOutput0 = 101,
|
|
||||||
Automation1PsoOutputPin_XL4sNone = 102,
|
|
||||||
Automation1PsoOutputPin_XL4sLaserOutput0 = 103,
|
|
||||||
Automation1PsoOutputPin_XR3None = 104,
|
|
||||||
Automation1PsoOutputPin_XR3PsoOutput1 = 105,
|
|
||||||
Automation1PsoOutputPin_XR3PsoOutput2 = 106,
|
|
||||||
Automation1PsoOutputPin_XR3PsoOutput3 = 107,
|
|
||||||
Automation1PsoOutputPin_XC4DedicatedOutput = 108,
|
|
||||||
Automation1PsoOutputPin_XC4AuxiliaryMarkerDifferential = 109,
|
|
||||||
Automation1PsoOutputPin_XC4AuxiliaryMarkerSingleEnded = 110,
|
|
||||||
XC4eDedicatedOutput = 111,
|
|
||||||
XC4eAuxiliaryMarkerDifferential = 112,
|
|
||||||
XC4eAuxiliaryMarkerSingleEnded = 113,
|
|
||||||
Automation1PsoOutputPin_XC6eDedicatedOutput = 114,
|
|
||||||
Automation1PsoOutputPin_XC6eAuxiliaryMarkerDifferential = 115,
|
|
||||||
Automation1PsoOutputPin_XC6eAuxiliaryMarkerSingleEnded = 116,
|
|
||||||
Automation1PsoOutputPin_XL5eDedicatedOutput = 117,
|
|
||||||
Automation1PsoOutputPin_XL5eAuxiliaryMarkerDifferential = 118,
|
|
||||||
Automation1PsoOutputPin_XL5eAuxiliaryMarkerSingleEnded = 119,
|
|
||||||
Automation1PsoOutputPin_XC2DedicatedOutput = 120,
|
|
||||||
Automation1PsoOutputPin_XC2eDedicatedOutput = 121,
|
|
||||||
Automation1PsoOutputPin_XL2eDedicatedOutput = 122,
|
|
||||||
Automation1PsoOutputPin_XI4DedicatedOutput = 123,
|
|
||||||
Automation1PsoOutputPin_iXC4DedicatedOutput = 124,
|
|
||||||
Automation1PsoOutputPin_iXC4AuxiliaryMarkerDifferential = 125,
|
|
||||||
Automation1PsoOutputPin_iXC4AuxiliaryMarkerSingleEnded = 126,
|
|
||||||
Automation1PsoOutputPin_iXC4eDedicatedOutput = 127,
|
|
||||||
Automation1PsoOutputPin_iXC4eAuxiliaryMarkerDifferential = 128,
|
|
||||||
Automation1PsoOutputPin_iXC4eAuxiliaryMarkerSingleEnded = 129,
|
|
||||||
Automation1PsoOutputPin_iXC6eDedicatedOutput = 130,
|
|
||||||
Automation1PsoOutputPin_iXC6eAuxiliaryMarkerDifferential = 131,
|
|
||||||
Automation1PsoOutputPin_iXC6eAuxiliaryMarkerSingleEnded = 132,
|
|
||||||
Automation1PsoOutputPin_iXL5eDedicatedOutput = 133,
|
|
||||||
Automation1PsoOutputPin_iXL5eAuxiliaryMarkerDifferential = 134,
|
|
||||||
Automation1PsoOutputPin_iXL5eAuxiliaryMarkerSingleEnded = 135,
|
|
||||||
Automation1PsoOutputPin_iXR3None = 136,
|
|
||||||
Automation1PsoOutputPin_iXR3PsoOutput1 = 137,
|
|
||||||
Automation1PsoOutputPin_iXR3PsoOutput2 = 138,
|
|
||||||
Automation1PsoOutputPin_iXR3PsoOutput3 = 139,
|
|
||||||
Automation1PsoOutputPin_GI4None = 140,
|
|
||||||
Automation1PsoOutputPin_GI4LaserOutput0 = 141,
|
|
||||||
Automation1PsoOutputPin_iXC2eDedicatedOutput = 143,
|
|
||||||
Automation1PsoOutputPin_iXL2eDedicatedOutput = 144,
|
|
||||||
Automation1PsoOutputPin_iXI4DedicatedOutput = 145,
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class DriveDataCaptureInput:
|
|
||||||
PositionCommand = 0
|
|
||||||
PrimaryFeedback = 1
|
|
||||||
AuxiliaryFeedback = 2
|
|
||||||
AnalogInput0 = 3
|
|
||||||
AnalogInput1 = 4
|
|
||||||
AnalogInput2 = 5
|
|
||||||
AnalogInput3 = 6
|
|
||||||
|
|
||||||
|
|
||||||
class DriveDataCaptureTrigger:
|
|
||||||
PsoOutput = 0
|
|
||||||
PsoEvent = 1
|
|
||||||
HighSpeedInput0RisingEdge = 2
|
|
||||||
HighSpeedInput0FallingEdge = 3
|
|
||||||
HighSpeedInput1RisingEdge = 4
|
|
||||||
HighSpeedInput1FallingEdge = 5
|
|
||||||
AuxiliaryMarkerRisingEdge = 6
|
|
||||||
AuxiliaryMarkerFallingEdge = 7
|
|
||||||
|
|
||||||
|
|
||||||
class PsoOutputPin:
|
|
||||||
GL4None = (100,)
|
|
||||||
GL4LaserOutput0 = (101,)
|
|
||||||
XL4sNone = (102,)
|
|
||||||
XL4sLaserOutput0 = (103,)
|
|
||||||
XR3None = (104,)
|
|
||||||
XR3PsoOutput1 = (105,)
|
|
||||||
XR3PsoOutput2 = (106,)
|
|
||||||
XR3PsoOutput3 = (107,)
|
|
||||||
XC4DedicatedOutput = (108,)
|
|
||||||
XC4AuxiliaryMarkerDifferential = (109,)
|
|
||||||
XC4AuxiliaryMarkerSingleEnded = (110,)
|
|
||||||
XC4eDedicatedOutput = (111,)
|
|
||||||
XC4eAuxiliaryMarkerDifferential = (112,)
|
|
||||||
XC4eAuxiliaryMarkerSingleEnded = (113,)
|
|
||||||
XC6eDedicatedOutput = (114,)
|
|
||||||
XC6eAuxiliaryMarkerDifferential = (115,)
|
|
||||||
XC6eAuxiliaryMarkerSingleEnded = (116,)
|
|
||||||
XL5eDedicatedOutput = (117,)
|
|
||||||
XL5eAuxiliaryMarkerDifferential = (118,)
|
|
||||||
XL5eAuxiliaryMarkerSingleEnded = (119,)
|
|
||||||
XC2DedicatedOutput = (120,)
|
|
||||||
XC2eDedicatedOutput = (121,)
|
|
||||||
XL2eDedicatedOutput = (122,)
|
|
||||||
XI4DedicatedOutput = (123,)
|
|
||||||
iXC4DedicatedOutput = (124,)
|
|
||||||
iXC4AuxiliaryMarkerDifferential = (125,)
|
|
||||||
iXC4AuxiliaryMarkerSingleEnded = (126,)
|
|
||||||
iXC4eDedicatedOutput = (127,)
|
|
||||||
iXC4eAuxiliaryMarkerDifferential = (128,)
|
|
||||||
iXC4eAuxiliaryMarkerSingleEnded = (129,)
|
|
||||||
iXC6eDedicatedOutput = (130,)
|
|
||||||
iXC6eAuxiliaryMarkerDifferential = (131,)
|
|
||||||
iXC6eAuxiliaryMarkerSingleEnded = (132,)
|
|
||||||
iXL5eDedicatedOutput = (133,)
|
|
||||||
iXL5eAuxiliaryMarkerDifferential = (134,)
|
|
||||||
iXL5eAuxiliaryMarkerSingleEnded = (135,)
|
|
||||||
iXR3None = (136,)
|
|
||||||
iXR3PsoOutput1 = (137,)
|
|
||||||
iXR3PsoOutput2 = (138,)
|
|
||||||
iXR3PsoOutput3 = (139,)
|
|
||||||
GI4None = (140,)
|
|
||||||
GI4LaserOutput0 = (141,)
|
|
||||||
iXC2DedicatedOutput = (142,)
|
|
||||||
iXC2eDedicatedOutput = (143,)
|
|
||||||
iXL2eDedicatedOutput = (144,)
|
|
||||||
iXI4DedicatedOutput = (145,)
|
|
@ -1,140 +0,0 @@
|
|||||||
// Test program for simple zig-zag line scanning with PSO window output
|
|
||||||
// "enable" signal and DDC synchronized to external trigger input.
|
|
||||||
// The file expects external parameter validation
|
|
||||||
// The PSO locations arrays are set externally from EPICS PV
|
|
||||||
//
|
|
||||||
|
|
||||||
enum ScanType
|
|
||||||
Pos = 0
|
|
||||||
Neg = 1
|
|
||||||
PosNeg = 2
|
|
||||||
NegPos = 3
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
program
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// External parameters - USE THEESE
|
|
||||||
var $fStartPosition as real = {{ scan.startpos }}
|
|
||||||
var $fScanRange as real = $fStartPosition + {{ scan.scanrange }}
|
|
||||||
var $iNumRepeat as integer = {{ scan.nrepeat }}
|
|
||||||
var $eScanType as ScanType = ScanType.{{ scan.scandir or 'Pos' }}
|
|
||||||
var $iNumDdcRead as integer = {{ scan.npoints }}
|
|
||||||
|
|
||||||
|
|
||||||
var $fVelJog as real = {{ scan.jogvel or 200 }}
|
|
||||||
var $fVelScan as real = {{ scan.scanvel }}
|
|
||||||
var $fAcceleration = {{ scan.scanacc or 500 }}
|
|
||||||
var $fSafeDist = 10.0
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Internal parameters - dont use
|
|
||||||
var $axis as axis = ROTY
|
|
||||||
var $ii as integer
|
|
||||||
var $iDdcSafeSpace as integer = 4096
|
|
||||||
|
|
||||||
// Set acceleration
|
|
||||||
SetupAxisRampType($axis, RampType.Linear)
|
|
||||||
SetupAxisRampValue($axis,0,$fAcceleration)
|
|
||||||
var $fAccDistance as real = 0.5 * $fVelScan * $fVelScan / $fAcceleration + $fSafeDist
|
|
||||||
|
|
||||||
// set the actual scan range
|
|
||||||
var $fPosStart as real
|
|
||||||
var $fPosEnd as real
|
|
||||||
if $eScanType == ScanType.Pos
|
|
||||||
$fPosStart = $fStartPosition - $fAccDistance
|
|
||||||
$fPosEnd = $fStartPosition + $fScanRange + $fAccDistance
|
|
||||||
elseif $eScanType == ScanType.Neg
|
|
||||||
$fPosStart = $fStartPosition + $fAccDistance
|
|
||||||
$fPosEnd = $fStartPosition - $fScanRange - $fAccDistance
|
|
||||||
elseif $eScanType == ScanType.PosNeg
|
|
||||||
$fPosStart = $fStartPosition - $fAccDistance
|
|
||||||
$fPosEnd = $fStartPosition + $fScanRange + $fAccDistance
|
|
||||||
elseif $eScanType == ScanType.NegPos
|
|
||||||
$fPosStart = $fStartPosition + $fAccDistance
|
|
||||||
$fPosEnd = $fStartPosition - $fScanRange - $fAccDistance
|
|
||||||
end
|
|
||||||
|
|
||||||
// Move to start position before the scan
|
|
||||||
MoveAbsolute($axis, $fPosStart, $fVelJog)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
|
|
||||||
// Configure PSO
|
|
||||||
PsoDistanceCounterOff($axis)
|
|
||||||
PsoDistanceEventsOff($axis)
|
|
||||||
PsoWindowConfigureEvents($axis, PsoWindowEventMode.None)
|
|
||||||
PsoWaveformOff($axis)
|
|
||||||
PsoOutputConfigureSource($axis, PsoOutputSource.Waveform)
|
|
||||||
var $iPsoArrayAddr as integer = 0
|
|
||||||
// Simple PSO trigger pattern
|
|
||||||
var $iPsoArrayPos[] as real = [{% for psoDist in scan.psoBoundsPos[:-1] %} UnitsToCounts($axis, {{ psoDist }}), {% endfor %} UnitsToCounts($axis, {{ scan.psoBoundsPos[-1] }})]
|
|
||||||
// var $iPsoArrayPos[] as real = [UnitsToCounts($axis, $fAccDistance), {% for psoDist in scan.psoBoundsPos[:-1] %} UnitsToCounts($axis, psoDist), {% endfor %}]
|
|
||||||
// var $iPsoArrayNeg[] as real = [UnitsToCounts($axis, $fAccDistance), {% for psoDist in scan.psoBoundsNeg[:-1] %} UnitsToCounts($axis, psoDist), {% endfor %}]
|
|
||||||
|
|
||||||
DriveArrayWrite($axis, $iPsoArrayPos, $iPsoArrayAddr, length($iPsoArrayPos), DriveArrayType.PsoDistanceEventDistances)
|
|
||||||
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayAddr, length($iPsoArrayPos), 0)
|
|
||||||
PsoDistanceEventsOn($axis)
|
|
||||||
|
|
||||||
PsoWaveformConfigureMode($axis, PsoWaveformMode.Toggle)
|
|
||||||
PsoWaveformOn($axis)
|
|
||||||
|
|
||||||
// Configure Drive Data Collection
|
|
||||||
var $iDdcArrayAddr as integer = 8388608
|
|
||||||
var $iDdcArraySize as integer = $iNumDdcRead
|
|
||||||
|
|
||||||
DriveDataCaptureConfigureInput($axis, 0, DriveDataCaptureInput.PrimaryFeedback);
|
|
||||||
DriveDataCaptureConfigureInput($axis, 1, DriveDataCaptureInput.AnalogInput0 );
|
|
||||||
|
|
||||||
DriveDataCaptureConfigureTrigger($axis, 0, DriveDataCaptureTrigger.PsoOutput );
|
|
||||||
DriveDataCaptureConfigureTrigger($axis, 1, DriveDataCaptureTrigger.PsoOutput );
|
|
||||||
|
|
||||||
DriveDataCaptureConfigureArray($axis, 0, $iDdcArrayAddr, $iDdcArraySize);
|
|
||||||
DriveDataCaptureConfigureArray($axis, 1, $iDdcArrayAddr + $iDdcSafeSpace + 8 * $iDdcArraySize, $iDdcArraySize);
|
|
||||||
|
|
||||||
// Directly before scan
|
|
||||||
PsoDistanceCounterOn($axis)
|
|
||||||
DriveDataCaptureOn($axis, 0)
|
|
||||||
DriveDataCaptureOn($axis, 1)
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// Start the actual scanning
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
for $ii = 0 to ($iNumRepeat-1)
|
|
||||||
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayAddr, length($iPsoArrayPos), 0)
|
|
||||||
|
|
||||||
if $eScanType == ScanType.Pos
|
|
||||||
MoveAbsolute($axis, $fPosEnd, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
MoveAbsolute($axis, $fPosStart, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
elseif $eScanType == ScanType.Neg
|
|
||||||
MoveAbsolute($axis, $fPosEnd, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
MoveAbsolute($axis, $fPosStart, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
elseif $eScanType == ScanType.PosNeg
|
|
||||||
if ($ii % 2) == 0
|
|
||||||
MoveAbsolute($axis, $fPosEnd, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
elseif ($ii % 2) == 1
|
|
||||||
MoveAbsolute($axis, $fPosStart, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
end
|
|
||||||
elseif $eScanType == ScanType.NegPos
|
|
||||||
if ($ii % 2) == 0
|
|
||||||
MoveAbsolute($axis, $fPosEnd, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
elseif ($ii % 2) == 1
|
|
||||||
MoveAbsolute($axis, $fPosStart, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Dwell(0.2)
|
|
||||||
end
|
|
||||||
|
|
||||||
// Directly after scan
|
|
||||||
PsoDistanceCounterOff($axis)
|
|
||||||
DriveDataCaptureOff($axis, 0)
|
|
||||||
DriveDataCaptureOff($axis, 1)
|
|
||||||
end
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
|||||||
// Snap-and-step
|
|
||||||
// Test program for high speed step scanning with individual triggers on PSO output.
|
|
||||||
// The file expects external parameter validation.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
program
|
|
||||||
// External parameters
|
|
||||||
var $fStartPosition as real = {{ scan.startpos }}
|
|
||||||
var $iNumSteps as integer = {{ scan.numsteps }}
|
|
||||||
var $fStepSize as real = {{ scan.stepsize }}
|
|
||||||
var $fExposureTimeSec as real = {{ scan.exptime }}
|
|
||||||
var $fVelJog as real = {{ scan.travel or 200 }}
|
|
||||||
var $fVelScan as real = {{ scan.velocity or 50 }}
|
|
||||||
var $fAcceleration = {{ scan.acceleration or 500 }}
|
|
||||||
|
|
||||||
// Internal
|
|
||||||
var $axis as axis = ROTY
|
|
||||||
var $ii as integer
|
|
||||||
|
|
||||||
// Set acceleration
|
|
||||||
SetupAxisRampType($axis, RampType.Linear)
|
|
||||||
SetupAxisRampValue($axis,0,$fAcceleration)
|
|
||||||
|
|
||||||
// Move to start position before the scan
|
|
||||||
var $fPosNext as real = $fStartPosition
|
|
||||||
MoveAbsolute($axis, $fPosNext, $fVelJog)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
|
|
||||||
// Configure PSO (to manual event generation)
|
|
||||||
PsoDistanceEventsOff($axis)
|
|
||||||
PsoWindowConfigureEvents($axis, PsoWindowEventMode.None)
|
|
||||||
PsoWaveformConfigurePulseFixedTotalTime($axis, 50)
|
|
||||||
PsoWaveformConfigurePulseFixedOnTime($axis, 20)
|
|
||||||
PsoWaveformConfigurePulseFixedCount($axis, 1)
|
|
||||||
PsoWaveformApplyPulseConfiguration($axis)
|
|
||||||
PsoWaveformConfigureMode($axis, PsoWaveformMode.Pulse)
|
|
||||||
PsoOutputConfigureSource($axis, PsoOutputSource.Waveform)
|
|
||||||
PsoWaveformOn($axis)
|
|
||||||
|
|
||||||
// Configure Drive Data Collection
|
|
||||||
var $iDdcArrayAddr as integer = 8388608
|
|
||||||
var $iDdcArraySize as integer = iMaximum(5000, $iNumSteps)
|
|
||||||
var $iDdcSafeSpace as integer = 4096
|
|
||||||
|
|
||||||
DriveDataCaptureConfigureInput($axis, 0, DriveDataCaptureInput.PrimaryFeedback);
|
|
||||||
DriveDataCaptureConfigureInput($axis, 1, DriveDataCaptureInput.AnalogInput0 );
|
|
||||||
|
|
||||||
DriveDataCaptureConfigureTrigger($axis, 0, DriveDataCaptureTrigger.PsoOutput );
|
|
||||||
DriveDataCaptureConfigureTrigger($axis, 1, DriveDataCaptureTrigger.PsoOutput );
|
|
||||||
|
|
||||||
DriveDataCaptureConfigureArray($axis, 0, $iDdcArrayAddr, $iDdcArraySize);
|
|
||||||
DriveDataCaptureConfigureArray($axis, 1, $iDdcArrayAddr + $iDdcSafeSpace + 8 * $iDdcArraySize, $iDdcArraySize);
|
|
||||||
|
|
||||||
// Directly before scan
|
|
||||||
PsoDistanceCounterOn($axis)
|
|
||||||
DriveDataCaptureOn($axis, 0)
|
|
||||||
DriveDataCaptureOn($axis, 1)
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
// Start the actual scanning
|
|
||||||
///////////////////////////////////////////////////////////
|
|
||||||
for $ii = 0 to ($iNumSteps-1)
|
|
||||||
MoveAbsolute($axis, $fPosNext, $fVelScan)
|
|
||||||
WaitForInPosition($axis)
|
|
||||||
PsoEventGenerateSingle($axis)
|
|
||||||
Dwell($fExposureTimeSec)
|
|
||||||
$fPosNext = $fPosNext + $fStepSize
|
|
||||||
end
|
|
||||||
|
|
||||||
// Directly after scan
|
|
||||||
PsoWaveformOff($axis)
|
|
||||||
DriveDataCaptureOff($axis, 0)
|
|
||||||
DriveDataCaptureOff($axis, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
// Demonstrates using a switch/case conditional.
|
|
||||||
function iMaximum($A as integer, $B as integer) as integer
|
|
||||||
var $retVal
|
|
||||||
if ($A > $B)
|
|
||||||
$retVal = $A
|
|
||||||
else
|
|
||||||
$retVal = $B
|
|
||||||
end
|
|
||||||
return $retVal
|
|
||||||
end
|
|
||||||
|
|
@ -1,434 +0,0 @@
|
|||||||
import enum
|
|
||||||
import os
|
|
||||||
import threading
|
|
||||||
import time as ttime
|
|
||||||
|
|
||||||
from bec_lib.logger import bec_logger
|
|
||||||
|
|
||||||
# from typing import Any
|
|
||||||
from ophyd import ADComponent as ADCpt
|
|
||||||
from ophyd import Component as Cpt
|
|
||||||
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
|
|
||||||
|
|
||||||
# import numpy as np
|
|
||||||
from ophyd.ophydobj import Kind
|
|
||||||
|
|
||||||
from ophyd_devices.epics.devices.psi_detector_base import CustomDetectorMixin, PSIDetectorBase
|
|
||||||
|
|
||||||
# os.environ["EPICS_CA_AUTO_ADDR_LIST"] = "No"
|
|
||||||
# os.environ["EPICS_CA_ADDR_LIST"] = "129.129.208.143"
|
|
||||||
|
|
||||||
|
|
||||||
logger = bec_logger.logger
|
|
||||||
|
|
||||||
|
|
||||||
class GrashopperError(Exception):
|
|
||||||
"""Base class for Grashopper detector errors."""
|
|
||||||
|
|
||||||
|
|
||||||
class GrashopperTimeoutError(GrashopperError):
|
|
||||||
"""Base class for Grashopper detector errors."""
|
|
||||||
|
|
||||||
|
|
||||||
class AutoMode(enum.IntEnum):
|
|
||||||
"""Acquire time auto for Grashopper detector.
|
|
||||||
|
|
||||||
class for acquire_auto and gain_auto
|
|
||||||
|
|
||||||
Off: Gain tap balancing is user controlled using Gain.
|
|
||||||
Once: Gain tap balancing is automatically adjusted once by the device.
|
|
||||||
Once it has converged, it automatically returns to the Off state.
|
|
||||||
Continuous: Gain tap balancing is constantly adjusted by the device.
|
|
||||||
"""
|
|
||||||
|
|
||||||
OFF = 0
|
|
||||||
ONCE = 1
|
|
||||||
CONTINUOUS = 2
|
|
||||||
|
|
||||||
|
|
||||||
class ImageMode(enum.IntEnum):
|
|
||||||
"""Image mode for Grashopper detector.
|
|
||||||
|
|
||||||
Single: Acquire a single image, ignores NumImages PV
|
|
||||||
Multiple: Acquire NumImages images
|
|
||||||
Continuous: Acquire images continuously
|
|
||||||
"""
|
|
||||||
|
|
||||||
SINGLE = 0
|
|
||||||
MULTIPLE = 1
|
|
||||||
CONTINUOUS = 2
|
|
||||||
|
|
||||||
|
|
||||||
class DetectorState(enum.IntEnum):
|
|
||||||
"""Detector states for Grashopper detector"""
|
|
||||||
|
|
||||||
IDLE = 0
|
|
||||||
ACQUIRE = 1
|
|
||||||
READOUT = 2
|
|
||||||
CORRECT = 3
|
|
||||||
SAVING = 4
|
|
||||||
ABORTING = 5
|
|
||||||
ERROR = 6
|
|
||||||
WAITING = 7
|
|
||||||
INITIALIZING = 8
|
|
||||||
DISCONNECTED = 9
|
|
||||||
ABORTED = 10
|
|
||||||
|
|
||||||
|
|
||||||
class ImageBinning(enum.IntEnum):
|
|
||||||
"""Image binning for Grashopper detector"""
|
|
||||||
|
|
||||||
X1 = 1
|
|
||||||
X2 = 2
|
|
||||||
X4 = 4
|
|
||||||
|
|
||||||
|
|
||||||
class VideoMode(enum.IntEnum):
|
|
||||||
"""Video mode for Grashopper detector.
|
|
||||||
|
|
||||||
For details, consult EPICs IOC manual.
|
|
||||||
"""
|
|
||||||
|
|
||||||
MODE0 = 0
|
|
||||||
MODE1 = 1
|
|
||||||
MODE2 = 2
|
|
||||||
MODE3 = 3
|
|
||||||
|
|
||||||
|
|
||||||
class PixelFormat(enum.IntEnum):
|
|
||||||
"""Pixel format for Grashopper detector."""
|
|
||||||
|
|
||||||
MONO8 = 0
|
|
||||||
MONO12PACKED = 1
|
|
||||||
MONO12P = 2
|
|
||||||
MONO16 = 3
|
|
||||||
|
|
||||||
|
|
||||||
class COLORMODE(enum.IntEnum):
|
|
||||||
"""Color mode for Grashopper detector.
|
|
||||||
|
|
||||||
Only for readback values from color_mode RO PV.
|
|
||||||
"""
|
|
||||||
|
|
||||||
MONO = 0
|
|
||||||
BAYER = 1
|
|
||||||
RGB1 = 2
|
|
||||||
RGB2 = 3
|
|
||||||
RGB3 = 4
|
|
||||||
YUV444 = 5
|
|
||||||
YUV422 = 6
|
|
||||||
YUV421 = 7
|
|
||||||
|
|
||||||
|
|
||||||
class TriggerSource(enum.IntEnum):
|
|
||||||
"""Trigger signals for Grashopper detector"""
|
|
||||||
|
|
||||||
SOFTWARE = 0
|
|
||||||
LINE0 = 1
|
|
||||||
LINE2 = 2
|
|
||||||
LINE3 = 3
|
|
||||||
|
|
||||||
|
|
||||||
class MemoryPolling(enum.IntEnum):
|
|
||||||
"""Memory polling for Grashopper detector.
|
|
||||||
|
|
||||||
Defines update rate of memory polling for IOC (1s suggested).
|
|
||||||
"""
|
|
||||||
|
|
||||||
PASSIVE = 0
|
|
||||||
EVENT = 1
|
|
||||||
IOINTR = 2
|
|
||||||
SECONDS10 = 3
|
|
||||||
SECONDS5 = 4
|
|
||||||
SECONDS2 = 5
|
|
||||||
SECONDS1 = 6
|
|
||||||
SECONDS05 = 7
|
|
||||||
SECONDS02 = 8
|
|
||||||
SECONDS01 = 9
|
|
||||||
|
|
||||||
|
|
||||||
class GrashopperTOMCATSetup(CustomDetectorMixin):
|
|
||||||
"""Mixin class to setup TOMCAT specific implementations of the detector.
|
|
||||||
|
|
||||||
This class will be called by the custom_prepare_cls attribute of the detector class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *_args, parent: Device = None, **_kwargs) -> None:
|
|
||||||
super().__init__(*_args, parent=parent, **_kwargs)
|
|
||||||
|
|
||||||
self.image_shape = (self.parent.cam.image_size_y.get(), self.parent.cam.image_size_x.get())
|
|
||||||
self.monitor_thread = None
|
|
||||||
self.stop_monitor = False
|
|
||||||
self.update_frequency = 1
|
|
||||||
self.low_frame_rate = 80
|
|
||||||
|
|
||||||
def initialize_detector(self) -> None:
|
|
||||||
"""Initialize detector."""
|
|
||||||
self.parent.cam.acquire.put(0)
|
|
||||||
self.parent.cam.acquire_time_auto.put(AutoMode.CONTINUOUS)
|
|
||||||
self.parent.cam.gain_auto.put(AutoMode.CONTINUOUS)
|
|
||||||
self.parent.cam.image_mode.put(ImageMode.MULTIPLE)
|
|
||||||
self.parent.cam.image_binning.put(ImageBinning.X1)
|
|
||||||
self.parent.cam.video_mode.put(VideoMode.MODE0)
|
|
||||||
self.parent.cam.pixel_format.put(PixelFormat.MONO16)
|
|
||||||
self.parent.cam.trigger_source.put(TriggerSource.SOFTWARE)
|
|
||||||
self.parent.cam.memory_polling.put(MemoryPolling.SECONDS1)
|
|
||||||
self.parent.cam.set_image_counter.put(0)
|
|
||||||
|
|
||||||
def initialize_detector_backend(self) -> None:
|
|
||||||
self.parent.image.queue_size.put(5)
|
|
||||||
self.parent.image.array_port.put(self.parent.cam.port_name.get())
|
|
||||||
self.parent.image.enable_cb.put(1)
|
|
||||||
self.parent.image.set_array_counter.put(0)
|
|
||||||
|
|
||||||
def set_exposure_time(self, exposure_time: float) -> None:
|
|
||||||
"""Set the detector framerate.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
framerate (float): Desired framerate in Hz smallest is 87Hz
|
|
||||||
"""
|
|
||||||
framerate = 1 / exposure_time
|
|
||||||
if framerate > self.low_frame_rate:
|
|
||||||
raise GrashopperError(
|
|
||||||
f"Trying to set exposure time to {exposure_time}s, this is below the lowest"
|
|
||||||
f" possible exposure of {1/self.low_frame_rate}s"
|
|
||||||
)
|
|
||||||
self.parent.cam.frame_rate.put(framerate)
|
|
||||||
|
|
||||||
def prepare_detector(self) -> None:
|
|
||||||
"""Prepare detector for acquisition."""
|
|
||||||
self.parent.cam.image_mode.put(ImageMode.MULTIPLE)
|
|
||||||
self.parent.cam.acquire_time_auto.put(AutoMode.CONTINUOUS)
|
|
||||||
self.set_exposure_time(self.parent.scaninfo.exp_time)
|
|
||||||
self.parent.set_trigger(TriggerSource.SOFTWARE)
|
|
||||||
self.parent.cam.set_image_counter.put(0)
|
|
||||||
self.set_acquisition_params()
|
|
||||||
|
|
||||||
def set_acquisition_params(self) -> None:
|
|
||||||
"""Set acquisition parameters for the detector"""
|
|
||||||
|
|
||||||
# Set number of images and frames (frames is for internal burst of detector)
|
|
||||||
self.parent.cam.num_images.put(
|
|
||||||
int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger)
|
|
||||||
)
|
|
||||||
|
|
||||||
def prepare_detector_backend(self) -> None:
|
|
||||||
"""Prepare detector backend for acquisition."""
|
|
||||||
self.parent.image.set_array_counter.put(0)
|
|
||||||
self.monitor_thread = None
|
|
||||||
self.stop_monitor = False
|
|
||||||
# self.run_monitor()
|
|
||||||
|
|
||||||
def arm_acquisition(self) -> None:
|
|
||||||
"""Arm grashopper detector for acquisition"""
|
|
||||||
self.parent.cam.acquire.put(1)
|
|
||||||
signal_conditions = [(self.parent.cam.detector_state.get, DetectorState.WAITING)]
|
|
||||||
if not self.wait_for_signals(
|
|
||||||
signal_conditions=signal_conditions,
|
|
||||||
timeout=self.parent.timeout,
|
|
||||||
check_stopped=True,
|
|
||||||
all_signals=False,
|
|
||||||
):
|
|
||||||
raise GrashopperTimeoutError(
|
|
||||||
f"Failed to arm the acquisition. Detector state {signal_conditions[0][0]}"
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_trigger(self) -> None:
|
|
||||||
"""Trigger the detector"""
|
|
||||||
if self.parent.cam.trigger_source.get() == TriggerSource.SOFTWARE:
|
|
||||||
self.parent.cam.software_trigger_device.put(1)
|
|
||||||
ttime.sleep(0.1)
|
|
||||||
self.send_data()
|
|
||||||
|
|
||||||
def run_monitor(self) -> None:
|
|
||||||
"""
|
|
||||||
Run the monitor loop in a separate thread.
|
|
||||||
"""
|
|
||||||
self.monitor_thread = threading.Thread(target=self.monitor_loop, daemon=True)
|
|
||||||
self.monitor_thread.start()
|
|
||||||
|
|
||||||
def monitor_loop(self) -> None:
|
|
||||||
"""
|
|
||||||
Monitor the detector status and send data.
|
|
||||||
"""
|
|
||||||
while True:
|
|
||||||
self.send_data()
|
|
||||||
ttime.sleep(1 / self.update_frequency)
|
|
||||||
if self.parent.stopped:
|
|
||||||
break
|
|
||||||
|
|
||||||
def send_data(self) -> None:
|
|
||||||
"""Send data to monitor endpoint in redis."""
|
|
||||||
try:
|
|
||||||
img = self.parent.image.array_data.get().reshape(self.image_shape)
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
self.parent._run_subs(sub_type=self.parent.SUB_VALUE, value=img)
|
|
||||||
except Exception as e:
|
|
||||||
logger.debug(f"{e} for image with shape {self.parent.image.array_data.get().shape}")
|
|
||||||
|
|
||||||
def stop_detector(self) -> None:
|
|
||||||
"""Stop detector."""
|
|
||||||
self.parent.cam.acquire.put(0)
|
|
||||||
signal_conditions = [(self.parent.cam.detector_state.get, DetectorState.IDLE)]
|
|
||||||
if not self.wait_for_signals(
|
|
||||||
signal_conditions=signal_conditions,
|
|
||||||
timeout=self.parent.timeout - self.parent.timeout // 2,
|
|
||||||
check_stopped=True,
|
|
||||||
all_signals=False,
|
|
||||||
):
|
|
||||||
# Retry stop detector and wait for remaining time
|
|
||||||
self.parent.cam.acquire.put(0)
|
|
||||||
if not self.wait_for_signals(
|
|
||||||
signal_conditions=signal_conditions,
|
|
||||||
timeout=self.parent.timeout - self.parent.timeout // 2,
|
|
||||||
check_stopped=True,
|
|
||||||
all_signals=False,
|
|
||||||
):
|
|
||||||
raise GrashopperTimeoutError(
|
|
||||||
f"Failed to stop detector, detector state {signal_conditions[0][0]}"
|
|
||||||
)
|
|
||||||
|
|
||||||
def stop_detector_backend(self) -> None:
|
|
||||||
"""Stop the data backend sending data."""
|
|
||||||
self.stop_monitor = True
|
|
||||||
|
|
||||||
|
|
||||||
class SLSDetectorCam(Device):
|
|
||||||
"""
|
|
||||||
SLS Detector Camera - Grashoppter
|
|
||||||
|
|
||||||
Base class to map EPICS PVs to ophyd signals.
|
|
||||||
"""
|
|
||||||
|
|
||||||
## Deprecated PVs, to be checked!
|
|
||||||
# acquire_time = ADCpt(EpicsSignal, "AcquireTime", kind=Kind.omitted)
|
|
||||||
# num_exposures = ADCpt(EpicsSignal, "NumExposures", kind=Kind.omitted)
|
|
||||||
# acquire_period = ADCpt(EpicsSignalWithRBV, "AcquirePeriod", kind=Kind.config)
|
|
||||||
|
|
||||||
# Control PVs
|
|
||||||
acquire_time_auto = ADCpt(EpicsSignal, "AcquireTimeAuto", kind=Kind.config)
|
|
||||||
|
|
||||||
frame_rate = ADCpt(EpicsSignalWithRBV, "FrameRate", kind=Kind.normal)
|
|
||||||
num_images = ADCpt(EpicsSignalWithRBV, "NumImages", kind=Kind.normal)
|
|
||||||
num_images_counter = ADCpt(EpicsSignalRO, "NumImagesCounter_RBV", kind=Kind.normal)
|
|
||||||
image_mode = ADCpt(EpicsSignalWithRBV, "ImageMode", kind=Kind.config)
|
|
||||||
acquire = ADCpt(EpicsSignalWithRBV, "Acquire", kind=Kind.config)
|
|
||||||
detector_state = ADCpt(EpicsSignalRO, "DetectorState_RBV", kind=Kind.normal)
|
|
||||||
status_message = ADCpt(EpicsSignalRO, "StatusMessage_RBV", string=True, kind=Kind.config)
|
|
||||||
|
|
||||||
set_image_counter = ADCpt(EpicsSignal, "ArrayCounter", kind=Kind.config)
|
|
||||||
image_counter = ADCpt(EpicsSignal, "ArrayCounter_RBV", kind=Kind.normal)
|
|
||||||
image_rate = ADCpt(EpicsSignalRO, "ArrayRate_RBV", kind=Kind.omitted)
|
|
||||||
|
|
||||||
# Asyn Port name
|
|
||||||
port_name = ADCpt(EpicsSignalRO, "PortName_RBV", string=True, kind=Kind.omitted)
|
|
||||||
|
|
||||||
# Readout related PVs
|
|
||||||
max_image_size_x = ADCpt(EpicsSignalRO, "MaxSizeX_RBV", kind=Kind.config)
|
|
||||||
max_image_size_y = ADCpt(EpicsSignalRO, "MaxSizeY_RBV", kind=Kind.config)
|
|
||||||
image_size_x = ADCpt(EpicsSignalRO, "ArraySizeX_RBV", kind=Kind.config)
|
|
||||||
image_size_y = ADCpt(EpicsSignalRO, "ArraySizeY_RBV", kind=Kind.config)
|
|
||||||
# Only BinY PV is working, sets both
|
|
||||||
image_binning = ADCpt(EpicsSignalWithRBV, "BinY", kind=Kind.config)
|
|
||||||
|
|
||||||
gain = ADCpt(EpicsSignalWithRBV, "Gain", kind=Kind.config)
|
|
||||||
gain_auto = ADCpt(EpicsSignalWithRBV, "GainAuto", kind=Kind.config)
|
|
||||||
video_mode = ADCpt(EpicsSignalWithRBV, "VideoMode", kind=Kind.config)
|
|
||||||
pixel_format = ADCpt(EpicsSignalWithRBV, "PixelFormat", kind=Kind.config)
|
|
||||||
# Desired to set this in future?
|
|
||||||
color_mode = ADCpt(EpicsSignalRO, "ColorMode_RBV", kind=Kind.config)
|
|
||||||
|
|
||||||
# HW Status PVs
|
|
||||||
temperature_actual = ADCpt(EpicsSignal, "TemperatureActual", kind=Kind.omitted)
|
|
||||||
|
|
||||||
# Trigger
|
|
||||||
trigger_mode_active = ADCpt(EpicsSignalWithRBV, "TriggerMode", kind=Kind.config)
|
|
||||||
trigger_source = ADCpt(EpicsSignalWithRBV, "TriggerSource", kind=Kind.config)
|
|
||||||
trigger_delay = ADCpt(EpicsSignalWithRBV, "TriggerDelay", kind=Kind.omitted)
|
|
||||||
exposure_mode = ADCpt(EpicsSignalWithRBV, "ExposureMode", kind=Kind.omitted)
|
|
||||||
software_trigger_device = ADCpt(EpicsSignal, "SoftwareTrigger", kind=Kind.config)
|
|
||||||
|
|
||||||
# buffer
|
|
||||||
memory_polling = ADCpt(EpicsSignal, "PoolUsedMem.SCAN", kind=Kind.omitted)
|
|
||||||
|
|
||||||
|
|
||||||
class SLSImagePlugin(Device):
|
|
||||||
"""SLS Image Plugin
|
|
||||||
|
|
||||||
Image plugin for SLS detector imitating the behaviour of ImagePlugin from
|
|
||||||
ophyd's areadetector plugins.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Control
|
|
||||||
array_port = Cpt(EpicsSignal, "NDArrayPort", kind=Kind.omitted, string=True)
|
|
||||||
enable_cb = Cpt(EpicsSignal, "EnableCallbacks", kind=Kind.config)
|
|
||||||
queue_size = Cpt(EpicsSignal, "QueueSize", kind=Kind.config)
|
|
||||||
set_array_counter = Cpt(EpicsSignal, "ArrayCounter", kind=Kind.config)
|
|
||||||
array_counter = Cpt(EpicsSignal, "ArrayCounter_RBV", kind=Kind.normal)
|
|
||||||
set_dropped_arrays = Cpt(EpicsSignal, "DroppedArrays", kind=Kind.config)
|
|
||||||
dropped_arrays = Cpt(EpicsSignal, "DroppedArrays_RBV", kind=Kind.normal)
|
|
||||||
image_id = Cpt(EpicsSignal, "UniqueId_RBV", kind=Kind.normal)
|
|
||||||
|
|
||||||
# Data
|
|
||||||
array_data = Cpt(EpicsSignal, "ArrayData", kind=Kind.omitted)
|
|
||||||
|
|
||||||
# Size related PVs from Plugin
|
|
||||||
array_size_0 = Cpt(EpicsSignalRO, "ArraySize0_RBV", kind=Kind.omitted)
|
|
||||||
array_size_1 = Cpt(EpicsSignalRO, "ArraySize1_RBV", kind=Kind.omitted)
|
|
||||||
array_size_2 = Cpt(EpicsSignalRO, "ArraySize2_RBV", kind=Kind.omitted)
|
|
||||||
array_dimension_size = Cpt(EpicsSignalRO, "NDimensions_RBV", kind=Kind.omitted)
|
|
||||||
|
|
||||||
|
|
||||||
class GrashopperTOMCAT(PSIDetectorBase):
|
|
||||||
"""
|
|
||||||
Grashopper detector for TOMCAT
|
|
||||||
|
|
||||||
Parent class: PSIDetectorBase
|
|
||||||
|
|
||||||
class attributes:
|
|
||||||
custom_prepare_cls (GrashopperTOMCATSetup) : Custom detector setup class for TOMCAT,
|
|
||||||
inherits from CustomDetectorMixin
|
|
||||||
cam (SLSDetectorCam) : Detector camera
|
|
||||||
image (SLSImagePlugin) : Image plugin for detector
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Specify which functions are revealed to the user in BEC client
|
|
||||||
USER_ACCESS = ["describe"]
|
|
||||||
|
|
||||||
SUB_MONITOR = "monitor"
|
|
||||||
SUB_VALUE = "value"
|
|
||||||
_default_sub = SUB_VALUE
|
|
||||||
|
|
||||||
# specify Setup class
|
|
||||||
custom_prepare_cls = GrashopperTOMCATSetup
|
|
||||||
# specify minimum readout time for detector
|
|
||||||
MIN_READOUT = 0
|
|
||||||
# specify class attributes
|
|
||||||
cam = ADCpt(SLSDetectorCam, "cam1:")
|
|
||||||
image = ADCpt(SLSImagePlugin, "image1:")
|
|
||||||
|
|
||||||
def stage(self) -> list[object]:
|
|
||||||
rtr = super().stage()
|
|
||||||
self.custom_prepare.arm_acquisition()
|
|
||||||
return rtr
|
|
||||||
|
|
||||||
def unstage(self) -> list[object]:
|
|
||||||
rtr = super().unstage()
|
|
||||||
self.custom_prepare.stop_monitor = True
|
|
||||||
return rtr
|
|
||||||
|
|
||||||
def set_trigger(self, trigger_source: TriggerSource) -> None:
|
|
||||||
"""Set trigger source for the detector.
|
|
||||||
Check the TriggerSource enum for possible values
|
|
||||||
|
|
||||||
Args:
|
|
||||||
trigger_source (TriggerSource): Trigger source for the detector
|
|
||||||
|
|
||||||
"""
|
|
||||||
value = trigger_source
|
|
||||||
self.cam.trigger_source.put(value)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
hopper = GrashopperTOMCAT(name="hopper", prefix="X02DA-PG-USB:", sim_mode=True)
|
|
||||||
hopper.wait_for_connection(all_signals=True)
|
|
@ -1,59 +0,0 @@
|
|||||||
""" TODO This class was never properly tested, it is solely a first draft and should be tested and extended before use! """
|
|
||||||
|
|
||||||
from ophyd import Component as Cpt
|
|
||||||
from ophyd import Device, EpicsSignal, EpicsSignalRO
|
|
||||||
|
|
||||||
|
|
||||||
class SequencerX12SA(Device):
|
|
||||||
"""Sequencer for flyscans with epics motor controller and owis stages"""
|
|
||||||
|
|
||||||
desired_output_link_1 = Cpt(Signal, "DOL1")
|
|
||||||
desired_output_value_1 = Cpt(EpicsSignal, "DO1")
|
|
||||||
output_link_1 = Cpt(EpicsSignal, "LNK1")
|
|
||||||
delay_time_1 = Cpt(EpicsSignal, "DLY1")
|
|
||||||
desired_output_link_2 = Cpt(EpicsSignal, "DOL2")
|
|
||||||
desired_output_value_2 = Cpt(EpicsSignal, "DO2")
|
|
||||||
output_link_2 = Cpt(EpicsSignal, "LNK2")
|
|
||||||
delay_time_2 = Cpt(EpicsSignal, "DLY2")
|
|
||||||
|
|
||||||
select_mechanism = Cpt(EpicsSignal, "SELM", string=True)
|
|
||||||
link_selection = Cpt(EpicsSignal, "SELN")
|
|
||||||
process = Cpt(EpicsSignal, "PROC", string=True)
|
|
||||||
|
|
||||||
status = Cpt(EpicsSignalRO, "STAT", string=True)
|
|
||||||
processing_active = Cpt(EpicsSignalRO, "PACT")
|
|
||||||
|
|
||||||
# def __init__(
|
|
||||||
# self,
|
|
||||||
# prefix="",
|
|
||||||
# *,
|
|
||||||
# name,
|
|
||||||
# kind=None,
|
|
||||||
# read_attrs=None,
|
|
||||||
# configuration_attrs=None,
|
|
||||||
# parent=None,
|
|
||||||
# **kwargs
|
|
||||||
# ):
|
|
||||||
# # get configuration attributes from kwargs and then remove them
|
|
||||||
# attrs = {}
|
|
||||||
# for key, value in kwargs.items():
|
|
||||||
# if hasattr(EpicsMotorEx, key) and isinstance(getattr(EpicsMotorEx, key), Cpt):
|
|
||||||
# attrs[key] = value
|
|
||||||
# for key in attrs:
|
|
||||||
# kwargs.pop(key)
|
|
||||||
|
|
||||||
# super().__init__(
|
|
||||||
# prefix,
|
|
||||||
# name=name,
|
|
||||||
# kind=kind,
|
|
||||||
# read_attrs=read_attrs,
|
|
||||||
# configuration_attrs=configuration_attrs,
|
|
||||||
# parent=parent,
|
|
||||||
# **kwargs
|
|
||||||
# )
|
|
||||||
|
|
||||||
# # set configuration attributes
|
|
||||||
# for key, value in attrs.items():
|
|
||||||
# # print out attributes that are being configured
|
|
||||||
# print("setting ", key, "=", value)
|
|
||||||
# getattr(self, key).put(value)
|
|
0
ophyd_devices/interfaces/base_classes/__init__.py
Normal file
0
ophyd_devices/interfaces/base_classes/__init__.py
Normal file
@ -5,7 +5,7 @@ from ophyd import Component as Cpt
|
|||||||
from ophyd import EpicsMotor
|
from ophyd import EpicsMotor
|
||||||
from typeguard import typechecked
|
from typeguard import typechecked
|
||||||
|
|
||||||
from ophyd_devices.ophyd_base_devices.bec_protocols import BECRotationProtocol
|
from ophyd_devices.interfaces.protocols.bec_protocols import BECRotationProtocol
|
||||||
from ophyd_devices.utils.bec_utils import ConfigSignal
|
from ophyd_devices.utils.bec_utils import ConfigSignal
|
||||||
|
|
||||||
logger = bec_logger.logger
|
logger = bec_logger.logger
|
0
ophyd_devices/interfaces/protocols/__init__.py
Normal file
0
ophyd_devices/interfaces/protocols/__init__.py
Normal file
@ -1,10 +0,0 @@
|
|||||||
from .bec_protocols import (
|
|
||||||
BECDeviceProtocol,
|
|
||||||
BECFlyerProtocol,
|
|
||||||
BECMixinProtocol,
|
|
||||||
BECPositionerProtocol,
|
|
||||||
BECRotationProtocol,
|
|
||||||
BECScanProtocol,
|
|
||||||
BECSignalProtocol,
|
|
||||||
)
|
|
||||||
from .tomcat_rotation_motors import TomcatAerotechRotation
|
|
@ -1,183 +0,0 @@
|
|||||||
""" Module for Tomcat rotation motors.
|
|
||||||
|
|
||||||
The following classes implement the rotation motors for:
|
|
||||||
|
|
||||||
- AerotechAutomation1 (Tomcat), based on EpicsMotorIOC.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from bec_lib import threadlocked
|
|
||||||
from ophyd import DeviceStatus
|
|
||||||
|
|
||||||
from ophyd_devices.ophyd_base_devices.bec_protocols import BECFlyerProtocol, BECScanProtocol
|
|
||||||
from ophyd_devices.ophyd_base_devices.ophyd_rotation_base import EpicsRotationBase
|
|
||||||
|
|
||||||
|
|
||||||
class TomcatAerotechRotation(EpicsRotationBase, BECFlyerProtocol, BECScanProtocol):
|
|
||||||
"""Special motor class that provides flyer interface and progress bar."""
|
|
||||||
|
|
||||||
SUB_PROGRESS = "progress"
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
prefix="",
|
|
||||||
*,
|
|
||||||
name,
|
|
||||||
kind=None,
|
|
||||||
read_attrs=None,
|
|
||||||
configuration_attrs=None,
|
|
||||||
parent=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
"""Implementation of the Tomcat AerotechAutomation 1 rotation motor class.
|
|
||||||
|
|
||||||
This motor class is based on EpicsRotationBase and provides in addition the flyer interface for BEC
|
|
||||||
and a progress update.
|
|
||||||
"""
|
|
||||||
super().__init__(
|
|
||||||
prefix=prefix,
|
|
||||||
name=name,
|
|
||||||
kind=kind,
|
|
||||||
read_attrs=read_attrs,
|
|
||||||
configuration_attrs=configuration_attrs,
|
|
||||||
parent=parent,
|
|
||||||
**kwargs,
|
|
||||||
)
|
|
||||||
self._start_position = None
|
|
||||||
self._target_position = None
|
|
||||||
self._stopped = False
|
|
||||||
self._rlock = threading.RLock()
|
|
||||||
self.subscribe(self._progress_update, run=False)
|
|
||||||
|
|
||||||
# ------------------ alternative to using configure method --------------------- #
|
|
||||||
@property
|
|
||||||
def start_position(self) -> float:
|
|
||||||
"""Get the start position."""
|
|
||||||
return self._start_position
|
|
||||||
|
|
||||||
@start_position.setter
|
|
||||||
def start_position(self, value: float) -> None:
|
|
||||||
"""Set the start position."""
|
|
||||||
self._start_position = value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def target_position(self) -> float:
|
|
||||||
"""Get the start position."""
|
|
||||||
return self._target_position
|
|
||||||
|
|
||||||
@target_position.setter
|
|
||||||
def target_position(self, value: float) -> None:
|
|
||||||
"""Set the start position."""
|
|
||||||
self._target_position = value
|
|
||||||
|
|
||||||
# ------------------ alternative to using configure method --------------------- #
|
|
||||||
# configure method is optional for flyers within BEC, you can use stage method or pre_scan method to
|
|
||||||
# set relevant parameters on the device.
|
|
||||||
|
|
||||||
# def configure(self, d: dict) -> dict:
|
|
||||||
# """Configure method from the device.
|
|
||||||
|
|
||||||
# This method is usually used to set configuration parameters for the device.
|
|
||||||
|
|
||||||
# Args:
|
|
||||||
# d (dict): Dictionary with configuration parameters.
|
|
||||||
|
|
||||||
# """
|
|
||||||
# if "target" in d:
|
|
||||||
# self._target_position = d["target"]
|
|
||||||
# del d["target"]
|
|
||||||
# if "position" in d:
|
|
||||||
# self._target_position = d["position"]
|
|
||||||
# del d["position"]
|
|
||||||
# return super().configure(d)
|
|
||||||
|
|
||||||
def pre_scan(self):
|
|
||||||
"""Perform pre-scan operation, e.g. move to start position."""
|
|
||||||
if self._start_position:
|
|
||||||
self.move(self._start_position, wait=True)
|
|
||||||
|
|
||||||
def kickoff(self) -> DeviceStatus:
|
|
||||||
"""Kickoff the scan.
|
|
||||||
|
|
||||||
The kickoff method should return a status object that is set to finish once the flyer flys, and is ready for the next actions.
|
|
||||||
I would consider the following implementation.
|
|
||||||
"""
|
|
||||||
self._start_position = float(self.position)
|
|
||||||
self.move(self._target_position, wait=False)
|
|
||||||
status = DeviceStatus(self)
|
|
||||||
status.set_finished()
|
|
||||||
return status
|
|
||||||
|
|
||||||
def complete(self) -> DeviceStatus:
|
|
||||||
"""Complete method of the scan.
|
|
||||||
|
|
||||||
This will be called in a fly scan after the kickoff, thus, the stage will be moving to it's target position.
|
|
||||||
It should
|
|
||||||
|
|
||||||
The complete method should return a status object that is set to finish once the flyer is done and the scan is complete.
|
|
||||||
I would consider the following implementation.
|
|
||||||
"""
|
|
||||||
threading.Thread(target=self._is_motor_moving, daemon=True).start()
|
|
||||||
status = DeviceStatus(self)
|
|
||||||
self.subscribe(status.set_finished, event_type=self.SUB_DONE, run=False)
|
|
||||||
return status
|
|
||||||
|
|
||||||
def stage(self) -> list[object]:
|
|
||||||
"""Stage the scan.
|
|
||||||
|
|
||||||
We add here in addition the setting of the _stopped flag to False for the thread.
|
|
||||||
"""
|
|
||||||
self._stopped = False
|
|
||||||
return super().stage()
|
|
||||||
|
|
||||||
def stop(self, success: bool = False) -> None:
|
|
||||||
"""Stop the scan.
|
|
||||||
|
|
||||||
If the device is stopped, the _stopped flag is set to True.
|
|
||||||
"""
|
|
||||||
self._stopped = True
|
|
||||||
super().stop(success=success)
|
|
||||||
|
|
||||||
@threadlocked
|
|
||||||
def _is_motor_moving(self):
|
|
||||||
"""Function to check if the motor is moving.
|
|
||||||
|
|
||||||
This function is used in a thread to check if the motor is moving.
|
|
||||||
It resolves by running"""
|
|
||||||
while self.motor_done_move.get():
|
|
||||||
if self._stopped:
|
|
||||||
self._done_moving(success=False)
|
|
||||||
return
|
|
||||||
time.sleep(0.1)
|
|
||||||
self._done_moving(success=True)
|
|
||||||
|
|
||||||
# TODO This logic could be refined to be more robust for various scan types, i.e. at the moment it just takes
|
|
||||||
# the start and target position and calculates the progress based on the current position.
|
|
||||||
def _progress_update(self, value, **kwargs) -> None:
|
|
||||||
"""Progress update on the scan.
|
|
||||||
|
|
||||||
Runs the progress update on the device progress during the scan.
|
|
||||||
It uses the SUB_PROGRESS event from ophyd to update BEC about the progress.
|
|
||||||
Scans need to be aware which device progress is relevant for the scan.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (float): The value of the motor position.
|
|
||||||
"""
|
|
||||||
if (self._start_position is None) or (self._target_position is None) or (not self.moving):
|
|
||||||
self._run_subs(sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1)
|
|
||||||
return
|
|
||||||
|
|
||||||
progress = np.abs(
|
|
||||||
(value - self._start_position) / (self._target_position - self._start_position)
|
|
||||||
)
|
|
||||||
max_value = 100
|
|
||||||
self._run_subs(
|
|
||||||
sub_type=self.SUB_PROGRESS,
|
|
||||||
value=int(100 * progress),
|
|
||||||
max_value=max_value,
|
|
||||||
done=int(np.isclose(max_value, progress, 1e-3)),
|
|
||||||
)
|
|
@ -1,51 +0,0 @@
|
|||||||
import inspect
|
|
||||||
|
|
||||||
import lmfit
|
|
||||||
|
|
||||||
|
|
||||||
class LmfitModelMixin:
|
|
||||||
|
|
||||||
# def __init__(self):
|
|
||||||
# self.model = lmfit.models.GaussianModel()
|
|
||||||
# self.params = self.model.make_params()
|
|
||||||
# self.params["center"].set(value=0)
|
|
||||||
# self.params["amplitude"].set(value=1)
|
|
||||||
# self.params["sigma"].set(value=1)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def available_models() -> dict:
|
|
||||||
"""
|
|
||||||
Get available models from lmfit.models.
|
|
||||||
|
|
||||||
Exclude Gaussian2dModel, ExpressionModel, Model, SplineModel.
|
|
||||||
"""
|
|
||||||
avail_models = {}
|
|
||||||
for name, model_cls in inspect.getmembers(lmfit.models):
|
|
||||||
try:
|
|
||||||
is_model = issubclass(model_cls, lmfit.model.Model)
|
|
||||||
except TypeError:
|
|
||||||
is_model = False
|
|
||||||
if is_model and name not in [
|
|
||||||
"Gaussian2dModel",
|
|
||||||
"ExpressionModel",
|
|
||||||
"Model",
|
|
||||||
"SplineModel",
|
|
||||||
]:
|
|
||||||
avail_models[name] = model_cls
|
|
||||||
return avail_models
|
|
||||||
|
|
||||||
def create_properties(self):
|
|
||||||
"""
|
|
||||||
Create properties for model parameters.
|
|
||||||
"""
|
|
||||||
for name in self.available_models():
|
|
||||||
setattr(self, name, param)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_model(model: str) -> lmfit.Model:
|
|
||||||
"""Get model for given string."""
|
|
||||||
if isinstance(model, str):
|
|
||||||
model = getattr(lmfit.models, model, None)
|
|
||||||
if not model:
|
|
||||||
raise ValueError(f"Model {model} not found.")
|
|
||||||
return model
|
|
@ -1,226 +0,0 @@
|
|||||||
# pylint: skip-file
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from ophyd_devices.epics.devices.grashopper_tomcat import (
|
|
||||||
COLORMODE,
|
|
||||||
AutoMode,
|
|
||||||
DetectorState,
|
|
||||||
GrashopperError,
|
|
||||||
GrashopperTimeoutError,
|
|
||||||
GrashopperTOMCATSetup,
|
|
||||||
ImageBinning,
|
|
||||||
ImageMode,
|
|
||||||
MemoryPolling,
|
|
||||||
PixelFormat,
|
|
||||||
TriggerSource,
|
|
||||||
VideoMode,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def patch_dual_pvs(device):
|
|
||||||
for walk in device.walk_signals():
|
|
||||||
if not hasattr(walk.item, "_read_pv"):
|
|
||||||
continue
|
|
||||||
if not hasattr(walk.item, "_write_pv"):
|
|
||||||
continue
|
|
||||||
if walk.item._read_pv.pvname.endswith("_RBV"):
|
|
||||||
walk.item._read_pv = walk.item._write_pv
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
|
||||||
def mock_GrashopperSetup():
|
|
||||||
mock_Grashopper = mock.MagicMock()
|
|
||||||
yield GrashopperTOMCATSetup(parent=mock_Grashopper)
|
|
||||||
|
|
||||||
|
|
||||||
# Fixture for scaninfo
|
|
||||||
@pytest.fixture(
|
|
||||||
params=[
|
|
||||||
{
|
|
||||||
"scan_id": "1234",
|
|
||||||
"scan_type": "step",
|
|
||||||
"num_points": 500,
|
|
||||||
"frames_per_trigger": 1,
|
|
||||||
"exp_time": 0.1,
|
|
||||||
"readout_time": 0.1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"scan_id": "1234",
|
|
||||||
"scan_type": "step",
|
|
||||||
"num_points": 500,
|
|
||||||
"frames_per_trigger": 5,
|
|
||||||
"exp_time": 0.01,
|
|
||||||
"readout_time": 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"scan_id": "1234",
|
|
||||||
"scan_type": "fly",
|
|
||||||
"num_points": 500,
|
|
||||||
"frames_per_trigger": 1,
|
|
||||||
"exp_time": 1,
|
|
||||||
"readout_time": 0.2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"scan_id": "1234",
|
|
||||||
"scan_type": "fly",
|
|
||||||
"num_points": 500,
|
|
||||||
"frames_per_trigger": 5,
|
|
||||||
"exp_time": 0.1,
|
|
||||||
"readout_time": 0.4,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
)
|
|
||||||
def scaninfo(request):
|
|
||||||
return request.param
|
|
||||||
|
|
||||||
|
|
||||||
def test_initialize_detector(mock_GrashopperSetup):
|
|
||||||
"""Test the initialize_detector method."""
|
|
||||||
# Call the function you want to test
|
|
||||||
mock_GrashopperSetup.initialize_detector()
|
|
||||||
|
|
||||||
# Assert the correct methods are called with the expected arguments
|
|
||||||
mock_GrashopperSetup.parent.cam.acquire.put.assert_called_once_with(0)
|
|
||||||
mock_GrashopperSetup.parent.cam.acquire_time_auto.put.assert_called_once_with(
|
|
||||||
AutoMode.CONTINUOUS
|
|
||||||
)
|
|
||||||
mock_GrashopperSetup.parent.cam.gain_auto.put.assert_called_once_with(AutoMode.CONTINUOUS)
|
|
||||||
mock_GrashopperSetup.parent.cam.image_mode.put.assert_called_once_with(ImageMode.MULTIPLE)
|
|
||||||
mock_GrashopperSetup.parent.cam.image_binning.put.assert_called_once_with(ImageBinning.X1)
|
|
||||||
mock_GrashopperSetup.parent.cam.video_mode.put.assert_called_once_with(VideoMode.MODE0)
|
|
||||||
mock_GrashopperSetup.parent.cam.pixel_format.put.assert_called_once_with(PixelFormat.MONO16)
|
|
||||||
mock_GrashopperSetup.parent.cam.trigger_source.put.assert_called_once_with(
|
|
||||||
TriggerSource.SOFTWARE
|
|
||||||
)
|
|
||||||
mock_GrashopperSetup.parent.cam.memory_polling.put.assert_called_once_with(
|
|
||||||
MemoryPolling.SECONDS1
|
|
||||||
)
|
|
||||||
mock_GrashopperSetup.parent.cam.set_image_counter.put.assert_called_once_with(0)
|
|
||||||
|
|
||||||
|
|
||||||
def test_initialize_detector_backend(mock_GrashopperSetup):
|
|
||||||
"""Test the initialize_detector_backend method."""
|
|
||||||
# Call the function you want to test
|
|
||||||
mock_GrashopperSetup.initialize_detector_backend()
|
|
||||||
|
|
||||||
# Assert the correct methods are called with the expected arguments
|
|
||||||
mock_GrashopperSetup.parent.image.queue_size.put.assert_called_once_with(5)
|
|
||||||
mock_GrashopperSetup.parent.image.array_port.put.assert_called_once_with(
|
|
||||||
mock_GrashopperSetup.parent.cam.port_name.get()
|
|
||||||
)
|
|
||||||
mock_GrashopperSetup.parent.image.enable_cb.put.assert_called_once_with(1)
|
|
||||||
mock_GrashopperSetup.parent.image.set_array_counter.put.assert_called_once_with(0)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("exposure_time", [1, 0.1, 0.01, 0.001, 0.0001])
|
|
||||||
def test_set_exposure_time(mock_GrashopperSetup, exposure_time):
|
|
||||||
"""Test the set_exposure_time method."""
|
|
||||||
# Call the function you want to test
|
|
||||||
frame_rate = 1 / exposure_time
|
|
||||||
if frame_rate > mock_GrashopperSetup.low_frame_rate:
|
|
||||||
with pytest.raises(GrashopperError):
|
|
||||||
mock_GrashopperSetup.set_exposure_time(exposure_time)
|
|
||||||
else:
|
|
||||||
mock_GrashopperSetup.set_exposure_time(exposure_time)
|
|
||||||
mock_GrashopperSetup.parent.cam.frame_rate.put.assert_called_once_with(frame_rate)
|
|
||||||
|
|
||||||
|
|
||||||
def test_prepare_detector(mock_GrashopperSetup, scaninfo):
|
|
||||||
"""Test the prepare_detector method."""
|
|
||||||
# setup scaninof
|
|
||||||
for k, v in scaninfo.items():
|
|
||||||
setattr(mock_GrashopperSetup.parent.scaninfo, k, v)
|
|
||||||
|
|
||||||
# Call the function you want to test
|
|
||||||
with (
|
|
||||||
mock.patch.object(
|
|
||||||
mock_GrashopperSetup, "set_acquisition_params"
|
|
||||||
) as mock_set_acquisition_params,
|
|
||||||
mock.patch.object(mock_GrashopperSetup, "set_exposure_time") as mock_set_exposure_time,
|
|
||||||
):
|
|
||||||
mock_GrashopperSetup.prepare_detector()
|
|
||||||
|
|
||||||
# Assert the correct methods are called with the expected arguments
|
|
||||||
mock_GrashopperSetup.parent.cam.image_mode.put.assert_called_once_with(ImageMode.MULTIPLE)
|
|
||||||
mock_GrashopperSetup.parent.cam.acquire_time_auto.put.assert_called_once_with(
|
|
||||||
AutoMode.CONTINUOUS
|
|
||||||
)
|
|
||||||
mock_GrashopperSetup.parent.set_trigger.assert_called_once_with(TriggerSource.SOFTWARE)
|
|
||||||
mock_GrashopperSetup.parent.cam.set_image_counter.put.assert_called_once_with(0)
|
|
||||||
mock_set_acquisition_params.assert_called_once()
|
|
||||||
mock_set_exposure_time.assert_called_once_with(scaninfo["exp_time"])
|
|
||||||
|
|
||||||
|
|
||||||
def test_prepare_detector_backend(mock_GrashopperSetup):
|
|
||||||
"""Test the prepare_detector_backend method."""
|
|
||||||
# Call the function you want to test
|
|
||||||
mock_GrashopperSetup.prepare_detector_backend()
|
|
||||||
mock_GrashopperSetup.parent.image.set_array_counter.put.assert_called_once_with(0)
|
|
||||||
assert mock_GrashopperSetup.monitor_thread is None
|
|
||||||
assert not mock_GrashopperSetup.stop_monitor
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("detector_state", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
||||||
def test_arm_acquisition(mock_GrashopperSetup, detector_state):
|
|
||||||
"""Test the arm_acquisition method."""
|
|
||||||
# Call the function you want to test
|
|
||||||
mock_GrashopperSetup.parent.cam.detector_state.get.return_value = detector_state
|
|
||||||
mock_GrashopperSetup.parent.timeout = 0.1
|
|
||||||
|
|
||||||
if detector_state != DetectorState.WAITING:
|
|
||||||
with pytest.raises(GrashopperTimeoutError):
|
|
||||||
mock_GrashopperSetup.arm_acquisition()
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_count == 1
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_args == mock.call(1)
|
|
||||||
else:
|
|
||||||
mock_GrashopperSetup.arm_acquisition()
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_count == 1
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_args == mock.call(1)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("trigger_source", [0, 1, 2, 3])
|
|
||||||
def test_on_trigger(mock_GrashopperSetup, trigger_source):
|
|
||||||
"""Test the on_trigger method."""
|
|
||||||
# Call the function you want to test
|
|
||||||
mock_GrashopperSetup.parent.cam.trigger_source.get.return_value = trigger_source
|
|
||||||
with mock.patch.object(mock_GrashopperSetup, "send_data") as mock_send_data:
|
|
||||||
mock_GrashopperSetup.on_trigger()
|
|
||||||
|
|
||||||
# Assert the correct methods are called with the expected arguments
|
|
||||||
if trigger_source == TriggerSource.SOFTWARE:
|
|
||||||
mock_GrashopperSetup.parent.cam.software_trigger_device.put.assert_called_once_with(1)
|
|
||||||
assert mock_send_data.call_count == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_set_acquisition_params(mock_GrashopperSetup, scaninfo):
|
|
||||||
"""Test the set_acquisition_params method."""
|
|
||||||
# Setup scaninfo
|
|
||||||
mock_GrashopperSetup.parent.scaninfo.num_points = scaninfo["num_points"]
|
|
||||||
mock_GrashopperSetup.parent.scaninfo.frames_per_trigger = scaninfo["frames_per_trigger"]
|
|
||||||
|
|
||||||
# Call the function you want to test
|
|
||||||
mock_GrashopperSetup.set_acquisition_params()
|
|
||||||
|
|
||||||
# Assert the correct methods are called with the expected arguments
|
|
||||||
expected_num_images = scaninfo["num_points"] * scaninfo["frames_per_trigger"]
|
|
||||||
mock_GrashopperSetup.parent.cam.num_images.put.assert_called_once_with(expected_num_images)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("detector_state", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
|
||||||
def test_stop_detector(mock_GrashopperSetup, detector_state):
|
|
||||||
"""Test the arm_acquisition method."""
|
|
||||||
# Call the function you want to test
|
|
||||||
mock_GrashopperSetup.parent.cam.detector_state.get.return_value = detector_state
|
|
||||||
mock_GrashopperSetup.parent.timeout = 0.1
|
|
||||||
|
|
||||||
if detector_state != DetectorState.IDLE:
|
|
||||||
with pytest.raises(GrashopperTimeoutError):
|
|
||||||
mock_GrashopperSetup.stop_detector()
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_count == 2
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_args == mock.call(0)
|
|
||||||
else:
|
|
||||||
mock_GrashopperSetup.stop_detector()
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_count == 1
|
|
||||||
assert mock_GrashopperSetup.parent.cam.acquire.put.call_args == mock.call(0)
|
|
@ -10,7 +10,7 @@ import pytest
|
|||||||
from bec_server.device_server.tests.utils import DMMock
|
from bec_server.device_server.tests.utils import DMMock
|
||||||
from ophyd import Device, Signal
|
from ophyd import Device, Signal
|
||||||
|
|
||||||
from ophyd_devices.ophyd_base_devices.bec_protocols import (
|
from ophyd_devices.interfaces.protocols.bec_protocols import (
|
||||||
BECDeviceProtocol,
|
BECDeviceProtocol,
|
||||||
BECFlyerProtocol,
|
BECFlyerProtocol,
|
||||||
BECPositionerProtocol,
|
BECPositionerProtocol,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user