mirror of
https://github.com/bec-project/ophyd_devices.git
synced 2025-06-02 18:10:40 +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:
|
||||
stage: test
|
||||
script:
|
||||
- ophyd_test --config ./ophyd_devices/epics/db/ --output ./config_tests
|
||||
- ophyd_test --config ./ophyd_devices/configs/ --output ./config_tests
|
||||
artifacts:
|
||||
paths:
|
||||
- ./config_tests
|
||||
|
@ -2,7 +2,7 @@ from .ophyd_patch import 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 SimFlyer
|
||||
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_signals import ReadOnlySignal
|
||||
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.dynamic_pseudo import ComputedSignal
|
||||
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.quadem import QuadEM
|
||||
from ophyd.sim import SynAxis, SynPeriodicSignal, SynSignal
|
||||
|
||||
from .devices.slits import SlitH, SlitV
|
||||
from .devices.specMotors import (
|
||||
from .epics_motor_ex import EpicsMotorEx
|
||||
from .slits import SlitH, SlitV
|
||||
from .sls_devices import SLSInfo, SLSOperatorMessages
|
||||
from .specMotors import (
|
||||
Bpm4i,
|
||||
EnergyKev,
|
||||
GirderMotorPITCH,
|
||||
@ -17,8 +18,4 @@ from .devices.specMotors import (
|
||||
PmDetectorRotation,
|
||||
PmMonoBender,
|
||||
)
|
||||
from .devices.SpmBase import SpmBase
|
||||
|
||||
# X07MA specific devices
|
||||
from .devices.X07MADevices import *
|
||||
from .devices.XbpmBase import XbpmBase, XbpmCsaxsOp
|
||||
from .SpmBase import SpmBase
|
@ -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 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
|
||||
|
||||
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 ophyd import Device, Signal
|
||||
|
||||
from ophyd_devices.ophyd_base_devices.bec_protocols import (
|
||||
from ophyd_devices.interfaces.protocols.bec_protocols import (
|
||||
BECDeviceProtocol,
|
||||
BECFlyerProtocol,
|
||||
BECPositionerProtocol,
|
||||
|
Loading…
x
Reference in New Issue
Block a user