diff --git a/devices/undulator.py b/devices/undulator.py index 5b1525c..7f795ad 100644 --- a/devices/undulator.py +++ b/devices/undulator.py @@ -21,7 +21,7 @@ class Undulators(Adjustable): for n_und_ref=None (default), the reference undulator currently used by the machine will be used """ - def __init__(self, n_unds=N_UNDS, n_und_ref=None, chic_fudge_offset=0, adjust_chic=True, scaled=True, ID="ATHOS_UNDULATORS", name="Athos Undulators", units="eV"): + def __init__(self, n_unds=N_UNDS, n_und_ref=None, chic_fudge_offset=0, adjust_chic=False, scaled=True, ID="ATHOS_UNDULATORS", name="Athos Undulators", units="eV"): super().__init__(ID, name=name, units=units) @@ -53,7 +53,9 @@ class Undulators(Adjustable): self.und_name_cal = und_name_cal = UND_NAME_FMT.format(n_und_ref) self.adjs = {name: Undulator(name) for name in und_names} - self.chic = CHIC(chic_fudge_offset, name, units) +# self.chic = CHIC(chic_fudge_offset, name, units) + self.phases = Phases(n_unds) + self.adjust_chic = adjust_chic self.scaled = scaled @@ -98,28 +100,35 @@ class Undulators(Adjustable): wait_for_all(tasks) # make sure new K values have been written TODO: needed? - sleep(0.5) + sleep(2) # check if this can be shortened back to 0.5 # switching on radial motors ... wait_for_all([ a.adj_radial_on.set_target_value(1, hold=False) for a in self.adjs.values() ]) - # ... and pushing go to ensure proper movements - wait_for_all([ - a.adj_radial_go.set_target_value(1, hold=False) for a in self.adjs.values() - ]) + # press a few times + for _ in range(3): + # ... and pushing go to ensure proper movements + wait_for_all([ + a.adj_radial_go.set_target_value(1, hold=False) for a in self.adjs.values() + ]) + sleep(0.2) - # make sure the undulators finished moving TODO: needed? - sleep(5) +# # make sure the undulators finished moving TODO: needed? +# sleep(5) if self.adjust_chic: print("CHIC adjustment follows") - self.chic.set_target_value(value, hold=False).wait() #TODO: test whether an additional sleep is needed +# self.chic.set_target_value(value, hold=False).wait() #TODO: test whether an additional sleep is needed + self.phases.set(value) print("CHIC adjustment done") else: print("CHIC adjustment skipped") + # make sure the undulators and phases finished moving TODO: needed? + sleep(7) + return self._as_task(change, hold=hold) @@ -152,8 +161,10 @@ class Undulator(PVAdjustable): pvname_readback = name + ":K_READ" super().__init__(pvname_setvalue, pvname_readback=pvname_readback, accuracy=accuracy, active_move=True, name=name, internal=True) self.adj_energy = PVAdjustable(name + ":FELPHOTENE", internal=True) - self.adj_radial_on = PVAdjustable(name + ":RADIAL-ON.PROC", internal=True) - self.adj_radial_go = PVAdjustable(name + ":RADIAL-GO.PROC", internal=True) + self.adj_radial_on = PVAdjustable(name + ":RADIAL-ON", internal=True) + self.adj_radial_go = PVAdjustable(name + ":RADIAL-GO", internal=True) +# self.adj_radial_on_proc = PVAdjustable(name + ":RADIAL-ON.PROC", internal=True) +# self.adj_radial_go_proc = PVAdjustable(name + ":RADIAL-GO.PROC", internal=True) @property def energy(self): @@ -245,6 +256,106 @@ class CHIC(PVAdjustable): +class TwoColorChicane(PVAdjustable): + + def __init__(self, name):#, t0=0): +# self.t0 = t0 +# name += " Two Color Chicane" + super().__init__("SATUN14-MBND100:I-SET", "SATUN14-MBND100:I-READ", process_time=1, name=name) + +# def set_target_value(self, value, hold=False): +# super().set_target_value(value) + +# def get_current_value(self): +# return super().get_current_value() + + + + + +class Phases: + + def __init__(self, n_unds=N_UNDS): + # 22 does not have a chicane + n_unds = n_unds.copy() + if 22 in n_unds: + n_unds.remove(22) + + # 22 does not have a chicane + n_unds_all = N_UNDS.copy() + if 22 in n_unds_all: + n_unds_all.remove(22) + + self.cb_auto_good = {i: PV(f"SATUN{i:02}-CHIC:AUTO-PHASING") for i in n_unds} + self.cb_auto_bad = {i: PV(f"SATUN{i:02}-CHIC:AUTO-PHASING") for i in set(n_unds_all) - set(n_unds)} + + self.pv_fixed_energy = PV("SATUN-CHIC:FIX_PHOTON_ENERGY") + self.pv_energy = PV("SATUN-CHIC:PHOTON-ENERGY") + + + def set(self, energy): + for cb in self.cb_auto_good.values(): cb.put(int(False)) + for cb in self.cb_auto_bad.values(): cb.put(int(False)) + sleep(0.1) + + pv_fixed_energy = self.pv_fixed_energy + + current_state = pv_fixed_energy.get() + pv_fixed_energy.put(int(True)) # enforce fixed energy + + self.pv_energy.put(energy / 1000) # in keV + sleep(0.1) + + for cb in self.cb_auto_good.values(): cb.put(int(True)) + sleep(0.1) + + for cb in self.cb_auto_good.values(): cb.put(int(False)) + for cb in self.cb_auto_bad.values(): cb.put(int(False)) + sleep(0.1) + +# pv_fixed_energy.put(current_state) # reset to original state + + + + + +#class Phases: + +# def __init__(self, n_unds=N_UNDS): +# # 22 does not have a chicane +# n_unds = n_unds.copy() +# if 22 in n_unds: +# n_unds.remove(22) +# self.pv_energy = PV("SATUN-CHIC:PHOTON-ENERGY") +# self.pv_fixed_energy = PV("SATUN-CHIC:FIX_PHOTON_ENERGY") +# self.adjs_apply = {i: PVAdjustable(f"SATUN{i:02}-CHIC:APPLY-DOP", internal=True) for i in n_unds} + + +# def set(self, energy): +# pv_energy = self.pv_energy +# pv_fixed_energy = self.pv_fixed_energy + +# current_state = pv_fixed_energy.get() +# pv_fixed_energy.put(int(True)) # enforce fixed energy + +# pv_energy.put(energy / 1000) # in keV + +# sleep(0.1) +# self.update() +## sleep(10) + +# pv_fixed_energy.put(current_state) # reset to original state + + +# def update(self): +# wait_for_all([ +# adj_apply.set_target_value(1) for adj_apply in self.adjs_apply.values() +# ]) + + + + + def get_machine_n_und_ref(): res = PVEnumAdjustable("SATUN:REF-UND").get() if not res.startswith("SATUN"):