diff --git a/csaxs_bec/bec_widgets/widgets/client.py b/csaxs_bec/bec_widgets/widgets/client.py index 381fef2..30b6768 100644 --- a/csaxs_bec/bec_widgets/widgets/client.py +++ b/csaxs_bec/bec_widgets/widgets/client.py @@ -4,6 +4,7 @@ from __future__ import annotations from bec_lib.logger import bec_logger + from bec_widgets.cli.rpc.rpc_base import RPCBase, rpc_call, rpc_timeout logger = bec_logger.logger @@ -13,8 +14,8 @@ logger = bec_logger.logger _Widgets = { "ConsoleButtonsWidget": "ConsoleButtonsWidget", - "SampleStorageWidget": "SampleStorageWidget", "SAXSWidget": "SAXSWidget", + "SampleStorageWidget": "SampleStorageWidget", "SlitControlWidget": "SlitControlWidget", "TomoParamsWidget": "TomoParamsWidget", "XRayEye": "XRayEye", @@ -62,25 +63,6 @@ class ConsoleButtonsWidget(RPCBase): """ -class SampleStorageWidget(RPCBase): - """View and correct the FlOMNI sample-storage records.""" - - _IMPORT_MODULE = "csaxs_bec.bec_widgets.widgets.sample_storage.sample_storage" - - @rpc_call - def refresh(self) -> "None": - """ - Re-read all slots (one bulk device round-trip) and update only the - cells whose state actually changed. - - Repainting every cell on every 2 s poll — even when nothing changed, - which is almost always the case for a sample magazine — was needless - work on the GUI thread. We diff against the last-seen state and only - call set_state() on cells that differ, so a steady-state poll does no - UI work at all. - """ - - class SAXSWidget(RPCBase): """Widget for preparing SAXS measurement tables from an image ROI.""" @@ -156,6 +138,31 @@ class SAXSWidget(RPCBase): None """ + @rpc_call + def move_to_selected_row(self, index: "int") -> "None": + """ + None + """ + + +class SampleStorageWidget(RPCBase): + """View and correct the FlOMNI sample-storage records.""" + + _IMPORT_MODULE = "csaxs_bec.bec_widgets.widgets.sample_storage.sample_storage" + + @rpc_call + def refresh(self) -> "None": + """ + Re-read all slots (one bulk device round-trip) and update only the + cells whose state actually changed. + + Repainting every cell on every 2 s poll — even when nothing changed, + which is almost always the case for a sample magazine — was needless + work on the GUI thread. We diff against the last-seen state and only + call set_state() on cells that differ, so a steady-state poll does no + UI work at all. + """ + class SlitControlWidget(RPCBase): """Interactive GUI for cSAXS slit center and size control.""" @@ -201,7 +208,7 @@ class SlitControlWidget(RPCBase): class TomoParamsWidget(RPCBase): - """Interactive GUI for FlOMNI tomo scan parameter editing and queue management.""" + """Interactive GUI for tomo scan parameter editing and queue management, for""" _IMPORT_MODULE = "csaxs_bec.bec_widgets.widgets.tomo_params.tomo_params" @@ -214,7 +221,8 @@ class TomoParamsWidget(RPCBase): @rpc_call def enter_edit_mode(self) -> "None": """ - Unlock all parameter fields for editing. + Unlock all parameter fields for editing, populated from the live + backend. """ @rpc_call @@ -227,6 +235,13 @@ class TomoParamsWidget(RPCBase): def submit_params(self) -> "None": """ Validate, write to global vars, and re-lock fields. + + Hard-blocked while the beamline is busy (plan/AI_docs + TOMO_QUEUE_COMMAND_JOBS_PLAN.md section 6.1's "must be blocked" rule, + made a real block rather than a soft confirm now that there's a safe + alternative for the "I want to prepare a parameter set while a scan + is running" case: add_edited_to_queue() below, which never touches + these live global vars). """ @rpc_call @@ -235,6 +250,21 @@ class TomoParamsWidget(RPCBase): Open queue dialog and trigger Add (also accessible via RPC). """ + @rpc_call + def add_edited_to_queue(self) -> "None": + """ + Package the current (possibly unsubmitted) form fields as a new + tomo-queue job and re-lock the fields, without ever touching the + live param global vars. + + This is the safe alternative to Submit while the beamline is busy: + it writes only to the ``tomo_queue`` var (see + TOMO_QUEUE_COMMAND_JOBS_PLAN.md section 6.1's two-write-paths rule), + so it's always allowed, whether or not a scan is running -- unlike + the CLI's ``tomo_queue_add()``, which snapshots the *live* vars and + would silently ignore an in-progress edit. + """ + class XRayEye(RPCBase): _IMPORT_MODULE = "csaxs_bec.bec_widgets.widgets.xray_eye.x_ray_eye" @@ -392,6 +422,19 @@ class XRayEye(RPCBase): on_live_view_enabled). """ + @rpc_call + def set_live_view_signal(self, signal: "str" = "image") -> "None": + """ + Switch which camera signal the live Image view displays. + + Defaults to the normal live-acquisition channel -- callers (e.g. + LamNI's smear rotation-center calibration aid) can switch to an + alternate signal (e.g. "smear_preview") while a special procedure + is running, and should switch back when done. New/freshly-opened + GUI instances always default to the normal channel; nothing + changes here unless a caller explicitly requests it. + """ + class XRayEye2DControl(RPCBase): _IMPORT_MODULE = "csaxs_bec.bec_widgets.widgets.xray_eye.x_ray_eye" diff --git a/csaxs_bec/bec_widgets/widgets/designer_plugins.py b/csaxs_bec/bec_widgets/widgets/designer_plugins.py index 63226c3..b40f400 100644 --- a/csaxs_bec/bec_widgets/widgets/designer_plugins.py +++ b/csaxs_bec/bec_widgets/widgets/designer_plugins.py @@ -9,11 +9,11 @@ designer_plugins = { "csaxs_bec.bec_widgets.widgets.console_buttons.console_buttons", "ConsoleButtonsWidget", ), + "SAXSWidget": ("csaxs_bec.bec_widgets.widgets.saxs_widget.saxs_widget", "SAXSWidget"), "SampleStorageWidget": ( "csaxs_bec.bec_widgets.widgets.sample_storage.sample_storage", "SampleStorageWidget", ), - "SAXSWidget": ("csaxs_bec.bec_widgets.widgets.saxs_widget.saxs_widget", "SAXSWidget"), "SlitControlWidget": ( "csaxs_bec.bec_widgets.widgets.slit_control.slit_control", "SlitControlWidget", @@ -27,8 +27,8 @@ designer_plugins = { widget_icons = { "ConsoleButtonsWidget": "widgets", - "SampleStorageWidget": "widgets", "SAXSWidget": "table_chart", + "SampleStorageWidget": "widgets", "SlitControlWidget": "widgets", "TomoParamsWidget": "widgets", "XRayEye": "widgets",