SnapNStep works, Sequence fails on Aerotech axis

This commit is contained in:
gac-x05la
2025-02-14 17:39:36 +01:00
parent d1e072b8d9
commit c3cf12b8e2
9 changed files with 109 additions and 163 deletions

View File

@@ -64,18 +64,18 @@ es1_roty:
# readoutPriority: monitored # readoutPriority: monitored
# softwareTrigger: false # softwareTrigger: false
# es1_tasks: es1_tasks:
# description: 'Automation1 task management interface' description: 'Automation1 task management interface'
# deviceClass: tomcat_bec.devices.aa1Tasks deviceClass: tomcat_bec.devices.aa1Tasks
# deviceConfig: deviceConfig:
# prefix: 'X02DA-ES1-SMP1:TASK:' prefix: 'X02DA-ES1-SMP1:TASK:'
# deviceTags: deviceTags:
# - es1 - es1
# enabled: true enabled: true
# onFailure: buffer onFailure: buffer
# readOnly: false readOnly: false
# readoutPriority: monitored readoutPriority: monitored
# softwareTrigger: false softwareTrigger: false
# es1_psod: # es1_psod:
@@ -92,18 +92,18 @@ es1_roty:
# softwareTrigger: true # softwareTrigger: true
# es1_ddaq: es1_ddaq:
# description: 'Automation1 position recording interface' description: 'Automation1 position recording interface'
# deviceClass: tomcat_bec.devices.aa1AxisDriveDataCollection deviceClass: tomcat_bec.devices.aa1AxisDriveDataCollection
# deviceConfig: deviceConfig:
# prefix: 'X02DA-ES1-SMP1:ROTY:DDC:' prefix: 'X02DA-ES1-SMP1:ROTY:DDC:'
# deviceTags: deviceTags:
# - es1 - es1
# enabled: true enabled: true
# onFailure: buffer onFailure: buffer
# readOnly: false readOnly: false
# readoutPriority: monitored readoutPriority: monitored
# softwareTrigger: false softwareTrigger: false
#camera: #camera:
@@ -152,7 +152,7 @@ gfdaq:
readoutPriority: monitored readoutPriority: monitored
softwareTrigger: false softwareTrigger: false
daq_stream0: gf_stream0:
description: stdDAQ preview (2 every 555) description: stdDAQ preview (2 every 555)
deviceClass: tomcat_bec.devices.StdDaqPreviewDetector deviceClass: tomcat_bec.devices.StdDaqPreviewDetector
deviceConfig: deviceConfig:
@@ -166,21 +166,6 @@ daq_stream0:
readoutPriority: monitored readoutPriority: monitored
softwareTrigger: false softwareTrigger: false
daq_stream1:
description: stdDAQ preview (1 at 5 Hz)
deviceClass: tomcat_bec.devices.StdDaqPreviewDetector
deviceConfig:
url: 'tcp://129.129.95.111:20001'
deviceTags:
- std-daq
- gfcam
enabled: true
onFailure: buffer
readOnly: false
readoutPriority: monitored
softwareTrigger: false
pcocam: pcocam:
description: PCO.edge camera client description: PCO.edge camera client
deviceClass: tomcat_bec.devices.PcoEdge5M deviceClass: tomcat_bec.devices.PcoEdge5M

View File

@@ -36,19 +36,22 @@ class AerotechDriveDataCollectionMixin(CustomDeviceMixin):
# NOTE: Scans don't have to fully configure the device # NOTE: Scans don't have to fully configure the device
if "ddc_trigger" in scanargs: if "ddc_trigger" in scanargs:
d["ddc_trigger"] = scanargs["ddc_trigger"] d["ddc_trigger"] = scanargs["ddc_trigger"]
if "ddc_num_points" in scanargs:
if "ddc_num_points" in scanargs and scanargs["ddc_num_points"] is not None:
d["num_points_total"] = scanargs["ddc_num_points"] d["num_points_total"] = scanargs["ddc_num_points"]
elif "daq_num_points" in scanargs and scanargs["daq_num_points"] is not None:
d["num_points_total"] = scanargs["daq_num_points"]
else: else:
# Try to figure out number of points # Try to figure out number of points
num_points = 1 num_points = 1
points_valid = False points_valid = False
if "steps" in scanargs and scanargs['steps'] is not None: if "steps" in scanargs and scanargs["steps"] is not None:
num_points *= scanargs["steps"] num_points *= scanargs["steps"]
points_valid = True points_valid = True
elif "exp_burst" in scanargs and scanargs['exp_burst'] is not None: if "exp_burst" in scanargs and scanargs["exp_burst"] is not None:
num_points *= scanargs["exp_burst"] num_points *= scanargs["exp_burst"]
points_valid = True points_valid = True
elif "repeats" in scanargs and scanargs['repeats'] is not None: if "repeats" in scanargs and scanargs["repeats"] is not None:
num_points *= scanargs["repeats"] num_points *= scanargs["repeats"]
points_valid = True points_valid = True
if points_valid: if points_valid:
@@ -143,6 +146,10 @@ class aa1AxisDriveDataCollection(PSIDeviceBase):
"""Bluesky-style stage""" """Bluesky-style stage"""
self._switch.set("Start", settle_time=0.2).wait() self._switch.set("Start", settle_time=0.2).wait()
def blueunstage(self):
"""Bluesky-style unstage"""
self._switch.set("Stop", settle_time=0.2).wait()
def reset(self): def reset(self):
"""Reset incremental readback""" """Reset incremental readback"""
self._switch.set("ResetRB", settle_time=0.1).wait() self._switch.set("ResetRB", settle_time=0.1).wait()
@@ -170,6 +177,8 @@ class aa1AxisDriveDataCollection(PSIDeviceBase):
elif index == 1: elif index == 1:
status = SubscriptionStatus(self._readstatus1, neg_edge, settle_time=0.5) status = SubscriptionStatus(self._readstatus1, neg_edge, settle_time=0.5)
self._readback1.set(1).wait() self._readback1.set(1).wait()
else:
raise ValueError(f"[{self.name}] Invalid data acquisition channel {index}")
# Start asynchronous readback # Start asynchronous readback
status.wait() status.wait()

View File

@@ -34,7 +34,8 @@ program
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Internal parameters - dont use // Internal parameters - dont use
var $axis as axis = ROTY var $axis as axis = ROTY
var $ii as integer var $ii as integer
var $axisFaults as integer = 0
var $iDdcSafeSpace as integer = 4096 var $iDdcSafeSpace as integer = 4096
// Set acceleration // Set acceleration
@@ -126,7 +127,12 @@ program
if $eScanType == ScanType.POS || $eScanType == ScanType.NEG if $eScanType == ScanType.POS || $eScanType == ScanType.NEG
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0) PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan) MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis) WaitForMotionDone($axis)
$axisFaults = StatusGetAxisItem($axis, AxisDataSignal.AxisFault)
if $axisFaults
TaskSetError(TaskGetIndex(), "AxisFault on axis ROTY")
end
elseif $eScanType == ScanType.POSNEG || $eScanType == ScanType.NEGPOS elseif $eScanType == ScanType.POSNEG || $eScanType == ScanType.NEGPOS
for $ii = 0 to ($iNumRepeat-1) for $ii = 0 to ($iNumRepeat-1)
// Feedback on progress // Feedback on progress
@@ -134,11 +140,15 @@ program
if ($ii % 2) == 0 if ($ii % 2) == 0
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0) PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan) MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
elseif ($ii % 2) == 1 elseif ($ii % 2) == 1
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayNegAddr, $iPsoArrayNegSize, 0) PsoDistanceConfigureArrayDistances($axis, $iPsoArrayNegAddr, $iPsoArrayNegSize, 0)
MoveAbsolute($axis, $fPosStart, $fVelScan) MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis) end
WaitForMotionDone($axis)
$axisFaults = StatusGetAxisItem($axis, AxisDataSignal.AxisFault)
if $axisFaults
TaskSetError(TaskGetIndex(), "AxisFault on axis ROTY")
end end
Dwell(0.2) Dwell(0.2)
end end

View File

@@ -78,6 +78,7 @@ program
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
$iglobal[2] = $iNumSteps $iglobal[2] = $iNumSteps
for $ii = 0 to ($iNumSteps-1) for $ii = 0 to ($iNumSteps-1)
$rglobal[4] = $ii
MoveAbsolute($axis, $fStartPosition + $ii * $fStepSize, $fVelScan) MoveAbsolute($axis, $fStartPosition + $ii * $fStepSize, $fVelScan)
WaitForMotionDone($axis) WaitForMotionDone($axis)

View File

@@ -47,7 +47,7 @@ class AerotechTasksMixin(CustomDeviceMixin):
# Perform bluesky-style configuration # Perform bluesky-style configuration
if len(d) > 0: if len(d) > 0:
logger.warning(f"[{self.parent.name}] Configuring with:\n{d}") # logger.warning(f"[{self.parent.name}] Configuring with:\n{d}")
self.parent.configure(d=d) self.parent.configure(d=d)
# The actual staging # The actual staging
@@ -55,12 +55,16 @@ class AerotechTasksMixin(CustomDeviceMixin):
def on_unstage(self): def on_unstage(self):
"""Stop the currently selected task""" """Stop the currently selected task"""
self.parent.switch.set("Stop").wait() self.parent.blueunstage()
def on_stop(self): def on_stop(self):
"""Stop the currently selected task""" """Stop the currently selected task"""
self.parent.switch.set("Stop").wait() self.parent.switch.set("Stop").wait()
def on_kickoff(self):
"""Start execution of the selected task"""
self.parent.bluekickoff()
class aa1Tasks(PSIDeviceBase): class aa1Tasks(PSIDeviceBase):
"""Task management API """Task management API
@@ -146,6 +150,10 @@ class aa1Tasks(PSIDeviceBase):
raise RuntimeError("Failed to load task, please check the Aerotech IOC") raise RuntimeError("Failed to load task, please check the Aerotech IOC")
return status return status
def blueunstage(self):
"""Bluesky style unstage, stops execution"""
self.switch.set("Stop").wait()
def bluekickoff(self): def bluekickoff(self):
"""Bluesky style kickoff""" """Bluesky style kickoff"""
# Launch and check success # Launch and check success
@@ -155,6 +163,10 @@ class aa1Tasks(PSIDeviceBase):
raise RuntimeError("Failed to load task, please check the Aerotech IOC") raise RuntimeError("Failed to load task, please check the Aerotech IOC")
return status return status
def kickoff(self):
"""Missing kickoff, for real?"""
self.custom_prepare.on_kickoff()
########################################################################## ##########################################################################
# Bluesky flyer interface # Bluesky flyer interface
def complete(self) -> DeviceStatus: def complete(self) -> DeviceStatus:

View File

@@ -7,7 +7,7 @@ Created on Thu Jun 27 17:28:43 2024
@author: mohacsi_i @author: mohacsi_i
""" """
from time import sleep from time import sleep
from ophyd import Signal, SignalRO, Component, EpicsSignal, EpicsSignalRO, Kind, DeviceStatus from ophyd import Signal, Component, EpicsSignal, EpicsSignalRO, Kind, DeviceStatus
from ophyd.device import DynamicDeviceComponent from ophyd.device import DynamicDeviceComponent
from ophyd_devices.interfaces.base_classes.psi_detector_base import ( from ophyd_devices.interfaces.base_classes.psi_detector_base import (
CustomDetectorMixin, CustomDetectorMixin,
@@ -174,6 +174,10 @@ class GigaFrostCameraMixin(CustomDetectorMixin):
d["image_height"] = scanargs["image_height"] d["image_height"] = scanargs["image_height"]
if "exp_time" in scanargs and scanargs["exp_time"] is not None: if "exp_time" in scanargs and scanargs["exp_time"] is not None:
d["exposure_time_ms"] = scanargs["exp_time"] d["exposure_time_ms"] = scanargs["exp_time"]
if "acq_time" in scanargs and scanargs["acq_time"] is not None:
d["exposure_time_ms"] = scanargs["acq_time"]
if "acq_period" in scanargs and scanargs["acq_period"] is not None:
d["exposure_period_ms"] = scanargs["acq_period"]
if "exp_burst" in scanargs and scanargs["exp_burst"] is not None: if "exp_burst" in scanargs and scanargs["exp_burst"] is not None:
d["exposure_num_burst"] = scanargs["exp_burst"] d["exposure_num_burst"] = scanargs["exp_burst"]
if "acq_mode" in scanargs and scanargs["acq_mode"] is not None: if "acq_mode" in scanargs and scanargs["acq_mode"] is not None:
@@ -497,6 +501,7 @@ class GigaFrostCamera(PSIDetectorBase):
# There's no status readback from the camera, so we just wait # There's no status readback from the camera, so we just wait
sleep_time = self.cfgExposure.value * self.cfgCntNum.value * 0.001 + 0.2 sleep_time = self.cfgExposure.value * self.cfgCntNum.value * 0.001 + 0.2
logger.warning(f"Gigafrost sleeping for {sleep_time} sec")
sleep(sleep_time) sleep(sleep_time)
return DeviceStatus(self, done=True, success=True, settle_time=sleep_time) return DeviceStatus(self, done=True, success=True, settle_time=sleep_time)

View File

@@ -7,7 +7,7 @@ Created on Wed Dec 6 11:33:54 2023
import time import time
from ophyd import Component, EpicsSignal, EpicsSignalRO, Kind from ophyd import Component, EpicsSignal, EpicsSignalRO, Kind
from ophyd.status import SubscriptionStatus, DeviceStatus from ophyd.status import SubscriptionStatus, DeviceStatus
from ophyd_devices import BECDeviceBase from ophyd_devices.interfaces.base_classes.psi_detector_base import PSIDetectorBase as BECDeviceBase
from ophyd_devices.interfaces.base_classes.psi_detector_base import ( from ophyd_devices.interfaces.base_classes.psi_detector_base import (
CustomDetectorMixin as CustomPrepare, CustomDetectorMixin as CustomPrepare,
) )
@@ -54,6 +54,10 @@ class PcoEdgeCameraMixin(CustomPrepare):
d["exposure_time_ms"] = scanargs["exp_time"] d["exposure_time_ms"] = scanargs["exp_time"]
if "exp_period" in scanargs and scanargs["exp_period"] is not None: if "exp_period" in scanargs and scanargs["exp_period"] is not None:
d["exposure_period_ms"] = scanargs["exp_period"] d["exposure_period_ms"] = scanargs["exp_period"]
if "acq_time" in scanargs and scanargs["acq_time"] is not None:
d["exposure_time_ms"] = scanargs["acq_time"]
if "acq_period" in scanargs and scanargs["acq_period"] is not None:
d["exposure_period_ms"] = scanargs["acq_period"]
# if 'exp_burst' in scanargs and scanargs['exp_burst'] is not None: # if 'exp_burst' in scanargs and scanargs['exp_burst'] is not None:
# d['exposure_num_burst'] = scanargs['exp_burst'] # d['exposure_num_burst'] = scanargs['exp_burst']
# if 'acq_mode' in scanargs and scanargs['acq_mode'] is not None: # if 'acq_mode' in scanargs and scanargs['acq_mode'] is not None:
@@ -469,5 +473,5 @@ class PcoEdge5M(HelgeCameraBase):
if __name__ == "__main__": if __name__ == "__main__":
# Drive data collection # Drive data collection
cam = PcoEdge5M("X02DA-CCDCAM2:", name="mcpcam") cam = PcoEdge5M(prefix="X02DA-CCDCAM2:", name="mcpcam")
cam.wait_for_connection() cam.wait_for_connection()

View File

@@ -1,2 +1,2 @@
from .tutorial_fly_scan import AcquireDark, AcquireWhite, AcquireRefs, TutorialFlyScanContLine from .tutorial_fly_scan import AcquireDark, AcquireWhite, AcquireRefs, TutorialFlyScanContLine
from .tomcat_scans import TomcatStepScan, TomcatSnapNStep, TomcatSimpleSequence from .tomcat_scans import TomcatSnapNStep, TomcatSimpleSequence

View File

@@ -18,95 +18,11 @@ import os
import time import time
from bec_lib import bec_logger from bec_lib import bec_logger
from bec_server.scan_server.scans import AsyncFlyScanBase, ScanBase, ScanArgType from bec_server.scan_server.scans import AsyncFlyScanBase, ScanArgType
logger = bec_logger.logger logger = bec_logger.logger
class TomcatStepScan(ScanBase):
"""Simple software step scan for Tomcat
Example class for simple BEC-based step scan using the low-level API. It's just a standard
'line_scan' with the only difference that overrides burst behavior to use camera burst instead
of individual software triggers.
NOTE: As decided by Tomcat, the scans should not manage the scope of devices
- All enabled devices are expected to be configured for acquisition by the end of stage
- Some devices can configure themselves from mandatory scan parameters (steps, burst)
- Other devices can be optionally configured by keyword arguments
- Devices will try to stage using whatever was set on them before
Example:
--------
>>> scans.tomcatstepscan(scan_start=-25, scan_end=155, steps=180, exp_time=0.005, exp_burst=5)
Common keyword arguments:
-------------------------
image_width : int
image_height : int
ddc_trigger : str
"""
scan_name = "tomcatstepscan"
scan_type = "step"
required_kwargs = ["scan_start", "scan_end", "steps"]
gui_config = {
"Movement parameters": ["steps"],
"Acquisition parameters": ["exp_time", "exp_burst"],
}
def update_scan_motors(self):
self.scan_motors = ["es1_roty"]
def _get_scan_motors(self):
self.scan_motors = ["es1_roty"]
def __init__(
self,
scan_start: float,
scan_end: float,
steps: int,
exp_time: float=0.005,
settling_time: float=0.2,
exp_burst: int=1,
**kwargs,
):
# Converting generic kwargs to tomcat device configuration parameters
super().__init__(
exp_time=exp_time,
settling_time=settling_time,
burst_at_each_point=1,
optim_trajectory=None,
**kwargs,
)
# For position calculation
self.motor = "es1_roty"
self.scan_start = scan_start
self.scan_end = scan_end
self.scan_steps = steps
self.scan_stepsize = (scan_end - scan_start) / steps
def _calculate_positions(self) -> None:
"""Pre-calculate scan positions"""
for ii in range(self.scan_steps + 1):
self.positions.append(self.scan_start + ii * self.scan_stepsize)
def _at_each_point(self, ind=None, pos=None):
""" Overriden at_each_point, using detector burst instaead of manual triggering"""
yield from self._move_scan_motors_and_wait(pos)
time.sleep(self.settling_time)
trigger_time = 0.001*self.exp_time * self.burst_at_each_point
yield from self.stubs.trigger(min_wait=trigger_time)
# yield from self.stubs.trigger(group='trigger', point_id=self.point_id)
# time.sleep(trigger_time)
yield from self.stubs.read(group="monitored", point_id=self.point_id)
# yield from self.stubs.read(group="monitored", point_id=self.point_id, wait_group=None)
self.point_id += 1
class TomcatSnapNStep(AsyncFlyScanBase): class TomcatSnapNStep(AsyncFlyScanBase):
"""Simple software step scan forTomcat """Simple software step scan forTomcat
@@ -115,7 +31,7 @@ class TomcatSnapNStep(AsyncFlyScanBase):
Example Example
------- -------
>>> scans.tomcatsnapnstepscan(scan_start=-25, scan_end=155, steps=180, exp_time=0.005, exp_burst=5) >>> scans.tomcatsnapnstepscan(scan_start=-25, scan_end=155, steps=180, acq_time=5, exp_burst=5)
""" """
scan_name = "tomcatsnapnstepscan" scan_name = "tomcatsnapnstepscan"
@@ -126,10 +42,10 @@ class TomcatSnapNStep(AsyncFlyScanBase):
required_kwargs = ["scan_start", "scan_end", "steps"] required_kwargs = ["scan_start", "scan_end", "steps"]
gui_config = { gui_config = {
"Movement parameters": ["steps"], "Movement parameters": ["steps"],
"Acquisition parameters": ["exp_time", "exp_burst"], "Acquisition parameters": ["acq_time", "exp_burst"],
} }
def _get_scan_motors(self): def _update_scan_motors(self):
self.scan_motors = ["es1_roty"] self.scan_motors = ["es1_roty"]
def __init__( def __init__(
@@ -137,8 +53,8 @@ class TomcatSnapNStep(AsyncFlyScanBase):
scan_start: float, scan_start: float,
scan_end: float, scan_end: float,
steps: int, steps: int,
exp_time:float=0.005,
settling_time:float=0.2, settling_time:float=0.2,
acq_time:float=5.0,
exp_burst:int=1, exp_burst:int=1,
sync:str="event", sync:str="event",
**kwargs, **kwargs,
@@ -147,14 +63,12 @@ class TomcatSnapNStep(AsyncFlyScanBase):
self.scan_start = scan_start self.scan_start = scan_start
self.scan_end = scan_end self.scan_end = scan_end
self.scan_steps = steps self.scan_steps = steps
self.scan_stepsize = (scan_end - scan_start) / steps self.exp_time = acq_time
self.scan_ntotal = exp_burst * (steps + 1)
self.exp_time = exp_time
self.exp_burst = exp_burst self.exp_burst = exp_burst
self.settling_time = settling_time self.settling_time = settling_time
self.scan_sync = sync self.scan_sync = sync
# General device configuration # Gigafrost trigger mode
kwargs["parameter"]["kwargs"]["acq_mode"] = "ext_enable" kwargs["parameter"]["kwargs"]["acq_mode"] = "ext_enable"
# Used for Aeroscript file substitutions for the task interface # Used for Aeroscript file substitutions for the task interface
@@ -165,7 +79,8 @@ class TomcatSnapNStep(AsyncFlyScanBase):
kwargs["parameter"]["kwargs"]["script_file"] = "bec.ascript" kwargs["parameter"]["kwargs"]["script_file"] = "bec.ascript"
super().__init__( super().__init__(
exp_time=exp_time, acq_time=acq_time,
exp_burst=exp_burst,
settling_time=settling_time, settling_time=settling_time,
burst_at_each_point=1, burst_at_each_point=1,
optim_trajectory=None, optim_trajectory=None,
@@ -182,12 +97,12 @@ class TomcatSnapNStep(AsyncFlyScanBase):
} }
filesubs = { filesubs = {
"startpos": self.scan_start, "startpos": self.scan_start,
"stepsize": self.scan_stepsize, "stepsize": (self.scan_end - self.scan_start) / self.scan_steps,
"numsteps": self.scan_steps, "numsteps": self.scan_steps,
"exptime": 2 * self.exp_time * self.exp_burst, "exptime": 0.002 * self.exp_time * self.exp_burst,
"settling": self.settling_time, "settling": self.settling_time,
"psotrigger": p_modes[self.scan_sync], "psotrigger": p_modes[self.scan_sync],
"npoints": self.scan_ntotal, "npoints": self.exp_burst * (self.scan_steps + 1),
} }
return filesubs return filesubs
@@ -196,7 +111,7 @@ class TomcatSnapNStep(AsyncFlyScanBase):
# Load the test file # Load the test file
filename = os.path.join(os.path.dirname(__file__), "../devices/aerotech/" + filename) filename = os.path.join(os.path.dirname(__file__), "../devices/aerotech/" + filename)
logger.info(f"Attempting to load file {filename}") logger.info(f"Attempting to load file {filename}")
with open(filename) as f: with open(filename, "r", encoding="utf-8") as f:
templatetext = f.read() templatetext = f.read()
# Substitute jinja template # Substitute jinja template
@@ -208,12 +123,15 @@ class TomcatSnapNStep(AsyncFlyScanBase):
"""The actual scan routine""" """The actual scan routine"""
print("TOMCAT Running scripted scan (via Jinjad AeroScript)") print("TOMCAT Running scripted scan (via Jinjad AeroScript)")
t_start = time.time() t_start = time.time()
# Kickoff
yield from self.stubs.send_rpc_and_wait("es1_tasks", "kickoff")
# Complete # Complete
# FIXME: this will swallow errors # FIXME: this will swallow errors
# yield from self.stubs.complete(device="es1_tasks") # yield from self.stubs.complete(device="es1_tasks")
st = yield from self.stubs.send_rpc_and_wait("es1_tasks", "complete") yield from self.stubs.send_rpc_and_wait("es1_tasks", "complete")
# st.wait()
# Check final state
task_states = yield from self.stubs.send_rpc_and_wait("es1_tasks", "taskStates.get") task_states = yield from self.stubs.send_rpc_and_wait("es1_tasks", "taskStates.get")
if task_states[4] == 8: if task_states[4] == 8:
raise RuntimeError(f"Task {4} finished in ERROR state") raise RuntimeError(f"Task {4} finished in ERROR state")
@@ -243,7 +161,7 @@ class TomcatSimpleSequence(AsyncFlyScanBase):
Example Example
------- -------
>>> scans.tomcatsimplesequencescan(33, 180, 180, exp_time=0.005, exp_burst=1800, repeats=10) >>> scans.tomcatsimplesequencescan(33, 180, 180, acq_time=5, exp_burst=1800, repeats=10)
""" """
scan_name = "tomcatsimplesequencescan" scan_name = "tomcatsimplesequencescan"
@@ -255,7 +173,7 @@ class TomcatSimpleSequence(AsyncFlyScanBase):
"Acquisition parameters": [ "Acquisition parameters": [
"gate_high", "gate_high",
"gate_low", "gate_low",
"exp_time", "acq_time",
"exp_burst", "exp_burst",
"sync", "sync",
], ],
@@ -271,7 +189,7 @@ class TomcatSimpleSequence(AsyncFlyScanBase):
gate_low: float, gate_low: float,
repeats: int = 1, repeats: int = 1,
repmode: str = "PosNeg", repmode: str = "PosNeg",
exp_time: float = 0.005, acq_time: float = 5,
exp_burst: float = 180, exp_burst: float = 180,
sync: str = "pso", sync: str = "pso",
**kwargs, **kwargs,
@@ -282,13 +200,13 @@ class TomcatSimpleSequence(AsyncFlyScanBase):
self.gate_low = gate_low self.gate_low = gate_low
self.scan_repnum = repeats self.scan_repnum = repeats
self.scan_repmode = repmode.upper() self.scan_repmode = repmode.upper()
self.exp_time = exp_time self.exp_time = acq_time
self.exp_burst = exp_burst self.exp_burst = exp_burst
self.scan_sync = sync self.scan_sync = sync
# Synthetic values # Synthetic values
self.scan_ntotal = exp_burst * repeats self.scan_ntotal = exp_burst * repeats
self.scan_velocity = gate_high / (exp_time * exp_burst) self.scan_velocity = gate_high / (0.001*acq_time * exp_burst)
self.scan_acceleration = 500 self.scan_acceleration = 500
self.scan_safedistance = 10 self.scan_safedistance = 10
self.scan_accdistance = ( self.scan_accdistance = (
@@ -314,7 +232,7 @@ class TomcatSimpleSequence(AsyncFlyScanBase):
kwargs["parameter"]["kwargs"]["script_file"] = "bec.ascript" kwargs["parameter"]["kwargs"]["script_file"] = "bec.ascript"
super().__init__( super().__init__(
exp_time=exp_time, acq_time=acq_time,
settling_time=0.5, settling_time=0.5,
relative=False, relative=False,
burst_at_each_point=1, burst_at_each_point=1,
@@ -327,7 +245,7 @@ class TomcatSimpleSequence(AsyncFlyScanBase):
# Load the test file # Load the test file
filename = os.path.join(os.path.dirname(__file__), "../devices/aerotech/" + filename) filename = os.path.join(os.path.dirname(__file__), "../devices/aerotech/" + filename)
logger.info(f"Attempting to load file {filename}") logger.info(f"Attempting to load file {filename}")
with open(filename) as f: with open(filename, 'r', encoding="utf-8") as f:
templatetext = f.read() templatetext = f.read()
# Substitute jinja template # Substitute jinja template
@@ -339,12 +257,14 @@ class TomcatSimpleSequence(AsyncFlyScanBase):
"""The actual scan routine""" """The actual scan routine"""
print("TOMCAT Running scripted scan (via Jinjad AeroScript)") print("TOMCAT Running scripted scan (via Jinjad AeroScript)")
t_start = time.time() t_start = time.time()
# Kickoff
yield from self.stubs.send_rpc_and_wait("es1_tasks", "kickoff")
# Complete # Complete
# FIXME: this will swallow errors # FIXME: this will swallow errors
# yield from self.stubs.complete(device="es1_tasks") # yield from self.stubs.complete(device="es1_tasks")
st = yield from self.stubs.send_rpc_and_wait("es1_tasks", "complete") yield from self.stubs.send_rpc_and_wait("es1_tasks", "complete")
# st.wait()
task_states = yield from self.stubs.send_rpc_and_wait("es1_tasks", "taskStates.get") task_states = yield from self.stubs.send_rpc_and_wait("es1_tasks", "taskStates.get")
if task_states[4] == 8: if task_states[4] == 8:
raise RuntimeError(f"Task {4} finished in ERROR state") raise RuntimeError(f"Task {4} finished in ERROR state")