Minor fixes

This commit is contained in:
gac-x05la
2024-10-21 12:16:41 +02:00
parent 13a4dff547
commit d681a82878
5 changed files with 78 additions and 64 deletions

View File

@@ -970,6 +970,8 @@ class aa1AxisDriveDataCollection(Device):
# This allocates the memory...
self.npoints.set(npoints).wait()
# Reset incremental readback
self._switch.set(2).wait()
new = self.read_configuration()
return (old, new)
@@ -993,6 +995,9 @@ class aa1AxisDriveDataCollection(Device):
status.set_finished()
return status
def reset(self):
"""Reset incremental readback"""
self._switch.set("ResetRB", settle_time=0.1).wait()
def complete(self, settle_time=0.1) -> DeviceStatus:
"""DDC just reads back whatever is available in the buffers"""

View File

@@ -8,12 +8,16 @@ program
// External parameters
var $fStartPosition as real = {{ scan.startpos }}
var $iNumSteps as integer = {{ scan.numsteps }}
var $iNumBurst as integer = {{ scan.numburst or 1 }}
var $fStepSize as real = {{ scan.stepsize }}
var $fExposureTimeSec as real = {{ scan.exptime }}
var $fSettlingTimeSec as real = {{ scan.settle }}
var $fSettlingTimeSec as real = {{ scan.settling }}
var $fVelJog as real = {{ scan.travel or 200 }}
var $fVelScan as real = {{ scan.velocity or 50 }}
var $fAcceleration = {{ scan.acceleration or 500 }}
var $eDdcTrigger as DriveDataCaptureTrigger = DriveDataCaptureTrigger.{{ scan.psotrigger }}
var $iNumDdcRead as integer = {{ scan.npoints }}
// Internal
var $axis as axis = ROTY
@@ -25,8 +29,7 @@ program
SetupAxisRampValue($axis,0,$fAcceleration)
// Move to start position before the scan (use soft-wait to catch errors)
var $fPosNext as real = $fStartPosition
MoveAbsolute($axis, $fPosNext, $fVelJog)
MoveAbsolute($axis, $fStartPosition, $fVelJog)
WaitForMotionDone($axis)
// Mandatory error checking after each movement
@@ -35,27 +38,33 @@ program
TaskSetError(TaskGetIndex(), "AxisFault on axis ROTY")
end
// Configure PSO (to manual event generation)
// Turn off PSO
PsoDistanceConfigureInputs($axis, [PsoDistanceInput.XC4PrimaryFeedback])
PsoDistanceCounterOff($axis)
PsoDistanceEventsOff($axis)
PsoWindowConfigureEvents($axis, PsoWindowEventMode.None)
PsoWaveformConfigurePulseFixedTotalTime($axis, 50)
PsoWaveformConfigurePulseFixedOnTime($axis, 20)
PsoWaveformConfigurePulseFixedCount($axis, 1)
PsoWaveformApplyPulseConfiguration($axis)
// Configure PSO (to manual event generation in pulsed mode)
PsoWaveformConfigureMode($axis, PsoWaveformMode.Pulse)
PsoWaveformConfigurePulseFixedTotalTime($axis, 100)
PsoWaveformConfigurePulseFixedOnTime($axis, 50)
PsoWaveformConfigurePulseFixedCount($axis, $iNumBurst)
PsoWaveformApplyPulseConfiguration($axis)
PsoWaveformOn($axis)
// Activete PSO
PsoOutputConfigureSource($axis, PsoOutputSource.Waveform)
PsoWaveformOn($axis)
// Configure Drive Data Collection
var $iDdcArrayAddr as integer = 8388608
var $iDdcArraySize as integer = iMaximum(5000, $iNumSteps)
var $iDdcArraySize as integer = $iNumDdcRead
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 );
DriveDataCaptureConfigureTrigger($axis, 0, $eDdcTrigger );
DriveDataCaptureConfigureTrigger($axis, 1, $eDdcTrigger );
DriveDataCaptureConfigureArray($axis, 0, $iDdcArrayAddr, $iDdcArraySize);
DriveDataCaptureConfigureArray($axis, 1, $iDdcArrayAddr + $iDdcSafeSpace + 8 * $iDdcArraySize, $iDdcArraySize);
@@ -71,7 +80,7 @@ program
///////////////////////////////////////////////////////////
$iglobal[2] = $iNumSteps
for $ii = 0 to ($iNumSteps-1)
MoveAbsolute($axis, $fPosNext, $fVelScan)
MoveAbsolute($axis, $fStartPosition + $ii * $fStepSize, $fVelScan)
WaitForMotionDone($axis)
$axisFaults = StatusGetAxisItem($axis, AxisDataSignal.AxisFault)
@@ -82,7 +91,6 @@ program
Dwell($fSettlingTimeSec)
PsoEventGenerateSingle($axis)
Dwell($fExposureTimeSec)
$fPosNext = $fPosNext + $fStepSize
$iglobal[1] = $ii
end

View File

@@ -248,6 +248,9 @@ class StdDaqClient(Device):
return
except (ConnectionClosedError, ConnectionClosedOK):
return
except AssertionError:
# Libraty throws after connection is closed
return
finally:
self._mon = None

View File

@@ -119,13 +119,14 @@ class TemplatedScanBase(AsyncFlyScanBase):
yield from self.stubs.send_rpc_and_wait("es1_tasks", "stage")
if self.camera is not None:
yield from self.stubs.send_rpc_and_wait(self.camera, "stage")
if self.daqname is not None:
yield from self.stubs.send_rpc_and_wait(self.daqname, "stage")
# DAQ should be staged from script
# if self.daqname is not None:
# yield from self.stubs.send_rpc_and_wait(self.daqname, "stage")
if self.preview is not None:
yield from self.stubs.send_rpc_and_wait(self.preview, "stage")
# TODO : This should stage the entire beamline
yield from super().stage()
# yield from super().stage()
def scan_core(self):
@@ -156,10 +157,10 @@ class TemplatedScanBase(AsyncFlyScanBase):
time.sleep(0.5)
# Collect
if self.daqname is not None and self.daqmode=="collect":
print("TOMCAT Collecting scripted scan results (from EPICS)")
positions = yield from self.stubs.send_rpc_and_wait(self.daqname, "collect")
logger.info(f"Finished scan with collected positions: {positions}")
# if self.daqname is not None and self.daqmode=="collect":
# print("TOMCAT Collecting scripted scan results (from EPICS)")
# positions = yield from self.stubs.send_rpc_and_wait(self.daqname, "collect")
# logger.info(f"Finished scan with collected positions: {positions}")
def cleanup(self):
"""Set scan progress to 1 to finish the scan"""
@@ -236,9 +237,12 @@ class GigaStepScanBase(ScanBase):
required_kwargs = ["scan_start", "scan_end","steps"]
gui_config = {
"Movement parameters": ["steps"],
"Acquisition parameters" : ["exp_time", "burst_at_each_point"]
"Acquisition parameters" : ["exp_time", "burst_at_each_point", "roix", "roiy"]
}
def _get_scan_motors(self):
self.scan_motors = ["es1_roty"]
def __init__(
self,
scan_start: float,
@@ -247,6 +251,8 @@ class GigaStepScanBase(ScanBase):
exp_time = 0.005,
settling_time = 0.2,
burst_at_each_point = 1,
roix = 2016,
roiy = 2016,
sync='event',
**kwargs):
super().__init__(
@@ -265,6 +271,8 @@ class GigaStepScanBase(ScanBase):
self.scan_stepsize = (scan_end - scan_start) / steps
self.scan_ntotal = burst_at_each_point * (steps + 1)
self.scan_nburst = burst_at_each_point
self.scan_roix = roix
self.scan_roiy = roiy
# Override wait time with actual latency
# NOTE : The BEC does not wait for trigger() status done
@@ -282,14 +290,13 @@ class GigaStepScanBase(ScanBase):
"nimages": burst_at_each_point,
"exposure": 1000*exp_time,
"period": 2000*exp_time,
"pixel_width": 2016,
"pixel_height": 2016
"pixel_width": self.scan_roix,
"pixel_height": self.scan_roiy
}
def _calculate_positions(self) -> None:
""" Pre-calculate scan positions """
self.positions = [self.scan_start]
for ii in range(self.scan_steps):
for ii in range(self.scan_steps+1):
self.positions.append(self.scan_start + ii*self.scan_stepsize)
def stage(self):
@@ -359,24 +366,25 @@ class SnapAndStepScanBase(TemplatedScanBase):
# Synthetic values
self.scan_stepsize = (scan_end-scan_start)/steps
self.scan_ntotal = steps * burst_at_each_point
self.scan_ntotal = (steps+1) * burst_at_each_point
# Aerotech DDC settings: Internal event trigger: PsoEvent = 1
t_modes = {'pso': 0, 'event': 1, 'inp0': 2, 'inp1': 4}
p_modes = {'pso': 'PsoOutput', 'event': 'PsoEvent', 'inp0': 'HighSpeedInput0RisingEdge', 'inp1': 'HighSpeedInput1RisingEdge'}
daq_trigger = t_modes[sync]
pso_trigger = p_modes[sync]
filename = "AerotechSnapAndStepTemplate.ascript"
filesubs = {
'startpos': self.scan_start,
'stepsize': self.scan_stepsize,
'numsteps': self.scan_steps,
'exptime': self.exp_time*self.exp_burst
'settling': self.settling_time
'exptime': 2*self.exp_time*self.exp_burst,
'settling': self.settling_time,
'psotrigger': pso_trigger,
'npoints': self.scan_ntotal
}
# Aerotech DDC settings: Internal event trigger: PsoEvent = 1
if isinstance(sync, str):
t_modes = {'pso': 0, 'event': 1, 'inp0': 2, 'inp1': 4}
daq_trigger = t_modes[sync]
else:
daq_trigger = int(sync)
# DDC config
daqname = "es1_ddaq"
daqcfg = {'ntotal': self.scan_ntotal, 'trigger': daq_trigger}
# Gigafrost config

View File

@@ -3,11 +3,13 @@
def bl_check_beam():
""" Checks beamline status"""
return True
motor_enabled = bool(dev.es1_roty.motor_enable.get())
result = motor_enabled
return result
def demostepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_point=1, settling_time=0, sync='event'):
def demostepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_point=1, settling_time=0, roix=2016, roiy=2016, sync='event'):
""" Demo step scan with GigaFrost
This is a small BEC user-space demo step scan at the microXAS testbench
@@ -30,7 +32,9 @@ def demostepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_poin
# Configure gigafrost
cfg = {
"ntotal": scan_ntotal, "nimages": burst_at_each_point,
"exposure": 1000*exp_time, "period": 2000*exp_time}
"exposure": 1000*exp_time, "period": 2000*exp_time,
"pixel_width": roix, "pixel_height": roiy
}
dev.gfclient.configure(d=cfg)
# Configure PSO trigger (trigger is normally disabled in fly mode)
dev.es1_psod.configure(d={})
@@ -51,7 +55,7 @@ def demostepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_poin
def demosequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg",
exp_time=0.005, exp_frames=180, sync='pso'):
exp_time=0.005, exp_frames=180, roix=2016, roiy=2016, sync='pso'):
""" Demo sequence scan with GigaFrost
This is a small BEC user-space sequence scan at the microXAS testbench
@@ -67,19 +71,16 @@ def demosequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg
if not bl_check_beam():
raise RuntimeError("Beamline is not in ready state")
print("Handing over to 'scans.line_scan'")
scans.sequencescan(scan_start, gate_high, gate_low, exp_time=exp_time, exp_frames=exp_frames, repeats=repeats, repmode=repmode)
print("Handing over to 'scans.sequencescan'")
scans.sequencescan(scan_start, gate_high, gate_low, exp_time=exp_time, exp_frames=exp_frames, repeats=repeats, roix=roix, roiy=roiy, repmode=repmode, sync=sync)
def becsequencescan(start, gate_high, gate_low, repeats=1, repmode="PosNeg",
exp_time=0.005, exp_frames=180, sync='pso'):
""" Demo sequence scan with GigaFrost
exp_time=0.005, exp_frames=180, roix=2016, roiy=2016, sync='pso'):
""" Demo sequence scan with GigaFrost via BEC
This is a small BEC user-space sequence scan at the microXAS testbench
triggering a customized scripted scan on the controller. The scan uses
a pre-written custom low-level sequence scan, so it is really minimal.
NOTE: It calls the AeroScript template version.
doing every scan logic from BEC, i.e. there's no AeroScript involved.
Example:
--------
@@ -93,8 +94,8 @@ def becsequencescan(start, gate_high, gate_low, repeats=1, repmode="PosNeg",
raise RuntimeError(f"Requires at least one frame per cycle, got {self.exp_frames}")
# Synthetic values
scan_roix = 2016
scan_roiy = 2016
scan_roix = roix
scan_roiy = roiy
scan_repnum = repeats
scan_repmode = repmode.upper()
scan_velocity = gate_high / (exp_time * exp_frames)
@@ -122,18 +123,13 @@ def becsequencescan(start, gate_high, gate_low, repeats=1, repmode="PosNeg",
else:
raise RuntimeError(f"Unsupported repetition mode: {repmode}")
# Aerotech DDC settings: Internal event trigger: PsoEvent = 1
t_modes = {'pso': 0, 'event': 1, 'inp0': 2, 'inp1': 4}
p_modes = {'pso': 'PsoOutput', 'event': 'PsoEvent', 'inp0': 'HighSpeedInput0RisingEdge', 'inp1': 'HighSpeedInput1RisingEdge'}
daq_trigger = t_modes[sync]
pso_trigger = p_modes[sync]
# Drice data collection config
daqname = "es1_ddaq"
daqcfg = {'ntotal': scan_ntotal, 'trigger': daq_trigger}
# Gigafrost config
camname = "gfclient"
camcfg = {
"ntotal": scan_ntotal,
"nimages": exp_frames,
@@ -143,6 +139,7 @@ def becsequencescan(start, gate_high, gate_low, repeats=1, repmode="PosNeg",
"pixel_height": scan_roiy
}
# PSO config
# Fill PSO vectors according to scan direction
# NOTE: Distance counter is bidirectional
psoBoundsPos = []
@@ -154,12 +151,7 @@ def becsequencescan(start, gate_high, gate_low, repeats=1, repmode="PosNeg",
if scan_repmode in ("POSNEG", "NEGPOS"):
psoBoundsPos = [scan_accdistance, gate_high]
psoBoundsNeg = [scan_accdistance + gate_low, gate_high]
# PSO config
psocfg = {
"distance": psoBoundsPos,
"wmode": "toggle"
}
psocfg = {"distance": psoBoundsPos, "wmode": "toggle"}
# Move to start position
dev.es1_roty.move(scan_start).wait()
@@ -206,5 +198,3 @@ def becsequencescan(start, gate_high, gate_low, repeats=1, repmode="PosNeg",
# Move back to start
dev.es1_roty.move(scan_start).wait()