Simplesequence triggers correctly

This commit is contained in:
gac-x05la
2024-10-16 16:09:03 +02:00
parent 08ca35d270
commit 5d3550d0fd
4 changed files with 181 additions and 59 deletions
@@ -709,15 +709,22 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
# ########################################################################
# Bluesky flyer interface
def prepare(self) -> DeviceStatus:
def prepare(self, distance=None) -> DeviceStatus:
""" Arm trigger for a synchronous or asynchronous acquisition"""
if self._distance_value is not None:
# Rearm the configured array
if isinstance(self._distance_value, (np.ndarray, list, tuple)):
self.dstArrayRearm.set(1).wait()
# Start monitoring the counters
self.dstEventsEna.set("On").wait()
self.dstCounterEna.set("On").wait()
if distance is not None:
# Write a new array
if isinstance(distance, (float, int)):
self.dstDistance.set(distance).wait()
elif isinstance(distance, (np.ndarray, list, tuple)):
self.dstDistanceArr.set(distance).wait()
else:
if self._distance_value is not None:
# Rearm the already configured array
if isinstance(self._distance_value, (np.ndarray, list, tuple)):
self.dstArrayRearm.set(1).wait()
# Start monitoring the counters
self.dstEventsEna.set("On").wait()
self.dstCounterEna.set("On").wait()
status = DeviceStatus(self)
status.set_finished()
return status
@@ -73,17 +73,24 @@ program
PsoDistanceEventsOff($axis)
PsoWindowConfigureEvents($axis, PsoWindowEventMode.None)
PsoWaveformOff($axis)
var $iPsoArrayPosAddr as integer = PSO_ADDR
// Simple PSO trigger pattern
var $iPsoArrayPos[] as real = [{% for psoDist in scan.psoBoundsPos[:-1] %} UnitsToCounts($axis, {{ psoDist }}), {% endfor %} UnitsToCounts($axis, {{ scan.psoBoundsPos[-1] }}) ]
var $iPsoArrayNeg[] as real = [{% for psoDist in scan.psoBoundsNeg[:-1] %} UnitsToCounts($axis, {{ psoDist }}), {% endfor %} UnitsToCounts($axis, {{ scan.psoBoundsNeg[-1] }}) ]
var $iPsoArrayPosAddr as integer = PSO_ADDR
var $iPsoArrayPosSize as integer = {{ scan.psoBoundsPosSize }}
var $iPsoArrayNegSize as integer = {{ scan.psoBoundsNegSize }}
// Calculate negative array offset (in bytes)
var $iPsoArrayNegAddr as integer = ($iPsoArrayPosAddr + length($iPsoArrayPos)) * 4
var $iPsoArrayPos[] as real = [{% for psoDist in scan.psoBoundsPos[:-1] %} UnitsToCounts($axis, {{ psoDist }}), {% endfor %} UnitsToCounts($axis, {{ scan.psoBoundsPos[-1] }}) ]
DriveArrayWrite($axis, $iPsoArrayPos, $iPsoArrayPosAddr, length($iPsoArrayPos), DriveArrayType.PsoDistanceEventDistances)
{% if scan.psoBoundsNeg|length > 0 %}
var $iPsoArrayNegAddr as integer = ($iPsoArrayPosAddr + length($iPsoArrayPos)) * 4
var $iPsoArrayNegSize as integer = {{ scan.psoBoundsNegSize }}
var $iPsoArrayNeg[] as real = [{% for psoDist in scan.psoBoundsNeg[:-1] %} UnitsToCounts($axis, {{ psoDist }}), {% endfor %} UnitsToCounts($axis, {{ scan.psoBoundsNeg[-1] }}) ]
DriveArrayWrite($axis, $iPsoArrayNeg, $iPsoArrayNegAddr, length($iPsoArrayNeg), DriveArrayType.PsoDistanceEventDistances)
{% else %}
var $iPsoArrayNegAddr as integer = ($iPsoArrayPosAddr + length($iPsoArrayPos)) * 4
var $iPsoArrayNegSize as integer = 0
var $iPsoArrayNeg[] as real = []
// DriveArrayWrite($axis, $iPsoArrayNeg, $iPsoArrayNegAddr, length($iPsoArrayNeg), DriveArrayType.PsoDistanceEventDistances)
{% endif %}
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, length($iPsoArrayPos), 0)
PsoDistanceCounterOn($axis)
@@ -113,33 +120,15 @@ program
///////////////////////////////////////////////////////////
// Start the actual scanning
///////////////////////////////////////////////////////////
for $ii = 0 to ($iNumRepeat-1)
// Feedback on progress
$rglobal[4] = $ii
if $eScanType == ScanType.POS
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
elseif $eScanType == ScanType.NEG
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
elseif $eScanType == ScanType.POSNEG
if ($ii % 2) == 0
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
elseif ($ii % 2) == 1
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayNegAddr, $iPsoArrayNegSize, 0)
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
end
elseif $eScanType == ScanType.NEGPOS
if $eScanType == ScanType.POS || $eScanType == ScanType.NEG
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
elseif $eScanType == ScanType.POSNEG || $eScanType == ScanType.NEGPOS
for $ii = 0 to ($iNumRepeat-1)
// Feedback on progress
$rglobal[4] = $ii
if ($ii % 2) == 0
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
@@ -149,13 +138,16 @@ program
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
end
Dwell(0.2)
end
Dwell(0.2)
end
// Directly after scan
PsoDistanceCounterOff($axis)
DriveDataCaptureOff($axis, 0)
DriveDataCaptureOff($axis, 1)
// move back to start position
MoveAbsolute($axis, $fPosStart, $fVelJog)
WaitForInPosition($axis)
end
+9 -16
View File
@@ -211,7 +211,7 @@ class SimpleFlyer(AsyncFlyScanBase):
def unstage(self):
""" Wait for DAQ before unstaging"""
time.sleep(5)
time.sleep(1)
yield from super().unstage()
@@ -311,7 +311,7 @@ class GigaStepScanBase(ScanBase):
def unstage(self):
""" Wait for DAQ before unstaging"""
time.sleep(5)
time.sleep(1)
yield from super().unstage()
@@ -396,7 +396,7 @@ class SnapAndStepScanBase(TemplatedScanBase):
def unstage(self):
""" Wait for DAQ before unstaging"""
time.sleep(5)
time.sleep(1)
yield from super().unstage()
@@ -433,7 +433,7 @@ class SequenceScanBase(TemplatedScanBase):
self.gate_high = gate_high
self.gate_low = gate_low
self.scan_repnum = repeats
self.scan_repmode = repmode
self.scan_repmode = repmode.upper()
self.exp_time = exp_time
self.exp_frames = exp_frames
@@ -501,24 +501,17 @@ class SequenceScanBase(TemplatedScanBase):
def prepare_positions(self):
# Fill PSO vectors according to scan direction
# NOTE: Distance counter is bidirectional
self.psoBoundsPos = []
self.psoBoundsNeg = []
if self.scan_repmode in ("pos", "Pos"):
if self.scan_repmode in ("pos", "Pos", "POS", "neg", "Neg", "NEG"):
self.psoBoundsPos.append(self.scan_accdistance)
for ii in range(self.scan_repnum):
self.psoBoundsPos += [self.gate_high, self.gate_low]
# self.psoBoundsPos[-1] = 10* (self.scan_accdistance+self.gate_low)
if self.scan_repmode in ("neg", "Neg"):
self.psoBoundsNeg.append(self.scan_accdistance)
for ii in range(self.scan_repnum):
self.psoBoundsNeg += [self.gate_high, self.gate_low]
# self.psoBoundsNeg[-1] = 10* (self.scan_accdistance+self.gate_low)
if self.scan_repmode in ("posneg", "PosNeg"):
self.psoBoundsPos = self.psoBoundsPos[:-1]
if self.scan_repmode in ("posneg", "PosNeg", "POSNEG", "negpos", "NegPos", "NEGPOS"):
self.psoBoundsPos = [self.scan_accdistance, self.gate_high]
self.psoBoundsNeg = [self.scan_accdistance + self.gate_low, self.gate_high]
if self.scan_repmode in ("negpos", "NegPos"):
self.psoBoundsNeg = [self.scan_accdistance, self.gate_high]
self.psoBoundsPos = [self.scan_accdistance + self.gate_low, self.gate_high]
self.filesubs['psoBoundsPos'] = self.psoBoundsPos
self.filesubs['psoBoundsNeg'] = self.psoBoundsNeg
@@ -529,7 +522,7 @@ class SequenceScanBase(TemplatedScanBase):
def unstage(self):
""" Wait for DAQ before unstaging"""
time.sleep(5)
time.sleep(1)
yield from super().unstage()
+131 -1
View File
@@ -68,4 +68,134 @@ def demosequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg
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)
scans.sequencescan(scan_start, gate_high, gate_low, exp_time=exp_time, exp_frames=exp_frames, repeats=repeats, repmode=repmode)
def becsequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg",
exp_time=0.005, exp_frames=180, sync='pso'):
""" Demo sequence scan with GigaFrost
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.
Example:
--------
>>> demosequencescan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
"""
if not bl_check_beam():
raise RuntimeError("Beamline is not in ready state")
# Parameter validation before scan
if exp_frames <=0:
raise RuntimeError(f"Requires at least one frame per cycle, got {self.exp_frames}")
# Synthetic values
scan_roix = 2016
scan_roiy = 2016
scan_repnum = repeats
scan_repmode = repmode.upper()
scan_velocity = gate_high / (exp_time * exp_frames)
scan_acceleration = 500
scan_safedistance = 10
scan_accdistance = scan_safedistance + 0.5* scan_velocity * scan_velocity / scan_acceleration
scan_ntotal = exp_frames * repeats
if scan_repmode in ("POS", "NEG"):
scan_range = repeats *(gate_high + gate_low)
if scan_repmode=="POS":
scan_end = scan_start + scan_range + scan_accdistance
if scan_repmode=="NEG":
scan_end = scan_start - scan_range - scan_accdistance
elif scan_repmode in ("POSNEG", "NEGPOS"):
scan_range = gate_high + gate_low
if scan_repmode=="POSNEG":
scan_end = scan_start + scan_range + scan_accdistance
if scan_repmode=="NEGPOS":
scan_end = scan_start - scan_range - scan_accdistance
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,
"exposure": 1000 * exp_time,
"period": 2000*exp_time,
"pixel_width": scan_roix,
"pixel_height": scan_roiy
}
# Fill PSO vectors according to scan direction
# NOTE: Distance counter is bidirectional
psoBoundsPos = []
psoBoundsNeg = []
if scan_repmode in ("POS", "NEG"):
psoBoundsPos.append(scan_accdistance)
for ii in range(scan_repnum):
psoBoundsPos += [gate_high, gate_low]
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"
}
# Move to start position
dev.es1_roty.move(scan_start).wait()
# Configure all devices
dev.gfclient.configure(camcfg)
dev.es1_ddaq.configure(daqcfg)
dev.es1_psod.configure(psocfg)
# Stage all devices
dev.gfclient.stage()
dev.es1_ddaq.stage()
dev.es1_psod.stage()
dev.daq_stream1.stage()
# Kick off devices
dev.gfclient.kickoff()
dev.es1_ddaq.kickoff()
dev.es1_psod.kickoff()
print("Handing over to 'scans.line_scan'")
if scan_repmode in ["POS", "NEG"]:
dev.es1_psod.prepare(psoBoundsPos)
dev.es1_roty.move(scan_end).wait()
elif scan_repmode in ["POSNEG", "NEGPOS"]:
for ii in range(scan_repnum):
if ii%2==0:
dev.es1_psod.prepare(psoBoundsPos)
dev.es1_roty.move(scan_end).wait()
if ii%2==1:
dev.es1_psod.prepare(psoBoundsNeg)
dev.es1_roty.move(scan_start).wait()
# Stage all devices
dev.gfclient.unstage()
dev.es1_ddaq.unstage()
dev.es1_psod.unstage()
dev.daq_stream1.unstage()
# Move back to start
dev.es1_roty.move(scan_start).wait()