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.

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.12.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
  139. {pymodaq-3.6.12.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 -671
  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.12.dist-info/METADATA +0 -39
  205. pymodaq-3.6.12.dist-info/entry_points.txt +0 -8
  206. pymodaq-3.6.12.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.12.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
@@ -1,15 +1,551 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Created the 27/10/2022
1
+ import numpy
2
+ import numpy as np
3
+ from numbers import Number
4
+ from typing import List, Union, Tuple
5
+ from pymodaq.utils.logger import get_module_name, set_logger
6
+ from collections.abc import Iterable
4
7
 
5
- @author: Sebastien Weber
6
- """
8
+ logger = set_logger(get_module_name(__file__))
7
9
 
8
- from pymodaq.daq_utils import math_utils
9
10
 
11
+ def my_moment(x, y):
12
+ """Returns the moments of a distribution y over an axe x
13
+
14
+ Parameters
15
+ ----------
16
+ x: list or ndarray
17
+ vector of floats
18
+ y: list or ndarray
19
+ vector of floats corresponding to the x axis
20
+
21
+ Returns
22
+ -------
23
+ m: list
24
+ Contains moment of order 0 (mean) and of order 1 (std) of the distribution y
25
+ """
26
+ dx = np.mean(np.diff(x))
27
+ norm = np.sum(y) * dx
28
+ m = [np.sum(x * y) * dx / norm]
29
+ m.extend([np.sqrt(np.sum((x - m[0]) ** 2 * y) * dx / norm)])
30
+ return m
31
+
32
+
33
+ def normalize(x):
34
+ x = x - np.min(x)
35
+ x = x / np.max(x)
36
+ return x
37
+
38
+
39
+ def odd_even(x):
40
+ """
41
+ odd_even tells if a number is odd (return True) or even (return False)
42
+
43
+ Parameters
44
+ ----------
45
+ x: the integer number to test
46
+
47
+ Returns
48
+ -------
49
+ bool : boolean
50
+ """
51
+ if not isinstance(x, int):
52
+ raise TypeError(f'{x} should be an integer')
53
+ if int(x) % 2 == 0:
54
+ bool = False
55
+ else:
56
+ bool = True
57
+ return bool
58
+
59
+
60
+ def greater2n(x):
61
+ """
62
+ return the first power of 2 greater than x
63
+ Parameters
64
+ ----------
65
+ x: (int or float) a number
66
+
67
+ Returns
68
+ -------
69
+ int: the power of 2 greater than x
70
+ """
71
+ if isinstance(x, bool):
72
+ raise TypeError(f'{x} should be an integer or a float')
73
+ if hasattr(x, '__iter__'):
74
+ res = []
75
+ for el in x:
76
+ if isinstance(el, bool):
77
+ raise TypeError(f'{el} should be an integer or a float')
78
+ if not (isinstance(el, int) or isinstance(el, float)):
79
+ raise TypeError(f'{x} elements should be integer or float')
80
+ res.append(1 << (int(el) - 1).bit_length())
81
+ if isinstance(x, np.ndarray):
82
+ return np.array(res)
83
+ else:
84
+ return res
85
+ else:
86
+ if not (isinstance(x, int) or isinstance(x, float)):
87
+ raise TypeError(f'{x} should be an integer or a float')
88
+ return 1 << (int(x) - 1).bit_length()
89
+
90
+
91
+ def linspace_step(start, stop, step):
92
+ """
93
+ Compute a regular linspace_step distribution from start to stop values.
94
+
95
+ =============== =========== ======================================
96
+ **Parameters** **Type** **Description**
97
+ *start* scalar the starting value of distribution
98
+ *stop* scalar the stopping value of distribution
99
+ *step* scalar the length of a distribution step
100
+ =============== =========== ======================================
101
+
102
+ Returns
103
+ -------
104
+
105
+ scalar array
106
+ The computed distribution axis as an array.
107
+ """
108
+ if np.abs(step) < 1e-12 or np.sign(stop - start) != np.sign(step) or start == stop:
109
+ raise ValueError('Invalid value for one parameter')
110
+ Nsteps = int(np.ceil((stop - start) / step))
111
+ new_stop = start + (Nsteps - 1) * step
112
+ if np.abs(new_stop + step - stop) < 1e-12:
113
+ Nsteps += 1
114
+ new_stop = start + (Nsteps - 1) * step
115
+ return np.linspace(start, new_stop, Nsteps)
116
+
117
+
118
+ def linspace_step_N(start, step, Npts):
119
+ stop = (Npts - 1) * step + start
120
+ return linspace_step(start, stop, step)
121
+
122
+
123
+ def find_index(x, threshold: Union[Number, List[Number]]) -> List[tuple]:
124
+ """find_index finds the index ix such that x(ix) is the closest from threshold
125
+
126
+ Parameters
127
+ ----------
128
+ x : vector
129
+ threshold : list of real numbers
130
+
131
+ Returns
132
+ -------
133
+ out : list of 2-tuple containing ix,x[ix]
134
+ out=[(ix0,xval0),(ix1,xval1),...]
135
+ """
136
+
137
+ if not hasattr(threshold, '__iter__'):
138
+ threshold = [threshold]
139
+ out = []
140
+ for value in threshold:
141
+ ix = int(np.argmin(np.abs(x - value)))
142
+ out.append((ix, x[ix]))
143
+ return out
144
+
145
+
146
+ def find_common_index(x: Iterable, y: Iterable, x0: Number, y0: Number) -> Tuple:
147
+ """find the index in two vectors corresponding to x0 and y0"""
148
+ vals = x + 1j * y
149
+ val = x0 + 1j * y0
150
+ ind = int(np.argmin(np.abs(vals - val)))
151
+ return ind, x[ind], y[ind]
152
+
153
+
154
+ def gauss1D(x, x0, dx, n=1):
155
+ """
156
+ compute the gaussian function along a vector x, centered in x0 and with a
157
+ FWHM i intensity of dx. n=1 is for the standart gaussian while n>1 defines
158
+ a hypergaussian
159
+
160
+ Parameters
161
+ ----------
162
+ x: (ndarray) first axis of the 2D gaussian
163
+ x0: (float) the central position of the gaussian
164
+ dx: (float) :the FWHM of the gaussian
165
+ n=1 : an integer to define hypergaussian, n=1 by default for regular gaussian
166
+ Returns
167
+ -------
168
+ out : vector
169
+ the value taken by the gaussian along x axis
170
+
171
+ """
172
+ if dx <= 0:
173
+ raise ValueError('dx should be strictly positive')
174
+ if not isinstance(n, int):
175
+ raise TypeError('n should be a positive integer')
176
+ elif n < 0:
177
+ raise ValueError('n should be a positive integer')
178
+ out = np.exp(-2 * np.log(2) ** (1 / n) * (((x - x0) / dx)) ** (2 * n))
179
+ return out
180
+
181
+
182
+ def gauss2D(x, x0, dx, y, y0, dy, n=1, angle=0):
183
+ """
184
+ compute the 2D gaussian function along a vector x, centered in x0 and with a
185
+ FWHM in intensity of dx and smae along y axis. n=1 is for the standard gaussian while n>1 defines
186
+ a hypergaussian. optionally rotate it by an angle in degree
187
+
188
+ Parameters
189
+ ----------
190
+ x: (ndarray) first axis of the 2D gaussian
191
+ x0: (float) the central position of the gaussian
192
+ dx: (float) :the FWHM of the gaussian
193
+ y: (ndarray) second axis of the 2D gaussian
194
+ y0: (float) the central position of the gaussian
195
+ dy: (float) :the FWHM of the gaussian
196
+ n=1 : an integer to define hypergaussian, n=1 by default for regular gaussian
197
+ angle: (float) a float to rotate main axes, in degree
198
+
199
+ Returns
200
+ -------
201
+ out : ndarray 2 dimensions
202
+
203
+ """
204
+ if angle == 0:
205
+ data = np.transpose(np.outer(gauss1D(x, x0, dx, n), gauss1D(y, y0, dy, n)))
10
206
 
11
- def __getattr__(name):
12
- if hasattr(math_utils, name):
13
- return getattr(math_utils, name)
14
207
  else:
15
- raise AttributeError
208
+
209
+ theta = np.radians(angle)
210
+ c, s = np.cos(theta), np.sin(theta)
211
+ R = np.array(((c, -s), (s, c)))
212
+ (x0r, y0r) = tuple(R.dot(np.array([x0, y0])))
213
+
214
+ data = np.zeros((len(y), len(x)))
215
+
216
+ for indx, xtmp in enumerate(x):
217
+ for indy, ytmp in enumerate(y):
218
+ rotatedvect = R.dot(np.array([xtmp, ytmp]))
219
+ data[indy, indx] = gauss1D(rotatedvect[0], x0r, dx, n) * gauss1D(rotatedvect[1], y0r, dy, n)
220
+
221
+ return data
222
+
223
+
224
+ def ftAxis(Npts, omega_max):
225
+ """
226
+ Given two numbers Npts,omega_max, return two vectors spanning the temporal
227
+ and spectral range. They are related by Fourier Transform
228
+
229
+ Parameters
230
+ ----------
231
+ Npts: (int)
232
+ A number of points defining the length of both grids
233
+ omega_max: (float)
234
+ The maximum circular frequency in the spectral domain. its unit defines
235
+ the temporal units. ex: omega_max in rad/fs implies time_grid in fs
236
+
237
+ Returns
238
+ -------
239
+ omega_grid: (ndarray)
240
+ The spectral axis of the FFT
241
+ time_grid: (ndarray))
242
+ The temporal axis of the FFT
243
+ See Also
244
+ --------
245
+ ftAxis, ftAxis_time, ift, ft2, ift2
246
+ """
247
+ if not isinstance(Npts, int):
248
+ raise TypeError('n should be a positive integer, if possible power of 2')
249
+ elif Npts < 1:
250
+ raise ValueError('n should be a strictly positive integer')
251
+ dT = 2 * np.pi / (2 * omega_max)
252
+ omega_grid = np.linspace(-omega_max, omega_max, Npts)
253
+ time_grid = dT * np.linspace(-(Npts - 1) / 2, (Npts - 1) / 2, Npts)
254
+ return omega_grid, time_grid
255
+
256
+
257
+ def ftAxis_time(Npts, time_max):
258
+ """
259
+ Given two numbers Npts,omega_max, return two vectors spanning the temporal
260
+ and spectral range. They are related by Fourier Transform
261
+
262
+ Parameters
263
+ ----------
264
+ Npts : number
265
+ A number of points defining the length of both grids
266
+ time_max : number
267
+ The maximum tmporal window
268
+
269
+ Returns
270
+ -------
271
+ omega_grid : vector
272
+ The spectral axis of the FFT
273
+ time_grid : vector
274
+ The temporal axis of the FFT
275
+ See Also
276
+ --------
277
+ ftAxis, ftAxis_time, ift, ft2, ift2
278
+ """
279
+ if not isinstance(Npts, int):
280
+ raise TypeError('n should be a positive integer, if possible power of 2')
281
+ elif Npts < 1:
282
+ raise ValueError('n should be a strictly positive integer')
283
+ dT = time_max / Npts
284
+ omega_max = (Npts - 1) / 2 * 2 * np.pi / time_max
285
+ omega_grid = np.linspace(-omega_max, omega_max, Npts)
286
+ time_grid = dT * np.linspace(-(Npts - 1) / 2, (Npts - 1) / 2, Npts)
287
+ return omega_grid, time_grid
288
+
289
+
290
+ def ft(x, dim=-1):
291
+ """
292
+ Process the 1D fast fourier transform and swaps the axis to get coorect results using ftAxis
293
+ Parameters
294
+ ----------
295
+ x: (ndarray) the array on which the FFT should be done
296
+ dim: the axis over which is done the FFT (default is the last of the array)
297
+
298
+ Returns
299
+ -------
300
+ See Also
301
+ --------
302
+ ftAxis, ftAxis_time, ift, ft2, ift2
303
+ """
304
+ if not isinstance(dim, int):
305
+ raise TypeError('dim should be an integer specifying the array dimension over which to do the calculation')
306
+ assert isinstance(x, np.ndarray)
307
+ assert dim >= -1
308
+ assert dim <= len(x.shape) - 1
309
+
310
+ out = np.fft.fftshift(np.fft.fft(np.fft.fftshift(x, axes=dim), axis=dim), axes=dim)
311
+ return out
312
+
313
+
314
+ def ift(x, dim=0):
315
+ """
316
+ Process the inverse 1D fast fourier transform and swaps the axis to get correct results using ftAxis
317
+ Parameters
318
+ ----------
319
+ x: (ndarray) the array on which the FFT should be done
320
+ dim: the axis over which is done the FFT (default is the last of the array)
321
+
322
+ Returns
323
+ -------
324
+ See Also
325
+ --------
326
+ ftAxis, ftAxis_time, ift, ft2, ift2
327
+ """
328
+ if not isinstance(dim, int):
329
+ raise TypeError('dim should be an integer specifying the array dimension over which to do the calculation')
330
+ assert isinstance(x, np.ndarray)
331
+ assert dim >= -1
332
+ assert dim <= len(x.shape) - 1
333
+ out = np.fft.fftshift(np.fft.ifft(np.fft.fftshift(x, axes=dim), axis=dim), axes=dim)
334
+ return out
335
+
336
+
337
+ def ft2(x, dim=(-2, -1)):
338
+ """
339
+ Process the 2D fast fourier transform and swaps the axis to get correct results using ftAxis
340
+ Parameters
341
+ ----------
342
+ x: (ndarray) the array on which the FFT should be done
343
+ dim: the axis over which is done the FFT (default is the last of the array)
344
+
345
+ Returns
346
+ -------
347
+ See Also
348
+ --------
349
+ ftAxis, ftAxis_time, ift, ft2, ift2
350
+ """
351
+ assert isinstance(x, np.ndarray)
352
+ if hasattr(dim, '__iter__'):
353
+ for d in dim:
354
+ if not isinstance(d, int):
355
+ raise TypeError(
356
+ 'elements in dim should be an integer specifying the array dimension over which to do the calculation')
357
+ assert d <= len(x.shape)
358
+ else:
359
+ if not isinstance(dim, int):
360
+ raise TypeError(
361
+ 'elements in dim should be an integer specifying the array dimension over which to do the calculation')
362
+ assert dim <= len(x.shape)
363
+ out = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(x, axes=dim)), axes=dim)
364
+ return out
365
+
366
+
367
+ def ift2(x, dim=(-2, -1)):
368
+ """
369
+ Process the inverse 2D fast fourier transform and swaps the axis to get correct results using ftAxis
370
+ Parameters
371
+ ----------
372
+ x: (ndarray) the array on which the FFT should be done
373
+ dim: the axis (or a tuple of axes) over which is done the FFT (default is the last of the array)
374
+
375
+ Returns
376
+ -------
377
+ See Also
378
+ --------
379
+ ftAxis, ftAxis_time, ift, ft2, ift2
380
+ """
381
+ assert isinstance(x, np.ndarray)
382
+ if hasattr(dim, '__iter__'):
383
+ for d in dim:
384
+ if not isinstance(d, int):
385
+ raise TypeError(
386
+ 'elements in dim should be an integer specifying the array dimension over which to do the calculation')
387
+ assert d <= len(x.shape)
388
+ else:
389
+ if not isinstance(dim, int):
390
+ raise TypeError(
391
+ 'elements in dim should be an integer specifying the array dimension over which to do the calculation')
392
+ assert dim <= len(x.shape)
393
+ out = np.fft.fftshift(np.fft.ifft2(np.fft.fftshift(x, axes=dim)), axes=dim)
394
+ return out
395
+
396
+
397
+ def flatten(xs):
398
+ """Flatten nested list"""
399
+ for x in xs:
400
+ if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
401
+ yield from flatten(x)
402
+ else:
403
+ yield x
404
+
405
+ class LSqEllipse:
406
+
407
+ def fit(self, data):
408
+ """Lest Squares fitting algorithm
409
+
410
+ Theory taken from (*)
411
+ Solving equation Sa=lCa. with a = |a b c d f g> and a1 = |a b c>
412
+ a2 = |d f g>
413
+
414
+ Args
415
+ ----
416
+ data (list:list:float): list of two lists containing the x and y data of the
417
+ ellipse. of the form [[x1, x2, ..., xi],[y1, y2, ..., yi]]
418
+
419
+ Returns
420
+ ------
421
+ coef (list): list of the coefficients describing an ellipse
422
+ [a,b,c,d,f,g] corresponding to ax**2+2bxy+cy**2+2dx+2fy+g
423
+ """
424
+ x, y = numpy.asarray(data, dtype=float)
425
+
426
+ # Quadratic part of design matrix [eqn. 15] from (*)
427
+ D1 = numpy.mat(numpy.vstack([x ** 2, x * y, y ** 2])).T
428
+ # Linear part of design matrix [eqn. 16] from (*)
429
+ D2 = numpy.mat(numpy.vstack([x, y, numpy.ones(len(x))])).T
430
+
431
+ # forming scatter matrix [eqn. 17] from (*)
432
+ S1 = D1.T * D1
433
+ S2 = D1.T * D2
434
+ S3 = D2.T * D2
435
+
436
+ # Constraint matrix [eqn. 18]
437
+ C1 = numpy.mat('0. 0. 2.; 0. -1. 0.; 2. 0. 0.')
438
+
439
+ # Reduced scatter matrix [eqn. 29]
440
+ M = C1.I * (S1 - S2 * S3.I * S2.T)
441
+
442
+ # M*|a b c >=l|a b c >. Find eigenvalues and eigenvectors from this equation [eqn. 28]
443
+ eval, evec = numpy.linalg.eig(M)
444
+
445
+ # eigenvector must meet constraint 4ac - b^2 to be valid.
446
+ cond = 4 * numpy.multiply(evec[0, :], evec[2, :]) - numpy.power(evec[1, :], 2)
447
+ a1 = evec[:, numpy.nonzero(cond.A > 0)[1]]
448
+
449
+ # |d f g> = -S3^(-1)*S2^(T)*|a b c> [eqn. 24]
450
+ a2 = -S3.I * S2.T * a1
451
+
452
+ # eigenvectors |a b c d f g>
453
+ self.coef = numpy.vstack([a1, a2])
454
+ self._save_parameters()
455
+
456
+ def _save_parameters(self):
457
+ """finds the important parameters of the fitted ellipse
458
+
459
+ Theory taken form http://mathworld.wolfram
460
+
461
+ Args
462
+ -----
463
+ coef (list): list of the coefficients describing an ellipse
464
+ [a,b,c,d,f,g] corresponding to ax**2+2bxy+cy**2+2dx+2fy+g
465
+
466
+ Returns
467
+ _______
468
+ center (List): of the form [x0, y0]
469
+ width (float): major axis
470
+ height (float): minor axis
471
+ phi (float): rotation of major axis form the x-axis in radians
472
+ """
473
+
474
+ # eigenvectors are the coefficients of an ellipse in general form
475
+ # a*x^2 + 2*b*x*y + c*y^2 + 2*d*x + 2*f*y + g = 0 [eqn. 15) from (**) or (***)
476
+ a = self.coef[0, 0]
477
+ b = self.coef[1, 0] / 2.
478
+ c = self.coef[2, 0]
479
+ d = self.coef[3, 0] / 2.
480
+ f = self.coef[4, 0] / 2.
481
+ g = self.coef[5, 0]
482
+
483
+ # finding center of ellipse [eqn.19 and 20] from (**)
484
+ x0 = (c * d - b * f) / (b ** 2. - a * c)
485
+ y0 = (a * f - b * d) / (b ** 2. - a * c)
486
+
487
+ # Find the semi-axes lengths [eqn. 21 and 22] from (**)
488
+ numerator = 2 * (a * f * f + c * d * d + g * b * b - 2 * b * d * f - a * c * g)
489
+ denominator1 = (b * b - a * c) * ((c - a) * numpy.sqrt(1 + 4 * b * b / ((a - c) * (a - c))) - (c + a))
490
+ denominator2 = (b * b - a * c) * ((a - c) * numpy.sqrt(1 + 4 * b * b / ((a - c) * (a - c))) - (c + a))
491
+ width = numpy.sqrt(numerator / denominator1)
492
+ height = numpy.sqrt(numerator / denominator2)
493
+
494
+ # angle of counterclockwise rotation of major-axis of ellipse to x-axis [eqn. 23] from (**)
495
+ # or [eqn. 26] from (***).
496
+ phi = .5 * numpy.arctan((2. * b) / (a - c))
497
+
498
+ self._center = [x0, y0]
499
+ self._width = width
500
+ self._height = height
501
+ self._phi = phi
502
+
503
+ @property
504
+ def center(self):
505
+ return self._center
506
+
507
+ @property
508
+ def width(self):
509
+ return self._width
510
+
511
+ @property
512
+ def height(self):
513
+ return self._height
514
+
515
+ @property
516
+ def phi(self):
517
+ """angle of counterclockwise rotation of major-axis of ellipse to x-axis
518
+ [eqn. 23] from (**)
519
+ """
520
+ return self._phi
521
+
522
+ def parameters(self):
523
+ return self.center, self.width, self.height, self.phi
524
+
525
+
526
+ def make_test_ellipse(center=[1, 1], width=1, height=.6, phi=3.14 / 5):
527
+ """Generate Elliptical data with noise
528
+
529
+ Args
530
+ ----
531
+ center (list:float): (<x_location>, <y_location>)
532
+ width (float): semimajor axis. Horizontal dimension of the ellipse (**)
533
+ height (float): semiminor axis. Vertical dimension of the ellipse (**)
534
+ phi (float:radians): tilt of the ellipse, the angle the semimajor axis
535
+ makes with the x-axis
536
+
537
+ Returns
538
+ -------
539
+ data (list:list:float): list of two lists containing the x and y data of the
540
+ ellipse. of the form [[x1, x2, ..., xi],[y1, y2, ..., yi]]
541
+ """
542
+ t = numpy.linspace(0, 2 * numpy.pi, 1000)
543
+ x_noise, y_noise = numpy.random.rand(2, len(t))
544
+
545
+ ellipse_x = center[0] + width * numpy.cos(t) * numpy.cos(phi) - height * numpy.sin(t) * numpy.sin(
546
+ phi) + x_noise / 2.
547
+ ellipse_y = center[1] + width * numpy.cos(t) * numpy.sin(phi) + height * numpy.sin(t) * numpy.cos(
548
+ phi) + y_noise / 2.
549
+
550
+ return [ellipse_x, ellipse_y]
551
+
@@ -6,6 +6,10 @@ def deprecation_msg(message, stacklevel=2):
6
6
  warnings.warn(message, DeprecationWarning, stacklevel=stacklevel)
7
7
 
8
8
 
9
+ def user_warning(message, stacklevel=3):
10
+ warnings.warn(message, UserWarning, stacklevel=stacklevel)
11
+
12
+
9
13
  MESSAGE_SEVERITIES = ['critical', 'information', 'question', 'warning']
10
14
 
11
15
 
@@ -51,7 +55,7 @@ def show_message(message="blabla", title="Error"):
51
55
 
52
56
  if __name__ == '__main__':
53
57
  import sys
54
- from pymodaq.daq_utils.plotting.data_viewers.viewer1D import Viewer1D
58
+ from pymodaq.utils.plotting.data_viewers.viewer1D import Viewer1D
55
59
  app = QtWidgets.QApplication([])
56
60
  widget = QtWidgets.QWidget()
57
61
  viewer = Viewer1D(widget)
@@ -1,15 +1,2 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Created the 27/10/2022
4
-
5
- @author: Sebastien Weber
6
- """
7
-
8
- from pymodaq.daq_utils import parameter
9
-
10
-
11
- def __getattr__(name):
12
- if hasattr(parameter, name):
13
- return getattr(parameter, name)
14
- else:
15
- raise AttributeError
1
+ from pyqtgraph.parametertree import parameterTypes, Parameter, ParameterTree
2
+ from . import pymodaq_ptypes
@@ -90,7 +90,7 @@ def add_text_to_elt(elt, param):
90
90
  elif isinstance(param.value(), float):
91
91
  text = 'float({})'.format(param.value())
92
92
  else:
93
- str(param.value())
93
+ text = str(param.value())
94
94
  elif param_type == 'int':
95
95
  if param.value() is True: # known bug is True should be clearly specified here
96
96
  val = 1
@@ -274,13 +274,19 @@ def elt_to_dict(el):
274
274
  param.update(dict(addText=addText))
275
275
 
276
276
  if 'limits' in el.attrib.keys():
277
- values = list(eval(el.get('limits'))) # make sure the evaluated values are returned as list (in case another
278
- # iterator type has been used)
279
- param.update(dict(values=values))
277
+ try:
278
+ values = list(eval(el.get('limits'))) # make sure the evaluated values are returned as list (in case another
279
+ # iterator type has been used
280
+ param.update(dict(values=values))
281
+ except:
282
+ pass
280
283
 
281
284
  if 'limits' in el.attrib.keys():
282
- limits = eval(el.get('limits'))
283
- param.update(dict(limits=limits))
285
+ try:
286
+ limits = eval(el.get('limits'))
287
+ param.update(dict(limits=limits))
288
+ except:
289
+ pass
284
290
 
285
291
  return param
286
292
 
@@ -1,4 +1,4 @@
1
- from pyqtgraph.parametertree.parameterTypes.basetypes import SimpleParameter, GroupParameter
1
+ from pyqtgraph.parametertree.parameterTypes.basetypes import SimpleParameter, GroupParameter, GroupParameterItem
2
2
  from .bool import BoolPushParameterItem
3
3
  from .pixmap import PixmapParameterItem, PixmapCheckParameterItem
4
4
  from .slide import SliderSpinBox, SliderParameterItem
@@ -14,8 +14,6 @@ from .numeric import NumericParameter
14
14
 
15
15
  from pyqtgraph.parametertree.Parameter import registerParameterType, registerParameterItemType
16
16
 
17
- GroupParameterCustom = GroupParameter
18
-
19
17
  registerParameterType('float', NumericParameter, override=True)
20
18
  registerParameterType('int', NumericParameter, override=True)
21
19
  registerParameterItemType('bool_push', BoolPushParameterItem, SimpleParameter, override=True)
@@ -81,7 +81,7 @@ class FileDirWidget(QtWidgets.QWidget):
81
81
  """
82
82
 
83
83
  self.hor_layout = QtWidgets.QHBoxLayout()
84
- self.base_path_edit = QtWidgets.QPlainTextEdit(str(self.path))
84
+ self.base_path_edit = QtWidgets.QPlainTextEdit(self.path)
85
85
  self.base_path_edit.setMaximumHeight(50)
86
86
  self.base_path_browse_pb = QtWidgets.QPushButton()
87
87
  self.base_path_browse_pb.setText("")
@@ -86,6 +86,9 @@ class ItemSelectParameterItem(WidgetParameterItem):
86
86
  opts = self.param.opts
87
87
  w = ItemSelect_pb()
88
88
  w.itemselect.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
89
+ if 'minheight' in opts:
90
+ w.itemselect.setMinimumHeight(opts['min_height'])
91
+
89
92
  if 'height' in opts:
90
93
  w.itemselect.setMaximumHeight(opts['height'])
91
94
  else:
@@ -1,5 +1,5 @@
1
1
  from pyqtgraph.parametertree.parameterTypes.basetypes import WidgetParameterItem, SimpleParameter
2
- from pymodaq.daq_utils.gui_utils.widgets import QLED
2
+ from pymodaq.utils.gui_utils.widgets import QLED
3
3
 
4
4
 
5
5
  class LedParameterItem(WidgetParameterItem):