pymodaq 5.1.6__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.
Files changed (154) hide show
  1. pymodaq/__init__.py +98 -0
  2. pymodaq/control_modules/__init__.py +1 -0
  3. pymodaq/control_modules/daq_move.py +1238 -0
  4. pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
  5. pymodaq/control_modules/daq_move_ui/factory.py +48 -0
  6. pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
  7. pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
  8. pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
  9. pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
  10. pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
  11. pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
  12. pymodaq/control_modules/daq_viewer.py +1517 -0
  13. pymodaq/control_modules/daq_viewer_ui.py +407 -0
  14. pymodaq/control_modules/mocks.py +57 -0
  15. pymodaq/control_modules/move_utility_classes.py +1141 -0
  16. pymodaq/control_modules/thread_commands.py +137 -0
  17. pymodaq/control_modules/ui_utils.py +72 -0
  18. pymodaq/control_modules/utils.py +591 -0
  19. pymodaq/control_modules/viewer_utility_classes.py +670 -0
  20. pymodaq/daq_utils/__init__.py +0 -0
  21. pymodaq/daq_utils/daq_utils.py +6 -0
  22. pymodaq/dashboard.py +2396 -0
  23. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
  24. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
  25. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
  26. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
  27. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
  28. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
  29. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
  30. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
  31. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
  32. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
  33. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
  34. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
  35. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
  36. pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
  37. pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
  38. pymodaq/examples/__init__.py +0 -0
  39. pymodaq/examples/function_plotter.py +160 -0
  40. pymodaq/examples/nonlinearscanner.py +126 -0
  41. pymodaq/examples/qt_less_standalone_module.py +165 -0
  42. pymodaq/examples/tcp_client.py +97 -0
  43. pymodaq/extensions/__init__.py +25 -0
  44. pymodaq/extensions/adaptive/__init__.py +2 -0
  45. pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
  46. pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
  47. pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
  48. pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
  49. pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
  50. pymodaq/extensions/adaptive/utils.py +123 -0
  51. pymodaq/extensions/bayesian/__init__.py +2 -0
  52. pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
  53. pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
  54. pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
  55. pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
  56. pymodaq/extensions/bayesian/utils.py +180 -0
  57. pymodaq/extensions/console.py +73 -0
  58. pymodaq/extensions/daq_logger/__init__.py +1 -0
  59. pymodaq/extensions/daq_logger/abstract.py +52 -0
  60. pymodaq/extensions/daq_logger/daq_logger.py +519 -0
  61. pymodaq/extensions/daq_logger/db/__init__.py +0 -0
  62. pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
  63. pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
  64. pymodaq/extensions/daq_logger/h5logging.py +84 -0
  65. pymodaq/extensions/daq_scan.py +1218 -0
  66. pymodaq/extensions/daq_scan_ui.py +241 -0
  67. pymodaq/extensions/data_mixer/__init__.py +0 -0
  68. pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
  69. pymodaq/extensions/data_mixer/data_mixer.py +262 -0
  70. pymodaq/extensions/data_mixer/model.py +108 -0
  71. pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  72. pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
  73. pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
  74. pymodaq/extensions/data_mixer/parser.py +53 -0
  75. pymodaq/extensions/data_mixer/utils.py +23 -0
  76. pymodaq/extensions/h5browser.py +9 -0
  77. pymodaq/extensions/optimizers_base/__init__.py +0 -0
  78. pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
  79. pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
  80. pymodaq/extensions/optimizers_base/utils.py +427 -0
  81. pymodaq/extensions/pid/__init__.py +16 -0
  82. pymodaq/extensions/pid/actuator_controller.py +14 -0
  83. pymodaq/extensions/pid/daq_move_PID.py +154 -0
  84. pymodaq/extensions/pid/pid_controller.py +1016 -0
  85. pymodaq/extensions/pid/utils.py +189 -0
  86. pymodaq/extensions/utils.py +111 -0
  87. pymodaq/icon.ico +0 -0
  88. pymodaq/post_treatment/__init__.py +6 -0
  89. pymodaq/post_treatment/load_and_plot.py +352 -0
  90. pymodaq/resources/__init__.py +0 -0
  91. pymodaq/resources/config_template.toml +57 -0
  92. pymodaq/resources/preset_default.xml +1 -0
  93. pymodaq/resources/setup_plugin.py +73 -0
  94. pymodaq/splash.png +0 -0
  95. pymodaq/utils/__init__.py +0 -0
  96. pymodaq/utils/array_manipulation.py +6 -0
  97. pymodaq/utils/calibration_camera.py +180 -0
  98. pymodaq/utils/chrono_timer.py +203 -0
  99. pymodaq/utils/config.py +53 -0
  100. pymodaq/utils/conftests.py +5 -0
  101. pymodaq/utils/daq_utils.py +158 -0
  102. pymodaq/utils/data.py +128 -0
  103. pymodaq/utils/enums.py +6 -0
  104. pymodaq/utils/exceptions.py +38 -0
  105. pymodaq/utils/gui_utils/__init__.py +10 -0
  106. pymodaq/utils/gui_utils/loader_utils.py +75 -0
  107. pymodaq/utils/gui_utils/utils.py +18 -0
  108. pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
  109. pymodaq/utils/h5modules/__init__.py +2 -0
  110. pymodaq/utils/h5modules/module_saving.py +526 -0
  111. pymodaq/utils/leco/__init__.py +25 -0
  112. pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
  113. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
  114. pymodaq/utils/leco/director_utils.py +74 -0
  115. pymodaq/utils/leco/leco_director.py +166 -0
  116. pymodaq/utils/leco/pymodaq_listener.py +364 -0
  117. pymodaq/utils/leco/rpc_method_definitions.py +43 -0
  118. pymodaq/utils/leco/utils.py +74 -0
  119. pymodaq/utils/logger.py +6 -0
  120. pymodaq/utils/managers/__init__.py +0 -0
  121. pymodaq/utils/managers/batchscan_manager.py +346 -0
  122. pymodaq/utils/managers/modules_manager.py +589 -0
  123. pymodaq/utils/managers/overshoot_manager.py +242 -0
  124. pymodaq/utils/managers/preset_manager.py +229 -0
  125. pymodaq/utils/managers/preset_manager_utils.py +262 -0
  126. pymodaq/utils/managers/remote_manager.py +484 -0
  127. pymodaq/utils/math_utils.py +6 -0
  128. pymodaq/utils/messenger.py +6 -0
  129. pymodaq/utils/parameter/__init__.py +10 -0
  130. pymodaq/utils/parameter/utils.py +6 -0
  131. pymodaq/utils/scanner/__init__.py +5 -0
  132. pymodaq/utils/scanner/scan_config.py +16 -0
  133. pymodaq/utils/scanner/scan_factory.py +259 -0
  134. pymodaq/utils/scanner/scan_selector.py +477 -0
  135. pymodaq/utils/scanner/scanner.py +324 -0
  136. pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
  137. pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
  138. pymodaq/utils/scanner/scanners/__init__.py +1 -0
  139. pymodaq/utils/scanner/scanners/sequential.py +224 -0
  140. pymodaq/utils/scanner/scanners/tabular.py +319 -0
  141. pymodaq/utils/scanner/utils.py +110 -0
  142. pymodaq/utils/svg/__init__.py +6 -0
  143. pymodaq/utils/svg/svg_renderer.py +20 -0
  144. pymodaq/utils/svg/svg_view.py +35 -0
  145. pymodaq/utils/svg/svg_viewer2D.py +50 -0
  146. pymodaq/utils/tcp_ip/__init__.py +6 -0
  147. pymodaq/utils/tcp_ip/mysocket.py +12 -0
  148. pymodaq/utils/tcp_ip/serializer.py +13 -0
  149. pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
  150. pymodaq-5.1.6.dist-info/METADATA +238 -0
  151. pymodaq-5.1.6.dist-info/RECORD +154 -0
  152. pymodaq-5.1.6.dist-info/WHEEL +4 -0
  153. pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
  154. pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,108 @@
1
+ import dataclasses
2
+ from typing import List, TYPE_CHECKING
3
+ import importlib
4
+ import inspect
5
+ import pkgutil
6
+ import warnings
7
+ from pathlib import Path
8
+ from typing import Union, List
9
+
10
+ import numpy as np # to be imported within models
11
+
12
+ from pymodaq_utils.utils import find_dict_in_list_from_key_val, get_entrypoints
13
+ from pymodaq_utils.logger import set_logger, get_module_name
14
+
15
+ from pymodaq_data.data import DataToExport
16
+
17
+ from pymodaq_gui.managers.parameter_manager import ParameterManager, Parameter
18
+ from pymodaq_gui.config_saver_loader import ConfigSaverLoader
19
+
20
+
21
+ logger = set_logger(get_module_name(__file__))
22
+
23
+ if TYPE_CHECKING:
24
+ from pymodaq.extensions.data_mixer import DataMixer
25
+ from pymodaq.utils.managers.modules_manager import ModulesManager
26
+
27
+
28
+ class DataMixerModel:
29
+
30
+ detectors_name: List[str] = []
31
+ params = []
32
+
33
+ def __init__(self, data_mixer: 'DataMixer'):
34
+ self.data_mixer = data_mixer
35
+ self.modules_manager: ModulesManager = data_mixer.modules_manager
36
+ self.settings: Parameter = self.data_mixer.settings.child('models', 'model_params')
37
+
38
+
39
+ def ini_model_base(self):
40
+ """ Method to add things that should be executed before instantiating the model"""
41
+ self.ini_model()
42
+
43
+ def ini_model(self):
44
+ pass
45
+
46
+ def update_settings(self, param: Parameter):
47
+ pass
48
+
49
+ def process_dte(self, measurements: DataToExport) -> DataToExport:
50
+ """
51
+ Convert the measurements in the units to be fed to the PID (same dimensionality as the setpoint)
52
+ Parameters
53
+ ----------
54
+ measurements: DataToExport
55
+ DataToExport object from which the model extract a value of the same units as the setpoint
56
+
57
+ Returns
58
+ -------
59
+ DataToExport: the converted input as 0D DataCalculated stored in a DataToExport
60
+ """
61
+ raise NotImplementedError
62
+
63
+
64
+ @dataclasses.dataclass
65
+ class PkgMock:
66
+ value: str
67
+
68
+
69
+ def get_models(model_name=None) -> list[dict[(str, str), (str, type)]]:
70
+ """
71
+ Get DataMixer Models
72
+
73
+ Returns
74
+ -------
75
+ list: list of dict containing the name and python module of the found models
76
+
77
+ Example
78
+ -------
79
+ model = [{'name': 'MyModel', 'class': DataModel}]
80
+ """
81
+ models_import = []
82
+ discovered_models = list(get_entrypoints(group='pymodaq.models'))
83
+ discovered_models.append(PkgMock('pymodaq.extensions.data_mixer'))
84
+ if len(discovered_models) > 0:
85
+ for pkg in discovered_models:
86
+ try:
87
+ module = importlib.import_module(pkg.value)
88
+ module_name = pkg.value
89
+
90
+ for mod in pkgutil.iter_modules([str(Path(module.__file__).parent.joinpath('models'))]):
91
+ try:
92
+ model_module = importlib.import_module(f'{module_name}.models.{mod.name}', module)
93
+ classes = inspect.getmembers(model_module, inspect.isclass)
94
+ for name, klass in classes:
95
+ if klass.__base__ is DataMixerModel:
96
+ models_import.append({'name': mod.name, 'module': model_module, 'class': klass})
97
+ break
98
+
99
+ except Exception as e: # pragma: no cover
100
+ logger.warning(str(e))
101
+
102
+ except Exception as e: # pragma: no cover
103
+ logger.warning(f'Impossible to import the {pkg.value} extension: {str(e)}')
104
+
105
+ if model_name is None:
106
+ return models_import
107
+ else:
108
+ return find_dict_in_list_from_key_val(models_import, 'name', model_name)
File without changes
@@ -0,0 +1,91 @@
1
+ from pymodaq.extensions.data_mixer.model import DataMixerModel, np # np will be used in method eval of the formula
2
+
3
+ from pymodaq_data.data import DataToExport, DataWithAxes
4
+ from pymodaq_gui.parameter import Parameter
5
+ from pymodaq_gui.config_saver_loader import ConfigSaverLoader
6
+
7
+ from pymodaq.extensions.data_mixer.parser import (
8
+ extract_data_names, split_formulae, replace_names_in_formula)
9
+
10
+ from pymodaq_utils.logger import set_logger, get_module_name
11
+
12
+ logger = set_logger(get_module_name(__file__))
13
+
14
+ class DataMixerModelEquation(DataMixerModel):
15
+ params = [
16
+ {'title': 'Get Data:', 'name': 'get_data', 'type': 'bool_push', 'value': False,
17
+ 'label': 'Get Data'},
18
+ {'title': 'Edit Formula:', 'name': 'edit_formula', 'type': 'text', 'value': ''},
19
+ {'title': 'Data0D:', 'name': 'data0D', 'type': 'itemselect',
20
+ 'value': dict(all_items=[], selected=[])},
21
+ {'title': 'Data1D:', 'name': 'data1D', 'type': 'itemselect',
22
+ 'value': dict(all_items=[], selected=[])},
23
+ {'title': 'Data2D:', 'name': 'data2D', 'type': 'itemselect',
24
+ 'value': dict(all_items=[], selected=[])},
25
+ {'title': 'DataND:', 'name': 'dataND', 'type': 'itemselect',
26
+ 'value': dict(all_items=[], selected=[])},
27
+ ]
28
+
29
+ def ini_model(self):
30
+ self.model_saver_loader = ConfigSaverLoader(self.settings, self.data_mixer.datamixer_config,
31
+ base_path=[self.__class__.__name__])
32
+ self.show_data_list()
33
+ self.model_saver_loader.load_config()
34
+
35
+ def update_settings(self, param: Parameter):
36
+ if param.name() == 'get_data':
37
+ self.show_data_list()
38
+ elif param.name() == 'edit_formula':
39
+ self.model_saver_loader.save_config(param)
40
+
41
+ def process_dte(self, dte: DataToExport):
42
+ formulae = split_formulae(self.get_formulae())
43
+ dte_processed = DataToExport('Computed')
44
+ for ind, formula in enumerate(formulae):
45
+ try:
46
+ dwa = self.compute_formula(formula, dte,
47
+ name=f'Formula_{ind:03.0f}')
48
+ dte_processed.append(dwa)
49
+ except Exception as e:
50
+ logger.exception(f'{str(e)}')
51
+ return dte_processed
52
+
53
+ def get_formulae(self) -> str:
54
+ """ Read the content of the formula QTextEdit widget"""
55
+ return self.settings['edit_formula']
56
+
57
+ def show_data_list(self):
58
+ dte = self.modules_manager.get_det_data_list()
59
+
60
+ data_list0D = dte.get_full_names('data0D')
61
+ data_list1D = dte.get_full_names('data1D')
62
+ data_list2D = dte.get_full_names('data2D')
63
+ data_listND = dte.get_full_names('dataND')
64
+
65
+ self.settings.child('data0D').setValue(dict(all_items=data_list0D, selected=[]))
66
+ self.settings.child('data1D').setValue(dict(all_items=data_list1D, selected=[]))
67
+ self.settings.child('data2D').setValue(dict(all_items=data_list2D, selected=[]))
68
+ self.settings.child('dataND').setValue(dict(all_items=data_listND, selected=[]))
69
+
70
+
71
+ def compute_formula(self, formula: str, dte: DataToExport,
72
+ name: str) -> DataWithAxes:
73
+ """ Compute the operations in formula using data stored in dte
74
+
75
+ Parameters
76
+ ----------
77
+ formula: str
78
+ The mathematical formula using numpy and data fullnames within curly brackets
79
+ dte: DataToExport
80
+ name: str
81
+ The name to give to the produced DataWithAxes
82
+
83
+ Returns
84
+ -------
85
+ DataWithAxes: the results of the formula computation
86
+ """
87
+ formula_to_eval, names = replace_names_in_formula(formula)
88
+ dwa = eval(formula_to_eval)
89
+ dwa.name = name
90
+ return dwa
91
+
@@ -0,0 +1,65 @@
1
+ import numpy as np
2
+
3
+ from pymodaq.extensions.data_mixer.model import DataMixerModel, np # np will be used in method eval of the formula
4
+
5
+ from pymodaq_utils.math_utils import gauss1D, my_moment
6
+
7
+ from pymodaq_data.data import DataToExport, DataWithAxes, DataCalculated, DataDim
8
+ from pymodaq_gui.parameter import Parameter
9
+
10
+ from pymodaq.extensions.data_mixer.parser import (
11
+ extract_data_names, split_formulae, replace_names_in_formula)
12
+
13
+
14
+ def gaussian_fit(x, amp, x0, dx, offset):
15
+ dx = np.abs(dx)
16
+ return amp * gauss1D(x, x0, dx) + offset
17
+
18
+
19
+ class DataMixerGaussianFitModel(DataMixerModel):
20
+ params = [
21
+ {'title': 'Get Data:', 'name': 'get_data', 'type': 'bool_push', 'value': False,
22
+ 'label': 'Get Data'},
23
+ {'title': 'Data1D:', 'name': 'data1D', 'type': 'itemselect',
24
+ 'value': dict(all_items=[], selected=[])},
25
+ ]
26
+
27
+ def ini_model(self):
28
+ self.show_data_list()
29
+
30
+ def show_data_list(self):
31
+ dte = self.modules_manager.get_det_data_list()
32
+ data_list1D = dte.get_full_names('data1D')
33
+ self.settings.child('data1D').setValue(dict(all_items=data_list1D, selected=[]))
34
+
35
+ def update_settings(self, param: Parameter):
36
+ if param.name() == 'get_data':
37
+ self.show_data_list()
38
+
39
+ def process_dte(self, dte: DataToExport):
40
+ dte_processed = DataToExport('computed')
41
+ if len(self.settings['data1D']['selected']) != 0:
42
+
43
+ dwa = dte.get_data_from_full_name(self.settings['data1D']['selected'][0])
44
+ dwa_fit = dwa.fit(gaussian_fit, self.get_guess(dwa), data_index=0)
45
+ dwa.append(dwa_fit)
46
+ dte_processed.append(dwa)
47
+ dte_processed.append(
48
+ DataCalculated('Coeffs',
49
+ data=[np.atleast_1d(coeff) for coeff in dwa_fit.fit_coeffs[0]],
50
+ labels=['amp', 'x0', 'dx', 'offset']))
51
+
52
+ return dte_processed
53
+
54
+ @staticmethod
55
+ def get_guess(dwa):
56
+ offset = np.min(dwa).value()
57
+ dwa.create_missing_axes()
58
+ moments = my_moment(dwa.axes[0].get_data(), dwa.data[0])
59
+ amp = (np.max(dwa) - np.min(dwa)).value()
60
+ x0 = float(moments[0])
61
+ dx = float(moments[1])
62
+
63
+ return amp, x0, dx, offset
64
+
65
+
@@ -0,0 +1,53 @@
1
+ import re
2
+ from typing import List
3
+
4
+
5
+ data_name_regexp = re.compile(r"({.*?})+") # first occurrences of things between {}
6
+
7
+
8
+ def split_formulae(formulae: str) -> List[str]:
9
+ """ Split a string into a list of string for each new line
10
+
11
+ Parameters
12
+ ----------
13
+ formulae: str
14
+ The formulae containing various mathematical formula separated with a new line character
15
+
16
+ Returns
17
+ -------
18
+ The various formula as a list of string
19
+ """
20
+ return re.split(r'\n', formulae)
21
+
22
+
23
+ def extract_data_names(formula: str) -> List[str]:
24
+ """ Extract the names of the data appearing between curly brackets with a given string formula
25
+
26
+ Parameters
27
+ ----------
28
+ formula: str
29
+ The mathematical expression to compute containing in curly brackets the data full names
30
+
31
+ Returns
32
+ -------
33
+
34
+ """
35
+ data_names = [data_name_with_curly[1:-1] for
36
+ data_name_with_curly in data_name_regexp.findall(formula)]
37
+ return data_names
38
+
39
+
40
+ def replace_names_in_formula(formula: str):
41
+ formula_tmp = formula[:]
42
+ names = []
43
+ while True:
44
+ m = data_name_regexp.search(formula_tmp)
45
+ if m is not None:
46
+ names.append(m.group())
47
+ formula_tmp = (
48
+ formula_tmp.replace(formula_tmp[m.start(): m.end()],
49
+ f'dte.get_data_from_full_name("{m.group()[1:-1]}")'))
50
+ else:
51
+ break
52
+ return formula_tmp, names
53
+
@@ -0,0 +1,23 @@
1
+ from pymodaq_utils.config import BaseConfig
2
+
3
+
4
+ class DataMixerConfig(BaseConfig):
5
+ """Main class to deal with configuration values for this plugin
6
+
7
+ To b subclassed for real implementation if needed, see Optimizer class attribute config_saver
8
+ """
9
+ config_template_path = None
10
+ config_name = f"datamixer_settings"
11
+
12
+
13
+ def find_key_in_nested_dict(dic, key):
14
+ stack = [dic]
15
+ while stack:
16
+ d = stack.pop()
17
+ if key in d:
18
+ return d[key]
19
+ for v in d.values():
20
+ if isinstance(v, dict):
21
+ stack.append(v)
22
+ if isinstance(v, list):
23
+ stack += v
@@ -0,0 +1,9 @@
1
+ from pymodaq_gui.h5modules.h5browser import main, H5Browser #backcompat
2
+ from pymodaq_utils.utils import deprecation_msg
3
+
4
+
5
+ deprecation_msg('H5Browser should now be loaded from the pymodaq_gui.h5modules.h5browser module')
6
+
7
+
8
+ if __name__ == '__main__':
9
+ main()
File without changes