diff --git a/debye_bec/bec_ipython_client/plugins/auto_gain.py b/debye_bec/bec_ipython_client/plugins/auto_gain.py index 35b8d14..45fd085 100644 --- a/debye_bec/bec_ipython_client/plugins/auto_gain.py +++ b/debye_bec/bec_ipython_client/plugins/auto_gain.py @@ -158,25 +158,27 @@ class AutoGain: logger.info("All checks done, start preparing for measurement") # Get initial monochromator position and velocity - init_pos = self.dev.mo1_bragg.position.get() - init_vel = self.dev.mo1_bragg.velocity.get() + init_pos = self.dev.mo1_bragg.position + init_vel = self.dev.mo1_bragg.velocity logger.info(f"Move mono to start of {emin} eV") self.dev.mo1_bragg.velocity.put(MONO_VELOCITY) - status = CompareStatus(self.dev.mo1_bragg.velocity, MONO_VELOCITY) - status.wait(TIMEOUT_PUT_PV) + # TODO, subscribe to the signal, not the property! + # status = CompareStatus(self.dev.mo1_bragg.velocity, MONO_VELOCITY) + # status.wait(TIMEOUT_PUT_PV) status = self.dev.mo1_bragg.move(emin) status.wait(TIMEOUT_MONO_MOVE) # Set NIDAQ to max mode self.dev.nidaq.epics_mode.put(EpicsMode.MAX) - status = CompareStatus(self.dev.nidaq.epics_mode, EpicsMode.MAX) - status.wait(timeout=TIMEOUT_PUT_PV) + # status = CompareStatus(self.dev.nidaq.epics_mode, EpicsMode.MAX) + # status.wait(timeout=TIMEOUT_PUT_PV) # Set gains to lowest gain for name, ch in active_channels.items(): lowest_gain = AVAILABLE_GAINS[0] - ch["self.dev"].set_gain(lowest_gain) + logger.info(f"Setting gain to {lowest_gain:.0e}".replace("+", "")) + ch["self.dev"].set_gain(f"{lowest_gain:.0e}".replace("+", "")) ch["gain"] = lowest_gain remeasure = True @@ -256,7 +258,9 @@ class AutoGain: bisect_right(AVAILABLE_GAINS, gain_ref * 100) - 1 ] for gname in group_names: - active_channels[gname]["dev"].set_gain(next_gain) + active_channels[gname]["self.dev"].set_gain( + f"{next_gain:.0e}".replace("+", "") + ) active_channels[gname]["gain"] = next_gain logger.info(f"Setting gain of {label} to {next_gain:.0e} and remeasure") remeasure = True @@ -270,7 +274,7 @@ class AutoGain: default=min(AVAILABLE_GAINS), ) for gname in group_names: - active_channels[gname]["dev"].set_gain(gain) + active_channels[gname]["self.dev"].set_gain(gain) active_channels[gname]["gain"] = gain logger.info(f"Calculated final gain for {label} of {gain:.0e}") @@ -281,15 +285,15 @@ class AutoGain: # Reset NIDAQ to mean mode self.dev.nidaq.epics_mode.put(EpicsMode.MEAN) - status = CompareStatus(self.dev.nidaq.epics_mode, EpicsMode.MEAN) - status.wait(timeout=TIMEOUT_PUT_PV) + # status = CompareStatus(self.dev.nidaq.epics_mode, EpicsMode.MEAN) + # status.wait(timeout=TIMEOUT_PUT_PV) # Wait for mono to move to initial position and reset velocity status = self.dev.mo1_bragg.move(init_pos) status.wait(TIMEOUT_MONO_MOVE) - self.dev.mo1_bragg.velocity.put(init_vel) - status = CompareStatus(self.dev.mo1_bragg.velocity, init_vel) - status.wait(timeout=TIMEOUT_PUT_PV) + self.dev.mo1_bragg.velocity.put(init_vel) # TODO: Fix, not using property! + # status = CompareStatus(self.dev.mo1_bragg.velocity, init_vel) + # status.wait(timeout=TIMEOUT_PUT_PV) def _get_ring_current(self) -> float: ring_current = 0 diff --git a/debye_bec/bec_ipython_client/plugins/digital_twin_core/digital_twin_core.py b/debye_bec/bec_ipython_client/plugins/digital_twin_core/digital_twin_core.py index c89dbe0..6e7a772 100644 --- a/debye_bec/bec_ipython_client/plugins/digital_twin_core/digital_twin_core.py +++ b/debye_bec/bec_ipython_client/plugins/digital_twin_core/digital_twin_core.py @@ -622,7 +622,7 @@ class DigitalTwinCore: Args: smpl(float): Sample position in mm fm_qy(None|float): FM qy value - fm_rotx(float: FM rotx position + fm_rotx(float: FM rotx position in rad Returns: float: bending radius in m diff --git a/debye_bec/bec_widgets/widgets/digital_twin/digital_twin.py b/debye_bec/bec_widgets/widgets/digital_twin/digital_twin.py index 205d380..c612c92 100644 --- a/debye_bec/bec_widgets/widgets/digital_twin/digital_twin.py +++ b/debye_bec/bec_widgets/widgets/digital_twin/digital_twin.py @@ -133,6 +133,7 @@ class DigitalTwin(BECWidget, QWidget): self.input.fm_focy.value_changed_connect(self.calc_assistant) if self.beamline == BeamlineId.X01DA: self.input.ot_es1_trz.value_changed_connect(self.calc_assistant) + self.input.smpl_to_xrd.value_changed_connect(self.calc_assistant) else: self.input.table.activated_connect(self.calc_assistant) self.input.es1man_trz.value_changed_connect(self.calc_assistant) @@ -348,6 +349,8 @@ class DigitalTwin(BECWidget, QWidget): self.calc_fm_ideal_pitch() case "es1man_trz": self.calc_fm_ideal_pitch() + case "smpl_to_xrd": + self.calc_fm_ideal_pitch() self.calc_positions() self.calc_assistant_sideview() self.calc_assistant_surfaces() @@ -396,7 +399,7 @@ class DigitalTwin(BECWidget, QWidget): "energy": self.input.energy.value(), "h_acc": self.input.sldi_hacc.value(), "v_acc": self.input.sldi_vacc.value(), - "cm_pitch": -self.input.cm_pitch.value(), + "cm_pitch": -np.float64(self.input.cm_pitch.value()), "cm_stripe": cm_stripe, "cm_trx": cm_trx, "mo1_mode": self.input.mo1_mode.currentText(), @@ -428,16 +431,26 @@ class DigitalTwin(BECWidget, QWidget): def set_assistant_config(self, config: ConfigDict) -> None: """ Applies an assistant config to the input Qt widgets. + Config must be without offsets! Args: config: Assistant configuration, as returned by ``get_assistant_config``. The acceleration and angular values are expected to be in SI units. """ + + config = ConfigDict(config) # Important: Copy dict to not change the original + + # Convert to mrad units! + config["h_acc"] *= 1e3 + config["v_acc"] *= 1e3 + config["cm_pitch"] *= -1e3 + config["fm_rotx"] *= 1e3 + self.input.energy.set_number(config["energy"]) - self.input.sldi_hacc.set_number(config["h_acc"] * 1e3) - self.input.sldi_vacc.set_number(config["v_acc"] * 1e3) - self.input.cm_pitch.set_number(-config["cm_pitch"] * 1e3) + self.input.sldi_hacc.set_number(config["h_acc"]) + self.input.sldi_vacc.set_number(config["v_acc"]) + self.input.cm_pitch.set_number(config["cm_pitch"]) self.input.cm_stripe.set_current_text(config["cm_stripe"]) self.input.fm_stripe.set_current_text(config["fm_stripe"]) self.input.mo1_mode.set_current_text(config["mo1_mode"]) @@ -445,14 +458,19 @@ class DigitalTwin(BECWidget, QWidget): self.bragg_angle = config["mo1_bragg"] - fm_rotx = -config["fm_rotx"] * 1e3 + fm_rotx = -config["fm_rotx"] self.qy = config["fm_qy"] - fm_rotx_real = 2 * config["cm_pitch"] - config["fm_rotx"] + smpl = config["ot_es1_trz"] + config["es1man_trz"] - radius = self.core.calc_fm_bnd_radius(smpl, config["fm_qy"], config["fm_rotx"]) + radius = self.core.calc_fm_bnd_radius(smpl, config["fm_qy"], config["fm_rotx"] * 1e-3) fm_focx, fm_focy = self.core.calc_beamsize( - config["h_acc"], config["v_acc"], config["fm_stripe"], fm_rotx_real * 1e-3, radius, smpl + config["h_acc"] * 1e-3, + config["v_acc"] * 1e-3, + config["fm_stripe"], + -fm_rotx * 1e-3, + radius, + smpl, ) if config["fm_qy"] is not None: self.input.fm_focus.set_current_text("Defocused") @@ -462,7 +480,7 @@ class DigitalTwin(BECWidget, QWidget): self.input.fm_focus.set_current_text("Focused") else: self.input.fm_focus.set_current_text("Manual") - self.input.fm_rotx_ideal.setValue(fm_rotx) + self.input.fm_rotx_ideal.setValue(fm_rotx * 1e-3) if self.beamline == BeamlineId.X01DA: self.input.ot_es1_trz.set_number(config["ot_es1_trz"]) @@ -646,6 +664,7 @@ class DigitalTwin(BECWidget, QWidget): fm_stripe = self.core.fm_trx_to_stripe(-pos["fm_trx"]) self.input.fm_stripe.set_current_text(fm_stripe) fm_rotx_real = 2 * pos["cm_rotx"] - pos["fm_rotx"] + logger.info(f"In adapt reality, fm_rotx_real is {fm_rotx_real}") self.input.fm_rotx.set_number(fm_rotx_real) if self.beamline == BeamlineId.X01DA: diff --git a/debye_bec/bec_widgets/widgets/scan_control_xas/scan_control_xas.py b/debye_bec/bec_widgets/widgets/scan_control_xas/scan_control_xas.py index 995ea76..daa5772 100644 --- a/debye_bec/bec_widgets/widgets/scan_control_xas/scan_control_xas.py +++ b/debye_bec/bec_widgets/widgets/scan_control_xas/scan_control_xas.py @@ -37,6 +37,8 @@ from ..edge_selector import EdgeSelector logger = bec_logger.logger ALLOWED_SCANS = [ + "acquire", + "line_scan", "xas_simple_scan", "xas_simple_scan_with_xrd", "xas_advanced_scan", diff --git a/debye_bec/bec_widgets/widgets/scheduler/scheduler.py b/debye_bec/bec_widgets/widgets/scheduler/scheduler.py index 6b947ef..00c5b8b 100644 --- a/debye_bec/bec_widgets/widgets/scheduler/scheduler.py +++ b/debye_bec/bec_widgets/widgets/scheduler/scheduler.py @@ -10,6 +10,7 @@ or finished cannot. from __future__ import annotations import json +import re import sys import threading import time @@ -485,6 +486,23 @@ class Scheduler(BECWidget, QWidget): + f"Comment: {item.form_state['kwargs']['metadata']['comment']}, " + f"Sample Name: {item.form_state['kwargs']['metadata']['sample_name']}" ) + elif re.match(r"^dev\..*\.move", item.command): + if item.form_state["relative"]: + text = ( + f"Move {item.form_state['device_name']} by {item.form_state['value']}" + ) + else: + text = ( + f"Move {item.form_state['device_name']} to {item.form_state['value']}" + ) + elif item.command.startswith("dev.ic"): + text = ( + f"Fill {item.form_state['chamber']} with {item.form_state['conc1']} % " + + f"{item.form_state['gas1']} and {item.form_state['conc2']} % " + + f"{item.form_state['gas2']} to {item.form_state['pressure']} bar" + ) + elif item.command.startswith("dev.reffoilchanger"): + text = f"Insert {item.form_state['ref']} reference foil" if text == "": text = f"{item.command}" if item.error: @@ -831,8 +849,6 @@ class Scheduler(BECWidget, QWidget): if initial is None: return - logger.info(f"Initial: {initial}") - dialog = ScheduleItemDialog( self.scans, self.dev, @@ -1072,6 +1088,9 @@ class Scheduler(BECWidget, QWidget): yet. Raises `RuntimeError` for an item that is already running/finished. """ + + logger.info(f"edit item with form_state: {form_state}") + command = command.strip() if not command: raise ValueError("command must not be empty") diff --git a/debye_bec/devices/ionization_chambers/ionization_chamber.py b/debye_bec/devices/ionization_chambers/ionization_chamber.py index 9d2bd2c..92a560d 100644 --- a/debye_bec/devices/ionization_chambers/ionization_chamber.py +++ b/debye_bec/devices/ionization_chambers/ionization_chamber.py @@ -120,13 +120,13 @@ class IonizationChamber0(PSIDeviceBase): self.timeout_for_pvwait = 2.5 super().__init__(name=name, prefix=prefix, scan_info=scan_info, **kwargs) - @typechecked - def set_gain(self, gain: Literal["1e6", "1e7", "5e7", "1e8", "1e9"]) -> None: + def set_gain(self, gain: float | str) -> None: """Configure the gain setting of the specified channel Args: gain (Literal['1e6', '1e7', '5e7', '1e8', '1e9']) : Desired gain """ + # TODO: Fix docstring if self.amp.cOnOff.get() == AmplifierEnable.OFF: status = CompareStatus(self.amp.cOnOff, AmplifierEnable.ON) @@ -135,15 +135,15 @@ class IonizationChamber0(PSIDeviceBase): status.wait(self.timeout_for_pvwait) match gain: - case "1e6": + case "1e6" | 1e6: self.amp.cGain_ENUM.put(AmplifierGain.G1E6) - case "1e7": + case "1e7" | 1e7: self.amp.cGain_ENUM.put(AmplifierGain.G1E7) - case "5e7": + case "5e7" | 5e7: self.amp.cGain_ENUM.put(AmplifierGain.G5E7) - case "1e8": + case "1e8" | 1e8: self.amp.cGain_ENUM.put(AmplifierGain.G1E8) - case "1e9": + case "1e9" | 1e9: self.amp.cGain_ENUM.put(AmplifierGain.G1E9) def set_filter(