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

View File

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

View File

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

View File

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