Dailiy commit

This commit is contained in:
Unknown MX Person
2024-09-18 18:26:54 +02:00
parent 23aadabfd1
commit 2563471ac8

View File

@@ -48,6 +48,9 @@ class AerotechFlyscanBase(AsyncFlyScanBase):
Low-level base class for standard scans at the PX beamlines at SLS. Theese scans use the
A3200 rotation stage and the actual experiment is performed using an AeroBasic script
controlled via global variables.
IMPORTANT: The AeroBasic scripts take care of the PSO configuration.
"""
scan_report_hint = "table"
arg_input = {}
@@ -126,17 +129,17 @@ class AerotechFlyscanBase(AsyncFlyScanBase):
class MeasureStandardWedge(AerotechFlyscanBase):
""" Standard wedge scan
""" Standard wedge scan using the OMEGA motor
Measure a standard continous line scan from `start` to `start` + `range`
during `scan_time` on the Omega axis.
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, scan_time=20)
>>> scans.standard_wedge(start=42, range=10, move_time=20)
Parameters
----------
@@ -144,26 +147,26 @@ class MeasureStandardWedge(AerotechFlyscanBase):
Scan start position of the axis.
range : (float, float)
Scan range of the axis.
scan_time : (float)
Total fly time for the movement [s].
move_time : (float)
Total travel time for the movement [s].
ready_rate : float, optional
No clue what is this... (default=500)
"""
scan_name = "standard_wedge"
required_kwargs = ["start", "range", "scan_time"]
required_kwargs = ["start", "range", "move_time"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
self.axis = ['abr.omega']
# Set parameters from meaningful inputs
self.scan_start = parameter['kwargs'].get("start")
self.scan_range = parameter['kwargs'].get("range")
self.scan_scan_time = parameter['kwargs'].get("scan_time")
self.scan_move_time = parameter['kwargs'].get("move_time")
self.scan_ready_rate = parameter['kwargs'].get("ready_rate", 500)
self.abr_command = AbrCmd.MEASURE_STANDARD
self.abr_globals = {
"var_1" : self.scan_start,
"var_2" : self.scan_range,
"var_3" : self.scan_scan_time,
"var_3" : self.scan_move_time,
"var_4" : self.scan_ready_rate,
}
# Call base class
@@ -171,40 +174,88 @@ class MeasureStandardWedge(AerotechFlyscanBase):
class MeasureScanSlits(AerotechFlyscanBase):
""" Slit scan
Measure a standard slit scan.
class MeasureVerticalLine(AerotechFlyscanBase):
""" Vertical line scan using the GMY motor
Simple relative continous line scan that records a single vertical line
with PSO output. There's no actual stepping, it's only used for velocity
calculation.
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.slit_scan(start=42, range=10, scan_time=20)
>>> scans.measure_vline(range_y=12, steps_y=40, exp_time=0.1)
Parameters
----------
delta_x : (float, float)
Scan range with slit in x.
delta_y : (float, float)
Scan range with slit in y.
velocity : (float)
Scan velocity [mm/s].
range_y : float
Step size [mm].
steps_y : int
Scan range of the axis.
exp_time : float
Eeffective exposure time per step [s]
"""
scan_name = "slit_scan"
required_kwargs = ["delta_x", "delta_y", "velocity"]
scan_name = "measure_vline"
required_kwargs = ["exp_time", "range_y", "steps_y"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = []
self.axis = ['abr.gmy']
# Set parameters from meaningful inputs
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_range_y = parameter['kwargs'].get("range_y")
self.scan_stepnum_y = parameter['kwargs'].get("steps_y")
self.scan_stepsize_y = self.scan_range_y / self.scan_stepnum_y
self.abr_command = AbrCmd.VERTICAL_LINE_SCAN
self.abr_globals = {
'var_1': self.scan_exp_time,
'var_2': self.scan_stepsize_y,
'var_3': self.scan_stepnum_y,
}
# Call base class
super().__init__(parameter=parameter, **kwargs)
class MeasureScanSlits(AerotechFlyscanBase):
""" Coordinated scan
Measure a hardware coordinated relative line scan with the X- and Y axes.
This is used to accurately track solid supports with long linear grooves,
as theese might be slightly rotated.
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.slit_scan(range=[10, 0.3], scan_time=20)
Parameters
----------
range_x : float
Move distance in X [mm].
range_y : float
Move distance in Y [mm].
velocity : float
Effective movement velocity [mm/s].
"""
scan_name = "slit_scan"
required_kwargs = ["range", "velocity"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ["abr.gmx", "abr.gmy"]
# Set parameters from meaningful inputs
self.abr_command = AbrCmd.SLIT_SCAN
self.scan_delta_x = parameter['kwargs'].get("delta_x")
self.scan_delta_y = parameter['kwargs'].get("delta_y")
self.scan_range_x = parameter['kwargs'].get("range_x")
self.scan_range_y = parameter['kwargs'].get("range_y")
self.scan_velocity = parameter['kwargs'].get("velocity")
self.abr_globals = {
"var_1" : self.scan_delta_x,
"var_2" : self.scan_delta_y,
"var_1" : self.scan_range_x,
"var_2" : self.scan_range_y,
"var_3" : self.scan_velocity,
}
# Call base class
@@ -215,40 +266,45 @@ class MeasureScanSlits(AerotechFlyscanBase):
class MeasureRasterSimple(AerotechFlyscanBase):
""" Simple raster scan
Measure a simplified raster scan, assuming the goniometer is currently
at the CENTER of TOP-LEFT CELL.
Measure a simplified relative zigzag raster scan in the X-Y plane.
The scan is relative assumes the goniometer is currently at the CENTER of
the first cell (i.e. TOP-LEFT). Each line is executed as a single continous
movement, i.e. there's no actual stepping in the X direction.
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.raster_simple(exp_time=0.5, cell_width=0.2, cell_height=0.2, ncols=10, nrows=10)
>>> scans.raster_simple(exp_time=0.1, range_x=4, range_y=4, steps_x=80, steps_y=80)
Parameters
----------
exp_time : (float)
Exposure time per point [s].
cell_width : (float)
exp_time : float
Effective exposure time for each cell along the X axis [s].
range_x : float
Scan step size [mm].
cell_height : (float)
range_y : float
Scan step size [mm].
ncols : (int)
Number of scan steps.
nrows : (int)
Number of scan steps.
steps_x : int
Number of scan steps in X (fast). Only used for velocity calculation.
steps_y : int
Number of scan steps in Y (slow).
"""
scan_name = "raster_simple"
required_kwargs = ["exp_time", "cell_width", "cell_height", "ncols", "nrows"]
required_kwargs = ["exp_time", "range_x", "range_y", "steps_x", "steps_y"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = []
self.axis = ['abr.gmx', 'abr.gmy']
# Set parameters from meaningful inputs
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_stepsize_x = parameter['kwargs'].get("cell_width")
self.scan_stepsize_y = parameter['kwargs'].get("cell_height")
self.scan_stepnum_x = parameter['kwargs'].get("ncols")
self.scan_stepnum_y = parameter['kwargs'].get("nrows")
self.scan_range_x = parameter['kwargs'].get("range_x")
self.scan_range_y = parameter['kwargs'].get("range_y")
self.scan_stepnum_x = parameter['kwargs'].get("steps_x")
self.scan_stepnum_y = parameter['kwargs'].get("steps_y")
self.scan_stepsize_x = self.scan_range_x / self.scan_stepnum_x
self.scan_stepsize_y = self.scan_range_y / self.scan_stepnum_y
self.abr_command = AbrCmd.RASTER_SCAN_SIMPLE
self.abr_raster_reset = True
self.abr_globals = {
@@ -269,29 +325,33 @@ class MeasureRasterSimple(AerotechFlyscanBase):
class MeasureSASTT(AerotechFlyscanBase):
""" Small angle scanning tensor tomography scan
Measure a Small Angle Scanning Tensor Tomography scan on the specified
grid assuming the goniometer is currently at the CENTER of the required
grid.
Measure a single projection for Small Angle Scanning Tensor Tomography.
It's essentially a separate grid scan, that can be modified independently.
The scan is relative and assumes the goniometer is currently at the CENTER
of the first cell (i.e. TOP-LEFT). Each line is executed as a single
continous movement, there's no actual stepping in the X direction.
NOTE: Not all beamlines have all SASTT modes implemented.
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.measure_sastt(exp_time=1.0, cell_width=0.01, cell_height=0.01, ncols=100, nrows=100)
>>> scans.measure_sastt(exp_time=0.01, range_x=1, range_y=1, steps_x=200, steps_y=200)
Parameters
----------
exp_time : (float)
Exposure time per point [s].
cell_width : (float)
exp_time : float
Effective exposure time for each cell along the X axis [s].
range_x : float
Scan step size [mm].
cell_height : (float)
range_y : float
Scan step size [mm].
ncols : (int)
Number of scan steps.
nrows : (int)
Number of scan steps.
steps_x : int
Number of scan steps in X (fast). Only used for velocity calculation.
steps_y : int
Number of scan steps in Y (slow).
odd_tweak : (float)
Distance to be added before the open shutter command [mm].
Used only in scan version=3. Should be small (default: 0)!
@@ -305,10 +365,10 @@ class MeasureSASTT(AerotechFlyscanBase):
3 = snake scan alternating PSO window for even/odd rows
"""
scan_name = "measure_sastt"
required_kwargs = ["exp_time", "cell_width", "cell_height", "ncols", "nrows"]
required_kwargs = ["exp_time", "range_x", "range_y", "steps_x", "steps_y"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = []
self.axis = ['abr.gmx', 'abr.gmy']
# Set parameters from meaningful inputs
self.scan_version = int(parameter['kwargs'].get("version", 1))
if self.scan_version==1:
@@ -319,14 +379,18 @@ class MeasureSASTT(AerotechFlyscanBase):
self.abr_command = AbrCmd.SCAN_SASTT_V3
else:
raise RuntimeError(f"Non existing SAS-TT scan mode: {self.scan_version}")
# Set parameters from meaningful inputs
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_stepsize_x = parameter['kwargs'].get("cell_width")
self.scan_stepsize_y = parameter['kwargs'].get("cell_height")
self.scan_stepnum_x = parameter['kwargs'].get("ncols")
self.scan_stepnum_y = parameter['kwargs'].get("nrows")
self.scan_range_x = parameter['kwargs'].get("range_x")
self.scan_range_y = parameter['kwargs'].get("range_y")
self.scan_stepnum_x = parameter['kwargs'].get("steps_x")
self.scan_stepnum_y = parameter['kwargs'].get("steps_y")
self.scan_even_tweak = parameter['kwargs'].get("even_tweak", 0)
self.scan_odd_tweak = parameter['kwargs'].get("odd_tweak", 0)
self.scan_stepsize_x = self.scan_range_x / self.scan_stepnum_x
self.scan_stepsize_y = self.scan_range_y / self.scan_stepnum_y
self.abr_globals = {
'var_1': self.scan_exp_time,
'var_2': self.scan_stepsize_x,
@@ -342,90 +406,57 @@ class MeasureSASTT(AerotechFlyscanBase):
class MeasureVerticalLine(AerotechFlyscanBase):
""" Vertical line scan using the GMY motor
Simple fly scan that records a single vertical line.
The line is nummCells * cellHeight long and the exposureTime is per cell.
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.measure_vline(cell_height=12, cell_num=10, cell_time=20)
Parameters
----------
cell_height : (float)
Step size [mm].
cell_num : (int)
Scan range of the axis.
cell_time : (float)
Exposure time per cell [s]
"""
scan_name = "measure_vline"
required_kwargs = ["cell_time", "cell_height", "cell_num"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['gmy']
# Set parameters from meaningful inputs
self.scan_cell_time = parameter['kwargs'].get("cell_time")
self.scan_stepsize_y = parameter['kwargs'].get("cell_height")
self.scan_stepnum_y = parameter['kwargs'].get("cell_num")
self.abr_command = AbrCmd.VERTICAL_LINE_SCAN
self.abr_globals = {
'var_1': self.scan_cell_time,
'var_2': self.scan_stepsize_y,
'var_3': self.scan_stepnum_y,
}
# Call base class
super().__init__(parameter=parameter, **kwargs)
class MeasureScreening(AerotechFlyscanBase):
""" Sample screening scan
Sample screening scan that scans intervals on the rotation axis taking
1 image/interval. This makes sure that we hit diffraction peaks if there
are any crystals.
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.measure_screening(start=42, range=10, scan_time=20, degrees=180, frames=1800)
>>> scans.measure_screening(start=42, range=180, steps=18, exp_time=0.1, oscrange=2.0)
Parameters
----------
start : float
Scan start position of the axis.
Absolute scan start position of the omega axis [deg].
range : float
Scan range of the axis.
scan_time : float
Total scan time for the movement [s].
degrees : (???)
frames : (???)
delta : (???)
(default: 0.5).
Total screened range of the omega axis relative to 'start' [deg].
steps : int
Number of blurred intervals.
exp_time : float
Exposure time per blurred interval [s].
oscrange : float
Motion blurring of each interval [deg]
delta : float
Safety margin for sub-range movements (default: 0.5) [deg].
"""
scan_name = "measure_screening"
required_kwargs = ["start", "range", "scan_time", "degrees", "frames"]
required_kwargs = ["start", "range", "steps", "exp_time", "oscrange"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['gmy']
# Set parameters from meaningful inputs
self.scan_start = parameter['kwargs'].get("start")
self.scan_range = parameter['kwargs'].get("range")
self.scan_scan_time = parameter['kwargs'].get("scan_time")
self.scan_degrees = parameter['kwargs'].get("degrees")
self.scan_frames = parameter['kwargs'].get("frames")
self.scan_range_o = parameter['kwargs'].get("range")
self.scan_stepnum_o = parameter['kwargs'].get("steps")
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_oscrange = parameter['kwargs'].get("oscrange")
self.scan_delta = parameter['kwargs'].get("delta", 0.5)
self.scan_stepsize_o = self.scan_range_o / self.scan_stepnum_o
self.abr_command = AbrCmd.SCREENING
self.abr_globals = {
"var_1" : self.scan_start,
"var_2" : self.scan_range,
"var_3" : self.scan_scan_time,
"var_4" : self.scan_degrees,
"var_5" : self.scan_frames,
"var_2" : self.scan_oscrange,
"var_3" : self.scan_exp_time,
"var_4" : self.scan_stepsize_o,
"var_5" : self.scan_stepnum_o,
"var_6" : self.scan_delta,
}
# Call base class
@@ -436,28 +467,32 @@ class MeasureScreening(AerotechFlyscanBase):
class MeasureFastOmega(AerotechFlyscanBase):
""" Fast omega scan
MEasures a fast rotational scan with the rotation stage (omega).
Performs a fast rotational scan with the rotation stage (omega). It ramps
up to constant speed and sets off PSO for the expected travel time. I.e.
not really a PSO output (as it ignores acceleration distance) but it's
expected to trigger at-speed for 'range' distance.
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.measure_fast_omega(start=42, range=180, scan_time=20)
>>> scans.measure_fast_omega(start=42, range=180, move_time=1.0)
Parameters
----------
start : float
Scan start position of the axis.
Scan start position of the axis [deg].
range : float
Scan range of the axis.
scan_time : float
Total scan time for the movement [s].
At-speed range of the axis relative to 'start' + acceleration
distance [deg].
move_time : float
Total time for the at-speed movement and trigger [s].
rate : (???)
(default: 200).
"""
scan_name = "measure_fast_omega"
required_kwargs = ["start", "range", "scan_time"]
required_kwargs = ["start", "range", "move_time"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
@@ -465,14 +500,14 @@ class MeasureFastOmega(AerotechFlyscanBase):
logger.info(parameter)
self.scan_start = parameter['kwargs'].get("start")
self.scan_range = parameter['kwargs'].get("range")
self.scan_scan_time = parameter['kwargs'].get("scan_time")
self.scan_rate = parameter['kwargs'].get("rate", 200)
self.scan_move_time = parameter['kwargs'].get("move_time")
self.scan_acceleration = parameter['kwargs'].get("acceleration", 200)
self.abr_command = AbrCmd.SUPER_FAST_OMEGA
self.abr_globals = {
"var_1" : self.scan_start,
"var_2" : self.scan_range,
"var_3" : self.scan_scan_time,
"var_4" : self.scan_rate,
"var_3" : self.scan_move_time,
"var_4" : self.scan_acceleration,
}
# Call base class
super().__init__(parameter=parameter, **kwargs)
@@ -482,42 +517,47 @@ class MeasureFastOmega(AerotechFlyscanBase):
class MeasureStillWedge(AerotechFlyscanBase):
""" Still wedge scan
Measure a simple step scan with the omega stage with PSO triggering.
The scan is similar to the continous wedge scan.
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.measure_still_wedge(start=42, range=90, scan_time=20, oscrange=15)
>>> scans.measure_still_wedge(start=42, range=180, exp_time=0.1, steps=60)
Parameters
----------
start : (float)
Scan start position of the axis.
Scan start position of the axis [mm].
range : (float)
Scan range of the axis.
scan_time : (float)
Total scan time for the movement [s].
oscrange : (float)
Scan range of the omega axis [mm].
exp_time : (float)
Exposure time per point [s].
steps : int
Number of actual steps.
sleep_after_shutter_close : (float)
[s] (default: 0.01).
"""
scan_name = "measure_still_wedge"
required_kwargs = ["start", "range", "exp_time", "oscrange"]
required_kwargs = ["start", "range", "exp_time", "steps"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
self.axis = ['abr.omega']
# Set parameters from meaningful inputs
self.scan_start = parameter['kwargs'].get("start")
self.scan_range = parameter['kwargs'].get("range")
self.scan_scan_time = parameter['kwargs'].get("scan_time")
self.scan_oscrange = parameter['kwargs'].get("oscrange")
self.scan_stepnum_o = parameter['kwargs'].get("steps")
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_shutter_sleep = parameter['kwargs'].get("sleep_after_shutter_close", 0.01)
self.scan_stepsize_o = self.scan_stepnum_o / self.scan_stepnum_o
self.abr_command = AbrCmd.STILL_WEDGE
self.abr_globals = {
"var_1" : self.scan_start,
"var_2" : self.scan_range,
"var_3" : self.scan_scan_time,
"var_4" : self.scan_oscrange,
"var_3" : self.scan_exp_time,
"var_4" : self.scan_stepsize_o,
"var_5" : self.scan_shutter_sleep,
}
# Call base class
@@ -528,37 +568,37 @@ class MeasureStillWedge(AerotechFlyscanBase):
class MeasureStills(AerotechFlyscanBase):
""" Still image sequence scan
Measures a series of still images without any motor movement.
IMPORTANT: use idle_time=0.0 to prevent shutter open/close
Measures a series of PSO triggered images without any motor movement.
NOTE: Use idle_time=0.0 to prevent shutter open/close.
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.measure_stills(nframes=100, exp_time=0.1, idle_time=30)
>>> scans.measure_stills(steps=100, exp_time=0.1, idle_time=3)
Parameters
----------
nframes : int
steps : int
Total number of frames to be recorded.
exposure_time : float
exp_time : float
Exposure time of each frame [s].
idle_time : float
Sleep time between the frames [s].
"""
scan_name = "measure_stills"
required_kwargs = ["exp_time", "nframes", "idle_time"]
required_kwargs = ["exp_time", "steps", "idle_time"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = []
# Set parameters from meaningful inputs
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_num_frames = parameter['kwargs'].get("nframes")
self.scan_numsteps = parameter['kwargs'].get("steps")
self.scan_idle_time = parameter['kwargs'].get("idle_time")
self.abr_command = AbrCmd.STILLS
self.abr_globals = {
"var_1" : self.scan_num_frames,
"var_1" : self.scan_numsteps,
"var_2" : self.scan_exp_time,
"var_3" : self.scan_idle_time,
}
@@ -570,42 +610,44 @@ class MeasureStills(AerotechFlyscanBase):
class MeasureSingleOscillation(AerotechFlyscanBase):
""" Single oscillation scan
Short line scan with the omega axis with PSO trigger.
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.measure_single_osc(start=42, range=180, scan_time=20)
>>> scans.measure_single_osc(start=42, range=180, move_time=20)
Parameters
----------
start : float
Scan start position of the axis.
Scan start position of the omegaaxis [mm].
range : float
Oscillation range of the axis.
scan_time : float
Oscillation range of the axis [mm].
move_time : float
Total scan time for the movement [s].
delta : (???)
(default: 0).
Safety margin for movement (default: 0).
settle : (???)
(default: 0.5).
"""
scan_name = "measure_single_osc"
required_kwargs = ["start", "range", "scan_time"]
required_kwargs = ["start", "range", "move_time"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
self.axis = ['abr.omega']
# Set parameters from meaningful inputs
self.scan_start = parameter['kwargs'].get("start")
self.scan_range = parameter['kwargs'].get("range")
self.scan_scan_time = parameter['kwargs'].get("scan_time")
self.scan_move_time = parameter['kwargs'].get("move_time")
self.scan_delta = parameter['kwargs'].get("delta", 0)
self.scan_settle = parameter['kwargs'].get("settle", 0.5)
self.abr_command = AbrCmd.SINGLE_OSCILLATION
self.abr_globals = {
"var_1" : self.scan_start,
"var_2" : self.scan_range,
"var_3" : self.scan_scan_time,
"var_3" : self.scan_move_time,
"var_4" : self.scan_delta,
"var_5" : self.scan_settle,
}
@@ -617,41 +659,44 @@ class MeasureSingleOscillation(AerotechFlyscanBase):
class MeasureRepeatedOscillation(AerotechFlyscanBase):
""" Repeated oscillation scan
Repeated relative line scans with the omega axis with PSO enable trigger.
The lines are performed in zigzag mode with PSO triggering.
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.measure_multi_osc(start=42, range=180, scan_time=20)
>>> scans.measure_multi_osc(steps=50, range=30, move_time=3)
Parameters
----------
nframes : int
???
scan_time : float
steps : int
Number of cycles to repeat the scan
move_time : float
Total scan time for the movement [s].
range : float
Oscillation range of the axis.
Relative oscillation range of the omega axis [deg].
settle : (???)
(default: 0).
Movement settle time after each line (default: 0) [s].
delta : (???)
(default: 0.5).
Safety margin for movement (default: 0.5) [deg].
"""
scan_name = "measure_multi_osc"
required_kwargs = ["nframes", "range", "scan_time"]
required_kwargs = ["steps", "range", "scan_time"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
# Set parameters from meaningful inputs
self.scan_num_frames = parameter['kwargs'].get("nframes")
self.scan_stepnum = parameter['kwargs'].get("steps")
self.scan_range = parameter['kwargs'].get("range")
self.scan_scan_time = parameter['kwargs'].get("scan_time")
self.scan_move_time = parameter['kwargs'].get("move_time")
self.scan_sleep = parameter['kwargs'].get("sleep", 0)
self.scan_delta = parameter['kwargs'].get("delta", 0.5)
self.abr_command = AbrCmd.REPEAT_SINGLE_OSCILLATION
self.abr_globals = {
"var_1" : self.scan_num_frames,
"var_2" : self.scan_scan_time,
"var_1" : self.scan_stepnum,
"var_2" : self.scan_move_time,
"var_3" : self.scan_range,
"var_4" : self.scan_sleep,
"var_5" : self.scan_delta,
@@ -664,12 +709,15 @@ class MeasureRepeatedOscillation(AerotechFlyscanBase):
class MeasureMSOX(AerotechFlyscanBase):
""" Standard MSOX scan
MSOX experiment for Florian, i.e. a glorified oscillation scan this time
with absolute positions. The lines are unidirectional with PSO triggering.
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.measure_msox(start=42, range=10, exp_time=0.1)
>>> scans.measure_msox(start=42, range=30, move_time=3.0)
Parameters
----------
@@ -677,32 +725,32 @@ class MeasureMSOX(AerotechFlyscanBase):
Scan start position of the axis.
range : float
Scan range of the axis.
exp_time : float
move_time : float
Exposure time for each point [s].
num_datasets : int
???
rest_time : float
???
steps : int
Number of repeats.
settle_time : float
Settle time before line start (default=0) [s].
"""
scan_name = "measure_msox"
required_kwargs = ["start", "range", "exp_time"]
required_kwargs = ["start", "range", "move_time"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
self.axis = ['abr.omega']
# Set parameters from meaningful inputs
self.scan_start = parameter['kwargs'].get("start")
self.scan_range = parameter['kwargs'].get("range")
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_num_datasets = parameter['kwargs'].get("num_datasets", 1)
self.scan_rest_time = parameter['kwargs'].get("rest_time", 0)
self.scan_move_time = parameter['kwargs'].get("move_time")
self.scan_stepnum = parameter['kwargs'].get("steps", 1)
self.scan_settle_time = parameter['kwargs'].get("settle_time", 0)
self.abr_command = AbrCmd.MSOX
self.abr_reset = True
self.abr_globals = {
"var_1" : self.scan_start,
"var_2" : self.scan_range,
"var_3" : self.scan_exp_time,
"var_4" : self.scan_num_datasets,
"var_5" : self.scan_rest_time,
"var_3" : self.scan_move_time,
"var_4" : self.scan_stepnum,
"var_5" : self.scan_settle_time,
"var_6" : 0,
"var_7" : 0,
"var_8" : 0,
@@ -717,6 +765,11 @@ class MeasureMSOX(AerotechFlyscanBase):
class MeasureGrid(AerotechFlyscanBase):
""" General grid scan
Performs an X-Y-Omega coordinated grid scan:
X axis is absolute (fast axis)
Y axis is relative to start
Omega starts at the current value and is synchronized to X
Note: This was probably never used in its current form, because the
code had an undefined variable 'self.position'
@@ -731,12 +784,14 @@ class MeasureGrid(AerotechFlyscanBase):
----------
positions : 2D-array
Scan position of each axis, i.e. (N, 3) shaped array.
ncols : int
Nmber of columns.
steps_x : int
Number of points along the X axis (fast).
steps_y : int
Number of points in the Y axis (slow).
angle:
???
Triggered angular range on the synchronized omega [deg]
exp_time : (float)
Exposure time for each point [s].
Exposure time for each point, only used for number of points and velocity [s].
"""
scan_name = "measure_raster"
required_kwargs = ["positions", "ncols", "angle", "exp_time"]
@@ -750,16 +805,19 @@ class MeasureGrid(AerotechFlyscanBase):
scan_gmy_step = 0.010
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
self.axis = ['abr.omega', 'abr.gmx', 'abr.gmy']
# Set parameters from meaningful inputs
self.abr_command = AbrCmd.RASTER_SCAN
self.abr_reset = True
self.scan_positions = parameter['kwargs'].get("positions")
self.scan_stepnum_x = parameter['kwargs'].get("ncols")
self.scan_stepnum_y = self.scan_positions / self.scan_stepnum_x
self.scan_angle = parameter['kwargs'].get("angle")
self.scan_stepnum_x = parameter['kwargs'].get("steps_x")
self.scan_stepnum_y = parameter['kwargs'].get("steps_y")
self.scan_anglerange = parameter['kwargs'].get("angle")
self.scan_exp_time = parameter['kwargs'].get("exp_time")
if len(self.scan_positions) != self.scan_stepnum_x * self.scan_stepnum_y:
raise RuntimeError("Number of points and positions do not match")
if len(self.scan_positions)==1:
raise RuntimeWarning("Raster scan with one cell makes no sense")
@@ -784,26 +842,17 @@ class MeasureGrid(AerotechFlyscanBase):
self.scan_gmy_step = np.linalg.norm([self.scan_ystep, self.scan_zstep])
# ToDo: Check with Zac what are theese parameters
self.scan_omega_position = yield from self.stubs.send_rpc_and_wait("abs", "omega.readback.get")
self.scan_start_o = yield from self.stubs.send_rpc_and_wait("abs", "omega.readback.get")
self.scan_gmx_offset = yield from self.stubs.send_rpc_and_wait("abs", "gmx.readback.get")
# ToDo : This was left out
# self._raster_starting_x = start_x
# self._raster_starting_y = y1
# self._raster_starting_z = z1
# self._raster_step_y = ystep
# self._raster_step_z = zstep
# self._raster_current_row = 0
# self._raster_num_rows = rows
# Configure the global variables
self.abr_globals = {
"var_1" : self.scan_omega_position,
"var_1" : self.scan_start_o,
"var_2" : self.scan_start_x,
"var_3" : self.scan_end_x,
"var_4" : self.scan_stepnum_x,
"var_5" : self.scan_stepnum_y,
"var_6" : self.scan_angle,
"var_6" : self.scan_anglerange,
"var_7" : self.scan_exp_time,
"var_8" : HALF_PERIOD,
"var_9" : self.scan_gmx_offset,
@@ -815,6 +864,11 @@ class MeasureGrid(AerotechFlyscanBase):
class MeasureGridStill(AerotechFlyscanBase):
""" Still grid scan
Performs an X-Y-Omega coordinated grid scan in stepping mode:
X axis is absolute
Y axis is relative to start
Omega starts at the current value and is synchronized to X
Note: This was probably never used in its current form, because the
code had an undefined variable 'self.position'
@@ -823,7 +877,7 @@ class MeasureGridStill(AerotechFlyscanBase):
Example
-------
>>> scans.measure_raster(positions=[[11, 2, 3.4], [11, 2, 3.5], ...], columns=20, exp_time=0.1, delay=0.05)
>>> scans.measure_raster(positions=[[11, 2, 3.4], [11, 2, 3.5], ...], steps_x=20, steps_y=20, exp_time=0.1, delay=0.05)
Parameters
----------
@@ -839,7 +893,7 @@ class MeasureGridStill(AerotechFlyscanBase):
???
"""
scan_name = "measure_raster_still"
required_kwargs = ["positions", "columns", "exp_time", "delay"]
required_kwargs = ["positions", "steps_x", "steps_y", "exp_time", "delay"]
# Default values
scan_start_x = None
@@ -850,16 +904,19 @@ class MeasureGridStill(AerotechFlyscanBase):
scan_gmy_step = 0.010
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
self.axis = ['abr.gmx', 'abr.gmy', 'abr.omega']
# Set parameters from meaningful inputs
self.abr_command = AbrCmd.RASTER_SCAN_STILL
self.abr_reset = True
self.scan_positions = parameter['kwargs'].get("positions")
self.scan_stepnum_x = parameter['kwargs'].get("columns")
self.scan_stepnum_y = self.scan_positions / self.scan_stepnum_x
self.scan_stepnum_x = parameter['kwargs'].get("steps_x")
self.scan_stepnum_y = parameter['kwargs'].get("steps_y")
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_delay = parameter['kwargs'].get("delay")
if len(self.scan_positions) != self.scan_stepnum_x * self.scan_stepnum_y:
raise RuntimeError("Number of points and positions do not match")
if len(self.scan_positions)==1:
raise RuntimeWarning("Raster scan with one cell makes no sense")
# Call base class
@@ -886,15 +943,6 @@ class MeasureGridStill(AerotechFlyscanBase):
self.scan_omega_position = yield from self.stubs.send_rpc_and_wait("abs", "omega.readback.get")
self.scan_gmx_offset = yield from self.stubs.send_rpc_and_wait("abs", "gmx.readback.get")
# ToDo : This was left out
# self._raster_starting_x = start_x
# self._raster_starting_y = y1
# self._raster_starting_z = z1
# self._raster_step_y = ystep
# self._raster_step_z = zstep
# self._raster_current_row = 0
# self._raster_num_rows = rows
self.abr_globals = {
"var_1" : self.scan_omega_position,
"var_2" : self.scan_start_x,
@@ -922,13 +970,13 @@ class MeasureJungfrau(AerotechFlyscanBase):
Parameters
----------
columns : int
steps_x : int
???
rows : int
steps_y : int
???
width : int
range_x : int
???
height : int
range_y : int
???
exp_time : float
Exposure time per point [s].
@@ -936,15 +984,17 @@ class MeasureJungfrau(AerotechFlyscanBase):
(default: 0.1).
"""
scan_name = "measure_jungfrau"
required_kwargs = ["columns", "rows", "width", "height", "exp_time"]
required_kwargs = ["steps_x", "steps_y", "range_x", "range_y", "exp_time"]
def __init__(self, *args, parameter: dict = None, **kwargs):
self.axis = ['omega']
# Set parameters from meaningful inputs
self.scan_num_cols = parameter['kwargs'].get("columns")
self.scan_num_rows = parameter['kwargs'].get("rows")
self.scan_width = parameter['kwargs'].get("width")
self.scan_height = parameter['kwargs'].get("height")
self.scan_stepnum_x = parameter['kwargs'].get("steps_x")
self.scan_stepnum_y = parameter['kwargs'].get("steps_y")
self.scan_range_x = parameter['kwargs'].get("range_x")
self.scan_range_y = parameter['kwargs'].get("range_y")
self.scan_stepsize_x = self.scan_range_x / self.scan_stepnum_x
self.scan_stepsize_y = self.scan_range_y / self.scan_stepnum_y
self.scan_exp_time = parameter['kwargs'].get("exp_time")
self.scan_sleep = parameter['kwargs'].get("sleep", 0.1)
self.abr_timeout = None if self.scan_sleep <= 0 else 5.0 + (self.scan_num_rows * self.scan_sleep) + (self.scan_num_cols * self.scan_num_rows * self.scan_exp_time)
@@ -952,10 +1002,10 @@ class MeasureJungfrau(AerotechFlyscanBase):
self.abr_reset = True
self.abr_complete = True
self.abr_globals = {
"var_1" : self.scan_num_cols,
"var_2" : self.scan_num_rows,
"var_3" : self.scan_width,
"var_4" : self.scan_height,
"var_1" : self.scan_stepnum_x,
"var_2" : self.scan_stepnum_y,
"var_3" : self.scan_stepsize_x,
"var_4" : self.scan_stepsize_y,
"var_5" : self.scan_exp_time,
"var_6" : self.scan_sleep,
"var_7" : 0,