wip
CI for debye_bec / test (pull_request) Successful in 1m33s
CI for debye_bec / test (push) Successful in 1m34s

This commit is contained in:
x01da
2026-09-28 14:43:25 +02:00
parent 46c37a6e38
commit 5eba9dbc4c
4 changed files with 33 additions and 11 deletions
@@ -247,11 +247,12 @@ class ScheduleItemDialog(QDialog):
if not device_name:
raise ValueError("No movable device available/selected.")
value = self.move_value_spin.value()
units = self.move_value_spin.suffix()
relative = self.move_relative_check.isChecked()
return {
"command": f"dev.{device_name}.move({value!r}, relative={relative!r})",
"kind": "move",
"form_state": {"device_name": device_name, "value": value, "relative": relative},
"form_state": {"device_name": device_name, "value": value, "units": units, "relative": relative},
}
def _prefill_move_page(self, state: dict):
@@ -96,9 +96,9 @@ def build_item_display_text(item: ScheduleItem, beamline: str | None) -> str:
)
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']:+g}"
text = f"Move {item.form_state['device_name']} by {item.form_state['value']:+g} {item.form_state['units']}"
else:
text = f"Move {item.form_state['device_name']} to {item.form_state['value']}"
text = f"Move {item.form_state['device_name']} to {item.form_state['value']} {item.form_state['units']}"
elif item.command.startswith("dev.ic"):
text = (
f"Fill {item.form_state['chamber']} with {item.form_state['conc1']} % "
@@ -345,6 +345,7 @@ class Scheduler(BECWidget, QWidget):
self._endpoint = schedule_endpoint(self.schedule_name)
self._lock = threading.Lock() # guards self.schedule (see module docstring)
self._abort_requested = False
self._pause_requested = False
self._guard_interrupt_requested = False # see "Guard interaction" in module docstring
self._current_report = None # ScanReport of the item currently executing, if any
self._current_item_kind: str | None = None # kind of the item _current_report belongs to
@@ -461,16 +462,24 @@ class Scheduler(BECWidget, QWidget):
run_row = QHBoxLayout()
self.run_btn = MyButton("Run / Continue", "success")
self.run_from_current_btn = MyButton("Run / Continue from current selection", "success")
self.abort_btn = MyButton("Pause after current item", "emergency")
self.abort_btn = MyButton("Pause now", "emergency")
self.pause_btn = MyButton("Pause after current item", "warning")
self.reset_btn = MyButton("Reset Schedule Status", "warning")
for button in (self.run_btn, self.run_from_current_btn, self.abort_btn, self.reset_btn):
for button in (
self.run_btn,
self.run_from_current_btn,
self.pause_btn,
self.abort_btn,
self.reset_btn,
):
run_row.addWidget(button)
run_row.addStretch()
control_layout.addLayout(run_row)
self.run_btn.clicked.connect(self.run_schedule)
self.run_from_current_btn.connect(self.run_schedule_from_selection)
self.run_from_current_btn.clicked.connect(self.run_schedule_from_selection)
self.abort_btn.clicked.connect(self.abort_schedule)
self.pause_btn.clicked.connect(self.pause_schedule)
self.reset_btn.clicked.connect(self.reset_schedule)
layout.addWidget(control_group)
@@ -729,8 +738,9 @@ class Scheduler(BECWidget, QWidget):
# Update execution control buttons
state = self._current_report is None # True if schedule is not running
self.run_btn.setEnabled(state)
self.run_from_current_btn.setEnabled(state)
self.run_from_current_btn.setEnabled(state and self._selected_item_id is not None)
self.abort_btn.setEnabled(not state)
self.pause_btn.setEnabled(not state)
self.reset_btn.setEnabled(state)
@SafeSlot()
@@ -1131,6 +1141,7 @@ class Scheduler(BECWidget, QWidget):
== QMessageBox.StandardButton.Yes
)
self._abort_requested = False
self._pause_requested = False
self.schedule.is_running = True
self._persist_locked()
self.schedule_changed.emit()
@@ -1163,6 +1174,10 @@ class Scheduler(BECWidget, QWidget):
except Exception: # pylint: disable=broad-except
logger.exception("Failed to cancel the currently running schedule item")
@SafeSlot()
def pause_schedule(self):
self._pause_requested = True
@SafeSlot()
def reset_schedule(self):
"""Clear all execution state and start the schedule over from item 1."""
@@ -1390,7 +1405,9 @@ class Scheduler(BECWidget, QWidget):
"auto_gain": self.auto_gain,
"np": np,
}
while not self._abort_requested and not self._closing.is_set():
while (
not self._abort_requested and not self._closing.is_set() and not self._pause_requested
):
with self._lock:
next_item = self._pick_next_runnable_locked(repeat_aborted_item, first_item)
if next_item is None or next_item == "stop":
@@ -1411,6 +1428,10 @@ class Scheduler(BECWidget, QWidget):
self.schedule.schedule_name,
"widget_closed",
)
elif self._pause_requested:
notify_schedule_state(
self.client, self.schedule.notifications, self.schedule.schedule_name, "paused"
)
else:
notify_schedule_state(
self.client, self.schedule.notifications, self.schedule.schedule_name, "finished"
+1 -1
View File
@@ -56,7 +56,7 @@ class CurrentFoilSignal(Signal):
return None
idx = self.parent.ref_rb.get()
try:
idx = int(round(idx)) + 1
idx = int(round(idx))
except (TypeError, ValueError):
return None
return getattr(self.parent, f"foil{idx:02d}", None)
@@ -1,6 +1,6 @@
from bec_server.file_writer.default_writer import DefaultFormat
import debye_bec.bec_widgets.widgets.digital_twin.x01da_parameters as bl
import debye_bec.bec_ipython_client.plugins.digital_twin_core.x01da_parameters as bl
class DebyeNexusStructure(DefaultFormat):
@@ -292,7 +292,7 @@ class DebyeNexusStructure(DefaultFormat):
foil = (
self.device_manager.devices.reffoilchanger.read(cached=True)
.get("current_foil")
.get("reffoilchanger_current_foil")
.get("value")
)
ref_foil = ai2ai4_active.create_dataset(name="Reference", data=foil)