Helical scan with proggress bar
This commit is contained in:
@@ -493,10 +493,10 @@ bstop_z:
|
|||||||
bstop_pneum:
|
bstop_pneum:
|
||||||
description: Beamstop pneumatic
|
description: Beamstop pneumatic
|
||||||
deviceClass: pxiii_bec.devices.PneumaticValve
|
deviceClass: pxiii_bec.devices.PneumaticValve
|
||||||
deviceConfig: {read_pv: 'X06DA-ES-BS:GET-POS', write_pv: 'X06DA-ES-BS:SET-POS', auto_monitor: true, put_complete: true}
|
deviceConfig: {read_pv: 'X06DA-ES-BS:GET-POS', write_pv: 'X06DA-ES-BS:SET-POS', kind: 'config', auto_monitor: true, put_complete: true}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
readoutPriority: monitored
|
readoutPriority: baseline
|
||||||
readOnly: false
|
readOnly: false
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
bstop_diode:
|
bstop_diode:
|
||||||
@@ -511,7 +511,7 @@ bstop_diode:
|
|||||||
frontlight:
|
frontlight:
|
||||||
description: Microscope frontlight
|
description: Microscope frontlight
|
||||||
deviceClass: ophyd.EpicsSignal
|
deviceClass: ophyd.EpicsSignal
|
||||||
deviceConfig: {read_pv: 'X06DA-ES-FL:SET-BRGHT', kind: 'normal', put_complete: true}
|
deviceConfig: {read_pv: 'X06DA-ES-FL:SET-BRGHT', kind: 'config', put_complete: true}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
readoutPriority: monitored
|
readoutPriority: monitored
|
||||||
@@ -520,10 +520,10 @@ frontlight:
|
|||||||
backlight:
|
backlight:
|
||||||
description: Backlight reflector
|
description: Backlight reflector
|
||||||
deviceClass: pxiii_bec.devices.PneumaticValve
|
deviceClass: pxiii_bec.devices.PneumaticValve
|
||||||
deviceConfig: {read_pv: 'X06DA-ES-BL:GET-POS', write_pv: 'X06DA-ES-BL:SET-POS', auto_monitor: true, put_complete: true}
|
deviceConfig: {read_pv: 'X06DA-ES-BL:GET-POS', write_pv: 'X06DA-ES-BL:SET-POS', kind: 'config', auto_monitor: true, put_complete: true}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
readoutPriority: monitored
|
readoutPriority: baseline
|
||||||
readOnly: false
|
readOnly: false
|
||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
det_y:
|
det_y:
|
||||||
@@ -595,7 +595,7 @@ abr:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
shx:
|
shx:
|
||||||
description: SmarGon X axis
|
description: SmarGon X axis
|
||||||
deviceClass: pxiii_bec.devices.SmarGonAxisA
|
deviceClass: pxiii_bec.devices.SmarGonAxisB
|
||||||
deviceConfig: {prefix: 'SCS', low_limit: -2, high_limit: 2, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
deviceConfig: {prefix: 'SCS', low_limit: -2, high_limit: 2, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -604,7 +604,7 @@ shx:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
shy:
|
shy:
|
||||||
description: SmarGon Y axis
|
description: SmarGon Y axis
|
||||||
deviceClass: pxiii_bec.devices.SmarGonAxisA
|
deviceClass: pxiii_bec.devices.SmarGonAxisB
|
||||||
deviceConfig: {prefix: 'SCS', low_limit: -2, high_limit: 2, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
deviceConfig: {prefix: 'SCS', low_limit: -2, high_limit: 2, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -613,7 +613,7 @@ shy:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
shz:
|
shz:
|
||||||
description: SmarGon Z axis
|
description: SmarGon Z axis
|
||||||
deviceClass: pxiii_bec.devices.SmarGonAxisA
|
deviceClass: pxiii_bec.devices.SmarGonAxisB
|
||||||
deviceConfig: {prefix: 'SCS', low_limit: 10, high_limit: 22, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
deviceConfig: {prefix: 'SCS', low_limit: 10, high_limit: 22, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -622,7 +622,7 @@ shz:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
chi:
|
chi:
|
||||||
description: SmarGon CHI axis
|
description: SmarGon CHI axis
|
||||||
deviceClass: pxiii_bec.devices.SmarGonAxisA
|
deviceClass: pxiii_bec.devices.SmarGonAxisB
|
||||||
deviceConfig: {prefix: 'SCS', low_limit: 0, high_limit: 40, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
deviceConfig: {prefix: 'SCS', low_limit: 0, high_limit: 40, sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -631,7 +631,7 @@ chi:
|
|||||||
softwareTrigger: false
|
softwareTrigger: false
|
||||||
phi:
|
phi:
|
||||||
description: SmarGon PHI axis
|
description: SmarGon PHI axis
|
||||||
deviceClass: pxiii_bec.devices.SmarGonAxisA
|
deviceClass: pxiii_bec.devices.SmarGonAxisB
|
||||||
deviceConfig: {prefix: 'SCS', sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
deviceConfig: {prefix: 'SCS', sg_url: 'http://x06da-smargopolo.psi.ch:3000'}
|
||||||
onFailure: buffer
|
onFailure: buffer
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class AerotechAbrMixin(CustomPrepare):
|
|||||||
scanargs = self.parent.scaninfo.scan_msg.info["kwargs"]
|
scanargs = self.parent.scaninfo.scan_msg.info["kwargs"]
|
||||||
scanname = self.parent.scaninfo.scan_msg.info["scan_name"]
|
scanname = self.parent.scaninfo.scan_msg.info["scan_name"]
|
||||||
|
|
||||||
if scanname in ("standardscan", "helicalscan"):
|
if scanname in ("standardscan", "helicalscan", "helicalscan1", "helicalscan2", "helicalscan3"):
|
||||||
d["scan_command"] = AbrCmd.MEASURE_STANDARD
|
d["scan_command"] = AbrCmd.MEASURE_STANDARD
|
||||||
d["var_1"] = scanargs["start"]
|
d["var_1"] = scanargs["start"]
|
||||||
d["var_2"] = scanargs["range"]
|
d["var_2"] = scanargs["range"]
|
||||||
|
|||||||
@@ -3,26 +3,30 @@ from ophyd.status import SubscriptionStatus
|
|||||||
|
|
||||||
|
|
||||||
class PneumaticValve(EpicsSignal):
|
class PneumaticValve(EpicsSignal):
|
||||||
"""Wrapper around EpicsSignal to wait until reaching target
|
"""Wrapper around EpicsSignal to wait until reaching target. Use the
|
||||||
|
status returned by set() to wait until movement is finished. Do NOT
|
||||||
|
use put if you want to wait, that's a low-level PV write op.
|
||||||
|
|
||||||
NOTE: The SET and GET states do not match exactly
|
NOTE: The SET and GET states do not match exactly
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def set(self, value, *, timeout=5, settle_time=0.1):
|
def set(self, value, *, timeout=5, settle_time=0.1):
|
||||||
"""Overloaded settet that waits for target state"""
|
"""Overloaded setter that waits for target state
|
||||||
|
|
||||||
|
NOTE: The SubscriptionStatus callback does not run in put()
|
||||||
|
"""
|
||||||
# Lazy hardcoded state lookup
|
# Lazy hardcoded state lookup
|
||||||
target = 1 if value in (1, "Measure") else 2
|
target = 1 if value in (1, "Measure") else 2
|
||||||
|
|
||||||
# Define wait until the busy flag goes high
|
# Define wait until an end state is reached
|
||||||
def on_target(*, value, **_):
|
def on_target(*, value, **_):
|
||||||
return bool(value == target)
|
return bool(value == target)
|
||||||
|
|
||||||
# Subscribe in advance and wait for update
|
# Subscribe a monitor in advance and wait for update
|
||||||
status = SubscriptionStatus(self, on_target, timeout=timeout, settle_time=0.1)
|
status = SubscriptionStatus(self, on_target, timeout=timeout, settle_time=0.1)
|
||||||
|
|
||||||
# Set value to start movement
|
# Set value to start movement
|
||||||
super().set(value, settle_time=settle_time).wait()
|
super().set(value, settle_time=settle_time).wait()
|
||||||
|
# Return the monitor
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def check_value(self, value):
|
def check_value(self, value):
|
||||||
|
|||||||
@@ -198,7 +198,8 @@ class SmarGonAxis(PVPositioner):
|
|||||||
|
|
||||||
def omove(self, position, wait=True, timeout=2.0, moved_cb=None):
|
def omove(self, position, wait=True, timeout=2.0, moved_cb=None):
|
||||||
"""Original move command without the BEC wrappers"""
|
"""Original move command without the BEC wrappers"""
|
||||||
status = self.setpoint.set(position, settle_time=0.1).wait()
|
status = self.setpoint.set(position, settle_time=0.1)
|
||||||
|
status.wait()
|
||||||
if not wait:
|
if not wait:
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|||||||
@@ -4,4 +4,6 @@ from .mx_measurements import (
|
|||||||
MeasureRasterSimple,
|
MeasureRasterSimple,
|
||||||
MeasureScreening,
|
MeasureScreening,
|
||||||
MeasureHelical,
|
MeasureHelical,
|
||||||
|
MeasureHelical2,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -353,3 +353,127 @@ class MeasureHelical(AerotechFlyscanBase):
|
|||||||
else:
|
else:
|
||||||
st = yield from self.stubs.send_rpc_and_wait("abr", "complete")
|
st = yield from self.stubs.send_rpc_and_wait("abr", "complete")
|
||||||
st.wait()
|
st.wait()
|
||||||
|
|
||||||
|
|
||||||
|
class MeasureHelical2(AerotechFlyscanBase):
|
||||||
|
"""Helical scan using the OMEGA motor
|
||||||
|
|
||||||
|
Measure an absolute continous line scan from `start` to `start` + `range`
|
||||||
|
during `move_time` on the Omega axis with PSO output.
|
||||||
|
|
||||||
|
The scan itself is executed by the scan service running on the Aerotech
|
||||||
|
controller. Ophyd just configures, launches it and waits for completion.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
>>> scans.standard_wedge(start=42, range=10, move_time=20)
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
start : float
|
||||||
|
Scan start position of the axis.
|
||||||
|
range : float
|
||||||
|
Scan range of the axis.
|
||||||
|
move_time : float
|
||||||
|
Total travel time for the movement [s].
|
||||||
|
ready_rate : float, optional
|
||||||
|
No clue what is this... (default=500)
|
||||||
|
sg_start : (float, float, float, float, float)
|
||||||
|
Complete SmarGon coordinate in tuple form.
|
||||||
|
sg_end : (float, float, float, float, float)
|
||||||
|
Complete SmarGon coordinate in tuple form.
|
||||||
|
sg_steps : int
|
||||||
|
Number of steps with SmarGon.
|
||||||
|
"""
|
||||||
|
|
||||||
|
scan_name = "helicalscan2"
|
||||||
|
required_kwargs = ["start", "range", "move_time", "sg_start", "sg_end", "sg_steps"]
|
||||||
|
point_id = 0
|
||||||
|
|
||||||
|
# def __init__(self, *args, parameter: dict = None, **kwargs):
|
||||||
|
# """Just set num_pos=0 to avoid hanging and override defaults if explicitly set from
|
||||||
|
# parameters.
|
||||||
|
# """
|
||||||
|
# self.num_pos = kwargs["sg_steps"]
|
||||||
|
# super().__init__(*args, parameter=parameter, **kwargs)
|
||||||
|
|
||||||
|
def prepare_positions(self):
|
||||||
|
# Smargon has no velocity control
|
||||||
|
self.smargon_start = np.array(self.caller_kwargs.get("sg_start"))
|
||||||
|
self.smargon_end = np.array(self.caller_kwargs.get("sg_end"))
|
||||||
|
self.smargon_steps = self.caller_kwargs.get("sg_steps")
|
||||||
|
self.smargon_range = self.smargon_end - self.smargon_start
|
||||||
|
self.smargon_step_size = self.smargon_range / self.smargon_steps
|
||||||
|
self.smargon_step_time = self.caller_kwargs.get("move_time") / self.smargon_steps
|
||||||
|
|
||||||
|
logger.info(f"Start:\t{self.smargon_start}")
|
||||||
|
logger.info(f"End:\t{self.smargon_end}")
|
||||||
|
logger.info(f"Steps:\t{self.smargon_steps}")
|
||||||
|
logger.info(f"Range:\t{self.smargon_range}")
|
||||||
|
logger.info(f"StepSize:\t{self.smargon_step_size}")
|
||||||
|
logger.info(f"StepTime:\t{self.smargon_step_time}")
|
||||||
|
|
||||||
|
self.num_pos = self.smargon_steps
|
||||||
|
self.positions = np.linspace(self.smargon_start, self.smargon_end, self.smargon_steps)
|
||||||
|
self.start_pos = self.positions[0, :]
|
||||||
|
# Call super
|
||||||
|
yield from super().prepare_positions()
|
||||||
|
|
||||||
|
# def update_scan_motors(self):
|
||||||
|
# """ Update step scan motors"""
|
||||||
|
# self.scan_motors = ['shx', 'shy', 'shz', 'chi', 'phi']
|
||||||
|
|
||||||
|
def pre_scan(self):
|
||||||
|
"""Mostly just checking if ABR stage is ok..."""
|
||||||
|
# Move roughly to start position
|
||||||
|
st0 = yield from self.stubs.send_rpc("shx", "omove", self.start_pos[0])
|
||||||
|
st1 = yield from self.stubs.send_rpc("shy", "omove", self.start_pos[1])
|
||||||
|
st2 = yield from self.stubs.send_rpc("shz", "omove", self.start_pos[2])
|
||||||
|
st3 = yield from self.stubs.send_rpc("chi", "omove", self.start_pos[3])
|
||||||
|
st4 = yield from self.stubs.send_rpc("phi", "omove", self.start_pos[4])
|
||||||
|
st0.wait()
|
||||||
|
st1.wait()
|
||||||
|
st2.wait()
|
||||||
|
st3.wait()
|
||||||
|
st4.wait()
|
||||||
|
|
||||||
|
# print(f"\n\n{self.readout_priority}\n\n")
|
||||||
|
|
||||||
|
# Call super
|
||||||
|
yield from super().pre_scan()
|
||||||
|
|
||||||
|
def scan_core(self):
|
||||||
|
"""The actual scan logic comes here."""
|
||||||
|
# Kick off the run
|
||||||
|
yield from self.stubs.send_rpc_and_wait("abr", "kickoff")
|
||||||
|
logger.info("Measurement launched on the ABR stage...")
|
||||||
|
|
||||||
|
logger.info("Performing SmarGon stepping...")
|
||||||
|
for _, sg_pos in enumerate(self.positions):
|
||||||
|
# sg_pos = self.smargon_start + ss * self.smargon_step_size
|
||||||
|
# Move to position but don't care
|
||||||
|
st0 = yield from self.stubs.send_rpc("shx", "omove", sg_pos[0])
|
||||||
|
st1 = yield from self.stubs.send_rpc("shy", "omove", sg_pos[1])
|
||||||
|
st2 = yield from self.stubs.send_rpc("shz", "omove", sg_pos[2])
|
||||||
|
st3 = yield from self.stubs.send_rpc("chi", "omove", sg_pos[3])
|
||||||
|
st4 = yield from self.stubs.send_rpc("phi", "omove", sg_pos[4])
|
||||||
|
t_start = time.time()
|
||||||
|
st0.wait()
|
||||||
|
st1.wait()
|
||||||
|
st2.wait()
|
||||||
|
st3.wait()
|
||||||
|
st4.wait()
|
||||||
|
t_end = time.time()
|
||||||
|
t_elapsed = t_end-t_start
|
||||||
|
time.sleep(max(self.smargon_step_time-t_elapsed, 0))
|
||||||
|
yield from self.stubs.read(group="monitored", point_id=self.point_id)
|
||||||
|
self.point_id += 1
|
||||||
|
|
||||||
|
# Wait for scan task to finish
|
||||||
|
if self.abr_complete:
|
||||||
|
if self.abr_timeout is not None:
|
||||||
|
st = yield from self.stubs.send_rpc_and_wait("abr", "complete", self.abr_timeout)
|
||||||
|
st.wait()
|
||||||
|
else:
|
||||||
|
st = yield from self.stubs.send_rpc_and_wait("abr", "complete")
|
||||||
|
st.wait()
|
||||||
|
|||||||
Reference in New Issue
Block a user