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
@@ -1,15 +1,835 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- Created the 27/10/2022
1
+ import os
2
+ import sys
3
+ import datetime
4
+ import importlib
5
+ import inspect
6
+ import json
7
+ import functools
8
+ import re
9
+ import time
10
+ import warnings
4
11
 
5
- @author: Sebastien Weber
6
- """
12
+ from packaging import version as version_mod
13
+ from pathlib import Path
14
+ import pkgutil
15
+ import traceback
7
16
 
8
- from pymodaq.daq_utils import daq_utils
17
+ import numpy as np
18
+ from qtpy import QtCore
19
+ from qtpy.QtCore import QLocale
20
+
21
+ from pymodaq.utils import logger as logger_module
22
+ from pymodaq.utils.config import get_set_preset_path, Config
23
+ from pymodaq.utils.messenger import deprecation_msg
24
+ from pymodaq.utils.qvariant import QVariant
25
+
26
+
27
+ python_version = f'{str(sys.version_info.major)}.{str(sys.version_info.minor)}'
28
+ if version_mod.parse(python_version) >= version_mod.parse('3.8'): # from version 3.8 this feature is included in the
29
+ # standard lib
30
+ from importlib import metadata
31
+ else:
32
+ import importlib_metadata as metadata # pragma: no cover
33
+
34
+ logger = logger_module.set_logger(logger_module.get_module_name(__file__))
35
+
36
+ plot_colors = [(255, 255, 255), (255, 0, 0), (0, 255, 0), (0, 0, 255), (14, 207, 189), (207, 14, 166), (207, 204, 14)]
37
+ config = Config()
9
38
 
10
39
 
11
40
  def __getattr__(name):
12
- if hasattr(daq_utils, name):
13
- return getattr(daq_utils, name)
41
+ if name in ['Axis', 'NavAxis', 'ScaledAxis', 'ScalingOptions', 'Data', 'DataTimeStamped', 'DataFromPlugins',
42
+ 'DataToEmit', 'DataToExport']:
43
+ data_mod = importlib.import_module('.data', 'pymodaq.utils')
44
+ deprecation_msg('Loading Axis or Data and their derived classes from daq_utils is deprecated, import them from'
45
+ ' pymodaq.utils.data module', 3)
46
+ return getattr(data_mod, name)
14
47
  else:
15
48
  raise AttributeError
49
+
50
+
51
+ def load_config():
52
+ deprecation_msg(f'config methods must now be imported from the pymodaq.utils.messenger.cnfig module')
53
+ return Config()
54
+
55
+
56
+ def set_logger(*args, **kwargs):
57
+ deprecation_msg(f'Logger methods must now be imported from the pymodaq.utils.logger module', 3)
58
+ return logger_module.set_logger(*args, **kwargs)
59
+
60
+
61
+ def get_module_name(*args, **kwargs):
62
+ deprecation_msg(f'Logger methods must now be imported from the pymodaq.utils.logger module', 3)
63
+ return logger_module.get_module_name(*args, **kwargs)
64
+
65
+
66
+ ## data classes deprecated calls
67
+
68
+
69
+
70
+ #################################
71
+
72
+ def is_64bits():
73
+ return sys.maxsize > 2**32
74
+
75
+
76
+ def timer(func):
77
+ """Print the runtime of the decorated function"""
78
+ @functools.wraps(func)
79
+ def wrapper_timer(*args, **kwargs):
80
+ start_time = time.perf_counter() # 1
81
+ value = func(*args, **kwargs)
82
+ end_time = time.perf_counter() # 2
83
+ run_time = end_time - start_time # 3
84
+ print(f"Finished {func.__name__!r} in {run_time:.4f} secs")
85
+ return value
86
+ return wrapper_timer
87
+
88
+
89
+ def get_version():
90
+ """Obtain pymodaq version from the VERSION file
91
+
92
+ Follows the layout from the packaging tool hatch, hatchling
93
+ """
94
+ DEFAULT_PATTERN = r'(?i)^(__version__|VERSION) *= *([\'"])v?(?P<version>.+?)\2'
95
+
96
+ with open(str(Path(__file__).parent.parent.joinpath('resources/VERSION')), 'r') as fvers:
97
+ contents = fvers.read().strip()
98
+ match = re.search(DEFAULT_PATTERN, contents, flags=re.MULTILINE)
99
+ groups = match.groupdict()
100
+ if 'version' not in groups:
101
+ raise ValueError('no group named `version` was defined in the pattern')
102
+ return groups['version']
103
+
104
+
105
+ def copy_preset(): # pragma: no cover
106
+ path = get_set_preset_path().joinpath('preset_default.xml')
107
+ if not path.exists(): # copy the preset_default from pymodaq folder and create one in pymodad's local folder
108
+ with open(str(Path(__file__).parent.parent.joinpath('resources/preset_default.xml')), 'r') as file:
109
+ path.write_text(file.read())
110
+
111
+
112
+ def set_qt_backend():
113
+ backend_present = True
114
+ if config('qtbackend', 'backend').lower() not in [mod.lower() for mod in sys.modules]:
115
+ backend_present = False
116
+ logger.warning(f"The chosen Qt backend ({config('qtbackend', 'backend')}) has not been installed...\n"
117
+ f"Trying another...")
118
+ backends = config('qtbackend', 'backends')
119
+ backends.pop(config('qtbackend', 'backend'))
120
+ for backend in backends:
121
+ if backend.lower() in [mod.lower() for mod in sys.modules]:
122
+ backend_present = True
123
+ break
124
+
125
+ if backend_present:
126
+ os.environ['QT_API'] = config('qtbackend', 'backend')
127
+ logger.info('************************')
128
+ logger.info(f"{config('qtbackend', 'backend')} Qt backend loaded")
129
+ logger.info('************************')
130
+ else:
131
+ msg = f"No Qt backend could be found in your system, please install either pyqt5/6 or pyside2/6." \
132
+ f"pyqt5 is still preferred, while pyqt6 should mostly work."
133
+ logger.critical(msg)
134
+ warnings.warn(msg, FutureWarning, 3)
135
+ print(msg.upper())
136
+
137
+
138
+ class JsonConverter:
139
+ def __init__(self):
140
+ super().__init__()
141
+
142
+ @classmethod
143
+ def trusted_types(cls):
144
+ return ['float', 'int', 'str', 'datetime', 'date', 'time', 'tuple', 'list', 'bool', 'bytes',
145
+ 'float64']
146
+
147
+ @classmethod
148
+ def istrusted(cls, type_name):
149
+ return type_name in cls.trusted_types()
150
+
151
+ @classmethod
152
+ def object2json(cls, obj):
153
+ dic = dict(module=type(obj).__module__, type=type(obj).__name__, data=repr(obj))
154
+ return json.dumps(dic)
155
+
156
+ @classmethod
157
+ def json2object(cls, jsonstring):
158
+ try:
159
+ dic = json.loads(jsonstring)
160
+ if isinstance(dic, dict):
161
+ if dic['type'] in cls.trusted_types():
162
+ return eval(dic['data'])
163
+ else:
164
+ return dic
165
+ else: # pragma: no cover
166
+ return dic
167
+ except Exception:
168
+ return jsonstring
169
+
170
+
171
+ def decode_data(encoded_data):
172
+ """
173
+ Decode QbyteArrayData generated when drop items in table/tree/list view
174
+ Parameters
175
+ ----------
176
+ encoded_data: QByteArray
177
+ Encoded data of the mime data to be dropped
178
+ Returns
179
+ -------
180
+ data: list
181
+ list of dict whose key is the QtRole in the Model, and the value a QVariant
182
+
183
+ """
184
+ data = []
185
+
186
+ ds = QtCore.QDataStream(encoded_data, QtCore.QIODevice.ReadOnly)
187
+ while not ds.atEnd():
188
+ row = ds.readInt32()
189
+ col = ds.readInt32()
190
+
191
+ map_items = ds.readInt32()
192
+ item = {}
193
+ for ind in range(map_items):
194
+ key = ds.readInt32()
195
+ #TODO check this is fine
196
+ value = QVariant()
197
+ #value = None
198
+ ds >> value
199
+ item[QtCore.Qt.ItemDataRole(key)] = value.value()
200
+ data.append(item)
201
+ return data
202
+
203
+
204
+ #############################
205
+
206
+ def capitalize(string, Nfirst=1):
207
+ """
208
+ Returns same string but with first Nfirst letters upper
209
+ Parameters
210
+ ----------
211
+ string: (str)
212
+ Nfirst: (int)
213
+ Returns
214
+ -------
215
+ str
216
+ """
217
+ return string[:Nfirst].upper() + string[Nfirst:]
218
+
219
+
220
+ def uncapitalize(string, Nfirst=1):
221
+ return string[:Nfirst].lower() + string[Nfirst:]
222
+
223
+
224
+ def get_data_dimension(arr: np.ndarray, scan_type='scan1D', remove_scan_dimension=False):
225
+ dimension = len(arr.shape)
226
+ if dimension == 1:
227
+ if arr.size == 1:
228
+ dimension = 0
229
+
230
+ if remove_scan_dimension:
231
+ if scan_type.lower() == 'scan1d':
232
+ dimension -= 1
233
+ elif scan_type.lower() == 'scan2d':
234
+ dimension -= 2
235
+ else:
236
+ if dimension > 2:
237
+ dimension = 'N'
238
+ return arr.shape, f'{dimension}D', arr.size
239
+
240
+
241
+ def getLineInfo():
242
+ """get information about where the Exception has been triggered"""
243
+ tb = sys.exc_info()[2]
244
+ res = ''
245
+ for t in traceback.format_tb(tb):
246
+ res += t
247
+ return res
248
+
249
+
250
+ class ThreadCommand:
251
+ """Generic object to pass info (command) and data (attribute) between thread or objects using signals
252
+
253
+ Parameters
254
+ ----------
255
+ command: str
256
+ The command to be analysed for further action
257
+ attribute: any type
258
+ the attribute related to the command. The actual type and value depend on the command and the situation
259
+ attributes: deprecated, attribute should be used instead
260
+
261
+ Attributes
262
+ ----------
263
+ command : str
264
+ The command to be analysed for further action
265
+ attribute : any type
266
+ the attribute related to the command. The actual type and value depend on the command and the situation
267
+ """
268
+
269
+ def __init__(self, command: str, attribute=None, attributes=None):
270
+ if not isinstance(command, str):
271
+ raise TypeError(f'The command in a Threadcommand object should be a string, not a {type(command)}')
272
+ self.command = command
273
+ if attribute is None and attributes is not None:
274
+ deprecation_msg('ThreadCommand signature changed, use attribute in place of attribute')
275
+ self.attribute = attributes
276
+ self.attributes = attributes
277
+ self.attribute = attribute
278
+
279
+ def __repr__(self):
280
+ return f'Threadcommand: {self.command} with attribute {self.attribute}'
281
+
282
+
283
+ def ensure_ndarray(data):
284
+ """
285
+ Make sure data is returned as a numpy array
286
+ Parameters
287
+ ----------
288
+ data
289
+
290
+ Returns
291
+ -------
292
+ ndarray
293
+ """
294
+ if not isinstance(data, np.ndarray):
295
+ if isinstance(data, list):
296
+ data = np.array(data)
297
+ else:
298
+ data = np.array([data])
299
+ return data
300
+
301
+
302
+ def setLocale():
303
+ """
304
+ defines the Locale to use to convert numbers to strings representation using language/country conventions
305
+ Default is English and US
306
+ """
307
+ language = getattr(QLocale, config('style', 'language'))
308
+ country = getattr(QLocale, config('style', 'country'))
309
+ QLocale.setDefault(QLocale(language, country))
310
+
311
+
312
+ def recursive_find_files_extension(ini_path, ext, paths=[]):
313
+ with os.scandir(ini_path) as it:
314
+ for entry in it:
315
+ if os.path.splitext(entry.name)[1][1:] == ext and entry.is_file():
316
+ paths.append(entry.path)
317
+ elif entry.is_dir():
318
+ recursive_find_files_extension(entry.path, ext, paths)
319
+ return paths
320
+
321
+
322
+ def recursive_find_files(ini_path, exp='make_enum', paths=[],
323
+ filters=['build']):
324
+ for child in Path(ini_path).iterdir():
325
+ if child.is_dir():
326
+ recursive_find_files(child, exp, paths, filters)
327
+ else:
328
+ if exp in child.stem:
329
+ if not any([filt in str(child) for filt in filters]):
330
+ paths.append(child)
331
+ return paths
332
+
333
+
334
+ def recursive_find_expr_in_files(ini_path, exp='make_enum', paths=[],
335
+ filters=['.git', '.idea', '__pycache__', 'build', 'egg', 'documentation', '.tox'],
336
+ replace=False, replace_str=''):
337
+
338
+ for child in Path(ini_path).iterdir():
339
+ if not any(filt in str(child) for filt in filters):
340
+ if child.is_dir():
341
+ recursive_find_expr_in_files(child, exp, paths, filters, replace=replace, replace_str=replace_str)
342
+ else:
343
+ try:
344
+ found = False
345
+ with child.open('r') as f:
346
+ replacement = ''
347
+ for ind, line in enumerate(f):
348
+ if exp in line:
349
+ found = True
350
+ paths.append([child, ind, line])
351
+ if replace:
352
+ replacement += line.replace(exp, replace_str)
353
+ else:
354
+ if replace:
355
+ replacement += line
356
+ if replace and found:
357
+ with child.open('w') as f:
358
+ f.write(replacement)
359
+ except Exception:
360
+ pass
361
+ return paths
362
+
363
+
364
+ def count_lines(ini_path, count=0, filters=['lextab', 'yacctab','pycache', 'pyc']):
365
+ # if Path(ini_path).is_file():
366
+ # with Path(ini_path).open('r') as f:
367
+ # count += len(f.readlines())
368
+ # return count
369
+ for child in Path(ini_path).iterdir():
370
+ if child.is_dir():
371
+ count = count_lines(child, count)
372
+ else:
373
+ try:
374
+ if not any([filt in child.name for filt in filters]):
375
+ if '.py' in child.name:
376
+ with child.open('r') as f:
377
+ count += len(f.readlines())
378
+ else:
379
+ print(child.stem)
380
+ except Exception:
381
+ pass
382
+ return count
383
+
384
+
385
+ def remove_spaces(string):
386
+ """
387
+ return a string without any white spaces in it
388
+ Parameters
389
+ ----------
390
+ string
391
+
392
+ Returns
393
+ -------
394
+
395
+ """
396
+ return ''.join(string.split())
397
+
398
+
399
+ def rint(x):
400
+ """
401
+ almost same as numpy rint function but return an integer
402
+ Parameters
403
+ ----------
404
+ x: (float or integer)
405
+
406
+ Returns
407
+ -------
408
+ nearest integer
409
+ """
410
+ return int(np.rint(x))
411
+
412
+
413
+ def elt_as_first_element(elt_list, match_word='Mock'):
414
+ if not hasattr(elt_list, '__iter__'):
415
+ raise TypeError('elt_list must be an iterable')
416
+ if elt_list:
417
+ ind_elt = 0
418
+ for ind, elt in enumerate(elt_list):
419
+ if not isinstance(elt, str):
420
+ raise TypeError('elt_list must be a list of str')
421
+ if match_word in elt:
422
+ ind_elt = ind
423
+ break
424
+ plugin_match = elt_list[ind_elt]
425
+ elt_list.remove(plugin_match)
426
+ plugins = [plugin_match]
427
+ plugins.extend(elt_list)
428
+ else:
429
+ plugins = []
430
+ return plugins
431
+
432
+
433
+ def elt_as_first_element_dicts(elt_list, match_word='Mock', key='name'):
434
+ if not hasattr(elt_list, '__iter__'):
435
+ raise TypeError('elt_list must be an iterable')
436
+ if elt_list:
437
+ ind_elt = 0
438
+ for ind, elt in enumerate(elt_list):
439
+ if not isinstance(elt, dict):
440
+ raise TypeError('elt_list must be a list of dicts')
441
+ if match_word in elt[key]:
442
+ ind_elt = ind
443
+ break
444
+ plugin_match = elt_list[ind_elt]
445
+ elt_list.remove(plugin_match)
446
+ plugins = [plugin_match]
447
+ plugins.extend(elt_list)
448
+ else:
449
+ plugins = []
450
+ return plugins
451
+
452
+
453
+ def find_object_if_matched_attr_name_val(obj, attr_name, attr_value):
454
+ """check if an attribute key/value pair match in a given object
455
+
456
+ Parameters
457
+ ----------
458
+ obj: object
459
+ list of objects
460
+ attr_name: str
461
+ attribute name to look for in the object
462
+ attr_value: object
463
+ value to match
464
+
465
+ Returns
466
+ -------
467
+ bool: True if the key/value pair has been found in dict_tmp
468
+
469
+ """
470
+ if hasattr(obj, attr_name):
471
+ if getattr(obj, attr_name) == attr_value:
472
+ return True
473
+ return False
474
+
475
+
476
+ def find_objects_in_list_from_attr_name_val(objects, attr_name, attr_value, return_first=True):
477
+ """ lookup within a list of objects. Look for the objects within the list which has the correct attribute name,
478
+ value pair
479
+
480
+ Parameters
481
+ ----------
482
+ objects: list
483
+ list of objects
484
+ attr_name: str
485
+ attribute name to look for in the object
486
+ attr_value: object
487
+ value to match
488
+ return_first: bool
489
+ if True return the first objects found in the list else all the objects matching
490
+
491
+ Returns
492
+ -------
493
+ list of tuple(object, int): object and index or list of object and indexes
494
+ """
495
+ selection = []
496
+ obj = None
497
+ for ind, obj_tmp in enumerate(objects):
498
+ if find_object_if_matched_attr_name_val(obj_tmp, attr_name, attr_value):
499
+ obj = obj_tmp
500
+ if return_first:
501
+ break
502
+ else:
503
+ selection.append((obj_tmp, ind))
504
+
505
+ if obj is None:
506
+ if return_first:
507
+ return None, -1
508
+ else:
509
+ return []
510
+ else:
511
+ if return_first:
512
+ return obj, ind
513
+ else:
514
+ return selection
515
+
516
+
517
+ def find_dict_if_matched_key_val(dict_tmp, key, value):
518
+ """
519
+ check if a key/value pair match in a given dictionnary
520
+ Parameters
521
+ ----------
522
+ dict_tmp: (dict) the dictionnary to be tested
523
+ key: (str) a key string to look for in dict_tmp
524
+ value: (object) any python object
525
+
526
+ Returns
527
+ -------
528
+ bool: True if the key/value pair has been found in dict_tmp
529
+
530
+ """
531
+ if key in dict_tmp:
532
+ if dict_tmp[key] == value:
533
+ return True
534
+ return False
535
+
536
+
537
+
538
+
539
+ def find_dict_in_list_from_key_val(dicts, key, value, return_index=False):
540
+ """ lookup within a list of dicts. Look for the dict within the list which has the correct key, value pair
541
+
542
+ Parameters
543
+ ----------
544
+ dicts: (list) list of dictionnaries
545
+ key: (str) specific key to look for in each dict
546
+ value: value to match
547
+
548
+ Returns
549
+ -------
550
+ dict: if found otherwise returns None
551
+ """
552
+ for ind, dict_tmp in enumerate(dicts):
553
+ if find_dict_if_matched_key_val(dict_tmp, key, value):
554
+ if return_index:
555
+ return dict_tmp, ind
556
+ else:
557
+ return dict_tmp
558
+ if return_index:
559
+ return None, -1
560
+ else:
561
+ return None
562
+
563
+
564
+ def get_plugins(plugin_type='daq_0Dviewer'): # pragma: no cover
565
+ """
566
+ Get plugins names as a list
567
+ Parameters
568
+ ----------
569
+ plugin_type: (str) plugin type either 'daq_0Dviewer', 'daq_1Dviewer', 'daq_2Dviewer', 'daq_NDviewer' or 'daq_move'
570
+ module: (module) parent module of the plugins
571
+
572
+ Returns
573
+ -------
574
+
575
+ """
576
+ plugins_import = []
577
+ discovered_plugins = metadata.entry_points()['pymodaq.plugins']
578
+
579
+ for module in discovered_plugins:
580
+ try:
581
+ if plugin_type == 'daq_move':
582
+ submodule = importlib.import_module(f'{module.value}.daq_move_plugins', module.value)
583
+ else:
584
+ submodule = importlib.import_module(f'{module.value}.daq_viewer_plugins.plugins_{plugin_type[4:6]}',
585
+ module.value)
586
+ plugin_list = [{'name': mod[len(plugin_type) + 1:],
587
+ 'module': submodule} for mod in [mod[1] for
588
+ mod in pkgutil.iter_modules([submodule.path.parent])]
589
+ if plugin_type in mod]
590
+ # check if modules are importable
591
+
592
+ for mod in plugin_list:
593
+ try:
594
+ if plugin_type == 'daq_move':
595
+ importlib.import_module(f'{submodule.__package__}.daq_move_{mod["name"]}')
596
+ else:
597
+ importlib.import_module(f'{submodule.__package__}.daq_{plugin_type[4:6]}viewer_{mod["name"]}')
598
+ plugins_import.append(mod)
599
+ except Exception as e: # pragma: no cover
600
+ pass
601
+ except Exception as e: # pragma: no cover
602
+ logger.warning(str(e))
603
+
604
+ #add utility plugin for PID
605
+ if plugin_type == 'daq_move':
606
+ try:
607
+ submodule = importlib.import_module('pymodaq.pid')
608
+
609
+ plugins_import.append({'name': 'PID', 'module': submodule})
610
+
611
+ except Exception: # pragma: no cover
612
+ pass
613
+
614
+ plugins_import = elt_as_first_element_dicts(plugins_import, match_word='Mock', key='name')
615
+ return plugins_import
616
+
617
+
618
+ def check_vals_in_iterable(iterable1, iterable2):
619
+ assert len(iterable1) == len(iterable2)
620
+ iterable1 = list(iterable1) # so the assertion below is valid for any kind of iterable, list, tuple, ndarray...
621
+ iterable2 = list(iterable2)
622
+ for val1, val2 in zip(iterable1, iterable2):
623
+ assert val1 == val2
624
+
625
+
626
+ def caller_name(skip=2):
627
+ """Get a name of a caller in the format module.class.method
628
+
629
+ `skip` specifies how many levels of stack to skip while getting caller
630
+ name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.
631
+
632
+ An empty string is returned if skipped levels exceed stack height
633
+ """
634
+ stack = inspect.stack()
635
+ start = 0 + skip
636
+ if len(stack) < start + 1:
637
+ return ''
638
+ parentframe = stack[start][0]
639
+
640
+ name = []
641
+ module = inspect.getmodule(parentframe)
642
+ # `modname` can be None when frame is executed directly in console
643
+ # TODO(techtonik): consider using __main__
644
+ if module:
645
+ name.append(module.__name__)
646
+ # detect classname
647
+ if 'self' in parentframe.f_locals:
648
+ # I don't know any way to detect call from the object method
649
+ # XXX: there seems to be no way to detect static method call - it will
650
+ # be just a function call
651
+ name.append(parentframe.f_locals['self'].__class__.__name__)
652
+ codename = parentframe.f_code.co_name
653
+ if codename != '<module>': # top level usually
654
+ name.append(codename) # function or a method
655
+ del parentframe
656
+ return ".".join(name)
657
+
658
+
659
+ def zeros_aligned(n, align, dtype=np.uint32):
660
+ """
661
+ Get aligned memory array wih alignment align.
662
+ Parameters
663
+ ----------
664
+ n: (int) length in dtype bytes of memory
665
+ align: (int) memory alignment
666
+ dtype: (numpy.dtype) type of the stored memory elements
667
+
668
+ Returns
669
+ -------
670
+
671
+ """
672
+ dtype = np.dtype(dtype)
673
+ nbytes = n * dtype.itemsize
674
+ buff = np.zeros(nbytes + align, dtype=np.uint8)
675
+ start_index = -buff.ctypes.data % align
676
+ return buff[start_index:start_index + nbytes].view(dtype)
677
+
678
+
679
+ # ########################
680
+ # #File management
681
+
682
+ def get_new_file_name(base_path=Path(config('data_saving', 'h5file', 'save_path')), base_name='tttr_data'):
683
+ if isinstance(base_path, str):
684
+ base_path = Path(base_path)
685
+
686
+ today = datetime.datetime.now()
687
+
688
+ date = today.strftime('%Y%m%d')
689
+ year = today.strftime('%Y')
690
+ year_dir = base_path.joinpath(year)
691
+ if not year_dir.is_dir():
692
+ year_dir.mkdir()
693
+ curr_dir = base_path.joinpath(year, date)
694
+ if not curr_dir.is_dir():
695
+ curr_dir.mkdir()
696
+
697
+ files = []
698
+ for entry in curr_dir.iterdir():
699
+ if entry.name.startswith(base_name) and entry.is_file():
700
+ files.append(entry.stem)
701
+ files.sort()
702
+ if not files:
703
+ index = 0
704
+ else:
705
+ index = int(files[-1][-3:]) + 1
706
+
707
+ file = f'{base_name}_{index:03d}'
708
+ return file, curr_dir
709
+
710
+
711
+ # ##############
712
+ # Math utilities
713
+ # math utility functions, should now be imported from the math_utils module
714
+ import pymodaq.utils.math_utils as mutils
715
+
716
+ def my_moment(x, y):
717
+ deprecation_msg(f'my_moment function should now be imported from the {mutils.__name__} module', stacklevel=3)
718
+ return mutils.my_moment(x, y)
719
+
720
+ def normalize(x):
721
+ deprecation_msg(f'normalize function should now be imported from the {mutils.__name__} module', stacklevel=3)
722
+ return mutils.normalize(x)
723
+
724
+
725
+ def odd_even(x):
726
+ deprecation_msg(f'odd_even function should now be imported from the {mutils.__name__} module', stacklevel=3)
727
+ return mutils.odd_even(x)
728
+
729
+
730
+ def greater2n(x):
731
+ deprecation_msg(f'greater2n function should now be imported from the {mutils.__name__} module', stacklevel=3)
732
+ return mutils.greater2n(x)
733
+
734
+
735
+ def linspace_step(start, stop, step):
736
+ deprecation_msg(f'linspace_step function should now be imported from the {mutils.__name__} module', stacklevel=3)
737
+ return mutils.linspace_step(start, stop, step)
738
+
739
+
740
+ def linspace_step_N(start, step, Npts):
741
+ deprecation_msg(f'linspace_step_N function should now be imported from the {mutils.__name__} module', stacklevel=3)
742
+ return mutils.linspace_step_N(start, step, Npts)
743
+
744
+
745
+ def find_index(x, threshold):
746
+ deprecation_msg(f'find_index function should now be imported from the {mutils.__name__} module', stacklevel=3)
747
+ return mutils.find_index(x, threshold)
748
+
749
+
750
+ def find_common_index(x, y, x0, y0):
751
+ deprecation_msg(f'find_common_index function should now be imported from the {mutils.__name__} module', stacklevel=3)
752
+ return mutils.find_common_index(x, y, x0, y0)
753
+
754
+
755
+ def gauss1D(x, x0, dx, n=1):
756
+ deprecation_msg(f'gauss1D function should now be imported from the {mutils.__name__} module', stacklevel=3)
757
+ return mutils.gauss1D(x, x0, dx, n=n)
758
+
759
+
760
+ def gauss2D(x, x0, dx, y, y0, dy, n=1, angle=0):
761
+ deprecation_msg(f'gauss2D function should now be imported from the {mutils.__name__} module', stacklevel=3)
762
+ return mutils.gauss2D(x, x0, dx, y, y0, dy, n, angle)
763
+
764
+ def ftAxis(Npts, omega_max):
765
+ deprecation_msg(f'ftAxis function should now be imported from the {mutils.__name__} module', stacklevel=3)
766
+ return mutils.ftAxis(Npts, omega_max)
767
+
768
+
769
+ def ftAxis_time(Npts, time_max):
770
+ deprecation_msg(f'ftAxis_time function should now be imported from the {mutils.__name__} module', stacklevel=3)
771
+ return mutils.ftAxis_time(Npts, time_max)
772
+
773
+
774
+ def ft(x, dim=-1):
775
+ deprecation_msg(f'ft function should now be imported from the {mutils.__name__} module', stacklevel=3)
776
+ return mutils.ft(x, dim)
777
+
778
+
779
+ def ift(x, dim=0):
780
+ deprecation_msg(f'ift function should now be imported from the {mutils.__name__} module', stacklevel=3)
781
+ return mutils.ift(x, dim)
782
+
783
+
784
+ def ft2(x, dim=(-2, -1)):
785
+ deprecation_msg(f'ft2 function should now be imported from the {mutils.__name__} module', stacklevel=3)
786
+ return mutils.ft2(x, dim)
787
+
788
+
789
+ def ift2(x, dim=(-2, -1)):
790
+ deprecation_msg(f'ift2 function should now be imported from the {mutils.__name__} module', stacklevel=3)
791
+ return mutils.ift2(x, dim)
792
+
793
+
794
+
795
+
796
+ if __name__ == '__main__':
797
+ #paths = recursive_find_expr_in_files('C:\\Users\\weber\\Labo\\Programmes Python\\PyMoDAQ_Git', 'visa')
798
+ # for p in paths:
799
+ # print(str(p))
800
+ # v = get_version()
801
+ # pass
802
+ #plugins = get_plugins() # pragma: no cover
803
+ #extensions = get_extension()
804
+ #models = get_models()
805
+ #count = count_lines('C:\\Users\\weber\\Labo\\Programmes Python\\PyMoDAQ_Git\\pymodaq\src')
806
+
807
+
808
+ # import license
809
+ # mit = license.find('MIT')
810
+ #
811
+
812
+ paths = recursive_find_expr_in_files(r'C:\Users\weber\Labo\Programmes Python\PyMoDAQ_Git',
813
+ exp="cfunc",
814
+ paths=[],
815
+ filters=['.git', '.idea', '__pycache__', 'build', 'egg', 'documentation',
816
+ '.tox',],
817
+ replace=False,
818
+ replace_str="pymodaq.utils")
819
+ get_version()
820
+ pass
821
+ # paths = recursive_find_files('C:\\Users\\weber\\Labo\\Programmes Python\\PyMoDAQ_Git',
822
+ # exp='VERSION', paths=[])
823
+ # import version
824
+ # for file in paths:
825
+ # with open(str(file), 'r') as f:
826
+ # v = version.Version(f.read())
827
+ # v.minor += 1
828
+ # v.patch = 0
829
+ # with open(str(file), 'w') as f:
830
+ # f.write(str(v))
831
+
832
+ # for file in paths:
833
+ # with open(str(file), 'w') as f:
834
+ # f.write(mit.render(name='Sebastien Weber', email='sebastien.weber@cemes.fr'))
835
+