0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 11:41:49 +02:00

fix: simplify AutoUpdate code thanks to threadpool executor in BEC Connector

This commit is contained in:
2024-12-17 19:43:51 +01:00
committed by wakonig_k
parent 92b802021f
commit 1b0382524f
4 changed files with 48 additions and 56 deletions

View File

@ -67,7 +67,7 @@ class AutoUpdates:
"""
return self._default_fig
def run(self, msg):
def do_update(self, msg):
"""
Run the update function if enabled.
"""
@ -76,20 +76,9 @@ class AutoUpdates:
if msg.status != "open":
return
info = self.get_scan_info(msg)
self.handler(info)
return self.handler(info)
def process_queue(self):
"""
Process the message queue.
"""
while True:
msg = self.msg_queue.get()
if msg is self._shutdown_sentinel:
break
self.run(msg)
@staticmethod
def get_selected_device(monitored_devices, selected_device):
def get_selected_device(self, monitored_devices, selected_device):
"""
Get the selected device for the plot. If no device is selected, the first
device in the monitored devices list is selected.
@ -106,14 +95,11 @@ class AutoUpdates:
Default update function.
"""
if info.scan_name == "line_scan" and info.scan_report_devices:
self.simple_line_scan(info)
return
return self.simple_line_scan(info)
if info.scan_name == "grid_scan" and info.scan_report_devices:
self.simple_grid_scan(info)
return
return self.simple_grid_scan(info)
if info.scan_report_devices:
self.best_effort(info)
return
return self.best_effort(info)
def simple_line_scan(self, info: ScanInfo) -> None:
"""
@ -123,12 +109,19 @@ class AutoUpdates:
if not fig:
return
dev_x = info.scan_report_devices[0]
dev_y = self.get_selected_device(info.monitored_devices, self.gui.selected_device)
selected_device = self.gui.selected_device
dev_y = self.get_selected_device(info.monitored_devices, selected_device)
if not dev_y:
return
fig.clear_all()
plt = fig.plot(x_name=dev_x, y_name=dev_y, label=f"Scan {info.scan_number} - {dev_y}")
plt.set(title=f"Scan {info.scan_number}", x_label=dev_x, y_label=dev_y)
fig.plot(
x_name=dev_x,
y_name=dev_y,
label=f"Scan {info.scan_number} - {dev_y}",
title=f"Scan {info.scan_number}",
x_label=dev_x,
y_label=dev_y,
)
def simple_grid_scan(self, info: ScanInfo) -> None:
"""
@ -139,12 +132,18 @@ class AutoUpdates:
return
dev_x = info.scan_report_devices[0]
dev_y = info.scan_report_devices[1]
dev_z = self.get_selected_device(info.monitored_devices, self.gui.selected_device)
selected_device = self.gui.selected_device
dev_z = self.get_selected_device(info.monitored_devices, selected_device)
fig.clear_all()
plt = fig.plot(
x_name=dev_x, y_name=dev_y, z_name=dev_z, label=f"Scan {info.scan_number} - {dev_z}"
fig.plot(
x_name=dev_x,
y_name=dev_y,
z_name=dev_z,
label=f"Scan {info.scan_number} - {dev_z}",
title=f"Scan {info.scan_number}",
x_label=dev_x,
y_label=dev_y,
)
plt.set(title=f"Scan {info.scan_number}", x_label=dev_x, y_label=dev_y)
def best_effort(self, info: ScanInfo) -> None:
"""
@ -154,17 +153,16 @@ class AutoUpdates:
if not fig:
return
dev_x = info.scan_report_devices[0]
dev_y = self.get_selected_device(info.monitored_devices, self.gui.selected_device)
selected_device = self.gui.selected_device
dev_y = self.get_selected_device(info.monitored_devices, selected_device)
if not dev_y:
return
fig.clear_all()
plt = fig.plot(x_name=dev_x, y_name=dev_y, label=f"Scan {info.scan_number} - {dev_y}")
plt.set(title=f"Scan {info.scan_number}", x_label=dev_x, y_label=dev_y)
def shutdown(self):
"""
Shutdown the auto update thread.
"""
self.msg_queue.put(self._shutdown_sentinel)
if self.auto_update_thread:
self.auto_update_thread.join()
fig.plot(
x_name=dev_x,
y_name=dev_y,
label=f"Scan {info.scan_number} - {dev_y}",
title=f"Scan {info.scan_number}",
x_label=dev_x,
y_label=dev_y,
)

View File

@ -340,12 +340,6 @@ class BECGuiClient(RPCBase):
with wait_for_server(self):
return self._auto_updates
def _shutdown_auto_updates(self):
if self._auto_updates_enabled:
if self._auto_updates is not None:
self._auto_updates.shutdown()
self._auto_updates = None
def _get_update_script(self) -> AutoUpdates | None:
eps = imd.entry_points(group="bec.widgets.auto_updates")
for ep in eps:
@ -389,18 +383,17 @@ class BECGuiClient(RPCBase):
def _start_update_script(self) -> None:
self._client.connector.register(MessageEndpoints.scan_status(), cb=self._handle_msg_update)
@staticmethod
def _handle_msg_update(msg: MessageObject, parent: BECGuiClient) -> None:
if parent.auto_updates is not None:
def _handle_msg_update(self, msg: MessageObject) -> None:
if self.auto_updates is not None:
# pylint: disable=protected-access
parent._update_script_msg_parser(msg.value)
return self._update_script_msg_parser(msg.value)
def _update_script_msg_parser(self, msg: messages.BECMessage) -> None:
if isinstance(msg, messages.ScanStatusMessage):
if not self.gui_is_alive():
return
if self._auto_updates_enabled:
self.auto_updates.msg_queue.put(msg)
return self.auto_updates.do_update(msg)
def _gui_post_startup(self):
self._top_level["main"] = WidgetDesc(
@ -415,6 +408,7 @@ class BECGuiClient(RPCBase):
auto_updates = AutoUpdates(self._top_level["main"].widget)
if auto_updates.create_default_dock:
auto_updates.start_default_dock()
self._start_update_script()
self._auto_updates = auto_updates
self._do_show_all()
self._gui_started_event.set()
@ -427,7 +421,6 @@ class BECGuiClient(RPCBase):
logger.success("GUI starting...")
self._startup_timeout = 5
self._gui_started_event.clear()
self._start_update_script()
self._process, self._process_output_processing_thread = _start_plot_process(
self._gui_id, self.__class__, self._client._service_config.config, logger=logger
)
@ -512,4 +505,3 @@ class BECGuiClient(RPCBase):
self._process_output_processing_thread.join()
self._process.wait()
self._process = None
self._shutdown_auto_updates()

View File

@ -219,9 +219,13 @@ class BECDockArea(BECWidget, QWidget):
@property
def selected_device(self) -> str:
gui_id = QApplication.instance().gui_id
return self.client.connector.get(
auto_update_config = self.client.connector.get(
MessageEndpoints.gui_auto_update_config(gui_id)
).selected_device
)
try:
return auto_update_config.selected_device
except AttributeError:
return None
@property
def panels(self) -> dict[str, BECDock]:

View File

@ -70,7 +70,6 @@ def test_client_utils_passes_client_config_to_server(bec_dispatcher):
mixin.gui_is_alive.side_effect = [True]
try:
with mock.patch.object(mixin, "_start_update_script"):
yield mixin
finally:
mixin.close()
@ -84,4 +83,3 @@ def test_client_utils_passes_client_config_to_server(bec_dispatcher):
mock_start_plot.assert_called_once_with(
"gui_id", BECGuiClient, mixin._client._service_config.config, logger=mock.ANY
)
mixin._start_update_script.assert_called_once()