Changed advanced scan to be used with energy inputs (not angle)

This commit is contained in:
gac-x01da (Resp. Clark Adam Hugh)
2024-09-11 13:27:35 +02:00
committed by gac-x01da
parent 5b46464ef9
commit 38bee8c5c7
2 changed files with 47 additions and 33 deletions

View File

@@ -226,8 +226,8 @@ class ScanParameter:
cycle_high: int = None
start: float = None
stop: float = None
t_kink: float = None
p_kink: float = None
e_kink: float = None
class Mo1Bragg(Device, PositionerBase):
@@ -528,34 +528,51 @@ class Mo1Bragg(Device, PositionerBase):
self.scan_settings.s_scan_angle_hi.put(high)
self.scan_settings.s_scan_scantime.put(scan_time)
def set_advanced_xas_settings(self, low: float, high:float, scan_time: float, t_kink: float, p_kink: float) -> None:
def set_advanced_xas_settings(self, low: float, high:float, scan_time: float, p_kink: float, e_kink: float) -> None:
"""Set Advanced XAS parameters for upcoming scan.
low (float): Low angle value of the scan in deg
high (float): High angle value of the scan in deg
scan_time (float): Time for a half oscillation in s
t_kink (float): Time of kink in s
p_kink (float): Position of kink in deg
p_kink (float): Position of kink in %
e_kink (float): Energy of kink in eV
Args:
"""
offset = low
range = high - low # total range (peak-peak)
## TODO Change to energy only, calculation done on ACS controller
## ACS requires energy as input, outputs angle
## + reset bit signal, + calc done bit signal
## In the meantime, misuse s_scan_angle/energy PVs
move_type = self.move_type.get()
if move_type == MoveType.ENERGY:
self.scan_settings.s_scan_energy_lo.put(e_kink)
time.sleep(1)
e_kink_deg = self.scan_settings.s_scan_angle_hi.get()
self.scan_settings.s_scan_energy_lo.put(low)
self.scan_settings.s_scan_energy_hi.put(high)
time.sleep(1)
low_deg = self.scan_settings.s_scan_angle_lo.get()
high_deg = self.scan_settings.s_scan_angle_hi.get()
sf = 0.025 # safety factor to limit acceleration -> NEVER SET TO ZERO !
n = 41 # number of samples to generate -> Always choose uneven number, otherwise peak value will not be included
degree = 3 # degree of spline, 3 works good
tc = 0.0062 # time to be compensated each spline in s
pc = 0.02 # angle to add at both limits, must be same values as used on ACS controller for simple scans
if t_kink > scan_time / 2 - sf:
raise Exception("Kink time of {0:0.3f} s too big, must be < {1:0.3f} s".format(t_kink, scan_time / 2 - sf))
# increase motion range slightly so that xas trigger signals will occur at defined energy limits
low_deg = low_deg - pc
high_deg = high_deg + pc
if p_kink > range:
raise Exception("Kink position of {0:0.3f}° deg too big, must be < {1:0.3f}° deg".format(p_kink, range))
if p_kink < 0 or p_kink > 100:
raise Exception("Kink position not within range of [0..100%]")
if e_kink_deg < low_deg or e_kink_deg > high_deg:
raise Exception("Kink energy not within selected energy range of scan")
tc1 = sf / scan_time * tc
tc2 = t_kink / scan_time * tc
t_kink = (scan_time - tc - 2*(sf - tc1)) * p_kink/100 + (sf - tc1)
t_input = [0, sf - tc1, t_kink - tc2, scan_time - sf - tc1, scan_time - tc]
p_input = [0, 0 , p_kink , range , range ]
t_input = [0, sf - tc1, t_kink , scan_time - tc - sf + tc1, scan_time - tc ]
p_input = [0, 0 , e_kink_deg - low_deg , high_deg - low_deg , high_deg - low_deg]
cv = np.stack((t_input, p_input)).T # spline coefficients
max_param = len(cv) - degree
@@ -567,7 +584,7 @@ class Mo1Bragg(Device, PositionerBase):
j = spl(np.linspace(0,max_param,n), 3)
tim, pos = p.T
pos = pos + offset
pos = pos + low_deg
vel = v[:,1]/v[:,0]
acc = []
@@ -588,9 +605,6 @@ class Mo1Bragg(Device, PositionerBase):
self.scan_settings.a_scan_vel.put(vel)
self.scan_settings.a_scan_time.put(dt)
def set_xrd_settings(
self,
enable_low: bool,
@@ -755,8 +769,8 @@ class Mo1Bragg(Device, PositionerBase):
low=self.scan_parameter.start,
high=self.scan_parameter.stop,
scan_time=self.scan_parameter.scan_time,
t_kink=self.scan_parameter.t_kink,
p_kink=self.scan_parameter.p_kink,
e_kink=self.scan_parameter.e_kink,
)
self.set_xrd_settings(
enable_low=False,
@@ -776,8 +790,8 @@ class Mo1Bragg(Device, PositionerBase):
low=self.scan_parameter.start,
high=self.scan_parameter.stop,
scan_time=self.scan_parameter.scan_time,
t_kink=self.scan_parameter.t_kink,
p_kink=self.scan_parameter.p_kink,
e_kink=self.scan_parameter.e_kink,
)
self.set_xrd_settings(
enable_low=self.scan_parameter.xrd_enable_low,

View File

@@ -173,7 +173,7 @@ class XASAdvancedScan(XASSimpleScan):
gui_config = {
"Movement Parameters": ["start", "stop"],
"Scan Parameters": ["scan_time", "scan_duration"],
"Spline Parameters": ["t_kink", "p_kink"],
"Spline Parameters": ["p_kink", "e_kink"],
}
def __init__(
@@ -182,27 +182,27 @@ class XASAdvancedScan(XASSimpleScan):
stop: float,
scan_time: float,
scan_duration: float,
t_kink: float,
p_kink: float,
e_kink: float,
motor: DeviceBase = "mo1_bragg",
**kwargs,
):
"""The xas_advanced_scan is an oscillation motion on the mono motor.
Start and Stop define the energy range for the scan, scan_time is the time for one scan cycle and scan_duration
is the duration of the scan. If scan duration is set to 0, the scan will run infinitely.
t_kink and p_kink add a kink to the motion profile to slow down in the exafs region of the scan.
p_kink and e_kink add a kink to the motion profile to slow down in the exafs region of the scan.
Args:
start (float): Start angle for the scan.
stop (float): Stop angle for the scan.
scan_time (float): Time for one oscillation .
scan_duration (float): Total duration of the scan.
t_kink (float): Time of the kink.
p_kink (float): Position of the kink.
e_kink (float): Energy of the kink.
motor (DeviceBase, optional): Motor device to be used for the scan. Defaults to "mo1_bragg".
Examples:
>>> scans.xas_advanced_scan(start=9, stop=11, scan_time=0.5, scan_duration=10, t_kink=0.15, p_kink=1)
>>> scans.xas_advanced_scan(start=9, stop=11, scan_time=0.5, scan_duration=10, p_kink=0.15, e_kink=1)
"""
super().__init__(
start=start,
@@ -212,8 +212,8 @@ class XASAdvancedScan(XASSimpleScan):
motor=motor,
**kwargs,
)
self.t_kink = t_kink
self.p_kink = p_kink
self.e_kink = e_kink
class XASAdvancedScanWithXRD(XASAdvancedScan):
@@ -221,7 +221,7 @@ class XASAdvancedScanWithXRD(XASAdvancedScan):
gui_config = {
"Movement Parameters": ["start", "stop"],
"Scan Parameters": ["scan_time", "scan_duration"],
"Spline Parameters": ["t_kink", "p_kink"],
"Spline Parameters": ["p_kink", "e_kink"],
"Low Energy Range": ["xrd_enable_low", "num_trigger_low", "exp_time_low", "cycle_low"],
"High Energy Range": ["xrd_enable_high", "num_trigger_high", "exp_time_high", "cycle_high"],
}
@@ -232,8 +232,8 @@ class XASAdvancedScanWithXRD(XASAdvancedScan):
stop: float,
scan_time: float,
scan_duration: float,
t_kink: float,
p_kink: float,
e_kink: float,
xrd_enable_low: bool,
num_trigger_low: int,
exp_time_low: float,
@@ -249,15 +249,15 @@ class XASAdvancedScanWithXRD(XASAdvancedScan):
with XRD triggering at low and high energy ranges.
Start and Stop define the energy range for the scan, scan_time is the time for one scan cycle and scan_duration
is the duration of the scan. If scan duration is set to 0, the scan will run infinitely.
t_kink and p_kink add a kink to the motion profile to slow down in the exafs region of the scan.
p_kink and e_kink add a kink to the motion profile to slow down in the exafs region of the scan.
Args:
start (float): Start angle for the scan.
stop (float): Stop angle for the scan.
scan_time (float): Time for one oscillation .
scan_duration (float): Total duration of the scan.
t_kink (float): Time of the kink.
p_kink (float): Position of the kink.
p_kink (float): Position of kink.
e_kink (float): Energy of the kink.
xrd_enable_low (bool): Enable XRD triggering for the low energy range.
num_trigger_low (int): Number of triggers for the low energy range.
exp_time_low (float): Exposure time for the low energy range.
@@ -269,20 +269,20 @@ class XASAdvancedScanWithXRD(XASAdvancedScan):
motor (DeviceBase, optional): Motor device to be used for the scan. Defaults to "mo1_bragg".
Examples:
>>> scans.xas_advanced_scan_with_xrd(start=9, stop=11, scan_time=0.5, scan_duration=10, t_kink=0.15, p_kink=1, xrd_enable_low=True, num_trigger_low=5, cycle_low=2, exp_time_low=100, xrd_enable_high=False, num_trigger_high=3, cycle_high=1, exp_time_high=1000)
>>> scans.xas_advanced_scan_with_xrd(start=9, stop=11, scan_time=0.5, scan_duration=10, p_kink=0.15, e_kink=1, xrd_enable_low=True, num_trigger_low=5, cycle_low=2, exp_time_low=100, xrd_enable_high=False, num_trigger_high=3, cycle_high=1, exp_time_high=1000)
"""
super().__init__(
start=start,
stop=stop,
scan_time=scan_time,
scan_duration=scan_duration,
t_kink=t_kink,
p_kink=p_kink,
e_kink=e_kink,
motor=motor,
**kwargs,
)
self.t_kink = t_kink
self.p_kink = p_kink
self.e_kink = e_kink
self.xrd_enable_low = xrd_enable_low
self.num_trigger_low = num_trigger_low
self.exp_time_low = exp_time_low