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:
@ -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,
|
||||
)
|
||||
|
@ -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()
|
||||
|
@ -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]:
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user