diff --git a/README.md b/README.md index 03b8da7..1c897e8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,43 @@ # Debye BEC -Debye-specific plugins and configs for BEC \ No newline at end of file +Debye-specific plugins and configs for BEC + +## How to + +### Open visual studio code +``` +code +``` +### Git +``` +git pull +git push origin feat/add_advanced_scan_modes +git status +``` + +### Start or restart BEC Server +``` +ssh x01da-bec-001 +cd /data/test/x01da-test-bec/bec_deployment +. /data/test/x01da-test-bec/bec_deployment/bec_venv/bin/activate +``` +Then +``` +bec-server start +``` +or +``` +bec-server attach +``` + +after change in code: +- ctrl-c + ctrl-c to stop scan server and device server module +- restart server modules + +### Start BEC Client +``` +ssh x01da-test-cons +cd /data/test/x01da-test-bec/bec_deployment +. /data/test/x01da-test-bec/bec_deployment/bec_venv/bin/activate +bec +``` diff --git a/debye_bec/devices/mo1_bragg.py b/debye_bec/devices/mo1_bragg.py index ae20ddf..35e9918 100644 --- a/debye_bec/devices/mo1_bragg.py +++ b/debye_bec/devices/mo1_bragg.py @@ -12,9 +12,12 @@ import enum import threading import time import traceback +import numpy as np +from scipy.interpolate import BSpline from dataclasses import dataclass from typing import Literal + from bec_lib.logger import bec_logger from ophyd import Component as Cpt from ophyd import ( @@ -231,7 +234,7 @@ class Mo1Bragg(Device, PositionerBase): the NI motor controller via web sockets. """ - USER_ACCESS = ["set_xtal", "stop_scan"] + USER_ACCESS = ["set_xtal", "set_advanced_xas_settings", "stop_scan"] crystal = Cpt(Mo1BraggCrystal, "") encoder = Cpt(Mo1BraggEncoder, "") @@ -523,6 +526,69 @@ 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: + """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 + Args: + """ + offset = low + range = high - low # total range (peak-peak) + + 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 + + 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)) + + 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)) + + tc1 = sf / scan_time * tc + tc2 = t_kink / scan_time * tc + + t_input = [0, sf - tc1, t_kink - tc2, scan_time - sf - tc1, scan_time - tc] + p_input = [0, 0 , p_kink , range , range ] + + cv = np.stack((t_input, p_input)).T # spline coefficients + max_param = len(cv) - degree + kv = np.clip(np.arange(len(cv)+degree+1)-degree,0,max_param) # knots + spl = BSpline(kv, cv, degree) # get spline function + p = spl(np.linspace(0,max_param,n)) + v = spl(np.linspace(0,max_param,n), 1) + a = spl(np.linspace(0,max_param,n), 2) + j = spl(np.linspace(0,max_param,n), 3) + + time, pos = p.T + pos = pos + offset + vel = v[:,1]/v[:,0] + + acc = [] + for item in a: + acc.append(0) if item[1] == 0 else acc.append(item[1]/item[0]) + jerk = [] + for item in j: + jerk.append(0) if item[1] == 0 else jerk.append(item[1]/item[0]) + + dt = np.zeros(len(time)) + for i in range(len(time)): + if i == 0: + dt[i] = 0 + else: + dt[i] = 1000*(time[i]-time[i-1]) + + self.scan_settings.a_scan_pos.put(pos) + self.scan_settings.a_scan_vel.put(vel) + self.scan_settings.a_scan_time.put(dt) + + + + def set_xrd_settings( self, enable_low: bool,