pymodaq 5.0.4__py3-none-any.whl → 5.1.0a0__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.
- pymodaq/control_modules/daq_move.py +78 -65
- pymodaq/control_modules/daq_move_ui.py +16 -15
- pymodaq/control_modules/daq_viewer.py +95 -87
- pymodaq/control_modules/daq_viewer_ui.py +22 -23
- pymodaq/control_modules/mocks.py +2 -2
- pymodaq/control_modules/move_utility_classes.py +28 -19
- pymodaq/control_modules/thread_commands.py +138 -0
- pymodaq/control_modules/utils.py +88 -20
- pymodaq/control_modules/viewer_utility_classes.py +8 -17
- pymodaq/dashboard.py +90 -27
- pymodaq/examples/qt_less_standalone_module.py +48 -11
- pymodaq/extensions/__init__.py +7 -3
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +159 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +86 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +106 -0
- pymodaq/extensions/adaptive/utils.py +97 -0
- pymodaq/extensions/bayesian/__init__.py +1 -1
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +71 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +86 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +121 -0
- pymodaq/extensions/bayesian/utils.py +27 -286
- pymodaq/extensions/daq_logger/daq_logger.py +7 -12
- pymodaq/extensions/daq_logger/h5logging.py +1 -1
- pymodaq/extensions/daq_scan.py +18 -47
- pymodaq/extensions/h5browser.py +3 -34
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/{bayesian/bayesian_optimisation.py → optimizers_base/optimizer.py} +441 -334
- pymodaq/extensions/optimizers_base/thread_commands.py +20 -0
- pymodaq/extensions/optimizers_base/utils.py +378 -0
- pymodaq/extensions/pid/pid_controller.py +6 -10
- pymodaq/extensions/utils.py +12 -0
- pymodaq/utils/data.py +1 -0
- pymodaq/utils/gui_utils/loader_utils.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +134 -22
- pymodaq/utils/leco/daq_move_LECODirector.py +73 -73
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +36 -84
- pymodaq/utils/leco/director_utils.py +25 -10
- pymodaq/utils/leco/leco_director.py +65 -26
- pymodaq/utils/leco/pymodaq_listener.py +118 -68
- pymodaq/utils/leco/utils.py +24 -24
- pymodaq/utils/managers/modules_manager.py +37 -8
- pymodaq/utils/scanner/scanners/_1d_scanners.py +0 -38
- pymodaq/utils/scanner/scanners/_2d_scanners.py +0 -58
- {pymodaq-5.0.4.dist-info → pymodaq-5.1.0a0.dist-info}/METADATA +4 -3
- {pymodaq-5.0.4.dist-info → pymodaq-5.1.0a0.dist-info}/RECORD +52 -38
- {pymodaq-5.0.4.dist-info → pymodaq-5.1.0a0.dist-info}/entry_points.txt +0 -2
- pymodaq/utils/leco/desktop.ini +0 -2
- {pymodaq-5.0.4.dist-info → pymodaq-5.1.0a0.dist-info}/WHEEL +0 -0
- {pymodaq-5.0.4.dist-info → pymodaq-5.1.0a0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,94 +1,75 @@
|
|
|
1
|
-
|
|
1
|
+
import abc
|
|
2
|
+
from typing import List, Optional
|
|
2
3
|
import tempfile
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
6
|
+
|
|
5
7
|
from qtpy import QtWidgets, QtCore
|
|
6
8
|
import time
|
|
7
9
|
import numpy as np
|
|
8
10
|
|
|
9
|
-
from
|
|
11
|
+
from collections import OrderedDict
|
|
12
|
+
|
|
13
|
+
|
|
10
14
|
from pymodaq.utils.managers.modules_manager import ModulesManager
|
|
11
15
|
from pymodaq_utils import utils
|
|
12
16
|
from pymodaq_utils import config as config_mod
|
|
13
|
-
from pymodaq_utils.enums import BaseEnum
|
|
14
|
-
|
|
15
|
-
from pymodaq_gui.config import ConfigSaverLoader
|
|
17
|
+
from pymodaq_utils.enums import BaseEnum, StrEnum
|
|
16
18
|
from pymodaq_utils.logger import set_logger, get_module_name
|
|
17
19
|
|
|
20
|
+
from pymodaq_data.h5modules.data_saving import DataEnlargeableSaver
|
|
21
|
+
|
|
18
22
|
from pymodaq_gui.plotting.data_viewers.viewer0D import Viewer0D
|
|
19
|
-
from pymodaq_gui.plotting.data_viewers.viewer import ViewerDispatcher
|
|
23
|
+
from pymodaq_gui.plotting.data_viewers.viewer import ViewerDispatcher
|
|
20
24
|
from pymodaq_gui.utils import QLED
|
|
21
|
-
from pymodaq_gui.utils.utils import mkQApp
|
|
22
25
|
from pymodaq_gui import utils as gutils
|
|
23
26
|
from pymodaq_gui.parameter import utils as putils
|
|
24
27
|
from pymodaq_gui.h5modules.saving import H5Saver
|
|
28
|
+
from pymodaq_gui.config import ConfigSaverLoader
|
|
25
29
|
|
|
26
|
-
from
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
from pymodaq.extensions.bayesian.utils import (get_bayesian_models, BayesianModelGeneric,
|
|
30
|
-
BayesianAlgorithm, UtilityKind,
|
|
31
|
-
UtilityParameters, StopType, StoppingParameters)
|
|
30
|
+
from pymodaq.utils.data import DataToExport, DataToActuators, DataCalculated, DataActuator
|
|
32
31
|
from pymodaq.post_treatment.load_and_plot import LoaderPlotter
|
|
33
|
-
from pymodaq.extensions.bayesian.utils import BayesianConfig
|
|
34
32
|
from pymodaq.extensions.utils import CustomExt
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
from pymodaq.utils.h5modules import module_saving
|
|
35
|
+
|
|
36
|
+
from pymodaq.extensions.optimizers_base.utils import (
|
|
37
|
+
get_optimizer_models, OptimizerModelGeneric,
|
|
38
|
+
GenericAlgorithm, StopType, StoppingParameters,
|
|
39
|
+
OptimizerConfig)
|
|
40
|
+
from pymodaq.extensions.optimizers_base.thread_commands import OptimizerToRunner, OptimizerThreadStatus
|
|
41
|
+
|
|
38
42
|
|
|
39
43
|
logger = set_logger(get_module_name(__file__))
|
|
40
44
|
config = config_mod.Config()
|
|
41
45
|
|
|
46
|
+
PREDICTION_PARAMS = [] # to be subclassed in ral optimizer implementations
|
|
47
|
+
MODELS = get_optimizer_models()
|
|
42
48
|
|
|
43
|
-
class DataNames(BaseEnum):
|
|
44
|
-
Fitness = 0
|
|
45
|
-
Individual = 1
|
|
46
|
-
ProbedData = 2
|
|
47
|
-
Actuators = 3
|
|
48
|
-
Kappa = 4
|
|
49
49
|
|
|
50
|
+
class DataNames(StrEnum):
|
|
51
|
+
Fitness = 'fitness'
|
|
52
|
+
Individual = 'individual'
|
|
53
|
+
ProbedData = 'probed_data'
|
|
54
|
+
Actuators = 'actuators'
|
|
55
|
+
Tradeoff = 'tradeoff'
|
|
50
56
|
|
|
51
|
-
class BayesianOptimisation(CustomExt):
|
|
52
|
-
""" PyMoDAQ extension of the DashBoard to perform the optimization of a target signal
|
|
53
|
-
taken form the detectors as a function of one or more parameters controlled by the actuators.
|
|
54
|
-
"""
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
explored_viewer_name = 'algo/ProbedData'
|
|
59
|
-
optimisation_done_signal = QtCore.Signal(DataToExport)
|
|
60
|
-
|
|
61
|
-
params = [
|
|
58
|
+
def optimizer_params(prediction_params: list[dict]):
|
|
59
|
+
return [
|
|
62
60
|
{'title': 'Main Settings:', 'name': 'main_settings', 'expanded': True, 'type': 'group',
|
|
63
61
|
'children': [
|
|
64
|
-
{'title': '
|
|
65
|
-
'children':
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
{'title': 'Kappa:', 'name': 'kappa', 'type': 'slide', 'value': 2.576,
|
|
69
|
-
'min': 0.001, 'max': 100, 'subtype': 'log',
|
|
70
|
-
'tip': 'Parameter to indicate how closed are the next parameters sampled.'
|
|
71
|
-
'Higher value = favors spaces that are least explored.'
|
|
72
|
-
'Lower value = favors spaces where the regression function is the '
|
|
73
|
-
'highest.'},
|
|
74
|
-
{'title': 'Kappa actual:', 'name': 'kappa_actual', 'type': 'float', 'value': 2.576,
|
|
75
|
-
'tip': 'Current value of the kappa parameter', 'readonly': True},
|
|
76
|
-
{'title': 'xi:', 'name': 'xi', 'type': 'slide', 'value': 0,
|
|
77
|
-
'tip': 'Governs the exploration/exploitation tradeoff.'
|
|
78
|
-
'Lower prefers exploitation, higher prefers exploration.'},
|
|
79
|
-
{'title': 'Kappa decay:', 'name': 'kappa_decay', 'type': 'float', 'value': 0.9,
|
|
80
|
-
'tip': 'kappa is multiplied by this factor every iteration.'},
|
|
81
|
-
{'title': 'Kappa decay delay:', 'name': 'kappa_decay_delay', 'type': 'int',
|
|
82
|
-
'value': 20, 'tip': 'Number of iterations that must have passed before applying '
|
|
83
|
-
'the decay to kappa.'},
|
|
84
|
-
]},
|
|
62
|
+
{'title': 'Prediction Function:', 'name': 'prediction', 'expanded': False, 'type': 'group',
|
|
63
|
+
'children': prediction_params
|
|
64
|
+
|
|
65
|
+
},
|
|
85
66
|
{'title': 'Stopping Criteria:', 'name': 'stopping', 'expanded': False, 'type': 'group',
|
|
86
67
|
'children': [
|
|
87
68
|
{'title': 'Niteration', 'name': 'niter', 'type': 'int', 'value': 100, 'min': -1},
|
|
88
69
|
{'title': 'Type:', 'name': 'stop_type', 'type': 'list',
|
|
89
70
|
'limits': StopType.names()},
|
|
90
71
|
{'title': 'Tolerance', 'name': 'tolerance', 'type': 'slide', 'value': 1e-2,
|
|
91
|
-
'min': 1e-8, 'max': 1, 'subtype': 'log',},
|
|
72
|
+
'min': 1e-8, 'max': 1, 'subtype': 'log', },
|
|
92
73
|
{'title': 'Npoints', 'name': 'npoints', 'type': 'int', 'value': 5, 'min': 1},
|
|
93
74
|
]},
|
|
94
75
|
{'title': 'Ini. State', 'name': 'ini_random', 'type': 'int', 'value': 5},
|
|
@@ -97,43 +78,219 @@ class BayesianOptimisation(CustomExt):
|
|
|
97
78
|
|
|
98
79
|
{'title': 'Models', 'name': 'models', 'type': 'group', 'expanded': True, 'visible': True,
|
|
99
80
|
'children': [
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
81
|
+
{'title': 'Models class:', 'name': 'model_class', 'type': 'list',
|
|
82
|
+
'limits': [d['name'] for d in MODELS]},
|
|
83
|
+
{'title': 'Ini Model', 'name': 'ini_model', 'type': 'action', },
|
|
84
|
+
{'title': 'Ini Algo', 'name': 'ini_runner', 'type': 'action', 'enabled': False},
|
|
85
|
+
{'title': 'Model params:', 'name': 'model_params', 'type': 'group', 'children': []},
|
|
86
|
+
]},
|
|
106
87
|
{'title': 'Move settings:', 'name': 'move_settings', 'expanded': True, 'type': 'group',
|
|
107
88
|
'visible': False, 'children': [
|
|
108
|
-
|
|
89
|
+
{'title': 'Units:', 'name': 'units', 'type': 'str', 'value': ''}]},
|
|
109
90
|
|
|
110
91
|
]
|
|
111
92
|
|
|
93
|
+
|
|
94
|
+
class DataToActuatorsOpti(DataToActuators):
|
|
95
|
+
""" Specific class including the step in the optimization loop for further use"""
|
|
96
|
+
ind_iter: int
|
|
97
|
+
def __init__(self, *args, ind_iter=0, **kwargs):
|
|
98
|
+
super().__init__(*args, ind_iter=ind_iter, **kwargs)
|
|
99
|
+
|
|
100
|
+
def __repr__(self):
|
|
101
|
+
return f'{super().__repr__()} iter:{self.ind_iter}'
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class OptimizationRunner(QtCore.QObject):
|
|
105
|
+
algo_output_signal = QtCore.Signal(DataToExport)
|
|
106
|
+
algo_finished = QtCore.Signal(DataToExport)
|
|
107
|
+
saver_signal = QtCore.Signal(DataToActuatorsOpti)
|
|
108
|
+
|
|
109
|
+
runner_command = QtCore.Signal(utils.ThreadCommand)
|
|
110
|
+
|
|
111
|
+
def __init__(self, model_class: OptimizerModelGeneric, modules_manager: ModulesManager,
|
|
112
|
+
algorithm: GenericAlgorithm, stopping_params: StoppingParameters):
|
|
113
|
+
super().__init__()
|
|
114
|
+
|
|
115
|
+
self.det_done_datas: DataToExport = None
|
|
116
|
+
self.input_from_dets: float = None
|
|
117
|
+
self.outputs: List[np.ndarray] = []
|
|
118
|
+
self.output_to_actuators: DataToActuators = None
|
|
119
|
+
self.dte_actuators: DataToExport = None
|
|
120
|
+
self.stopping_params: StoppingParameters = stopping_params
|
|
121
|
+
|
|
122
|
+
self.model_class: OptimizerModelGeneric = model_class
|
|
123
|
+
self.modules_manager: ModulesManager = modules_manager
|
|
124
|
+
|
|
125
|
+
self.running = True
|
|
126
|
+
self._ind_iter = -1
|
|
127
|
+
|
|
128
|
+
self.optimization_algorithm: GenericAlgorithm = algorithm
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def queue_command(self, command: utils.ThreadCommand):
|
|
132
|
+
"""
|
|
133
|
+
"""
|
|
134
|
+
if command.command == OptimizerToRunner.RUN:
|
|
135
|
+
if command.attribute is None:
|
|
136
|
+
command.attribute = {}
|
|
137
|
+
self.run_opti(**command.attribute)
|
|
138
|
+
|
|
139
|
+
elif command.command == OptimizerToRunner.STOP:
|
|
140
|
+
self.running = False
|
|
141
|
+
|
|
142
|
+
elif command.command == OptimizerToRunner.STOPPING:
|
|
143
|
+
self.stopping_params: StoppingParameters = command.attribute
|
|
144
|
+
|
|
145
|
+
elif command.command == OptimizerToRunner.BOUNDS:
|
|
146
|
+
self.optimization_algorithm.bounds = command.attribute
|
|
147
|
+
|
|
148
|
+
def run_opti(self, sync_detectors=True, sync_acts=True):
|
|
149
|
+
"""Start the optimization loop
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
sync_detectors: (bool) if True will make sure all selected detectors (if any) all got their data before calling
|
|
154
|
+
the model
|
|
155
|
+
sync_acts: (bool) if True will make sure all selected actuators (if any) all reached their target position
|
|
156
|
+
before calling the model
|
|
157
|
+
"""
|
|
158
|
+
self.running = True
|
|
159
|
+
converged = False
|
|
160
|
+
try:
|
|
161
|
+
if sync_detectors:
|
|
162
|
+
self.modules_manager.connect_detectors()
|
|
163
|
+
if sync_acts:
|
|
164
|
+
self.modules_manager.connect_actuators()
|
|
165
|
+
|
|
166
|
+
self.current_time = time.perf_counter()
|
|
167
|
+
logger.info('Optimisation loop starting')
|
|
168
|
+
while self.running:
|
|
169
|
+
self._ind_iter += 1
|
|
170
|
+
|
|
171
|
+
next_target = self.optimization_algorithm.ask()
|
|
172
|
+
|
|
173
|
+
self.outputs = next_target
|
|
174
|
+
self.output_to_actuators: DataToActuators = \
|
|
175
|
+
self.model_class.convert_output(
|
|
176
|
+
self.outputs,
|
|
177
|
+
best_individual=self.optimization_algorithm.best_individual
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
self.modules_manager.move_actuators(self.output_to_actuators,
|
|
181
|
+
self.output_to_actuators.mode,
|
|
182
|
+
polling=sync_acts)
|
|
183
|
+
|
|
184
|
+
# Do the evaluation (measurements)
|
|
185
|
+
self.det_done_datas = self.modules_manager.grab_data()
|
|
186
|
+
self.input_from_dets = self.model_class.convert_input(self.det_done_datas)
|
|
187
|
+
|
|
188
|
+
#log data
|
|
189
|
+
self.runner_command.emit(
|
|
190
|
+
utils.ThreadCommand(OptimizerThreadStatus.ADD_DATA,))
|
|
191
|
+
|
|
192
|
+
# Run the algo internal mechanic
|
|
193
|
+
self.optimization_algorithm.tell(float(self.input_from_dets))
|
|
194
|
+
|
|
195
|
+
dte = DataToExport('algo', data=[
|
|
196
|
+
self.individual_as_data(
|
|
197
|
+
np.array([self.optimization_algorithm.best_fitness]),
|
|
198
|
+
DataNames.Fitness),
|
|
199
|
+
self.individual_as_data(
|
|
200
|
+
self.optimization_algorithm.best_individual,
|
|
201
|
+
DataNames.Individual),
|
|
202
|
+
DataCalculated(DataNames.ProbedData,
|
|
203
|
+
data=[np.array([self.input_from_dets])],),
|
|
204
|
+
self.output_to_actuators.merge_as_dwa(
|
|
205
|
+
'Data0D', DataNames.Actuators),
|
|
206
|
+
DataCalculated(DataNames.Tradeoff,
|
|
207
|
+
data=[np.array([self.optimization_algorithm.tradeoff])])
|
|
208
|
+
])
|
|
209
|
+
self.algo_output_signal.emit(dte)
|
|
210
|
+
self.saver_signal.emit(DataToActuatorsOpti(DataNames.Actuators,
|
|
211
|
+
data = self.output_to_actuators.deepcopy().data,
|
|
212
|
+
mode=self.output_to_actuators.mode,
|
|
213
|
+
ind_iter=self._ind_iter))
|
|
214
|
+
|
|
215
|
+
self.optimization_algorithm.update_prediction_function()
|
|
216
|
+
|
|
217
|
+
if self.optimization_algorithm.stopping(self._ind_iter, self.stopping_params):
|
|
218
|
+
converged = True
|
|
219
|
+
break
|
|
220
|
+
|
|
221
|
+
self.current_time = time.perf_counter()
|
|
222
|
+
QtWidgets.QApplication.processEvents()
|
|
223
|
+
QtWidgets.QApplication.processEvents()
|
|
224
|
+
logger.info('Optimisation loop exiting')
|
|
225
|
+
self.modules_manager.connect_actuators(False)
|
|
226
|
+
self.modules_manager.connect_detectors(False)
|
|
227
|
+
|
|
228
|
+
if converged:
|
|
229
|
+
self.algo_finished.emit(dte)
|
|
230
|
+
|
|
231
|
+
except Exception as e:
|
|
232
|
+
logger.exception(str(e))
|
|
233
|
+
|
|
234
|
+
@staticmethod
|
|
235
|
+
def individual_as_data(individual: np.ndarray, name: str = 'Individual') -> DataCalculated:
|
|
236
|
+
return DataCalculated(name, data=[np.atleast_1d(np.squeeze(coordinate)) for coordinate in
|
|
237
|
+
np.atleast_1d(np.squeeze(individual))])
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class GenericOptimization(CustomExt):
|
|
241
|
+
""" PyMoDAQ extension of the DashBoard to perform the optimization of a target signal
|
|
242
|
+
taken form the detectors as a function of one or more parameters controlled by the actuators.
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
command_runner = QtCore.Signal(utils.ThreadCommand)
|
|
246
|
+
explored_viewer_name = f'algo/{DataNames.ProbedData}'
|
|
247
|
+
optimization_done_signal = QtCore.Signal(DataToExport)
|
|
248
|
+
|
|
249
|
+
runner = OptimizationRunner # replace in real implementation if customization is needed
|
|
250
|
+
DISPLAY_BEST = True
|
|
251
|
+
|
|
252
|
+
params = optimizer_params(PREDICTION_PARAMS)
|
|
253
|
+
|
|
254
|
+
config_saver = OptimizerConfig #to be redefined in real implementation if needed
|
|
255
|
+
|
|
112
256
|
def __init__(self, dockarea, dashboard):
|
|
113
257
|
super().__init__(dockarea, dashboard)
|
|
114
258
|
|
|
115
|
-
self.
|
|
259
|
+
self._ini_runner = False
|
|
260
|
+
|
|
261
|
+
self.algorithm: Optional[GenericAlgorithm] = None
|
|
116
262
|
self.viewer_fitness: Optional[Viewer0D] = None
|
|
117
263
|
self.viewer_observable: Optional[ViewerDispatcher] = None
|
|
118
|
-
self.model_class: Optional[
|
|
264
|
+
self.model_class: Optional[OptimizerModelGeneric] = None
|
|
119
265
|
self._save_main_settings = True
|
|
120
266
|
self._modules_manager = ModulesManager(self.dashboard.detector_modules,
|
|
121
267
|
self.dashboard.actuators_modules)
|
|
122
268
|
self.modules_manager.actuators_changed[list].connect(self.update_actuators)
|
|
123
269
|
self.modules_manager.settings.child('data_dimensions').setOpts(expanded=False)
|
|
124
270
|
self.modules_manager.settings.child('actuators_positions').setOpts(expanded=False)
|
|
271
|
+
|
|
272
|
+
self._h5saver: H5Saver = None
|
|
273
|
+
self.h5saver.settings.child('do_save').hide()
|
|
274
|
+
self.h5saver.settings.child('custom_name').hide()
|
|
275
|
+
self.h5saver.new_file_sig.connect(self.create_new_file)
|
|
276
|
+
|
|
125
277
|
self.setup_ui()
|
|
126
278
|
|
|
127
|
-
self.
|
|
279
|
+
self.optimizer_config = self.config_saver()
|
|
280
|
+
|
|
128
281
|
self.mainsettings_saver_loader = ConfigSaverLoader(
|
|
129
|
-
self.settings.child('main_settings'), self.
|
|
282
|
+
self.settings.child('main_settings'), self.optimizer_config)
|
|
283
|
+
|
|
284
|
+
self._base_name: str = None
|
|
130
285
|
|
|
131
286
|
self.h5temp: H5Saver = None
|
|
132
287
|
self.temp_path: tempfile.TemporaryDirectory = None
|
|
133
|
-
|
|
134
288
|
self.enlargeable_saver: DataEnlargeableSaver = None
|
|
135
289
|
self.live_plotter = LoaderPlotter(self.dockarea)
|
|
136
290
|
|
|
291
|
+
self._module_and_data_saver: module_saving.OptimizerSaver = None
|
|
292
|
+
|
|
293
|
+
self._ind_iter: int = 0
|
|
137
294
|
self.enl_index = 0
|
|
138
295
|
|
|
139
296
|
self.settings.child('models', 'ini_model').sigActivated.connect(
|
|
@@ -141,6 +298,62 @@ class BayesianOptimisation(CustomExt):
|
|
|
141
298
|
|
|
142
299
|
self.settings.child('models', 'ini_runner').sigActivated.connect(
|
|
143
300
|
self.get_action('ini_runner').trigger)
|
|
301
|
+
self.ini_custom_attributes()
|
|
302
|
+
|
|
303
|
+
@property
|
|
304
|
+
def title(self):
|
|
305
|
+
return f'{self.__class__.__name__}'
|
|
306
|
+
|
|
307
|
+
def ini_custom_attributes(self):
|
|
308
|
+
""" Here you can reimplement specific attributes"""
|
|
309
|
+
self._base_name: str = 'Optimizer' # base name used for naming the hdf5 file
|
|
310
|
+
|
|
311
|
+
@property
|
|
312
|
+
def h5saver(self):
|
|
313
|
+
if self._h5saver is None:
|
|
314
|
+
self._h5saver = H5Saver(save_type='optimizer', backend=config('general', 'hdf5_backend'))
|
|
315
|
+
self._h5saver.settings.child('base_name').setValue('Optimizer')
|
|
316
|
+
if self._h5saver.h5_file is None:
|
|
317
|
+
self._h5saver.init_file(update_h5=True)
|
|
318
|
+
if not self._h5saver.isopen():
|
|
319
|
+
self._h5saver.init_file(addhoc_file_path=self._h5saver.settings['current_h5_file'])
|
|
320
|
+
return self._h5saver
|
|
321
|
+
|
|
322
|
+
@h5saver.setter
|
|
323
|
+
def h5saver(self, h5saver_temp: H5Saver):
|
|
324
|
+
self._h5saver = h5saver_temp
|
|
325
|
+
|
|
326
|
+
@property
|
|
327
|
+
def module_and_data_saver(self):
|
|
328
|
+
if not self._module_and_data_saver.h5saver.isopen():
|
|
329
|
+
self._module_and_data_saver.h5saver = self.h5saver
|
|
330
|
+
return self._module_and_data_saver
|
|
331
|
+
|
|
332
|
+
@module_and_data_saver.setter
|
|
333
|
+
def module_and_data_saver(self, mod: module_saving.OptimizerSaver):
|
|
334
|
+
self._module_and_data_saver = mod
|
|
335
|
+
self._module_and_data_saver.h5saver = self.h5saver
|
|
336
|
+
|
|
337
|
+
def create_new_file(self, new_file):
|
|
338
|
+
if new_file:
|
|
339
|
+
self.close_file()
|
|
340
|
+
self.module_and_data_saver.h5saver = self.h5saver # force all control modules to update their h5saver
|
|
341
|
+
|
|
342
|
+
def close_file(self):
|
|
343
|
+
self.h5saver.close_file()
|
|
344
|
+
|
|
345
|
+
def add_data(self, dta: DataToActuatorsOpti):
|
|
346
|
+
if self.is_action_checked('save'):
|
|
347
|
+
self.module_and_data_saver.add_data(axis_values=[dwa[0] for dwa in dta],
|
|
348
|
+
init_step=dta.ind_iter == 0)
|
|
349
|
+
|
|
350
|
+
@abc.abstractmethod
|
|
351
|
+
def validate_config(self) -> bool:
|
|
352
|
+
pass
|
|
353
|
+
|
|
354
|
+
@property
|
|
355
|
+
def config_path(self) -> Path:
|
|
356
|
+
return self.optimizer_config.config_path
|
|
144
357
|
|
|
145
358
|
@property
|
|
146
359
|
def modules_manager(self) -> ModulesManager:
|
|
@@ -160,32 +373,37 @@ class BayesianOptimisation(CustomExt):
|
|
|
160
373
|
########
|
|
161
374
|
pyqtgraph.dockarea.Dock
|
|
162
375
|
"""
|
|
376
|
+
self.docks['saving'] = gutils.Dock('Saving')
|
|
377
|
+
self.docks['saving'].addWidget(self.h5saver.settings_tree)
|
|
378
|
+
self.dockarea.addDock(self.docks['saving'])
|
|
379
|
+
|
|
163
380
|
self.docks['settings'] = gutils.Dock('Settings')
|
|
164
|
-
self.dockarea.addDock(self.docks['settings'])
|
|
165
|
-
splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
|
381
|
+
self.dockarea.addDock(self.docks['settings'], 'below', self.docks['saving'])
|
|
382
|
+
splitter = QtWidgets.QSplitter(QtCore.Qt.Orientation.Vertical)
|
|
166
383
|
self.docks['settings'].addWidget(splitter)
|
|
167
384
|
splitter.addWidget(self.settings_tree)
|
|
168
385
|
splitter.addWidget(self.modules_manager.settings_tree)
|
|
169
|
-
self.modules_manager.show_only_control_modules(
|
|
386
|
+
self.modules_manager.show_only_control_modules(True)
|
|
387
|
+
|
|
170
388
|
splitter.setSizes((int(self.dockarea.height() / 2),
|
|
171
389
|
int(self.dockarea.height() / 2)))
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if len(
|
|
183
|
-
self.get_set_model_params(
|
|
390
|
+
if self.DISPLAY_BEST:
|
|
391
|
+
widget_observable = QtWidgets.QWidget()
|
|
392
|
+
widget_observable.setLayout(QtWidgets.QHBoxLayout())
|
|
393
|
+
observable_dockarea = gutils.DockArea()
|
|
394
|
+
widget_observable.layout().addWidget(observable_dockarea)
|
|
395
|
+
self.viewer_observable = ViewerDispatcher(observable_dockarea, direction='bottom')
|
|
396
|
+
self.docks['observable'] = gutils.Dock('Observable')
|
|
397
|
+
self.dockarea.addDock(self.docks['observable'], 'right', self.docks['settings'])
|
|
398
|
+
self.docks['observable'].addWidget(widget_observable)
|
|
399
|
+
|
|
400
|
+
if len(MODELS) != 0:
|
|
401
|
+
self.get_set_model_params(MODELS[0]['name'])
|
|
184
402
|
|
|
185
403
|
def get_set_model_params(self, model_name):
|
|
186
404
|
self.settings.child('models', 'model_params').clearChildren()
|
|
187
|
-
if len(
|
|
188
|
-
model_class = utils.find_dict_in_list_from_key_val(
|
|
405
|
+
if len(MODELS) > 0:
|
|
406
|
+
model_class = utils.find_dict_in_list_from_key_val(MODELS, 'name', model_name)['class']
|
|
189
407
|
params = getattr(model_class, 'params')
|
|
190
408
|
self.settings.child('models', 'model_params').addChildren(params)
|
|
191
409
|
|
|
@@ -223,26 +441,26 @@ class BayesianOptimisation(CustomExt):
|
|
|
223
441
|
elif param.name() in putils.iter_children(self.settings.child('models', 'model_params'), []):
|
|
224
442
|
if self.model_class is not None:
|
|
225
443
|
self.model_class.update_settings(param)
|
|
226
|
-
elif param.name() in putils.iter_children(
|
|
227
|
-
self.settings.child('main_settings', 'utility'), []):
|
|
228
|
-
if param.name() != 'kappa_actual':
|
|
229
|
-
self.update_utility_function()
|
|
230
444
|
elif param.name() in putils.iter_children(
|
|
231
445
|
self.settings.child('main_settings', 'bounds'), []):
|
|
232
446
|
self.update_bounds()
|
|
233
447
|
elif param.name() in putils.iter_children(
|
|
234
448
|
self.settings.child('main_settings', 'stopping'), []):
|
|
235
449
|
self.update_stopping_criteria()
|
|
236
|
-
|
|
237
|
-
self.settings.child('main_settings'), []):
|
|
450
|
+
elif param.name() in putils.iter_children(
|
|
451
|
+
self.settings.child('main_settings', 'prediction'), []):
|
|
452
|
+
if param.name() != 'tradeoff_actual':
|
|
453
|
+
self.update_prediction_function()
|
|
454
|
+
|
|
455
|
+
if self._save_main_settings and self.model_class is not None and param.name() in putils.iter_children(
|
|
456
|
+
self.settings.child('main_settings'), []):
|
|
238
457
|
self.mainsettings_saver_loader.save_config()
|
|
239
458
|
|
|
240
|
-
def
|
|
241
|
-
utility_settings = self.settings.child('main_settings', '
|
|
242
|
-
uparams =
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
self.command_runner.emit(utils.ThreadCommand('utility', uparams))
|
|
459
|
+
def update_prediction_function(self):
|
|
460
|
+
utility_settings = self.settings.child('main_settings', 'prediction')
|
|
461
|
+
uparams = {child.name() : child.value() for child in utility_settings.children()}
|
|
462
|
+
self.command_runner.emit(
|
|
463
|
+
utils.ThreadCommand(OptimizerToRunner.PREDICTION, uparams))
|
|
246
464
|
|
|
247
465
|
def get_stopping_parameters(self) -> StoppingParameters:
|
|
248
466
|
stopping_settings = self.settings.child('main_settings', 'stopping')
|
|
@@ -253,20 +471,23 @@ class BayesianOptimisation(CustomExt):
|
|
|
253
471
|
return stopping_params
|
|
254
472
|
|
|
255
473
|
def update_stopping_criteria(self):
|
|
256
|
-
self.command_runner.emit(
|
|
474
|
+
self.command_runner.emit(
|
|
475
|
+
utils.ThreadCommand(OptimizerToRunner.STOPPING, self.get_stopping_parameters()))
|
|
257
476
|
|
|
258
477
|
def update_bounds(self):
|
|
259
478
|
bounds = {}
|
|
260
479
|
for child in self.settings.child('main_settings', 'bounds').children():
|
|
261
480
|
bounds[child.name()] = (child['min'], child['max'])
|
|
262
481
|
|
|
263
|
-
self.command_runner.emit(utils.ThreadCommand(
|
|
482
|
+
self.command_runner.emit(utils.ThreadCommand(OptimizerToRunner.BOUNDS, bounds))
|
|
264
483
|
|
|
265
484
|
def setup_actions(self):
|
|
266
485
|
logger.debug('setting actions')
|
|
267
486
|
self.add_action('quit', 'Quit', 'close2', "Quit program")
|
|
268
487
|
self.add_action('ini_model', 'Init Model', 'ini')
|
|
269
488
|
self.add_widget('model_led', QLED, toolbar=self.toolbar)
|
|
489
|
+
self.add_action('save', 'Save?', 'SaveAs', tip='If checked, data will be saved',
|
|
490
|
+
checkable=True)
|
|
270
491
|
self.add_action('ini_runner', 'Init the Optimisation Algorithm', 'ini', checkable=True,
|
|
271
492
|
enabled=False)
|
|
272
493
|
self.add_widget('runner_led', QLED, toolbar=self.toolbar)
|
|
@@ -277,24 +498,30 @@ class BayesianOptimisation(CustomExt):
|
|
|
277
498
|
|
|
278
499
|
def connect_things(self):
|
|
279
500
|
logger.debug('connecting things')
|
|
280
|
-
self.connect_action('quit', self.quit
|
|
501
|
+
self.connect_action('quit', self.quit)
|
|
281
502
|
self.connect_action('ini_model', self.ini_model)
|
|
282
|
-
self.connect_action('ini_runner', self.
|
|
283
|
-
self.connect_action('run', self.
|
|
503
|
+
self.connect_action('ini_runner', self.ini_optimization_runner)
|
|
504
|
+
self.connect_action('run', self.run_optimization)
|
|
284
505
|
self.connect_action('gotobest', self.go_to_best)
|
|
506
|
+
self.connect_action('save', self.ini_saver)
|
|
507
|
+
self.h5saver.new_file_sig.connect(self.create_new_file)
|
|
285
508
|
|
|
286
509
|
def go_to_best(self):
|
|
287
510
|
best_individual = self.algorithm.best_individual
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
511
|
+
if best_individual is not None:
|
|
512
|
+
actuators = self.modules_manager.selected_actuators_name
|
|
513
|
+
dte_act = DataToActuators('best',
|
|
514
|
+
data=[
|
|
515
|
+
DataActuator(actuators[ind],
|
|
516
|
+
data=float(best_individual[ind]))
|
|
517
|
+
for ind in range(len(best_individual))
|
|
518
|
+
],
|
|
519
|
+
mode='abs')
|
|
520
|
+
self.modules_manager.connect_actuators(True)
|
|
521
|
+
self.modules_manager.move_actuators(dte_act, polling=True)
|
|
522
|
+
self.modules_manager.connect_actuators(False)
|
|
296
523
|
|
|
297
|
-
|
|
524
|
+
self.modules_manager.grab_datas()
|
|
298
525
|
|
|
299
526
|
def quit(self):
|
|
300
527
|
self.dockarea.parent().close()
|
|
@@ -303,7 +530,7 @@ class BayesianOptimisation(CustomExt):
|
|
|
303
530
|
def set_model(self):
|
|
304
531
|
model_name = self.settings.child('models', 'model_class').value()
|
|
305
532
|
self.model_class = utils.find_dict_in_list_from_key_val(
|
|
306
|
-
|
|
533
|
+
MODELS, 'name', model_name)['class'](self)
|
|
307
534
|
self.model_class.ini_model_base()
|
|
308
535
|
|
|
309
536
|
def ini_temp_file(self):
|
|
@@ -350,7 +577,7 @@ class BayesianOptimisation(CustomExt):
|
|
|
350
577
|
|
|
351
578
|
QtWidgets.QApplication.processEvents()
|
|
352
579
|
win_width = self.dockarea.width()
|
|
353
|
-
self.docks['settings'].container().setSizes((int(win_width / 5),
|
|
580
|
+
self.docks['settings'].container().parent().setSizes((int(win_width / 5),
|
|
354
581
|
int(2 * win_width / 5),
|
|
355
582
|
int(2 * win_width / 5), 10, 10))
|
|
356
583
|
|
|
@@ -370,21 +597,34 @@ class BayesianOptimisation(CustomExt):
|
|
|
370
597
|
{'title': 'max', 'name': 'max', 'type': 'float', 'value': 5},
|
|
371
598
|
]})
|
|
372
599
|
self.settings.child('main_settings', 'bounds').addChildren(params)
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
600
|
+
|
|
601
|
+
try:
|
|
602
|
+
self.mainsettings_saver_loader.base_path = [self.model_class.__class__.__name__] + \
|
|
603
|
+
self.modules_manager.selected_actuators_name
|
|
604
|
+
self.mainsettings_saver_loader.load_config()
|
|
605
|
+
self._save_main_settings = True
|
|
606
|
+
except Exception as e:
|
|
607
|
+
logger.exception(f'Could not load the configuration')
|
|
608
|
+
|
|
609
|
+
self.update_after_actuators_changed(self.modules_manager.selected_actuators_name)
|
|
610
|
+
|
|
611
|
+
@abc.abstractmethod
|
|
612
|
+
def update_after_actuators_changed(self, actuators: list[str]):
|
|
613
|
+
""" Actions to do after the actuators have been updated
|
|
614
|
+
|
|
615
|
+
To be implemented
|
|
616
|
+
"""
|
|
617
|
+
...
|
|
377
618
|
|
|
378
619
|
def format_bounds(self):
|
|
379
|
-
bound_dict =
|
|
620
|
+
bound_dict = OrderedDict([])
|
|
380
621
|
for bound in self.settings.child('main_settings', 'bounds').children():
|
|
381
622
|
bound_dict.update({bound.name(): (bound['min'], bound['max'])})
|
|
382
623
|
return bound_dict
|
|
383
624
|
|
|
625
|
+
@abc.abstractmethod
|
|
384
626
|
def set_algorithm(self):
|
|
385
|
-
self.algorithm =
|
|
386
|
-
ini_random=self.settings['main_settings', 'ini_random'],
|
|
387
|
-
bounds=self.format_bounds(),)
|
|
627
|
+
self.algorithm = ...
|
|
388
628
|
|
|
389
629
|
def ini_model(self):
|
|
390
630
|
try:
|
|
@@ -398,8 +638,9 @@ class BayesianOptimisation(CustomExt):
|
|
|
398
638
|
self.get_action('model_led').set_as_true()
|
|
399
639
|
self.set_action_enabled('ini_model', False)
|
|
400
640
|
|
|
401
|
-
self.
|
|
402
|
-
|
|
641
|
+
if self.DISPLAY_BEST:
|
|
642
|
+
self.viewer_observable.update_viewers(['Viewer0D', 'Viewer0D'],
|
|
643
|
+
['Fitness', 'Individual'])
|
|
403
644
|
self.settings.child('models', 'ini_model').setValue(True)
|
|
404
645
|
self.settings.child('models', 'ini_runner').setOpts(enabled=True)
|
|
405
646
|
self.set_action_enabled('ini_runner', True)
|
|
@@ -416,37 +657,68 @@ class BayesianOptimisation(CustomExt):
|
|
|
416
657
|
except Exception as e:
|
|
417
658
|
logger.exception(str(e))
|
|
418
659
|
|
|
419
|
-
def
|
|
420
|
-
if self.is_action_checked('
|
|
421
|
-
self.
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
self.
|
|
425
|
-
|
|
426
|
-
self.ini_temp_file()
|
|
427
|
-
self.ini_live_plot()
|
|
428
|
-
|
|
429
|
-
self.runner_thread = QtCore.QThread()
|
|
430
|
-
runner = OptimisationRunner(self.model_class, self.modules_manager, self.algorithm,
|
|
431
|
-
self.get_stopping_parameters())
|
|
432
|
-
self.runner_thread.runner = runner
|
|
433
|
-
runner.algo_output_signal.connect(self.process_output)
|
|
434
|
-
runner.algo_finished.connect(self.optimisation_done)
|
|
435
|
-
self.command_runner.connect(runner.queue_command)
|
|
660
|
+
def ini_saver(self):
|
|
661
|
+
if self.is_action_checked('save'):
|
|
662
|
+
self.module_and_data_saver = module_saving.OptimizerSaver(
|
|
663
|
+
self, enl_axis_names=self.modules_manager.selected_actuators_name,
|
|
664
|
+
enl_axis_units=[act.units for act in self.modules_manager.actuators])
|
|
665
|
+
self.create_new_file(True)
|
|
666
|
+
self.module_and_data_saver.h5saver = self.h5saver
|
|
436
667
|
|
|
437
|
-
|
|
668
|
+
def ini_optimization_runner(self):
|
|
669
|
+
if self.is_action_checked('ini_runner'):
|
|
438
670
|
|
|
439
|
-
self.
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
671
|
+
if not self._ini_runner:
|
|
672
|
+
self._ini_runner = True
|
|
673
|
+
self.set_algorithm()
|
|
674
|
+
|
|
675
|
+
if self.is_action_checked('save'):
|
|
676
|
+
node = self.module_and_data_saver.get_set_node(new=True)
|
|
677
|
+
self.h5saver.settings.child('current_scan_name').setValue(node.name)
|
|
678
|
+
|
|
679
|
+
self.settings.child('models', 'ini_runner').setValue(True)
|
|
680
|
+
self.enl_index = 0
|
|
681
|
+
|
|
682
|
+
self.ini_temp_file()
|
|
683
|
+
self.ini_live_plot()
|
|
684
|
+
|
|
685
|
+
self.runner_thread = QtCore.QThread()
|
|
686
|
+
runner = self.runner(self.model_class, self.modules_manager, self.algorithm,
|
|
687
|
+
self.get_stopping_parameters())
|
|
688
|
+
self.runner_thread.runner = runner
|
|
689
|
+
runner.algo_output_signal.connect(self.process_output)
|
|
690
|
+
runner.algo_finished.connect(self.optimization_done)
|
|
691
|
+
runner.runner_command.connect(self.thread_status)
|
|
692
|
+
runner.saver_signal.connect(self.add_data)
|
|
693
|
+
self.command_runner.connect(runner.queue_command)
|
|
694
|
+
|
|
695
|
+
runner.moveToThread(self.runner_thread)
|
|
696
|
+
|
|
697
|
+
self.runner_thread.start()
|
|
698
|
+
self.get_action('runner_led').set_as_true()
|
|
699
|
+
self.set_action_enabled('run', True)
|
|
700
|
+
self.model_class.runner_initialized()
|
|
701
|
+
self.update_prediction_function()
|
|
444
702
|
else:
|
|
445
703
|
if self.is_action_checked('run'):
|
|
446
704
|
self.get_action('run').trigger()
|
|
447
705
|
QtWidgets.QApplication.processEvents()
|
|
448
|
-
|
|
706
|
+
|
|
707
|
+
self.splash.setVisible(True)
|
|
708
|
+
self.splash.showMessage('Quitting Runner Thread')
|
|
709
|
+
try:
|
|
710
|
+
self.command_runner.disconnect()
|
|
711
|
+
except TypeError:
|
|
712
|
+
pass
|
|
713
|
+
self.runner_thread.quit()
|
|
714
|
+
self.runner_thread.wait(5000)
|
|
715
|
+
if not self.runner_thread.isFinished():
|
|
716
|
+
self.runner_thread.terminate()
|
|
717
|
+
self.runner_thread.wait()
|
|
718
|
+
self.runner_thread = None
|
|
719
|
+
self.splash.setVisible(False)
|
|
449
720
|
self.get_action('runner_led').set_as_false()
|
|
721
|
+
self._ini_runner = False
|
|
450
722
|
|
|
451
723
|
def clean_h5_temp(self):
|
|
452
724
|
if self.temp_path is not None:
|
|
@@ -456,30 +728,30 @@ class BayesianOptimisation(CustomExt):
|
|
|
456
728
|
except Exception as e:
|
|
457
729
|
logger.exception(str(e))
|
|
458
730
|
|
|
459
|
-
def
|
|
731
|
+
def optimization_done(self, dte: DataToExport):
|
|
460
732
|
self.go_to_best()
|
|
461
|
-
self.
|
|
733
|
+
self.optimization_done_signal.emit(dte)
|
|
462
734
|
|
|
463
735
|
def process_output(self, dte: DataToExport):
|
|
464
736
|
|
|
465
737
|
self.enl_index += 1
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
738
|
+
try:
|
|
739
|
+
dwa_tradeoff = dte.remove(dte.get_data_from_name(DataNames.Tradeoff))
|
|
740
|
+
self.settings.child('main_settings', 'prediction', 'tradeoff_actual').setValue(
|
|
741
|
+
float(dwa_tradeoff[0][0])
|
|
742
|
+
)
|
|
743
|
+
except KeyError:
|
|
744
|
+
pass
|
|
745
|
+
dwa_data = dte.remove(dte.get_data_from_name(DataNames.ProbedData))
|
|
746
|
+
dwa_actuators: DataActuator = dte.remove(dte.get_data_from_name(DataNames.Actuators))
|
|
747
|
+
if self.DISPLAY_BEST:
|
|
748
|
+
self.viewer_observable.show_data(dte)
|
|
474
749
|
|
|
475
|
-
# dwa_observations = self.algorithm.get_dwa_obervations(
|
|
476
|
-
# self.modules_manager.selected_actuators_name)
|
|
477
750
|
self.model_class.update_plots()
|
|
478
751
|
|
|
479
|
-
best_individual = dte.get_data_from_name(DataNames.Individual
|
|
752
|
+
best_individual = dte.get_data_from_name(DataNames.Individual)
|
|
480
753
|
best_indiv_as_list = [float(best_individual[ind][0]) for ind in range(len(best_individual))]
|
|
481
754
|
|
|
482
|
-
|
|
483
755
|
self.enlargeable_saver.add_data('/RawData', dwa_data,
|
|
484
756
|
axis_values=dwa_actuators.values())
|
|
485
757
|
if len(best_indiv_as_list) == 1 or (
|
|
@@ -495,191 +767,26 @@ class BayesianOptimisation(CustomExt):
|
|
|
495
767
|
def enable_controls_opti(self, enable: bool):
|
|
496
768
|
pass
|
|
497
769
|
|
|
498
|
-
def
|
|
770
|
+
def run_optimization(self):
|
|
499
771
|
if self.is_action_checked('run'):
|
|
772
|
+
self.set_action_enabled('save', False)
|
|
500
773
|
self.get_action('run').set_icon('pause')
|
|
501
|
-
self.
|
|
774
|
+
self.set_action_checked('gotobest', False)
|
|
775
|
+
self.set_action_enabled('gotobest', False)
|
|
776
|
+
self.command_runner.emit(utils.ThreadCommand(OptimizerToRunner.START))
|
|
502
777
|
QtWidgets.QApplication.processEvents()
|
|
503
778
|
QtWidgets.QApplication.processEvents()
|
|
504
|
-
self.command_runner.emit(utils.ThreadCommand(
|
|
779
|
+
self.command_runner.emit(utils.ThreadCommand(OptimizerToRunner.RUN))
|
|
505
780
|
else:
|
|
506
781
|
self.get_action('run').set_icon('run2')
|
|
507
|
-
self.
|
|
782
|
+
self.set_action_enabled('save', True)
|
|
783
|
+
self.command_runner.emit(utils.ThreadCommand(OptimizerToRunner.STOP))
|
|
508
784
|
self.set_action_enabled('gotobest', True)
|
|
509
|
-
|
|
510
|
-
QtWidgets.QApplication.processEvents()
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
class OptimisationRunner(QtCore.QObject):
|
|
514
|
-
algo_output_signal = QtCore.Signal(DataToExport)
|
|
515
|
-
algo_finished = QtCore.Signal(DataToExport)
|
|
516
|
-
|
|
517
|
-
def __init__(self, model_class: BayesianModelGeneric, modules_manager: ModulesManager,
|
|
518
|
-
algorithm: BayesianAlgorithm, stopping_params: StoppingParameters):
|
|
519
|
-
super().__init__()
|
|
520
|
-
|
|
521
|
-
self.det_done_datas: DataToExport = None
|
|
522
|
-
self.input_from_dets: float = None
|
|
523
|
-
self.outputs: List[np.ndarray] = []
|
|
524
|
-
self.dte_actuators: DataToExport = None
|
|
525
|
-
self.stopping_params: StoppingParameters = stopping_params
|
|
526
|
-
|
|
527
|
-
self.model_class: BayesianModelGeneric = model_class
|
|
528
|
-
self.modules_manager: ModulesManager = modules_manager
|
|
529
|
-
|
|
530
|
-
self.running = True
|
|
531
|
-
|
|
532
|
-
self.optimisation_algorithm: BayesianAlgorithm = algorithm
|
|
533
|
-
|
|
534
|
-
self._ind_iter: int = 0
|
|
535
|
-
|
|
536
|
-
@QtCore.Slot(utils.ThreadCommand)
|
|
537
|
-
def queue_command(self, command: utils.ThreadCommand):
|
|
538
|
-
"""
|
|
539
|
-
"""
|
|
540
|
-
if command.command == "run":
|
|
541
|
-
self.run_opti(**command.attribute)
|
|
542
|
-
|
|
543
|
-
elif command.command == "stop":
|
|
544
|
-
self.running = False
|
|
545
|
-
|
|
546
|
-
elif command.command == 'utility':
|
|
547
|
-
utility_params: UtilityParameters = command.attribute
|
|
548
|
-
self.optimisation_algorithm.set_utility_function(
|
|
549
|
-
utility_params.kind,
|
|
550
|
-
kappa=utility_params.kappa,
|
|
551
|
-
xi=utility_params.xi,
|
|
552
|
-
kappa_decay=utility_params.kappa_decay,
|
|
553
|
-
kappa_decay_delay=utility_params.kappa_decay_delay)
|
|
554
|
-
|
|
555
|
-
elif command.command == 'stopping':
|
|
556
|
-
self.stopping_params: StoppingParameters = command.attribute
|
|
557
|
-
|
|
558
|
-
elif command.command == 'bounds':
|
|
559
|
-
self.optimisation_algorithm.set_bounds(command.attribute)
|
|
560
|
-
|
|
561
|
-
def run_opti(self, sync_detectors=True, sync_acts=True):
|
|
562
|
-
"""Start the optimisation loop
|
|
563
|
-
|
|
564
|
-
Parameters
|
|
565
|
-
----------
|
|
566
|
-
sync_detectors: (bool) if True will make sure all selected detectors (if any) all got their data before calling
|
|
567
|
-
the model
|
|
568
|
-
sync_acts: (bool) if True will make sure all selected actuators (if any) all reached their target position
|
|
569
|
-
before calling the model
|
|
570
|
-
"""
|
|
571
|
-
self.running = True
|
|
572
|
-
converged = False
|
|
573
|
-
try:
|
|
574
|
-
if sync_detectors:
|
|
575
|
-
self.modules_manager.connect_detectors()
|
|
576
|
-
if sync_acts:
|
|
577
|
-
self.modules_manager.connect_actuators()
|
|
578
|
-
|
|
579
|
-
self.current_time = time.perf_counter()
|
|
580
|
-
logger.info('Optimisation loop starting')
|
|
581
|
-
while self.running:
|
|
582
|
-
self._ind_iter += 1
|
|
583
|
-
|
|
584
|
-
next_target = self.optimisation_algorithm.ask()
|
|
585
|
-
|
|
586
|
-
self.outputs = next_target
|
|
587
|
-
self.output_to_actuators: DataToActuators =\
|
|
588
|
-
self.model_class.convert_output(
|
|
589
|
-
self.outputs,
|
|
590
|
-
best_individual=self.optimisation_algorithm.best_individual
|
|
591
|
-
)
|
|
592
|
-
|
|
593
|
-
self.modules_manager.move_actuators(self.output_to_actuators,
|
|
594
|
-
self.output_to_actuators.mode,
|
|
595
|
-
polling=sync_acts)
|
|
596
|
-
|
|
597
|
-
# Do the evaluation (measurements)
|
|
598
|
-
self.det_done_datas = self.modules_manager.grab_data()
|
|
599
|
-
self.input_from_dets = self.model_class.convert_input(self.det_done_datas)
|
|
600
|
-
|
|
601
|
-
# Run the algo internal mechanic
|
|
602
|
-
self.optimisation_algorithm.tell(float(self.input_from_dets))
|
|
603
|
-
|
|
604
|
-
dte = DataToExport('algo',
|
|
605
|
-
data=[self.individual_as_data(
|
|
606
|
-
np.array([self.optimisation_algorithm.best_fitness]),
|
|
607
|
-
DataNames.Fitness.name),
|
|
608
|
-
self.individual_as_data(
|
|
609
|
-
self.optimisation_algorithm.best_individual,
|
|
610
|
-
DataNames.Individual.name),
|
|
611
|
-
DataCalculated(DataNames.ProbedData.name,
|
|
612
|
-
data=[np.array([self.input_from_dets])],
|
|
613
|
-
),
|
|
614
|
-
self.output_to_actuators.merge_as_dwa(
|
|
615
|
-
'Data0D', DataNames.Actuators.name),
|
|
616
|
-
DataCalculated(
|
|
617
|
-
DataNames.Kappa.name,
|
|
618
|
-
data=[
|
|
619
|
-
np.array([self.optimisation_algorithm.kappa])])
|
|
620
|
-
])
|
|
621
|
-
self.algo_output_signal.emit(dte)
|
|
622
|
-
|
|
623
|
-
self.optimisation_algorithm.update_utility_function()
|
|
624
|
-
|
|
625
|
-
if self.optimisation_algorithm.stopping(self._ind_iter, self.stopping_params):
|
|
626
|
-
converged = True
|
|
627
|
-
break
|
|
628
|
-
|
|
629
|
-
self.current_time = time.perf_counter()
|
|
630
785
|
QtWidgets.QApplication.processEvents()
|
|
631
786
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
self.modules_manager.connect_detectors(False)
|
|
635
|
-
|
|
636
|
-
if converged:
|
|
637
|
-
self.algo_finished.emit(dte)
|
|
638
|
-
|
|
639
|
-
except Exception as e:
|
|
640
|
-
logger.exception(str(e))
|
|
641
|
-
|
|
642
|
-
@staticmethod
|
|
643
|
-
def individual_as_data(individual: np.ndarray, name: str = 'Individual') -> DataCalculated:
|
|
644
|
-
return DataCalculated(name, data=[np.atleast_1d(np.squeeze(coordinate)) for coordinate in
|
|
645
|
-
np.atleast_1d(np.squeeze(individual))])
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
def main(init_qt=True):
|
|
649
|
-
import sys
|
|
650
|
-
from pathlib import Path
|
|
651
|
-
from pymodaq.utils.daq_utils import get_set_preset_path
|
|
652
|
-
|
|
653
|
-
if init_qt: # used for the test suite
|
|
654
|
-
app = mkQApp("PyMoDAQ Dashboard")
|
|
655
|
-
|
|
656
|
-
from pymodaq.dashboard import DashBoard
|
|
657
|
-
|
|
658
|
-
win = QtWidgets.QMainWindow()
|
|
659
|
-
area = gutils.dock.DockArea()
|
|
660
|
-
win.setCentralWidget(area)
|
|
661
|
-
win.resize(1000, 500)
|
|
662
|
-
|
|
663
|
-
dashboard = DashBoard(area)
|
|
664
|
-
daq_scan = None
|
|
665
|
-
file = Path(get_set_preset_path()).joinpath(f"{'beam_steering_mock'}.xml")
|
|
666
|
-
|
|
667
|
-
if file.exists():
|
|
668
|
-
dashboard.set_preset_mode(file)
|
|
669
|
-
daq_scan = dashboard.load_bayesian()
|
|
670
|
-
else:
|
|
671
|
-
msgBox = QtWidgets.QMessageBox()
|
|
672
|
-
msgBox.setText(f"The default file specified in the configuration file does not exists!\n"
|
|
673
|
-
f"{file}\n"
|
|
674
|
-
f"Impossible to load the DAQScan Module")
|
|
675
|
-
msgBox.setStandardButtons(msgBox.Ok)
|
|
676
|
-
ret = msgBox.exec()
|
|
787
|
+
def thread_status(self, status: utils.ThreadCommand):
|
|
788
|
+
pass
|
|
677
789
|
|
|
678
|
-
if init_qt:
|
|
679
|
-
sys.exit(app.exec_())
|
|
680
|
-
return dashboard, daq_scan, win
|
|
681
790
|
|
|
682
791
|
|
|
683
|
-
if __name__ == '__main__':
|
|
684
|
-
main()
|
|
685
792
|
|