pymodaq 3.6.12__py3-none-any.whl → 4.0.1__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.
Potentially problematic release.
This version of pymodaq might be problematic. Click here for more details.
- pymodaq/__init__.py +13 -6
- pymodaq/control_modules/__init__.py +0 -7
- pymodaq/control_modules/daq_move.py +965 -2
- pymodaq/control_modules/daq_move_ui.py +319 -0
- pymodaq/control_modules/daq_viewer.py +1573 -3
- pymodaq/control_modules/daq_viewer_ui.py +393 -0
- pymodaq/control_modules/mocks.py +51 -0
- pymodaq/control_modules/move_utility_classes.py +709 -8
- pymodaq/control_modules/utils.py +256 -0
- pymodaq/control_modules/viewer_utility_classes.py +663 -6
- pymodaq/daq_utils.py +89 -0
- pymodaq/dashboard.py +91 -72
- pymodaq/examples/custom_app.py +12 -11
- pymodaq/examples/custom_viewer.py +10 -10
- pymodaq/examples/function_plotter.py +16 -13
- pymodaq/examples/nonlinearscanner.py +8 -6
- pymodaq/examples/parameter_ex.py +7 -7
- pymodaq/examples/preset_MockCamera.xml +1 -0
- pymodaq/extensions/__init__.py +16 -0
- pymodaq/extensions/console.py +76 -0
- pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
- pymodaq/extensions/daq_scan.py +1339 -0
- pymodaq/extensions/daq_scan_ui.py +240 -0
- pymodaq/extensions/h5browser.py +23 -0
- pymodaq/{pid → extensions/pid}/__init__.py +4 -2
- pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
- pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
- pymodaq/{pid → extensions/pid}/utils.py +52 -6
- pymodaq/extensions/utils.py +40 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
- pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
- pymodaq/post_treatment/load_and_plot.py +219 -0
- pymodaq/post_treatment/process_to_scalar.py +263 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
- pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +32 -13
- pymodaq/resources/preset_default.xml +1 -1
- pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
- pymodaq/utils/__init__.py +0 -29
- pymodaq/utils/abstract/__init__.py +48 -0
- pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
- pymodaq/utils/array_manipulation.py +379 -8
- pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
- pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
- pymodaq/utils/config.py +448 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +828 -8
- pymodaq/utils/data.py +1873 -7
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
- pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
- pymodaq/{daq_utils → utils}/enums.py +12 -7
- pymodaq/utils/exceptions.py +37 -0
- pymodaq/utils/factory.py +82 -0
- pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
- pymodaq/utils/gui_utils/custom_app.py +129 -0
- pymodaq/utils/gui_utils/file_io.py +66 -0
- pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
- pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
- pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
- pymodaq/utils/gui_utils/widgets/label.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
- pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
- pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
- pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
- pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
- pymodaq/utils/h5modules/__init__.py +1 -0
- pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
- pymodaq/utils/h5modules/browsing.py +683 -0
- pymodaq/utils/h5modules/data_saving.py +839 -0
- pymodaq/utils/h5modules/h5logging.py +110 -0
- pymodaq/utils/h5modules/module_saving.py +350 -0
- pymodaq/utils/h5modules/saving.py +914 -0
- pymodaq/utils/h5modules/utils.py +85 -0
- pymodaq/utils/logger.py +64 -6
- pymodaq/utils/managers/action_manager.py +460 -0
- pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
- pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
- pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
- pymodaq/utils/managers/parameter_manager.py +110 -0
- pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
- pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
- pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
- pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
- pymodaq/utils/math_utils.py +546 -10
- pymodaq/{daq_utils → utils}/messenger.py +5 -1
- pymodaq/utils/parameter/__init__.py +2 -15
- pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
- pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
- pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
- pymodaq/utils/parameter/utils.py +206 -11
- pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
- pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
- pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
- pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
- pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
- pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
- pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
- pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
- pymodaq/utils/plotting/navigator.py +355 -0
- pymodaq/utils/plotting/scan_selector.py +480 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
- pymodaq/utils/plotting/utils/filter.py +538 -0
- pymodaq/utils/plotting/utils/lineout.py +224 -0
- pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
- pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
- pymodaq/utils/plotting/widgets.py +76 -0
- pymodaq/utils/scanner/__init__.py +10 -0
- pymodaq/utils/scanner/scan_factory.py +204 -0
- pymodaq/utils/scanner/scanner.py +271 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
- pymodaq/utils/scanner/scanners/sequential.py +192 -0
- pymodaq/utils/scanner/scanners/tabular.py +294 -0
- pymodaq/utils/scanner/utils.py +83 -0
- pymodaq/utils/slicing.py +47 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +51 -0
- pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
- pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
- pymodaq/utils/units.py +216 -0
- pymodaq-4.0.1.dist-info/METADATA +159 -0
- {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
- {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
- pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
- pymodaq/daq_move/daq_move_gui.py +0 -279
- pymodaq/daq_move/daq_move_gui.ui +0 -534
- pymodaq/daq_move/daq_move_main.py +0 -1042
- pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
- pymodaq/daq_move/utility_classes.py +0 -671
- pymodaq/daq_scan.py +0 -2160
- pymodaq/daq_utils/array_manipulation.py +0 -386
- pymodaq/daq_utils/config.py +0 -273
- pymodaq/daq_utils/conftests.py +0 -7
- pymodaq/daq_utils/custom_parameter_tree.py +0 -9
- pymodaq/daq_utils/daq_enums.py +0 -133
- pymodaq/daq_utils/daq_utils.py +0 -1402
- pymodaq/daq_utils/exceptions.py +0 -71
- pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
- pymodaq/daq_utils/gui_utils/file_io.py +0 -75
- pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
- pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
- pymodaq/daq_utils/h5exporters.py +0 -242
- pymodaq/daq_utils/h5modules.py +0 -1559
- pymodaq/daq_utils/h5utils.py +0 -241
- pymodaq/daq_utils/managers/action_manager.py +0 -236
- pymodaq/daq_utils/managers/parameter_manager.py +0 -57
- pymodaq/daq_utils/math_utils.py +0 -705
- pymodaq/daq_utils/parameter/__init__.py +0 -1
- pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
- pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
- pymodaq/daq_utils/parameter/utils.py +0 -136
- pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
- pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
- pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
- pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
- pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
- pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
- pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
- pymodaq/daq_utils/plotting/items/__init__.py +0 -0
- pymodaq/daq_utils/plotting/navigator.py +0 -500
- pymodaq/daq_utils/plotting/scan_selector.py +0 -289
- pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
- pymodaq/daq_utils/plotting/utils/filter.py +0 -236
- pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
- pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
- pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
- pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
- pymodaq/daq_utils/scanner.py +0 -1289
- pymodaq/daq_utils/tree_layout/__init__.py +0 -0
- pymodaq/daq_viewer/__init__.py +0 -0
- pymodaq/daq_viewer/daq_gui_settings.py +0 -237
- pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
- pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
- pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
- pymodaq/daq_viewer/utility_classes.py +0 -673
- pymodaq/examples/logger_image/__init__.py +0 -0
- pymodaq/examples/logger_image/logger_displayer.py +0 -121
- pymodaq/examples/logger_image/setup.svg +0 -3119
- pymodaq/examples/logger_image/setup_svg.py +0 -114
- pymodaq/h5browser.py +0 -39
- pymodaq/utils/scanner.py +0 -15
- pymodaq-3.6.12.dist-info/METADATA +0 -39
- pymodaq-3.6.12.dist-info/entry_points.txt +0 -8
- pymodaq-3.6.12.dist-info/top_level.txt +0 -1
- /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
- /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
- /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
- /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
- /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
- /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
- /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
- /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
- /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
- /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
- /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
- /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
- /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
- {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
from typing import List, Union, TYPE_CHECKING, Iterable
|
|
2
|
+
|
|
3
|
+
from qtpy import QtWidgets
|
|
4
|
+
from qtpy.QtCore import QObject, Signal, Slot
|
|
5
|
+
|
|
6
|
+
from pyqtgraph.graphicsItems import InfiniteLine, ROI
|
|
7
|
+
|
|
8
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
9
|
+
from pymodaq.utils.data import DataToExport, DataRaw, DataWithAxes
|
|
10
|
+
from pymodaq.utils.exceptions import ViewerError
|
|
11
|
+
from pymodaq.utils.enums import BaseEnum, enum_checker
|
|
12
|
+
from pymodaq.utils.factory import ObjectFactory, BuilderBase
|
|
13
|
+
from pymodaq.utils.plotting import data_viewers
|
|
14
|
+
from pymodaq.utils.gui_utils import DockArea, Dock
|
|
15
|
+
from pymodaq.utils.managers.parameter_manager import ParameterManager
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from pymodaq.utils.plotting.data_viewers.viewer0D import Viewer0D
|
|
19
|
+
from pymodaq.utils.plotting.data_viewers.viewer1D import Viewer1D
|
|
20
|
+
from pymodaq.utils.plotting.data_viewers.viewer2D import Viewer2D
|
|
21
|
+
from pymodaq.utils.plotting.data_viewers.viewerND import ViewerND
|
|
22
|
+
|
|
23
|
+
config_viewers = {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
logger = set_logger(get_module_name(__file__))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ViewersEnum(BaseEnum):
|
|
30
|
+
"""enum relating a given viewer with data type"""
|
|
31
|
+
Viewer0D = 'Data0D'
|
|
32
|
+
Viewer1D = 'Data1D'
|
|
33
|
+
Viewer2D = 'Data2D'
|
|
34
|
+
ViewerND = 'DataND'
|
|
35
|
+
ViewerSequential = 'DataSequential'
|
|
36
|
+
|
|
37
|
+
def get_dim(self):
|
|
38
|
+
return self.value.split('Data')[1].split('D')[0]
|
|
39
|
+
|
|
40
|
+
def increase_dim(self, ndim: int):
|
|
41
|
+
dim = self.get_dim()
|
|
42
|
+
if dim != 'N':
|
|
43
|
+
dim_as_int = int(dim) + ndim
|
|
44
|
+
if dim_as_int > 2:
|
|
45
|
+
dim = 'N'
|
|
46
|
+
else:
|
|
47
|
+
dim = str(dim_as_int)
|
|
48
|
+
else:
|
|
49
|
+
dim = 'N'
|
|
50
|
+
return ViewersEnum[f'Viewer{dim}D']
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_viewer_enum_from_axes(Naxes: int):
|
|
54
|
+
if Naxes < 0:
|
|
55
|
+
raise ValueError('Naxes could not be below 0')
|
|
56
|
+
if Naxes == 0:
|
|
57
|
+
viewer_enum = ViewersEnum['Viewer0D']
|
|
58
|
+
elif Naxes == 1:
|
|
59
|
+
viewer_enum = ViewersEnum['Viewer1D']
|
|
60
|
+
elif Naxes == 2:
|
|
61
|
+
viewer_enum = ViewersEnum['Viewer2D']
|
|
62
|
+
else:
|
|
63
|
+
viewer_enum = ViewersEnum['ViewerND']
|
|
64
|
+
return viewer_enum
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ViewerFactory(ObjectFactory):
|
|
68
|
+
def get(self, viewer_name, **kwargs):
|
|
69
|
+
if viewer_name not in ViewersEnum.names():
|
|
70
|
+
raise ValueError(f'{viewer_name} is not a valid PyMoDAQ Viewer: {ViewersEnum.names()}')
|
|
71
|
+
return self.create(viewer_name, **kwargs)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def viewers(self):
|
|
75
|
+
return self.keys
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@ViewerFactory.register('Viewer0D')
|
|
79
|
+
def create_viewer0D(parent: QtWidgets.QWidget = None, **_ignored):
|
|
80
|
+
return data_viewers.viewer0D.Viewer0D(parent)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@ViewerFactory.register('Viewer1D')
|
|
84
|
+
def create_viewer1D(parent: QtWidgets.QWidget, **_ignored):
|
|
85
|
+
return data_viewers.viewer1D.Viewer1D(parent)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@ViewerFactory.register('Viewer2D')
|
|
89
|
+
def create_viewer2D(parent: QtWidgets.QWidget, **_ignored):
|
|
90
|
+
return data_viewers.viewer2D.Viewer2D(parent)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@ViewerFactory.register('ViewerND')
|
|
94
|
+
def create_viewerND(parent: QtWidgets.QWidget, **_ignored):
|
|
95
|
+
return data_viewers.viewerND.ViewerND(parent)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# @ViewerFactory.register('ViewerSequential')
|
|
99
|
+
# def create_viewer_sequential(widget: QtWidgets.QWidget, **_ignored):
|
|
100
|
+
# return data_viewers.viewer_sequential.ViewerSequential(widget)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
viewer_factory = ViewerFactory()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class ViewerDispatcher:
|
|
107
|
+
"""MixIn class to add easy control for adding multuiple data viewers in docks depending on data to be plotted"""
|
|
108
|
+
|
|
109
|
+
def __init__(self, dockarea: DockArea, title: str = '', next_to_dock: Dock = None):
|
|
110
|
+
super().__init__()
|
|
111
|
+
self._title = title
|
|
112
|
+
self._next_to_dock = next_to_dock
|
|
113
|
+
|
|
114
|
+
self.dockarea = dockarea
|
|
115
|
+
|
|
116
|
+
self._viewer_docks = []
|
|
117
|
+
self._viewer_widgets = []
|
|
118
|
+
self._viewer_types = []
|
|
119
|
+
self._viewers = []
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def viewers(self):
|
|
123
|
+
return self._viewers
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def viewer_docks(self):
|
|
127
|
+
return self._viewer_docks
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def viewer_widgets(self):
|
|
131
|
+
return self._viewer_widgets
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def viewer_types(self):
|
|
135
|
+
return self._viewer_types
|
|
136
|
+
|
|
137
|
+
def remove_viewers(self, Nviewers_to_leave: int = 0):
|
|
138
|
+
"""Remove viewers from the list after index Nviewers_to_leave
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
Nviewers
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
|
|
147
|
+
"""
|
|
148
|
+
while len(self.viewer_docks) > Nviewers_to_leave:
|
|
149
|
+
widget = self.viewer_widgets.pop()
|
|
150
|
+
widget.close()
|
|
151
|
+
dock = self.viewer_docks.pop()
|
|
152
|
+
dock.close()
|
|
153
|
+
self.viewers.pop()
|
|
154
|
+
self.viewer_types.pop()
|
|
155
|
+
QtWidgets.QApplication.processEvents()
|
|
156
|
+
|
|
157
|
+
def add_viewer(self, viewer_type: ViewersEnum, dock_viewer=None, dock_name=None):
|
|
158
|
+
viewer_type = enum_checker(ViewersEnum, viewer_type)
|
|
159
|
+
|
|
160
|
+
if dock_viewer is None:
|
|
161
|
+
if dock_name is None:
|
|
162
|
+
dock_name = f'{self._title}_Viewer_{len(self.viewer_docks) + 1}'
|
|
163
|
+
dock_viewer = Dock(dock_name, size=(350, 350), closable=False)
|
|
164
|
+
self.viewer_docks.append(dock_viewer)
|
|
165
|
+
|
|
166
|
+
self._viewer_widgets.append(QtWidgets.QWidget())
|
|
167
|
+
self.viewers.append(viewer_factory.get(viewer_type.name, parent=self._viewer_widgets[-1]))
|
|
168
|
+
|
|
169
|
+
self.viewer_types.append(viewer_type)
|
|
170
|
+
|
|
171
|
+
self.viewer_docks[-1].addWidget(self._viewer_widgets[-1])
|
|
172
|
+
# if len(self.viewer_docks) == 1:
|
|
173
|
+
# if self._next_to_dock is not None:
|
|
174
|
+
# self.dockarea.addDock(self.viewer_docks[-1], 'right', self._next_to_dock)
|
|
175
|
+
# else:
|
|
176
|
+
# self.dockarea.addDock(self.viewer_docks[-1])
|
|
177
|
+
# else:
|
|
178
|
+
# self.dockarea.addDock(self.viewer_docks[-1], 'right', self.viewer_docks[-2])
|
|
179
|
+
self.dockarea.addDock(self.viewer_docks[-1], 'right')
|
|
180
|
+
|
|
181
|
+
def update_viewers(self, viewers_type: List[ViewersEnum], viewers_name: List[str] = None, force=False):
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
Parameters
|
|
185
|
+
----------
|
|
186
|
+
viewers_type: List[ViewersEnum]
|
|
187
|
+
viewers_name: List[str] or None
|
|
188
|
+
force: bool
|
|
189
|
+
if True remove all viewers before update else check if new viewers type are compatible with old ones
|
|
190
|
+
|
|
191
|
+
Returns
|
|
192
|
+
-------
|
|
193
|
+
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
Nviewers_to_leave = 0
|
|
197
|
+
if not force:
|
|
198
|
+
# check if viewers are compatible with new data dim
|
|
199
|
+
for ind, viewer_type in enumerate(viewers_type):
|
|
200
|
+
if len(self.viewer_types) > ind:
|
|
201
|
+
if viewer_type == self.viewer_types[ind]:
|
|
202
|
+
Nviewers_to_leave += 1
|
|
203
|
+
else:
|
|
204
|
+
break
|
|
205
|
+
else:
|
|
206
|
+
break
|
|
207
|
+
self.remove_viewers(Nviewers_to_leave)
|
|
208
|
+
ind_loop = 0
|
|
209
|
+
while len(self.viewers) < len(viewers_type):
|
|
210
|
+
self.add_viewer(viewers_type[Nviewers_to_leave + ind_loop],
|
|
211
|
+
dock_name=viewers_name[Nviewers_to_leave + ind_loop] if viewers_name is not None else None)
|
|
212
|
+
ind_loop += 1
|
|
213
|
+
QtWidgets.QApplication.processEvents()
|
|
214
|
+
|
|
215
|
+
def close(self):
|
|
216
|
+
for dock in self.viewer_docks:
|
|
217
|
+
dock.close()
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class ViewerBase(QObject):
|
|
221
|
+
"""Base Class for data viewers implementing all common functionalities
|
|
222
|
+
|
|
223
|
+
Parameters
|
|
224
|
+
----------
|
|
225
|
+
parent: QtWidgets.QWidget
|
|
226
|
+
title: str
|
|
227
|
+
|
|
228
|
+
Attributes
|
|
229
|
+
----------
|
|
230
|
+
view: QObject
|
|
231
|
+
Ui interface of the viewer
|
|
232
|
+
|
|
233
|
+
data_to_export_signal: Signal[DataToExport]
|
|
234
|
+
ROI_changed: Signal
|
|
235
|
+
crosshair_dragged: Signal[float, float]
|
|
236
|
+
crosshair_clicked: Signal[bool]
|
|
237
|
+
sig_double_clicked: Signal[float, float]
|
|
238
|
+
status_signal: Signal[str]
|
|
239
|
+
"""
|
|
240
|
+
data_to_export_signal = Signal(DataToExport)
|
|
241
|
+
_data_to_show_signal = Signal(DataWithAxes)
|
|
242
|
+
|
|
243
|
+
ROI_changed = Signal()
|
|
244
|
+
crosshair_dragged = Signal(float, float) # Crosshair position in units of scaled top/right axes
|
|
245
|
+
status_signal = Signal(str)
|
|
246
|
+
crosshair_clicked = Signal(bool)
|
|
247
|
+
sig_double_clicked = Signal(float, float)
|
|
248
|
+
|
|
249
|
+
def __init__(self, parent=None, title=''):
|
|
250
|
+
super().__init__()
|
|
251
|
+
self.title = title if title != '' else self.__class__.__name__
|
|
252
|
+
|
|
253
|
+
self._raw_data = None
|
|
254
|
+
self.data_to_export: DataToExport = DataToExport(name=self.title)
|
|
255
|
+
self.view: Union[Viewer0D, Viewer1D, Viewer2D, ViewerND] = None
|
|
256
|
+
|
|
257
|
+
if parent is None:
|
|
258
|
+
parent = QtWidgets.QWidget()
|
|
259
|
+
parent.show()
|
|
260
|
+
self.parent = parent
|
|
261
|
+
|
|
262
|
+
self._display_temporary = False
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def has_action(self):
|
|
266
|
+
"""Convenience method"""
|
|
267
|
+
if hasattr(self.view, 'has_action'):
|
|
268
|
+
return self.view.has_action
|
|
269
|
+
|
|
270
|
+
@property
|
|
271
|
+
def is_action_checked(self):
|
|
272
|
+
"""Convenience method"""
|
|
273
|
+
if hasattr(self.view, 'is_action_checked'):
|
|
274
|
+
return self.view.is_action_checked
|
|
275
|
+
|
|
276
|
+
@property
|
|
277
|
+
def is_action_visible(self):
|
|
278
|
+
"""Convenience method"""
|
|
279
|
+
if hasattr(self.view, 'is_action_visible'):
|
|
280
|
+
return self.view.is_action_visible
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def set_action_checked(self):
|
|
284
|
+
"""Convenience method"""
|
|
285
|
+
if hasattr(self.view, 'set_action_checked'):
|
|
286
|
+
return self.view.set_action_checked
|
|
287
|
+
|
|
288
|
+
@property
|
|
289
|
+
def set_action_visible(self):
|
|
290
|
+
"""Convenience method"""
|
|
291
|
+
if hasattr(self.view, 'set_action_visible'):
|
|
292
|
+
return self.view.set_action_visible
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def get_action(self):
|
|
296
|
+
"""Convenience method"""
|
|
297
|
+
if hasattr(self.view, 'get_action'):
|
|
298
|
+
return self.view.get_action
|
|
299
|
+
|
|
300
|
+
@property
|
|
301
|
+
def toolbar(self):
|
|
302
|
+
"""Convenience property"""
|
|
303
|
+
if hasattr(self.view, 'toolbar'):
|
|
304
|
+
return self.view.toolbar
|
|
305
|
+
|
|
306
|
+
@property
|
|
307
|
+
def viewer_type(self):
|
|
308
|
+
"""str: the viewer data type see DATA_TYPES"""
|
|
309
|
+
return ViewersEnum[self.__class__.__name__].value
|
|
310
|
+
|
|
311
|
+
def show_data(self, data: DataWithAxes, **kwargs):
|
|
312
|
+
"""Entrypoint to display data into the viewer
|
|
313
|
+
|
|
314
|
+
Parameters
|
|
315
|
+
----------
|
|
316
|
+
data: data_mod.DataFromPlugins
|
|
317
|
+
"""
|
|
318
|
+
if len(data.shape) > 4:
|
|
319
|
+
raise ViewerError(f'Ndarray of dim: {len(data.shape)} cannot be plotted using a {self.viewer_type}')
|
|
320
|
+
|
|
321
|
+
self.data_to_export = DataToExport(name=self.title)
|
|
322
|
+
self._raw_data = data
|
|
323
|
+
|
|
324
|
+
self._display_temporary = False
|
|
325
|
+
|
|
326
|
+
self._show_data(data, **kwargs)
|
|
327
|
+
|
|
328
|
+
def show_data_temp(self, data: DataRaw, **kwargs):
|
|
329
|
+
"""Entrypoint to display temporary data into the viewer
|
|
330
|
+
|
|
331
|
+
No processed data signal is emitted from the viewer
|
|
332
|
+
|
|
333
|
+
Parameters
|
|
334
|
+
----------
|
|
335
|
+
data: data_mod.DataFromPlugins
|
|
336
|
+
"""
|
|
337
|
+
self._display_temporary = True
|
|
338
|
+
self.show_data(data, **kwargs)
|
|
339
|
+
|
|
340
|
+
def _show_data(self, data: DataRaw):
|
|
341
|
+
"""Specific viewers should implement it"""
|
|
342
|
+
raise NotImplementedError
|
|
343
|
+
|
|
344
|
+
def add_attributes_from_view(self):
|
|
345
|
+
"""Convenience function to add attributes from the view to self"""
|
|
346
|
+
for attribute in self.convenience_attributes:
|
|
347
|
+
if hasattr(self.view, attribute):
|
|
348
|
+
setattr(self, attribute, getattr(self.view, attribute))
|
|
349
|
+
|
|
350
|
+
def trigger_action(self, action_name: str):
|
|
351
|
+
"""Convenience function to trigger programmatically one of the action of the related view"""
|
|
352
|
+
if self.has_action(action_name):
|
|
353
|
+
self.get_action(action_name).trigger()
|
|
354
|
+
|
|
355
|
+
def activate_roi(self, activate=True):
|
|
356
|
+
"""Activate the Roi manager using the corresponding action"""
|
|
357
|
+
raise NotImplementedError
|
|
358
|
+
|
|
359
|
+
def setVisible(self, show=True):
|
|
360
|
+
"""convenience method to show or hide the paretn widget"""
|
|
361
|
+
self.parent.setVisible(show)
|
|
362
|
+
|
|
363
|
+
@property
|
|
364
|
+
def roi_target(self) -> Union[InfiniteLine.InfiniteLine, ROI.ROI]:
|
|
365
|
+
"""To be implemented if necessary (Viewer1D and above)"""
|
|
366
|
+
return None
|
|
367
|
+
|
|
368
|
+
def move_roi_target(self, pos: Iterable[float] = None, **kwargs):
|
|
369
|
+
"""move a specific read only ROI at the given position on the viewer"""
|
|
370
|
+
...
|
|
371
|
+
|
|
372
|
+
def show_roi_target(self, show=True):
|
|
373
|
+
"""Show/Hide a specific read only ROI"""
|
|
374
|
+
if self.roi_target is not None:
|
|
375
|
+
self.roi_target.setVisible(show)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
if __name__ == '__main__':
|
|
379
|
+
import sys
|
|
380
|
+
import random
|
|
381
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
382
|
+
|
|
383
|
+
dockarea = DockArea()
|
|
384
|
+
prog = ViewerDispatcher(dockarea=dockarea, title='Dispatcher')
|
|
385
|
+
dockarea.show()
|
|
386
|
+
N = 2
|
|
387
|
+
viewers = ['Viewer0D', 'Viewer1D', 'Viewer2D']
|
|
388
|
+
viewers = [ViewersEnum[random.choice(viewers)] for ind in range(N)]
|
|
389
|
+
viewers = ['Viewer2D', 'Viewer2D', ]
|
|
390
|
+
print(viewers)
|
|
391
|
+
prog.update_viewers(viewers)
|
|
392
|
+
|
|
393
|
+
sys.exit(app.exec_())
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
from typing import List, Union
|
|
2
|
+
from numbers import Real
|
|
3
|
+
|
|
4
|
+
from qtpy import QtWidgets, QtGui
|
|
5
|
+
from qtpy.QtCore import QObject, Slot, Signal, Qt
|
|
6
|
+
import sys
|
|
7
|
+
import pyqtgraph
|
|
8
|
+
|
|
9
|
+
import pymodaq.utils.daq_utils as utils
|
|
10
|
+
from pymodaq.utils import data as data_mod
|
|
11
|
+
from pymodaq.utils.logger import set_logger, get_module_name
|
|
12
|
+
from pymodaq.utils.plotting.data_viewers.viewer import ViewerBase
|
|
13
|
+
from pymodaq.utils.managers.action_manager import ActionManager
|
|
14
|
+
from pymodaq.utils.plotting.widgets import PlotWidget
|
|
15
|
+
from pymodaq.utils.plotting.utils.plot_utils import Data0DWithHistory
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
from collections import OrderedDict
|
|
19
|
+
import datetime
|
|
20
|
+
|
|
21
|
+
logger = set_logger(get_module_name(__file__))
|
|
22
|
+
PLOT_COLORS = utils.plot_colors
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DataDisplayer(QObject):
|
|
26
|
+
"""
|
|
27
|
+
This Object deals with the display of 0D data on a plotitem
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
updated_item = Signal(list)
|
|
31
|
+
labels_changed = Signal(list)
|
|
32
|
+
|
|
33
|
+
def __init__(self, plotitem: pyqtgraph.PlotItem):
|
|
34
|
+
super().__init__()
|
|
35
|
+
self._plotitem = plotitem
|
|
36
|
+
self._plotitem.addLegend()
|
|
37
|
+
self._plot_items: List[pyqtgraph.PlotDataItem] = []
|
|
38
|
+
self._min_lines: List[pyqtgraph.InfiniteLine] = []
|
|
39
|
+
self._max_lines: List[pyqtgraph.InfiniteLine] = []
|
|
40
|
+
self._data = Data0DWithHistory()
|
|
41
|
+
|
|
42
|
+
self._mins: List = []
|
|
43
|
+
self._maxs: List = []
|
|
44
|
+
|
|
45
|
+
self._show_lines: bool = False
|
|
46
|
+
|
|
47
|
+
axis = self._plotitem.getAxis('bottom')
|
|
48
|
+
axis.setLabel(text='Samples', units='S')
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def legend(self):
|
|
52
|
+
return self._plotitem.legend
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def axis(self):
|
|
56
|
+
return self._data.xaxis
|
|
57
|
+
|
|
58
|
+
def clear_data(self):
|
|
59
|
+
self._data.clear_data()
|
|
60
|
+
self._mins = []
|
|
61
|
+
self._maxs = []
|
|
62
|
+
|
|
63
|
+
def update_axis(self, history_length: int):
|
|
64
|
+
self._data.length = history_length
|
|
65
|
+
|
|
66
|
+
def update_data(self, data: data_mod.DataRaw):
|
|
67
|
+
if len(data) != len(self._plot_items):
|
|
68
|
+
self.update_display_items(data)
|
|
69
|
+
|
|
70
|
+
self._data.add_datas(data)
|
|
71
|
+
for ind, data_str in enumerate(self._data.datas):
|
|
72
|
+
self._plot_items[ind].setData(self._data.xaxis, self._data.datas[data_str])
|
|
73
|
+
if len(self._mins) != len(self._data.datas):
|
|
74
|
+
self._mins = []
|
|
75
|
+
self._maxs = []
|
|
76
|
+
|
|
77
|
+
for ind, label in enumerate(self._data.datas):
|
|
78
|
+
if len(self._mins) != len(self._data.datas):
|
|
79
|
+
self._mins.append(float(np.min(self._data.datas[label])))
|
|
80
|
+
self._maxs.append(float(np.max(self._data.datas[label])))
|
|
81
|
+
else:
|
|
82
|
+
self._mins[ind] = min(self._mins[ind], float(np.min(self._data.datas[label])))
|
|
83
|
+
self._maxs[ind] = max(self._maxs[ind], float(np.max(self._data.datas[label])))
|
|
84
|
+
self._min_lines[ind].setValue(self._mins[ind])
|
|
85
|
+
self._max_lines[ind].setValue(self._maxs[ind])
|
|
86
|
+
|
|
87
|
+
def update_display_items(self, data: data_mod.DataRaw):
|
|
88
|
+
while len(self._plot_items) > 0:
|
|
89
|
+
plot_item = self._plotitem.removeItem(self._plot_items.pop(0))
|
|
90
|
+
self.legend.removeItem(plot_item)
|
|
91
|
+
self._plotitem.removeItem(self._max_lines.pop(0))
|
|
92
|
+
self._plotitem.removeItem(self._min_lines.pop(0))
|
|
93
|
+
|
|
94
|
+
for ind in range(len(data)):
|
|
95
|
+
self._plot_items.append(pyqtgraph.PlotDataItem(pen=PLOT_COLORS[ind]))
|
|
96
|
+
self._plotitem.addItem(self._plot_items[-1])
|
|
97
|
+
self.legend.addItem(self._plot_items[-1], data.labels[ind])
|
|
98
|
+
max_line = pyqtgraph.InfiniteLine(angle=0, pen=pyqtgraph.mkPen(color=PLOT_COLORS[ind], style=Qt.DashLine))
|
|
99
|
+
min_line = pyqtgraph.InfiniteLine(angle=0, pen=pyqtgraph.mkPen(color=PLOT_COLORS[ind], style=Qt.DashLine))
|
|
100
|
+
self._max_lines.append(max_line)
|
|
101
|
+
self._min_lines.append(min_line)
|
|
102
|
+
max_line.setVisible(self._show_lines)
|
|
103
|
+
min_line.setVisible(self._show_lines)
|
|
104
|
+
self._plotitem.addItem(self._max_lines[-1])
|
|
105
|
+
self._plotitem.addItem(self._min_lines[-1])
|
|
106
|
+
|
|
107
|
+
self.updated_item.emit(self._plot_items)
|
|
108
|
+
self.labels_changed.emit(data.labels)
|
|
109
|
+
|
|
110
|
+
def show_min_max(self, show=True):
|
|
111
|
+
self._show_lines = show
|
|
112
|
+
for line in self._max_lines:
|
|
113
|
+
line.setVisible(show)
|
|
114
|
+
for line in self._min_lines:
|
|
115
|
+
line.setVisible(show)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class View0D(ActionManager, QObject):
|
|
119
|
+
def __init__(self, parent_widget: QtWidgets.QWidget = None):
|
|
120
|
+
QObject.__init__(self)
|
|
121
|
+
ActionManager.__init__(self, toolbar=QtWidgets.QToolBar())
|
|
122
|
+
|
|
123
|
+
self.data_displayer: DataDisplayer = None
|
|
124
|
+
self.plot_widget: PlotWidget = PlotWidget()
|
|
125
|
+
self.values_list = QtWidgets.QListWidget()
|
|
126
|
+
|
|
127
|
+
self.setup_actions()
|
|
128
|
+
|
|
129
|
+
self.parent_widget = parent_widget
|
|
130
|
+
if self.parent_widget is None:
|
|
131
|
+
self.parent_widget = QtWidgets.QWidget()
|
|
132
|
+
self.parent_widget.show()
|
|
133
|
+
|
|
134
|
+
self.data_displayer = DataDisplayer(self.plotitem)
|
|
135
|
+
|
|
136
|
+
self._setup_widgets()
|
|
137
|
+
self._connect_things()
|
|
138
|
+
self._prepare_ui()
|
|
139
|
+
|
|
140
|
+
self.get_action('Nhistory').setValue(200) #default history length
|
|
141
|
+
|
|
142
|
+
def setup_actions(self):
|
|
143
|
+
self.add_action('clear', 'Clear plot', 'clear2', 'Clear the current plots')
|
|
144
|
+
self.add_widget('Nhistory', pyqtgraph.SpinBox, tip='Set the history length of the plot',
|
|
145
|
+
setters=dict(setMaximumWidth=100))
|
|
146
|
+
self.add_action('show_data_as_list', 'Show numbers', 'ChnNum', 'If triggered, will display last data as numbers'
|
|
147
|
+
'in a side panel', checkable=True)
|
|
148
|
+
self.add_action('show_min_max', 'Show Min/Max lines', 'Statistics',
|
|
149
|
+
'If triggered, will display horizontal dashed lines for min/max of data', checkable=True)
|
|
150
|
+
|
|
151
|
+
def _setup_widgets(self):
|
|
152
|
+
self.parent_widget.setLayout(QtWidgets.QVBoxLayout())
|
|
153
|
+
self.parent_widget.layout().addWidget(self.toolbar)
|
|
154
|
+
|
|
155
|
+
splitter_hor = QtWidgets.QSplitter(Qt.Horizontal)
|
|
156
|
+
self.parent_widget.layout().addWidget(splitter_hor)
|
|
157
|
+
|
|
158
|
+
splitter_hor.addWidget(self.plot_widget)
|
|
159
|
+
splitter_hor.addWidget(self.values_list)
|
|
160
|
+
|
|
161
|
+
font = QtGui.QFont()
|
|
162
|
+
font.setPointSize(20)
|
|
163
|
+
self.values_list.setFont(font)
|
|
164
|
+
|
|
165
|
+
def _connect_things(self):
|
|
166
|
+
self.connect_action('clear', self.data_displayer.clear_data)
|
|
167
|
+
self.connect_action('show_data_as_list', self.show_data_list)
|
|
168
|
+
self.connect_action('Nhistory', self.data_displayer.update_axis, signal_name='valueChanged')
|
|
169
|
+
self.connect_action('show_min_max', self.data_displayer.show_min_max)
|
|
170
|
+
|
|
171
|
+
def _prepare_ui(self):
|
|
172
|
+
"""add here everything needed at startup"""
|
|
173
|
+
self.values_list.setVisible(False)
|
|
174
|
+
|
|
175
|
+
def get_double_clicked(self):
|
|
176
|
+
return self.plot_widget.view.sig_double_clicked
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def plotitem(self):
|
|
180
|
+
return self.plot_widget.plotItem
|
|
181
|
+
|
|
182
|
+
def display_data(self, data: data_mod.DataRaw):
|
|
183
|
+
self.data_displayer.update_data(data)
|
|
184
|
+
if self.is_action_checked('show_data_as_list'):
|
|
185
|
+
self.values_list.clear()
|
|
186
|
+
self.values_list.addItems(['{:.03e}'.format(dat[0]) for dat in data])
|
|
187
|
+
QtWidgets.QApplication.processEvents()
|
|
188
|
+
|
|
189
|
+
def show_data_list(self, state=None):
|
|
190
|
+
if state is None:
|
|
191
|
+
state = self.is_action_checked('show_data_as_list')
|
|
192
|
+
self.values_list.setVisible(state)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class Viewer0D(ViewerBase):
|
|
196
|
+
"""this plots 0D data on a plotwidget with history. Display as numbers in a table is possible.
|
|
197
|
+
|
|
198
|
+
Datas and measurements are then exported with the signal data_to_export_signal
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
def __init__(self, parent=None, title=''):
|
|
202
|
+
super().__init__(parent, title)
|
|
203
|
+
self.view = View0D(self.parent)
|
|
204
|
+
self._labels = []
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def labels(self):
|
|
208
|
+
return self._labels
|
|
209
|
+
|
|
210
|
+
@labels.setter
|
|
211
|
+
def labels(self, labels):
|
|
212
|
+
if labels != self._labels:
|
|
213
|
+
self._labels = labels
|
|
214
|
+
|
|
215
|
+
@Slot(list)
|
|
216
|
+
def _show_data(self, data: data_mod.DataRaw):
|
|
217
|
+
self.labels = data.labels
|
|
218
|
+
self.view.display_data(data)
|
|
219
|
+
self.data_to_export_signal.emit(self.data_to_export)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def main_view():
|
|
223
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
224
|
+
widget = QtWidgets.QWidget()
|
|
225
|
+
prog = View0D(widget)
|
|
226
|
+
widget.show()
|
|
227
|
+
sys.exit(app.exec_())
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def main():
|
|
231
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
232
|
+
widget = QtWidgets.QWidget()
|
|
233
|
+
prog = Viewer0D(widget)
|
|
234
|
+
from pymodaq.utils.daq_utils import gauss1D
|
|
235
|
+
|
|
236
|
+
x = np.linspace(0, 200, 201)
|
|
237
|
+
y1 = gauss1D(x, 75, 25) + 0.1*np.random.rand(len(x))
|
|
238
|
+
y2 = 0.7 * gauss1D(x, 120, 50, 2) + 0.2*np.random.rand(len(x))
|
|
239
|
+
widget.show()
|
|
240
|
+
prog.get_action('show_data_as_list').trigger()
|
|
241
|
+
for ind, data in enumerate(y1):
|
|
242
|
+
prog.show_data(data_mod.DataRaw('mydata', data=[np.array([data]), np.array([y2[ind]])],
|
|
243
|
+
labels=['lab1', 'lab2']))
|
|
244
|
+
QtWidgets.QApplication.processEvents()
|
|
245
|
+
|
|
246
|
+
sys.exit(app.exec_())
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if __name__ == '__main__': # pragma: no cover
|
|
250
|
+
#main_view()
|
|
251
|
+
main()
|