bec-widgets 0.56.2__py3-none-any.whl → 0.57.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.
.gitlab-ci.yml CHANGED
@@ -273,7 +273,7 @@ end-2-end-conda:
273
273
  - cd ../
274
274
  - pip install -e .[dev,pyqt6]
275
275
  - cd ./tests/end-2-end
276
- - pytest --start-servers --flush-redis --random-order
276
+ - pytest -v --start-servers --flush-redis --random-order
277
277
 
278
278
  artifacts:
279
279
  when: on_failure
CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
 
4
4
 
5
+ ## v0.57.0 (2024-06-05)
6
+
7
+ ### Documentation
8
+
9
+ * docs: extend user documentation for BEC Widgets ([`4160f3d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4160f3d6d7ec1122785b5e3fdfc4afe67a95e9a1))
10
+
11
+ ### Feature
12
+
13
+ * feat(widgets/console): BECJupyterConsole added ([`8c03034`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8c03034acf6b3ed1e346ebf1b785d41068513cc5))
14
+
15
+
16
+ ## v0.56.3 (2024-06-05)
17
+
18
+ ### Ci
19
+
20
+ * ci: increased verbosity for e2e tests ([`4af1abe`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4af1abe4e15b62d2f7e70bf987a1a7d8694ef4d5))
21
+
22
+ ### Fix
23
+
24
+ * fix: fixed support for auto updates ([`131f49d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/131f49da8ea65af4d44b50e81c1acfc29cd92093))
25
+
26
+
5
27
  ## v0.56.2 (2024-06-05)
6
28
 
7
29
  ### Documentation
@@ -142,10 +164,6 @@
142
164
 
143
165
  ## v0.52.0 (2024-05-07)
144
166
 
145
- ### Ci
146
-
147
- * ci: fixed support for child pipelines ([`e65c7f3`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e65c7f3be895ada407bd358edf67d569d2cab08e))
148
-
149
167
  ### Feature
150
168
 
151
169
  * feat(utils/layout_manager): added GridLayoutManager to extend functionalities of native QGridLayout ([`fcd6ef0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fcd6ef0975dc872f69c9d6fb2b8a1ad04a423aae))
@@ -155,22 +173,3 @@
155
173
  ### Fix
156
174
 
157
175
  * fix(widgets/dock): BECDockArea close overwrites the default pyqtgraph Container close + minor improvements ([`ceae979`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ceae979f375ecc33c5c97148f197655c1ca57b6c))
158
-
159
- ### Refactor
160
-
161
- * refactor(widget/plots): WidgetConfig changed to SubplotConfig ([`03fa1f2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/03fa1f26d0fa6b58ed05556fb2438d1e62f6c107))
162
-
163
-
164
- ## v0.51.0 (2024-05-07)
165
-
166
- ### Build
167
-
168
- * build(cli): changed repo name to bec_widgets ([`799ea55`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/799ea554de9a7f3720d100be4886a63f02c6a390))
169
-
170
- ### Ci
171
-
172
- * ci: added rule for parent-child pipelines ([`e085125`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e0851250eecb85503db929d37f75d2ba366308a6))
173
-
174
- ### Feature
175
-
176
- * feat(utils): added plugin helper to find and load ([`5ece269`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5ece269adb0e9b0c2a468f1dfbaa6212e86d3561))
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.56.2
3
+ Version: 0.57.0
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -1,8 +1 @@
1
- from bec_lib.utils.import_utils import lazy_import_from
2
-
3
- # from .auto_updates import AutoUpdates, ScanInfo
4
- # TODO: put back when Pydantic gets faster
5
- AutoUpdates, ScanInfo = lazy_import_from(
6
- "bec_widgets.cli.auto_updates", ("AutoUpdates", "ScanInfo")
7
- )
8
1
  from .client import BECDockArea, BECFigure
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
5
5
  from pydantic import BaseModel
6
6
 
7
7
  if TYPE_CHECKING:
8
- from .client import BECFigure
8
+ from .client import BECDockArea, BECFigure
9
9
 
10
10
 
11
11
  class ScanInfo(BaseModel):
@@ -18,9 +18,20 @@ class ScanInfo(BaseModel):
18
18
 
19
19
 
20
20
  class AutoUpdates:
21
- def __init__(self, figure: BECFigure, enabled: bool = True):
22
- self.enabled = enabled
23
- self.figure = figure
21
+ create_default_dock: bool = False
22
+ enabled: bool = False
23
+ dock_name: str = None
24
+
25
+ def __init__(self, gui: BECDockArea):
26
+ self.gui = gui
27
+
28
+ def start_default_dock(self):
29
+ """
30
+ Create a default dock for the auto updates.
31
+ """
32
+ dock = self.gui.add_dock("default_figure")
33
+ dock.add_widget_bec("BECFigure")
34
+ self.dock_name = "default_figure"
24
35
 
25
36
  @staticmethod
26
37
  def get_scan_info(msg) -> ScanInfo:
@@ -44,6 +55,18 @@ class AutoUpdates:
44
55
  status=status,
45
56
  )
46
57
 
58
+ def get_default_figure(self) -> BECFigure | None:
59
+ """
60
+ Get the default figure from the GUI.
61
+ """
62
+ dock = self.gui.panels.get(self.dock_name, [])
63
+ if not dock:
64
+ return None
65
+ widgets = dock.widget_list
66
+ if not widgets:
67
+ return None
68
+ return widgets[0]
69
+
47
70
  def run(self, msg):
48
71
  """
49
72
  Run the update function if enabled.
@@ -86,33 +109,42 @@ class AutoUpdates:
86
109
  """
87
110
  Simple line scan.
88
111
  """
112
+ fig = self.get_default_figure()
113
+ if not fig:
114
+ return
89
115
  dev_x = info.scan_report_devices[0]
90
- dev_y = self.get_selected_device(info.monitored_devices, self.figure.selected_device)
116
+ dev_y = self.get_selected_device(info.monitored_devices, self.gui.selected_device)
91
117
  if not dev_y:
92
118
  return
93
- self.figure.clear_all()
94
- plt = self.figure.plot(dev_x, dev_y)
119
+ fig.clear_all()
120
+ plt = fig.plot(x_name=dev_x, y_name=dev_y)
95
121
  plt.set(title=f"Scan {info.scan_number}", x_label=dev_x, y_label=dev_y)
96
122
 
97
123
  def simple_grid_scan(self, info: ScanInfo) -> None:
98
124
  """
99
125
  Simple grid scan.
100
126
  """
127
+ fig = self.get_default_figure()
128
+ if not fig:
129
+ return
101
130
  dev_x = info.scan_report_devices[0]
102
131
  dev_y = info.scan_report_devices[1]
103
- dev_z = self.get_selected_device(info.monitored_devices, self.figure.selected_device)
104
- self.figure.clear_all()
105
- plt = self.figure.plot(dev_x, dev_y, dev_z, label=f"Scan {info.scan_number}")
132
+ dev_z = self.get_selected_device(info.monitored_devices, self.gui.selected_device)
133
+ fig.clear_all()
134
+ plt = fig.plot(x_name=dev_x, y_name=dev_y, z_name=dev_z, label=f"Scan {info.scan_number}")
106
135
  plt.set(title=f"Scan {info.scan_number}", x_label=dev_x, y_label=dev_y)
107
136
 
108
137
  def best_effort(self, info: ScanInfo) -> None:
109
138
  """
110
139
  Best effort scan.
111
140
  """
141
+ fig = self.get_default_figure()
142
+ if not fig:
143
+ return
112
144
  dev_x = info.scan_report_devices[0]
113
- dev_y = self.get_selected_device(info.monitored_devices, self.figure.selected_device)
145
+ dev_y = self.get_selected_device(info.monitored_devices, self.gui.selected_device)
114
146
  if not dev_y:
115
147
  return
116
- self.figure.clear_all()
117
- plt = self.figure.plot(dev_x, dev_y, label=f"Scan {info.scan_number}")
148
+ fig.clear_all()
149
+ plt = fig.plot(x_name=dev_x, y_name=dev_y, label=f"Scan {info.scan_number}")
118
150
  plt.set(title=f"Scan {info.scan_number}", x_label=dev_x, y_label=dev_y)
@@ -17,10 +17,13 @@ from bec_lib.utils.import_utils import isinstance_based_on_class_name, lazy_impo
17
17
  from qtpy.QtCore import QCoreApplication
18
18
 
19
19
  import bec_widgets.cli.client as client
20
+ from bec_widgets.cli.auto_updates import AutoUpdates
20
21
 
21
22
  if TYPE_CHECKING:
22
23
  from bec_lib.device import DeviceBase
23
24
 
25
+ from bec_widgets.cli.client import BECDockArea, BECFigure
26
+
24
27
  messages = lazy_import("bec_lib.messages")
25
28
  # from bec_lib.connector import MessageObject
26
29
  MessageObject = lazy_import_from("bec_lib.connector", ("MessageObject",))
@@ -62,16 +65,19 @@ class BECGuiClientMixin:
62
65
  def __init__(self, **kwargs) -> None:
63
66
  super().__init__(**kwargs)
64
67
  self._process = None
65
- self.update_script = self._get_update_script()
68
+ self.auto_updates = self._get_update_script()
66
69
  self._target_endpoint = MessageEndpoints.scan_status()
67
70
  self._selected_device = None
68
71
  self.stderr_output = []
69
72
 
70
- def _get_update_script(self) -> AutoUpdates:
73
+ def _get_update_script(self) -> AutoUpdates | None:
71
74
  eps = imd.entry_points(group="bec.widgets.auto_updates")
72
75
  for ep in eps:
73
76
  if ep.name == "plugin_widgets_update":
74
- return ep.load()(figure=self)
77
+ try:
78
+ return ep.load()(gui=self)
79
+ except Exception as e:
80
+ print(f"Error loading auto update script from plugin: {str(e)}")
75
81
  return None
76
82
 
77
83
  @property
@@ -97,7 +103,7 @@ class BECGuiClientMixin:
97
103
 
98
104
  @staticmethod
99
105
  def _handle_msg_update(msg: MessageObject, parent: BECGuiClientMixin) -> None:
100
- if parent.update_script is not None:
106
+ if parent.auto_updates is not None:
101
107
  # pylint: disable=protected-access
102
108
  parent._update_script_msg_parser(msg.value)
103
109
 
@@ -105,7 +111,7 @@ class BECGuiClientMixin:
105
111
  if isinstance(msg, messages.ScanStatusMessage):
106
112
  if not self.gui_is_alive():
107
113
  return
108
- self.update_script.run(msg)
114
+ self.auto_updates.run(msg)
109
115
 
110
116
  def show(self) -> None:
111
117
  """
@@ -12,22 +12,22 @@ from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
12
12
  from bec_widgets.utils import BECDispatcher, UILoader
13
13
  from bec_widgets.widgets import BECFigure
14
14
  from bec_widgets.widgets.dock.dock_area import BECDockArea
15
-
16
-
17
- class JupyterConsoleWidget(RichJupyterWidget): # pragma: no cover:
18
- def __init__(self):
19
- super().__init__()
20
-
21
- self.kernel_manager = QtInProcessKernelManager()
22
- self.kernel_manager.start_kernel(show_banner=False)
23
- self.kernel_client = self.kernel_manager.client()
24
- self.kernel_client.start_channels()
25
-
26
- self.kernel_manager.kernel.shell.push({"np": np, "pg": pg})
27
-
28
- def shutdown_kernel(self):
29
- self.kernel_client.stop_channels()
30
- self.kernel_manager.shutdown_kernel()
15
+ from bec_widgets.widgets.jupyter_console.jupyter_console import BECJupyterConsole
16
+
17
+ # class JupyterConsoleWidget(RichJupyterWidget): # pragma: no cover:
18
+ # def __init__(self):
19
+ # super().__init__()
20
+ #
21
+ # self.kernel_manager = QtInProcessKernelManager()
22
+ # self.kernel_manager.start_kernel(show_banner=False)
23
+ # self.kernel_client = self.kernel_manager.client()
24
+ # self.kernel_client.start_channels()
25
+ #
26
+ # self.kernel_manager.kernel.shell.push({"np": np, "pg": pg})
27
+ #
28
+ # def shutdown_kernel(self):
29
+ # self.kernel_client.stop_channels()
30
+ # self.kernel_manager.shutdown_kernel()
31
31
 
32
32
 
33
33
  class JupyterConsoleWindow(QWidget): # pragma: no cover:
@@ -45,25 +45,25 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
45
45
  self.safe_close = False
46
46
 
47
47
  # console push
48
- self.console.kernel_manager.kernel.shell.push(
49
- {
50
- "fig": self.figure,
51
- "dock": self.dock,
52
- "w1": self.w1,
53
- "w2": self.w2,
54
- "w3": self.w3,
55
- "d0": self.d0,
56
- "d1": self.d1,
57
- "d2": self.d2,
58
- "fig0": self.fig0,
59
- "fig1": self.fig1,
60
- "fig2": self.fig2,
61
- "bar": self.bar,
62
- "bec": self.figure.client,
63
- "scans": self.figure.client.scans,
64
- "dev": self.figure.client.device_manager.devices,
65
- }
66
- )
48
+ if self.console.inprocess is True:
49
+ self.console.kernel_manager.kernel.shell.push(
50
+ {
51
+ "np": np,
52
+ "pg": pg,
53
+ "fig": self.figure,
54
+ "dock": self.dock,
55
+ "w1": self.w1,
56
+ "w2": self.w2,
57
+ "w3": self.w3,
58
+ "d0": self.d0,
59
+ "d1": self.d1,
60
+ "d2": self.d2,
61
+ "fig0": self.fig0,
62
+ "fig1": self.fig1,
63
+ "fig2": self.fig2,
64
+ "bar": self.bar,
65
+ }
66
+ )
67
67
 
68
68
  def _init_ui(self):
69
69
  # Plotting window
@@ -82,9 +82,8 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
82
82
  self._init_dock()
83
83
 
84
84
  self.console_layout = QVBoxLayout(self.ui.widget_console)
85
- self.console = JupyterConsoleWidget()
85
+ self.console = BECJupyterConsole(inprocess=True)
86
86
  self.console_layout.addWidget(self.console)
87
- self.console.set_default_style("linux")
88
87
 
89
88
  def _init_figure(self):
90
89
  self.figure.plot(x_name="samx", y_name="bpm4d")
@@ -144,7 +143,7 @@ if __name__ == "__main__": # pragma: no cover
144
143
  app = QApplication(sys.argv)
145
144
  app.setApplicationName("Jupyter Console")
146
145
  app.setApplicationDisplayName("Jupyter Console")
147
- qdarktheme.setup_theme("auto")
146
+ # qdarktheme.setup_theme("auto")
148
147
  icon = QIcon()
149
148
  icon.addFile(os.path.join(module_path, "assets", "terminal_icon.png"), size=QSize(48, 48))
150
149
  app.setWindowIcon(icon)
File without changes
@@ -0,0 +1,72 @@
1
+ from bec_ipython_client.main import BECIPythonClient
2
+ from qtconsole.inprocess import QtInProcessKernelManager
3
+ from qtconsole.manager import QtKernelManager
4
+ from qtconsole.rich_jupyter_widget import RichJupyterWidget
5
+ from qtpy.QtWidgets import QApplication, QMainWindow
6
+
7
+
8
+ class BECJupyterConsole(RichJupyterWidget): # pragma: no cover:
9
+ def __init__(self, inprocess: bool = False):
10
+ super().__init__()
11
+
12
+ self.inprocess = None
13
+
14
+ self.kernel_manager, self.kernel_client = self._init_kernel(inprocess=inprocess)
15
+ self.set_default_style("linux")
16
+ self._init_bec()
17
+
18
+ def _init_kernel(self, inprocess: bool = False, kernel_name: str = "python3"):
19
+ self.inprocess = inprocess
20
+ if inprocess is True:
21
+ print("starting inprocess kernel")
22
+ kernel_manager = QtInProcessKernelManager()
23
+ else:
24
+ kernel_manager = QtKernelManager(kernel_name=kernel_name)
25
+ kernel_manager.start_kernel()
26
+ kernel_client = kernel_manager.client()
27
+ kernel_client.start_channels()
28
+ return kernel_manager, kernel_client
29
+
30
+ def _init_bec(self):
31
+ if self.inprocess is True:
32
+ self._init_bec_inprocess()
33
+ else:
34
+ self._init_bec_kernel()
35
+
36
+ def _init_bec_inprocess(self):
37
+ self.client = BECIPythonClient()
38
+ self.client.start()
39
+
40
+ self.kernel_manager.kernel.shell.push(
41
+ {
42
+ "bec": self.client,
43
+ "dev": self.client.device_manager.devices,
44
+ "scans": self.client.scans,
45
+ }
46
+ )
47
+
48
+ def _init_bec_kernel(self):
49
+ self.execute(
50
+ """
51
+ from bec_ipython_client.main import BECIPythonClient
52
+ bec = BECIPythonClient()
53
+ bec.start()
54
+ dev = bec.device_manager.devices if bec else None
55
+ scans = bec.scans if bec else None
56
+ """
57
+ )
58
+
59
+ def shutdown_kernel(self):
60
+ self.kernel_client.stop_channels()
61
+ self.kernel_manager.shutdown_kernel()
62
+
63
+
64
+ if __name__ == "__main__": # pragma: no cover
65
+ import sys
66
+
67
+ app = QApplication(sys.argv)
68
+ win = QMainWindow()
69
+ win.setCentralWidget(BECJupyterConsole(True))
70
+ win.show()
71
+
72
+ sys.exit(app.exec_())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.56.2
3
+ Version: 0.57.0
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -1,12 +1,12 @@
1
1
  .gitignore,sha256=cMQ1MLmnoR88aMCCJwUyfoTnufzl4-ckmHtlFUqHcT4,3253
2
- .gitlab-ci.yml,sha256=14teoIFfOHkepa-_tW9nAxSF3sjdWnRMFLfu2yooR5s,12236
2
+ .gitlab-ci.yml,sha256=RF2JeGh8tG09DyAOwEu991IZy3C8Vm6lI8O_4Dr9B9Q,12239
3
3
  .pylintrc,sha256=OstrgmEyP0smNFBKoIN5_26-UmNZgMHnbjvAWX0UrLs,18535
4
4
  .readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
5
- CHANGELOG.md,sha256=Dlbe1lzOU3UKOPM1DoQGLtyP1ujMmmOlJwmHaj34Sl8,7082
5
+ CHANGELOG.md,sha256=5B8bCS1KZ56bmlknmX87m-IlHrGx5FRlezcvPV5ofKU,6929
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=4xqyCIK1rFhZFj-yomxD4tuLq6qzwkBaMBOZcswJgIM,1135
7
+ PKG-INFO,sha256=dP0il5iNEWbJgS7gF-sZFpiN8YHoUhpBCY2cA6YuoEI,1135
8
8
  README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
9
- pyproject.toml,sha256=gPO0n84KHnJqOMohCjHJo8LvpNSAtUfsTcED4tcQnzU,1803
9
+ pyproject.toml,sha256=7ThtTbvCFc141uvVAUpKkTQUZrOIIlK9qfCMCbX65Ek,1803
10
10
  .git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
11
11
  .gitlab/issue_templates/bug_report_template.md,sha256=gAuyEwl7XlnebBrkiJ9AqffSNOywmr8vygUFWKTuQeI,386
12
12
  .gitlab/issue_templates/documentation_update_template.md,sha256=FHLdb3TS_D9aL4CYZCjyXSulbaW5mrN2CmwTaeLPbNw,860
@@ -15,17 +15,17 @@ pyproject.toml,sha256=gPO0n84KHnJqOMohCjHJo8LvpNSAtUfsTcED4tcQnzU,1803
15
15
  bec_widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  bec_widgets/assets/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqgdX7a00nM3igZdc20pkYM,1747017
17
17
  bec_widgets/assets/terminal_icon.png,sha256=bJl7Tft4Fi2uxvuXI8o14uMHnI9eAWKSU2uftXCH9ws,3889
18
- bec_widgets/cli/__init__.py,sha256=v5oaQMydRVEaqKNI73A3_AbQ0efXxBt2SLoUBKANrV8,301
19
- bec_widgets/cli/auto_updates.py,sha256=ptZeBKr13o9THc8oKLn93K_16i6G3pxzw8hZ4MUgjW4,3845
18
+ bec_widgets/cli/__init__.py,sha256=tLD8HWgyURhMjYlKZ43pBu-qvGD1LI5o3n3rEieg-70,43
19
+ bec_widgets/cli/auto_updates.py,sha256=RFc9sbNE9Ec8K3U1DSrLzwUweM3W51Lmcp9D2gSt2e4,4696
20
20
  bec_widgets/cli/client.py,sha256=tQIaQcNnOkF3M-Ym4_U7vMwpYWgVPEGAJY4ibnlPLgM,52909
21
- bec_widgets/cli/client_utils.py,sha256=IPWfseFBYFjCmBp4LsXyNUOcV5KTTdiW1jsLvG3jF5A,10536
21
+ bec_widgets/cli/client_utils.py,sha256=gxa9TpYCWa0a7jsrMaWv_FQOnfeqP-xht8PYbhcEgys,10802
22
22
  bec_widgets/cli/generate_cli.py,sha256=tBt-F4Xccg9Pj2zuDEGHd0Ho1fKLfCf3PuSa8KmelQk,4431
23
23
  bec_widgets/cli/rpc_register.py,sha256=QxXUZu5XNg00Yf5O3UHWOXg3-f_pzKjjoZYMOa-MOJc,2216
24
24
  bec_widgets/cli/rpc_wigdet_handler.py,sha256=OXHoiDFJPzbQ5RO0bzIX5aUXeMMlJTwAiTmB0_7Chj4,913
25
25
  bec_widgets/cli/server.py,sha256=rsj31Vsx6ayThNe4PQelQFahGjYXFZjfrNyB2fnm6Ro,5737
26
26
  bec_widgets/examples/__init__.py,sha256=WWQ0cu7m8sA4Ehy-DWdTIqSISjaHsbxhsNmNrMnhDZU,202
27
27
  bec_widgets/examples/jupyter_console/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- bec_widgets/examples/jupyter_console/jupyter_console_window.py,sha256=O_jcU7DY39PCrjVSJ7YJtTNSj8-se_AvzsgEiVqmKk8,5266
28
+ bec_widgets/examples/jupyter_console/jupyter_console_window.py,sha256=7cqnDuSXlEVBTP2-UDunby4rsoL7ktaH3uI_bHy4uyU,5344
29
29
  bec_widgets/examples/jupyter_console/jupyter_console_window.ui,sha256=2A2mNTUMZBYygz8K4qWzrcjnNqZBMVyeHm26iLZVRWI,1473
30
30
  bec_widgets/examples/motor_movement/__init__.py,sha256=LzPJkxLAxOsZCbXR-fRCPmeYobp7Yqds6tDxW4W1gSw,214
31
31
  bec_widgets/examples/motor_movement/motor_control_compilations.py,sha256=8rpA7a2xVZTDMrx7YQIj3IJew78J1gcVMkHvloS0U_Q,9055
@@ -63,6 +63,8 @@ bec_widgets/widgets/figure/plots/motor_map/motor_map.py,sha256=HKRbt8sD8fmzpYcEW
63
63
  bec_widgets/widgets/figure/plots/waveform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
64
  bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=k6Lh08V00N9gATppaLgaSaij4Husf8sYU_HXTvF3oB4,21664
65
65
  bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=9q7nJfyH8y9rWw_AIOd6tk7cbckoAGNLHv2oHEKCCyo,7229
66
+ bec_widgets/widgets/jupyter_console/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ bec_widgets/widgets/jupyter_console/jupyter_console.py,sha256=ioLYJL31RdBoAOGFSS8PVSnUhkWPWmLC3tiKp7CouO8,2251
66
68
  bec_widgets/widgets/motor_control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
69
  bec_widgets/widgets/motor_control/motor_control.py,sha256=UrLCvp3J6uiVxWV2jqQbsA2nsMf9s_rrDH2KjnUm-bk,7890
68
70
  bec_widgets/widgets/motor_control/motor_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -105,17 +107,23 @@ docs/introduction/introduction.md,sha256=wp7jmhkUtJnSnEnmIAZGUcau_3-5e5-FohvZb63
105
107
  docs/user/customisation.md,sha256=Og0NuUsTs8HdwKtpHnycGmH8wCqOeYgj2ozlYRJ-Drk,249
106
108
  docs/user/user.md,sha256=uCTcjclIi6rdjYRQebko6bWFEVsjyfshsVU3BDYrC-Y,1403
107
109
  docs/user/api_reference/api_reference.md,sha256=q2Imc48Rq6GcAP0R4bS3KuW5ptZZdsV4wxGJb3JJQHg,174
108
- docs/user/applications/applications.md,sha256=hs8WKVuxBENV2Q7m4wN8wmSI_B3JBYrSYS1IYdbyoWg,147
109
- docs/user/getting_started/getting_started.md,sha256=BagVhtCSoLgYlVaaYOep3KT5r_8DjtQKYj2g-PoU7uw,346
110
- docs/user/getting_started/installation.md,sha256=Rt7O2VI5LRrrRpru1YSb8KAd92znFhHJFs7vhpmHIXQ,1239
110
+ docs/user/applications/applications.md,sha256=yOECfaYRUEDIxF-O0duOwSJlG4f93RylrpMjbw1-8Dg,100
111
+ docs/user/getting_started/command_line_introduction.md,sha256=qTGXnxyRajxv7AXbZaPVVOA5D6zBnK0M0ZF0bniymEM,8683
112
+ docs/user/getting_started/getting_started.md,sha256=zYzoHC8xvHF5wDK66thkdamf8mKKNEudiA-fCOzbedM,358
113
+ docs/user/getting_started/gui_complex_gui.gif,sha256=ovv9u371BGG5GqhzyBMl4mvqMHLfJS0ylr-dR0Ydwtw,6550393
114
+ docs/user/getting_started/installation.md,sha256=nBl2Hfvo6ua3-tVZn1B-UG0hCTlrFY6_ibXHWnXeegs,1135
115
+ docs/user/widgets/bec_figure.md,sha256=KMblP_mANA0ZLotjOIZSw_ErXGzkJdhw1R-WuOWr70Q,5084
116
+ docs/user/widgets/image_plot.gif,sha256=_mVFhMTXGqwDOcEtrBHMZj5Thn2sLhDAHEeL2XyHN-s,14098977
111
117
  docs/user/widgets/motor.gif,sha256=FtaWdRHx4UZaGJPpq8LNhMMgX4PFcAB6IZ93JCMEh_w,2280719
118
+ docs/user/widgets/progress_bar.gif,sha256=5jh0Zw2BBGPuNxszV1DBLJCb4_6glIRX-U2ABjnsK2k,5263592
112
119
  docs/user/widgets/scatter_2D.gif,sha256=yHpsuAUseMafJjI_J5BcOhmE3nu9VFn_Xm9XHzJaH5I,13188862
120
+ docs/user/widgets/spiral_progress_bar.md,sha256=22EqXLGOtiOQdJDznMFQet78zWfAXzQS3IlLjpXOEKs,1119
113
121
  docs/user/widgets/w1D.gif,sha256=tuHbleJpl6bJFNNC2OdndF5LF7IyfvlkFCMGZajrQPs,622773
114
- docs/user/widgets/widgets.md,sha256=vIfilXMyE1iPQMQXGH8wEjXWsFI6GPI0Cn9VQg5lLwI,1879
122
+ docs/user/widgets/widgets.md,sha256=NFdqTlLTHXueErLzvw4wHwTUrzRSEuRelb1fiT4PySg,352
115
123
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
124
  tests/end-2-end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
125
  tests/end-2-end/conftest.py,sha256=b5Yebbj8C1-IcXq23XGbOnXF0kOZD_Po46Z-p4cBwfs,1346
118
- tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=GIROuIBctS-_D8RvxeF35uQPt7tKk4wpVnaWV0w-Ni8,7617
126
+ tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=E2XR6cgmyrHknbe-97LhuSAGlsPguc5VOQ2-Q5Apvm0,9843
119
127
  tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=X8lQLx2NsB6-nU61IhVtAw1-pJ4A2qFgx5PxOWC0V7Q,5527
120
128
  tests/end-2-end/test_rpc_register_e2e.py,sha256=M7sSq3us2yQIW5tAIFOFfBULatZTQNLdt0frh1bINts,1595
121
129
  tests/unit_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -126,7 +134,7 @@ tests/unit_tests/test_bec_dispatcher.py,sha256=rYPiRizHaswhGZw55IBMneDFxmPiCCLAZ
126
134
  tests/unit_tests/test_bec_dock.py,sha256=gvtNkkCPrDFY_1qZ53ZXChdgmQFSwwQrr1VeZC5ybKc,3610
127
135
  tests/unit_tests/test_bec_figure.py,sha256=xYAftY8bI_EH-SlNPD0Tjd7FS_47ouZ1E4hrpjPt7O4,8002
128
136
  tests/unit_tests/test_bec_motor_map.py,sha256=AfD_9-x6VV3TPnkQgNfFYRndPHDsGx-a_YknFeDr6hc,4588
129
- tests/unit_tests/test_client_utils.py,sha256=YFJMqx4XBF_gKOFLfVkaQK3nx4TETtv6kQhJUjH-Rqo,802
137
+ tests/unit_tests/test_client_utils.py,sha256=eViJ1Tz-HX9TkMvQH6W8cO-c3_1I8bUc4_Yen6LOc0E,830
130
138
  tests/unit_tests/test_crosshair.py,sha256=3OMAJ2ZaISYXMOtkXf1rPdy94vCr8njeLi6uHblBL9Q,5045
131
139
  tests/unit_tests/test_generate_cli_client.py,sha256=J7CFoO67txGu_u1Mwk32EejRX204FRuvmVg_yhAr1WM,2397
132
140
  tests/unit_tests/test_motor_control.py,sha256=NBekcGALo5mYkuyBJvBhvJkWiQDV82hI4GmsobRzjTI,20770
@@ -142,7 +150,7 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
142
150
  tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
143
151
  tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
144
152
  tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
145
- bec_widgets-0.56.2.dist-info/METADATA,sha256=4xqyCIK1rFhZFj-yomxD4tuLq6qzwkBaMBOZcswJgIM,1135
146
- bec_widgets-0.56.2.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
147
- bec_widgets-0.56.2.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
148
- bec_widgets-0.56.2.dist-info/RECORD,,
153
+ bec_widgets-0.57.0.dist-info/METADATA,sha256=dP0il5iNEWbJgS7gF-sZFpiN8YHoUhpBCY2cA6YuoEI,1135
154
+ bec_widgets-0.57.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
155
+ bec_widgets-0.57.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
156
+ bec_widgets-0.57.0.dist-info/RECORD,,
@@ -8,7 +8,3 @@
8
8
  maxdepth: 1
9
9
  hidden: true
10
10
  ---
11
-
12
- apps/motor_app
13
- apps/plot_app
14
- apps/modular_app
@@ -0,0 +1,87 @@
1
+ (user.command_line_introduction)=
2
+ # Command Line Introduction
3
+ In order to use BEC Widgets as a plotting tool for BEC, it needs to be [installed](#user.installation) in the same python environment as the BECIpythonClient. If that is the case, it will automatically launch a GUI and assign the control of the GUI to the `gui` object in the client. The GUI backend will also be automatically connect to the BEC server, giving access to all information on the server and allowing the user to visualize the data in real-time.
4
+
5
+ ## BECDockArea
6
+ The `gui` object represents the top level of hierarchy in BEC Widgets. It is a [`BECDockArea`](/api_reference/_autosummary/bec_widgets.cli.client.BECDockArea) based on the [pyqtgraph.dockarea](https://pyqtgraph.readthedocs.io/en/latest/api_reference/dockarea.html). The GUI can be further composed of multiple [`BECDock`](/api_reference/_autosummary/bec_widgets.cli.client.BECDock)s that can be detached and attached to the main area. These docks allow users to freely arrange and customize the widgets they add to the gui, giving them the necessary freedom to design the user interface they desire.
7
+
8
+ ## Widgets
9
+ Widgets are the building blocks of the BEC Widgets framework. They are the visual components that allow users to interact with the data and control the behavior of the application. Each dock can contain multiple widgets, although we recommend using a direct mapping of a single widget to a dock. We currently support two type of widgets:
10
+ - [`BECFigure`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure): A widget that can be used to visualize data from BEC. It is automatically connected to the BEC server and can be used to plot data from BEC.
11
+ - [`SpiralProgressBar`](/api_reference/_autosummary/bec_widgets.cli.client.SpiralProgressBar): A custom widget that can be used to show progress in a spiral shape.
12
+
13
+ **BECFigure**
14
+ The [`BECFigure`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure) widget is one of the core widgets developed for BEC and designed to be flexible and can be used to visualize different types of data. It can be used to visualize [1D Waveform](user.widgets.waveform_1d), [2D Scatter Plot](user.widgets.scatter_2d), [Motor Position Map](user.widgets.motor_map) and 2D image data. As mentioned before, starting the BECIPythonClient will automatically launch a `gui` with a single dock area and a BECFigure widget attached to it. This widget is accessible via the `fig` object from the client directly. We also provide two methods [`plot()`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure.rst#bec_widgets.cli.client.BECFigure.plot), [`image()`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure.rst#bec_widgets.cli.client.BECFigure.image) and [`motor_map()`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure.rst#bec_widgets.cli.client.BECFigure.motor_map) as shortcuts to add a plot, image or motor map to the BECFigure.
15
+
16
+ **Waveform Plot**
17
+ The [`BECWaveForm`](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform) is a widget that can be used to visualize 1D waveform data, i.e. to plot data of a monitor against a motor position. The method [`plot()`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure.rst#bec_widgets.cli.client.BECFigure.plot) of BECFigure adds a BECWaveForm widget to the figure, and returns the plot object.
18
+
19
+ ```python
20
+ plt = fig.add_plot('samx', 'bpm4i')
21
+ ```
22
+ Here, we assign the plot to the object `plt`. We can now use this object to further customize the plot, e.g. changing the title ([`set_title()`](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform.rst#bec_widgets.cli.client.BECWaveform.set_title)), axis labels ([`set_x_label()`](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform.rst#bec_widgets.cli.client.BECWaveform.set_x_label)) or limits ([`set_x_lim()`](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform.rst#bec_widgets.cli.client.BECWaveform.set_x_lim)). We invite you to explore the API of the BECWaveForm in the [documentation](user.widgets.waveform_1d) or directly in the command line.
23
+
24
+ **Scatter Plot**
25
+ The [`BECWaveForm`](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveForm) widget can also be used to visualize 2D scatter plots. More details on setting up the scatter plot are available in the widget documentation of the [scatter plot](user.widgets.scatter_2d).
26
+
27
+ **Motor Map**
28
+ The [`BECMotorMap`](/api_reference/_autosummary/bec_widgets.cli.client.BECMotorMap) widget can be used to visualize the position of motors. It's focused on tracking and visualizing the position of motors, crucial for precise alignment and movement tracking during scans. More details on setting up the motor map are available in the widget documentation of the [motor map](user.widgets.motor_map).
29
+
30
+ **Image Plot**
31
+ The [`BECImageItem`](/api_reference/_autosummary/bec_widgets.cli.client.BECImageItem) widget can be used to visualize 2D image data for example a camera. More details on setting up the image plot are available in the widget documentation of the [image plot](user.widgets.image)
32
+
33
+ ### Useful Commands
34
+ We recommend users to explore the API of the widgets by themselves since we assume that the user interface is supposed to be intuitive and self-explanatory. We appreciate feedback from user in order to constantly improve the experience and allow easy access to the gui, widgets and their functionality. We recommend checking the [API documentation](user.api_reference), but also by using BEC Widgets, exploring the available functions and check their dockstrings.
35
+ ```python
36
+ gui.add_dock? # shows the dockstring of the add_dock method
37
+ ```
38
+
39
+ In addition, we list below a few useful commands that can be used to interface with the widgets:
40
+
41
+ ```python
42
+ gui.panels # returns a dictionary of all docks in the gui
43
+ gui.add_dock() # adds a new dock to the gui
44
+
45
+ dock = gui.panels['dock_2']
46
+ dock.add_widget_bec('BECFigure') # adds a new widget of BECFigure to the dock
47
+ dock.widget_list # returns a list of all widgets in the dock
48
+
49
+ figure = dock.widget_list[0] # assigns the created BECFigure to figure
50
+ plt = figure.add_plot('samx', 'bpm4i') # adds a BECWaveForm plot to the figure
51
+ plt.curves # returns a list of all curves in the plot
52
+ ```
53
+
54
+ We note that commands can also be chained. For example, `gui.add_dock().add_widget_bec('BECFigure')` will add a new dock to the gui and add a new widget of `BECFigure` to the dock.
55
+
56
+ ## Composing a larger GUI
57
+ The example given above introduces BEC Widgets with its different components, and provides an overview of how to interact with the widgets. Nevertheless, another power aspect of BEC Widgets lies in the ability to compose a larger GUI with multiple docks and widgets. This section aims to provide a tutorial like guide on how to compose a more complex GUI that (A) live-plots a 1D waveform, (B) plots data from a camera, and (C) tracks the positions of two motors.
58
+ Let's assume BEC was just started and the `gui` object is available in the client. A single dock is already attached together with a BEC Figure. Let's add the 1D waveform to this dock, change the color of the line to white and add the title *1D Waveform* to the plot.
59
+
60
+ ```python
61
+ plt = fig.add_plot('samx', 'bpm4i')
62
+ plt.curves[0].set_color(color="white")
63
+ plt.set_title('1D Waveform')
64
+ ```
65
+
66
+ Next, we add 2 new docks to the gui, one to plot the data of a camera and one to track the positions of two motors.
67
+ ```ipython
68
+ cam_widget= gui.add_dock(name="cam_dock").add_widget_bec('BECFigure').image("eiger")
69
+ motor_widget = gui.add_dock(name="mot_dock").add_widget_bec('BECFigure').motor_map("samx", "samy")
70
+ ```
71
+ Note, we chain commands here which is possible since the `add_dock` and `add_widget_bec` methods return the dock and the widget respectively. We can now further customize the widgets by changing the title, axis labels, etc.
72
+
73
+ ```python
74
+ cam_widget.set_title("Camera Image Eiger")
75
+ cam_widget.set_vrange(vmin=0, vmax=100)
76
+ ```
77
+ As a final step, we can now add also a SpiralProgressBar to a new dock, and perform a grid_scan with the motors *samx* and *samy*.
78
+ As you see in the example below, all docks are arranged below each other. This is the default behavior of the `add_dock` method. However, the docks can be freely arranged by drag and drop as desired by the user. We invite you to explore this by yourself following the example in the video, and build your custom GUI with BEC Widgets.
79
+
80
+ ```python
81
+ prog_bar = gui.add_dock(name="prog_dock").add_widget_bec('SpiralProgressBar')
82
+ prog_bar.set_line_widths(15)
83
+ scans.grid_scan(dev.samy, -2, 2, 10, dev.samx, -5, 5, 10, exp_time=0.1, relative=False)
84
+ ```
85
+
86
+ ![gui_complex_gui](./gui_complex_gui.gif)
87
+
@@ -8,5 +8,6 @@ maxdepth: 2
8
8
  hidden: true
9
9
  ---
10
10
 
11
- getting_started/installation
11
+ installation/
12
+ command_line_introduction/
12
13
  ```
@@ -1,7 +1,5 @@
1
1
  (user.installation)=
2
2
  # Installation
3
-
4
-
5
3
  **Prerequisites**
6
4
 
7
5
  Before installing BEC Widgets, please ensure the following requirements are met:
@@ -11,25 +9,14 @@ Before installing BEC Widgets, please ensure the following requirements are met:
11
9
 
12
10
  **Standard Installation**
13
11
 
14
- Install BEC Widgets using the pip package manager. Open your terminal and execute:
15
-
16
- ```bash
17
- pip install bec_widgets PyQt6
18
- ```
19
-
20
- This command installs BEC Widgets along with its dependencies, including the default PyQt6.
21
-
22
- **Selecting a PyQt Version**
23
-
24
- BEC Widgets supports both PyQt5 and PyQt6. To install a specific version, use:
12
+ To install BEC Widgets using the pip package manager, execute the following command in your terminal for getting the default PyQT6 version in your python environment:
25
13
 
26
- For PyQt6:
27
14
 
28
15
  ```bash
29
16
  pip install bec_widgets[pyqt6]
30
17
  ```
31
18
 
32
- For PyQt5:
19
+ In case you want to use PyQt5, you can install it by using the following command:
33
20
 
34
21
  ```bash
35
22
  pip install bec_widgets[pyqt5]
@@ -0,0 +1,100 @@
1
+ (user.widgets.bec_figure)=
2
+ # BECFigure
3
+ [`BECFigure`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure) is a widget that provides a graphical user interface for creating and managing plots. It is a versatile tool that allows users to create a wide range of plots, from simple 1D waveforms to complex 2D scatter plots. BECFigure is designed to be user-friendly and interactive, enabling users to customize plots and visualize data in real-time.
4
+ In the following, we describe 4 different type of widgets thaat are available in BECFigure.
5
+
6
+ (user.widgets.waveform_1d)=
7
+ ## [1D Waveform Widget](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform)
8
+
9
+ **Purpose:** This widget provides a straightforward visualization of 1D data. It is particularly useful for plotting positioner movements against detector readings, enabling users to observe correlations and patterns in a simple, linear format.
10
+
11
+ **Key Features:**
12
+ - Real-time plotting of positioner versus detector values.
13
+ - Interactive controls for zooming and panning through the data.
14
+ - Customizable visual elements such as line color and style.
15
+
16
+ **Example of Use:**
17
+ ![Waveform 1D](./w1D.gif)
18
+
19
+ **Code example**
20
+ The following code snipped demonstrates how to create a 1D waveform plot using BEC Widgets within BEC. More details about BEC Widgets in BEC can be found in the getting started section within the [introduction to the command line.](user.command_line_introduction)
21
+ ```python
22
+ # adds a new dock, a new BECFigure and a BECWaveForm to the dock
23
+ plt = gui.add_dock().add_widget_bec('BECFigure').plot('samx', 'bpm4i')
24
+ # add a second curve to the same plot
25
+ plt.add_curve_scan('samx', 'bpm3i')
26
+ plt.set_title("Gauss plots vs. samx")
27
+ plt.set_x_label("Motor X")
28
+ plt.set_y_label("Gauss Signal (A.U.")
29
+ ```
30
+ Note, the return value of the simulated devices *bpm4i* and *bpm3i* may not be gaussian signals, but they can be easily configured with the code snippet below. For more details please check the documentation of the [simulation](https://bec.readthedocs.io/en/latest/developer/devices/bec_sim.html).
31
+ ```python
32
+ # bpm4i uses GaussianModel and samx as a reference; default settings
33
+ dev.bpm4i.sim.select_sim_model("GaussianModel")
34
+ # bpm3i uses StepModel and samx as a reference; default settings
35
+ dev.bpm3i.sim.select_sim_model("StepModel")
36
+ ```
37
+
38
+ (user.widgets.scatter_2d)=
39
+ ## [2D Scatter Plot](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform)
40
+
41
+ **Purpose:** The 2D scatter plot widget is designed for more complex data visualization. It employs a false color map to represent a third dimension (z-axis), making it an ideal tool for visualizing multidimensional data sets.
42
+
43
+ **Key Features:**
44
+
45
+ - 2D scatter plot with color-coded data points based on a third variable (two positioners for x/y vs. one detector for colormap).
46
+ - Interactive false color map for enhanced data interpretation.
47
+ - Tools for selecting and inspecting specific data points.
48
+
49
+ **Example of Use:**
50
+ ![Waveform 1D](./scatter_2D.gif)
51
+
52
+ **Code example**
53
+ The following code snipped demonstrates how to create a 2D scatter plot using BEC Widgets within BEC.
54
+ ```python
55
+ # adds a new dock, a new BECFigure and a BECWaveForm to the dock
56
+ plt = gui.add_dock().add_widget_bec('BECFigure').add_plot('samx', 'samy', 'bpm4i')
57
+ ```
58
+
59
+ (user.widgets.motor_map)=
60
+ ## [Motor Position Map](/api_reference/_autosummary/bec_widgets.cli.client.BECMotorMap)
61
+
62
+ **Purpose:** A specialized component derived from the Motor Alignment Tool. It's focused on tracking and visualizing the position of motors, crucial for precise alignment and movement tracking during scans.
63
+
64
+ **Key Features:**
65
+ - Real-time tracking of motor positions.
66
+ - Visual representation of motor trajectories, aiding in alignment tasks.
67
+
68
+ **Example of Use:**
69
+ ![Waveform 1D](./motor.gif)
70
+
71
+ **Code example**
72
+ The following code snipped demonstrates how to create a motor map using BEC Widgets within BEC.
73
+ ```python
74
+ # add a motor map to the gui
75
+ mot_map = gui.add_dock().add_widget_bec('BECFigure').motor_map('samx', 'samy')
76
+ # change the number of points displayed
77
+ ```
78
+
79
+ (user.widgets.image_2d)=
80
+ ## [Image Plot](/api_reference/_autosummary/bec_widgets.cli.client.BECImageItem)
81
+
82
+ **Purpose:** A versatile widget for visualizing 2D image data, such as camera images. It provides a detailed representation of image data, with an attached color and scale bar to dynamically adjust the image display.
83
+
84
+ **Key Features:**
85
+ - Live-plotting of 2D image data from cameras (*if data stream is available in BEC*).
86
+ - Color maps and scale bars for customizing image display.
87
+ **Example of Use:**
88
+ ![Image 2D](./image_plot.gif)
89
+
90
+ **Code example**
91
+ The following code snipped demonstrates how to create a motor map using BEC Widgets within BEC.
92
+ ```python
93
+ # add a camera view for the eiger camera to the gui
94
+ cam_widget = gui.add_dock().add_widget_bec('BECFigure').image('eiger')
95
+ # set the title of the camera view
96
+ cam_widget.set_title("Camera Image Eiger")
97
+ # change the color map range, e.g. from 0 to 100, per default it is autoscaling
98
+ # Note, the simulation has hot pixels on the detector
99
+ cam_widget.set_vrange(vmin=0, vmax=100)
100
+ ```
Binary file
Binary file
@@ -0,0 +1,21 @@
1
+ (user.widgets.spiral_progress_bar)=
2
+ # [Spiral Progress Bar](/api_reference/_autosummary/bec_widgets.cli.client.SpiralProgressBar)
3
+ **Purpose** The Spiral Progress Bar widget is a circular progress bar that can be used to visualize the progress of a task. The widget is designed to be used in applications where the progress of a task is represented as a percentage. The Spiral Progress Bar widget is a part of the BEC Widgets library and can be controlled directly using its API, or hooked up to the progress of a device readback or scan.
4
+
5
+ **Key Features:**
6
+
7
+ - circular progress bar to show updates on the progress of a task.
8
+ - hooks to update the progress bar from a device readback or scan.
9
+ - multiple progress rings to show different tasks in parallel.
10
+
11
+ **Example of Use:**
12
+ ![SpiralProgressBar](./progress_bar.gif)
13
+
14
+ **Code example**
15
+ The following code snipped demonstrates how to create a 2D scatter plot using BEC Widgets within BEC.
16
+ ```python
17
+ # adds a new dock with a spiral progress bar
18
+ progress = gui.add_dock().add_widget_bec("SpiralProgressBar")
19
+ # customize the size of the ring
20
+ progress.set_line_widfth(20)
21
+ ```
@@ -1,41 +1,15 @@
1
1
  (user.widgets)=
2
2
  # Widgets
3
-
4
- ## Visualization Widgets
5
-
6
3
  BEC Widgets includes a variety of visualization widgets designed to cater to diverse data representation needs in beamline experiments. These widgets enhance the user experience by providing intuitive and interactive data visualizations.
7
4
 
8
- ### 1D Waveform Widget
9
-
10
- **Purpose:** This widget provides a straightforward visualization of 1D data. It is particularly useful for plotting positioner movements against detector readings, enabling users to observe correlations and patterns in a simple, linear format.
11
-
12
- **Key Features:**
13
- - Real-time plotting of positioner versus detector values.
14
- - Interactive controls for zooming and panning through the data.
15
- - Customizable visual elements such as line color and style.
16
-
17
- **Example of Use:**
18
- ![Waveform 1D](./w1D.gif)
19
- ### 2D Scatter Plot
20
-
21
- **Purpose:** The 2D scatter plot widget is designed for more complex data visualization. It employs a false color map to represent a third dimension (z-axis), making it an ideal tool for visualizing multidimensional data sets.
22
-
23
- **Key Features:**
24
-
25
- - 2D scatter plot with color-coded data points based on a third variable (two positioners for x/y vs. one detector for colormap).
26
- - Interactive false color map for enhanced data interpretation.
27
- - Tools for selecting and inspecting specific data points.
28
-
29
- **Example of Use:**
30
- ![Waveform 1D](./scatter_2D.gif)
31
- ### Motor Position Map
5
+ ```{toctree}
6
+ ---
7
+ maxdepth: 2
8
+ hidden: false
9
+ ---
32
10
 
33
- **Purpose:** A specialized component derived from the Motor Alignment Tool. It's focused on tracking and visualizing the position of motors, crucial for precise alignment and movement tracking during scans.
11
+ bec_figure/
12
+ spiral_progress_bar/
13
+ ```
34
14
 
35
- **Key Features:**
36
- - Real-time tracking of motor positions.
37
- - Visual representation of motor trajectories, aiding in alignment tasks.
38
- - Ability to record and recall specific motor positions for repetitive tasks.
39
15
 
40
- **Example of Use:**
41
- ![Waveform 1D](./motor.gif)
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "0.56.2"
7
+ version = "0.57.0"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -1,11 +1,25 @@
1
1
  import numpy as np
2
2
  import pytest
3
+ from bec_lib.client import BECClient
3
4
  from bec_lib.endpoints import MessageEndpoints
4
5
 
6
+ from bec_widgets.cli.auto_updates import AutoUpdates
5
7
  from bec_widgets.cli.client import BECDockArea, BECFigure, BECImageShow, BECMotorMap, BECWaveform
6
8
  from bec_widgets.utils import Colors
7
9
 
8
10
 
11
+ @pytest.fixture(name="bec_client")
12
+ def cli_bec_client(rpc_server_dock):
13
+ """
14
+ Fixture to create a BECClient instance that is independent of the GUI.
15
+ """
16
+ # pylint: disable=protected-access
17
+ cli_client = BECClient(forced=True, config=rpc_server_dock.client._service_config)
18
+ cli_client.start()
19
+ yield cli_client
20
+ cli_client.shutdown()
21
+
22
+
9
23
  def test_rpc_add_dock_with_figure_e2e(rpc_server_dock, qtbot):
10
24
  dock = BECDockArea(rpc_server_dock.gui_id)
11
25
  dock_server = rpc_server_dock.gui
@@ -224,3 +238,57 @@ def test_spiral_bar_scan_update(rpc_server_dock, qtbot):
224
238
  np.testing.assert_allclose(bar_server.rings[1].config.min_value, init_samy, atol=0.1)
225
239
  np.testing.assert_allclose(bar_server.rings[0].config.max_value, final_samx, atol=0.1)
226
240
  np.testing.assert_allclose(bar_server.rings[1].config.max_value, final_samy, atol=0.1)
241
+
242
+
243
+ def test_auto_update(rpc_server_dock, bec_client, qtbot):
244
+ dock = BECDockArea(rpc_server_dock.gui_id)
245
+ dock._client = bec_client
246
+
247
+ AutoUpdates.enabled = True
248
+ AutoUpdates.create_default_dock = True
249
+ dock.auto_updates = AutoUpdates(gui=dock)
250
+ dock.auto_updates.start_default_dock()
251
+ dock.selected_device = "bpm4i"
252
+
253
+ # we need to start the update script manually; normally this is done when the GUI is started
254
+ dock._start_update_script()
255
+
256
+ client = bec_client
257
+ dev = client.device_manager.devices
258
+ scans = client.scans
259
+ queue = client.queue
260
+
261
+ status = scans.line_scan(dev.samx, -5, 5, steps=10, exp_time=0.05, relative=False)
262
+
263
+ # wait for scan to finish
264
+ while not status.status == "COMPLETED":
265
+ qtbot.wait(200)
266
+
267
+ last_scan_data = queue.scan_storage.storage[-1].data
268
+
269
+ # get data from curves
270
+ plt = dock.auto_updates.get_default_figure()
271
+ widgets = plt.widget_list
272
+ plt_data = widgets[0].get_all_data()
273
+
274
+ # check plotted data
275
+ assert plt_data["bpm4i-bpm4i"]["x"] == last_scan_data["samx"]["samx"].val
276
+ assert plt_data["bpm4i-bpm4i"]["y"] == last_scan_data["bpm4i"]["bpm4i"].val
277
+
278
+ status = scans.grid_scan(
279
+ dev.samx, -10, 10, 5, dev.samy, -5, 5, 5, exp_time=0.05, relative=False
280
+ )
281
+
282
+ # wait for scan to finish
283
+ while not status.status == "COMPLETED":
284
+ qtbot.wait(200)
285
+
286
+ plt = dock.auto_updates.get_default_figure()
287
+ widgets = plt.widget_list
288
+ plt_data = widgets[0].get_all_data()
289
+
290
+ last_scan_data = queue.scan_storage.storage[-1].data
291
+
292
+ # check plotted data
293
+ assert plt_data[f"Scan {status.scan.scan_number}"]["x"] == last_scan_data["samx"]["samx"].val
294
+ assert plt_data[f"Scan {status.scan.scan_number}"]["y"] == last_scan_data["samy"]["samy"].val
@@ -25,5 +25,5 @@ def test_rpc_call_accepts_device_as_input(cli_figure):
25
25
  dev1 = FakeDevice("samx")
26
26
  dev2 = FakeDevice("bpm4i")
27
27
  fig, mock_rpc_call = cli_figure
28
- fig.plot(dev1, dev2)
29
- mock_rpc_call.assert_called_with("plot", "samx", "bpm4i")
28
+ fig.plot(x_name=dev1, y_name=dev2)
29
+ mock_rpc_call.assert_called_with("plot", x_name="samx", y_name="bpm4i")