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

refactor: repo reorganization

This commit is contained in:
wyzula-jan
2023-12-12 11:05:33 +01:00
parent cba8131367
commit 3abd955465
33 changed files with 33 additions and 257 deletions

View File

@ -1,127 +0,0 @@
import numpy as np
import pyqtgraph as pg
from pyqtgraph import mkPen
from pyqtgraph.Qt import QtCore, QtWidgets
class ConfigPlotter(pg.GraphicsWidget):
"""
ConfigPlotter is a widget that can be used to plot data from multiple channels
in a grid layout. The layout is specified by a list of dicts, where each dict
specifies the position of the plot in the grid, the channels to plot, and the
type of plot to use. The plot type is specified by the name of the pyqtgraph
item to use. For example, to plot a single channel in a PlotItem, the config
would look like this:
config = [
{
"cols": 1,
"rows": 1,
"y": 0,
"x": 0,
"config": {"channels": ["a"], "label_xy": ["", "a"], "item": "PlotItem"},
}
]
"""
def __init__(self, configs: list[dict], parent=None):
super().__init__(parent)
self.configs = configs
self.plots = {}
self._init_ui()
self._init_plots()
def _init_ui(self):
pg.setConfigOption("background", "w")
pg.setConfigOption("foreground", "k")
# pylint: disable=no-member
self.pen = mkPen(color=(56, 76, 107), width=4, style=QtCore.Qt.SolidLine)
self.view = pg.GraphicsView()
self.view.setAntialiasing(True)
self.view.show()
self.layout = pg.GraphicsLayout()
self.view.setCentralWidget(self.layout)
def _init_plots(self):
for config in self.configs:
channels = config["config"]["channels"]
for channel in channels:
item = pg.PlotItem()
self.layout.addItem(
item,
row=config["y"],
col=config["x"],
rowspan=config["rows"],
colspan=config["cols"],
)
# call the corresponding init function, e.g. init_plotitem
init_func = getattr(self, f"init_{config['config']['item']}")
init_func(channel, config["config"], item)
# self.init_ImageItem(channel, config["config"], item)
def init_PlotItem(self, channel: str, config: dict, item: pg.GraphicsItem):
"""
Initialize a PlotItem
Args:
channel(str): channel to plot
config(dict): config dict for the channel
item(pg.GraphicsItem): PlotItem to plot the data
"""
# pylint: disable=invalid-name
plot_data = item.plot(np.random.rand(100), pen=self.pen)
item.setLabel("left", channel)
self.plots[channel] = {"item": item, "plot_data": plot_data}
def init_ImageItem(self, channel: str, config: dict, item: pg.GraphicsItem):
"""
Initialize an ImageItem
Args:
channel(str): channel to plot
config(dict): config dict for the channel
item(pg.GraphicsItem): ImageItem to plot the data
"""
# pylint: disable=invalid-name
img = pg.ImageItem()
item.addItem(img)
img.setImage(np.random.rand(100, 100))
self.plots[channel] = {"item": item, "plot_data": img}
if __name__ == "__main__":
import sys
CONFIG = [
{
"cols": 1,
"rows": 1,
"y": 0,
"x": 0,
"config": {"channels": ["a"], "label_xy": ["", "a"], "item": "PlotItem"},
},
{
"cols": 1,
"rows": 1,
"y": 1,
"x": 0,
"config": {"channels": ["b"], "label_xy": ["", "b"], "item": "PlotItem"},
},
{
"cols": 1,
"rows": 2,
"y": 0,
"x": 1,
"config": {"channels": ["c"], "label_xy": ["", "c"], "item": "ImageItem"},
},
]
app = QtWidgets.QApplication(sys.argv)
win = ConfigPlotter(CONFIG)
pg.exec()

View File

@ -1,33 +0,0 @@
import os
import sys
from qtpy import QtWidgets, uic
class UI(QtWidgets.QWidget):
def __init__(self, uipath):
super().__init__()
self.ui = uic.loadUi(uipath, self)
_, fname = os.path.split(uipath)
self.setWindowTitle(fname)
self.show()
def main():
"""A basic script to display UI file
Run the script, passing UI file path as an argument, e.g.
$ python bec_widgets/display_ui_file.py bec_widgets/line_plot.ui
"""
app = QtWidgets.QApplication(sys.argv)
UI(sys.argv[1])
sys.exit(app.exec())
if __name__ == "__main__":
main()

View File

@ -22,7 +22,7 @@ from pyqtgraph.Qt import QtCore, uic
from pyqtgraph.Qt import QtWidgets from pyqtgraph.Qt import QtWidgets
from bec_lib import MessageEndpoints from bec_lib import MessageEndpoints
from bec_widgets.qt_utils import Crosshair, Colors from bec_widgets.utils import Crosshair, Colors
# TODO implement: # TODO implement:
@ -570,7 +570,7 @@ class PlotApp(QWidget):
except Exception as e: except Exception as e:
print(f"An error occurred while saving the settings to {file_path}: {e}") print(f"An error occurred while saving the settings to {file_path}: {e}")
def load_settings_from_yaml(self) -> dict: # TODO can be replace by the qt_utils function def load_settings_from_yaml(self) -> dict: # TODO can be replace by the utils function
"""Load settings from a .yaml file using a file dialog and update the current settings.""" """Load settings from a .yaml file using a file dialog and update the current settings."""
options = QFileDialog.Options() options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.DontUseNativeDialog
@ -692,7 +692,7 @@ if __name__ == "__main__":
import argparse import argparse
# from bec_widgets import ctrl_c # from bec_widgets import ctrl_c
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils.bec_dispatcher import bec_dispatcher
parser = argparse.ArgumentParser(description="Plotting App") parser = argparse.ArgumentParser(description="Plotting App")
parser.add_argument( parser.add_argument(

View File

@ -1,9 +1,7 @@
import os import os
from qtpy import uic from qtpy import uic
from qtpy.QtWidgets import QMainWindow, QApplication, QVBoxLayout from qtpy.QtWidgets import QMainWindow, QApplication
from bec_widgets.widgets.monitor import BECMonitor
# some default configs for demonstration purposes # some default configs for demonstration purposes
config_1 = { config_1 = {
@ -197,7 +195,7 @@ class ModularApp(QMainWindow):
if __name__ == "__main__": if __name__ == "__main__":
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils.bec_dispatcher import bec_dispatcher
# BECclient global variables # BECclient global variables
client = bec_dispatcher.client client = bec_dispatcher.client

View File

@ -25,7 +25,7 @@ from qtpy.QtWidgets import QShortcut
from pyqtgraph.Qt import QtWidgets, uic, QtCore from pyqtgraph.Qt import QtWidgets, uic, QtCore
from bec_lib import MessageEndpoints, messages from bec_lib import MessageEndpoints, messages
from bec_widgets.qt_utils import DoubleValidationDelegate from bec_widgets.utils import DoubleValidationDelegate
# TODO - General features # TODO - General features

View File

@ -9,7 +9,8 @@ from qtpy.QtWidgets import QApplication, QTableWidgetItem, QWidget
from pyqtgraph import mkBrush, mkColor, mkPen from pyqtgraph import mkBrush, mkColor, mkPen
from pyqtgraph.Qt import QtCore, uic from pyqtgraph.Qt import QtCore, uic
from bec_widgets.qt_utils import Crosshair from bec_widgets.utils import Crosshair, ctrl_c
# TODO implement: # TODO implement:
# - implement scanID database for visualizing previous scans # - implement scanID database for visualizing previous scans
@ -238,8 +239,7 @@ class PlotApp(QWidget):
if __name__ == "__main__": if __name__ == "__main__":
import yaml import yaml
from bec_widgets import ctrl_c from bec_widgets.utils.bec_dispatcher import bec_dispatcher
from bec_widgets.bec_dispatcher import bec_dispatcher
with open("config_noworker.yaml", "r") as file: with open("config_noworker.yaml", "r") as file:
config = yaml.safe_load(file) config = yaml.safe_load(file)

View File

@ -12,7 +12,7 @@ from qtpy.QtWidgets import (
) )
from pyqtgraph import mkPen from pyqtgraph import mkPen
from pyqtgraph.Qt import QtCore from pyqtgraph.Qt import QtCore
from bec_widgets.qt_utils import Crosshair from bec_widgets.utils import Crosshair
class ExampleApp(QWidget): class ExampleApp(QWidget):

View File

@ -1,21 +1,19 @@
import os import os
import threading import threading
import time import time
import warnings
from typing import Any
import numpy as np import numpy as np
import pyqtgraph import pyqtgraph
import pyqtgraph as pg import pyqtgraph as pg
from bec_lib import messages, MessageEndpoints from bec_lib import messages, MessageEndpoints
from bec_lib.redis_connector import MessageObject, RedisConnector from bec_lib.redis_connector import RedisConnector
from qtpy.QtCore import Slot as pyqtSlot from qtpy.QtCore import Slot as pyqtSlot
from qtpy.QtWidgets import QCheckBox, QTableWidgetItem from qtpy.QtWidgets import QTableWidgetItem
from pyqtgraph import mkBrush, mkColor, mkPen from pyqtgraph import mkBrush, mkPen
from pyqtgraph.Qt import QtCore, QtWidgets, uic from pyqtgraph.Qt import QtCore, QtWidgets, uic
from pyqtgraph.Qt.QtCore import pyqtSignal from pyqtgraph.Qt.QtCore import pyqtSignal
from bec_widgets.qt_utils import Crosshair, Colors from bec_widgets.utils import Crosshair, Colors
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils.bec_dispatcher import bec_dispatcher
# client = bec_dispatcher.client # client = bec_dispatcher.client

View File

@ -1,7 +1,7 @@
from qtpy.QtDesigner import QPyDesignerCustomWidgetPlugin from qtpy.QtDesigner import QPyDesignerCustomWidgetPlugin
from qtpy.QtGui import QIcon from qtpy.QtGui import QIcon
from bec_widgets.scan2d_plot import BECScanPlot2D from bec_widgets.widgets.scan_plot.scan2d_plot import BECScanPlot2D
class BECScanPlot2DPlugin(QPyDesignerCustomWidgetPlugin): class BECScanPlot2DPlugin(QPyDesignerCustomWidgetPlugin):

View File

@ -1,7 +1,7 @@
from qtpy.QtDesigner import QPyDesignerCustomWidgetPlugin from qtpy.QtDesigner import QPyDesignerCustomWidgetPlugin
from qtpy.QtGui import QIcon from qtpy.QtGui import QIcon
from bec_widgets.scan_plot import BECScanPlot from bec_widgets.widgets.scan_plot.scan_plot import BECScanPlot
class BECScanPlotPlugin(QPyDesignerCustomWidgetPlugin): class BECScanPlotPlugin(QPyDesignerCustomWidgetPlugin):

View File

@ -1,12 +0,0 @@
Add/modify the path in the following variable to make the plugin avaiable in Qt Designer:
```
$ export PYQTDESIGNERPATH=/<path to repo>/bec_widgets/qtdesigner_plugins
```
It can be done when activating a conda environment (run with the corresponding env already activated):
```
$ conda env config vars set PYQTDESIGNERPATH=/<path to repo>/bec_widgets/qtdesigner_plugins
```
All the available conda-forge `pyqt >=5.15` packages don't seem to support loading Qt Designer
python plugins at the time of writing. Use `pyqt =5.12` to solve the issue for now.

View File

@ -12,7 +12,7 @@ from qtpy.QtWidgets import (
QLineEdit, QLineEdit,
) )
from bec_widgets.qt_utils.yaml_dialog import load_yaml, save_yaml from bec_widgets.utils.yaml_dialog import load_yaml, save_yaml
current_path = os.path.dirname(__file__) current_path = os.path.dirname(__file__)
Ui_Form, BaseClass = uic.loadUiType(os.path.join(current_path, "config_dialog.ui")) Ui_Form, BaseClass = uic.loadUiType(os.path.join(current_path, "config_dialog.ui"))

View File

@ -5,14 +5,13 @@ import pyqtgraph as pg
from bec_lib import MessageEndpoints from bec_lib import MessageEndpoints
from pydantic import ValidationError from pydantic import ValidationError
from pyqtgraph import mkBrush, mkPen from pyqtgraph import mkBrush, mkPen
from qtpy import QtCore, uic from qtpy import QtCore
from qtpy.QtCore import Signal as pyqtSignal from qtpy.QtCore import Signal as pyqtSignal
from qtpy.QtCore import Slot as pyqtSlot from qtpy.QtCore import Slot as pyqtSlot
from qtpy.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QWidget from qtpy.QtWidgets import QApplication, QMessageBox
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils import Colors, Crosshair
from bec_widgets.qt_utils import Colors, Crosshair from bec_widgets.utils.yaml_dialog import load_yaml
from bec_widgets.qt_utils.yaml_dialog import load_yaml
from bec_widgets.validation import MonitorConfigValidator from bec_widgets.validation import MonitorConfigValidator
# just for demonstration purposes if script run directly # just for demonstration purposes if script run directly
@ -590,7 +589,7 @@ if __name__ == "__main__": # pragma: no cover
import json import json
import sys import sys
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils.bec_dispatcher import bec_dispatcher
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--config_file", help="Path to the config file.") parser.add_argument("--config_file", help="Path to the config file.")

View File

@ -21,7 +21,7 @@ from qtpy.QtWidgets import (
) )
from bec_lib import MessageEndpoints from bec_lib import MessageEndpoints
from bec_widgets.qt_utils.widget_io import WidgetIO from bec_widgets.utils.widget_io import WidgetIO
class ScanArgType: class ScanArgType:
@ -425,7 +425,7 @@ class ScanControl(QWidget):
# Application example # Application example
if __name__ == "__main__": # pragma: no cover if __name__ == "__main__": # pragma: no cover
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils.bec_dispatcher import bec_dispatcher
# BECclient global variables # BECclient global variables
client = bec_dispatcher.client client = bec_dispatcher.client

View File

@ -6,7 +6,7 @@ from bec_lib import MessageEndpoints
from bec_lib.logger import bec_logger from bec_lib.logger import bec_logger
from qtpy.QtCore import Property as pyqtProperty, Slot as pyqtSlot from qtpy.QtCore import Property as pyqtProperty, Slot as pyqtSlot
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils.bec_dispatcher import bec_dispatcher
logger = bec_logger.logger logger = bec_logger.logger

View File

@ -6,7 +6,7 @@ from bec_lib import MessageEndpoints
from bec_lib.logger import bec_logger from bec_lib.logger import bec_logger
from qtpy.QtCore import Property as pyqtProperty, Slot as pyqtSlot from qtpy.QtCore import Property as pyqtProperty, Slot as pyqtSlot
from bec_widgets.bec_dispatcher import bec_dispatcher from bec_widgets.utils.bec_dispatcher import bec_dispatcher
logger = bec_logger.logger logger = bec_logger.logger

View File

@ -5,7 +5,7 @@ from bec_lib.messages import ScanMessage
from bec_lib.connector import MessageObject from bec_lib.connector import MessageObject
# TODO: find a better way to mock singletons # TODO: find a better way to mock singletons
from bec_widgets.bec_dispatcher import _BECDispatcher from bec_widgets.utils.bec_dispatcher import _BECDispatcher
msg = MessageObject(topic="", value=ScanMessage(point_id=0, scanID=0, data={}).dumps()) msg = MessageObject(topic="", value=ScanMessage(point_id=0, scanID=0, data={}).dumps())

View File

@ -1,45 +0,0 @@
import pyqtgraph as pg
from pytestqt import qtbot
from bec_widgets import config_plotter
def test_config_plotter(qtbot):
"""Test ConfigPlotter"""
config = [
{
"cols": 1,
"rows": 1,
"y": 0,
"x": 0,
"config": {"channels": ["a"], "label_xy": ["", "a"], "item": "PlotItem"},
}
]
plotter = config_plotter.ConfigPlotter(config)
assert isinstance(plotter.plots["a"]["item"], pg.PlotItem)
def test_config_plotter_image(qtbot):
"""Test ConfigPlotter"""
config = [
{
"cols": 1,
"rows": 1,
"y": 0,
"x": 0,
"config": {"channels": ["a"], "label_xy": ["", "a"], "item": "PlotItem"},
},
{
"cols": 1,
"rows": 1,
"y": 1,
"x": 0,
"config": {"channels": ["b"], "label_xy": ["", "b"], "item": "ImageItem"},
},
]
plotter = config_plotter.ConfigPlotter(config)
assert isinstance(plotter.plots["a"]["item"], pg.PlotItem)

View File

@ -2,7 +2,7 @@ import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
from qtpy.QtCore import QPointF from qtpy.QtCore import QPointF
from bec_widgets.qt_utils import Crosshair from bec_widgets.utils import Crosshair
def test_mouse_moved_lines(qtbot): def test_mouse_moved_lines(qtbot):

View File

@ -7,7 +7,7 @@ import pytest
from qtpy.QtWidgets import QLineEdit from qtpy.QtWidgets import QLineEdit
from bec_widgets.widgets import ScanControl from bec_widgets.widgets import ScanControl
from bec_widgets.qt_utils.widget_io import WidgetIO from bec_widgets.utils.widget_io import WidgetIO
# TODO there has to be a better way to mock messages than this, in this case I just took the msg from bec # TODO there has to be a better way to mock messages than this, in this case I just took the msg from bec

View File

@ -1,6 +1,4 @@
from pytestqt import qtbot from bec_widgets.widgets.scan_plot import scan_plot
from bec_widgets import scan_plot
def test_scan_plot(qtbot): def test_scan_plot(qtbot):

View File

@ -8,7 +8,7 @@ from qtpy.QtWidgets import (
QSpinBox, QSpinBox,
) )
from bec_widgets.qt_utils.widget_io import WidgetHierarchy from bec_widgets.utils.widget_io import WidgetHierarchy
@pytest.fixture(scope="function") @pytest.fixture(scope="function")

View File

@ -5,7 +5,7 @@ import pytest
import yaml import yaml
from qtpy.QtWidgets import QWidget, QVBoxLayout, QPushButton from qtpy.QtWidgets import QWidget, QVBoxLayout, QPushButton
from bec_widgets.qt_utils.yaml_dialog import load_yaml, save_yaml from bec_widgets.utils.yaml_dialog import load_yaml, save_yaml
@pytest.fixture(scope="function") @pytest.fixture(scope="function")