pymodaq 5.0.18__py3-none-any.whl → 5.1.0__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 (92) hide show
  1. pymodaq/__init__.py +23 -11
  2. pymodaq/control_modules/__init__.py +1 -0
  3. pymodaq/control_modules/daq_move.py +451 -246
  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.py → daq_move_ui/ui_base.py} +168 -210
  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 +113 -101
  13. pymodaq/control_modules/daq_viewer_ui.py +41 -31
  14. pymodaq/control_modules/mocks.py +2 -2
  15. pymodaq/control_modules/move_utility_classes.py +113 -41
  16. pymodaq/control_modules/thread_commands.py +137 -0
  17. pymodaq/control_modules/ui_utils.py +72 -0
  18. pymodaq/control_modules/utils.py +107 -63
  19. pymodaq/control_modules/viewer_utility_classes.py +13 -17
  20. pymodaq/dashboard.py +1294 -625
  21. pymodaq/examples/qt_less_standalone_module.py +48 -11
  22. pymodaq/extensions/__init__.py +8 -3
  23. pymodaq/extensions/adaptive/__init__.py +2 -0
  24. pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
  25. pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
  26. pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
  27. pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
  28. pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
  29. pymodaq/extensions/adaptive/utils.py +123 -0
  30. pymodaq/extensions/bayesian/__init__.py +1 -1
  31. pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
  32. pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
  33. pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
  34. pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
  35. pymodaq/extensions/bayesian/utils.py +71 -297
  36. pymodaq/extensions/daq_logger/daq_logger.py +7 -12
  37. pymodaq/extensions/daq_logger/h5logging.py +1 -1
  38. pymodaq/extensions/daq_scan.py +30 -55
  39. pymodaq/extensions/data_mixer/__init__.py +0 -0
  40. pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
  41. pymodaq/extensions/data_mixer/data_mixer.py +262 -0
  42. pymodaq/extensions/data_mixer/model.py +108 -0
  43. pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  44. pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
  45. pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
  46. pymodaq/extensions/data_mixer/parser.py +53 -0
  47. pymodaq/extensions/data_mixer/utils.py +23 -0
  48. pymodaq/extensions/h5browser.py +3 -34
  49. pymodaq/extensions/optimizers_base/__init__.py +0 -0
  50. pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
  51. pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
  52. pymodaq/extensions/optimizers_base/utils.py +427 -0
  53. pymodaq/extensions/pid/actuator_controller.py +3 -2
  54. pymodaq/extensions/pid/daq_move_PID.py +107 -30
  55. pymodaq/extensions/pid/pid_controller.py +613 -287
  56. pymodaq/extensions/pid/utils.py +8 -5
  57. pymodaq/extensions/utils.py +17 -2
  58. pymodaq/resources/config_template.toml +57 -0
  59. pymodaq/resources/preset_default.xml +1 -1
  60. pymodaq/utils/config.py +10 -4
  61. pymodaq/utils/daq_utils.py +14 -0
  62. pymodaq/utils/data.py +1 -0
  63. pymodaq/utils/gui_utils/loader_utils.py +25 -15
  64. pymodaq/utils/h5modules/module_saving.py +134 -22
  65. pymodaq/utils/leco/daq_move_LECODirector.py +123 -84
  66. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +84 -97
  67. pymodaq/utils/leco/director_utils.py +32 -16
  68. pymodaq/utils/leco/leco_director.py +104 -27
  69. pymodaq/utils/leco/pymodaq_listener.py +186 -97
  70. pymodaq/utils/leco/rpc_method_definitions.py +43 -0
  71. pymodaq/utils/leco/utils.py +25 -25
  72. pymodaq/utils/managers/batchscan_manager.py +12 -11
  73. pymodaq/utils/managers/modules_manager.py +74 -33
  74. pymodaq/utils/managers/overshoot_manager.py +11 -10
  75. pymodaq/utils/managers/preset_manager.py +100 -64
  76. pymodaq/utils/managers/preset_manager_utils.py +163 -107
  77. pymodaq/utils/managers/remote_manager.py +21 -16
  78. pymodaq/utils/scanner/scan_factory.py +12 -3
  79. pymodaq/utils/scanner/scan_selector.py +1 -3
  80. pymodaq/utils/scanner/scanner.py +35 -6
  81. pymodaq/utils/scanner/scanners/_1d_scanners.py +15 -46
  82. pymodaq/utils/scanner/scanners/_2d_scanners.py +21 -68
  83. pymodaq/utils/scanner/scanners/sequential.py +50 -31
  84. pymodaq/utils/scanner/scanners/tabular.py +45 -28
  85. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/METADATA +7 -6
  86. pymodaq-5.1.0.dist-info/RECORD +154 -0
  87. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/entry_points.txt +0 -2
  88. pymodaq/extensions/bayesian/bayesian_optimisation.py +0 -690
  89. pymodaq/utils/leco/desktop.ini +0 -2
  90. pymodaq-5.0.18.dist-info/RECORD +0 -121
  91. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/WHEEL +0 -0
  92. {pymodaq-5.0.18.dist-info → pymodaq-5.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,2 +1,2 @@
1
- from . import bayesian_optimisation
1
+ from . import bayesian_optimization
2
2
  from . import utils
@@ -0,0 +1,2 @@
1
+ from .acquisition_function_factory import GenericAcquisitionFunctionFactory, GenericAcquisitionFunctionBase
2
+ from .base_acquisition_function import GenericUpperConfidenceBound, GenericExpectedImprovement, GenericProbabilityOfImprovement
@@ -0,0 +1,80 @@
1
+ from abc import ABCMeta, abstractmethod
2
+ from typing import Callable
3
+
4
+ from numpy.random import RandomState
5
+ from bayes_opt.acquisition import AcquisitionFunction
6
+
7
+ from pymodaq_gui.managers.parameter_manager import ParameterManager
8
+ from pymodaq_utils.logger import set_logger, get_module_name
9
+
10
+ logger = set_logger(get_module_name(__file__))
11
+
12
+
13
+ class GenericAcquisitionFunctionBase(metaclass=ABCMeta):
14
+ _function: AcquisitionFunction
15
+ usual_name: str
16
+ short_name: str
17
+ params : property(abstractmethod)
18
+
19
+ def base_acq(self, mean, std):
20
+ return self._function.base_acq(mean, std)
21
+
22
+ def decay_exploration(self):
23
+ self._function.decay_exploration()
24
+
25
+ @property
26
+ def tradeoff(self):
27
+ raise NotImplementedError
28
+
29
+ @tradeoff.setter
30
+ def tradeoff(self, tradeoff):
31
+ raise NotImplementedError
32
+
33
+ def suggest(self, gaussian_process, target_space, n_random = 1000, n_l_bfgs_b = 10, fit_gp = True):
34
+ return self._function.suggest(gaussian_process, target_space, n_random, n_l_bfgs_b, fit_gp)
35
+
36
+
37
+ class GenericAcquisitionFunctionFactory:
38
+ _builders = {}
39
+
40
+ @classmethod
41
+ def register(cls) -> Callable:
42
+ """ To be used as a decorator
43
+
44
+ Register in the class registry a new scanner class using its 2 identifiers: scan_type and scan_sub_type
45
+ """
46
+
47
+ def inner_wrapper(wrapped_class: GenericAcquisitionFunctionBase) -> Callable:
48
+ key = wrapped_class.short_name
49
+
50
+ if key not in cls._builders:
51
+ cls._builders[key] = wrapped_class
52
+ else:
53
+ logger.warning(f'The {key} builder is already registered. Replacing it')
54
+ return wrapped_class
55
+
56
+ return inner_wrapper
57
+
58
+
59
+ @classmethod
60
+ def get(cls, key : str) -> GenericAcquisitionFunctionBase:
61
+ builder = cls._builders.get(key)
62
+ if not builder:
63
+ raise ValueError(key)
64
+ return builder
65
+
66
+ @classmethod
67
+ def create(cls, key, **kwargs) -> GenericAcquisitionFunctionBase:
68
+ return cls._builders.get(key)(**kwargs)
69
+
70
+ @classmethod
71
+ def keys(cls) -> list[str]:
72
+ return list(cls._builders.keys())
73
+
74
+ @classmethod
75
+ def short_names(cls) -> list[str]:
76
+ return list(cls.keys())
77
+
78
+ @classmethod
79
+ def usual_names(cls) -> list[str]:
80
+ return [cls.get(builder).usual_name for builder in cls._builders]
@@ -0,0 +1,105 @@
1
+ from bayes_opt.acquisition import UpperConfidenceBound, ExpectedImprovement, ProbabilityOfImprovement
2
+ from pymodaq.extensions.bayesian.acquisition import GenericAcquisitionFunctionFactory, GenericAcquisitionFunctionBase
3
+
4
+
5
+ @GenericAcquisitionFunctionFactory.register()
6
+ class GenericUpperConfidenceBound(GenericAcquisitionFunctionBase):
7
+ usual_name = "Upper Confidence Bound"
8
+ short_name = "ucb"
9
+ params = [
10
+ {'title': 'Kappa:', 'name': 'kappa', 'type': 'slide', 'value': 2.576,
11
+ 'min': 0.001, 'max': 100, 'subtype': 'log',
12
+ 'tip': 'Parameter to indicate how closed are the next parameters sampled.'
13
+ 'Higher value = favors spaces that are least explored.'
14
+ 'Lower value = favors spaces where the regression function is the '
15
+ 'highest.'},
16
+ {'title': 'Kappa actual:', 'name': 'tradeoff_actual', 'type': 'float', 'value': 2.576,
17
+ 'tip': 'Current value of the kappa parameter', 'readonly': True},
18
+ {'title': 'Exploration decay:', 'name': 'exploration_decay', 'type': 'float', 'value': 0.9,
19
+ 'tip': 'kappa is multiplied by this factor every iteration.'},
20
+ {'title': 'Exploration decay delay:', 'name': 'exploration_decay_delay', 'type': 'int', 'value': 20,
21
+ 'tip': 'Number of iterations that must have passed before applying the decay to kappa.'}
22
+ ]
23
+
24
+
25
+ def __init__(self, **kwargs):
26
+ super().__init__()
27
+ self._function = UpperConfidenceBound(
28
+ kappa=kwargs.get('kappa', 2.576),
29
+ exploration_decay=kwargs.get('exploration_decay', None),
30
+ exploration_decay_delay=kwargs.get('exploration_decay_delay', None),
31
+ random_state=kwargs.get('random_state', None),
32
+ )
33
+
34
+ @property
35
+ def tradeoff(self):
36
+ return self._function.kappa
37
+
38
+ @tradeoff.setter
39
+ def tradeoff(self, tradeoff):
40
+ self._function.kappa = tradeoff
41
+
42
+ @GenericAcquisitionFunctionFactory.register()
43
+ class GenericProbabilityOfImprovement(GenericAcquisitionFunctionBase):
44
+ usual_name = "Probability of Improvement"
45
+ short_name = "poi"
46
+ params = [
47
+ {'title': 'Xi:', 'name': 'xi', 'type': 'slide', 'value': 0,
48
+ 'tip': 'Governs the exploration/exploitation tradeoff.'
49
+ 'Lower prefers exploitation, higher prefers exploration.'},
50
+ {'title': 'Xi actual:', 'name': 'tradeoff_actual', 'type': 'float', 'value': 2.576,
51
+ 'tip': 'Current value of the xi parameter', 'readonly': True},
52
+ {'title': 'Exploration decay:', 'name': 'exploration_decay', 'type': 'float', 'value': 0.9,
53
+ 'tip': 'Xi is multiplied by this factor every iteration.'},
54
+ {'title': 'Exploration decay delay:', 'name': 'exploration_decay_delay', 'type': 'int', 'value': 20,
55
+ 'tip': 'Number of iterations that must have passed before applying the decay to xi.'}
56
+ ]
57
+
58
+ def __init__(self, **kwargs):
59
+ super().__init__()
60
+ self._function = ProbabilityOfImprovement(
61
+ xi=kwargs.get('xi'),
62
+ exploration_decay=kwargs.get('exploration_decay', None),
63
+ exploration_decay_delay=kwargs.get('exploration_decay_delay', None),
64
+ random_state=kwargs.get('random_state', None),
65
+ )
66
+
67
+ @property
68
+ def tradeoff(self):
69
+ return self._function.xi
70
+
71
+ @tradeoff.setter
72
+ def tradeoff(self, tradeoff):
73
+ self._function.xi = tradeoff
74
+
75
+ @GenericAcquisitionFunctionFactory.register()
76
+ class GenericExpectedImprovement(GenericAcquisitionFunctionBase):
77
+ usual_name = "Expected Improvement"
78
+ short_name = "ei"
79
+ params = [
80
+ {'title': 'Xi:', 'name': 'xi', 'type': 'slide', 'value': 0,
81
+ 'tip': 'Governs the exploration/exploitation tradeoff.'
82
+ 'Lower prefers exploitation, higher prefers exploration.'},
83
+ {'title': 'Xi actual:', 'name': 'tradeoff_actual', 'type': 'float', 'value': 2.576,
84
+ 'tip': 'Current value of the xi parameter', 'readonly': True},
85
+ {'title': 'Exploration decay:', 'name': 'exploration_decay', 'type': 'float', 'value': 0.9,
86
+ 'tip': 'Xi is multiplied by this factor every iteration.'},
87
+ {'title': 'Exploration decay delay:', 'name': 'exploration_decay_delay', 'type': 'int', 'value': 20,
88
+ 'tip': 'Number of iterations that must have passed before applying the decay to xi.'}
89
+ ]
90
+ def __init__(self, **kwargs):
91
+ super().__init__()
92
+ self._function = ExpectedImprovement(
93
+ xi=kwargs.get('xi'),
94
+ exploration_decay=kwargs.get('exploration_decay', None),
95
+ exploration_decay_delay=kwargs.get('exploration_decay_delay', None),
96
+ random_state=kwargs.get('random_state', None),
97
+ )
98
+
99
+ @property
100
+ def tradeoff(self):
101
+ return self._function.xi
102
+
103
+ @tradeoff.setter
104
+ def tradeoff(self, tradeoff):
105
+ self._function.xi = tradeoff
@@ -0,0 +1,143 @@
1
+
2
+
3
+ from pymodaq_utils import config as config_mod, utils
4
+ from pymodaq_utils.logger import set_logger, get_module_name
5
+ from pymodaq_utils.utils import ThreadCommand
6
+
7
+
8
+ from pymodaq.extensions.bayesian.utils import BayesianAlgorithm, BayesianConfig
9
+
10
+ from pymodaq.extensions.bayesian.acquisition import GenericAcquisitionFunctionFactory
11
+
12
+ from pymodaq.extensions.optimizers_base.optimizer import (
13
+ GenericOptimization, OptimizationRunner, optimizer_params, OptimizerAction)
14
+ from pymodaq.extensions.optimizers_base.utils import OptimizerModelDefault, find_key_in_nested_dict
15
+ from pymodaq.extensions.optimizers_base.thread_commands import OptimizerToRunner, OptimizerThreadStatus
16
+
17
+
18
+ logger = set_logger(get_module_name(__file__))
19
+ config = config_mod.Config()
20
+
21
+
22
+ EXTENSION_NAME = 'BayesianOptimization'
23
+ CLASS_NAME = 'BayesianOptimization'
24
+
25
+ PREDICTION_NAMES = GenericAcquisitionFunctionFactory.usual_names()
26
+ PREDICTION_SHORT_NAMES = GenericAcquisitionFunctionFactory.short_names()
27
+ PREDICTION_PARAMS = ([{'title': 'Kind', 'name': 'kind', 'type': 'list',
28
+ 'value': PREDICTION_NAMES[0],
29
+ 'limits': {name: short_name for name, short_name in zip(PREDICTION_NAMES, PREDICTION_SHORT_NAMES)}}
30
+ ] +
31
+ [{'title': 'Options', 'name': 'options', 'type': 'group',
32
+ 'children': GenericAcquisitionFunctionFactory.get(PREDICTION_SHORT_NAMES[0]).params}]
33
+ )
34
+
35
+
36
+ class BayesianOptimizationRunner(OptimizationRunner):
37
+
38
+ def __init__(self, *args, **kwargs):
39
+ super().__init__(*args, **kwargs)
40
+
41
+ def queue_command(self, command: ThreadCommand):
42
+ """
43
+ """
44
+ if command.command == OptimizerToRunner.PREDICTION:
45
+ kind = command.attribute.pop('kind')
46
+ self.optimization_algorithm.set_acquisition_function(
47
+ kind,
48
+ **command.attribute)
49
+ else:
50
+ super().queue_command(command)
51
+
52
+
53
+ class BayesianOptimization(GenericOptimization):
54
+ """ PyMoDAQ extension of the DashBoard to perform the optimization of a target signal
55
+ taken form the detectors as a function of one or more parameters controlled by the actuators.
56
+ """
57
+
58
+ runner = BayesianOptimizationRunner
59
+ params = optimizer_params(PREDICTION_PARAMS)
60
+ config_saver = BayesianConfig
61
+
62
+ def ini_custom_attributes(self):
63
+ """ Here you can reimplement specific attributes"""
64
+ self._base_name: str = 'Bayesian'
65
+
66
+ def update_after_actuators_changed(self, actuators: list[str]):
67
+ """ Actions to do after the actuators have been updated
68
+ """
69
+ pass
70
+
71
+ def update_prediction_function(self):
72
+ """ Get the selected prediction function options and pass them to the Runner
73
+
74
+ Should be reimplemented in real Optimizer implementation
75
+ """
76
+ utility_settings = self.settings.child('main_settings', 'prediction')
77
+
78
+ kind = utility_settings.child('kind').value()
79
+ uparams = {child.name() : child.value() for child in utility_settings.child('options').children()}
80
+ uparams['kind'] = kind
81
+ self.command_runner.emit(
82
+ utils.ThreadCommand(OptimizerToRunner.PREDICTION, uparams))
83
+
84
+
85
+ def validate_config(self) -> bool:
86
+ utility = find_key_in_nested_dict(self.optimizer_config.to_dict(), 'prediction')
87
+ if utility:
88
+ try:
89
+ kind = utility.pop('kind', None)
90
+ if kind is not None:
91
+ GenericAcquisitionFunctionFactory.create(kind, **utility)
92
+ except ValueError:
93
+ return False
94
+
95
+ return True
96
+
97
+ def value_changed(self, param):
98
+ """ to be subclassed for actions to perform when one of the param's value in self.settings is changed
99
+
100
+ For instance:
101
+ if param.name() == 'do_something':
102
+ if param.value():
103
+ print('Do something')
104
+ self.settings.child('main_settings', 'something_done').setValue(False)
105
+
106
+ Parameters
107
+ ----------
108
+ param: (Parameter) the parameter whose value just changed
109
+ """
110
+ super().value_changed(param)
111
+ if param.name() == 'kind':
112
+ param.parent().child('options').clearChildren()
113
+ param.parent().child('options').addChildren(
114
+ GenericAcquisitionFunctionFactory.get(param.value()).params)
115
+
116
+ def set_algorithm(self):
117
+ self.algorithm = BayesianAlgorithm(
118
+ ini_random=self.settings['main_settings', 'ini_random'],
119
+ bounds=self.format_bounds(),
120
+ actuators=self.modules_manager.selected_actuators_name)
121
+
122
+ def thread_status(self, status: utils.ThreadCommand):
123
+ super().thread_status(status)
124
+ if status.command == OptimizerThreadStatus.TRADE_OFF:
125
+ self.settings.child('main_settings', 'prediction', 'options', 'tradeoff_actual').setValue(status.attribute)
126
+
127
+
128
+ def main():
129
+ from pymodaq_gui.utils.utils import mkQApp
130
+ from pymodaq.utils.gui_utils.loader_utils import load_dashboard_with_preset
131
+
132
+ app = mkQApp('Bayesian Optimiser')
133
+ #preset_file_name = config('presets', f'beam_steering')
134
+
135
+ dashboard, extension, win = load_dashboard_with_preset('beam_steering', 'Bayesian')
136
+
137
+ app.exec()
138
+
139
+ return dashboard, extension, win
140
+
141
+ if __name__ == '__main__':
142
+ main()
143
+