bec-widgets 0.44.5__py3-none-any.whl → 0.46.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.
bec_widgets/cli/client.py CHANGED
@@ -142,9 +142,12 @@ class BECWaveform1D(RPCBase):
142
142
  self,
143
143
  x_name: "str",
144
144
  y_name: "str",
145
+ z_name: "Optional[str]" = None,
145
146
  x_entry: "Optional[str]" = None,
146
147
  y_entry: "Optional[str]" = None,
148
+ z_entry: "Optional[str]" = None,
147
149
  color: "Optional[str]" = None,
150
+ color_map_z: "Optional[str]" = "plasma",
148
151
  label: "Optional[str]" = None,
149
152
  validate_bec: "bool" = True,
150
153
  **kwargs
@@ -156,7 +159,10 @@ class BECWaveform1D(RPCBase):
156
159
  x_entry(str): Entry of the x signal.
157
160
  y_name(str): Name of the y signal.
158
161
  y_entry(str): Entry of the y signal.
162
+ z_name(str): Name of the z signal.
163
+ z_entry(str): Entry of the z signal.
159
164
  color(str, optional): Color of the curve. Defaults to None.
165
+ color_map_z(str): The color map to use for the z-axis.
160
166
  label(str, optional): Label of the curve. Defaults to None.
161
167
  **kwargs: Additional keyword arguments for the curve configuration.
162
168
 
@@ -404,11 +410,14 @@ class BECFigure(RPCBase, BECFigureClientMixin):
404
410
  self,
405
411
  x_name: "str" = None,
406
412
  y_name: "str" = None,
413
+ z_name: "str" = None,
407
414
  x_entry: "str" = None,
408
415
  y_entry: "str" = None,
416
+ z_entry: "str" = None,
409
417
  x: "list | np.ndarray" = None,
410
418
  y: "list | np.ndarray" = None,
411
419
  color: "Optional[str]" = None,
420
+ color_map_z: "Optional[str]" = "plasma",
412
421
  label: "Optional[str]" = None,
413
422
  validate: "bool" = True,
414
423
  row: "int" = None,
@@ -450,22 +459,48 @@ class BECFigure(RPCBase, BECFigureClientMixin):
450
459
  row(int): The row coordinate of the widget in the figure. If not provided, the next empty row will be used.
451
460
  col(int): The column coordinate of the widget in the figure. If not provided, the next empty column will be used.
452
461
  config(dict): Additional configuration for the widget.
453
- **axis_kwargs:
462
+ **axis_kwargs: Additional axis properties to set on the widget after creation.
454
463
 
455
464
  Returns:
456
465
  BECImageShow: The image widget.
457
466
  """
458
467
 
468
+ @rpc_call
469
+ def add_motor_map(
470
+ self,
471
+ motor_x: "str" = None,
472
+ motor_y: "str" = None,
473
+ row: "int" = None,
474
+ col: "int" = None,
475
+ config=None,
476
+ **axis_kwargs
477
+ ) -> "BECMotorMap":
478
+ """
479
+ Args:
480
+ motor_x(str): The name of the motor for the X axis.
481
+ motor_y(str): The name of the motor for the Y axis.
482
+ row(int): The row coordinate of the widget in the figure. If not provided, the next empty row will be used.
483
+ col(int): The column coordinate of the widget in the figure. If not provided, the next empty column will be used.
484
+ config(dict): Additional configuration for the widget.
485
+ **axis_kwargs:
486
+
487
+ Returns:
488
+ BECMotorMap: The motor map widget.
489
+ """
490
+
459
491
  @rpc_call
460
492
  def plot(
461
493
  self,
462
494
  x_name: "str" = None,
463
495
  y_name: "str" = None,
496
+ z_name: "str" = None,
464
497
  x_entry: "str" = None,
465
498
  y_entry: "str" = None,
499
+ z_entry: "str" = None,
466
500
  x: "list | np.ndarray" = None,
467
501
  y: "list | np.ndarray" = None,
468
502
  color: "Optional[str]" = None,
503
+ color_map_z: "Optional[str]" = "plasma",
469
504
  label: "Optional[str]" = None,
470
505
  validate: "bool" = True,
471
506
  **axis_kwargs
@@ -475,11 +510,14 @@ class BECFigure(RPCBase, BECFigureClientMixin):
475
510
  Args:
476
511
  x_name(str): The name of the device for the x-axis.
477
512
  y_name(str): The name of the device for the y-axis.
513
+ z_name(str): The name of the device for the z-axis.
478
514
  x_entry(str): The name of the entry for the x-axis.
479
515
  y_entry(str): The name of the entry for the y-axis.
516
+ z_entry(str): The name of the entry for the z-axis.
480
517
  x(list | np.ndarray): Custom x data to plot.
481
518
  y(list | np.ndarray): Custom y data to plot.
482
519
  color(str): The color of the curve.
520
+ color_map_z(str): The color map to use for the z-axis.
483
521
  label(str): The label of the curve.
484
522
  validate(bool): If True, validate the device names and entries.
485
523
  **axis_kwargs: Additional axis properties to set on the widget after creation.
@@ -512,6 +550,21 @@ class BECFigure(RPCBase, BECFigureClientMixin):
512
550
  BECImageShow: The image widget.
513
551
  """
514
552
 
553
+ @rpc_call
554
+ def motor_map(
555
+ self, motor_x: "str" = None, motor_y: "str" = None, **axis_kwargs
556
+ ) -> "BECMotorMap":
557
+ """
558
+ Add a motor map to the figure. Always access the first motor map widget in the figure.
559
+ Args:
560
+ motor_x(str): The name of the motor for the X axis.
561
+ motor_y(str): The name of the motor for the Y axis.
562
+ **axis_kwargs: Additional axis properties to set on the widget after creation.
563
+
564
+ Returns:
565
+ BECMotorMap: The motor map widget.
566
+ """
567
+
515
568
  @rpc_call
516
569
  def remove(
517
570
  self,
@@ -596,6 +649,14 @@ class BECCurve(RPCBase):
596
649
  symbol_color(str, optional): Color of the symbol. Defaults to None.
597
650
  """
598
651
 
652
+ @rpc_call
653
+ def set_colormap(self, colormap: "str"):
654
+ """
655
+ Set the colormap for the scatter plot z gradient.
656
+ Args:
657
+ colormap(str): Colormap for the scatter plot.
658
+ """
659
+
599
660
  @rpc_call
600
661
  def set_symbol(self, symbol: "str"):
601
662
  """
@@ -1091,3 +1152,64 @@ class BECImageItem(RPCBase):
1091
1152
  Returns:
1092
1153
  dict: The configuration of the plot widget.
1093
1154
  """
1155
+
1156
+
1157
+ class BECMotorMap(RPCBase):
1158
+ @rpc_call
1159
+ def change_motors(
1160
+ self,
1161
+ motor_x: "str",
1162
+ motor_y: "str",
1163
+ motor_x_entry: "str" = None,
1164
+ motor_y_entry: "str" = None,
1165
+ validate_bec: "bool" = True,
1166
+ ) -> "None":
1167
+ """
1168
+ Change the active motors for the plot.
1169
+ Args:
1170
+ motor_x(str): Motor name for the X axis.
1171
+ motor_y(str): Motor name for the Y axis.
1172
+ motor_x_entry(str): Motor entry for the X axis.
1173
+ motor_y_entry(str): Motor entry for the Y axis.
1174
+ validate_bec(bool, optional): If True, validate the signal with BEC. Defaults to True.
1175
+ """
1176
+
1177
+ @rpc_call
1178
+ def set_max_points(self, max_points: "int") -> "None":
1179
+ """
1180
+ Set the maximum number of points to display.
1181
+ Args:
1182
+ max_points(int): Maximum number of points to display.
1183
+ """
1184
+
1185
+ @rpc_call
1186
+ def set_precision(self, precision: "int") -> "None":
1187
+ """
1188
+ Set the decimal precision of the motor position.
1189
+ Args:
1190
+ precision(int): Decimal precision of the motor position.
1191
+ """
1192
+
1193
+ @rpc_call
1194
+ def set_num_dim_points(self, num_dim_points: "int") -> "None":
1195
+ """
1196
+ Set the number of dim points for the motor map.
1197
+ Args:
1198
+ num_dim_points(int): Number of dim points.
1199
+ """
1200
+
1201
+ @rpc_call
1202
+ def set_background_value(self, background_value: "int") -> "None":
1203
+ """
1204
+ Set the background value of the motor map.
1205
+ Args:
1206
+ background_value(int): Background value of the motor map.
1207
+ """
1208
+
1209
+ @rpc_call
1210
+ def set_scatter_size(self, scatter_size: "int") -> "None":
1211
+ """
1212
+ Set the scatter size of the motor map plot.
1213
+ Args:
1214
+ scatter_size(int): Size of the scatter points.
1215
+ """
@@ -109,20 +109,21 @@ if __name__ == "__main__": # pragma: no cover
109
109
 
110
110
  from bec_widgets.utils import BECConnector
111
111
  from bec_widgets.widgets.figure import BECFigure
112
- from bec_widgets.widgets.plots import BECImageShow, BECPlotBase, BECWaveform1D
112
+ from bec_widgets.widgets.plots import BECImageShow, BECMotorMap, BECPlotBase, BECWaveform
113
113
  from bec_widgets.widgets.plots.image import BECImageItem
114
- from bec_widgets.widgets.plots.waveform1d import BECCurve
114
+ from bec_widgets.widgets.plots.waveform import BECCurve
115
115
 
116
116
  current_path = os.path.dirname(__file__)
117
117
  client_path = os.path.join(current_path, "client.py")
118
118
  clss = [
119
119
  BECPlotBase,
120
- BECWaveform1D,
120
+ BECWaveform,
121
121
  BECFigure,
122
122
  BECCurve,
123
123
  BECImageShow,
124
124
  BECConnector,
125
125
  BECImageItem,
126
+ BECMotorMap,
126
127
  ]
127
128
  generator = ClientGenerator()
128
129
  generator.generate_client(clss)
bec_widgets/cli/server.py CHANGED
@@ -6,11 +6,11 @@ from qtpy.QtCore import QTimer
6
6
  from bec_widgets.utils import BECDispatcher
7
7
  from bec_widgets.utils.bec_connector import BECConnector
8
8
  from bec_widgets.widgets.figure import BECFigure
9
- from bec_widgets.widgets.plots import BECCurve, BECImageShow, BECWaveform1D
9
+ from bec_widgets.widgets.plots import BECCurve, BECImageShow, BECWaveform
10
10
 
11
11
 
12
12
  class BECWidgetsCLIServer:
13
- WIDGETS = [BECWaveform1D, BECFigure, BECCurve, BECImageShow]
13
+ WIDGETS = [BECWaveform, BECFigure, BECCurve, BECImageShow]
14
14
 
15
15
  def __init__(self, gui_id: str = None, dispatcher: BECDispatcher = None) -> None:
16
16
  self.dispatcher = BECDispatcher() if dispatcher is None else dispatcher
@@ -1,7 +1,6 @@
1
1
  from .editor import BECEditor
2
2
  from .figure import BECFigure, FigureConfig
3
3
  from .monitor import BECMonitor
4
- from .monitor_scatter_2D import BECMonitor2DScatter
5
4
  from .motor_control import (
6
5
  MotorControlAbsolute,
7
6
  MotorControlRelative,
@@ -10,5 +9,5 @@ from .motor_control import (
10
9
  MotorThread,
11
10
  )
12
11
  from .motor_map import MotorMap
13
- from .plots import BECCurve, BECPlotBase, BECWaveform1D
12
+ from .plots import BECCurve, BECMotorMap, BECWaveform
14
13
  from .scan_control import ScanControl
@@ -17,12 +17,14 @@ from qtpy.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
17
17
  from bec_widgets.utils import BECConnector, BECDispatcher, ConnectionConfig
18
18
  from bec_widgets.widgets.plots import (
19
19
  BECImageShow,
20
+ BECMotorMap,
20
21
  BECPlotBase,
21
- BECWaveform1D,
22
+ BECWaveform,
22
23
  Waveform1DConfig,
23
24
  WidgetConfig,
24
25
  )
25
26
  from bec_widgets.widgets.plots.image import ImageConfig
27
+ from bec_widgets.widgets.plots.motor_map import MotorMapConfig
26
28
 
27
29
 
28
30
  class FigureConfig(ConnectionConfig):
@@ -42,8 +44,9 @@ class WidgetHandler:
42
44
  def __init__(self):
43
45
  self.widget_factory = {
44
46
  "PlotBase": (BECPlotBase, WidgetConfig),
45
- "Waveform1D": (BECWaveform1D, Waveform1DConfig),
47
+ "Waveform1D": (BECWaveform, Waveform1DConfig),
46
48
  "ImShow": (BECImageShow, ImageConfig),
49
+ "MotorMap": (BECMotorMap, MotorMapConfig),
47
50
  }
48
51
 
49
52
  def create_widget(
@@ -98,8 +101,10 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
98
101
  "widgets",
99
102
  "add_plot",
100
103
  "add_image",
104
+ "add_motor_map",
101
105
  "plot",
102
106
  "image",
107
+ "motor_map",
103
108
  "remove",
104
109
  "change_layout",
105
110
  "change_theme",
@@ -159,18 +164,21 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
159
164
  self,
160
165
  x_name: str = None,
161
166
  y_name: str = None,
167
+ z_name: str = None,
162
168
  x_entry: str = None,
163
169
  y_entry: str = None,
170
+ z_entry: str = None,
164
171
  x: list | np.ndarray = None,
165
172
  y: list | np.ndarray = None,
166
173
  color: Optional[str] = None,
174
+ color_map_z: Optional[str] = "plasma",
167
175
  label: Optional[str] = None,
168
176
  validate: bool = True,
169
177
  row: int = None,
170
178
  col: int = None,
171
179
  config=None,
172
180
  **axis_kwargs,
173
- ) -> BECWaveform1D:
181
+ ) -> BECWaveform:
174
182
  """
175
183
  Add a Waveform1D plot to the figure at the specified position.
176
184
  Args:
@@ -192,8 +200,8 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
192
200
 
193
201
  # TODO remove repetition from .plot method
194
202
 
195
- # User wants to add scan curve
196
- if x_name is not None and y_name is not None and x is None and y is None:
203
+ # User wants to add scan curve -> 1D Waveform
204
+ 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:
197
205
  waveform.add_curve_scan(
198
206
  x_name=x_name,
199
207
  y_name=y_name,
@@ -203,7 +211,27 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
203
211
  color=color,
204
212
  label=label,
205
213
  )
206
- # User wants to add custom curve
214
+ # User wants to add scan curve -> 2D Waveform Scatter
215
+ if (
216
+ x_name is not None
217
+ and y_name is not None
218
+ and z_name is not None
219
+ and x is None
220
+ and y is None
221
+ ):
222
+ waveform.add_curve_scan(
223
+ x_name=x_name,
224
+ y_name=y_name,
225
+ z_name=z_name,
226
+ x_entry=x_entry,
227
+ y_entry=y_entry,
228
+ z_entry=z_entry,
229
+ color=color,
230
+ color_map=color_map_z,
231
+ label=label,
232
+ validate=validate,
233
+ )
234
+ # User wants to add custom curve
207
235
  elif x is not None and y is not None and x_name is None and y_name is None:
208
236
  waveform.add_curve_custom(
209
237
  x=x,
@@ -218,52 +246,81 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
218
246
  self,
219
247
  x_name: str = None,
220
248
  y_name: str = None,
249
+ z_name: str = None,
221
250
  x_entry: str = None,
222
251
  y_entry: str = None,
252
+ z_entry: str = None,
223
253
  x: list | np.ndarray = None,
224
254
  y: list | np.ndarray = None,
225
255
  color: Optional[str] = None,
256
+ color_map_z: Optional[str] = "plasma",
226
257
  label: Optional[str] = None,
227
258
  validate: bool = True,
228
259
  **axis_kwargs,
229
- ) -> BECWaveform1D:
260
+ ) -> BECWaveform:
230
261
  """
231
262
  Add a 1D waveform plot to the figure. Always access the first waveform widget in the figure.
232
263
  Args:
233
264
  x_name(str): The name of the device for the x-axis.
234
265
  y_name(str): The name of the device for the y-axis.
266
+ z_name(str): The name of the device for the z-axis.
235
267
  x_entry(str): The name of the entry for the x-axis.
236
268
  y_entry(str): The name of the entry for the y-axis.
269
+ z_entry(str): The name of the entry for the z-axis.
237
270
  x(list | np.ndarray): Custom x data to plot.
238
271
  y(list | np.ndarray): Custom y data to plot.
239
272
  color(str): The color of the curve.
273
+ color_map_z(str): The color map to use for the z-axis.
240
274
  label(str): The label of the curve.
241
275
  validate(bool): If True, validate the device names and entries.
242
276
  **axis_kwargs: Additional axis properties to set on the widget after creation.
243
277
 
244
278
  Returns:
245
- BECWaveform1D: The waveform plot widget.
279
+ BECWaveform: The waveform plot widget.
246
280
  """
247
- waveform = self._find_first_widget_by_class(BECWaveform1D, can_fail=True)
281
+ waveform = self._find_first_widget_by_class(BECWaveform, can_fail=True)
248
282
  if waveform is not None:
249
283
  if axis_kwargs:
250
284
  waveform.set(**axis_kwargs)
251
285
  else:
252
286
  waveform = self.add_plot(**axis_kwargs)
253
287
 
254
- # User wants to add scan curve
255
- if x_name is not None and y_name is not None and x is None and y is None:
288
+ # User wants to add scan curve -> 1D Waveform
289
+ 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:
256
290
  waveform.add_curve_scan(
257
291
  x_name=x_name,
258
292
  y_name=y_name,
259
293
  x_entry=x_entry,
260
294
  y_entry=y_entry,
295
+ color=color,
296
+ color_map_z="plasma",
297
+ label=label,
261
298
  validate=validate,
299
+ )
300
+ # User wants to add scan curve -> 2D Waveform Scatter
301
+ elif (
302
+ x_name is not None
303
+ and y_name is not None
304
+ and z_name is not None
305
+ and x is None
306
+ and y is None
307
+ ):
308
+ waveform.add_curve_scan(
309
+ x_name=x_name,
310
+ y_name=y_name,
311
+ z_name=z_name,
312
+ x_entry=x_entry,
313
+ y_entry=y_entry,
314
+ z_entry=z_entry,
262
315
  color=color,
316
+ color_map=color_map_z,
263
317
  label=label,
318
+ validate=validate,
264
319
  )
265
320
  # User wants to add custom curve
266
- elif x is not None and y is not None and x_name is None and y_name is None:
321
+ elif (
322
+ x is not None and y is not None and x_name is None and y_name is None and z_name is None
323
+ ):
267
324
  waveform.add_curve_custom(
268
325
  x=x,
269
326
  y=y,
@@ -347,7 +404,7 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
347
404
  row(int): The row coordinate of the widget in the figure. If not provided, the next empty row will be used.
348
405
  col(int): The column coordinate of the widget in the figure. If not provided, the next empty column will be used.
349
406
  config(dict): Additional configuration for the widget.
350
- **axis_kwargs:
407
+ **axis_kwargs: Additional axis properties to set on the widget after creation.
351
408
 
352
409
  Returns:
353
410
  BECImageShow: The image widget.
@@ -389,6 +446,72 @@ class BECFigure(BECConnector, pg.GraphicsLayoutWidget):
389
446
 
390
447
  return image
391
448
 
449
+ def motor_map(self, motor_x: str = None, motor_y: str = None, **axis_kwargs) -> BECMotorMap:
450
+ """
451
+ Add a motor map to the figure. Always access the first motor map widget in the figure.
452
+ Args:
453
+ motor_x(str): The name of the motor for the X axis.
454
+ motor_y(str): The name of the motor for the Y axis.
455
+ **axis_kwargs: Additional axis properties to set on the widget after creation.
456
+
457
+ Returns:
458
+ BECMotorMap: The motor map widget.
459
+ """
460
+ motor_map = self._find_first_widget_by_class(BECMotorMap, can_fail=True)
461
+ if motor_map is not None:
462
+ if axis_kwargs:
463
+ motor_map.set(**axis_kwargs)
464
+ else:
465
+ motor_map = self.add_motor_map(**axis_kwargs)
466
+
467
+ if motor_x is not None and motor_y is not None:
468
+ motor_map.change_motors(motor_x, motor_y)
469
+
470
+ return motor_map
471
+
472
+ def add_motor_map(
473
+ self,
474
+ motor_x: str = None,
475
+ motor_y: str = None,
476
+ row: int = None,
477
+ col: int = None,
478
+ config=None,
479
+ **axis_kwargs,
480
+ ) -> BECMotorMap:
481
+ """
482
+
483
+ Args:
484
+ motor_x(str): The name of the motor for the X axis.
485
+ motor_y(str): The name of the motor for the Y axis.
486
+ row(int): The row coordinate of the widget in the figure. If not provided, the next empty row will be used.
487
+ col(int): The column coordinate of the widget in the figure. If not provided, the next empty column will be used.
488
+ config(dict): Additional configuration for the widget.
489
+ **axis_kwargs:
490
+
491
+ Returns:
492
+ BECMotorMap: The motor map widget.
493
+ """
494
+ widget_id = self._generate_unique_widget_id()
495
+ if config is None:
496
+ config = MotorMapConfig(
497
+ widget_class="BECMotorMap",
498
+ gui_id=widget_id,
499
+ parent_id=self.gui_id,
500
+ )
501
+ motor_map = self.add_widget(
502
+ widget_type="MotorMap",
503
+ widget_id=widget_id,
504
+ row=row,
505
+ col=col,
506
+ config=config,
507
+ **axis_kwargs,
508
+ )
509
+
510
+ if motor_x is not None and motor_y is not None:
511
+ motor_map.change_motors(motor_x, motor_y)
512
+
513
+ return motor_map
514
+
392
515
  def add_widget(
393
516
  self,
394
517
  widget_type: Literal["PlotBase", "Waveform1D", "ImShow"] = "PlotBase",
@@ -746,7 +869,8 @@ class DebugWindow(QWidget): # pragma: no cover:
746
869
  self.console.set_default_style("linux")
747
870
 
748
871
  def _init_figure(self):
749
- self.figure.add_widget(widget_type="Waveform1D", row=0, col=0, title="Widget 1")
872
+ # self.figure.add_widget(widget_type="Waveform1D", row=0, col=0, title="Widget 1")
873
+ self.figure.plot("samx", "bpm4d")
750
874
  self.figure.add_widget(widget_type="Waveform1D", row=0, col=1, title="Widget 2")
751
875
  self.figure.add_image(
752
876
  title="Image", row=1, col=0, color_map="viridis", color_bar="simple", vrange=(0, 100)
@@ -759,14 +883,16 @@ class DebugWindow(QWidget): # pragma: no cover:
759
883
  self.w4 = self.figure[1, 1]
760
884
 
761
885
  # curves for w1
762
- self.w1.add_curve_scan("samx", "bpm4i", pen_style="dash")
763
- self.w1.add_curve_custom(
764
- x=[1, 2, 3, 4, 5],
765
- y=[1, 2, 3, 4, 5],
766
- label="curve-custom",
767
- color="blue",
768
- pen_style="dashdot",
769
- )
886
+ self.w1.add_curve_scan("samx", "samy", "bpm4i", pen_style="dash")
887
+ self.w1.add_curve_scan("samx", "samy", "bpm3a", pen_style="dash")
888
+
889
+ # self.w1.add_curve_custom(
890
+ # x=[1, 2, 3, 4, 5],
891
+ # y=[1, 2, 3, 4, 5],
892
+ # label="curve-custom",
893
+ # color="blue",
894
+ # pen_style="dashdot",
895
+ # )
770
896
  self.c1 = self.w1.get_config()
771
897
 
772
898
  # curves for w2
@@ -1,3 +1,4 @@
1
1
  from .image import BECImageItem, BECImageShow, ImageItemConfig
2
+ from .motor_map import BECMotorMap, MotorMapConfig
2
3
  from .plot_base import AxisConfig, BECPlotBase, WidgetConfig
3
- from .waveform1d import BECCurve, BECWaveform1D, Waveform1DConfig
4
+ from .waveform import BECCurve, BECWaveform, Waveform1DConfig