mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-13 11:11:49 +02:00
feat: add BECDevice widget
This commit is contained in:
0
bec_widgets/widgets/bec_device/__init__.py
Normal file
0
bec_widgets/widgets/bec_device/__init__.py
Normal file
160
bec_widgets/widgets/bec_device/bec_device.py
Normal file
160
bec_widgets/widgets/bec_device/bec_device.py
Normal file
@ -0,0 +1,160 @@
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from ophyd import Kind
|
||||
from qtpy.QtCore import Slot
|
||||
from qtpy.QtWidgets import QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QWidget
|
||||
|
||||
from bec_widgets.utils import BECConnector
|
||||
|
||||
|
||||
class OphydSignalBox(QWidget):
|
||||
"""A widget to display a signal value of an Ophyd signal."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent=None,
|
||||
device_name: str = None,
|
||||
signal_name: str = None,
|
||||
device_base_class: str = None,
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.layout = QHBoxLayout()
|
||||
self.device_name = device_name
|
||||
self.device_base_class = device_base_class
|
||||
self.signal_name = signal_name
|
||||
|
||||
self.signal_label = None
|
||||
self.signal_value = None
|
||||
self._init_ui()
|
||||
|
||||
def _init_ui(self):
|
||||
"""Initialize the UI of the signal widget."""
|
||||
self._create_signal_widget()
|
||||
|
||||
def _create_signal_widget(self):
|
||||
"""Create the signal widget with label and value."""
|
||||
self.signal_label = QLabel()
|
||||
self.signal_label.setText(f"{self.signal_name}")
|
||||
self.signal_value = QLineEdit()
|
||||
self.signal_value.setDisabled(True)
|
||||
|
||||
self.layout.addWidget(self.signal_label)
|
||||
self.layout.addWidget(self.signal_value)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
@Slot(dict, dict)
|
||||
def update_readback(self, content: dict, metadata: dict):
|
||||
"""Update the readback value of the signal.
|
||||
|
||||
Args:
|
||||
content (dict): The content of the signal.
|
||||
metadata (dict): The metadata of the signal.
|
||||
"""
|
||||
if self.device_base_class == "positioner" and self.signal_name == "readback":
|
||||
signal_key = self.device_name
|
||||
else:
|
||||
signal_key = f"{self.device_name}_{self.signal_name}"
|
||||
value = content["signals"][signal_key]["value"]
|
||||
value = f"{value:.4f}" if isinstance(value, float) else f"{value}"
|
||||
self.signal_value.setText(f"{value}")
|
||||
|
||||
|
||||
class BECDevice(BECConnector, QWidget):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent=None,
|
||||
client=None,
|
||||
gui_id: str | None = None,
|
||||
device_name: str = None,
|
||||
device_signals: str | list[str] = None,
|
||||
):
|
||||
super().__init__(client=client, gui_id=gui_id)
|
||||
QWidget.__init__(self, parent=parent)
|
||||
|
||||
self.device_name = device_name
|
||||
group = QGroupBox(self.device_name, self)
|
||||
self.layout = QGridLayout(group)
|
||||
self.device_signals = self.get_device_signals(device_signals)
|
||||
self.table = {}
|
||||
self._init_UI()
|
||||
|
||||
def _init_UI(self):
|
||||
"""Initialize the UI of the device widget."""
|
||||
|
||||
for ii, signal_name in enumerate(self.device_signals):
|
||||
# pylint: disable=protected-access
|
||||
dev_info = self.client.device_manager.devices[self.device_name]._info
|
||||
kind = [
|
||||
info["kind_int"]
|
||||
for info in dev_info["signals"]
|
||||
if info["component_name"] == signal_name
|
||||
][0]
|
||||
signal_box = OphydSignalBox(
|
||||
device_name=self.device_name,
|
||||
signal_name=signal_name,
|
||||
device_base_class=dev_info["device_base_class"],
|
||||
)
|
||||
self.table[signal_name] = signal_box
|
||||
self.layout.addWidget(signal_box, ii, 0)
|
||||
if kind == Kind.hinted.value or kind == Kind.normal.value:
|
||||
self.bec_dispatcher.connect_slot(
|
||||
signal_box.update_readback, MessageEndpoints.device_readback(self.device_name)
|
||||
)
|
||||
elif kind == Kind.config.value:
|
||||
self.bec_dispatcher.connect_slot(
|
||||
signal_box.update_readback,
|
||||
MessageEndpoints.device_read_configuration(self.device_name),
|
||||
)
|
||||
# Receive first updates upon start
|
||||
self.client.device_manager.devices[self.device_name].read(cached=False)
|
||||
self.client.device_manager.devices[self.device_name].read_configuration(cached=False)
|
||||
|
||||
def get_device_signals(self, device_signals: str | list | None) -> list[str]:
|
||||
"""Get the signals of the device from the BEC.
|
||||
|
||||
Args:
|
||||
device_name (str | list | None): The name of the device.
|
||||
"""
|
||||
if device_signals is None:
|
||||
device_signals = []
|
||||
device_signals.extend(self.signals_name_from_kind(self.device_name, Kind.hinted))
|
||||
device_signals.extend(self.signals_name_from_kind(self.device_name, Kind.normal))
|
||||
device_signals.extend(self.signals_name_from_kind(self.device_name, Kind.config))
|
||||
elif isinstance(device_signals, str):
|
||||
device_signals = [device_signals]
|
||||
return device_signals
|
||||
|
||||
def signals_name_from_kind(self, device_name: str, kind: Kind) -> list[str]:
|
||||
"""Get the signals name from the device name and kind.
|
||||
|
||||
Args:
|
||||
device_name (str): The name of the device.
|
||||
kind (Kind): The kind of the signal.
|
||||
"""
|
||||
rtr = []
|
||||
# pylint: disable=protected-access
|
||||
dev_info = self.client.device_manager.devices[device_name]._info
|
||||
for info in dev_info["signals"]:
|
||||
if info["kind_int"] == kind.value:
|
||||
rtr.append(info["component_name"])
|
||||
return rtr
|
||||
|
||||
@Slot(dict, dict)
|
||||
def on_device_readback(self, content: dict, metadata: dict) -> None:
|
||||
for signal_name, ophyd_signal in self.table.items():
|
||||
if signal_name in content["signals"].keys():
|
||||
value = content["signals"][signal_name]["value"]
|
||||
value = f"{value:.4f}" if isinstance(value, float) else f"{value}"
|
||||
ophyd_signal.update_readback(value)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import qdarktheme
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
app = QApplication([])
|
||||
qdarktheme.setup_theme("auto")
|
||||
widget = BECDevice(device_name="eiger")
|
||||
widget.show()
|
||||
app.exec_()
|
Reference in New Issue
Block a user