pymodaq 5.0.0__py3-none-any.whl → 5.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.
- pymodaq/__init__.py +55 -89
- pymodaq/control_modules/daq_move.py +123 -52
- pymodaq/control_modules/daq_move_ui.py +42 -11
- pymodaq/control_modules/daq_viewer.py +30 -13
- pymodaq/control_modules/move_utility_classes.py +345 -78
- pymodaq/control_modules/utils.py +26 -9
- pymodaq/control_modules/viewer_utility_classes.py +51 -14
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +532 -263
- pymodaq/examples/qt_less_standalone_module.py +128 -0
- pymodaq/extensions/bayesian/bayesian_optimisation.py +30 -21
- pymodaq/extensions/bayesian/utils.py +6 -3
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/daq_logger.py +4 -5
- pymodaq/extensions/daq_scan.py +1 -3
- pymodaq/extensions/daq_scan_ui.py +7 -9
- pymodaq/extensions/pid/__init__.py +0 -1
- pymodaq/extensions/pid/actuator_controller.py +13 -0
- pymodaq/extensions/pid/daq_move_PID.py +25 -46
- pymodaq/extensions/pid/pid_controller.py +48 -40
- pymodaq/extensions/pid/utils.py +3 -2
- pymodaq/extensions/utils.py +41 -7
- pymodaq/resources/setup_plugin.py +1 -0
- pymodaq/updater.py +107 -0
- pymodaq/utils/chrono_timer.py +6 -7
- pymodaq/utils/daq_utils.py +6 -3
- pymodaq/utils/data.py +11 -16
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/gui_utils/loader_utils.py +27 -2
- pymodaq/utils/gui_utils/utils.py +9 -12
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +21 -14
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +13 -8
- pymodaq/utils/leco/pymodaq_listener.py +8 -7
- pymodaq/utils/leco/utils.py +33 -7
- pymodaq/utils/managers/modules_manager.py +20 -10
- pymodaq/utils/managers/overshoot_manager.py +45 -1
- pymodaq/utils/managers/preset_manager.py +22 -46
- pymodaq/utils/managers/preset_manager_utils.py +17 -13
- pymodaq/utils/managers/remote_manager.py +1 -1
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +5 -1
- pymodaq/utils/tcp_ip/mysocket.py +4 -110
- pymodaq/utils/tcp_ip/serializer.py +4 -769
- pymodaq/utils/tcp_ip/tcp_server_client.py +5 -5
- pymodaq-5.0.1.dist-info/METADATA +242 -0
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.1.dist-info}/RECORD +51 -52
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.1.dist-info}/WHEEL +1 -1
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.1.dist-info}/entry_points.txt +1 -0
- pymodaq/examples/custom_app.py +0 -255
- pymodaq/examples/custom_viewer.py +0 -112
- pymodaq/examples/parameter_ex.py +0 -158
- pymodaq/examples/preset_MockCamera.xml +0 -1
- pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.py +0 -142
- pymodaq/post_treatment/daq_measurement/daq_measurement_GUI.ui +0 -232
- pymodaq/post_treatment/daq_measurement/daq_measurement_main.py +0 -391
- pymodaq/post_treatment/daq_measurement/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -2
- pymodaq-5.0.0.dist-info/METADATA +0 -166
- /pymodaq/{post_treatment/daq_measurement → daq_utils}/__init__.py +0 -0
- {pymodaq-5.0.0.dist-info → pymodaq-5.0.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from functools import partial # needed for the button to sync setpoint with currpoint
|
|
3
|
+
from typing import Dict, List, TYPE_CHECKING
|
|
4
|
+
|
|
3
5
|
import numpy as np
|
|
4
6
|
|
|
5
7
|
from qtpy import QtGui, QtWidgets
|
|
@@ -9,13 +11,14 @@ from simple_pid import PID
|
|
|
9
11
|
|
|
10
12
|
from pymodaq_utils.logger import set_logger, get_module_name
|
|
11
13
|
from pymodaq_utils.utils import ThreadCommand, find_dict_in_list_from_key_val
|
|
14
|
+
from pymodaq.utils.exceptions import DetectorError, ActuatorError, PIDError
|
|
12
15
|
|
|
13
16
|
from pymodaq_gui.parameter import utils as putils
|
|
14
17
|
from pymodaq_gui.parameter import Parameter, ParameterTree
|
|
15
18
|
from pymodaq_gui.plotting.data_viewers.viewer0D import Viewer0D
|
|
16
19
|
from pymodaq_gui.utils.widgets import QLED, LabelWithFont, SpinBox
|
|
17
20
|
from pymodaq_gui.utils.dock import DockArea, Dock
|
|
18
|
-
|
|
21
|
+
|
|
19
22
|
|
|
20
23
|
from pymodaq_data.data import DataToExport, DataCalculated, DataRaw
|
|
21
24
|
from pymodaq_utils.config import Config
|
|
@@ -23,6 +26,11 @@ from pymodaq_utils.config import Config
|
|
|
23
26
|
from pymodaq.utils.managers.modules_manager import ModulesManager
|
|
24
27
|
from pymodaq.extensions.pid.utils import get_models
|
|
25
28
|
from pymodaq.utils.data import DataActuator, DataToActuators
|
|
29
|
+
from pymodaq.extensions.pid.actuator_controller import PIDController
|
|
30
|
+
from pymodaq.extensions.utils import CustomExt
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from pymodaq.control_modules.daq_move import DAQ_Move
|
|
26
34
|
|
|
27
35
|
|
|
28
36
|
config = Config()
|
|
@@ -38,7 +46,7 @@ def convert_output_limits(lim_min=-10., min_status=False, lim_max=10., max_statu
|
|
|
38
46
|
return output
|
|
39
47
|
|
|
40
48
|
|
|
41
|
-
class DAQ_PID(
|
|
49
|
+
class DAQ_PID(CustomExt):
|
|
42
50
|
"""
|
|
43
51
|
"""
|
|
44
52
|
command_pid = Signal(ThreadCommand)
|
|
@@ -170,7 +178,7 @@ class DAQ_PID(CustomApp):
|
|
|
170
178
|
self.set_action_enabled('run', enable)
|
|
171
179
|
self.set_action_enabled('pause', enable)
|
|
172
180
|
|
|
173
|
-
def setup_menu(self):
|
|
181
|
+
def setup_menu(self, menubar: QtWidgets.QMenuBar = None):
|
|
174
182
|
'''
|
|
175
183
|
to be subclassed
|
|
176
184
|
create menu for actions contained into the self.actions_manager, for instance:
|
|
@@ -241,6 +249,7 @@ class DAQ_PID(CustomApp):
|
|
|
241
249
|
logger.debug('connecting actions and other')
|
|
242
250
|
self.connect_action('quit', self.quit_fun, )
|
|
243
251
|
self.connect_action('ini_model', self.ini_model)
|
|
252
|
+
self.connect_action('create_setp_actuators', self.create_setp_actuators)
|
|
244
253
|
self.connect_action('ini_pid', self.ini_PID)
|
|
245
254
|
self.connect_action('run', self.run_PID)
|
|
246
255
|
self.connect_action('pause', self.pause_PID)
|
|
@@ -252,12 +261,21 @@ class DAQ_PID(CustomApp):
|
|
|
252
261
|
self.add_widget('model_label', QtWidgets.QLabel, 'Init Model:')
|
|
253
262
|
self.add_action('ini_model', 'Init Model', 'ini', tip='Initialize the selected model: algo/data conversion')
|
|
254
263
|
self.add_widget('model_led', QLED, toolbar=self.toolbar)
|
|
264
|
+
|
|
265
|
+
self.add_action('create_setp_actuators', 'Create SetPoint Actuators', 'Add_Step',
|
|
266
|
+
tip='Create a DAQ_Move Control Module for each SetPoint allowing to'
|
|
267
|
+
'control them from the DashBoard, therefore within other extensions')
|
|
268
|
+
|
|
255
269
|
self.add_widget('model_label', QtWidgets.QLabel, 'Init PID Runner:')
|
|
256
|
-
self.add_action('ini_pid', 'Init the PID loop', 'ini', tip='Init the PID thread',
|
|
270
|
+
self.add_action('ini_pid', 'Init the PID loop', 'ini', tip='Init the PID thread',
|
|
271
|
+
checkable=True)
|
|
257
272
|
self.add_widget('pid_led', QLED, toolbar=self.toolbar)
|
|
258
|
-
self.add_action('run', 'Run The PID loop', 'run2', tip='run or stop the pid loop',
|
|
259
|
-
|
|
273
|
+
self.add_action('run', 'Run The PID loop', 'run2', tip='run or stop the pid loop',
|
|
274
|
+
checkable=True)
|
|
275
|
+
self.add_action('pause', 'Pause the PID loop', 'pause', tip='Pause the PID loop',
|
|
276
|
+
checkable=True)
|
|
260
277
|
self.set_action_checked('pause', True)
|
|
278
|
+
self.set_action_enabled('create_setp_actuators', False)
|
|
261
279
|
logger.debug('actions set')
|
|
262
280
|
|
|
263
281
|
def setup_docks(self):
|
|
@@ -297,6 +315,17 @@ class DAQ_PID(CustomApp):
|
|
|
297
315
|
|
|
298
316
|
self.dock_pid.addWidget(widget)
|
|
299
317
|
|
|
318
|
+
def create_setp_actuators(self):
|
|
319
|
+
# Now that we have the module manager, load PID if it is checked in managers
|
|
320
|
+
try:
|
|
321
|
+
for setp in self.model_class.setpoints_names:
|
|
322
|
+
self.dashboard.add_move_from_extension(setp, 'PID', PIDController(self))
|
|
323
|
+
self.set_action_enabled('create_setp_actuators', False)
|
|
324
|
+
|
|
325
|
+
except Exception as e:
|
|
326
|
+
raise PIDError('Could not load the PID extension and create setpoints actuators'
|
|
327
|
+
f'{str(e)}')
|
|
328
|
+
|
|
300
329
|
def get_set_model_params(self, model_name):
|
|
301
330
|
self.settings.child('models', 'model_params').clearChildren()
|
|
302
331
|
models = get_models()
|
|
@@ -355,6 +384,7 @@ class DAQ_PID(CustomApp):
|
|
|
355
384
|
self.enable_controls_pid(True)
|
|
356
385
|
self.get_action('model_led').set_as_true()
|
|
357
386
|
self.set_action_enabled('ini_model', False)
|
|
387
|
+
self.set_action_enabled('create_setp_actuators', True)
|
|
358
388
|
|
|
359
389
|
except Exception as e:
|
|
360
390
|
logger.exception(str(e))
|
|
@@ -368,10 +398,10 @@ class DAQ_PID(CustomApp):
|
|
|
368
398
|
for ind, sp in enumerate(self.setpoints_sb):
|
|
369
399
|
sp.setValue(values[ind])
|
|
370
400
|
|
|
371
|
-
def setpoints_external(self, values_dict):
|
|
401
|
+
def setpoints_external(self, values_dict: Dict[str, DataActuator]):
|
|
372
402
|
for key in values_dict:
|
|
373
403
|
index = self.model_class.setpoints_names.index(key)
|
|
374
|
-
self.setpoints_sb[index].setValue(values_dict[key])
|
|
404
|
+
self.setpoints_sb[index].setValue(values_dict[key].value())
|
|
375
405
|
|
|
376
406
|
@property
|
|
377
407
|
def curr_points(self):
|
|
@@ -643,38 +673,16 @@ class PIDRunner(QObject):
|
|
|
643
673
|
|
|
644
674
|
|
|
645
675
|
if __name__ == '__main__':
|
|
646
|
-
import
|
|
647
|
-
from
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
win = QtWidgets.QMainWindow()
|
|
658
|
-
area = DockArea()
|
|
659
|
-
win.setCentralWidget(area)
|
|
660
|
-
win.resize(1000, 500)
|
|
661
|
-
win.setWindowTitle('PyMoDAQ Dashboard')
|
|
662
|
-
|
|
663
|
-
dashboard = DashBoard(area)
|
|
664
|
-
pid = None
|
|
665
|
-
file = Path(get_set_preset_path()).joinpath(f"{config('presets', 'default_preset_for_pid')}.xml")
|
|
666
|
-
if file.exists():
|
|
667
|
-
dashboard.set_preset_mode(file)
|
|
668
|
-
pid = dashboard.load_pid_module()
|
|
669
|
-
else:
|
|
670
|
-
msgBox = QtWidgets.QMessageBox()
|
|
671
|
-
msgBox.setText(f"The default file specified in the configuration file does not exists!\n"
|
|
672
|
-
f"{file}\n"
|
|
673
|
-
f"Impossible to load the DAQ_PID Module")
|
|
674
|
-
msgBox.setStandardButtons(msgBox.Ok)
|
|
675
|
-
ret = msgBox.exec()
|
|
676
|
-
|
|
677
|
-
sys.exit(app.exec_())
|
|
676
|
+
from pymodaq_gui.utils.utils import mkQApp
|
|
677
|
+
from pymodaq.utils.gui_utils.loader_utils import load_dashboard_with_preset
|
|
678
|
+
|
|
679
|
+
app = mkQApp('DAQ_PID')
|
|
680
|
+
preset_file_name = config('presets', f'default_preset_for_pid')
|
|
681
|
+
|
|
682
|
+
dashboard, extension, win = load_dashboard_with_preset(preset_file_name, 'DAQ_PID')
|
|
683
|
+
|
|
684
|
+
app.exec()
|
|
685
|
+
|
|
678
686
|
|
|
679
687
|
|
|
680
688
|
|
pymodaq/extensions/pid/utils.py
CHANGED
|
@@ -27,6 +27,7 @@ DAQ_2DViewer_Det_types = get_plugins('daq_2Dviewer')
|
|
|
27
27
|
DAQ_NDViewer_Det_types = get_plugins('daq_NDviewer')
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
|
|
30
31
|
class DataToActuatorPID(DataToActuators):
|
|
31
32
|
|
|
32
33
|
def __init__(self, *args, **kwargs):
|
|
@@ -181,8 +182,8 @@ def get_models(model_name=None):
|
|
|
181
182
|
"""
|
|
182
183
|
from pymodaq.extensions.pid.utils import PIDModelGeneric
|
|
183
184
|
models_import = []
|
|
184
|
-
discovered_models = get_entrypoints(group='pymodaq.pid_models')
|
|
185
|
-
discovered_models
|
|
185
|
+
discovered_models = list(get_entrypoints(group='pymodaq.pid_models'))
|
|
186
|
+
discovered_models.extend(list(get_entrypoints(group='pymodaq.models')))
|
|
186
187
|
if len(discovered_models) > 0:
|
|
187
188
|
for pkg in discovered_models:
|
|
188
189
|
try:
|
pymodaq/extensions/utils.py
CHANGED
|
@@ -8,14 +8,22 @@ import importlib
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
import pkgutil
|
|
10
10
|
import warnings
|
|
11
|
+
from typing import Union, TYPE_CHECKING
|
|
11
12
|
|
|
12
|
-
from
|
|
13
|
+
from qtpy import QtCore, QtWidgets
|
|
13
14
|
|
|
15
|
+
from pymodaq_gui.utils.dock import DockArea
|
|
16
|
+
from pymodaq_utils.utils import get_entrypoints
|
|
14
17
|
from pymodaq_utils import logger as logger_module
|
|
18
|
+
from pymodaq_gui.utils.custom_app import CustomApp
|
|
15
19
|
|
|
20
|
+
from pymodaq.utils.managers.modules_manager import ModulesManager
|
|
16
21
|
|
|
17
22
|
logger = logger_module.set_logger(logger_module.get_module_name(__file__))
|
|
18
23
|
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from pymodaq.dashboard import DashBoard
|
|
26
|
+
|
|
19
27
|
|
|
20
28
|
def get_ext_modules(path: Path):
|
|
21
29
|
modules = []
|
|
@@ -47,13 +55,39 @@ def get_extensions():
|
|
|
47
55
|
module = importlib.import_module(pkg.value)
|
|
48
56
|
modules = get_ext_modules(Path(module.__path__[0]).joinpath('extensions'))
|
|
49
57
|
for mod in modules:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
try:
|
|
59
|
+
mod_in = importlib.import_module(f'{pkg.value}.extensions.{mod}')
|
|
60
|
+
if hasattr(mod_in, 'EXTENSION_NAME'):
|
|
61
|
+
extension_import.append({'pkg': pkg.value, 'module': mod,
|
|
62
|
+
'name': mod_in.EXTENSION_NAME,
|
|
63
|
+
'class_name': mod_in.CLASS_NAME})
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
except Exception as e: # pragma: no cover
|
|
66
|
+
logger.warning(f'Impossible to import the {pkg.value}.extensions.{mod} extension: '
|
|
67
|
+
f'{str(e)}')
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logger.warning(f'Impossible to import the {pkg.value} package: '
|
|
70
|
+
f'{str(e)}')
|
|
57
71
|
|
|
58
72
|
return extension_import
|
|
59
73
|
|
|
74
|
+
|
|
75
|
+
class CustomExt(CustomApp):
|
|
76
|
+
|
|
77
|
+
def __init__(self, parent: Union[DockArea, QtWidgets.QWidget], dashboard: 'DashBoard'):
|
|
78
|
+
super().__init__(parent)
|
|
79
|
+
|
|
80
|
+
self.dashboard = dashboard
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def modules_manager(self) -> ModulesManager:
|
|
84
|
+
"""useful tool to interact with DAQ_Moves and DAQ_Viewers
|
|
85
|
+
|
|
86
|
+
Will be available if a DashBoard has been set
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
ModulesManager
|
|
91
|
+
"""
|
|
92
|
+
if self.dashboard is not None:
|
|
93
|
+
return self.dashboard.modules_manager
|
|
@@ -23,6 +23,7 @@ def setup(path: Path):
|
|
|
23
23
|
name=PLUGIN_NAME,
|
|
24
24
|
description=config['plugin-info']['description'],
|
|
25
25
|
long_description=long_description,
|
|
26
|
+
long_description_content_type='text/x-rst',
|
|
26
27
|
license=config['plugin-info']['license'],
|
|
27
28
|
url=config['plugin-info']['package-url'],
|
|
28
29
|
author=config['plugin-info']['author'],
|
pymodaq/updater.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
import time
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
10
|
+
|
|
11
|
+
logger = set_logger(get_module_name(__file__))
|
|
12
|
+
logger.addHandler(logging.StreamHandler(sys.stdout))
|
|
13
|
+
|
|
14
|
+
def wait_for_parent():
|
|
15
|
+
'''
|
|
16
|
+
A function to wait for its parent to terminate execution.
|
|
17
|
+
|
|
18
|
+
In order to achieve that, this process has to be started with
|
|
19
|
+
stdin replaced by a piped stream from its parent. When the
|
|
20
|
+
parent terminates, stdin will close and either return from read
|
|
21
|
+
or throw an exception. De facto creating a way to wait for its
|
|
22
|
+
parent's termination.
|
|
23
|
+
|
|
24
|
+
It then sleep for 2 seconds, to let the parent process complete
|
|
25
|
+
termination.
|
|
26
|
+
|
|
27
|
+
CAUTION: If the process was not started by piping stdin AND
|
|
28
|
+
the --wait option is set, this function will hang forever.
|
|
29
|
+
|
|
30
|
+
We could use `psutil` or a similar lib to check for parent's process
|
|
31
|
+
existance with its pid.
|
|
32
|
+
'''
|
|
33
|
+
|
|
34
|
+
logger.info("Waiting for parent process to stop.")
|
|
35
|
+
try:
|
|
36
|
+
sys.stdin.read()
|
|
37
|
+
except:
|
|
38
|
+
pass
|
|
39
|
+
logger.debug("Parent process closed stdin")
|
|
40
|
+
time.sleep(2)
|
|
41
|
+
logger.info("Parent process stopped.")
|
|
42
|
+
|
|
43
|
+
def process_args():
|
|
44
|
+
'''
|
|
45
|
+
Declare arguments for updater.py, parse them and returns them in an object.
|
|
46
|
+
The arguments are:
|
|
47
|
+
--file <file> to request a python program to (re)start after update if needed (optional)
|
|
48
|
+
--wait to wait for the starting process to terminate before updating (optional, defaults to False)
|
|
49
|
+
packages the package list to install/update (they should contain the version in a pip accepted format)
|
|
50
|
+
'''
|
|
51
|
+
parser = argparse.ArgumentParser(description='Update pymodaq using pip.')
|
|
52
|
+
parser.add_argument('--file', type=str, help='the pymodaq script to restart after update')
|
|
53
|
+
parser.add_argument("--wait", action="store_true", help="enable waiting for pymodaq to finish mode (default is disabled).")
|
|
54
|
+
parser.add_argument('packages', type=str, nargs='+', help='package list')
|
|
55
|
+
return parser.parse_args()
|
|
56
|
+
|
|
57
|
+
def restart_if_command_launch(args):
|
|
58
|
+
'''
|
|
59
|
+
Try to detect if this process if launched using the declared command (i.e. `pymodaq_updater`)
|
|
60
|
+
or using the script file (`updater.py`). If it uses the command, it restart the process to
|
|
61
|
+
force it to use the script file, thus preventing a locked file during update on windows systems.
|
|
62
|
+
'''
|
|
63
|
+
python_file_path = Path(__file__) # Should be the path to `updater.py`
|
|
64
|
+
started_path = Path(sys.argv[0]) # Either `updater.py` or `pymodaq_updater`
|
|
65
|
+
|
|
66
|
+
# If they're different we'll restart using the script file
|
|
67
|
+
if started_path.absolute() != python_file_path.absolute():
|
|
68
|
+
logger.info("Started as pymodaq_updater, need to restart using python to prevent lock.")
|
|
69
|
+
# We HAVE to wait for this process to stop in the restarted process
|
|
70
|
+
new_args = ['--wait'] + sys.argv[1:]
|
|
71
|
+
if args.wait:
|
|
72
|
+
wait_for_parent()
|
|
73
|
+
|
|
74
|
+
subprocess.Popen([sys.executable, str(python_file_path.absolute())] + new_args, stdin=subprocess.PIPE)
|
|
75
|
+
sys.exit(0)
|
|
76
|
+
|
|
77
|
+
def main():
|
|
78
|
+
args = process_args()
|
|
79
|
+
logger.info(f"Arguments processed: {args}")
|
|
80
|
+
|
|
81
|
+
restart_if_command_launch(args)
|
|
82
|
+
|
|
83
|
+
if args.wait:
|
|
84
|
+
wait_for_parent()
|
|
85
|
+
|
|
86
|
+
packages_str = ', '.join(args.packages)
|
|
87
|
+
logger.info(f'Updating packages: {packages_str}')
|
|
88
|
+
|
|
89
|
+
with subprocess.Popen([sys.executable, '-m', 'pip', 'install'] + args.packages, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as pip:
|
|
90
|
+
for line in pip.stdout:
|
|
91
|
+
# Can't decode as some characters are not valid and make the whole process fail
|
|
92
|
+
logger.info(line[:-1])
|
|
93
|
+
ret_code = pip.wait()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if ret_code == 0:
|
|
97
|
+
logger.info(f'Succesfully updated {packages_str}')
|
|
98
|
+
else:
|
|
99
|
+
logger.error(f'Error while updating {packages_str}, pip returned {ret_code}')
|
|
100
|
+
|
|
101
|
+
if args.file is not None:
|
|
102
|
+
logger.info(f"Restarting {args.file} script after update.")
|
|
103
|
+
subprocess.Popen([sys.executable, args.file])
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
main()
|
pymodaq/utils/chrono_timer.py
CHANGED
|
@@ -6,8 +6,7 @@ from qtpy import QtGui, QtWidgets
|
|
|
6
6
|
from qtpy.QtCore import Qt, QObject, QTimer
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
from pymodaq_gui.utils import DockArea, Dock
|
|
10
|
-
from pymodaq_gui.QtDesigner_Ressources import QtDesigner_ressources_rc
|
|
9
|
+
from pymodaq_gui.utils.dock import DockArea, Dock
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class PushButtonShortcut(QtWidgets.QPushButton):
|
|
@@ -64,7 +63,7 @@ class ChronoTimer(QObject):
|
|
|
64
63
|
|
|
65
64
|
self.dock_chrono_timer.setAutoFillBackground(True)
|
|
66
65
|
palette = self.dock_chrono_timer.palette()
|
|
67
|
-
palette.setColor(palette.
|
|
66
|
+
palette.setColor(palette.Window, QtGui.QColor(0, 0, 0))
|
|
68
67
|
self.dock_chrono_timer.setPalette(palette)
|
|
69
68
|
|
|
70
69
|
self.time_lcd = QtWidgets.QLCDNumber(8)
|
|
@@ -92,7 +91,7 @@ class ChronoTimer(QObject):
|
|
|
92
91
|
self.controls_layout.addWidget(hor_widget)
|
|
93
92
|
|
|
94
93
|
icon = QtGui.QIcon()
|
|
95
|
-
icon.addPixmap(QtGui.QPixmap("
|
|
94
|
+
icon.addPixmap(QtGui.QPixmap("icons:run2.png"), QtGui.QIcon.Normal,
|
|
96
95
|
QtGui.QIcon.Off)
|
|
97
96
|
self.start_pb = PushButtonShortcut(icon, 'Start',
|
|
98
97
|
shortcut='Home', shortcut_widget=self.area)
|
|
@@ -102,7 +101,7 @@ class ChronoTimer(QObject):
|
|
|
102
101
|
hor_layout.addWidget(self.start_pb)
|
|
103
102
|
|
|
104
103
|
icon = QtGui.QIcon()
|
|
105
|
-
icon.addPixmap(QtGui.QPixmap("
|
|
104
|
+
icon.addPixmap(QtGui.QPixmap("icons:pause.png"), QtGui.QIcon.Normal,
|
|
106
105
|
QtGui.QIcon.Off)
|
|
107
106
|
self.pause_pb = PushButtonShortcut(icon, 'Pause',
|
|
108
107
|
shortcut='Ctrl+p', shortcut_widget=self.area)
|
|
@@ -112,7 +111,7 @@ class ChronoTimer(QObject):
|
|
|
112
111
|
hor_layout.addWidget(self.pause_pb)
|
|
113
112
|
|
|
114
113
|
icon = QtGui.QIcon()
|
|
115
|
-
icon.addPixmap(QtGui.QPixmap("
|
|
114
|
+
icon.addPixmap(QtGui.QPixmap("icons:Refresh2.png"), QtGui.QIcon.Normal,
|
|
116
115
|
QtGui.QIcon.Off)
|
|
117
116
|
self.reset_pb = PushButtonShortcut(icon, 'Reset',
|
|
118
117
|
shortcut='F5', shortcut_widget=self.area)
|
|
@@ -184,7 +183,7 @@ class ChronoTimer(QObject):
|
|
|
184
183
|
# lcd.setPalette(QtGui.QPalette(Qt.red))
|
|
185
184
|
if hasattr(Qt, color):
|
|
186
185
|
palette.setBrush(palette.WindowText, getattr(Qt, color))
|
|
187
|
-
palette.setColor(palette.
|
|
186
|
+
palette.setColor(palette.Window, QtGui.QColor(0, 0, 0))
|
|
188
187
|
lcd.setPalette(palette)
|
|
189
188
|
|
|
190
189
|
|
pymodaq/utils/daq_utils.py
CHANGED
|
@@ -5,9 +5,11 @@ import pkgutil
|
|
|
5
5
|
import platform
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
|
-
from pymodaq_utils import logger as logger_module
|
|
9
8
|
from pymodaq_utils.config import Config
|
|
10
|
-
from pymodaq_utils.utils import get_entrypoints, ThreadCommand, getLineInfo
|
|
9
|
+
from pymodaq_utils.utils import get_entrypoints, ThreadCommand, getLineInfo, find_keys_from_val, is_64bits, timer # for backcompat
|
|
10
|
+
from pymodaq_utils.logger import set_logger, get_module_name # for backcompat
|
|
11
|
+
|
|
12
|
+
from pymodaq.utils.data import DataFromPlugins # for backcompat
|
|
11
13
|
|
|
12
14
|
from pymodaq.utils.config import get_set_preset_path
|
|
13
15
|
|
|
@@ -18,7 +20,7 @@ else:
|
|
|
18
20
|
from functools import lru_cache as cache
|
|
19
21
|
|
|
20
22
|
|
|
21
|
-
logger =
|
|
23
|
+
logger = set_logger(get_module_name(__file__))
|
|
22
24
|
|
|
23
25
|
config = Config()
|
|
24
26
|
|
|
@@ -122,6 +124,7 @@ def get_instrument_plugins(): # pragma: no cover
|
|
|
122
124
|
except Exception as e:
|
|
123
125
|
logger.debug(f'Impossible to import PID utility plugin: {str(e)}')
|
|
124
126
|
|
|
127
|
+
plugins_import.sort(key=lambda mod: mod['name'])
|
|
125
128
|
return plugins_import
|
|
126
129
|
|
|
127
130
|
|
pymodaq/utils/data.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import numbers
|
|
3
3
|
import warnings
|
|
4
|
+
import copy
|
|
4
5
|
|
|
5
6
|
from typing import List
|
|
6
7
|
|
|
7
8
|
from pymodaq_utils.warnings import deprecation_msg, user_warning
|
|
8
9
|
|
|
9
10
|
from pymodaq_data.data import (DataRaw, DataWithAxes, DataToExport, DataCalculated, DataDim,
|
|
10
|
-
DataSource, DataBase, Axis, NavAxis
|
|
11
|
+
DataSource, DataBase, Axis, NavAxis, DataDistribution, Q_, Unit,
|
|
12
|
+
) # imported here for backcompatibility
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class DataActuator(DataRaw):
|
|
@@ -24,25 +26,18 @@ class DataActuator(DataRaw):
|
|
|
24
26
|
|
|
25
27
|
def __repr__(self):
|
|
26
28
|
if self.dim.name == 'Data0D':
|
|
27
|
-
return f'<{self.__class__.__name__} ({self.data[0][0]})>'
|
|
29
|
+
return f'<{self.__class__.__name__} ({self.data[0][0]} {self.units})>'
|
|
28
30
|
else:
|
|
29
|
-
return f'<{self.__class__.__name__} ({self.shape})>'
|
|
31
|
+
return f'<{self.__class__.__name__} ({self.shape} {self.units})>'
|
|
30
32
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return
|
|
36
|
-
else:
|
|
37
|
-
return float(np.mean(self.data))
|
|
33
|
+
def __add__(self, other: object):
|
|
34
|
+
if isinstance(other, numbers.Number) and self.length == 1 and self.size == 1:
|
|
35
|
+
new_data = copy.deepcopy(self)
|
|
36
|
+
new_data = new_data + DataActuator(data=other)
|
|
37
|
+
return new_data
|
|
38
38
|
|
|
39
|
-
def values(self) -> List[float]:
|
|
40
|
-
"""Returns the underlying float value (for each data array in the data list) if this data
|
|
41
|
-
holds only a float otherwise returns a mean of the underlying data"""
|
|
42
|
-
if self.length == 1 and self.size == 1:
|
|
43
|
-
return [float(data_array[0]) for data_array in self.data]
|
|
44
39
|
else:
|
|
45
|
-
return
|
|
40
|
+
return super().__add__(other)
|
|
46
41
|
|
|
47
42
|
|
|
48
43
|
class DataFromPlugins(DataRaw):
|
pymodaq/utils/enums.py
ADDED
|
@@ -5,14 +5,35 @@ from qtpy import QtWidgets
|
|
|
5
5
|
from pymodaq.dashboard import DashBoard
|
|
6
6
|
from pymodaq.utils.gui_utils import DockArea
|
|
7
7
|
from pymodaq.utils.config import get_set_preset_path
|
|
8
|
+
from pymodaq.extensions.utils import CustomExt
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
def load_dashboard_with_preset(preset_name: str, extension_name: str)
|
|
11
|
+
def load_dashboard_with_preset(preset_name: str, extension_name: str) -> \
|
|
12
|
+
(DashBoard, CustomExt, QtWidgets.QMainWindow):
|
|
13
|
+
""" Load the Dashboard using a given preset then load an extension
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
preset_name: str
|
|
18
|
+
The filename (without extension) defining the preset to be loaded in the Dashboard
|
|
19
|
+
extension_name: str
|
|
20
|
+
The name of the extension. Either the builtins ones:
|
|
21
|
+
* 'DAQScan'
|
|
22
|
+
* 'DAQLogger'
|
|
23
|
+
* 'DAQ_PID'
|
|
24
|
+
* 'Bayesian'
|
|
25
|
+
|
|
26
|
+
or the ones defined within a plugin
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
|
|
31
|
+
"""
|
|
11
32
|
win = QtWidgets.QMainWindow()
|
|
12
33
|
area = DockArea()
|
|
13
34
|
win.setCentralWidget(area)
|
|
14
35
|
win.resize(1000, 500)
|
|
15
|
-
win.setWindowTitle('
|
|
36
|
+
win.setWindowTitle('extension_name')
|
|
16
37
|
win.show()
|
|
17
38
|
|
|
18
39
|
# win.setVisible(False)
|
|
@@ -26,6 +47,10 @@ def load_dashboard_with_preset(preset_name: str, extension_name: str):
|
|
|
26
47
|
extension = dashboard.load_scan_module()
|
|
27
48
|
elif extension_name == 'DAQLogger':
|
|
28
49
|
extension = dashboard.load_log_module()
|
|
50
|
+
elif extension_name == 'DAQ_PID':
|
|
51
|
+
extension = dashboard.load_pid_module()
|
|
52
|
+
elif extension_name == 'Bayesian':
|
|
53
|
+
extension = dashboard.load_bayesian()
|
|
29
54
|
else:
|
|
30
55
|
extension = dashboard.load_extension_from_name(extension_name)
|
|
31
56
|
else:
|
pymodaq/utils/gui_utils/utils.py
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
|
|
3
|
-
from qtpy.QtCore import QObject, Signal, QEvent, QBuffer, QIODevice, Qt
|
|
4
|
-
from qtpy import QtWidgets, QtCore, QtGui
|
|
5
|
-
|
|
6
|
-
from pathlib import Path
|
|
7
1
|
from pymodaq_utils.config import Config
|
|
8
2
|
from pymodaq_utils.logger import set_logger, get_module_name
|
|
9
3
|
|
|
4
|
+
from pymodaq_gui.utils.splash import get_splash_sc
|
|
5
|
+
|
|
6
|
+
|
|
10
7
|
config = Config()
|
|
11
8
|
logger = set_logger(get_module_name(__file__))
|
|
12
9
|
|
|
10
|
+
from pymodaq_utils.warnings import deprecation_msg
|
|
11
|
+
|
|
12
|
+
deprecation_msg('Importing get_splash_sc stuff from pymodaq is deprecated '
|
|
13
|
+
'in pymodaq>5.0.0,'
|
|
14
|
+
'please use the same method from the '
|
|
15
|
+
'pymodaq_gui.utils.splash module')
|
|
13
16
|
|
|
14
|
-
def get_splash_sc():
|
|
15
|
-
here = Path(__file__)
|
|
16
|
-
splash_sc = QtWidgets.QSplashScreen(
|
|
17
|
-
QtGui.QPixmap(str(here.parent.parent.parent.joinpath('splash.png'))),
|
|
18
|
-
Qt.WindowStaysOnTopHint)
|
|
19
|
-
return splash_sc
|
|
20
17
|
|
|
21
18
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from pymodaq_gui.utils.widgets.lcd import LCD
|
|
2
|
+
|
|
3
|
+
from pymodaq_utils.warnings import deprecation_msg
|
|
4
|
+
|
|
5
|
+
deprecation_msg('Importing LCD from pymodaq is deprecated '
|
|
6
|
+
'in pymodaq>5.0.0,'
|
|
7
|
+
'please use the same method from the '
|
|
8
|
+
'pymodaq_gui.utils.widgets.lcd module')
|