From 10308b56f859b2b909a6de9669f0f5c9e774cd43 Mon Sep 17 00:00:00 2001 From: gac-furka Date: Tue, 26 Jul 2022 15:04:23 +0200 Subject: [PATCH] Mods for July beamtime --- .furka.py.swo | Bin 0 -> 16384 bytes constraints.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ furka.py | 76 ++++++++++++++++++++++++++++++--------- nightscan_4.py | 71 ++++++++++++++++++++++++++++++++++++ qspace.py | 15 ++++++++ tth.py | 57 +++++++++++++++++++++++++++++ undulator.py | 2 +- 7 files changed, 299 insertions(+), 17 deletions(-) create mode 100644 .furka.py.swo create mode 100644 constraints.py create mode 100644 nightscan_4.py create mode 100644 tth.py diff --git a/.furka.py.swo b/.furka.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..f70213c8f5e6e025bfafc1d2733b30f0c0233575 GIT binary patch literal 16384 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 MS|Ty|E?(3A7f6;?mH+?% literal 0 HcmV?d00001 diff --git a/constraints.py b/constraints.py new file mode 100644 index 0000000..2346099 --- /dev/null +++ b/constraints.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +from math import inf + + +class ExtraConstraint: + + def __init__(self, **kwargs): + self.kwargs = _unpack(kwargs) + + def __call__(self, x): + kwargs = self.kwargs + for name, value in x.items(): + vmin = kwargs.get(f"{name}_min", -inf) + vmax = kwargs.get(f"{name}_max", +inf) + check = (vmin <= value < vmax) +# print(name, f"\t{vmin} <= {value} < {vmax}\t->", check) + if not check: + return False + return True + + + +def _unpack(d): + res = {} + for k, v in d.items(): + if k.endswith("_min") or k.endswith("_max"): + res[k] = v + else: + try: + vmin, vmax = v + except (ValueError, TypeError) as e: + raise ValueError(f"cannot unpack {k} = {v} into ({k}_min, {k}_max), need exactly 2 values") from e + res[k + "_min"] = vmin + res[k + "_max"] = vmax + if res != d: + print(f"unpacked: {d} -> {res}") + return res + + + +if __name__ == "__main__": + + cons = ExtraConstraint(beta_min=0, beta_max=10, gamma_max=33) + + + example = { + "alpha": 1, + "beta": 1 + } + + assert cons(example) + + + example = { + "alpha": 1, + "beta": 11 + } + + assert not cons(example) + + + example = { + "gamma": 3 + } + + assert cons(example) + + + example = { + "gamma": 333 + } + + assert not cons(example) + + + cons = ExtraConstraint(alpha=(1, 100)) + + example = { + "alpha": 10 + } + + assert cons(example) + + example = { + "alpha": 1000 + } + + assert not cons(example) + + + badcons = ExtraConstraint(test=33) + + + diff --git a/furka.py b/furka.py index f412772..b2b56e1 100644 --- a/furka.py +++ b/furka.py @@ -18,34 +18,42 @@ from undulator import Undulators from undulator import Mono from undulator import Coupled_MonoUnd + +from tth import Coupled_tth +from tth import LakeShore + from qspace import QSpace3D from qspace import Wavelength from qspace import HistoryDummy +from constraints import ExtraConstraint dummy = DummyAdjustable(units="au") -mot_x = Motor("SATES30-RETRO:MOT_X", name="Retro X") +#mot_x = Motor("SATES30-RETRO:MOT_X", name="Retro X") mot_y = Motor("SATES30-RETRO:MOT_Y", name="Retro Y") -mot_z = Motor("SATES30-RETRO:MOT_Z", name="Retro Z") -mot_theta = Motor("SATES30-RETRO:MOT_RY", name="Retro Theta") +#mot_z = Motor("SATES30-RETRO:MOT_Z", name="Retro Z") +#mot_theta = Motor("SATES30-RETRO:MOT_RY", name="Retro Theta") -retro = SimpleDevice("Retro Stages", x=mot_x, y=mot_y, z=mot_z, theta=mot_theta) +#retro = SimpleDevice("Retro Stages", x=mot_x, y=mot_y, z=mot_z, theta=mot_theta) KBV_RX = PVAdjustable("SATOP31-OKBV178:W_RX.VAL", pvname_moving="SATOP31-OKBV178:MOVING", name = "KB_Vertical_RX") #KBV_RX = PVAdjustable("SATOP31-OKBV178:W_RX.VAL", process_time=1, name = "KBV_RX") KBH_RY = PVAdjustable("SATOP31-OKBH179:W_RY.VAL", pvname_moving="SATOP31-OKBH179:MOVING", name = "KB_Horiz_RY") #KBH_RY = PVAdjustable("SATOP31-OKBH179:W_RY.VAL", process_time=1, name = "KBH_RY") +lxt = PVAdjustable("SLAAT01-LTIM-PDLY:DELAY", pvname_done_moving="SLAAT01-LTIM-PDLY:WAITING", name="LXT") + + #mono_slits = PVAdjustable("SATOP11-OSGM087:EXITSLIT",pvname_done_moving="SATOP31-OEXS132:MOT_H.DMOV", name = "Mono_Slits" ) -n_und_ref = 12 +n_und_ref = 13 n_unds = [ 6, 7, 8, 9, 10, 11, 12, 13, # 14 is the CHIC 15, 16, 17, 18, 19, 20, 21, 22 ] chic_fudge_offset = 0 -Mon2Unds_offset = -5 +Mon2Unds_offset = 9 und = Undulators(n_unds, n_und_ref, chic_fudge_offset, name="z Athos Undulators") #und = Undulators(name="Undulators") @@ -61,15 +69,39 @@ MonUnd = Coupled_MonoUnd( name="Mono+Und" ) +tth_scan = Coupled_tth(delta=0.3885, name="theta 2theta") + +lakeshore = PVAdjustable("SATES30-LS336:LOOP1_SP", "SATES30-LS336:A_RBV", accuracy=0.25, name="Lakeshore Temp") + + + + +#lakeshore = LakeShore(name="Temperature") wl = Wavelength(Mon) + + + mu = Motor("SATES30-RIXS:MOT_SRY.VAL") chi = Motor("SATES30-RIXS:MOT_SRZ.VAL") phi = Motor("SATES30-RIXS:MOT_SRX.VAL") nu = Motor("SATES30-RIXS:MOT_DRY.VAL") q = QSpace3D("SOMETHING:Q", mu, chi, phi, nu, wl) +TX = Motor("SATES30-RIXS:MOT_STX.VAL") +TY = Motor("SATES30-RIXS:MOT_STY.VAL") +TZ = Motor("SATES30-RIXS:MOT_STZ.VAL") +TwoTRY=Motor("SATES30-RIXS:MOT_2TRY.VAL") + + + +PICO_X1 = PVAdjustable("SLAAT31-LMNP-PICO11:DRIVE", name="PICO X1") +PICO_Y1 = PVAdjustable("SLAAT31-LMNP-PICO12:DRIVE", name="PICO Y1") + + + + fake_mu = HistoryDummy.init_from(mu) fake_chi = HistoryDummy.init_from(chi) fake_phi = HistoryDummy.init_from(phi) @@ -77,13 +109,7 @@ fake_nu = HistoryDummy.init_from(nu) fake_q = QSpace3D("FAKE:Q", fake_mu, fake_chi, fake_phi, fake_nu, wl) #fake_q.set_lattice("FAKE:Q", fake_mu, fake_chi, fake_phi, fake_nu, wl) -fake_q.set_lattice("Y-hex", a=5.9, c=43.3) -fake_q.add_orientation((1,0,16), (0,0,1), None, "normal direction") -fake_q.add_orientation((-2,0,1), (0,1,0), None, "beam direction") -fake_q.calc_ub() - - -laser_delay = DelayStage("SLAAT31-LMOT-M808:MOT", name="Laser Delay") +laser_delay = Motor("SLAAT31-LMOT-M808:MOT", name="Laser Delay") laser_WP = Motor("SLAAT31-LMOT-M801:MOT", name="Laser WavePlate") channels = [ @@ -93,15 +119,33 @@ channels = [ "SATES30-LSCP10-FNS:CH0:VAL_GET", "SATES30-LSCP10-FNS:CH1:VAL_GET", "SATES30-LSCP10-FNS:CH2:VAL_GET", + "SATES30-LSCP10-FNS:CH3:VAL_GET", "SATES30-LSCP10-FNS:CH4:VAL_GET", +# "SATOP31-PMOS132-2D:SPECTRUM_CENTER", +# "SATOP31-PMOS132-2D:SPECTRUM_FWHM", +# "SATOP31-PMOS132-2D:SPECTRUM_X", +# "SATOP31-PMOS132-2D:SPECTRUM_Y", +# "SATOP31-PMOS132-2D:processing_parameters", +# "SATES30-CVME-EVR0:CALCS", + "SLAAT21-LSCP01-FNS:CH0:VAL_GET", + "SLAAT21-LSCP01:CH0:1", # "SATES30-LSCP10-FNS:CH0:WFMi" # "SATES31-CAMS187-RIXS1:SPC", # "SATES31-CAMS187-RIXS1:SPC_gauss", # "SATES31-CAMS187-RIXS1:SPC_wgt", - "SATES31-CAMS187-RIXS1:Spectrum", +# "SATES31-CAMS187-RIXS1:Spectrum", # "SATES31-CAMS187-RIXS1:evt_list", - "SATES31-CAMS187-RIXS1:FPICTURE" - +# "SATES31-CAMS187-RIXS1:FPICTURE" + "SATES30-CVME-EVR0:DUMMY_PV1_NBS", + "SATES30-CVME-EVR0:DUMMY_PV2_NBS", + "SATES30-CVME-EVR0:DUMMY_PV3_NBS", + "SATES30-CVME-EVR0:DUMMY_PV4_NBS", + "SATES30-CVME-EVR0:DUMMY_PV5_NBS", + "SATES30-CVME-EVR0:DUMMY_PV6_NBS", + "SATES30-CVME-EVR0:DUMMY_PV7_NBS", + "SATES30-CVME-EVR0:DUMMY_PV8_NBS", + "SATES30-CVME-EVR0:DUMMY_PV9_NBS", + "SATES30-CVME-EVR0:DUMMY_PV10_NBS" ] pvs = [ diff --git a/nightscan_4.py b/nightscan_4.py new file mode 100644 index 0000000..829676d --- /dev/null +++ b/nightscan_4.py @@ -0,0 +1,71 @@ +import time + +#Starting temperature setpoint 202K + +laser_delay.set_target_value(112).wait() + +mu.set_target_value(21.3).wait() +nu.set_target_value(-125.8).wait() + +#Theta scan +scan.scan1D(mu, 20,24,0.2, 1200, "Th_cm", return_to_initial_values=True) + +#DS @ CM +scan.scan1D(laser_delay, 107, 110.2, 0.2, 2400, "DS_range1", return_to_initial_values=False) +scan.scan1D(laser_delay, 110.21, 110.5, 0.01, 2400, "DS_range2", return_to_initial_values=False) +scan.scan1D(laser_delay, 111, 130, 0.5, 2400, "DS_range3", return_to_initial_values=False) + +#DS @ ICM +mu.set_target_value(22.5).wait() +nu.set_target_value(-125.4).wait() +scan.scan1D(laser_delay, 107, 110.2, 0.2, 2400, "DS_range1", return_to_initial_values=False) +scan.scan1D(laser_delay, 110.21, 110.5, 0.01, 2400, "DS_range2", return_to_initial_values=False) +scan.scan1D(laser_delay, 111, 130, 0.5, 2400, "DS_range3", return_to_initial_values=False) + +lakeshore.set_target_value(207).wait() +time.sleep(30*60) + +laser_delay.set_target_value(112).wait() + +mu.set_target_value(21.3).wait() +nu.set_target_value(-125.8).wait() + +#Theta scan +scan.scan1D(mu, 20,24,0.2, 1200, "Th_cm", return_to_initial_values=True) + +#DS @ CM +scan.scan1D(laser_delay, 107, 110.2, 0.2, 2400, "DS_range1", return_to_initial_values=False) +scan.scan1D(laser_delay, 110.21, 110.5, 0.01, 2400, "DS_range2", return_to_initial_values=False) +scan.scan1D(laser_delay, 111, 130, 0.5, 2400, "DS_range3", return_to_initial_values=False) + +#DS @ ICM +mu.set_target_value(22.5).wait() +nu.set_target_value(-125.4).wait() +scan.scan1D(laser_delay, 107, 110.2, 0.2, 2400, "DS_range1", return_to_initial_values=False) +scan.scan1D(laser_delay, 110.21, 110.5, 0.01, 2400, "DS_range2", return_to_initial_values=False) +scan.scan1D(laser_delay, 111, 130, 0.5, 2400, "DS_range3", return_to_initial_values=False) + + +lakeshore.set_target_value(212).wait() +time.sleep(30*60) + +laser_delay.set_target_value(112).wait() + +mu.set_target_value(21.3).wait() +nu.set_target_value(-125.8).wait() + +#Theta scan +scan.scan1D(mu, 20,24,0.2, 1200, "Th_cm", return_to_initial_values=True) + +#DS @ CM +scan.scan1D(laser_delay, 107, 110.2, 0.2, 2400, "DS_range1", return_to_initial_values=False) +scan.scan1D(laser_delay, 110.21, 110.5, 0.01, 2400, "DS_range2", return_to_initial_values=False) +scan.scan1D(laser_delay, 111, 130, 0.5, 2400, "DS_range3", return_to_initial_values=False) + +#DS @ ICM +mu.set_target_value(22.5).wait() +nu.set_target_value(-125.4).wait() +scan.scan1D(laser_delay, 107, 110.2, 0.2, 2400, "DS_range1", return_to_initial_values=False) +scan.scan1D(laser_delay, 110.21, 110.5, 0.01, 2400, "DS_range2", return_to_initial_values=False) +scan.scan1D(laser_delay, 111, 130, 0.5, 2400, "DS_range3", return_to_initial_values=False) + diff --git a/qspace.py b/qspace.py index 75533f1..a64419a 100644 --- a/qspace.py +++ b/qspace.py @@ -11,6 +11,7 @@ from slic.devices.device import Device from slic.devices.simpledevice import SimpleDevice from slic.utils.printing import printable_table +from constraints import ExtraConstraint INDICES = { "h": 0, @@ -87,6 +88,13 @@ class QSpace3D(Device): for name, value in kwargs.items(): setattr(self.dc.cons, name, value) + def get_position(self, *args, extra_cons=None): + wl = self.wavelength.get_current_value() + res = self.dc.hkl.get_position(*args, wl) + if extra_cons: + res = [r for r in res if extra_cons(_flatten_get_position_result(r))] + return res + def hard_constraints(x): if x["betain"]<0: return False @@ -115,6 +123,13 @@ class QSpace3D(Device): +def _flatten_get_position_result(x): + d0, d1 = x + d0 = d0.asdict + return dict(**d0, **d1) + + + class QSpace1D(Adjustable): def __init__(self, ID, index, dc, motors, wavelength): diff --git a/tth.py b/tth.py new file mode 100644 index 0000000..dca84af --- /dev/null +++ b/tth.py @@ -0,0 +1,57 @@ +from time import sleep +import numpy as np +from epics import PV + +from logzero import logger as log + +from slic.core.adjustable import Adjustable +from slic.core.adjustable import PVAdjustable +from slic.core.scanner.scanbackend import wait_for_all #, stop_all +from slic.devices.general.motor import Motor + + +class LakeShore(Adjustable): + + def __init__(self, ID="Temp", units="T", accuracy=0, name="" ): + super().__init__(ID, name=name, units=units) + self.SP_RBV_T=PVAdjustable("SATES30-LS336:LOOP1_SP", "SATES30-LS336:A_RBV", name = "Temp") + self.accuracy=accuracy + + def set_target_value(self, value): + t_T= self.SP_RBV_T.set_target_value(value) + t_T.wait() + + def get_current_value(self): + return self.SP_RBV_T.get_current_value() + + def is_moving(self): + delta = abs(self.SP_RBV_T.pvs.setvalue.get() - self.SP_RBV_T.pvs.readback.get() ) + return (delta > self.accuracy) + + + + + + + + +class Coupled_tth(Adjustable): + + + def __init__(self, ID="tth", units="deg", delta=0, name="" ): + super().__init__(ID, name=name, units=units) + self.SRY = Motor("SATES30-RIXS:MOT_SRY.VAL") + self.DRY = Motor("SATES30-RIXS:MOT_DRY.VAL") + self.delta = delta + + def set_target_value(self, value): + s_SRY = 90 - value + self.delta + s_DRY = -2*value + t_SRY = self.SRY.set_target_value(s_SRY) + t_DRY = self.DRY.set_target_value(s_DRY) + t_SRY.wait() + t_DRY.wait() + def get_current_value(self): + return self.DRY.get_current_value()*(-.5) + def is_moving(self): + return any([self.SRY.is_moving(),self.DRY.is_moving()]) diff --git a/undulator.py b/undulator.py index d190c55..92e0a1c 100644 --- a/undulator.py +++ b/undulator.py @@ -106,7 +106,7 @@ class Undulators(Adjustable): class Undulator(PVAdjustable): - def __init__(self, name, accuracy=0.0005): + def __init__(self, name, accuracy=0.5): pvname_setvalue = name + ":K_SET" pvname_readback = name + ":K_READ" super().__init__(pvname_setvalue, pvname_readback=pvname_readback, accuracy=accuracy, active_move=True, name=name, internal=True)