bec-widgets 0.83.1__py3-none-any.whl → 0.84.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CHANGELOG.md +34 -36
- PKG-INFO +1 -1
- bec_widgets/cli/client.py +61 -8
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +105 -57
- bec_widgets/utils/bec_dispatcher.py +5 -2
- bec_widgets/widgets/figure/figure.py +21 -114
- bec_widgets/widgets/figure/plots/waveform/waveform.py +651 -94
- bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +9 -2
- {bec_widgets-0.83.1.dist-info → bec_widgets-0.84.0.dist-info}/METADATA +1 -1
- {bec_widgets-0.83.1.dist-info → bec_widgets-0.84.0.dist-info}/RECORD +17 -18
- pyproject.toml +1 -1
- tests/unit_tests/client_mocks.py +13 -4
- tests/unit_tests/test_device_input_widgets.py +2 -0
- tests/unit_tests/test_waveform1d.py +202 -23
- bec_widgets/examples/jupyter_console/jupyter_console_window.ui +0 -54
- {bec_widgets-0.83.1.dist-info → bec_widgets-0.84.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.83.1.dist-info → bec_widgets-0.84.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.83.1.dist-info → bec_widgets-0.84.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
@@ -1,5 +1,39 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## v0.84.0 (2024-07-15)
|
4
|
+
|
5
|
+
### Feature
|
6
|
+
|
7
|
+
* feat(waveform): async readback update implemented for async devices ([`0c6a9f2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/0c6a9f2310df31ddcd68050a17cfbf52c3e2e226))
|
8
|
+
|
9
|
+
* feat(waveform): data are taken directly from ScanItem which is defined from scan_status endpoint; scan update is triggered from scan_segment; plots can be added just specifying y_name -> best effort for setting x reported device ([`b8717f1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b8717f13276734dd655ab03cd6005985ad5af9fb))
|
10
|
+
|
11
|
+
### Fix
|
12
|
+
|
13
|
+
* fix(waveform): timestamp are not converted to human readable format ([`e495fd3`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e495fd30c4c16474689943c7263e3060cb09ffb4))
|
14
|
+
|
15
|
+
* fix(waveform): set_x method various bugs fixed ([`8516a1d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8516a1d639925a877f174fa13f427a71131cc918))
|
16
|
+
|
17
|
+
* fix(waveform): x axis switching logic fixed when axis are not compatible ([`e4e1a90`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e4e1a905d19def22f970b364c18c953f00e10389))
|
18
|
+
|
19
|
+
* fix(waveform): dap leaked RID for all daps in current process; dap RID is now f"{scan_id}-{gui_id}" to distinguish for each plot instance ([`d23fd8b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d23fd8bd074ede6e14eb8e85e025cbced4bd45ef))
|
20
|
+
|
21
|
+
* fix(waveform): only one type of x axis allowed; x mode validated ([`9d6ae87`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9d6ae87d0f03ca227570fcca8af2d8190828d271))
|
22
|
+
|
23
|
+
* fix(waveform): data for axis are taken by separate method; validation consolidated ([`fc5a8bd`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fc5a8bdd8b260f5e9b59ec71a4610c57442e43fe))
|
24
|
+
|
25
|
+
* fix(bec_dispatcher): connect_slot can accept kwargs ([`0aa317a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/0aa317aae58d3612d46f05b85f8b0db3d12bbe14))
|
26
|
+
|
27
|
+
### Refactor
|
28
|
+
|
29
|
+
* refactor(waveform): plot can be prompted without specifying kwargs ([`48911e9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/48911e934815923c94edb5ced6042058a11a97f5))
|
30
|
+
|
31
|
+
* refactor(jupyter_console_window): added more examples of waveforms ([`fc935d9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fc935d9fc81067c3a67389ff88ea97da2e0c903e))
|
32
|
+
|
33
|
+
### Test
|
34
|
+
|
35
|
+
* test(waveform): tests extended ([`006992e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/006992e43cc56d56261bc4fd3e9cae9abcab2153))
|
36
|
+
|
3
37
|
## v0.83.1 (2024-07-14)
|
4
38
|
|
5
39
|
### Fix
|
@@ -105,39 +139,3 @@
|
|
105
139
|
* feat(color_button): can get colors in RGBA or HEX ([`9594be2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9594be260680d11c8550ff74ffb8d679e5a5b8f6))
|
106
140
|
|
107
141
|
## v0.80.1 (2024-07-06)
|
108
|
-
|
109
|
-
### Fix
|
110
|
-
|
111
|
-
* fix(entry_validator): check for entry == "" ([`61de7e9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/61de7e9e221c766b9fb3ec23246da6a11c96a986))
|
112
|
-
|
113
|
-
## v0.80.0 (2024-07-06)
|
114
|
-
|
115
|
-
### Feature
|
116
|
-
|
117
|
-
* feat(qt5): dropped support for qt5; pyside2 and pyqt5 ([`fadbf77`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fadbf77866903beff6580802bc203d53367fc7e7))
|
118
|
-
|
119
|
-
* feat(plugins): moved plugin dict to dataclass and container ([`03819a3`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/03819a3d902b4a51f3e882d52aedd971b2a8e127))
|
120
|
-
|
121
|
-
* feat(plugins): added support for pyqt6 ui files ([`d6d0777`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d6d07771135335cb78dc648508ce573b8970261a))
|
122
|
-
|
123
|
-
* feat(plugins): added bec widgets base class ([`1aa83e0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1aa83e0ef1ffe45b01677b0b4590535cb0ca1cff))
|
124
|
-
|
125
|
-
## v0.79.3 (2024-07-05)
|
126
|
-
|
127
|
-
### Fix
|
128
|
-
|
129
|
-
* fix: changed inheritance to adress qt designer bug in rendering ([`e403870`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e403870874bd5e45840a034d6f1b3dd576d9c846))
|
130
|
-
|
131
|
-
* fix: add designer plugin classes ([`1586ce2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1586ce2d6cba2bb086b2ef596e724bb9e40ab4f2))
|
132
|
-
|
133
|
-
### Refactor
|
134
|
-
|
135
|
-
* refactor: simplify logic in bec_status_box ([`576353c`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/576353cfe8c6fd64db561f0b6e2bc951300643d3))
|
136
|
-
|
137
|
-
## v0.79.2 (2024-07-04)
|
138
|
-
|
139
|
-
### Fix
|
140
|
-
|
141
|
-
* fix: overwrite closeEvent and call super class ([`bc0ef78`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bc0ef7893ef100b71b62101c459655509b534a56))
|
142
|
-
|
143
|
-
## v0.79.1 (2024-07-03)
|
PKG-INFO
CHANGED
bec_widgets/cli/client.py
CHANGED
@@ -19,6 +19,9 @@ class Widgets(str, enum.Enum):
|
|
19
19
|
BECMotorMapWidget = "BECMotorMapWidget"
|
20
20
|
BECQueue = "BECQueue"
|
21
21
|
BECStatusBox = "BECStatusBox"
|
22
|
+
DeviceBox = "DeviceBox"
|
23
|
+
DeviceComboBox = "DeviceComboBox"
|
24
|
+
DeviceLineEdit = "DeviceLineEdit"
|
22
25
|
RingProgressBar = "RingProgressBar"
|
23
26
|
ScanControl = "ScanControl"
|
24
27
|
StopButton = "StopButton"
|
@@ -465,8 +468,9 @@ class BECFigure(RPCBase):
|
|
465
468
|
@rpc_call
|
466
469
|
def plot(
|
467
470
|
self,
|
468
|
-
|
471
|
+
arg1: "list | np.ndarray | str | None" = None,
|
469
472
|
y: "list | np.ndarray | None" = None,
|
473
|
+
x: "list | np.ndarray | None" = None,
|
470
474
|
x_name: "str | None" = None,
|
471
475
|
y_name: "str | None" = None,
|
472
476
|
z_name: "str | None" = None,
|
@@ -488,8 +492,9 @@ class BECFigure(RPCBase):
|
|
488
492
|
Add a 1D waveform plot to the figure. Always access the first waveform widget in the figure.
|
489
493
|
|
490
494
|
Args:
|
491
|
-
|
495
|
+
arg1(list | np.ndarray | str | None): First argument which can be x data, y data, or y_name.
|
492
496
|
y(list | np.ndarray): Custom y data to plot.
|
497
|
+
x(list | np.ndarray): Custom x data to plot.
|
493
498
|
x_name(str): The name of the device for the x-axis.
|
494
499
|
y_name(str): The name of the device for the y-axis.
|
495
500
|
z_name(str): The name of the device for the z-axis.
|
@@ -1494,8 +1499,9 @@ class BECWaveform(RPCBase):
|
|
1494
1499
|
@rpc_call
|
1495
1500
|
def plot(
|
1496
1501
|
self,
|
1497
|
-
|
1502
|
+
arg1: "list | np.ndarray | str | None" = None,
|
1498
1503
|
y: "list | np.ndarray | None" = None,
|
1504
|
+
x: "list | np.ndarray | None" = None,
|
1499
1505
|
x_name: "str | None" = None,
|
1500
1506
|
y_name: "str | None" = None,
|
1501
1507
|
z_name: "str | None" = None,
|
@@ -1507,13 +1513,20 @@ class BECWaveform(RPCBase):
|
|
1507
1513
|
label: "str | None" = None,
|
1508
1514
|
validate: "bool" = True,
|
1509
1515
|
dap: "str | None" = None,
|
1516
|
+
**kwargs,
|
1510
1517
|
) -> "BECCurve":
|
1511
1518
|
"""
|
1512
1519
|
Plot a curve to the plot widget.
|
1520
|
+
|
1513
1521
|
Args:
|
1514
|
-
|
1522
|
+
arg1(list | np.ndarray | str | None): First argument which can be x data, y data, or y_name.
|
1515
1523
|
y(list | np.ndarray): Custom y data to plot.
|
1516
|
-
|
1524
|
+
x(list | np.ndarray): Custom y data to plot.
|
1525
|
+
x_name(str): Name of the x signal.
|
1526
|
+
- "best_effort": Use the best effort signal.
|
1527
|
+
- "timestamp": Use the timestamp signal.
|
1528
|
+
- "index": Use the index signal.
|
1529
|
+
- Custom signal name of device from BEC.
|
1517
1530
|
y_name(str): The name of the device for the y-axis.
|
1518
1531
|
z_name(str): The name of the device for the z-axis.
|
1519
1532
|
x_entry(str): The name of the entry for the x-axis.
|
@@ -1523,7 +1536,7 @@ class BECWaveform(RPCBase):
|
|
1523
1536
|
color_map_z(str): The color map to use for the z-axis.
|
1524
1537
|
label(str): The label of the curve.
|
1525
1538
|
validate(bool): If True, validate the device names and entries.
|
1526
|
-
dap(str): The dap model to use for the curve. If not specified, none will be added.
|
1539
|
+
dap(str): The dap model to use for the curve, only available for sync devices. If not specified, none will be added.
|
1527
1540
|
|
1528
1541
|
Returns:
|
1529
1542
|
BECCurve: The curve object.
|
@@ -1532,12 +1545,13 @@ class BECWaveform(RPCBase):
|
|
1532
1545
|
@rpc_call
|
1533
1546
|
def add_dap(
|
1534
1547
|
self,
|
1535
|
-
x_name: "str",
|
1536
|
-
y_name: "str",
|
1548
|
+
x_name: "str | None" = None,
|
1549
|
+
y_name: "str | None" = None,
|
1537
1550
|
x_entry: "Optional[str]" = None,
|
1538
1551
|
y_entry: "Optional[str]" = None,
|
1539
1552
|
color: "Optional[str]" = None,
|
1540
1553
|
dap: "str" = "GaussianModel",
|
1554
|
+
validate_bec: "bool" = True,
|
1541
1555
|
**kwargs,
|
1542
1556
|
) -> "BECCurve":
|
1543
1557
|
"""
|
@@ -1552,12 +1566,27 @@ class BECWaveform(RPCBase):
|
|
1552
1566
|
color_map_z(str): The color map to use for the z-axis.
|
1553
1567
|
label(str, optional): Label of the curve. Defaults to None.
|
1554
1568
|
dap(str): The dap model to use for the curve.
|
1569
|
+
validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True.
|
1555
1570
|
**kwargs: Additional keyword arguments for the curve configuration.
|
1556
1571
|
|
1557
1572
|
Returns:
|
1558
1573
|
BECCurve: The curve object.
|
1559
1574
|
"""
|
1560
1575
|
|
1576
|
+
@rpc_call
|
1577
|
+
def set_x(self, x_name: "str", x_entry: "str | None" = None):
|
1578
|
+
"""
|
1579
|
+
Change the x axis of the plot widget.
|
1580
|
+
|
1581
|
+
Args:
|
1582
|
+
x_name(str): Name of the x signal.
|
1583
|
+
- "best_effort": Use the best effort signal.
|
1584
|
+
- "timestamp": Use the timestamp signal.
|
1585
|
+
- "index": Use the index signal.
|
1586
|
+
- Custom signal name of device from BEC.
|
1587
|
+
x_entry(str): Entry of the x signal.
|
1588
|
+
"""
|
1589
|
+
|
1561
1590
|
@rpc_call
|
1562
1591
|
def get_dap_params(self) -> "dict":
|
1563
1592
|
"""
|
@@ -1742,6 +1771,12 @@ class BECWaveform(RPCBase):
|
|
1742
1771
|
Remove the plot widget from the figure.
|
1743
1772
|
"""
|
1744
1773
|
|
1774
|
+
@rpc_call
|
1775
|
+
def clear_all(self):
|
1776
|
+
"""
|
1777
|
+
None
|
1778
|
+
"""
|
1779
|
+
|
1745
1780
|
@rpc_call
|
1746
1781
|
def set_legend_label_size(self, size: "int" = None):
|
1747
1782
|
"""
|
@@ -1752,6 +1787,24 @@ class BECWaveform(RPCBase):
|
|
1752
1787
|
"""
|
1753
1788
|
|
1754
1789
|
|
1790
|
+
class DeviceBox(RPCBase):
|
1791
|
+
@property
|
1792
|
+
@rpc_call
|
1793
|
+
def _config_dict(self) -> "dict":
|
1794
|
+
"""
|
1795
|
+
Get the configuration of the widget.
|
1796
|
+
|
1797
|
+
Returns:
|
1798
|
+
dict: The configuration of the widget.
|
1799
|
+
"""
|
1800
|
+
|
1801
|
+
@rpc_call
|
1802
|
+
def _get_all_rpc(self) -> "dict":
|
1803
|
+
"""
|
1804
|
+
Get all registered RPC objects.
|
1805
|
+
"""
|
1806
|
+
|
1807
|
+
|
1755
1808
|
class DeviceComboBox(RPCBase):
|
1756
1809
|
@property
|
1757
1810
|
@rpc_call
|
@@ -2,13 +2,19 @@ import os
|
|
2
2
|
|
3
3
|
import numpy as np
|
4
4
|
import pyqtgraph as pg
|
5
|
-
from qtconsole.inprocess import QtInProcessKernelManager
|
6
|
-
from qtconsole.rich_jupyter_widget import RichJupyterWidget
|
7
5
|
from qtpy.QtCore import QSize
|
8
6
|
from qtpy.QtGui import QIcon
|
9
|
-
from qtpy.QtWidgets import
|
10
|
-
|
11
|
-
|
7
|
+
from qtpy.QtWidgets import (
|
8
|
+
QApplication,
|
9
|
+
QGroupBox,
|
10
|
+
QHBoxLayout,
|
11
|
+
QSplitter,
|
12
|
+
QTabWidget,
|
13
|
+
QVBoxLayout,
|
14
|
+
QWidget,
|
15
|
+
)
|
16
|
+
|
17
|
+
from bec_widgets.utils import BECDispatcher
|
12
18
|
from bec_widgets.utils.colors import apply_theme
|
13
19
|
from bec_widgets.widgets.dock.dock_area import BECDockArea
|
14
20
|
from bec_widgets.widgets.figure import BECFigure
|
@@ -21,14 +27,8 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
21
27
|
def __init__(self, parent=None):
|
22
28
|
super().__init__(parent)
|
23
29
|
|
24
|
-
current_path = os.path.dirname(__file__)
|
25
|
-
self.ui = UILoader().load_ui(os.path.join(current_path, "jupyter_console_window.ui"), self)
|
26
|
-
|
27
30
|
self._init_ui()
|
28
31
|
|
29
|
-
self.ui.splitter.setSizes([200, 100])
|
30
|
-
self.safe_close = False
|
31
|
-
|
32
32
|
# console push
|
33
33
|
if self.console.inprocess is True:
|
34
34
|
self.console.kernel_manager.kernel.shell.push(
|
@@ -40,10 +40,12 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
40
40
|
"w1": self.w1,
|
41
41
|
"w2": self.w2,
|
42
42
|
"w3": self.w3,
|
43
|
-
"w1_c": self.w1_c,
|
44
|
-
"w2_c": self.w2_c,
|
45
|
-
"w3_c": self.w3_c,
|
46
43
|
"w4": self.w4,
|
44
|
+
"w5": self.w5,
|
45
|
+
"w6": self.w6,
|
46
|
+
"w7": self.w7,
|
47
|
+
"w8": self.w8,
|
48
|
+
"w9": self.w9,
|
47
49
|
"d0": self.d0,
|
48
50
|
"d1": self.d1,
|
49
51
|
"d2": self.d2,
|
@@ -53,14 +55,30 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
53
55
|
)
|
54
56
|
|
55
57
|
def _init_ui(self):
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
self.layout = QHBoxLayout(self)
|
59
|
+
|
60
|
+
# Horizontal splitter
|
61
|
+
splitter = QSplitter(self)
|
62
|
+
self.layout.addWidget(splitter)
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
+
tab_widget = QTabWidget(splitter)
|
65
|
+
|
66
|
+
first_tab = QWidget()
|
67
|
+
first_tab_layout = QVBoxLayout(first_tab)
|
68
|
+
self.dock = BECDockArea(gui_id="dock")
|
69
|
+
first_tab_layout.addWidget(self.dock)
|
70
|
+
tab_widget.addTab(first_tab, "Dock Area")
|
71
|
+
|
72
|
+
second_tab = QWidget()
|
73
|
+
second_tab_layout = QVBoxLayout(second_tab)
|
74
|
+
self.figure = BECFigure(parent=self, gui_id="figure")
|
75
|
+
second_tab_layout.addWidget(self.figure)
|
76
|
+
tab_widget.addTab(second_tab, "BEC Figure")
|
77
|
+
|
78
|
+
group_box = QGroupBox("Jupyter Console", splitter)
|
79
|
+
group_box_layout = QVBoxLayout(group_box)
|
80
|
+
self.console = BECJupyterConsole(inprocess=True)
|
81
|
+
group_box_layout.addWidget(self.console)
|
64
82
|
|
65
83
|
# add stuff to figure
|
66
84
|
self._init_figure()
|
@@ -68,44 +86,70 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
68
86
|
# init dock for testing
|
69
87
|
self._init_dock()
|
70
88
|
|
71
|
-
self.
|
72
|
-
self.console = BECJupyterConsole(inprocess=True)
|
73
|
-
self.console_layout.addWidget(self.console)
|
89
|
+
self.setWindowTitle("Jupyter Console Window")
|
74
90
|
|
75
91
|
def _init_figure(self):
|
76
|
-
self.figure.plot(
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
92
|
+
self.w1 = self.figure.plot(
|
93
|
+
x_name="samx",
|
94
|
+
y_name="bpm4i",
|
95
|
+
# title="Standard Plot with sync device, custom labels - w1",
|
96
|
+
# x_label="Motor Position",
|
97
|
+
# y_label="Intensity (A.U.)",
|
98
|
+
row=0,
|
99
|
+
col=0,
|
100
|
+
)
|
101
|
+
self.w1.set(
|
102
|
+
title="Standard Plot with sync device, custom labels - w1",
|
103
|
+
x_label="Motor Position",
|
104
|
+
y_label="Intensity (A.U.)",
|
105
|
+
)
|
106
|
+
self.w2 = self.figure.motor_map("samx", "samy", row=0, col=1)
|
107
|
+
self.w3 = self.figure.image(
|
108
|
+
"eiger", color_map="viridis", vrange=(0, 100), title="Eiger Image - w3", row=0, col=2
|
109
|
+
)
|
110
|
+
self.w4 = self.figure.plot(
|
111
|
+
x_name="samx",
|
112
|
+
y_name="samy",
|
113
|
+
z_name="bpm4i",
|
114
|
+
color_map_z="magma",
|
115
|
+
new=True,
|
116
|
+
title="2D scatter plot - w4",
|
117
|
+
row=0,
|
118
|
+
col=3,
|
119
|
+
)
|
120
|
+
self.w5 = self.figure.plot(
|
121
|
+
y_name="bpm4i",
|
122
|
+
new=True,
|
123
|
+
title="Best Effort Plot - w5",
|
124
|
+
dap="GaussianModel",
|
125
|
+
row=1,
|
126
|
+
col=0,
|
127
|
+
)
|
128
|
+
self.w6 = self.figure.plot(
|
129
|
+
x_name="timestamp", y_name="bpm4i", new=True, title="Timestamp Plot - w6", row=1, col=1
|
130
|
+
)
|
131
|
+
self.w7 = self.figure.plot(
|
132
|
+
x_name="index", y_name="bpm4i", new=True, title="Index Plot - w7", row=1, col=2
|
133
|
+
)
|
134
|
+
self.w8 = self.figure.plot(
|
135
|
+
y_name="monitor_async", new=True, title="Async Plot - Best Effort - w8", row=2, col=0
|
136
|
+
)
|
137
|
+
self.w9 = self.figure.plot(
|
138
|
+
x_name="timestamp",
|
139
|
+
y_name="monitor_async",
|
140
|
+
new=True,
|
141
|
+
title="Async Plot - timestamp - w9",
|
142
|
+
row=2,
|
143
|
+
col=1,
|
144
|
+
)
|
145
|
+
self.w10 = self.figure.plot(
|
146
|
+
x_name="index",
|
147
|
+
y_name="monitor_async",
|
148
|
+
new=True,
|
149
|
+
title="Async Plot - index - w10",
|
150
|
+
row=2,
|
151
|
+
col=2,
|
81
152
|
)
|
82
|
-
|
83
|
-
self.figure.change_layout(2, 2)
|
84
|
-
|
85
|
-
self.w1 = self.figure[0, 0]
|
86
|
-
self.w2 = self.figure[0, 1]
|
87
|
-
self.w3 = self.figure[1, 0]
|
88
|
-
self.w4 = self.figure[1, 1]
|
89
|
-
|
90
|
-
# Plot Customisation
|
91
|
-
self.w1.set_title("Waveform 1")
|
92
|
-
self.w1.set_x_label("Motor Position (samx)")
|
93
|
-
self.w1.set_y_label("Intensity A.U.")
|
94
|
-
|
95
|
-
# Image Customisation
|
96
|
-
self.w3.set_title("Eiger Image")
|
97
|
-
self.w3.set_x_label("X")
|
98
|
-
self.w3.set_y_label("Y")
|
99
|
-
|
100
|
-
# Configs to try to pass
|
101
|
-
self.w1_c = self.w1._config_dict
|
102
|
-
self.w2_c = self.w2._config_dict
|
103
|
-
self.w3_c = self.w3._config_dict
|
104
|
-
|
105
|
-
# curves for w1
|
106
|
-
self.c1 = self.w1.get_config()
|
107
|
-
|
108
|
-
self.fig_c = self.figure._config_dict
|
109
153
|
|
110
154
|
def _init_dock(self):
|
111
155
|
|
@@ -131,9 +175,13 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
131
175
|
|
132
176
|
def closeEvent(self, event):
|
133
177
|
"""Override to handle things when main window is closed."""
|
178
|
+
self.dock.clear_all()
|
134
179
|
self.dock.cleanup()
|
180
|
+
self.dock.close()
|
135
181
|
self.figure.clear_all()
|
136
|
-
self.figure.
|
182
|
+
self.figure.cleanup()
|
183
|
+
self.figure.close()
|
184
|
+
|
137
185
|
super().closeEvent(event)
|
138
186
|
|
139
187
|
|
@@ -134,7 +134,10 @@ class BECDispatcher:
|
|
134
134
|
cls.qapp = None
|
135
135
|
|
136
136
|
def connect_slot(
|
137
|
-
self,
|
137
|
+
self,
|
138
|
+
slot: Callable,
|
139
|
+
topics: Union[EndpointInfo, str, list[Union[EndpointInfo, str]]],
|
140
|
+
**kwargs,
|
138
141
|
) -> None:
|
139
142
|
"""Connect widget's pyqt slot, so that it is called on new pub/sub topic message.
|
140
143
|
|
@@ -144,7 +147,7 @@ class BECDispatcher:
|
|
144
147
|
topics (EndpointInfo | str | list): A topic or list of topics that can typically be acquired via bec_lib.MessageEndpoints
|
145
148
|
"""
|
146
149
|
slot = QtThreadSafeCallback(slot)
|
147
|
-
self.client.connector.register(topics, cb=slot)
|
150
|
+
self.client.connector.register(topics, cb=slot, **kwargs)
|
148
151
|
topics_str, _ = self.client.connector._convert_endpointinfo(topics)
|
149
152
|
self._slots[slot].update(set(topics_str))
|
150
153
|
|
@@ -227,106 +227,12 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
227
227
|
"""
|
228
228
|
self._widgets = value
|
229
229
|
|
230
|
-
def _init_waveform(
|
231
|
-
self,
|
232
|
-
waveform,
|
233
|
-
x_name: str = None,
|
234
|
-
y_name: str = None,
|
235
|
-
z_name: str = None,
|
236
|
-
x_entry: str = None,
|
237
|
-
y_entry: str = None,
|
238
|
-
z_entry: str = None,
|
239
|
-
x: list | np.ndarray = None,
|
240
|
-
y: list | np.ndarray = None,
|
241
|
-
color: str | None = None,
|
242
|
-
color_map_z: str | None = "plasma",
|
243
|
-
label: str | None = None,
|
244
|
-
validate: bool = True,
|
245
|
-
dap: str | None = None,
|
246
|
-
) -> BECWaveform:
|
247
|
-
"""
|
248
|
-
Configure the waveform based on the provided parameters.
|
249
|
-
|
250
|
-
Args:
|
251
|
-
waveform (BECWaveform): The waveform to configure.
|
252
|
-
x (list | np.ndarray): Custom x data to plot.
|
253
|
-
y (list | np.ndarray): Custom y data to plot.
|
254
|
-
x_name (str): The name of the device for the x-axis.
|
255
|
-
y_name (str): The name of the device for the y-axis.
|
256
|
-
z_name (str): The name of the device for the z-axis.
|
257
|
-
x_entry (str): The name of the entry for the x-axis.
|
258
|
-
y_entry (str): The name of the entry for the y-axis.
|
259
|
-
z_entry (str): The name of the entry for the z-axis.
|
260
|
-
color (str): The color of the curve.
|
261
|
-
color_map_z (str): The color map to use for the z-axis.
|
262
|
-
label (str): The label of the curve.
|
263
|
-
validate (bool): If True, validate the device names and entries.
|
264
|
-
dap (str): The DAP model to use for the curve.
|
265
|
-
"""
|
266
|
-
if x is not None and y is None:
|
267
|
-
if isinstance(x, np.ndarray):
|
268
|
-
if x.ndim == 1:
|
269
|
-
y = np.arange(x.size)
|
270
|
-
waveform.add_curve_custom(x=np.arange(x.size), y=x, color=color, label=label)
|
271
|
-
return waveform
|
272
|
-
if x.ndim == 2:
|
273
|
-
waveform.add_curve_custom(x=x[:, 0], y=x[:, 1], color=color, label=label)
|
274
|
-
return waveform
|
275
|
-
elif isinstance(x, list):
|
276
|
-
y = np.arange(len(x))
|
277
|
-
waveform.add_curve_custom(x=np.arange(len(x)), y=x, color=color, label=label)
|
278
|
-
return waveform
|
279
|
-
else:
|
280
|
-
raise ValueError(
|
281
|
-
"Invalid input. Provide either device names (x_name, y_name) or custom data."
|
282
|
-
)
|
283
|
-
if x is not None and y is not None:
|
284
|
-
waveform.add_curve_custom(x=x, y=y, color=color, label=label)
|
285
|
-
return waveform
|
286
|
-
# User wants to add scan curve -> 1D Waveform
|
287
|
-
if x_name is not None and y_name is not None and z_name is None and x is None and y is None:
|
288
|
-
waveform.plot(
|
289
|
-
x_name=x_name,
|
290
|
-
y_name=y_name,
|
291
|
-
x_entry=x_entry,
|
292
|
-
y_entry=y_entry,
|
293
|
-
validate=validate,
|
294
|
-
color=color,
|
295
|
-
label=label,
|
296
|
-
dap=dap,
|
297
|
-
)
|
298
|
-
# User wants to add scan curve -> 2D Waveform Scatter
|
299
|
-
if (
|
300
|
-
x_name is not None
|
301
|
-
and y_name is not None
|
302
|
-
and z_name is not None
|
303
|
-
and x is None
|
304
|
-
and y is None
|
305
|
-
):
|
306
|
-
waveform.plot(
|
307
|
-
x_name=x_name,
|
308
|
-
y_name=y_name,
|
309
|
-
z_name=z_name,
|
310
|
-
x_entry=x_entry,
|
311
|
-
y_entry=y_entry,
|
312
|
-
z_entry=z_entry,
|
313
|
-
color=color,
|
314
|
-
color_map_z=color_map_z,
|
315
|
-
label=label,
|
316
|
-
validate=validate,
|
317
|
-
dap=dap,
|
318
|
-
)
|
319
|
-
# User wants to add custom curve
|
320
|
-
elif x is not None and y is not None and x_name is None and y_name is None:
|
321
|
-
waveform.add_curve_custom(x=x, y=y, color=color, label=label)
|
322
|
-
|
323
|
-
return waveform
|
324
|
-
|
325
230
|
@typechecked
|
326
231
|
def plot(
|
327
232
|
self,
|
328
|
-
|
233
|
+
arg1: list | np.ndarray | str | None = None,
|
329
234
|
y: list | np.ndarray | None = None,
|
235
|
+
x: list | np.ndarray | None = None,
|
330
236
|
x_name: str | None = None,
|
331
237
|
y_name: str | None = None,
|
332
238
|
z_name: str | None = None,
|
@@ -348,8 +254,9 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
348
254
|
Add a 1D waveform plot to the figure. Always access the first waveform widget in the figure.
|
349
255
|
|
350
256
|
Args:
|
351
|
-
|
257
|
+
arg1(list | np.ndarray | str | None): First argument which can be x data, y data, or y_name.
|
352
258
|
y(list | np.ndarray): Custom y data to plot.
|
259
|
+
x(list | np.ndarray): Custom x data to plot.
|
353
260
|
x_name(str): The name of the device for the x-axis.
|
354
261
|
y_name(str): The name of the device for the y-axis.
|
355
262
|
z_name(str): The name of the device for the z-axis.
|
@@ -376,23 +283,23 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
|
|
376
283
|
if config is not None:
|
377
284
|
return waveform
|
378
285
|
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
286
|
+
if arg1 is not None or y_name is not None or (y is not None and x is not None):
|
287
|
+
waveform.plot(
|
288
|
+
arg1=arg1,
|
289
|
+
y=y,
|
290
|
+
x=x,
|
291
|
+
x_name=x_name,
|
292
|
+
y_name=y_name,
|
293
|
+
z_name=z_name,
|
294
|
+
x_entry=x_entry,
|
295
|
+
y_entry=y_entry,
|
296
|
+
z_entry=z_entry,
|
297
|
+
color=color,
|
298
|
+
color_map_z=color_map_z,
|
299
|
+
label=label,
|
300
|
+
validate=validate,
|
301
|
+
dap=dap,
|
302
|
+
)
|
396
303
|
return waveform
|
397
304
|
|
398
305
|
def _init_image(
|