pymodaq 3.6.13__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.

Files changed (233) hide show
  1. pymodaq/__init__.py +13 -6
  2. pymodaq/control_modules/__init__.py +0 -7
  3. pymodaq/control_modules/daq_move.py +965 -2
  4. pymodaq/control_modules/daq_move_ui.py +319 -0
  5. pymodaq/control_modules/daq_viewer.py +1573 -3
  6. pymodaq/control_modules/daq_viewer_ui.py +393 -0
  7. pymodaq/control_modules/mocks.py +51 -0
  8. pymodaq/control_modules/move_utility_classes.py +709 -8
  9. pymodaq/control_modules/utils.py +256 -0
  10. pymodaq/control_modules/viewer_utility_classes.py +663 -6
  11. pymodaq/daq_utils.py +89 -0
  12. pymodaq/dashboard.py +91 -72
  13. pymodaq/examples/custom_app.py +12 -11
  14. pymodaq/examples/custom_viewer.py +10 -10
  15. pymodaq/examples/function_plotter.py +16 -13
  16. pymodaq/examples/nonlinearscanner.py +8 -6
  17. pymodaq/examples/parameter_ex.py +7 -7
  18. pymodaq/examples/preset_MockCamera.xml +1 -0
  19. pymodaq/extensions/__init__.py +16 -0
  20. pymodaq/extensions/console.py +76 -0
  21. pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
  22. pymodaq/extensions/daq_scan.py +1339 -0
  23. pymodaq/extensions/daq_scan_ui.py +240 -0
  24. pymodaq/extensions/h5browser.py +23 -0
  25. pymodaq/{pid → extensions/pid}/__init__.py +4 -2
  26. pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
  27. pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
  28. pymodaq/{pid → extensions/pid}/utils.py +52 -6
  29. pymodaq/extensions/utils.py +40 -0
  30. pymodaq/post_treatment/__init__.py +6 -0
  31. pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
  32. pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
  33. pymodaq/post_treatment/load_and_plot.py +219 -0
  34. pymodaq/post_treatment/process_to_scalar.py +263 -0
  35. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
  36. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
  37. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
  38. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
  39. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
  40. pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
  41. pymodaq/resources/VERSION +1 -1
  42. pymodaq/resources/config_template.toml +32 -13
  43. pymodaq/resources/preset_default.xml +1 -1
  44. pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
  45. pymodaq/utils/__init__.py +0 -29
  46. pymodaq/utils/abstract/__init__.py +48 -0
  47. pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
  48. pymodaq/utils/array_manipulation.py +379 -8
  49. pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
  50. pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
  51. pymodaq/utils/config.py +448 -0
  52. pymodaq/utils/conftests.py +5 -0
  53. pymodaq/utils/daq_utils.py +828 -8
  54. pymodaq/utils/data.py +1873 -7
  55. pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
  56. pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
  57. pymodaq/{daq_utils → utils}/enums.py +12 -7
  58. pymodaq/utils/exceptions.py +37 -0
  59. pymodaq/utils/factory.py +82 -0
  60. pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
  61. pymodaq/utils/gui_utils/custom_app.py +129 -0
  62. pymodaq/utils/gui_utils/file_io.py +66 -0
  63. pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
  64. pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
  65. pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
  66. pymodaq/utils/gui_utils/widgets/label.py +24 -0
  67. pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
  68. pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
  69. pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
  70. pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
  71. pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
  72. pymodaq/utils/h5modules/__init__.py +1 -0
  73. pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
  74. pymodaq/utils/h5modules/browsing.py +683 -0
  75. pymodaq/utils/h5modules/data_saving.py +839 -0
  76. pymodaq/utils/h5modules/h5logging.py +110 -0
  77. pymodaq/utils/h5modules/module_saving.py +350 -0
  78. pymodaq/utils/h5modules/saving.py +914 -0
  79. pymodaq/utils/h5modules/utils.py +85 -0
  80. pymodaq/utils/logger.py +64 -6
  81. pymodaq/utils/managers/action_manager.py +460 -0
  82. pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
  83. pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
  84. pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
  85. pymodaq/utils/managers/parameter_manager.py +110 -0
  86. pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
  87. pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
  88. pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
  89. pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
  90. pymodaq/utils/math_utils.py +546 -10
  91. pymodaq/{daq_utils → utils}/messenger.py +5 -1
  92. pymodaq/utils/parameter/__init__.py +2 -15
  93. pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
  94. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
  95. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
  96. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
  97. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
  98. pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
  99. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
  100. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
  101. pymodaq/utils/parameter/utils.py +206 -11
  102. pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
  103. pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
  104. pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
  105. pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
  106. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
  107. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
  108. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
  109. pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
  110. pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
  111. pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
  112. pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
  113. pymodaq/utils/plotting/navigator.py +355 -0
  114. pymodaq/utils/plotting/scan_selector.py +480 -0
  115. pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
  116. pymodaq/utils/plotting/utils/filter.py +538 -0
  117. pymodaq/utils/plotting/utils/lineout.py +224 -0
  118. pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
  119. pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
  120. pymodaq/utils/plotting/widgets.py +76 -0
  121. pymodaq/utils/scanner/__init__.py +10 -0
  122. pymodaq/utils/scanner/scan_factory.py +204 -0
  123. pymodaq/utils/scanner/scanner.py +271 -0
  124. pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
  125. pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
  126. pymodaq/utils/scanner/scanners/sequential.py +192 -0
  127. pymodaq/utils/scanner/scanners/tabular.py +294 -0
  128. pymodaq/utils/scanner/utils.py +83 -0
  129. pymodaq/utils/slicing.py +47 -0
  130. pymodaq/utils/svg/__init__.py +6 -0
  131. pymodaq/utils/svg/svg_renderer.py +20 -0
  132. pymodaq/utils/svg/svg_view.py +35 -0
  133. pymodaq/utils/svg/svg_viewer2D.py +51 -0
  134. pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
  135. pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
  136. pymodaq/utils/units.py +216 -0
  137. pymodaq-4.0.1.dist-info/METADATA +159 -0
  138. {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
  139. {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
  140. pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
  141. pymodaq/daq_move/daq_move_gui.py +0 -279
  142. pymodaq/daq_move/daq_move_gui.ui +0 -534
  143. pymodaq/daq_move/daq_move_main.py +0 -1042
  144. pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
  145. pymodaq/daq_move/utility_classes.py +0 -686
  146. pymodaq/daq_scan.py +0 -2160
  147. pymodaq/daq_utils/array_manipulation.py +0 -386
  148. pymodaq/daq_utils/config.py +0 -273
  149. pymodaq/daq_utils/conftests.py +0 -7
  150. pymodaq/daq_utils/custom_parameter_tree.py +0 -9
  151. pymodaq/daq_utils/daq_enums.py +0 -133
  152. pymodaq/daq_utils/daq_utils.py +0 -1402
  153. pymodaq/daq_utils/exceptions.py +0 -71
  154. pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
  155. pymodaq/daq_utils/gui_utils/file_io.py +0 -75
  156. pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
  157. pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
  158. pymodaq/daq_utils/h5exporters.py +0 -242
  159. pymodaq/daq_utils/h5modules.py +0 -1559
  160. pymodaq/daq_utils/h5utils.py +0 -241
  161. pymodaq/daq_utils/managers/action_manager.py +0 -236
  162. pymodaq/daq_utils/managers/parameter_manager.py +0 -57
  163. pymodaq/daq_utils/math_utils.py +0 -705
  164. pymodaq/daq_utils/parameter/__init__.py +0 -1
  165. pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
  166. pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
  167. pymodaq/daq_utils/parameter/utils.py +0 -136
  168. pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
  169. pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
  170. pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
  171. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
  172. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
  173. pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
  174. pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
  175. pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
  176. pymodaq/daq_utils/plotting/items/__init__.py +0 -0
  177. pymodaq/daq_utils/plotting/navigator.py +0 -500
  178. pymodaq/daq_utils/plotting/scan_selector.py +0 -289
  179. pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
  180. pymodaq/daq_utils/plotting/utils/filter.py +0 -236
  181. pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
  182. pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
  183. pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
  184. pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
  185. pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
  186. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
  187. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
  188. pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
  189. pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
  190. pymodaq/daq_utils/scanner.py +0 -1289
  191. pymodaq/daq_utils/tree_layout/__init__.py +0 -0
  192. pymodaq/daq_viewer/__init__.py +0 -0
  193. pymodaq/daq_viewer/daq_gui_settings.py +0 -237
  194. pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
  195. pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
  196. pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
  197. pymodaq/daq_viewer/utility_classes.py +0 -673
  198. pymodaq/examples/logger_image/__init__.py +0 -0
  199. pymodaq/examples/logger_image/logger_displayer.py +0 -121
  200. pymodaq/examples/logger_image/setup.svg +0 -3119
  201. pymodaq/examples/logger_image/setup_svg.py +0 -114
  202. pymodaq/h5browser.py +0 -39
  203. pymodaq/utils/scanner.py +0 -15
  204. pymodaq-3.6.13.dist-info/METADATA +0 -39
  205. pymodaq-3.6.13.dist-info/entry_points.txt +0 -8
  206. pymodaq-3.6.13.dist-info/top_level.txt +0 -1
  207. /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
  208. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
  209. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
  210. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
  211. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
  212. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
  213. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
  214. /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
  215. /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
  216. /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
  217. /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
  218. /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
  219. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
  220. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
  221. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
  222. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
  223. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
  224. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
  225. /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
  226. /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
  227. /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
  228. /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
  229. /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
  230. /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
  231. /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
  232. /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
  233. {pymodaq-3.6.13.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,574 @@
1
+ import sys
2
+ import datetime
3
+ from collections import OrderedDict
4
+ from typing import List, Iterable
5
+
6
+ from qtpy import QtWidgets
7
+ from qtpy.QtCore import QObject, Slot, Signal, Qt
8
+ import pyqtgraph as pg
9
+ import numpy as np
10
+
11
+ from pymodaq.utils.data import DataRaw, DataFromRoi, Axis, DataToExport, DataCalculated, DataWithAxes
12
+ from pymodaq.utils.logger import set_logger, get_module_name
13
+ from pymodaq.utils.parameter import utils as putils
14
+ from pymodaq.utils.plotting.items.crosshair import Crosshair
15
+ from pymodaq.utils import daq_utils as utils
16
+ import pymodaq.utils.math_utils as mutils
17
+ from pymodaq.utils.managers.action_manager import ActionManager
18
+ from pymodaq.utils.plotting.data_viewers.viewer import ViewerBase
19
+
20
+ from pymodaq.utils.managers.roi_manager import ROIManager
21
+ from pymodaq.utils.plotting.utils.filter import Filter1DFromCrosshair, Filter1DFromRois
22
+ from pymodaq.utils.plotting.utils.lineout import LineoutPlotter
23
+ from pymodaq.utils.plotting.widgets import PlotWidget
24
+
25
+
26
+ logger = set_logger(get_module_name(__file__))
27
+
28
+ PLOT_COLORS = utils.plot_colors
29
+
30
+
31
+ class LineoutPlotter(LineoutPlotter):
32
+ """class to manage and display data filtered out into lineouts (1D, 0D)
33
+
34
+ Should be inherited and subclass some methods as appropriate
35
+
36
+ Parameters
37
+ ----------
38
+ graph_widgets: OrderedDict
39
+ Includes plotwidgets to display data
40
+ roi_manager:
41
+ The ROIManager to create ROIs and manage their properties
42
+ crosshair:
43
+ The Crosshair object
44
+ """
45
+ lineout_widgets = ['int']
46
+
47
+ def __init__(self, graph_widgets: OrderedDict, roi_manager: ROIManager, crosshair: Crosshair):
48
+ super().__init__(graph_widgets, roi_manager, crosshair)
49
+
50
+ def plot_other_lineouts(self, roi_dicts):
51
+ pass
52
+
53
+ def plot_other_crosshair_lineouts(self, crosshair_dict):
54
+ pass
55
+
56
+
57
+ class DataDisplayer(QObject):
58
+ """
59
+ This Object deals with the display of 1D data on a plotitem
60
+ """
61
+
62
+ updated_item = Signal(list)
63
+ labels_changed = Signal(list)
64
+
65
+ def __init__(self, plotitem: pg.PlotItem):
66
+ super().__init__()
67
+ self._plotitem = plotitem
68
+ self._plotitem.addLegend()
69
+ self._plot_items: List[pg.PlotDataItem] = []
70
+ self._axis: Axis = None
71
+ self._data: DataRaw = None
72
+
73
+ @property
74
+ def legend(self):
75
+ return self._plotitem.legend
76
+
77
+ def update_axis(self, axis: Axis):
78
+ self._axis = axis.copy()
79
+ if self._axis.data is None: # create real data vector once here for subsequent use
80
+ self._axis.create_linear_data(axis.size)
81
+
82
+ def get_axis(self) -> Axis:
83
+ return self._axis
84
+
85
+ def get_plot_items(self):
86
+ return self._plot_items
87
+
88
+ def get_plot_item(self, index: int):
89
+ return self._plot_items[index]
90
+
91
+ def update_data(self, data: DataRaw, do_xy=False):
92
+ self._data = data
93
+ if len(data) != len(self._plot_items):
94
+ self.update_display_items(data)
95
+
96
+ axis = data.get_axis_from_index(0, create=False)[0]
97
+ if axis is not None:
98
+ self.update_axis(axis)
99
+
100
+ self.update_xyplot(do_xy, data)
101
+
102
+ def update_xyplot(self, do_xy=True, data=None):
103
+ if data is None:
104
+ data = self._data
105
+
106
+ for ind_data, dat in enumerate(data.data):
107
+ if data.size > 0:
108
+ if not do_xy:
109
+ if self._axis is None:
110
+ self.update_axis(Axis('index', data=Axis.create_simple_linear_data(dat.size)))
111
+ self._plot_items[ind_data].setData(self._axis.get_data(), dat)
112
+ else:
113
+ self._plot_items[ind_data].setData(np.array([]), np.array([]))
114
+
115
+ if do_xy and len(data) == 2:
116
+ self._plot_items[0].setData(data.data[0], data.data[1])
117
+ axis = self._plotitem.getAxis('bottom')
118
+ axis.setLabel(text=data.labels[0], units='')
119
+ axis = self._plotitem.getAxis('left')
120
+ axis.setLabel(text=data.labels[1], units='')
121
+ self.legend.setVisible(False)
122
+
123
+ else:
124
+ axis = self._plotitem.getAxis('bottom')
125
+ axis.setLabel(text=self._axis.label, units=self._axis.units)
126
+ axis = self._plotitem.getAxis('left')
127
+ axis.setLabel(text='', units='')
128
+ self.legend.setVisible(True)
129
+
130
+ def plot_with_scatter(self, with_scatter=True):
131
+ symbol_size = 5
132
+ for ind, plot_item in enumerate(self.get_plot_items()):
133
+ if with_scatter:
134
+ pen = None
135
+ symbol = 'o'
136
+ brush = PLOT_COLORS[ind]
137
+
138
+ else:
139
+ pen = PLOT_COLORS[ind]
140
+ symbol = None
141
+ brush = None
142
+
143
+ plot_item.setPen(pen)
144
+ plot_item.setSymbolBrush(brush)
145
+ plot_item.setSymbol(symbol)
146
+ plot_item.setSymbolSize(symbol_size)
147
+
148
+ def update_display_items(self, data: DataRaw):
149
+ while len(self._plot_items) > 0:
150
+ self._plotitem.removeItem(self._plot_items.pop(0))
151
+ for ind in range(len(data)):
152
+ self._plot_items.append(pg.PlotDataItem(pen=PLOT_COLORS[ind]))
153
+ self._plotitem.addItem(self._plot_items[-1])
154
+ self.legend.addItem(self._plot_items[-1], data.labels[ind])
155
+ self.updated_item.emit(self._plot_items)
156
+ self.labels_changed.emit(data.labels)
157
+
158
+ @property
159
+ def labels(self):
160
+ return self._data.labels
161
+
162
+ def legend_items(self):
163
+ return [item[1].text for item in self.legend.items]
164
+
165
+
166
+ class View1D(ActionManager, QObject):
167
+ def __init__(self, parent_widget: QtWidgets.QWidget = None):
168
+ QObject.__init__(self)
169
+ ActionManager.__init__(self, toolbar=QtWidgets.QToolBar())
170
+
171
+ self.data_displayer: DataDisplayer = None
172
+ self.plot_widget: PlotWidget = None
173
+ self.lineout_widgets: PlotWidget = None
174
+ self.graphical_widgets: dict = None
175
+ self.crosshair: Crosshair = None
176
+
177
+ self.roi_target = pg.InfiniteLine(pen='w')
178
+
179
+ self.setup_actions()
180
+
181
+ self.parent_widget = parent_widget
182
+ if self.parent_widget is None:
183
+ self.parent_widget = QtWidgets.QWidget()
184
+ self.parent_widget.show()
185
+
186
+ self.plot_widget = PlotWidget()
187
+ self.roi_manager = ROIManager('1D')
188
+ self.data_displayer = DataDisplayer(self.plotitem)
189
+
190
+ self.setup_widgets()
191
+
192
+ self.lineout_plotter = LineoutPlotter(self.graphical_widgets, self.roi_manager, self.crosshair)
193
+ self.connect_things()
194
+ self.prepare_ui()
195
+
196
+ self.plotitem.addItem(self.roi_target)
197
+ self.roi_target.setVisible(False)
198
+
199
+ def move_roi_target(self, pos: Iterable[float], **kwargs):
200
+ if not self.roi_target.isVisible():
201
+ self.roi_target.setVisible(True)
202
+ self.roi_target.setPos(pos[0])
203
+
204
+ def get_double_clicked(self):
205
+ return self.plot_widget.view.sig_double_clicked
206
+
207
+ def display_roi_lineouts(self, roi_dict):
208
+ self.lineout_plotter.plot_roi_lineouts(roi_dict)
209
+
210
+ @property
211
+ def axis(self):
212
+ """Get the current axis used to display data"""
213
+ return self.data_displayer.get_axis()
214
+
215
+ @property
216
+ def plotitem(self):
217
+ return self.plot_widget.plotItem
218
+
219
+ def get_crosshair_signal(self):
220
+ """Convenience function from the Crosshair"""
221
+ return self.crosshair.crosshair_dragged
222
+
223
+ def get_crosshair_position(self):
224
+ """Convenience function from the Crosshair"""
225
+ return self.crosshair.get_positions()
226
+
227
+ def set_crosshair_position(self, *positions):
228
+ """Convenience function from the Crosshair"""
229
+ self.crosshair.set_crosshair_position(*positions)
230
+
231
+ def display_data(self, data: DataRaw):
232
+ self.set_action_visible('xyplot', len(data) == 2)
233
+ self.data_displayer.update_data(data, self.is_action_checked('xyplot'))
234
+
235
+ def prepare_ui(self):
236
+ self.show_hide_crosshair(False)
237
+ self.show_lineout_widgets()
238
+
239
+ def do_math(self):
240
+ try:
241
+ if self.is_action_checked('do_math'):
242
+ self.roi_manager.roiwidget.show()
243
+ self.lineout_widgets.show()
244
+ else:
245
+ self.lineout_widgets.hide()
246
+ self.roi_manager.roiwidget.hide()
247
+
248
+ except Exception as e:
249
+ logger.exception(str(e))
250
+
251
+ @Slot(int, str)
252
+ def update_roi_channels(self, index, roi_type=''):
253
+ """Update the use_channel setting each time a ROI is added"""
254
+ item_param = self.roi_manager.settings.child('ROIs', self.roi_manager.roi_format(index))
255
+ item_param.child('use_channel').setOpts(limits=self.data_displayer.labels)
256
+ item_param.child('use_channel').setValue(self.data_displayer.labels[0])
257
+
258
+ def setup_widgets(self):
259
+ self.parent_widget.setLayout(QtWidgets.QVBoxLayout())
260
+ splitter_hor = QtWidgets.QSplitter(Qt.Horizontal)
261
+ self.parent_widget.layout().addWidget(splitter_hor)
262
+
263
+ splitter_ver = QtWidgets.QSplitter(Qt.Vertical)
264
+ splitter_hor.addWidget(splitter_ver)
265
+ splitter_hor.addWidget(self.roi_manager.roiwidget)
266
+ self.roi_manager.roiwidget.hide()
267
+
268
+ splitter_ver.addWidget(self.toolbar)
269
+
270
+ self.lineout_widgets = PlotWidget()
271
+ self.graphical_widgets = dict(lineouts=dict(int=self.lineout_widgets))
272
+
273
+ splitter_ver.addWidget(self.plot_widget)
274
+ splitter_ver.addWidget(self.lineout_widgets)
275
+ self.roi_manager.viewer_widget = self.plot_widget
276
+
277
+ self.crosshair = Crosshair(self.plotitem, orientation='vertical')
278
+ self.show_hide_crosshair()
279
+
280
+ def connect_things(self):
281
+ self.connect_action('aspect_ratio', self.lock_aspect_ratio)
282
+
283
+ self.connect_action('do_math', self.do_math)
284
+ self.connect_action('do_math', self.lineout_plotter.roi_clicked)
285
+
286
+ self.connect_action('scatter', self.data_displayer.plot_with_scatter)
287
+ self.connect_action('xyplot', self.data_displayer.update_xyplot)
288
+ self.connect_action('crosshair', self.show_hide_crosshair)
289
+ self.connect_action('crosshair', self.lineout_plotter.crosshair_clicked)
290
+
291
+ self.roi_manager.new_ROI_signal.connect(self.update_roi_channels)
292
+ self.data_displayer.labels_changed.connect(self.roi_manager.update_use_channel)
293
+
294
+
295
+ def show_lineout_widgets(self):
296
+ state = self.is_action_checked('do_math') or self.is_action_checked('crosshair')
297
+ for lineout_name in LineoutPlotter.lineout_widgets:
298
+ lineout = self.lineout_plotter.get_lineout_widget(lineout_name)
299
+ lineout.setMouseEnabled(state, state)
300
+ lineout.showAxis('left', state)
301
+ lineout.setVisible(state)
302
+ lineout.update()
303
+
304
+ def setup_actions(self):
305
+ self.add_action('do_math', 'Math', 'Calculator', 'Do Math using ROI', checkable=True)
306
+ self.add_action('crosshair', 'Crosshair', 'reset', 'Show data cursor', checkable=True)
307
+ self.add_action('aspect_ratio', 'AspectRatio', 'Zoom_1_1', 'Fix the aspect ratio', checkable=True)
308
+ self.add_action('scatter', 'Scatter', 'Marker', 'Switch between line or scatter plots', checkable=True)
309
+ self.add_action('xyplot', 'XYPlotting', '2d',
310
+ 'Switch between normal or XY representation (valid for 2 channels)', checkable=True,
311
+ visible=False)
312
+ self.add_action('x_label', 'x:')
313
+ self.add_action('y_label', 'y:')
314
+
315
+ def lock_aspect_ratio(self):
316
+ if self.is_action_checked('aspect_ratio'):
317
+ self.plotitem.vb.setAspectLocked(lock=True, ratio=1)
318
+ else:
319
+ self.plotitem.vb.setAspectLocked(lock=False)
320
+
321
+ def update_crosshair_data(self, crosshair_dict: dict):
322
+ try:
323
+ string = "y="
324
+ for key in crosshair_dict:
325
+ string += "{:.3e} / ".format(crosshair_dict[key]['value'])
326
+ self.get_action('y_label').setText(string)
327
+ self.get_action('x_label').setText(f"x={crosshair_dict[key]['pos']:.3e} ")
328
+
329
+ except Exception as e:
330
+ pass
331
+
332
+ @Slot(bool)
333
+ def show_hide_crosshair(self, show=True):
334
+ self.crosshair.setVisible(show)
335
+ self.set_action_visible('x_label', show)
336
+ self.set_action_visible('y_label', show)
337
+ if self.is_action_checked('crosshair'):
338
+ range = self.plotitem.vb.viewRange()
339
+ self.crosshair.set_crosshair_position(xpos=np.mean(np.array(range[0])))
340
+
341
+ def add_plot_item(self, item):
342
+ self.plotitem.addItem(item)
343
+
344
+
345
+ class Viewer1D(ViewerBase):
346
+ """this plots 1D data on a plotwidget. Math and measurement can be done on it.
347
+
348
+ Datas and measurements are then exported with the signal data_to_export_signal
349
+ """
350
+
351
+ def __init__(self, parent=None, title=''):
352
+ super().__init__(parent=parent, title=title)
353
+
354
+ self.view = View1D(self.parent)
355
+
356
+ self.filter_from_rois = Filter1DFromRois(self.view.roi_manager)
357
+ self.filter_from_rois.register_activation_signal(self.view.get_action('do_math').triggered)
358
+ self.filter_from_rois.register_target_slot(self.process_roi_lineouts)
359
+
360
+ self.filter_from_crosshair = Filter1DFromCrosshair(self.view.crosshair)
361
+ self.filter_from_crosshair.register_activation_signal(self.view.get_action('crosshair').triggered)
362
+ self.filter_from_crosshair.register_target_slot(self.process_crosshair_lineouts)
363
+
364
+ self.prepare_connect_ui()
365
+
366
+ self._labels = []
367
+
368
+ @property
369
+ def roi_manager(self):
370
+ """Convenience method """
371
+ return self.view.roi_manager
372
+
373
+ @property
374
+ def roi_target(self) -> pg.InfiniteLine:
375
+ return self.view.roi_target
376
+
377
+ def move_roi_target(self, pos: Iterable[float] = None):
378
+ """move a specific read only ROI at the given position on the viewer"""
379
+ self.view.move_roi_target(pos)
380
+
381
+ @property
382
+ def crosshair(self):
383
+ """Convenience method """
384
+ return self.view.crosshair
385
+
386
+ def set_crosshair_position(self, xpos, ypos=0):
387
+ """Convenience method to set the crosshair positions"""
388
+ self.view.crosshair.set_crosshair_position(xpos=xpos, ypos=ypos)
389
+
390
+ def add_plot_item(self, item):
391
+ self.view.add_item(item)
392
+
393
+ @Slot(dict)
394
+ def process_crosshair_lineouts(self, crosshair_dict):
395
+ self.view.update_crosshair_data(crosshair_dict)
396
+ self.crosshair_dragged.emit(*self.view.crosshair.get_positions())
397
+
398
+ @Slot(dict)
399
+ def process_roi_lineouts(self, roi_dict):
400
+ self.view.display_roi_lineouts(roi_dict)
401
+ self.measure_data_dict = dict([])
402
+ for roi_key, lineout_data in roi_dict.items():
403
+ if not self._display_temporary:
404
+ if lineout_data.hor_data.size != 0:
405
+ self.data_to_export.append(
406
+ DataFromRoi(name=f'Hlineout_{roi_key}', data=[lineout_data.hor_data],
407
+ axes=[Axis(data=lineout_data.hor_axis.get_data(),
408
+ units=lineout_data.hor_axis.units,
409
+ label=lineout_data.hor_axis.label,
410
+ index=0)]))
411
+
412
+ self.data_to_export.append(DataCalculated(name=f'Integrated_{roi_key}',
413
+ data=[lineout_data.math_data]))
414
+
415
+ self.measure_data_dict[f'{roi_key}:'] = lineout_data.math_data
416
+
417
+ QtWidgets.QApplication.processEvents()
418
+
419
+ self.view.roi_manager.settings.child('measurements').setValue(self.measure_data_dict)
420
+ if not self._display_temporary:
421
+ self.data_to_export_signal.emit(self.data_to_export)
422
+ self.ROI_changed.emit()
423
+
424
+ def prepare_connect_ui(self):
425
+ self._data_to_show_signal.connect(self.view.display_data)
426
+ self.view.lineout_plotter.roi_changed.connect(self.roi_changed)
427
+ self.view.get_crosshair_signal().connect(self.crosshair_changed)
428
+ self.view.get_double_clicked().connect(self.double_clicked)
429
+
430
+ @Slot(float, float)
431
+ def double_clicked(self, posx, posy):
432
+ if self.view.is_action_checked('crosshair'):
433
+ self.view.crosshair.set_crosshair_position(posx)
434
+ self.crosshair_changed()
435
+ self.sig_double_clicked.emit(posx, posy)
436
+
437
+ @Slot(dict)
438
+ def roi_changed(self):
439
+ self.filter_from_rois.filter_data(self._raw_data)
440
+
441
+ def crosshair_changed(self):
442
+ self.filter_from_crosshair.filter_data(self._raw_data)
443
+
444
+ def activate_roi(self, activate=True):
445
+ self.view.set_action_checked('do_math', activate)
446
+ self.view.get_action('do_math').triggered.emit(activate)
447
+
448
+ @property
449
+ def labels(self):
450
+ return self._labels
451
+
452
+ @labels.setter
453
+ def labels(self, labels):
454
+ if labels != self._labels:
455
+ self._labels = labels
456
+
457
+ @Slot(list)
458
+ def _show_data(self, data: DataWithAxes):
459
+ self.labels = data.labels
460
+
461
+ self.get_axis_from_view(data)
462
+
463
+ self.view.display_data(data.sort_data())
464
+ if len(self.view.roi_manager.ROIs) == 0:
465
+ self.data_to_export_signal.emit(self.data_to_export)
466
+ else:
467
+ self.roi_changed()
468
+ if self.view.is_action_checked('crosshair'):
469
+ self.crosshair_changed()
470
+
471
+ def get_axis_from_view(self, data: DataWithAxes):
472
+ if len(data.axes) == 0:
473
+ if self.view.axis is not None:
474
+ data.axes = [self.view.axis]
475
+
476
+ def update_status(self, txt):
477
+ logger.info(txt)
478
+
479
+
480
+ def main():
481
+ app = QtWidgets.QApplication(sys.argv)
482
+ Form = QtWidgets.QWidget()
483
+ prog = Viewer1D(Form)
484
+
485
+ from pymodaq.utils.math_utils import gauss1D
486
+
487
+ x = np.linspace(0, 200, 201)
488
+ y1 = gauss1D(x, 75, 25)
489
+ y2 = gauss1D(x, 120, 50, 2)
490
+ tau_half = 27
491
+ tau2 = 100
492
+ x0 = 50
493
+ dx = 20
494
+ ydata_expodec = np.zeros((len(x)))
495
+ ydata_expodec[:50] = 1 * gauss1D(x[:50], x0, dx, 2)
496
+ ydata_expodec[50:] = 1 * np.exp(-(x[50:] - x0) / (tau_half / np.log(2))) # +1*np.exp(-(x[50:]-x0)/tau2)
497
+ ydata_expodec += 0.1 * np.random.rand(len(x))
498
+
499
+ # x = np.sin(np.linspace(0,6*np.pi,201))
500
+ # y = np.sin(np.linspace(0, 6*np.pi, 201)+np.pi/2)
501
+ data = DataRaw('mydata', data=[y1, ydata_expodec],
502
+ axes=[Axis('myaxis', 'units', data=x)])
503
+
504
+ Form.show()
505
+ prog.view.get_action('do_math').trigger()
506
+
507
+ def print_data(data: DataToExport):
508
+ print(data.data)
509
+ print('******')
510
+ print(data.get_data_from_dim('Data1D'))
511
+ print('******')
512
+ print(data.get_data_from_dim('Data0D'))
513
+ print('***********************************')
514
+
515
+ #prog.data_to_export_signal.connect(print_data)
516
+
517
+
518
+ QtWidgets.QApplication.processEvents()
519
+ prog.show_data(data)
520
+ QtWidgets.QApplication.processEvents()
521
+ sys.exit(app.exec_())
522
+
523
+
524
+ def main_unsorted():
525
+ app = QtWidgets.QApplication(sys.argv)
526
+ widget = QtWidgets.QWidget()
527
+ prog = Viewer1D(widget)
528
+
529
+ from pymodaq.utils.daq_utils import gauss1D
530
+
531
+ x = np.linspace(0, 200, 201)
532
+ xaxis = np.concatenate((x, x[::-1]))
533
+ y = gauss1D(x, 75, 25)
534
+ yaxis = np.concatenate((y, -y))
535
+ data = DataRaw('mydata', data=[yaxis],
536
+ axes=[Axis('myaxis', 'units', data=xaxis)])
537
+ widget.show()
538
+ prog.show_data(data)
539
+
540
+ sys.exit(app.exec_())
541
+
542
+
543
+ def main_view1D():
544
+ app = QtWidgets.QApplication(sys.argv)
545
+ widget = QtWidgets.QWidget()
546
+ prog = View1D(widget)
547
+ widget.show()
548
+ sys.exit(app.exec_())
549
+
550
+
551
+ def main_nans():
552
+ app = QtWidgets.QApplication(sys.argv)
553
+ widget = QtWidgets.QWidget()
554
+ prog = Viewer1D(widget)
555
+
556
+ from pymodaq.utils.daq_utils import gauss1D
557
+
558
+ x = np.linspace(0, 200, 201)
559
+ y = gauss1D(x, 75, 25)
560
+
561
+ y[100:150] = np.nan
562
+ data = DataRaw('mydata', data=[y],
563
+ axes=[Axis('myaxis', 'units', data=x)])
564
+
565
+ widget.show()
566
+ prog.show_data(data)
567
+
568
+ sys.exit(app.exec_())
569
+
570
+ if __name__ == '__main__': # pragma: no cover
571
+ main()
572
+ #main_unsorted()
573
+ #main_view1D()
574
+ #main_nans()
@@ -3,9 +3,11 @@ from qtpy.QtCore import Slot, QObject, QThread, Signal, QLocale, QDateTime, QSiz
3
3
  import sys
4
4
  import pyqtgraph as pg
5
5
  import numpy as np
6
- from pymodaq.daq_utils import daq_utils as utils
7
6
 
8
- logger = utils.set_logger(utils.get_module_name(__file__))
7
+ from pymodaq.utils.logger import set_logger, get_module_name
8
+ from pymodaq.utils import daq_utils as utils
9
+
10
+ logger = set_logger(get_module_name(__file__))
9
11
 
10
12
 
11
13
  class Viewer1DBasic(QObject):
@@ -72,6 +74,9 @@ class Viewer1DBasic(QObject):
72
74
  self.roi_region.sigRegionChanged.connect(self.update_region)
73
75
  self.roi_line.sigPositionChanged.connect(self.update_line)
74
76
 
77
+ def get_line_position(self):
78
+ return self.roi_line.getXPos()
79
+
75
80
  def show_roi_region(self, show=True):
76
81
  self.roi_region.setVisible(show)
77
82
 
@@ -204,7 +209,7 @@ if __name__ == '__main__': # pragma: no cover
204
209
  prog.show_roi_line()
205
210
  prog.roi_region_signal.connect(print_region)
206
211
  prog.roi_line_signal.connect(print_line)
207
- from pymodaq.daq_utils.daq_utils import gauss1D
212
+ from pymodaq.utils.daq_utils import gauss1D
208
213
 
209
214
  x = np.linspace(0, 200, 201)
210
215
  y1 = gauss1D(x, 75, 25)