bec-widgets 0.73.2__py3-none-any.whl → 0.74.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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.74.0 (2024-06-25)
4
+
5
+ ### Documentation
6
+
7
+ * docs(becfigure): docs added ([`a51b15d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a51b15da3f5e83e0c897a0342bdb05b9c677a179))
8
+
9
+ ### Feature
10
+
11
+ * feat(waveform1d): dap LMFit model can be added to plot ([`1866ba6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1866ba66c8e3526661beb13fff3e13af6a0ae562))
12
+
13
+ ### Test
14
+
15
+ * test(waveform1d): dap e2e test added ([`7271b42`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/7271b422f98ef9264970d708811c414b69a644db))
16
+
3
17
  ## v0.73.2 (2024-06-25)
4
18
 
5
19
  ### Fix
@@ -133,19 +147,3 @@
133
147
  * fix(generate_cli): fixed rpc generate for classes without user access; closes #226 ([`925c893`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/925c893f3ff4337fc8b4d237c8ffc19a597b0996))
134
148
 
135
149
  ## v0.68.0 (2024-06-21)
136
-
137
- ### Feature
138
-
139
- * feat: properly handle SIGINT (ctrl-c) in BEC GUI server -> calls qapplication.quit() ([`3644f34`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/3644f344da2df674bc0d5740c376a86b9d0dfe95))
140
-
141
- * feat: bec-gui-server: redirect stdout and stderr (if any) as proper debug and error log entries ([`d1266a1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d1266a1ce148ff89557a039e3a182a87a3948f49))
142
-
143
- ### Fix
144
-
145
- * fix: ignore GUI server output (any output will go to log file)
146
-
147
- If a logger is given to log `_start_log_process`, the server stdout and
148
- stderr streams will be redirected as log entries with levels DEBUG or ERROR
149
- in their parent process ([`ce37416`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ce374163cab87a92847409051739777bc505a77b))
150
-
151
- * fix: do not create 'BECClient' logger when instantiating BECDispatcher ([`f7d0b07`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/f7d0b0768ace42a33e2556bb33611d4f02e5a6d9))
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.73.2
3
+ Version: 0.74.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
bec_widgets/cli/client.py CHANGED
@@ -31,6 +31,13 @@ class BECCurve(RPCBase):
31
31
  Remove the curve from the plot.
32
32
  """
33
33
 
34
+ @property
35
+ @rpc_call
36
+ def dap_params(self):
37
+ """
38
+ None
39
+ """
40
+
34
41
  @property
35
42
  @rpc_call
36
43
  def rpc_id(self) -> "str":
@@ -143,6 +150,13 @@ class BECCurve(RPCBase):
143
150
  tuple[np.ndarray,np.ndarray]: X and Y data of the curve.
144
151
  """
145
152
 
153
+ @property
154
+ @rpc_call
155
+ def dap_params(self):
156
+ """
157
+ None
158
+ """
159
+
146
160
 
147
161
  class BECDock(RPCBase):
148
162
  @property
@@ -457,6 +471,7 @@ class BECFigure(RPCBase):
457
471
  row: "int" = None,
458
472
  col: "int" = None,
459
473
  config=None,
474
+ dap: "str | None" = None,
460
475
  **axis_kwargs,
461
476
  ) -> "BECWaveform":
462
477
  """
@@ -550,6 +565,7 @@ class BECFigure(RPCBase):
550
565
  color_map_z: "str | None" = "plasma",
551
566
  label: "str | None" = None,
552
567
  validate: "bool" = True,
568
+ dap: "str | None" = None,
553
569
  **axis_kwargs,
554
570
  ) -> "BECWaveform":
555
571
  """
@@ -568,6 +584,7 @@ class BECFigure(RPCBase):
568
584
  color_map_z(str): The color map to use for the z-axis.
569
585
  label(str): The label of the curve.
570
586
  validate(bool): If True, validate the device names and entries.
587
+ dap(str): The DAP model to use for the curve.
571
588
  **axis_kwargs: Additional axis properties to set on the widget after creation.
572
589
 
573
590
  Returns:
@@ -1467,6 +1484,7 @@ class BECWaveform(RPCBase):
1467
1484
  color_map_z: "str | None" = "plasma",
1468
1485
  label: "str | None" = None,
1469
1486
  validate: "bool" = True,
1487
+ dap: "str | None" = None,
1470
1488
  ) -> "BECCurve":
1471
1489
  """
1472
1490
  Plot a curve to the plot widget.
@@ -1483,11 +1501,50 @@ class BECWaveform(RPCBase):
1483
1501
  color_map_z(str): The color map to use for the z-axis.
1484
1502
  label(str): The label of the curve.
1485
1503
  validate(bool): If True, validate the device names and entries.
1504
+ dap(str): The dap model to use for the curve. If not specified, none will be added.
1505
+
1506
+ Returns:
1507
+ BECCurve: The curve object.
1508
+ """
1509
+
1510
+ @rpc_call
1511
+ def add_dap(
1512
+ self,
1513
+ x_name: "str",
1514
+ y_name: "str",
1515
+ x_entry: "Optional[str]" = None,
1516
+ y_entry: "Optional[str]" = None,
1517
+ color: "Optional[str]" = None,
1518
+ dap: "str" = "GaussianModel",
1519
+ **kwargs,
1520
+ ) -> "BECCurve":
1521
+ """
1522
+ Add LMFIT dap model curve to the plot widget.
1523
+
1524
+ Args:
1525
+ x_name(str): Name of the x signal.
1526
+ x_entry(str): Entry of the x signal.
1527
+ y_name(str): Name of the y signal.
1528
+ y_entry(str): Entry of the y signal.
1529
+ color(str, optional): Color of the curve. Defaults to None.
1530
+ color_map_z(str): The color map to use for the z-axis.
1531
+ label(str, optional): Label of the curve. Defaults to None.
1532
+ dap(str): The dap model to use for the curve.
1533
+ **kwargs: Additional keyword arguments for the curve configuration.
1486
1534
 
1487
1535
  Returns:
1488
1536
  BECCurve: The curve object.
1489
1537
  """
1490
1538
 
1539
+ @rpc_call
1540
+ def get_dap_params(self) -> "dict":
1541
+ """
1542
+ Get the DAP parameters of all DAP curves.
1543
+
1544
+ Returns:
1545
+ dict: DAP parameters of all DAP curves.
1546
+ """
1547
+
1491
1548
  @rpc_call
1492
1549
  def remove_curve(self, *identifiers):
1493
1550
  """
@@ -14,21 +14,6 @@ from bec_widgets.widgets.dock.dock_area import BECDockArea
14
14
  from bec_widgets.widgets.figure import BECFigure
15
15
  from bec_widgets.widgets.jupyter_console.jupyter_console import BECJupyterConsole
16
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
-
32
17
 
33
18
  class JupyterConsoleWindow(QWidget): # pragma: no cover:
34
19
  """A widget that contains a Jupyter console linked to BEC Widgets with full API access (contains Qt and pyqtgraph API)."""
@@ -61,6 +46,7 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
61
46
  "fig0": self.fig0,
62
47
  "fig1": self.fig1,
63
48
  "fig2": self.fig2,
49
+ "plt": self.plt,
64
50
  "bar": self.bar,
65
51
  }
66
52
  )
@@ -115,7 +101,8 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
115
101
 
116
102
  self.d2 = self.dock.add_dock(name="dock_2", position="bottom")
117
103
  self.fig2 = self.d2.add_widget("BECFigure", row=0, col=0)
118
- self.fig2.plot(x_name="samx", y_name="bpm4i")
104
+ self.plt = self.fig2.plot(x_name="samx", y_name="bpm3a")
105
+ self.plt.plot(x_name="samx", y_name="bpm4i", dap="GaussianModel")
119
106
  self.bar = self.d2.add_widget("RingProgressBar", row=0, col=1)
120
107
  self.bar.set_diameter(200)
121
108
 
@@ -228,6 +228,7 @@ class BECConnector:
228
228
  all_connections = self.rpc_register.list_all_connections()
229
229
  if len(all_connections) == 0:
230
230
  print("No more connections. Shutting down GUI BEC client.")
231
+ self.bec_dispatcher.disconnect_all()
231
232
  self.client.shutdown()
232
233
 
233
234
  # def closeEvent(self, event):
@@ -195,10 +195,11 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
195
195
  z_entry: str = None,
196
196
  x: list | np.ndarray = None,
197
197
  y: list | np.ndarray = None,
198
- color: Optional[str] = None,
199
- color_map_z: Optional[str] = "plasma",
200
- label: Optional[str] = None,
198
+ color: str | None = None,
199
+ color_map_z: str | None = "plasma",
200
+ label: str | None = None,
201
201
  validate: bool = True,
202
+ dap: str | None = None,
202
203
  ):
203
204
  """
204
205
  Configure the waveform based on the provided parameters.
@@ -217,6 +218,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
217
218
  color_map_z (str): The color map to use for the z-axis.
218
219
  label (str): The label of the curve.
219
220
  validate (bool): If True, validate the device names and entries.
221
+ dap (str): The DAP model to use for the curve.
220
222
  """
221
223
  if x is not None and y is None:
222
224
  if isinstance(x, np.ndarray):
@@ -240,7 +242,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
240
242
  return waveform
241
243
  # User wants to add scan curve -> 1D Waveform
242
244
  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:
243
- waveform.add_curve_scan(
245
+ waveform.plot(
244
246
  x_name=x_name,
245
247
  y_name=y_name,
246
248
  x_entry=x_entry,
@@ -248,6 +250,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
248
250
  validate=validate,
249
251
  color=color,
250
252
  label=label,
253
+ dap=dap,
251
254
  )
252
255
  # User wants to add scan curve -> 2D Waveform Scatter
253
256
  if (
@@ -257,7 +260,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
257
260
  and x is None
258
261
  and y is None
259
262
  ):
260
- waveform.add_curve_scan(
263
+ waveform.plot(
261
264
  x_name=x_name,
262
265
  y_name=y_name,
263
266
  z_name=z_name,
@@ -268,6 +271,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
268
271
  color_map_z=color_map_z,
269
272
  label=label,
270
273
  validate=validate,
274
+ dap=dap,
271
275
  )
272
276
  # User wants to add custom curve
273
277
  elif x is not None and y is not None and x_name is None and y_name is None:
@@ -292,6 +296,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
292
296
  row: int = None,
293
297
  col: int = None,
294
298
  config=None,
299
+ dap: str | None = None,
295
300
  **axis_kwargs,
296
301
  ) -> BECWaveform:
297
302
  """
@@ -339,6 +344,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
339
344
  color_map_z=color_map_z,
340
345
  label=label,
341
346
  validate=validate,
347
+ dap=dap,
342
348
  )
343
349
  return waveform
344
350
 
@@ -357,6 +363,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
357
363
  color_map_z: str | None = "plasma",
358
364
  label: str | None = None,
359
365
  validate: bool = True,
366
+ dap: str | None = None,
360
367
  **axis_kwargs,
361
368
  ) -> BECWaveform:
362
369
  """
@@ -375,6 +382,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
375
382
  color_map_z(str): The color map to use for the z-axis.
376
383
  label(str): The label of the curve.
377
384
  validate(bool): If True, validate the device names and entries.
385
+ dap(str): The DAP model to use for the curve.
378
386
  **axis_kwargs: Additional axis properties to set on the widget after creation.
379
387
 
380
388
  Returns:
@@ -403,6 +411,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
403
411
  color_map_z=color_map_z,
404
412
  label=label,
405
413
  validate=validate,
414
+ dap=dap,
406
415
  )
407
416
  # TODO remove repetition from .plot method
408
417
  return waveform
@@ -1,10 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import time
3
4
  from collections import defaultdict
4
5
  from typing import Any, Literal, Optional
5
6
 
6
7
  import numpy as np
7
8
  import pyqtgraph as pg
9
+ from bec_lib import messages
8
10
  from bec_lib.endpoints import MessageEndpoints
9
11
  from bec_lib.scan_data import ScanData
10
12
  from pydantic import Field, ValidationError
@@ -36,6 +38,8 @@ class BECWaveform(BECPlotBase):
36
38
  "rpc_id",
37
39
  "config_dict",
38
40
  "plot",
41
+ "add_dap",
42
+ "get_dap_params",
39
43
  "remove_curve",
40
44
  "scan_history",
41
45
  "curves",
@@ -57,6 +61,7 @@ class BECWaveform(BECPlotBase):
57
61
  "set_legend_label_size",
58
62
  ]
59
63
  scan_signal_update = pyqtSignal()
64
+ dap_params_update = pyqtSignal(dict)
60
65
 
61
66
  def __init__(
62
67
  self,
@@ -73,6 +78,7 @@ class BECWaveform(BECPlotBase):
73
78
  )
74
79
 
75
80
  self._curves_data = defaultdict(dict)
81
+ self.old_scan_id = None
76
82
  self.scan_id = None
77
83
 
78
84
  # Scan segment update proxy
@@ -80,6 +86,9 @@ class BECWaveform(BECPlotBase):
80
86
  self.scan_signal_update, rateLimit=25, slot=self._update_scan_segment_plot
81
87
  )
82
88
 
89
+ self.proxy_update_dap = pg.SignalProxy(
90
+ self.scan_signal_update, rateLimit=25, slot=self.refresh_dap
91
+ )
83
92
  # Get bec shortcuts dev, scans, queue, scan_storage, dap
84
93
  self.get_bec_shortcuts()
85
94
 
@@ -213,6 +222,7 @@ class BECWaveform(BECPlotBase):
213
222
  color_map_z: str | None = "plasma",
214
223
  label: str | None = None,
215
224
  validate: bool = True,
225
+ dap: str | None = None, # TODO add dap custom curve wrapper
216
226
  ) -> BECCurve:
217
227
  """
218
228
  Plot a curve to the plot widget.
@@ -229,6 +239,7 @@ class BECWaveform(BECPlotBase):
229
239
  color_map_z(str): The color map to use for the z-axis.
230
240
  label(str): The label of the curve.
231
241
  validate(bool): If True, validate the device names and entries.
242
+ dap(str): The dap model to use for the curve. If not specified, none will be added.
232
243
 
233
244
  Returns:
234
245
  BECCurve: The curve object.
@@ -237,6 +248,8 @@ class BECWaveform(BECPlotBase):
237
248
  if x is not None and y is not None:
238
249
  return self.add_curve_custom(x=x, y=y, label=label, color=color)
239
250
  else:
251
+ if dap:
252
+ self.add_dap(x_name=x_name, y_name=y_name, dap=dap)
240
253
  return self.add_curve_scan(
241
254
  x_name=x_name,
242
255
  y_name=y_name,
@@ -256,6 +269,7 @@ class BECWaveform(BECPlotBase):
256
269
  y: list | np.ndarray,
257
270
  label: str = None,
258
271
  color: str = None,
272
+ curve_source: str = "custom",
259
273
  **kwargs,
260
274
  ) -> BECCurve:
261
275
  """
@@ -266,12 +280,13 @@ class BECWaveform(BECPlotBase):
266
280
  y(list|np.ndarray): Y data of the curve.
267
281
  label(str, optional): Label of the curve. Defaults to None.
268
282
  color(str, optional): Color of the curve. Defaults to None.
283
+ curve_source(str, optional): Tag for source of the curve. Defaults to "custom".
269
284
  **kwargs: Additional keyword arguments for the curve configuration.
270
285
 
271
286
  Returns:
272
287
  BECCurve: The curve object.
273
288
  """
274
- curve_source = "custom"
289
+ curve_source = curve_source
275
290
  curve_id = label or f"Curve {len(self.plot_item.curves) + 1}"
276
291
 
277
292
  curve_exits = self._check_curve_id(curve_id, self._curves_data)
@@ -314,10 +329,12 @@ class BECWaveform(BECPlotBase):
314
329
  color_map_z: Optional[str] = "plasma",
315
330
  label: Optional[str] = None,
316
331
  validate_bec: bool = True,
332
+ source: str = "scan_segment",
333
+ dap: Optional[str] = None,
317
334
  **kwargs,
318
335
  ) -> BECCurve:
319
336
  """
320
- Add a curve to the plot widget from the scan segment.
337
+ Add a curve to the plot widget from the scan segment. #TODO adapt docs to DAP
321
338
 
322
339
  Args:
323
340
  x_name(str): Name of the x signal.
@@ -335,7 +352,7 @@ class BECWaveform(BECPlotBase):
335
352
  BECCurve: The curve object.
336
353
  """
337
354
  # Check if curve already exists
338
- curve_source = "scan_segment"
355
+ curve_source = source
339
356
 
340
357
  # Get entry if not provided and validate
341
358
  x_entry, y_entry, z_entry = self._validate_signal_entries(
@@ -371,12 +388,74 @@ class BECWaveform(BECPlotBase):
371
388
  x=SignalData(name=x_name, entry=x_entry),
372
389
  y=SignalData(name=y_name, entry=y_entry),
373
390
  z=SignalData(name=z_name, entry=z_entry) if z_name else None,
391
+ dap=dap,
374
392
  ),
375
393
  **kwargs,
376
394
  )
377
395
  curve = self._add_curve_object(name=label, source=curve_source, config=curve_config)
378
396
  return curve
379
397
 
398
+ def add_dap(
399
+ self,
400
+ x_name: str,
401
+ y_name: str,
402
+ x_entry: Optional[str] = None,
403
+ y_entry: Optional[str] = None,
404
+ color: Optional[str] = None,
405
+ dap: str = "GaussianModel",
406
+ **kwargs,
407
+ ) -> BECCurve:
408
+ """
409
+ Add LMFIT dap model curve to the plot widget.
410
+
411
+ Args:
412
+ x_name(str): Name of the x signal.
413
+ x_entry(str): Entry of the x signal.
414
+ y_name(str): Name of the y signal.
415
+ y_entry(str): Entry of the y signal.
416
+ color(str, optional): Color of the curve. Defaults to None.
417
+ color_map_z(str): The color map to use for the z-axis.
418
+ label(str, optional): Label of the curve. Defaults to None.
419
+ dap(str): The dap model to use for the curve.
420
+ **kwargs: Additional keyword arguments for the curve configuration.
421
+
422
+ Returns:
423
+ BECCurve: The curve object.
424
+ """
425
+ x_entry, y_entry, _ = self._validate_signal_entries(
426
+ x_name, y_name, None, x_entry, y_entry, None
427
+ )
428
+ label = f"{y_name}-{y_entry}-{dap}"
429
+ curve = self.add_curve_scan(
430
+ x_name=x_name,
431
+ y_name=y_name,
432
+ x_entry=x_entry,
433
+ y_entry=y_entry,
434
+ color=color,
435
+ label=label,
436
+ source="DAP",
437
+ dap=dap,
438
+ pen_style="dash",
439
+ symbol="star",
440
+ **kwargs,
441
+ )
442
+
443
+ self.setup_dap(self.old_scan_id, self.scan_id)
444
+ self.refresh_dap()
445
+ return curve
446
+
447
+ def get_dap_params(self) -> dict:
448
+ """
449
+ Get the DAP parameters of all DAP curves.
450
+
451
+ Returns:
452
+ dict: DAP parameters of all DAP curves.
453
+ """
454
+ params = {}
455
+ for curve_id, curve in self._curves_data["DAP"].items():
456
+ params[curve_id] = curve.dap_params
457
+ return params
458
+
380
459
  def _add_curve_object(
381
460
  self,
382
461
  name: str,
@@ -528,13 +607,75 @@ class BECWaveform(BECPlotBase):
528
607
  return
529
608
 
530
609
  if current_scan_id != self.scan_id:
610
+ self.old_scan_id = self.scan_id
531
611
  self.scan_id = current_scan_id
532
612
  self.scan_segment_data = self.queue.scan_storage.find_scan_by_ID(
533
613
  self.scan_id
534
614
  ) # TODO do scan access through BECFigure
615
+ self.setup_dap(self.old_scan_id, self.scan_id)
535
616
 
536
617
  self.scan_signal_update.emit()
537
618
 
619
+ def setup_dap(self, old_scan_id, new_scan_id):
620
+ """
621
+ Setup DAP for the new scan.
622
+
623
+ Args:
624
+ old_scan_id(str): old_scan_id, used to disconnect the previous dispatcher connection.
625
+ new_scan_id(str): new_scan_id, used to connect the new dispatcher connection.
626
+
627
+ """
628
+ self.bec_dispatcher.disconnect_slot(
629
+ self.update_dap, MessageEndpoints.dap_response(old_scan_id)
630
+ )
631
+ if len(self._curves_data["DAP"]) > 0:
632
+ self.bec_dispatcher.connect_slot(
633
+ self.update_dap, MessageEndpoints.dap_response(new_scan_id)
634
+ )
635
+
636
+ def refresh_dap(self):
637
+ """
638
+ Refresh the DAP curves with the latest data from the DAP model MessageEndpoints.dap_response().
639
+ """
640
+ for curve_id, curve in self._curves_data["DAP"].items():
641
+ x_name = curve.config.signals.x.name
642
+ y_name = curve.config.signals.y.name
643
+ x_entry = curve.config.signals.x.entry
644
+ y_entry = curve.config.signals.y.entry
645
+ model_name = curve.config.signals.dap
646
+ model = getattr(self.dap, model_name)
647
+
648
+ msg = messages.DAPRequestMessage(
649
+ dap_cls="LmfitService1D",
650
+ dap_type="on_demand",
651
+ config={
652
+ "args": [self.scan_id, x_name, x_entry, y_name, y_entry],
653
+ "kwargs": {},
654
+ "class_args": model._plugin_info["class_args"],
655
+ "class_kwargs": model._plugin_info["class_kwargs"],
656
+ },
657
+ metadata={"RID": self.scan_id},
658
+ )
659
+ self.client.connector.set_and_publish(MessageEndpoints.dap_request(), msg)
660
+
661
+ @pyqtSlot(dict, dict)
662
+ def update_dap(self, msg, metadata):
663
+ self.msg = msg
664
+ scan_id, x_name, x_entry, y_name, y_entry = msg["dap_request"].content["config"]["args"]
665
+ model = msg["dap_request"].content["config"]["class_kwargs"]["model"]
666
+
667
+ curve_id_request = f"{y_name}-{y_entry}-{model}"
668
+
669
+ for curve_id, curve in self._curves_data["DAP"].items():
670
+ if curve_id == curve_id_request:
671
+ if msg["data"] is not None:
672
+ x = msg["data"][0]["x"]
673
+ y = msg["data"][0]["y"]
674
+ curve.setData(x, y)
675
+ curve.dap_params = msg["data"][1]["fit_parameters"]
676
+ self.dap_params_update.emit(curve.dap_params)
677
+ break
678
+
538
679
  def _update_scan_segment_plot(self):
539
680
  """Update the plot with the data from the scan segment."""
540
681
  data = self.scan_segment_data.data
@@ -609,13 +750,17 @@ class BECWaveform(BECPlotBase):
609
750
  if scan_index is not None and scan_id is not None:
610
751
  raise ValueError("Only one of scan_id or scan_index can be provided.")
611
752
 
753
+ # Reset DAP connector
754
+ self.bec_dispatcher.disconnect_slot(
755
+ self.update_dap, MessageEndpoints.dap_response(self.scan_id)
756
+ )
612
757
  if scan_index is not None:
613
758
  self.scan_id = self.queue.scan_storage.storage[scan_index].scan_id
614
- data = self.queue.scan_storage.find_scan_by_ID(self.scan_id).data
615
759
  elif scan_id is not None:
616
760
  self.scan_id = scan_id
617
- data = self.queue.scan_storage.find_scan_by_ID(self.scan_id).data
618
761
 
762
+ self.setup_dap(self.old_scan_id, self.scan_id)
763
+ data = self.queue.scan_storage.find_scan_by_ID(self.scan_id).data
619
764
  self._update_scan_curves(data)
620
765
 
621
766
  def get_all_data(self, output: Literal["dict", "pandas"] = "dict") -> dict | pd.DataFrame:
@@ -661,6 +806,9 @@ class BECWaveform(BECPlotBase):
661
806
  def cleanup(self):
662
807
  """Cleanup the widget connection from BECDispatcher."""
663
808
  self.bec_dispatcher.disconnect_slot(self.on_scan_segment, MessageEndpoints.scan_segment())
809
+ self.bec_dispatcher.disconnect_slot(
810
+ self.update_dap, MessageEndpoints.dap_response(self.scan_id)
811
+ )
664
812
  for curve in self.curves:
665
813
  curve.cleanup()
666
814
  super().cleanup()
@@ -31,6 +31,7 @@ class Signal(BaseModel):
31
31
  x: SignalData # TODO maybe add metadata for config gui later
32
32
  y: SignalData
33
33
  z: Optional[SignalData] = None
34
+ dap: Optional[str] = None
34
35
  model_config: dict = {"validate_assignment": True}
35
36
 
36
37
 
@@ -63,6 +64,7 @@ class CurveConfig(ConnectionConfig):
63
64
  class BECCurve(BECConnector, pg.PlotDataItem):
64
65
  USER_ACCESS = [
65
66
  "remove",
67
+ "dap_params",
66
68
  "rpc_id",
67
69
  "config_dict",
68
70
  "set",
@@ -75,6 +77,7 @@ class BECCurve(BECConnector, pg.PlotDataItem):
75
77
  "set_pen_width",
76
78
  "set_pen_style",
77
79
  "get_data",
80
+ "dap_params",
78
81
  ]
79
82
 
80
83
  def __init__(
@@ -96,6 +99,7 @@ class BECCurve(BECConnector, pg.PlotDataItem):
96
99
 
97
100
  self.parent_item = parent_item
98
101
  self.apply_config()
102
+ self.dap_params = None
99
103
  if kwargs:
100
104
  self.set(**kwargs)
101
105
 
@@ -119,6 +123,14 @@ class BECCurve(BECConnector, pg.PlotDataItem):
119
123
  self.setSymbolSize(self.config.symbol_size)
120
124
  self.setSymbol(self.config.symbol)
121
125
 
126
+ @property
127
+ def dap_params(self):
128
+ return self._dap_params
129
+
130
+ @dap_params.setter
131
+ def dap_params(self, value):
132
+ self._dap_params = value
133
+
122
134
  def set_data(self, x, y):
123
135
  if self.config.source == "custom":
124
136
  self.setData(x, y)
@@ -241,5 +253,6 @@ class BECCurve(BECConnector, pg.PlotDataItem):
241
253
 
242
254
  def remove(self):
243
255
  """Remove the curve from the plot."""
244
- self.parent_item.removeItem(self)
256
+ # self.parent_item.removeItem(self)
257
+ self.parent_item.remove_curve(self.name())
245
258
  self.cleanup()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.73.2
3
+ Version: 0.74.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
@@ -2,11 +2,11 @@
2
2
  .gitlab-ci.yml,sha256=RnYDz4zKXjlqltTryprlB1s5vLXxI2-seW-Vb70NNF0,8162
3
3
  .pylintrc,sha256=OstrgmEyP0smNFBKoIN5_26-UmNZgMHnbjvAWX0UrLs,18535
4
4
  .readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
5
- CHANGELOG.md,sha256=1gxCAwPtBXbKQBu8qYGoa5nGPpVo9mCugMJxicel-5Q,7381
5
+ CHANGELOG.md,sha256=3OR7elUbZdoiPcldtqGY44VNZH4TSuz0svsMYCGuLUA,6941
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=j218s_gIgChSd6XQlMySe16wGrVOcS0MEPCZ7S4vU_g,1302
7
+ PKG-INFO,sha256=plkqu38RzQ_wzukLGmT6Em8xZ2dnAFx-2GQHqzkfiBQ,1302
8
8
  README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
9
- pyproject.toml,sha256=f65NttBDHT4IZg0T5qIH5y4QGERQQggr_98iBUPQ5IM,2215
9
+ pyproject.toml,sha256=g7vJWYDj3s2pBA-9wQjQnACLoeiCC8Vv-GMnNT5t2H0,2215
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
@@ -17,7 +17,7 @@ bec_widgets/assets/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqgdX7a00nM3i
17
17
  bec_widgets/assets/terminal_icon.png,sha256=bJl7Tft4Fi2uxvuXI8o14uMHnI9eAWKSU2uftXCH9ws,3889
18
18
  bec_widgets/cli/__init__.py,sha256=d0Q6Fn44e7wFfLabDOBxpcJ1DPKWlFunGYDUBmO-4hA,22
19
19
  bec_widgets/cli/auto_updates.py,sha256=DyBV3HnjMSH-cvVkYNcDiYKVf0Xut4Qy2qGQqkW47Bw,4833
20
- bec_widgets/cli/client.py,sha256=faWHDMG9mwD1fB5ptuZ-_QWka0Lrv9iJ94QupwmqCmY,59358
20
+ bec_widgets/cli/client.py,sha256=dXno8pOJ3sP6fAA_nEkAyX2XfJ75GUDVqAkHcYYxCjU,60979
21
21
  bec_widgets/cli/client_utils.py,sha256=zq1gPW7t4n9Nsn4MLkdUeKwwl-9nUcf5UjuN8lZr9iY,12281
22
22
  bec_widgets/cli/generate_cli.py,sha256=InKBVYM7DRfAVLNJhRJbWWSSPBQBHI8Ek6v7NCsK0ME,4997
23
23
  bec_widgets/cli/rpc_register.py,sha256=QxXUZu5XNg00Yf5O3UHWOXg3-f_pzKjjoZYMOa-MOJc,2216
@@ -25,7 +25,7 @@ bec_widgets/cli/rpc_wigdet_handler.py,sha256=1qQOGrM8rozaWLkoxAW8DTVLv_L_DZdZgUM
25
25
  bec_widgets/cli/server.py,sha256=2EJvkQDzrDTsZjRPs7g2v_iPTspGqxzY34tRAnvjxjY,7281
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=VdX3OwlIiUCD4b75MQS4YwLLaZGvsJ-z3QFPe2y9f78,5343
28
+ bec_widgets/examples/jupyter_console/jupyter_console_window.py,sha256=tyvV9ZW5QHgF7Q2AqaUPO0cdz3eldZnIlVCqwd9CkGA,4910
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
@@ -38,7 +38,7 @@ bec_widgets/examples/plugin_example_pyside/tictactoe.py,sha256=s3rCurXloVcmMdzZi
38
38
  bec_widgets/examples/plugin_example_pyside/tictactoeplugin.py,sha256=BBt3MD8oDLUMCCY3mioJa1QRR0WQdW6DuvVmK1Taovk,1734
39
39
  bec_widgets/examples/plugin_example_pyside/tictactoetaskmenu.py,sha256=LNwplI6deUdKY6FOhUuWBanotxk9asF2G-6k7lFfA8Y,2301
40
40
  bec_widgets/utils/__init__.py,sha256=1930ji1Jj6dVuY81Wd2kYBhHYNV-2R0bN_L4o9zBj1U,533
41
- bec_widgets/utils/bec_connector.py,sha256=3BNkb83HZDNL_fwbvMnG6FM28VTmlsndnc4z84E3v1w,7286
41
+ bec_widgets/utils/bec_connector.py,sha256=t59482Tu30eiQ2YNHJZFEE-wQFt4qf85OmBfPkl-3N4,7335
42
42
  bec_widgets/utils/bec_designer.py,sha256=2ay6c7dLozV06vsJcceoMRe78ePxQf_7pxnrEZjOrB8,4386
43
43
  bec_widgets/utils/bec_dispatcher.py,sha256=yM9PG04O7ABhiA9Nzk38Rv9Qbjc5O93wi2xfSbOlOxc,6202
44
44
  bec_widgets/utils/bec_table.py,sha256=nA2b8ukSeUfquFMAxGrUVOqdrzMoDYD6O_4EYbOG2zk,717
@@ -79,7 +79,7 @@ bec_widgets/widgets/dock/__init__.py,sha256=B7foHt02gnhM7mFksa7GJVwT7n0j_JvYDCt6
79
79
  bec_widgets/widgets/dock/dock.py,sha256=lEl6ppy0v-8X5bVX7EQIYka8rAakjkZyh6ufgr7YxKs,7595
80
80
  bec_widgets/widgets/dock/dock_area.py,sha256=9c_tLzyBRllLfc4H5o9-4bvasWp5hWe1NWg4mupXVtU,7911
81
81
  bec_widgets/widgets/figure/__init__.py,sha256=3hGx_KOV7QHCYAV06aNuUgKq4QIYCjUTad-DrwkUaBM,44
82
- bec_widgets/widgets/figure/figure.py,sha256=3bf1TyzIE8kVRDgjLqdlvCoE4wrozyfbeCWLjCo1Fwo,31821
82
+ bec_widgets/widgets/figure/figure.py,sha256=3lmx93RLrXfLp07NYcUujD-O79ATmVQUzkEyowJPOzQ,32097
83
83
  bec_widgets/widgets/figure/plots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
84
  bec_widgets/widgets/figure/plots/plot_base.py,sha256=QdDMMuWwTK0f6kNN8aAPBM7jah7TpUbYrMrRTdb2EZY,10419
85
85
  bec_widgets/widgets/figure/plots/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -89,8 +89,8 @@ bec_widgets/widgets/figure/plots/image/image_processor.py,sha256=GeTtWjbldy6VejM
89
89
  bec_widgets/widgets/figure/plots/motor_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
90
  bec_widgets/widgets/figure/plots/motor_map/motor_map.py,sha256=Ff2WoNHxO_A3ggsbSd_AVUP1JeOWMuJs-0GLskxn-94,15267
91
91
  bec_widgets/widgets/figure/plots/waveform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
- bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=Z0cgQitW4SvBnQHvhsTJvx-2yoOW231GulhrM4o0hbA,23560
93
- bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=lTyeCydzvrcdvQXc89jEjoor-Uvo54i197-_M4VtqX8,7970
92
+ bec_widgets/widgets/figure/plots/waveform/waveform.py,sha256=j_Lb3ovxKzNKgssNTR9HJ-L4MP-SmesRcdyxIcbqnO0,29101
93
+ bec_widgets/widgets/figure/plots/waveform/waveform_curve.py,sha256=mSBzqQNpLhol1_2_9k7s2b-Y0ICGU242T39md0LxTSA,8291
94
94
  bec_widgets/widgets/jupyter_console/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
95
  bec_widgets/widgets/jupyter_console/jupyter_console.py,sha256=ioLYJL31RdBoAOGFSS8PVSnUhkWPWmLC3tiKp7CouO8,2251
96
96
  bec_widgets/widgets/motor_control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -153,7 +153,8 @@ docs/user/getting_started/gui_complex_gui.gif,sha256=ovv9u371BGG5GqhzyBMl4mvqMHL
153
153
  docs/user/getting_started/installation.md,sha256=5_fPbmUqLGtwOskFHTlytd4PJKrMcHqHShzM9ymM0oI,1149
154
154
  docs/user/getting_started/quick_start.md,sha256=ABDRRB8DM8dFYdsWUfzQV0eaffRFAlcn2HIfw7yiUGs,9401
155
155
  docs/user/widgets/BECFigure.png,sha256=8dQr4u0uk_y0VV-R1Jh9yTR3Vidd9HDEno_07R0swaE,1605920
156
- docs/user/widgets/bec_figure.md,sha256=BwcumbhZd6a2zKmoHTvwKr8kG8WxBx9lS_QwxNiBMpQ,5155
156
+ docs/user/widgets/bec_figure.md,sha256=tNT-5QP3DekY_iC9jOMULzdxmUU8wMkkX5Ru9yq0Txo,6671
157
+ docs/user/widgets/bec_figure_dap.gif,sha256=8EBRKcB7828M7w429c7djTZG2AbfJ-Zsy1epPvyYoII,4058735
157
158
  docs/user/widgets/bec_status_box.gif,sha256=kLxf40HbS6fjdUIQ2b9SiduBEXdBd4DDWGEnQDOFMcY,1259044
158
159
  docs/user/widgets/bec_status_box.md,sha256=YJ7uHuaHRsvP7tkC65O7siJOzm1LRtsrvH1ikeOH9xo,1156
159
160
  docs/user/widgets/buttons.md,sha256=Yci21PmxlRvfKcrvY7mVI7JkECPmE6j9WyWyH3j7Y2o,1221
@@ -171,8 +172,8 @@ docs/user/widgets/widgets.md,sha256=ZeRNmP7GUOu8kEoGu9XHsyF8Hb1foqZKEbwpgFP7ITk,
171
172
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
173
  tests/end-2-end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
173
174
  tests/end-2-end/conftest.py,sha256=-BLnFE-NeCerf6xahGCkbZ4Ktactowi6RkBnboIzRvg,1767
174
- tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=RyVSYBSA4XnECJlHnXL2ISG17QSKS5dXEsZT-VP2PzM,9057
175
- tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=zTbB_F4Fs-QG8KhMK24xfsrCQBgZUAguMk3KFdEdP2o,5095
175
+ tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=59nrcbEB0NK7ttXdOizN9kjUaqhMImVGaf4aciT4Jcs,9099
176
+ tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=rAVA7aLP7dhQNK_BQK9wD-1whhy-MIyeIgknY5xwSAU,5980
176
177
  tests/end-2-end/test_rpc_register_e2e.py,sha256=3dfCnSvdcRO92pzHt9WlCTK0vzTKAvPtliEoEKrtuzQ,1604
177
178
  tests/end-2-end/test_scan_control_e2e.py,sha256=u7oLgFyltkMW2apSZKDukMIXvYrbhHrU32p4mBdn8VE,2276
178
179
  tests/unit_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -202,7 +203,7 @@ tests/unit_tests/test_scan_control_group_box.py,sha256=HNqjP10B_NonikspNwKz9upJU
202
203
  tests/unit_tests/test_stop_button.py,sha256=2OH9dhs_-S5QovPPgU-5hJoViE1YKZa0gxisb4vOY28,712
203
204
  tests/unit_tests/test_text_box_widget.py,sha256=cT0uEHt_6d-FwST0A_wE9sFW9E3F_nJbKhuBAeU4yHg,1862
204
205
  tests/unit_tests/test_vscode_widget.py,sha256=NVB23ppLqIj-Opd8QnapqUJzDMz6mIZfm3wGPnFXyUE,2788
205
- tests/unit_tests/test_waveform1d.py,sha256=I3_pF0ieltcTWtweOBjICaOxJ8NCQ0-NWxpKg8Pas3E,15893
206
+ tests/unit_tests/test_waveform1d.py,sha256=bADYGc7COoDnYxaAM0fX6SUASOVirlZEOnXIOlyajNw,15993
206
207
  tests/unit_tests/test_website_widget.py,sha256=fBADIJJBAHU4Ro7u95kdemFVNv196UOcuO9oLHuHt8A,761
207
208
  tests/unit_tests/test_widget_io.py,sha256=FeL3ZYSBQnRt6jxj8VGYw1cmcicRQyHKleahw7XIyR0,3475
208
209
  tests/unit_tests/test_yaml_dialog.py,sha256=HNrqferkdg02-9ieOhhI2mr2Qvt7GrYgXmQ061YCTbg,5794
@@ -211,8 +212,8 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
211
212
  tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
212
213
  tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
213
214
  tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
214
- bec_widgets-0.73.2.dist-info/METADATA,sha256=j218s_gIgChSd6XQlMySe16wGrVOcS0MEPCZ7S4vU_g,1302
215
- bec_widgets-0.73.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
216
- bec_widgets-0.73.2.dist-info/entry_points.txt,sha256=3otEkCdDB9LZJuBLzG4pFLK5Di0CVybN_12IsZrQ-58,166
217
- bec_widgets-0.73.2.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
218
- bec_widgets-0.73.2.dist-info/RECORD,,
215
+ bec_widgets-0.74.0.dist-info/METADATA,sha256=plkqu38RzQ_wzukLGmT6Em8xZ2dnAFx-2GQHqzkfiBQ,1302
216
+ bec_widgets-0.74.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
217
+ bec_widgets-0.74.0.dist-info/entry_points.txt,sha256=3otEkCdDB9LZJuBLzG4pFLK5Di0CVybN_12IsZrQ-58,166
218
+ bec_widgets-0.74.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
219
+ bec_widgets-0.74.0.dist-info/RECORD,,
@@ -7,7 +7,6 @@ In the following, we describe 4 different type of widgets thaat are available in
7
7
 
8
8
  ![BECFigure.png](BECFigure.png)
9
9
 
10
- (user.widgets.waveform_1d)=
11
10
  ## [1D Waveform Widget](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform)
12
11
 
13
12
  **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.
@@ -20,11 +19,12 @@ In the following, we describe 4 different type of widgets thaat are available in
20
19
  **Example of Use:**
21
20
  ![Waveform 1D](./w1D.gif)
22
21
 
23
- **Code example**
22
+ **Code example 1 - adding curves**
23
+
24
24
  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)
25
25
  ```python
26
26
  # adds a new dock, a new BECFigure and a BECWaveForm to the dock
27
- plt = gui.add_dock().add_widget('BECFigure').plot('samx', 'bpm4i')
27
+ plt = gui.add_dock().add_widget('BECFigure').plot(x_name='samx', y_name='bpm4i')
28
28
  # add a second curve to the same plot
29
29
  plt.plot(x_name='samx', y_name='bpm3i')
30
30
  plt.set_title("Gauss plots vs. samx")
@@ -39,6 +39,48 @@ dev.bpm4i.sim.select_sim_model("GaussianModel")
39
39
  dev.bpm3i.sim.select_sim_model("StepModel")
40
40
  ```
41
41
 
42
+ **Code example 2 - Adding Data Processing Pipeline Curve with LMFit Models**
43
+
44
+ Together with the scan curve, one can also add a second curve that fits the signal using a specified model
45
+ from [LMFit](https://lmfit.github.io/lmfit-py/builtin_models.html). The following code snippet demonstrates how to
46
+ create a 1D waveform curve with an attached DAP process, or how to add a DAP process to an existing curve using the BEC
47
+ CLI. Please note that for this example, both devices were set as Gaussian signals.
48
+
49
+ ```python
50
+ # Add a new dock, a new BECFigure, and a BECWaveForm to the dock with a GaussianModel DAP
51
+ plt = gui.add_dock().add_widget('BECFigure').plot(x_name='samx', y_name='bpm4i', dap="GaussianModel")
52
+
53
+ # Add a second curve to the same plot without DAP
54
+ plt.plot(x_name='samx', y_name='bpm3a')
55
+
56
+ # Add DAP to the second curve
57
+ plt.add_dap(x_name='samx', y_name='bpm3a', dap="GaussianModel")
58
+
59
+ ```
60
+
61
+ To get the parameters of the fit, one has to retrieve the curve objects and call the dap_params property.
62
+
63
+ ```python
64
+ # Get the curve object by name from the legend
65
+ dap_bpm4i = plt.get_curve("bpm4i-bpm4i-GaussianModel")
66
+ dap_bpm3a = plt.get_curve("bpm3a-bpm3a-GaussianModel")
67
+
68
+ # Get the parameters of the fit
69
+ print(dap_bpm4i.dap_params)
70
+ # Output
71
+ {'amplitude': 197.399639720862,
72
+ 'center': 5.013486095404885,
73
+ 'sigma': 0.9820868875739888}
74
+
75
+ print(dap_bpm3a.dap_params)
76
+ # Output
77
+ {'amplitude': 698.3072786185278,
78
+ 'center': 0.9702840866173836,
79
+ 'sigma': 1.97139754785518}
80
+ ```
81
+
82
+ ![Waveform 1D_DAP](./bec_figure_dap.gif)
83
+
42
84
  (user.widgets.scatter_2d)=
43
85
  ## [2D Scatter Plot](/api_reference/_autosummary/bec_widgets.cli.client.BECWaveform)
44
86
 
Binary file
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "0.73.2"
7
+ version = "0.74.0"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -53,6 +53,7 @@ def test_rpc_add_dock_with_figure_e2e(bec_client_lib, rpc_server_dock):
53
53
  assert im.__class__ == BECImageShow
54
54
 
55
55
  assert mm.config_dict["signals"] == {
56
+ "dap": None,
56
57
  "source": "device_readback",
57
58
  "x": {
58
59
  "name": "samx",
@@ -71,6 +72,7 @@ def test_rpc_add_dock_with_figure_e2e(bec_client_lib, rpc_server_dock):
71
72
  "z": None,
72
73
  }
73
74
  assert plt.config_dict["curves"]["bpm4i-bpm4i"]["signals"] == {
75
+ "dap": None,
74
76
  "source": "scan_segment",
75
77
  "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
76
78
  "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None, "limits": None},
@@ -1,3 +1,5 @@
1
+ import time
2
+
1
3
  import numpy as np
2
4
  import pytest
3
5
  from bec_lib.endpoints import MessageEndpoints
@@ -38,6 +40,7 @@ def test_rpc_plotting_shortcuts_init_configs(rpc_server_figure, qtbot):
38
40
  # check if the correct devices are set
39
41
  # plot
40
42
  assert plt.config_dict["curves"]["bpm4i-bpm4i"]["signals"] == {
43
+ "dap": None,
41
44
  "source": "scan_segment",
42
45
  "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
43
46
  "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None, "limits": None},
@@ -47,6 +50,7 @@ def test_rpc_plotting_shortcuts_init_configs(rpc_server_figure, qtbot):
47
50
  assert im.config_dict["images"]["eiger"]["monitor"] == "eiger"
48
51
  # motor map
49
52
  assert motor_map.config_dict["signals"] == {
53
+ "dap": None,
50
54
  "source": "device_readback",
51
55
  "x": {
52
56
  "name": "samx",
@@ -66,6 +70,7 @@ def test_rpc_plotting_shortcuts_init_configs(rpc_server_figure, qtbot):
66
70
  }
67
71
  # plot with z scatter
68
72
  assert plt_z.config_dict["curves"]["bpm4i-bpm4i"]["signals"] == {
73
+ "dap": None,
69
74
  "source": "scan_segment",
70
75
  "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
71
76
  "y": {"name": "samy", "entry": "samy", "unit": None, "modifier": None, "limits": None},
@@ -151,3 +156,32 @@ def test_rpc_motor_map(rpc_server_figure, bec_client_lib):
151
156
  np.testing.assert_equal(
152
157
  [motor_map_data["x"][-1], motor_map_data["y"][-1]], [final_pos_x, final_pos_y]
153
158
  )
159
+
160
+
161
+ def test_dap_rpc(rpc_server_figure, bec_client_lib):
162
+
163
+ fig = BECFigure(rpc_server_figure)
164
+ plt = fig.plot(x_name="samx", y_name="bpm4i", dap="GaussianModel")
165
+
166
+ client = bec_client_lib
167
+ dev = client.device_manager.devices
168
+ scans = client.scans
169
+
170
+ dev.bpm4i.sim.sim_select_model("GaussianModel")
171
+ params = dev.bpm4i.sim.sim_params
172
+ params.update(
173
+ {"noise": "uniform", "noise_multiplier": 10, "center": 5, "sigma": 1, "amplitude": 200}
174
+ )
175
+ dev.bpm4i.sim.sim_params = params
176
+ time.sleep(1)
177
+
178
+ res = scans.line_scan(dev.samx, 0, 8, steps=50, relative=False)
179
+ res.wait()
180
+
181
+ time.sleep(2)
182
+
183
+ dap_curve = plt.get_curve("bpm4i-bpm4i-GaussianModel")
184
+ fit_params = dap_curve.dap_params
185
+ print(fit_params)
186
+
187
+ assert np.isclose(fit_params["center"], 5, atol=0.5)
@@ -85,6 +85,7 @@ def test_create_waveform1D_by_config(bec_figure):
85
85
  "pen_style": "dash",
86
86
  "source": "scan_segment",
87
87
  "signals": {
88
+ "dap": None,
88
89
  "source": "scan_segment",
89
90
  "x": {
90
91
  "name": "samx",
@@ -248,6 +249,7 @@ def test_change_curve_appearance_methods(bec_figure, qtbot):
248
249
  assert c1.config.pen_style == "dashdot"
249
250
  assert c1.config.source == "scan_segment"
250
251
  assert c1.config.signals.model_dump() == {
252
+ "dap": None,
251
253
  "source": "scan_segment",
252
254
  "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
253
255
  "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None, "limits": None},
@@ -277,6 +279,7 @@ def test_change_curve_appearance_args(bec_figure):
277
279
  assert c1.config.pen_style == "dashdot"
278
280
  assert c1.config.source == "scan_segment"
279
281
  assert c1.config.signals.model_dump() == {
282
+ "dap": None,
280
283
  "source": "scan_segment",
281
284
  "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
282
285
  "y": {"name": "bpm4i", "entry": "bpm4i", "unit": None, "modifier": None, "limits": None},
@@ -384,6 +387,7 @@ def test_curve_add_by_config(bec_figure):
384
387
  "pen_style": "dash",
385
388
  "source": "scan_segment",
386
389
  "signals": {
390
+ "dap": None,
387
391
  "source": "scan_segment",
388
392
  "x": {"name": "samx", "entry": "samx", "unit": None, "modifier": None, "limits": None},
389
393
  "y": {