This commit is contained in:
mohacsi_i 2024-03-12 10:56:30 +01:00
parent 1b328d31de
commit 1dda0e04ba
2 changed files with 828 additions and 570 deletions

View File

@ -8,67 +8,109 @@ import time
try: try:
from .AerotechAutomation1Enums import * from .AerotechAutomation1Enums import *
from .AerotechAutomation1Enums import (DataCollectionMode, DataCollectionFrequency, from .AerotechAutomation1Enums import (
AxisDataSignal, PsoWindowInput, DriveDataCaptureInput, DriveDataCaptureTrigger, DataCollectionMode,
TaskDataSignal, SystemDataSignal, TomcatSequencerState) DataCollectionFrequency,
AxisDataSignal,
PsoWindowInput,
DriveDataCaptureInput,
DriveDataCaptureTrigger,
TaskDataSignal,
SystemDataSignal,
TomcatSequencerState,
)
except: except:
from AerotechAutomation1Enums import * from AerotechAutomation1Enums import *
from AerotechAutomation1Enums import (DataCollectionMode, DataCollectionFrequency, from AerotechAutomation1Enums import (
AxisDataSignal, PsoWindowInput, DriveDataCaptureInput, DriveDataCaptureTrigger, DataCollectionMode,
TaskDataSignal, SystemDataSignal, TomcatSequencerState) DataCollectionFrequency,
AxisDataSignal,
PsoWindowInput,
DriveDataCaptureInput,
DriveDataCaptureTrigger,
TaskDataSignal,
SystemDataSignal,
TomcatSequencerState,
)
from typing import Union from typing import Union
from collections import OrderedDict from collections import OrderedDict
class EpicsMotorX(EpicsMotor): class EpicsMotorX(EpicsMotor):
""" Special motor class that provides flyer interface and progress bar. """ Special motor class that provides flyer interface and progress bar.
""" """
SUB_PROGRESS = "progress" SUB_PROGRESS = "progress"
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs): def __init__(
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs) self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._startPosition = None self._startPosition = None
self._targetPosition = None self._targetPosition = None
self.subscribe(self._progress_update, run=False) self.subscribe(self._progress_update, run=False)
def configure(self, d: dict): def configure(self, d: dict):
if "target" in d: if "target" in d:
self._targetPosition = d['target'] self._targetPosition = d["target"]
del d['target'] del d["target"]
if "position" in d: if "position" in d:
self._targetPosition = d['position'] self._targetPosition = d["position"]
del d['position'] del d["position"]
return super().configure(d) return super().configure(d)
def kickoff(self): def kickoff(self):
self._startPosition = float( self.position) self._startPosition = float(self.position)
return self.move(self._targetPosition, wait=False) return self.move(self._targetPosition, wait=False)
def move(self, position, wait=True, **kwargs): def move(self, position, wait=True, **kwargs):
self._startPosition = float( self.position) self._startPosition = float(self.position)
return super().move(position, wait, **kwargs) return super().move(position, wait, **kwargs)
def _progress_update(self, value, **kwargs) -> None: def _progress_update(self, value, **kwargs) -> None:
"""Progress update on the scan""" """Progress update on the scan"""
if (self._startPosition is None) or (self._targetPosition is None) or (not self.moving): if (self._startPosition is None) or (self._targetPosition is None) or (not self.moving):
self._run_subs( sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1, ) self._run_subs(
sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1,
)
return return
progress = np.abs( (value-self._startPosition)/(self._targetPosition-self._startPosition) ) progress = np.abs(
(value - self._startPosition) / (self._targetPosition - self._startPosition)
)
max_value = 100 max_value = 100
self._run_subs( self._run_subs(
sub_type=self.SUB_PROGRESS, sub_type=self.SUB_PROGRESS,
value=int(100*progress), max_value=max_value, done=int(np.isclose(max_value, progress, 1e-3)), ) value=int(100 * progress),
max_value=max_value,
done=int(np.isclose(max_value, progress, 1e-3)),
)
class EpicsPassiveRO(EpicsSignalRO): class EpicsPassiveRO(EpicsSignalRO):
""" Small helper class to read PVs that need to be processed first. """ Small helper class to read PVs that need to be processed first.
""" """
def __init__(self, read_pv, *, string=False, name=None, **kwargs): def __init__(self, read_pv, *, string=False, name=None, **kwargs):
super().__init__(read_pv, string=string, name=name, **kwargs) super().__init__(read_pv, string=string, name=name, **kwargs)
self._proc = EpicsSignal(read_pv+".PROC", kind=Kind.omitted, put_complete=True) self._proc = EpicsSignal(read_pv + ".PROC", kind=Kind.omitted, put_complete=True)
def wait_for_connection(self, *args, **kwargs): def wait_for_connection(self, *args, **kwargs):
super().wait_for_connection(*args, **kwargs) super().wait_for_connection(*args, **kwargs)
@ -83,10 +125,9 @@ class EpicsPassiveRO(EpicsSignalRO):
return super().value return super().value
class aa1Controller(Device): class aa1Controller(Device):
"""Ophyd proxy class for the Aerotech Automation 1's core controller functionality""" """Ophyd proxy class for the Aerotech Automation 1's core controller functionality"""
controllername = Component(EpicsSignalRO, "NAME", kind=Kind.config) controllername = Component(EpicsSignalRO, "NAME", kind=Kind.config)
serialnumber = Component(EpicsSignalRO, "SN", kind=Kind.config) serialnumber = Component(EpicsSignalRO, "SN", kind=Kind.config)
apiversion = Component(EpicsSignalRO, "API_VERSION", kind=Kind.config) apiversion = Component(EpicsSignalRO, "API_VERSION", kind=Kind.config)
@ -94,8 +135,28 @@ class aa1Controller(Device):
taskcount = Component(EpicsSignalRO, "TASKCOUNT", kind=Kind.config) taskcount = Component(EpicsSignalRO, "TASKCOUNT", kind=Kind.config)
fastpoll = Component(EpicsSignalRO, "POLLTIME", auto_monitor=True, kind=Kind.hinted) fastpoll = Component(EpicsSignalRO, "POLLTIME", auto_monitor=True, kind=Kind.hinted)
slowpoll = Component(EpicsSignalRO, "DRVPOLLTIME", auto_monitor=True, kind=Kind.hinted) slowpoll = Component(EpicsSignalRO, "DRVPOLLTIME", auto_monitor=True, kind=Kind.hinted)
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs) def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
class aa1Tasks(Device): class aa1Tasks(Device):
""" Task management API """ Task management API
@ -127,6 +188,7 @@ class aa1Tasks(Device):
''' '''
""" """
SUB_PROGRESS = "progress" SUB_PROGRESS = "progress"
_failure = Component(EpicsSignalRO, "FAILURE", auto_monitor=True, kind=Kind.hinted) _failure = Component(EpicsSignalRO, "FAILURE", auto_monitor=True, kind=Kind.hinted)
errStatus = Component(EpicsSignalRO, "ERRW", auto_monitor=True, kind=Kind.hinted) errStatus = Component(EpicsSignalRO, "ERRW", auto_monitor=True, kind=Kind.hinted)
@ -134,17 +196,37 @@ class aa1Tasks(Device):
taskStates = Component(EpicsSignalRO, "STATES-RBV", auto_monitor=True, kind=Kind.hinted) taskStates = Component(EpicsSignalRO, "STATES-RBV", auto_monitor=True, kind=Kind.hinted)
taskIndex = Component(EpicsSignal, "TASKIDX", kind=Kind.config, put_complete=True) taskIndex = Component(EpicsSignal, "TASKIDX", kind=Kind.config, put_complete=True)
switch = Component(EpicsSignal, "SWITCH", kind=Kind.config, put_complete=True) switch = Component(EpicsSignal, "SWITCH", kind=Kind.config, put_complete=True)
_execute = Component(EpicsSignal, "EXECUTE", string=True, kind=Kind.config, put_complete=True) _execute = Component(EpicsSignal, "EXECUTE", string=True, kind=Kind.config, put_complete=True)
_executeMode = Component(EpicsSignal, "EXECUTE-MODE", kind=Kind.config, put_complete=True) _executeMode = Component(EpicsSignal, "EXECUTE-MODE", kind=Kind.config, put_complete=True)
_executeReply = Component(EpicsSignalRO, "EXECUTE_RBV", string=True, auto_monitor=True) _executeReply = Component(EpicsSignalRO, "EXECUTE_RBV", string=True, auto_monitor=True)
fileName = Component(EpicsSignal, "FILENAME", string=True, kind=Kind.omitted, put_complete=True) fileName = Component(EpicsSignal, "FILENAME", string=True, kind=Kind.omitted, put_complete=True)
_fileRead = Component(EpicsPassiveRO, "FILEREAD", string=True, kind=Kind.omitted) _fileRead = Component(EpicsPassiveRO, "FILEREAD", string=True, kind=Kind.omitted)
_fileWrite = Component(EpicsSignal, "FILEWRITE", string=True, kind=Kind.omitted, put_complete=True) _fileWrite = Component(
EpicsSignal, "FILEWRITE", string=True, kind=Kind.omitted, put_complete=True
)
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs): def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
""" __init__ MUST have a full argument list""" """ __init__ MUST have a full argument list"""
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs) super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._currentTask = None self._currentTask = None
self._textToExecute = None self._textToExecute = None
self._isConfigured = False self._isConfigured = False
@ -154,7 +236,9 @@ class aa1Tasks(Device):
def _progress_update(self, value, **kwargs) -> None: def _progress_update(self, value, **kwargs) -> None:
"""Progress update on the scan""" """Progress update on the scan"""
value = self.progress() value = self.progress()
self._run_subs( sub_type=self.SUB_PROGRESS, value=value, max_value=1, done=1, ) self._run_subs(
sub_type=self.SUB_PROGRESS, value=value, max_value=1, done=1,
)
def _progress(self) -> None: def _progress(self) -> None:
"""Progress update on the scan""" """Progress update on the scan"""
@ -172,7 +256,7 @@ class aa1Tasks(Device):
self.fileName.set(filename).wait() self.fileName.set(filename).wait()
filebytes = self._fileRead.get() filebytes = self._fileRead.get()
# C-strings terminate with trailing zero # C-strings terminate with trailing zero
if filebytes[-1]==0: if filebytes[-1] == 0:
filebytes = filebytes[:-1] filebytes = filebytes[:-1]
filetext = filebytes filetext = filebytes
return filetext return filetext
@ -182,19 +266,19 @@ class aa1Tasks(Device):
self.fileName.set(filename).wait() self.fileName.set(filename).wait()
self._fileWrite.set(filetext).wait() self._fileWrite.set(filetext).wait()
def runScript(self, filename: str, taskIndex: int==2, filetext=None, settle_time=0.5) -> None: def runScript(self, filename: str, taskIndex: int == 2, filetext=None, settle_time=0.5) -> None:
""" Run a script file that either exists, or is newly created and compiled""" """ Run a script file that either exists, or is newly created and compiled"""
self.configure({'text': filetext, 'filename': filename, 'taskIndex': taskIndex}) self.configure({"text": filetext, "filename": filename, "taskIndex": taskIndex})
print("Runscript configured") print("Runscript configured")
self.trigger().wait() self.trigger().wait()
print("Runscript waited") print("Runscript waited")
def execute(self, text: str, taskIndex: int=3, mode: str=0, settle_time=0.5): def execute(self, text: str, taskIndex: int = 3, mode: str = 0, settle_time=0.5):
""" Run a short text command on the Automation1 controller""" """ Run a short text command on the Automation1 controller"""
print(f"Executing program on task: {taskIndex}") print(f"Executing program on task: {taskIndex}")
self.configure({'text': text, 'taskIndex': taskIndex, 'mode': mode}) self.configure({"text": text, "taskIndex": taskIndex, "mode": mode})
self.kickoff().wait() self.kickoff().wait()
if mode in [0, "None", None]: if mode in [0, "None", None]:
@ -203,16 +287,16 @@ class aa1Tasks(Device):
raw = self._executeReply.get() raw = self._executeReply.get()
return raw return raw
def configure(self, d: dict={}) -> tuple: def configure(self, d: dict = {}) -> tuple:
""" Configuration interface for flying """ Configuration interface for flying
""" """
# Unrolling the configuration dict # Unrolling the configuration dict
text = str(d['text']) if 'text' in d else None text = str(d["text"]) if "text" in d else None
filename = str(d['filename']) if 'filename' in d else None filename = str(d["filename"]) if "filename" in d else None
taskIndex = int(d['taskIndex']) if 'taskIndex' in d else 4 taskIndex = int(d["taskIndex"]) if "taskIndex" in d else 4
settle_time = float(d['settle_time']) if 'settle_time' in d else None settle_time = float(d["settle_time"]) if "settle_time" in d else None
mode = d['mode'] if 'mode' in d else None mode = d["mode"] if "mode" in d else None
self._isStepConfig = d['stepper'] if 'stepper' in d else False self._isStepConfig = d["stepper"] if "stepper" in d else False
# Validation # Validation
if taskIndex < 1 or taskIndex > 31: if taskIndex < 1 or taskIndex > 31:
@ -302,6 +386,7 @@ class aa1Tasks(Device):
print("Called aa1Task.complete()") print("Called aa1Task.complete()")
timestamp_ = 0 timestamp_ = 0
taskIdx = int(self.taskIndex.get()) taskIdx = int(self.taskIndex.get())
def notRunning2(*args, old_value, value, timestamp, **kwargs): def notRunning2(*args, old_value, value, timestamp, **kwargs):
nonlocal timestamp_ nonlocal timestamp_
result = False if value[taskIdx] in ["Running", 4] else True result = False if value[taskIdx] in ["Running", 4] else True
@ -315,7 +400,14 @@ class aa1Tasks(Device):
def describe_collect(self) -> OrderedDict: def describe_collect(self) -> OrderedDict:
dd = OrderedDict() dd = OrderedDict()
dd['success'] = {'source': "internal", 'dtype': 'integer', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0} dd["success"] = {
"source": "internal",
"dtype": "integer",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
return {self.name: dd} return {self.name: dd}
def collect(self) -> OrderedDict: def collect(self) -> OrderedDict:
@ -331,6 +423,7 @@ class aa1TaskState(Device):
This is the task state monitoring interface for Automation1 tasks. It This is the task state monitoring interface for Automation1 tasks. It
does not launch execution, but can wait for the execution to complete. does not launch execution, but can wait for the execution to complete.
""" """
index = Component(EpicsSignalRO, "INDEX", kind=Kind.config) index = Component(EpicsSignalRO, "INDEX", kind=Kind.config)
status = Component(EpicsSignalRO, "STATUS", auto_monitor=True, kind=Kind.hinted) status = Component(EpicsSignalRO, "STATUS", auto_monitor=True, kind=Kind.hinted)
errorCode = Component(EpicsSignalRO, "ERROR", auto_monitor=True, kind=Kind.hinted) errorCode = Component(EpicsSignalRO, "ERROR", auto_monitor=True, kind=Kind.hinted)
@ -341,9 +434,10 @@ class aa1TaskState(Device):
print("Called aa1TaskState.complete()") print("Called aa1TaskState.complete()")
# Define wait until the busy flag goes down (excluding initial update) # Define wait until the busy flag goes down (excluding initial update)
timestamp_ = 0 timestamp_ = 0
def notRunning(*args, old_value, value, timestamp, **kwargs): def notRunning(*args, old_value, value, timestamp, **kwargs):
nonlocal timestamp_ nonlocal timestamp_
result = False if (timestamp_== 0) else (value not in ["Running", 4]) result = False if (timestamp_ == 0) else (value not in ["Running", 4])
timestamp_ = timestamp timestamp_ = timestamp
print(result) print(result)
return result return result
@ -359,7 +453,14 @@ class aa1TaskState(Device):
def describe_collect(self) -> OrderedDict: def describe_collect(self) -> OrderedDict:
dd = OrderedDict() dd = OrderedDict()
dd['success'] = {'source': "internal", 'dtype': 'integer', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0} dd["success"] = {
"source": "internal",
"dtype": "integer",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
return dd return dd
def collect(self) -> OrderedDict: def collect(self) -> OrderedDict:
@ -381,14 +482,15 @@ class aa1DataAcquisition(Device):
3. Start your data collection 3. Start your data collection
4. Read back the recorded data with "readback" 4. Read back the recorded data with "readback"
""" """
# Status monitoring # Status monitoring
status = Component(EpicsSignalRO, "RUNNING", auto_monitor=True, kind=Kind.hinted) status = Component(EpicsSignalRO, "RUNNING", auto_monitor=True, kind=Kind.hinted)
points_max = Component(EpicsSignal, "MAXPOINTS", kind=Kind.config, put_complete=True) points_max = Component(EpicsSignal, "MAXPOINTS", kind=Kind.config, put_complete=True)
signal_num = Component(EpicsSignalRO, "NITEMS", kind=Kind.config) signal_num = Component(EpicsSignalRO, "NITEMS", kind=Kind.config)
points_total = Component(EpicsSignalRO, "NTOTAL", auto_monitor=True, kind=Kind.hinted) points_total = Component(EpicsSignalRO, "NTOTAL", auto_monitor=True, kind=Kind.hinted)
points_collected = Component(EpicsSignalRO, "NCOLLECTED", auto_monitor=True, kind=Kind.hinted) points_collected = Component(EpicsSignalRO, "NCOLLECTED", auto_monitor=True, kind=Kind.hinted)
points_retrieved= Component(EpicsSignalRO, "NRETRIEVED", auto_monitor=True, kind=Kind.hinted) points_retrieved = Component(EpicsSignalRO, "NRETRIEVED", auto_monitor=True, kind=Kind.hinted)
overflow = Component(EpicsSignalRO, "OVERFLOW", auto_monitor=True, kind=Kind.hinted) overflow = Component(EpicsSignalRO, "OVERFLOW", auto_monitor=True, kind=Kind.hinted)
runmode = Component(EpicsSignalRO, "MODE_RBV", auto_monitor=True, kind=Kind.hinted) runmode = Component(EpicsSignalRO, "MODE_RBV", auto_monitor=True, kind=Kind.hinted)
# DAQ setup # DAQ setup
@ -448,7 +550,7 @@ class aa1DataAcquisition(Device):
self._switch.set("START").wait() self._switch.set("START").wait()
# Wait for finishing acquisition # Wait for finishing acquisition
# Note: this is very bad blocking sleep # Note: this is very bad blocking sleep
while self.status.value!=0: while self.status.value != 0:
sleep(0.1) sleep(0.1)
sleep(0.1) sleep(0.1)
@ -456,7 +558,7 @@ class aa1DataAcquisition(Device):
data = self.data_rb.get() data = self.data_rb.get()
rows = self.data_rows.get() rows = self.data_rows.get()
cols = self.data_cols.get() cols = self.data_cols.get()
if len(data)==0 or rows==0 or cols==0: if len(data) == 0 or rows == 0 or cols == 0:
sleep(0.5) sleep(0.5)
data = self.data_rb.get() data = self.data_rb.get()
rows = self.data_rows.get() rows = self.data_rows.get()
@ -476,7 +578,7 @@ class aa1DataAcquisition(Device):
data = self.data_rb.get() data = self.data_rb.get()
rows = self.data_rows.get() rows = self.data_rows.get()
cols = self.data_cols.get() cols = self.data_cols.get()
if len(data)==0 or rows==0 or cols==0: if len(data) == 0 or rows == 0 or cols == 0:
sleep(0.2) sleep(0.2)
data = self.data_rb.get() data = self.data_rb.get()
rows = self.data_rows.get() rows = self.data_rows.get()
@ -486,7 +588,6 @@ class aa1DataAcquisition(Device):
return data return data
class aa1GlobalVariables(Device): class aa1GlobalVariables(Device):
""" Global variables """ Global variables
@ -505,10 +606,11 @@ class aa1GlobalVariables(Device):
ret_arr = var.readFloat(1000, 1024) ret_arr = var.readFloat(1000, 1024)
""" """
# Status monitoring # Status monitoring
num_real = Component(EpicsSignalRO, "NUM-REAL_RBV", kind=Kind.config) num_real = Component(EpicsSignalRO, "NUM-REAL_RBV", kind=Kind.config)
num_int = Component(EpicsSignalRO, "NUM-INT_RBV", kind=Kind.config) num_int = Component(EpicsSignalRO, "NUM-INT_RBV", kind=Kind.config)
num_string = Component(EpicsSignalRO, "NUM-STRING_RBV", kind=Kind.config) num_string = Component(EpicsSignalRO, "NUM-STRING_RBV", kind=Kind.config)
integer_addr = Component(EpicsSignal, "INT-ADDR", kind=Kind.omitted, put_complete=True) integer_addr = Component(EpicsSignal, "INT-ADDR", kind=Kind.omitted, put_complete=True)
integer_size = Component(EpicsSignal, "INT-SIZE", kind=Kind.omitted, put_complete=True) integer_size = Component(EpicsSignal, "INT-SIZE", kind=Kind.omitted, put_complete=True)
@ -528,7 +630,7 @@ class aa1GlobalVariables(Device):
string = Component(EpicsSignal, "STRING", string=True, kind=Kind.omitted, put_complete=True) string = Component(EpicsSignal, "STRING", string=True, kind=Kind.omitted, put_complete=True)
string_rb = Component(EpicsPassiveRO, "STRING-RBV", string=True, kind=Kind.omitted) string_rb = Component(EpicsPassiveRO, "STRING-RBV", string=True, kind=Kind.omitted)
def readInt(self, address: int, size: int=None) -> int: def readInt(self, address: int, size: int = None) -> int:
""" Read a 64-bit integer global variable """ """ Read a 64-bit integer global variable """
if address > self.num_int.get(): if address > self.num_int.get():
raise RuntimeError("Integer address {address} is out of range") raise RuntimeError("Integer address {address} is out of range")
@ -559,8 +661,7 @@ class aa1GlobalVariables(Device):
else: else:
raise RuntimeError("Unsupported integer value type: {type(value)}") raise RuntimeError("Unsupported integer value type: {type(value)}")
def readFloat(self, address: int, size: int = None) -> float:
def readFloat(self, address: int, size: int=None) -> float:
""" Read a 64-bit double global variable """ """ Read a 64-bit double global variable """
if address > self.num_real.get(): if address > self.num_real.get():
raise RuntimeError("Floating point address {address} is out of range") raise RuntimeError("Floating point address {address} is out of range")
@ -613,7 +714,6 @@ class aa1GlobalVariables(Device):
raise RuntimeError("Unsupported string value type: {type(value)}") raise RuntimeError("Unsupported string value type: {type(value)}")
class aa1GlobalVariableBindings(Device): class aa1GlobalVariableBindings(Device):
""" Polled global variables """ Polled global variables
@ -621,30 +721,124 @@ class aa1GlobalVariableBindings(Device):
on the Automation1 controller. These variables are continuously polled on the Automation1 controller. These variables are continuously polled
and are thus a convenient way to interface scripts with the outside word. and are thus a convenient way to interface scripts with the outside word.
""" """
int0 = Component(EpicsSignalRO, "INT0_RBV", auto_monitor=True, name="int0", kind=Kind.hinted) int0 = Component(EpicsSignalRO, "INT0_RBV", auto_monitor=True, name="int0", kind=Kind.hinted)
int1 = Component(EpicsSignalRO, "INT1_RBV", auto_monitor=True, name="int1", kind=Kind.hinted) int1 = Component(EpicsSignalRO, "INT1_RBV", auto_monitor=True, name="int1", kind=Kind.hinted)
int2 = Component(EpicsSignalRO, "INT2_RBV", auto_monitor=True, name="int2", kind=Kind.hinted) int2 = Component(EpicsSignalRO, "INT2_RBV", auto_monitor=True, name="int2", kind=Kind.hinted)
int3 = Component(EpicsSignalRO, "INT3_RBV", auto_monitor=True, name="int3", kind=Kind.hinted) int3 = Component(EpicsSignalRO, "INT3_RBV", auto_monitor=True, name="int3", kind=Kind.hinted)
int8 = Component(EpicsSignal, "INT8_RBV", put_complete=True, write_pv="INT8", auto_monitor=True, name="int8", kind=Kind.hinted) int8 = Component(
int9 = Component(EpicsSignal, "INT9_RBV", put_complete=True, write_pv="INT9", auto_monitor=True, name="int9", kind=Kind.hinted) EpicsSignal,
int10 = Component(EpicsSignal, "INT10_RBV", put_complete=True, write_pv="INT10", auto_monitor=True, name="int10", kind=Kind.hinted) "INT8_RBV",
int11 = Component(EpicsSignal, "INT11_RBV", put_complete=True, write_pv="INT11", auto_monitor=True, name="int11", kind=Kind.hinted) put_complete=True,
write_pv="INT8",
auto_monitor=True,
name="int8",
kind=Kind.hinted,
)
int9 = Component(
EpicsSignal,
"INT9_RBV",
put_complete=True,
write_pv="INT9",
auto_monitor=True,
name="int9",
kind=Kind.hinted,
)
int10 = Component(
EpicsSignal,
"INT10_RBV",
put_complete=True,
write_pv="INT10",
auto_monitor=True,
name="int10",
kind=Kind.hinted,
)
int11 = Component(
EpicsSignal,
"INT11_RBV",
put_complete=True,
write_pv="INT11",
auto_monitor=True,
name="int11",
kind=Kind.hinted,
)
float0 = Component(EpicsSignalRO, "REAL0_RBV", auto_monitor=True, name="float0", kind=Kind.hinted) float0 = Component(
float1 = Component(EpicsSignalRO, "REAL1_RBV", auto_monitor=True, name="float1", kind=Kind.hinted) EpicsSignalRO, "REAL0_RBV", auto_monitor=True, name="float0", kind=Kind.hinted
float2 = Component(EpicsSignalRO, "REAL2_RBV", auto_monitor=True, name="float2", kind=Kind.hinted) )
float3 = Component(EpicsSignalRO, "REAL3_RBV", auto_monitor=True, name="float3", kind=Kind.hinted) float1 = Component(
float16 = Component(EpicsSignal, "REAL16_RBV", write_pv="REAL16", put_complete=True, auto_monitor=True, name="float16", kind=Kind.hinted) EpicsSignalRO, "REAL1_RBV", auto_monitor=True, name="float1", kind=Kind.hinted
float17 = Component(EpicsSignal, "REAL17_RBV", write_pv="REAL17", put_complete=True, auto_monitor=True, name="float17", kind=Kind.hinted) )
float18 = Component(EpicsSignal, "REAL18_RBV", write_pv="REAL18", put_complete=True, auto_monitor=True, name="float18", kind=Kind.hinted) float2 = Component(
float19 = Component(EpicsSignal, "REAL19_RBV", write_pv="REAL19", put_complete=True, auto_monitor=True, name="float19", kind=Kind.hinted) EpicsSignalRO, "REAL2_RBV", auto_monitor=True, name="float2", kind=Kind.hinted
)
float3 = Component(
EpicsSignalRO, "REAL3_RBV", auto_monitor=True, name="float3", kind=Kind.hinted
)
float16 = Component(
EpicsSignal,
"REAL16_RBV",
write_pv="REAL16",
put_complete=True,
auto_monitor=True,
name="float16",
kind=Kind.hinted,
)
float17 = Component(
EpicsSignal,
"REAL17_RBV",
write_pv="REAL17",
put_complete=True,
auto_monitor=True,
name="float17",
kind=Kind.hinted,
)
float18 = Component(
EpicsSignal,
"REAL18_RBV",
write_pv="REAL18",
put_complete=True,
auto_monitor=True,
name="float18",
kind=Kind.hinted,
)
float19 = Component(
EpicsSignal,
"REAL19_RBV",
write_pv="REAL19",
put_complete=True,
auto_monitor=True,
name="float19",
kind=Kind.hinted,
)
# BEC LiveTable crashes on non-numeric values # BEC LiveTable crashes on non-numeric values
str0 = Component(EpicsSignalRO, "STR0_RBV", auto_monitor=True, string=True, name="str0", kind=Kind.config) str0 = Component(
str1 = Component(EpicsSignalRO, "STR1_RBV", auto_monitor=True, string=True, name="str1", kind=Kind.config) EpicsSignalRO, "STR0_RBV", auto_monitor=True, string=True, name="str0", kind=Kind.config
str4 = Component(EpicsSignal, "STR4_RBV", put_complete=True, string=True, auto_monitor=True, write_pv="STR4", name="str4", kind=Kind.config) )
str5 = Component(EpicsSignal, "STR5_RBV", put_complete=True, string=True, auto_monitor=True, write_pv="STR5", name="str5", kind=Kind.config) str1 = Component(
EpicsSignalRO, "STR1_RBV", auto_monitor=True, string=True, name="str1", kind=Kind.config
)
str4 = Component(
EpicsSignal,
"STR4_RBV",
put_complete=True,
string=True,
auto_monitor=True,
write_pv="STR4",
name="str4",
kind=Kind.config,
)
str5 = Component(
EpicsSignal,
"STR5_RBV",
put_complete=True,
string=True,
auto_monitor=True,
write_pv="STR5",
name="str5",
kind=Kind.config,
)
class aa1AxisIo(Device): class aa1AxisIo(Device):
@ -655,6 +849,7 @@ class aa1AxisIo(Device):
should be done in AeroScript. Only one pin can be writen directly but should be done in AeroScript. Only one pin can be writen directly but
several can be polled! several can be polled!
""" """
polllvl = Component(EpicsSignal, "POLLLVL", put_complete=True, kind=Kind.config) polllvl = Component(EpicsSignal, "POLLLVL", put_complete=True, kind=Kind.config)
ai0 = Component(EpicsSignalRO, "AI0-RBV", auto_monitor=True, kind=Kind.hinted) ai0 = Component(EpicsSignalRO, "AI0-RBV", auto_monitor=True, kind=Kind.hinted)
ai1 = Component(EpicsSignalRO, "AI1-RBV", auto_monitor=True, kind=Kind.hinted) ai1 = Component(EpicsSignalRO, "AI1-RBV", auto_monitor=True, kind=Kind.hinted)
@ -692,7 +887,6 @@ class aa1AxisIo(Device):
self.do.set(value, settle_time=settle_time).wait() self.do.set(value, settle_time=settle_time).wait()
class aa1AxisPsoBase(Device): class aa1AxisPsoBase(Device):
""" Position Sensitive Output - Base class """ Position Sensitive Output - Base class
@ -708,23 +902,26 @@ class aa1AxisPsoBase(Device):
Specific operation modes should be implemented in child classes. Specific operation modes should be implemented in child classes.
""" """
# ######################################################################## # ########################################################################
# General module status # General module status
status = Component(EpicsSignalRO, "STATUS", auto_monitor=True, kind=Kind.hinted) status = Component(EpicsSignalRO, "STATUS", auto_monitor=True, kind=Kind.hinted)
output = Component(EpicsSignalRO, "OUTPUT-RBV", auto_monitor=True, kind=Kind.hinted) output = Component(EpicsSignalRO, "OUTPUT-RBV", auto_monitor=True, kind=Kind.hinted)
_eventSingle = Component(EpicsSignal, "EVENT:SINGLE", put_complete=True, kind=Kind.omitted) _eventSingle = Component(EpicsSignal, "EVENT:SINGLE", put_complete=True, kind=Kind.omitted)
_reset = Component(EpicsSignal, "RESET", put_complete=True, kind=Kind.omitted) _reset = Component(EpicsSignal, "RESET", put_complete=True, kind=Kind.omitted)
posInput = Component(EpicsSignal, "DIST:INPUT", put_complete=True, kind=Kind.omitted) posInput = Component(EpicsSignal, "DIST:INPUT", put_complete=True, kind=Kind.omitted)
# ######################################################################## # ########################################################################
# PSO Distance event module # PSO Distance event module
dstEventsEna = Component(EpicsSignal, "DIST:EVENTS", put_complete=True, kind=Kind.omitted) dstEventsEna = Component(EpicsSignal, "DIST:EVENTS", put_complete=True, kind=Kind.omitted)
dstCounterEna = Component(EpicsSignal, "DIST:COUNTER", put_complete=True, kind=Kind.omitted) dstCounterEna = Component(EpicsSignal, "DIST:COUNTER", put_complete=True, kind=Kind.omitted)
dstCounterVal = Component(EpicsSignalRO, "DIST:CTR0_RBV", auto_monitor=True, kind=Kind.hinted) dstCounterVal = Component(EpicsSignalRO, "DIST:CTR0_RBV", auto_monitor=True, kind=Kind.hinted)
dstArrayIdx = Component(EpicsSignalRO, "DIST:IDX_RBV", auto_monitor=True, kind=Kind.hinted) dstArrayIdx = Component(EpicsSignalRO, "DIST:IDX_RBV", auto_monitor=True, kind=Kind.hinted)
dstArrayDepleted = Component(EpicsSignalRO, "DIST:ARRAY-DEPLETED-RBV", auto_monitor=True, kind=Kind.hinted) dstArrayDepleted = Component(
EpicsSignalRO, "DIST:ARRAY-DEPLETED-RBV", auto_monitor=True, kind=Kind.hinted
)
dstDirection = Component(EpicsSignal, "DIST:EVENTDIR", put_complete=True, kind=Kind.omitted) dstDirection = Component(EpicsSignal, "DIST:EVENTDIR", put_complete=True, kind=Kind.omitted)
dstDistance = Component(EpicsSignal, "DIST:DISTANCE", put_complete=True, kind=Kind.hinted) dstDistance = Component(EpicsSignal, "DIST:DISTANCE", put_complete=True, kind=Kind.hinted)
dstDistanceArr = Component(EpicsSignal, "DIST:DISTANCES", put_complete=True, kind=Kind.omitted) dstDistanceArr = Component(EpicsSignal, "DIST:DISTANCES", put_complete=True, kind=Kind.omitted)
dstArrayRearm = Component(EpicsSignal, "DIST:REARM-ARRAY", put_complete=True, kind=Kind.omitted) dstArrayRearm = Component(EpicsSignal, "DIST:REARM-ARRAY", put_complete=True, kind=Kind.omitted)
@ -742,10 +939,10 @@ class aa1AxisPsoBase(Device):
# PSO waveform module # PSO waveform module
waveEnable = Component(EpicsSignal, "WAVE:ENABLE", put_complete=True, kind=Kind.omitted) waveEnable = Component(EpicsSignal, "WAVE:ENABLE", put_complete=True, kind=Kind.omitted)
waveMode = Component(EpicsSignal, "WAVE:MODE", put_complete=True, kind=Kind.omitted) waveMode = Component(EpicsSignal, "WAVE:MODE", put_complete=True, kind=Kind.omitted)
#waveDelay = Component(EpicsSignal, "WAVE:DELAY", put_complete=True, kind=Kind.omitted) # waveDelay = Component(EpicsSignal, "WAVE:DELAY", put_complete=True, kind=Kind.omitted)
# PSO waveform pulse output # PSO waveform pulse output
#pulseTrunc = Component(EpicsSignal, "WAVE:PULSE:TRUNC", put_complete=True, kind=Kind.omitted) # pulseTrunc = Component(EpicsSignal, "WAVE:PULSE:TRUNC", put_complete=True, kind=Kind.omitted)
pulseOnTime = Component(EpicsSignal, "WAVE:PULSE:ONTIME", put_complete=True, kind=Kind.omitted) pulseOnTime = Component(EpicsSignal, "WAVE:PULSE:ONTIME", put_complete=True, kind=Kind.omitted)
pulseWindow = Component(EpicsSignal, "WAVE:PULSE:PERIOD", put_complete=True, kind=Kind.omitted) pulseWindow = Component(EpicsSignal, "WAVE:PULSE:PERIOD", put_complete=True, kind=Kind.omitted)
pulseCount = Component(EpicsSignal, "WAVE:PULSE:COUNT", put_complete=True, kind=Kind.omitted) pulseCount = Component(EpicsSignal, "WAVE:PULSE:COUNT", put_complete=True, kind=Kind.omitted)
@ -767,9 +964,6 @@ class aa1AxisPsoBase(Device):
self.waveMode.set(orig_waveMode).wait() self.waveMode.set(orig_waveMode).wait()
class aa1AxisPsoDistance(aa1AxisPsoBase): class aa1AxisPsoDistance(aa1AxisPsoBase):
""" Position Sensitive Output - Distance mode """ Position Sensitive Output - Distance mode
@ -802,11 +996,30 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
pso.configure(d={'distance': 1.8, 'wmode': "pulsed", 'n_pulse': 5}) pso.configure(d={'distance': 1.8, 'wmode': "pulsed", 'n_pulse': 5})
pso.kickoff().wait() pso.kickoff().wait()
""" """
SUB_PROGRESS = "progress" SUB_PROGRESS = "progress"
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs): def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
""" __init__ MUST have a full argument list""" """ __init__ MUST have a full argument list"""
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs) super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._Vdistance = 3.141592 self._Vdistance = 3.141592
self.subscribe(self._progress_update, "progress", run=False) self.subscribe(self._progress_update, "progress", run=False)
@ -814,7 +1027,9 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
"""Progress update on the scan""" """Progress update on the scan"""
if self.dstArrayDepleted.value: if self.dstArrayDepleted.value:
print("PSO array depleted") print("PSO array depleted")
self._run_subs( sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1, ) self._run_subs(
sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1,
)
return return
progress = 1 progress = 1
@ -822,23 +1037,25 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
print(f"PSO array proggress: {progress}") print(f"PSO array proggress: {progress}")
self._run_subs( self._run_subs(
sub_type=self.SUB_PROGRESS, sub_type=self.SUB_PROGRESS,
value=int(progress), max_value=max_value, done=int(np.isclose(max_value, progress, 1e-3)), ) value=int(progress),
max_value=max_value,
done=int(np.isclose(max_value, progress, 1e-3)),
)
# ######################################################################## # ########################################################################
# PSO high level interface # PSO high level interface
def configure(self, d: dict={}) -> tuple: def configure(self, d: dict = {}) -> tuple:
""" Simplified configuration interface to access the most common """ Simplified configuration interface to access the most common
functionality for distance mode PSO. functionality for distance mode PSO.
:param distance: The trigger distance or the array of distances between subsequent points. :param distance: The trigger distance or the array of distances between subsequent points.
:param wmode: Waveform mode configuration, usually pulsed/toggled. :param wmode: Waveform mode configuration, usually pulsed/toggled.
""" """
distance = d['distance'] distance = d["distance"]
wmode = str(d['wmode']) wmode = str(d["wmode"])
t_pulse = float(d['t_pulse']) if 't_pulse' in d else 100 t_pulse = float(d["t_pulse"]) if "t_pulse" in d else 100
w_pulse = float(d['w_pulse']) if 'w_pulse' in d else 200 w_pulse = float(d["w_pulse"]) if "w_pulse" in d else 200
n_pulse = float(d['n_pulse']) if 'n_pulse' in d else 1 n_pulse = float(d["n_pulse"]) if "n_pulse" in d else 1
# Validate input parameters # Validate input parameters
if wmode not in ["pulse", "pulsed", "toggle", "toggled"]: if wmode not in ["pulse", "pulsed", "toggle", "toggled"]:
@ -896,7 +1113,7 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
def complete(self, settle_time=0.1) -> DeviceStatus: def complete(self, settle_time=0.1) -> DeviceStatus:
""" DDC just reads back whatever is available in the buffers""" """ DDC just reads back whatever is available in the buffers"""
sleep(settle_time) sleep(settle_time)
status = DeviceStatus(self) status = DeviceStatus(self)
status.set_finished() status.set_finished()
return status return status
@ -908,11 +1125,14 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
self.dstEventsEna.set("Off").wait() self.dstEventsEna.set("Off").wait()
self.dstCounterEna.set("Off").wait() self.dstCounterEna.set("Off").wait()
return super().unstage() return super().unstage()
# ######################################################################## # ########################################################################
# Bluesky flyer interface # Bluesky flyer interface
def kickoff(self) -> DeviceStatus: def kickoff(self) -> DeviceStatus:
# Rearm the configured array # Rearm the configured array
if hasattr(self, "_distanceValue") and isinstance(self._distanceValue, (np.ndarray, list, tuple)): if hasattr(self, "_distanceValue") and isinstance(
self._distanceValue, (np.ndarray, list, tuple)
):
self.dstArrayRearm.set(1).wait() self.dstArrayRearm.set(1).wait()
# Start monitoring the counters # Start monitoring the counters
self.dstEventsEna.set("On").wait() self.dstEventsEna.set("On").wait()
@ -925,18 +1145,21 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
def complete(self) -> DeviceStatus: def complete(self) -> DeviceStatus:
""" Bluesky flyer interface""" """ Bluesky flyer interface"""
# Array mode waits until the buffer is empty # Array mode waits until the buffer is empty
if hasattr(self, "_distanceValue") and isinstance(self._distanceValue, (np.ndarray, list, tuple)): if hasattr(self, "_distanceValue") and isinstance(
self._distanceValue, (np.ndarray, list, tuple)
):
# Define wait until the busy flag goes down (excluding initial update) # Define wait until the busy flag goes down (excluding initial update)
timestamp_ = 0 timestamp_ = 0
def notRunning(*args, old_value, value, timestamp, **kwargs): def notRunning(*args, old_value, value, timestamp, **kwargs):
nonlocal timestamp_ nonlocal timestamp_
result = False if (timestamp_== 0) else bool(int(value) & 0x1000) result = False if (timestamp_ == 0) else bool(int(value) & 0x1000)
print(f"Old {old_value}\tNew: {value}\tResult: {result}") print(f"Old {old_value}\tNew: {value}\tResult: {result}")
timestamp_ = timestamp timestamp_ = timestamp
return result return result
# Subscribe and wait for update # Subscribe and wait for update
#status = SubscriptionStatus(self.status, notRunning, settle_time=0.5) # status = SubscriptionStatus(self.status, notRunning, settle_time=0.5)
# Data capture can be stopped any time # Data capture can be stopped any time
status = DeviceStatus(self) status = DeviceStatus(self)
status.set_finished() status.set_finished()
@ -948,18 +1171,23 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
def describe_collect(self) -> OrderedDict: def describe_collect(self) -> OrderedDict:
ret = OrderedDict() ret = OrderedDict()
ret['index'] = {'source': "internal", 'dtype': 'integer', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0} ret["index"] = {
"source": "internal",
"dtype": "integer",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
return {self.name: ret} return {self.name: ret}
def collect(self) -> OrderedDict: def collect(self) -> OrderedDict:
ret = OrderedDict() ret = OrderedDict()
ret["timestamps"] = {"index": time.time()} ret["timestamps"] = {"index": time.time()}
ret["data"] = {"index": self.dstCounterVal.value } ret["data"] = {"index": self.dstCounterVal.value}
yield ret yield ret
class aa1AxisPsoWindow(aa1AxisPsoBase): class aa1AxisPsoWindow(aa1AxisPsoBase):
""" Position Sensitive Output - Window mode """ Position Sensitive Output - Window mode
@ -979,27 +1207,46 @@ class aa1AxisPsoWindow(aa1AxisPsoBase):
For a more detailed description of additional signals and masking plase For a more detailed description of additional signals and masking plase
refer to Automation1's online manual. refer to Automation1's online manual.
""" """
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
""" __init__ MUST have a full argument list""" """ __init__ MUST have a full argument list"""
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs) super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._mode = "output" self._mode = "output"
self._eventMode = "Enter" self._eventMode = "Enter"
# ######################################################################## # ########################################################################
# PSO high level interface # PSO high level interface
def configure(self, d: dict={}) -> tuple: def configure(self, d: dict = {}) -> tuple:
""" Simplified configuration interface to access the most common """ Simplified configuration interface to access the most common
functionality for distance mode PSO. functionality for distance mode PSO.
:param distance: The trigger distance or the array of distances between subsequent points. :param distance: The trigger distance or the array of distances between subsequent points.
:param wmode: Waveform mode configuration, usually output/pulsed/toggled. :param wmode: Waveform mode configuration, usually output/pulsed/toggled.
""" """
bounds = d['distance'] bounds = d["distance"]
wmode = str(d['wmode']) wmode = str(d["wmode"])
emode = str(d['emode']) emode = str(d["emode"])
t_pulse = float(d['t_pulse']) if 't_pulse' in d else None t_pulse = float(d["t_pulse"]) if "t_pulse" in d else None
w_pulse = float(d['w_pulse']) if 'w_pulse' in d else None w_pulse = float(d["w_pulse"]) if "w_pulse" in d else None
n_pulse = float(d['n_pulse']) if 'n_pulse' in d else None n_pulse = float(d["n_pulse"]) if "n_pulse" in d else None
# Validate input parameters # Validate input parameters
if wmode not in ["pulse", "pulsed", "toggle", "toggled", "output", "flag"]: if wmode not in ["pulse", "pulsed", "toggle", "toggled", "output", "flag"]:
@ -1080,11 +1327,6 @@ class aa1AxisPsoWindow(aa1AxisPsoBase):
return super().unstage() return super().unstage()
class aa1AxisDriveDataCollection(Device): class aa1AxisDriveDataCollection(Device):
""" Axis data collection """ Axis data collection
@ -1125,29 +1367,50 @@ class aa1AxisDriveDataCollection(Device):
SUB_PROGRESS = "progress" SUB_PROGRESS = "progress"
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs): def __init__(
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs) self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self.subscribe(self._progress_update, "progress", run=False) self.subscribe(self._progress_update, "progress", run=False)
def _progress_update(self, value, **kwargs) -> None: def _progress_update(self, value, **kwargs) -> None:
"""Progress update on the scan""" """Progress update on the scan"""
if self.state.value not in (2, "Acquiring"): if self.state.value not in (2, "Acquiring"):
self._run_subs( sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1, ) self._run_subs(
sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1,
)
return return
progress = 1 progress = 1
max_value = 1 max_value = 1
self._run_subs( self._run_subs(
sub_type=self.SUB_PROGRESS, sub_type=self.SUB_PROGRESS,
value=int(progress), max_value=max_value, done=int(np.isclose(max_value, progress, 1e-3)), ) value=int(progress),
max_value=max_value,
done=int(np.isclose(max_value, progress, 1e-3)),
)
def configure(self, d: dict = {}) -> tuple:
npoints = int(d["npoints"])
def configure(self, d: dict={}) -> tuple: trigger = int(d["trigger"]) if "trigger" in d else DriveDataCaptureTrigger.PsoOutput
npoints = int(d['npoints']) source0 = int(d["source0"]) if "source0" in d else DriveDataCaptureInput.PrimaryFeedback
trigger = int(d['trigger']) if 'trigger' in d else DriveDataCaptureTrigger.PsoOutput source1 = int(d["source1"]) if "source1" in d else DriveDataCaptureInput.PositionCommand
source0 = int(d['source0']) if 'source0' in d else DriveDataCaptureInput.PrimaryFeedback
source1 = int(d['source1']) if 'source1' in d else DriveDataCaptureInput.PositionCommand
old = self.read_configuration() old = self.read_configuration()
@ -1180,7 +1443,7 @@ class aa1AxisDriveDataCollection(Device):
def complete(self, settle_time=0.1) -> DeviceStatus: def complete(self, settle_time=0.1) -> DeviceStatus:
""" DDC just reads back whatever is available in the buffers""" """ DDC just reads back whatever is available in the buffers"""
sleep(settle_time) sleep(settle_time)
status = DeviceStatus(self) status = DeviceStatus(self)
status.set_finished() status.set_finished()
return status return status
@ -1194,17 +1457,18 @@ class aa1AxisDriveDataCollection(Device):
# Define wait until the busy flag goes down (excluding initial update) # Define wait until the busy flag goes down (excluding initial update)
timestamp_ = 0 timestamp_ = 0
def negEdge(*args, old_value, value, timestamp, **kwargs): def negEdge(*args, old_value, value, timestamp, **kwargs):
nonlocal timestamp_ nonlocal timestamp_
result = False if (timestamp_== 0) else (old_value == 1 and value == 0) result = False if (timestamp_ == 0) else (old_value == 1 and value == 0)
# print(f"\nBuffer1 status:\t{old_value} ({timestamp_}) to {value} ({timestamp}) Result: {result}") # print(f"\nBuffer1 status:\t{old_value} ({timestamp_}) to {value} ({timestamp}) Result: {result}")
timestamp_ = timestamp timestamp_ = timestamp
return result return result
if index==0: if index == 0:
status = SubscriptionStatus(self._readstatus0, negEdge, settle_time=0.5) status = SubscriptionStatus(self._readstatus0, negEdge, settle_time=0.5)
self._readback0.set(1).wait() self._readback0.set(1).wait()
elif index==1: elif index == 1:
status = SubscriptionStatus(self._readstatus1, negEdge, settle_time=0.5) status = SubscriptionStatus(self._readstatus1, negEdge, settle_time=0.5)
self._readback1.set(1).wait() self._readback1.set(1).wait()
@ -1212,11 +1476,24 @@ class aa1AxisDriveDataCollection(Device):
status.wait() status.wait()
return status return status
def describe_collect(self) -> OrderedDict: def describe_collect(self) -> OrderedDict:
ret = OrderedDict() ret = OrderedDict()
ret['buffer0'] = {'source': "internal", 'dtype': 'array', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0} ret["buffer0"] = {
ret['buffer1'] = {'source': "internal", 'dtype': 'array', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0} "source": "internal",
"dtype": "array",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
ret["buffer1"] = {
"source": "internal",
"dtype": "array",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
return {self.name: ret} return {self.name: ret}
def collect(self) -> OrderedDict: def collect(self) -> OrderedDict:
@ -1227,29 +1504,23 @@ class aa1AxisDriveDataCollection(Device):
b0 = self._buffer0.value b0 = self._buffer0.value
b1 = self._buffer1.value b1 = self._buffer1.value
ret = OrderedDict() ret = OrderedDict()
ret["timestamps"] = {"buffer0": time.time(), "buffer1": time.time() } ret["timestamps"] = {"buffer0": time.time(), "buffer1": time.time()}
ret["data"] = {"buffer0": b0, "buffer1": b1 } ret["data"] = {"buffer0": b0, "buffer1": b1}
yield ret yield ret
# Automatically start simulation if directly invoked # Automatically start simulation if directly invoked
if __name__ == "__main__": if __name__ == "__main__":
AA1_IOC_NAME = "X02DA-ES1-SMP1" AA1_IOC_NAME = "X02DA-ES1-SMP1"
AA1_AXIS_NAME = "ROTY" AA1_AXIS_NAME = "ROTY"
# Drive data collection # Drive data collection
task = aa1Tasks(AA1_IOC_NAME+":TASK:", name="tsk") task = aa1Tasks(AA1_IOC_NAME + ":TASK:", name="tsk")
task.wait_for_connection() task.wait_for_connection()
task.describe() task.describe()
ddc = aa1AxisDriveDataCollection("X02DA-ES1-SMP1:ROTY:DDC:", name="ddc") ddc = aa1AxisDriveDataCollection("X02DA-ES1-SMP1:ROTY:DDC:", name="ddc")
ddc.wait_for_connection() ddc.wait_for_connection()
globb = aa1GlobalVariableBindings(AA1_IOC_NAME+":VAR:", name="globb") globb = aa1GlobalVariableBindings(AA1_IOC_NAME + ":VAR:", name="globb")
globb.wait_for_connection() globb.wait_for_connection()
globb.describe() globb.describe()
mot = EpicsMotor(AA1_IOC_NAME+ ":" + AA1_AXIS_NAME, name="x") mot = EpicsMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x")
mot.wait_for_connection() mot.wait_for_connection()

View File

@ -272,232 +272,230 @@ class AxisDataSignal:
class TaskDataSignal: class TaskDataSignal:
ProgramLineNumber = 17 ProgramLineNumber = 17
CoordinatedFlags = 40 CoordinatedFlags = 40
CoordinatedArcStartAngle = 53 CoordinatedArcStartAngle = 53
CoordinatedArcEndAngle = 54 CoordinatedArcEndAngle = 54
CoordinatedArcRadius = 55 CoordinatedArcRadius = 55
CoordinatedArcRadiusError = 56 CoordinatedArcRadiusError = 56
CoordinatedPositionCommand = 57 CoordinatedPositionCommand = 57
CoordinatedSpeedCommand = 58 CoordinatedSpeedCommand = 58
CoordinatedAccelerationCommand = 59 CoordinatedAccelerationCommand = 59
CoordinatedTotalDistance = 60 CoordinatedTotalDistance = 60
CoordinatedPercentDone = 61 CoordinatedPercentDone = 61
CoordinatedPositionCommandBackwardsDiff = 62 CoordinatedPositionCommandBackwardsDiff = 62
TaskParameter = 69 TaskParameter = 69
TaskError = 70 TaskError = 70
TaskWarning = 71 TaskWarning = 71
CoordinatedSpeedTargetActual = 86 CoordinatedSpeedTargetActual = 86
DependentCoordinatedSpeedTargetActual = 87 DependentCoordinatedSpeedTargetActual = 87
ActiveFixtureOffset = 88 ActiveFixtureOffset = 88
TaskStatus0 = 90 TaskStatus0 = 90
TaskStatus1 = 91 TaskStatus1 = 91
TaskStatus2 = 92 TaskStatus2 = 92
SpindleSpeedTarget = 93 SpindleSpeedTarget = 93
CoordinateSystem1I = 96 CoordinateSystem1I = 96
CoordinateSystem1J = 97 CoordinateSystem1J = 97
CoordinateSystem1K = 98 CoordinateSystem1K = 98
CoordinateSystem1Plane = 99 CoordinateSystem1Plane = 99
ToolNumberActive = 100 ToolNumberActive = 100
Mfo = 101 Mfo = 101
CoordinatedSpeedTarget = 102 CoordinatedSpeedTarget = 102
DependentCoordinatedSpeedTarget = 103 DependentCoordinatedSpeedTarget = 103
CoordinatedAccelerationRate = 104 CoordinatedAccelerationRate = 104
CoordinatedDecelerationRate = 105 CoordinatedDecelerationRate = 105
CoordinatedAccelerationTime = 106 CoordinatedAccelerationTime = 106
CoordinatedDecelerationTime = 107 CoordinatedDecelerationTime = 107
TaskMode = 108 TaskMode = 108
TaskState = 117 TaskState = 117
TaskStateInternal = 118 TaskStateInternal = 118
ExecutionMode = 121 ExecutionMode = 121
EnableAlignmentAxes = 127 EnableAlignmentAxes = 127
CoordinatedGalvoLaserOutput = 133 CoordinatedGalvoLaserOutput = 133
CoordinatedMotionRate = 145 CoordinatedMotionRate = 145
CoordinatedTaskCommand = 146 CoordinatedTaskCommand = 146
EnableState = 166 EnableState = 166
LookaheadMovesExamined = 200 LookaheadMovesExamined = 200
ProfileControlMask = 231 ProfileControlMask = 231
CoordinatedArcRadiusReciprocal = 253 CoordinatedArcRadiusReciprocal = 253
MotionEngineStage = 254 MotionEngineStage = 254
CoordinatedTimeScale = 256 CoordinatedTimeScale = 256
CoordinatedTimeScaleDerivative = 257 CoordinatedTimeScaleDerivative = 257
IfovSpeedScale = 266 IfovSpeedScale = 266
IfovSpeedScaleAverage = 267 IfovSpeedScaleAverage = 267
IfovGenerationFrameCounter = 268 IfovGenerationFrameCounter = 268
IfovGenerationTimeOriginal = 269 IfovGenerationTimeOriginal = 269
IfovGenerationTimeModified = 270 IfovGenerationTimeModified = 270
IfovCoordinatedPositionCommand = 271 IfovCoordinatedPositionCommand = 271
IfovCoordinatedSpeedCommand = 272 IfovCoordinatedSpeedCommand = 272
IfovCenterPointH = 276 IfovCenterPointH = 276
IfovCenterPointV = 277 IfovCenterPointV = 277
IfovTrajectoryCount = 278 IfovTrajectoryCount = 278
IfovTrajectoryIndex = 279 IfovTrajectoryIndex = 279
IfovAttemptCode = 280 IfovAttemptCode = 280
IfovGenerationFrameIndex = 281 IfovGenerationFrameIndex = 281
IfovMaximumVelocity = 282 IfovMaximumVelocity = 282
IfovIdealVelocity = 283 IfovIdealVelocity = 283
TaskInternalDebug = 284 TaskInternalDebug = 284
IfovCoordinatedAccelerationCommand = 285 IfovCoordinatedAccelerationCommand = 285
IfovFovPositionH = 286 IfovFovPositionH = 286
IfovFovPositionV = 287 IfovFovPositionV = 287
IfovFovDimensionH = 288 IfovFovDimensionH = 288
IfovFovDimensionV = 289 IfovFovDimensionV = 289
MotionBufferElements = 311 MotionBufferElements = 311
MotionBufferMoves = 312 MotionBufferMoves = 312
MotionLineNumber = 313 MotionLineNumber = 313
MotionBufferRetraceMoves = 314 MotionBufferRetraceMoves = 314
MotionBufferRetraceElements = 315 MotionBufferRetraceElements = 315
MotionBufferIndex = 316 MotionBufferIndex = 316
MotionBufferIndexLookahead = 317 MotionBufferIndexLookahead = 317
MotionBufferProcessingBlocked = 318 MotionBufferProcessingBlocked = 318
ActiveMoveValid = 319 ActiveMoveValid = 319
TaskExecutionLines = 320 TaskExecutionLines = 320
SchedulerTaskHolds = 321 SchedulerTaskHolds = 321
SchedulerProgramLoopRuns = 322 SchedulerProgramLoopRuns = 322
SchedulerTaskBlocked = 323 SchedulerTaskBlocked = 323
CriticalSectionsActive = 324 CriticalSectionsActive = 324
AxesSlowdownReason = 331 AxesSlowdownReason = 331
TaskExecutionTime = 333 TaskExecutionTime = 333
TaskExecutionTimeMaximum = 334 TaskExecutionTimeMaximum = 334
TaskExecutionLinesMaximum = 335 TaskExecutionLinesMaximum = 335
LookaheadDecelReason = 338 LookaheadDecelReason = 338
LookaheadDecelMoves = 339 LookaheadDecelMoves = 339
LookaheadDecelDistance = 340 LookaheadDecelDistance = 340
ProgramCounter = 341 ProgramCounter = 341
StackPointer = 342 StackPointer = 342
FramePointer = 343 FramePointer = 343
StringStackPointer = 344 StringStackPointer = 344
ProgramLineNumberSourceFileId = 349 ProgramLineNumberSourceFileId = 349
MotionLineNumberSourceFileId = 350 MotionLineNumberSourceFileId = 350
ProgramLineNumberSourcePathId = 351 ProgramLineNumberSourcePathId = 351
MotionLineNumberSourcePathId = 352 MotionLineNumberSourcePathId = 352
StringArgumentStackPointer = 354 StringArgumentStackPointer = 354
CoordinatedAccelerationSCurvePercentage = 369 CoordinatedAccelerationSCurvePercentage = 369
CoordinatedDecelerationSCurvePercentage = 370 CoordinatedDecelerationSCurvePercentage = 370
DependentCoordinatedAccelerationRate = 373 DependentCoordinatedAccelerationRate = 373
DependentCoordinatedDecelerationRate = 374 DependentCoordinatedDecelerationRate = 374
CriticalSectionTimeout = 375 CriticalSectionTimeout = 375
CommandQueueCapacity = 421 CommandQueueCapacity = 421
CommandQueueUnexecutedCount = 422 CommandQueueUnexecutedCount = 422
CommandQueueTimesEmptied = 423 CommandQueueTimesEmptied = 423
CommandQueueExecutedCount = 424 CommandQueueExecutedCount = 424
class SystemDataSignal: class SystemDataSignal:
VirtualBinaryInput = 46 VirtualBinaryInput = 46
VirtualBinaryOutput = 47 VirtualBinaryOutput = 47
VirtualRegisterInput = 48 VirtualRegisterInput = 48
VirtualRegisterOutput = 49 VirtualRegisterOutput = 49
Timer = 51 Timer = 51
TimerPerformance = 52 TimerPerformance = 52
GlobalReal = 67 GlobalReal = 67
CommunicationRealTimeErrors = 81 CommunicationRealTimeErrors = 81
LibraryCommand = 119 LibraryCommand = 119
DataCollectionSampleTime = 120 DataCollectionSampleTime = 120
DataCollectionSampleIndex = 129 DataCollectionSampleIndex = 129
ModbusClientConnected = 134 ModbusClientConnected = 134
ModbusServerConnected = 135 ModbusServerConnected = 135
ModbusClientError = 136 ModbusClientError = 136
ModbusServerError = 137 ModbusServerError = 137
StopWatchTimer = 157 StopWatchTimer = 157
ScopetrigId = 163 ScopetrigId = 163
EstimatedProcessorUsage = 177 EstimatedProcessorUsage = 177
DataCollectionStatus = 188 DataCollectionStatus = 188
SignalLogState = 198 SignalLogState = 198
SafeZoneViolationMask = 207 SafeZoneViolationMask = 207
SafeZoneActiveMask = 229 SafeZoneActiveMask = 229
ModbusClientInputWords = 240 ModbusClientInputWords = 240
ModbusClientOutputWords = 241 ModbusClientOutputWords = 241
ModbusClientInputBits = 242 ModbusClientInputBits = 242
ModbusClientOutputBits = 243 ModbusClientOutputBits = 243
ModbusClientOutputBitsStatus = 244 ModbusClientOutputBitsStatus = 244
ModbusClientOutputWordsStatus = 245 ModbusClientOutputWordsStatus = 245
ModbusServerInputWords = 246 ModbusServerInputWords = 246
ModbusServerOutputWords = 247 ModbusServerOutputWords = 247
ModbusServerInputBits = 248 ModbusServerInputBits = 248
ModbusServerOutputBits = 249 ModbusServerOutputBits = 249
SystemParameter = 265 SystemParameter = 265
ThermoCompSensorTemperature = 305 ThermoCompSensorTemperature = 305
ThermoCompControllingTemperature = 306 ThermoCompControllingTemperature = 306
ThermoCompCompensatingTemperature = 307 ThermoCompCompensatingTemperature = 307
ThermoCompStatus = 308 ThermoCompStatus = 308
GlobalInteger = 345 GlobalInteger = 345
AliveAxesMask = 348 AliveAxesMask = 348
SignalLogPointsStored = 377 SignalLogPointsStored = 377
ControllerInitializationWarning = 379 ControllerInitializationWarning = 379
StopWatchTimerMin = 416 StopWatchTimerMin = 416
StopWatchTimerMax = 417 StopWatchTimerMax = 417
StopWatchTimerAvg = 418 StopWatchTimerAvg = 418
EthercatEnabled = 428 EthercatEnabled = 428
EthercatError = 429 EthercatError = 429
EthercatTxPdo = 430 EthercatTxPdo = 430
EthercatTxPdoSize = 431 EthercatTxPdoSize = 431
EthercatRxPdo = 432 EthercatRxPdo = 432
EthercatRxPdoSize = 433 EthercatRxPdoSize = 433
EthercatState = 437 EthercatState = 437
ModbusClientEnabled = 438 ModbusClientEnabled = 438
ModbusServerEnabled = 439 ModbusServerEnabled = 439
class DataCollectionFrequency: class DataCollectionFrequency:
Undefined = 0 Undefined = 0
Fixed1kHz = 1 Fixed1kHz = 1
Fixed10kHz = 2 Fixed10kHz = 2
Fixed20kHz = 3 Fixed20kHz = 3
Fixed100kHz = 4 Fixed100kHz = 4
Fixed200kHz = 5 Fixed200kHz = 5
class DataCollectionMode: class DataCollectionMode:
Snapshot = 0 Snapshot = 0
Continouous = 1 Continouous = 1
# Specifies the PSO distance input settings for the XC4e drive. # Specifies the PSO distance input settings for the XC4e drive.
class PsoDistanceInput: class PsoDistanceInput:
XC4PrimaryFeedback = 130 XC4PrimaryFeedback = 130
XC4AuxiliaryFeedback = 131 XC4AuxiliaryFeedback = 131
XC4SyncPortA = 132 XC4SyncPortA = 132
XC4SyncPortB = 133 XC4SyncPortB = 133
XC4DrivePulseStream = 134 XC4DrivePulseStream = 134
XC4ePrimaryFeedback = 135 XC4ePrimaryFeedback = 135
XC4eAuxiliaryFeedback = 136 XC4eAuxiliaryFeedback = 136
XC4eSyncPortA = 137 XC4eSyncPortA = 137
XC4eSyncPortB = 138 XC4eSyncPortB = 138
XC4eDrivePulseStream = 139 XC4eDrivePulseStream = 139
class PsoWindowInput: class PsoWindowInput:
XC4PrimaryFeedback = 130 XC4PrimaryFeedback = 130
XC4AuxiliaryFeedback = 131 XC4AuxiliaryFeedback = 131
XC4SyncPortA = 132 XC4SyncPortA = 132
XC4SyncPortB = 133 XC4SyncPortB = 133
XC4DrivePulseStream = 134 XC4DrivePulseStream = 134
XC4ePrimaryFeedback = 135 XC4ePrimaryFeedback = 135
XC4eAuxiliaryFeedback = 136 XC4eAuxiliaryFeedback = 136
XC4eSyncPortA = 137 XC4eSyncPortA = 137
XC4eSyncPortB = 138 XC4eSyncPortB = 138
XC4eDrivePulseStream = 139 XC4eDrivePulseStream = 139
XL5ePrimaryFeedback = 145, XL5ePrimaryFeedback = (145,)
XL5eAuxiliaryFeedback = 146, XL5eAuxiliaryFeedback = (146,)
XL5eSyncPortA = 147, XL5eSyncPortA = (147,)
XL5eSyncPortB = 148, XL5eSyncPortB = (148,)
XL5eDrivePulseStream = 149, XL5eDrivePulseStream = (149,)
# @brief Specifies the PSO output pin settings for each drive. # @brief Specifies the PSO output pin settings for each drive.
class XC4ePsoOutputPin: class XC4ePsoOutputPin:
DedicatedOutput = 111 DedicatedOutput = 111
AuxiliaryMarkerDifferential = 112 AuxiliaryMarkerDifferential = 112
AuxiliaryMarkerSingleEnded = 113 AuxiliaryMarkerSingleEnded = 113
class XC4PsoOutputPin: class XC4PsoOutputPin:
DedicatedOutput = 108 DedicatedOutput = 108
AuxiliaryMarkerDifferential = 109 AuxiliaryMarkerDifferential = 109
AuxiliaryMarkerSingleEnded = 110 AuxiliaryMarkerSingleEnded = 110
""" """
@ -834,81 +832,70 @@ class Automation1PsoOutputPin:
class DriveDataCaptureInput: class DriveDataCaptureInput:
PositionCommand = 0 PositionCommand = 0
PrimaryFeedback = 1 PrimaryFeedback = 1
AuxiliaryFeedback = 2 AuxiliaryFeedback = 2
AnalogInput0 = 3 AnalogInput0 = 3
AnalogInput1 = 4 AnalogInput1 = 4
AnalogInput2 = 5 AnalogInput2 = 5
AnalogInput3 = 6 AnalogInput3 = 6
class DriveDataCaptureTrigger: class DriveDataCaptureTrigger:
PsoOutput = 0 PsoOutput = 0
PsoEvent = 1 PsoEvent = 1
HighSpeedInput0RisingEdge = 2 HighSpeedInput0RisingEdge = 2
HighSpeedInput0FallingEdge = 3 HighSpeedInput0FallingEdge = 3
HighSpeedInput1RisingEdge = 4 HighSpeedInput1RisingEdge = 4
HighSpeedInput1FallingEdge = 5 HighSpeedInput1FallingEdge = 5
AuxiliaryMarkerRisingEdge = 6 AuxiliaryMarkerRisingEdge = 6
AuxiliaryMarkerFallingEdge = 7 AuxiliaryMarkerFallingEdge = 7
class PsoOutputPin: class PsoOutputPin:
GL4None = 100, GL4None = (100,)
GL4LaserOutput0 = 101, GL4LaserOutput0 = (101,)
XL4sNone = 102, XL4sNone = (102,)
XL4sLaserOutput0 = 103, XL4sLaserOutput0 = (103,)
XR3None = 104, XR3None = (104,)
XR3PsoOutput1 = 105, XR3PsoOutput1 = (105,)
XR3PsoOutput2 = 106, XR3PsoOutput2 = (106,)
XR3PsoOutput3 = 107, XR3PsoOutput3 = (107,)
XC4DedicatedOutput = 108, XC4DedicatedOutput = (108,)
XC4AuxiliaryMarkerDifferential = 109, XC4AuxiliaryMarkerDifferential = (109,)
XC4AuxiliaryMarkerSingleEnded = 110, XC4AuxiliaryMarkerSingleEnded = (110,)
XC4eDedicatedOutput = 111, XC4eDedicatedOutput = (111,)
XC4eAuxiliaryMarkerDifferential = 112, XC4eAuxiliaryMarkerDifferential = (112,)
XC4eAuxiliaryMarkerSingleEnded = 113, XC4eAuxiliaryMarkerSingleEnded = (113,)
XC6eDedicatedOutput = 114, XC6eDedicatedOutput = (114,)
XC6eAuxiliaryMarkerDifferential = 115, XC6eAuxiliaryMarkerDifferential = (115,)
XC6eAuxiliaryMarkerSingleEnded = 116, XC6eAuxiliaryMarkerSingleEnded = (116,)
XL5eDedicatedOutput = 117, XL5eDedicatedOutput = (117,)
XL5eAuxiliaryMarkerDifferential = 118, XL5eAuxiliaryMarkerDifferential = (118,)
XL5eAuxiliaryMarkerSingleEnded = 119, XL5eAuxiliaryMarkerSingleEnded = (119,)
XC2DedicatedOutput = 120, XC2DedicatedOutput = (120,)
XC2eDedicatedOutput = 121, XC2eDedicatedOutput = (121,)
XL2eDedicatedOutput = 122, XL2eDedicatedOutput = (122,)
XI4DedicatedOutput = 123, XI4DedicatedOutput = (123,)
iXC4DedicatedOutput = 124, iXC4DedicatedOutput = (124,)
iXC4AuxiliaryMarkerDifferential = 125, iXC4AuxiliaryMarkerDifferential = (125,)
iXC4AuxiliaryMarkerSingleEnded = 126, iXC4AuxiliaryMarkerSingleEnded = (126,)
iXC4eDedicatedOutput = 127, iXC4eDedicatedOutput = (127,)
iXC4eAuxiliaryMarkerDifferential = 128, iXC4eAuxiliaryMarkerDifferential = (128,)
iXC4eAuxiliaryMarkerSingleEnded = 129, iXC4eAuxiliaryMarkerSingleEnded = (129,)
iXC6eDedicatedOutput = 130, iXC6eDedicatedOutput = (130,)
iXC6eAuxiliaryMarkerDifferential = 131, iXC6eAuxiliaryMarkerDifferential = (131,)
iXC6eAuxiliaryMarkerSingleEnded = 132, iXC6eAuxiliaryMarkerSingleEnded = (132,)
iXL5eDedicatedOutput = 133, iXL5eDedicatedOutput = (133,)
iXL5eAuxiliaryMarkerDifferential = 134, iXL5eAuxiliaryMarkerDifferential = (134,)
iXL5eAuxiliaryMarkerSingleEnded = 135, iXL5eAuxiliaryMarkerSingleEnded = (135,)
iXR3None = 136, iXR3None = (136,)
iXR3PsoOutput1 = 137, iXR3PsoOutput1 = (137,)
iXR3PsoOutput2 = 138, iXR3PsoOutput2 = (138,)
iXR3PsoOutput3 = 139, iXR3PsoOutput3 = (139,)
GI4None = 140, GI4None = (140,)
GI4LaserOutput0 = 141, GI4LaserOutput0 = (141,)
iXC2DedicatedOutput = 142, iXC2DedicatedOutput = (142,)
iXC2eDedicatedOutput = 143, iXC2eDedicatedOutput = (143,)
iXL2eDedicatedOutput = 144, iXL2eDedicatedOutput = (144,)
iXI4DedicatedOutput = 145, iXI4DedicatedOutput = (145,)