1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2026-04-08 17:57:54 +02:00

Compare commits

...

3 Commits

4 changed files with 380 additions and 2 deletions

View File

@@ -0,0 +1,100 @@
import os
import numpy as np
import pyqtgraph as pg
import requests
import sys
from PySide6.QtCore import Signal, Slot
from qtpy.QtCore import QSize
from qtpy.QtGui import QActionGroup, QIcon
from qtpy.QtWidgets import QApplication, QMainWindow, QStyle
import bec_widgets
from bec_lib.client import BECClient
from bec_lib.service_config import ServiceConfig
from bec_widgets.examples.general_app.web_links import BECWebLinksMixin
from bec_widgets.qt_utils.error_popups import SafeSlot
from bec_widgets.utils.bec_dispatcher import QtRedisConnector
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.colors import apply_theme
from bec_widgets.utils.ui_loader import UILoader
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
class TomcatApp(QMainWindow, BECWidget):
select_slice = Signal()
def __init__(self, parent=None, client=None, gui_id=None):
super(TomcatApp, self).__init__(parent)
BECWidget.__init__(self, client=client, gui_id=gui_id)
ui_file_path = os.path.join(os.path.dirname(__file__), "tomcat_app.ui")
self.load_ui(ui_file_path)
self.resize(1280, 720)
self.get_bec_shortcuts()
self.bec_dispatcher.connect_slot(self.test_connection, "GPU Fastapi message")
self.bec_dispatcher.connect_slot(self.status_update, "GPU Fastapi message")
self.ui.slider_select.valueChanged.connect(self.select_slice_from_slider)
self.proxy_slider = pg.SignalProxy(self.select_slice, rateLimit=2, slot=self.send_slice)
self.image_widget = self.ui.image_widget
def load_ui(self, ui_file):
loader = UILoader(self)
self.ui = loader.loader(ui_file)
self.setCentralWidget(self.ui)
def status_update(self, msg):
status = msg["data"]["GPU SVC Status"]
if status == "Running":
self.ui.radio_io.setChecked(True)
else:
self.ui.radio_io.setChecked(False)
# @SafeSlot(dict, dict)
def test_connection(self, msg):
print("Test Connection")
print(msg)
# print(metadata)
def select_slice_from_slider(self, value):
print(value)
self.select_slice.emit()
@Slot()
def send_slice(self):
value = self.ui.slider_select.value()
requests.post(
"http://ra-gpu-006:8000/api/v1/reco/single_slice",
json={"slice": value, "rot_center": 0},
)
print(f"Sending slice {value}")
def main(): # pragma: no cover
app = QApplication(sys.argv)
icon = QIcon()
icon.addFile(
os.path.join(MODULE_PATH, "assets", "app_icons", "BEC-General-App.png"), size=QSize(48, 48)
)
app.setWindowIcon(icon)
config = ServiceConfig(redis={"host": "ra-gpu-006", "port": 6379})
client = BECClient(config=config, connector_cls=QtRedisConnector)
main_window = TomcatApp(client=client)
main_window.show()
main_window.image_widget.image("RecoPreview")
# custom_data = np.random.rand(100, 100)
# main_window.image_widget._image.add_custom_image("custom", custom_data)
sys.exit(app.exec_())
if __name__ == "__main__": # pragma: no cover
main()

View File

@@ -0,0 +1,278 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>631</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="BECImageWidget" name="image_widget"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>29</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="status_dock">
<property name="windowTitle">
<string>Status</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Dataset loaded</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="radio_dataset">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>I/O Service</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="radio_io">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="lineEdit_2"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Reco Service</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="radioButton_4">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_11">
<property name="text">
<string>reco-adress</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Streaming Service</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QRadioButton" name="radioButton_3">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_12">
<property name="text">
<string>stream-adress</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dock_data">
<property name="windowTitle">
<string>Dataset</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Input Dataset (full HDF5 path)</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_edit_dataset"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="button_load">
<property name="text">
<string>Load Dataset</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_close">
<property name="text">
<string>Close Dataset</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Single Slice Live Preview</string>
</property>
</widget>
</item>
<item>
<widget class="ToggleSwitch" name="toggle_preview"/>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Select Slice</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slider_select">
<property name="maximum">
<number>500</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Current Index</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Rotation center (offset from center)</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slider_rotation">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Rotation Index</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="button_reconstruct">
<property name="text">
<string>Reconstruct</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_single">
<property name="text">
<string>Single Slice</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="button_async">
<property name="text">
<string>Sample Async task</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>BECImageWidget</class>
<extends>QWidget</extends>
<header>bec_image_widget</header>
</customwidget>
<customwidget>
<class>ToggleSwitch</class>
<extends>QWidget</extends>
<header>toggle_switch</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>slider_select</sender>
<signal>valueChanged(int)</signal>
<receiver>label_4</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>61</x>
<y>396</y>
</hint>
<hint type="destinationlabel">
<x>73</x>
<y>425</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -634,7 +634,7 @@ class BECImageShow(BECPlotBase):
)
image_item.connected = False
if monitor and image_item.connected is False:
self.entry_validator.validate_monitor(monitor)
# self.entry_validator.validate_monitor(monitor)
if self.image_type == "device_monitor_1d":
self.bec_dispatcher.connect_slot(
self.on_image_update, MessageEndpoints.device_monitor_1d(monitor)

View File

@@ -190,7 +190,7 @@ class BECImageWidget(BECWidget, QWidget):
###################################
# User Access Methods from image
###################################
@SafeSlot(popup_error=True)
@SafeSlot(popup_error=False)
def image(
self,
monitor: str,