pymodaq 5.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymodaq/__init__.py +98 -0
- pymodaq/control_modules/__init__.py +1 -0
- pymodaq/control_modules/daq_move.py +1238 -0
- pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/factory.py +48 -0
- pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
- pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
- pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
- pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
- pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
- pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
- pymodaq/control_modules/daq_viewer.py +1517 -0
- pymodaq/control_modules/daq_viewer_ui.py +407 -0
- pymodaq/control_modules/mocks.py +57 -0
- pymodaq/control_modules/move_utility_classes.py +1141 -0
- pymodaq/control_modules/thread_commands.py +137 -0
- pymodaq/control_modules/ui_utils.py +72 -0
- pymodaq/control_modules/utils.py +591 -0
- pymodaq/control_modules/viewer_utility_classes.py +670 -0
- pymodaq/daq_utils/__init__.py +0 -0
- pymodaq/daq_utils/daq_utils.py +6 -0
- pymodaq/dashboard.py +2396 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
- pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
- pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
- pymodaq/examples/__init__.py +0 -0
- pymodaq/examples/function_plotter.py +160 -0
- pymodaq/examples/nonlinearscanner.py +126 -0
- pymodaq/examples/qt_less_standalone_module.py +165 -0
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +25 -0
- pymodaq/extensions/adaptive/__init__.py +2 -0
- pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
- pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
- pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
- pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
- pymodaq/extensions/adaptive/utils.py +123 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
- pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
- pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
- pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
- pymodaq/extensions/bayesian/utils.py +180 -0
- pymodaq/extensions/console.py +73 -0
- pymodaq/extensions/daq_logger/__init__.py +1 -0
- pymodaq/extensions/daq_logger/abstract.py +52 -0
- pymodaq/extensions/daq_logger/daq_logger.py +519 -0
- pymodaq/extensions/daq_logger/db/__init__.py +0 -0
- pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
- pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
- pymodaq/extensions/daq_logger/h5logging.py +84 -0
- pymodaq/extensions/daq_scan.py +1218 -0
- pymodaq/extensions/daq_scan_ui.py +241 -0
- pymodaq/extensions/data_mixer/__init__.py +0 -0
- pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
- pymodaq/extensions/data_mixer/data_mixer.py +262 -0
- pymodaq/extensions/data_mixer/model.py +108 -0
- pymodaq/extensions/data_mixer/models/__init__.py +0 -0
- pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
- pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
- pymodaq/extensions/data_mixer/parser.py +53 -0
- pymodaq/extensions/data_mixer/utils.py +23 -0
- pymodaq/extensions/h5browser.py +9 -0
- pymodaq/extensions/optimizers_base/__init__.py +0 -0
- pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
- pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
- pymodaq/extensions/optimizers_base/utils.py +427 -0
- pymodaq/extensions/pid/__init__.py +16 -0
- pymodaq/extensions/pid/actuator_controller.py +14 -0
- pymodaq/extensions/pid/daq_move_PID.py +154 -0
- pymodaq/extensions/pid/pid_controller.py +1016 -0
- pymodaq/extensions/pid/utils.py +189 -0
- pymodaq/extensions/utils.py +111 -0
- pymodaq/icon.ico +0 -0
- pymodaq/post_treatment/__init__.py +6 -0
- pymodaq/post_treatment/load_and_plot.py +352 -0
- pymodaq/resources/__init__.py +0 -0
- pymodaq/resources/config_template.toml +57 -0
- pymodaq/resources/preset_default.xml +1 -0
- pymodaq/resources/setup_plugin.py +73 -0
- pymodaq/splash.png +0 -0
- pymodaq/utils/__init__.py +0 -0
- pymodaq/utils/array_manipulation.py +6 -0
- pymodaq/utils/calibration_camera.py +180 -0
- pymodaq/utils/chrono_timer.py +203 -0
- pymodaq/utils/config.py +53 -0
- pymodaq/utils/conftests.py +5 -0
- pymodaq/utils/daq_utils.py +158 -0
- pymodaq/utils/data.py +128 -0
- pymodaq/utils/enums.py +6 -0
- pymodaq/utils/exceptions.py +38 -0
- pymodaq/utils/gui_utils/__init__.py +10 -0
- pymodaq/utils/gui_utils/loader_utils.py +75 -0
- pymodaq/utils/gui_utils/utils.py +18 -0
- pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
- pymodaq/utils/h5modules/__init__.py +2 -0
- pymodaq/utils/h5modules/module_saving.py +526 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
- pymodaq/utils/leco/director_utils.py +74 -0
- pymodaq/utils/leco/leco_director.py +166 -0
- pymodaq/utils/leco/pymodaq_listener.py +364 -0
- pymodaq/utils/leco/rpc_method_definitions.py +43 -0
- pymodaq/utils/leco/utils.py +74 -0
- pymodaq/utils/logger.py +6 -0
- pymodaq/utils/managers/__init__.py +0 -0
- pymodaq/utils/managers/batchscan_manager.py +346 -0
- pymodaq/utils/managers/modules_manager.py +589 -0
- pymodaq/utils/managers/overshoot_manager.py +242 -0
- pymodaq/utils/managers/preset_manager.py +229 -0
- pymodaq/utils/managers/preset_manager_utils.py +262 -0
- pymodaq/utils/managers/remote_manager.py +484 -0
- pymodaq/utils/math_utils.py +6 -0
- pymodaq/utils/messenger.py +6 -0
- pymodaq/utils/parameter/__init__.py +10 -0
- pymodaq/utils/parameter/utils.py +6 -0
- pymodaq/utils/scanner/__init__.py +5 -0
- pymodaq/utils/scanner/scan_config.py +16 -0
- pymodaq/utils/scanner/scan_factory.py +259 -0
- pymodaq/utils/scanner/scan_selector.py +477 -0
- pymodaq/utils/scanner/scanner.py +324 -0
- pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
- pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
- pymodaq/utils/scanner/scanners/__init__.py +1 -0
- pymodaq/utils/scanner/scanners/sequential.py +224 -0
- pymodaq/utils/scanner/scanners/tabular.py +319 -0
- pymodaq/utils/scanner/utils.py +110 -0
- pymodaq/utils/svg/__init__.py +6 -0
- pymodaq/utils/svg/svg_renderer.py +20 -0
- pymodaq/utils/svg/svg_view.py +35 -0
- pymodaq/utils/svg/svg_viewer2D.py +50 -0
- pymodaq/utils/tcp_ip/__init__.py +6 -0
- pymodaq/utils/tcp_ip/mysocket.py +12 -0
- pymodaq/utils/tcp_ip/serializer.py +13 -0
- pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
- pymodaq-5.1.6.dist-info/METADATA +238 -0
- pymodaq-5.1.6.dist-info/RECORD +154 -0
- pymodaq-5.1.6.dist-info/WHEEL +4 -0
- pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
- pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
import logging
|
|
3
|
+
import datetime
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
from sqlalchemy import create_engine
|
|
7
|
+
from sqlalchemy.orm import sessionmaker
|
|
8
|
+
from sqlalchemy_utils import database_exists, create_database
|
|
9
|
+
|
|
10
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
11
|
+
from pymodaq_utils.config import Config
|
|
12
|
+
|
|
13
|
+
from pymodaq_gui.h5modules.saving import dashboard_submodules_params
|
|
14
|
+
from pymodaq_gui.messenger import messagebox
|
|
15
|
+
from pymodaq_gui.managers.parameter_manager import ParameterManager
|
|
16
|
+
|
|
17
|
+
from pymodaq_data.data import DataToExport
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
from .db_logger_models import (Base, Data0D, Data1D, Data2D, LogInfo,
|
|
21
|
+
Configuration, ControlModule)
|
|
22
|
+
from ..abstract import AbstractLogger
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
logger = set_logger(get_module_name(__file__))
|
|
26
|
+
config = Config()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class DBLogHandler(logging.StreamHandler):
|
|
30
|
+
def __init__(self, dblogger):
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.dblogger = dblogger
|
|
33
|
+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
34
|
+
self.setFormatter(formatter)
|
|
35
|
+
|
|
36
|
+
def emit(self, record):
|
|
37
|
+
msg = self.format(record)
|
|
38
|
+
self.dblogger.add_log(msg)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class DbLogger:
|
|
42
|
+
user = config('network', 'logging', 'user', 'username')
|
|
43
|
+
user_pwd = config('network', 'logging', 'user', 'pwd')
|
|
44
|
+
|
|
45
|
+
def __init__(self, database_name, ip_address=config('network', 'logging', 'sql', 'ip'),
|
|
46
|
+
port=config('network', 'logging', 'sql', 'port'), save2D=False):
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
models_base
|
|
52
|
+
ip_address
|
|
53
|
+
port
|
|
54
|
+
database_name
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
self.ip_address = ip_address
|
|
58
|
+
self.port = port
|
|
59
|
+
self.database_name = database_name
|
|
60
|
+
|
|
61
|
+
self.engine = None
|
|
62
|
+
self.Session = None
|
|
63
|
+
self._save2D = save2D
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def save2D(self):
|
|
67
|
+
return self._save2D
|
|
68
|
+
|
|
69
|
+
@save2D.setter
|
|
70
|
+
def save2D(self, value):
|
|
71
|
+
self._save2D = value
|
|
72
|
+
|
|
73
|
+
@contextmanager
|
|
74
|
+
def session_scope(self):
|
|
75
|
+
"""Provide a transactional scope around a series of operations."""
|
|
76
|
+
session = self.Session()
|
|
77
|
+
try:
|
|
78
|
+
yield session
|
|
79
|
+
session.commit()
|
|
80
|
+
except Exception as e:
|
|
81
|
+
logger.error(str(e))
|
|
82
|
+
session.rollback()
|
|
83
|
+
finally:
|
|
84
|
+
session.close()
|
|
85
|
+
|
|
86
|
+
def connect_db(self):
|
|
87
|
+
url = f"postgresql://{self.user}:{self.user_pwd}@{self.ip_address}:"\
|
|
88
|
+
f"{self.port}/{self.database_name}"
|
|
89
|
+
logger.debug(f'Connecting database using: {url}')
|
|
90
|
+
try:
|
|
91
|
+
self.engine = create_engine(f"postgresql://{self.user}:{self.user_pwd}@{self.ip_address}:"
|
|
92
|
+
f"{self.port}/{self.database_name}")
|
|
93
|
+
except ModuleNotFoundError as e:
|
|
94
|
+
messagebox('warning', 'ModuleError',
|
|
95
|
+
f'The postgresql backend *psycopg2* has not been installed.\n'
|
|
96
|
+
f'Could not connect to your database')
|
|
97
|
+
logger.warning(str(e))
|
|
98
|
+
return False
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
if not database_exists(self.engine.url):
|
|
102
|
+
create_database(self.engine.url)
|
|
103
|
+
assert database_exists(self.engine.url)
|
|
104
|
+
except Exception as e:
|
|
105
|
+
logger.critical(f'Impossible to connect to the DB: {str(e)}')
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
self.create_table()
|
|
109
|
+
self.Session = sessionmaker(bind=self.engine)
|
|
110
|
+
logger.debug(f'Database Connected')
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
def close(self):
|
|
114
|
+
if self.engine is not None:
|
|
115
|
+
self.engine.dispose()
|
|
116
|
+
|
|
117
|
+
def create_table(self):
|
|
118
|
+
# create tables if not existing
|
|
119
|
+
if self.engine is not None:
|
|
120
|
+
Base.metadata.create_all(self.engine)
|
|
121
|
+
|
|
122
|
+
def get_detectors(self, session) -> List[str]:
|
|
123
|
+
"""Returns the list of detectors name
|
|
124
|
+
|
|
125
|
+
Parameters
|
|
126
|
+
----------
|
|
127
|
+
session: (Session) SQLAlchemy session instance for db transactions
|
|
128
|
+
|
|
129
|
+
Returns
|
|
130
|
+
-------
|
|
131
|
+
the list of all created detectors
|
|
132
|
+
"""
|
|
133
|
+
return [res[0] for res in session.query(ControlModule.name)]
|
|
134
|
+
|
|
135
|
+
def get_actuators(self, session) -> List[str]:
|
|
136
|
+
"""Returns the list of actuators name
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
session: (Session) SQLAlchemy session instance for db transactions
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
the list of all created actuators
|
|
145
|
+
"""
|
|
146
|
+
return [res[0] for res in session.query(ControlModule.name)]
|
|
147
|
+
|
|
148
|
+
def add_detectors(self, detectors):
|
|
149
|
+
"""
|
|
150
|
+
add detectors in the detectors table
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
detectors: (list) list of dict with keys: name and settings_xml
|
|
154
|
+
"""
|
|
155
|
+
self.add_control_modules(detectors, 'DAQ_Viewer')
|
|
156
|
+
|
|
157
|
+
def add_actuators(self, actuators):
|
|
158
|
+
"""
|
|
159
|
+
add actuators in the actuators table
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
actuators: list
|
|
163
|
+
list of dict with keys: name and settings_xml
|
|
164
|
+
"""
|
|
165
|
+
self.add_control_modules(actuators, 'DAQ_Move')
|
|
166
|
+
|
|
167
|
+
def add_control_modules(self, modules, module_type='DAQ_Viewer'):
|
|
168
|
+
if not isinstance(modules, list):
|
|
169
|
+
modules = [modules]
|
|
170
|
+
with self.session_scope() as session:
|
|
171
|
+
existing_modules = [d.name for d in session.query(ControlModule)]
|
|
172
|
+
for mod in modules:
|
|
173
|
+
if mod['name'] not in existing_modules:
|
|
174
|
+
session.add(ControlModule(name=mod['name'], module_type=module_type,
|
|
175
|
+
settings_xml=mod['xml_settings']))
|
|
176
|
+
|
|
177
|
+
def add_config(self, config_settings):
|
|
178
|
+
with self.session_scope() as session:
|
|
179
|
+
session.add(Configuration(timestamp=datetime.datetime.now().timestamp(), settings_xml=config_settings))
|
|
180
|
+
|
|
181
|
+
def add_log(self, log):
|
|
182
|
+
with self.session_scope() as session:
|
|
183
|
+
session.add(LogInfo(log))
|
|
184
|
+
|
|
185
|
+
def add_data(self, data: DataToExport):
|
|
186
|
+
with self.session_scope() as session:
|
|
187
|
+
time_stamp = data.timestamp
|
|
188
|
+
module_name = data.name
|
|
189
|
+
|
|
190
|
+
if session.query(ControlModule).filter_by(name=module_name).count() == 0:
|
|
191
|
+
self.add_control_modules(session, dict(name=module_name), data.control_module)
|
|
192
|
+
|
|
193
|
+
module_id = session.query(ControlModule).filter_by(name=module_name).one().id # detector/actuator names should/are unique
|
|
194
|
+
|
|
195
|
+
for dwa in data.get_data_from_dim('Data0D'):
|
|
196
|
+
for ind, data_array in enumerate(dwa):
|
|
197
|
+
session.add(Data0D(timestamp=dwa.timestamp, control_module_id=module_id, channel=dwa.labels[ind],
|
|
198
|
+
value=float(data_array[0])))
|
|
199
|
+
|
|
200
|
+
for dwa in data.get_data_from_dim('Data1D'):
|
|
201
|
+
for ind, data_array in enumerate(dwa):
|
|
202
|
+
session.add(Data1D(timestamp=dwa.timestamp, control_module_id=module_id,
|
|
203
|
+
channel=dwa.labels[ind],
|
|
204
|
+
value=data_array.tolist()))
|
|
205
|
+
if self.save2D:
|
|
206
|
+
for dwa in data.get_data_from_dim('Data2D'):
|
|
207
|
+
for ind, data_array in enumerate(dwa):
|
|
208
|
+
session.add(Data2D(timestamp=dwa.timestamp, control_module_id=module_id,
|
|
209
|
+
channel=dwa.labels[ind],
|
|
210
|
+
value=data_array.tolist()))
|
|
211
|
+
|
|
212
|
+
# not yet dataND as db should not know where to save these datas
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class DbLoggerGUI(DbLogger, ParameterManager):
|
|
216
|
+
params = [
|
|
217
|
+
{'title': 'Database:', 'name': 'database_type', 'type': 'list', 'value': 'PostgreSQL',
|
|
218
|
+
'limits': ['PostgreSQL', ]},
|
|
219
|
+
{'title': 'Server IP:', 'name': 'server_ip', 'type': 'str',
|
|
220
|
+
'value': config('network', 'logging', 'sql', 'ip'),
|
|
221
|
+
'tip':'Either localhost if the database server is on the same computer or the IP address of the server'},
|
|
222
|
+
{'title': 'Server port:', 'name': 'server_port', 'type': 'int',
|
|
223
|
+
'value': config('network', 'logging', 'sql', 'port')},
|
|
224
|
+
{'title': 'Connect:', 'name': 'connect_db', 'type': 'bool_push', 'value': False},
|
|
225
|
+
{'title': 'Connected:', 'name': 'connected_db', 'type': 'led', 'value': False},
|
|
226
|
+
] + dashboard_submodules_params
|
|
227
|
+
|
|
228
|
+
def __init__(self, database_name):
|
|
229
|
+
DbLogger.__init__(self, database_name, ip_address=config('network', 'logging', 'sql', 'ip'),
|
|
230
|
+
port=config('network', 'logging', 'sql', 'port'), save2D=False)
|
|
231
|
+
ParameterManager.__init__(self)
|
|
232
|
+
|
|
233
|
+
self.settings.child('do_save').hide()
|
|
234
|
+
|
|
235
|
+
def value_changed(self, param):
|
|
236
|
+
if param.name() == 'server_ip':
|
|
237
|
+
self.ip_address = param.value()
|
|
238
|
+
|
|
239
|
+
elif param.name() == 'server_port':
|
|
240
|
+
self.port = param.value()
|
|
241
|
+
|
|
242
|
+
elif param.name() == 'connect_db':
|
|
243
|
+
if param.value():
|
|
244
|
+
status = self.connect_db()
|
|
245
|
+
self.settings.child('connected_db').setValue(status)
|
|
246
|
+
else:
|
|
247
|
+
self.close()
|
|
248
|
+
self.settings.child('connected_db').setValue(False)
|
|
249
|
+
|
|
250
|
+
elif param.name() == 'save_2D':
|
|
251
|
+
self.save2D = param.value()
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class DataBaseLogger(AbstractLogger):
|
|
255
|
+
def __init__(self, database_name):
|
|
256
|
+
self.dblogger = DbLoggerGUI(database_name)
|
|
257
|
+
|
|
258
|
+
@property
|
|
259
|
+
def settings_tree(self):
|
|
260
|
+
return self.dblogger.settings_tree
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def settings(self):
|
|
264
|
+
return self.dblogger.settings
|
|
265
|
+
|
|
266
|
+
def init_logger(self, settings):
|
|
267
|
+
if not self.settings.child('connected_db').value():
|
|
268
|
+
status = self.dblogger.connect_db()
|
|
269
|
+
if not status:
|
|
270
|
+
logger.critical('the Database is not and cannot be connnect')
|
|
271
|
+
return False
|
|
272
|
+
|
|
273
|
+
self.dblogger.add_config(settings)
|
|
274
|
+
return True
|
|
275
|
+
|
|
276
|
+
def get_handler(self):
|
|
277
|
+
return DBLogHandler(self.dblogger)
|
|
278
|
+
|
|
279
|
+
def add_detector(self, det_name, settings):
|
|
280
|
+
self.dblogger.add_detectors([dict(name=det_name, xml_settings=settings)])
|
|
281
|
+
|
|
282
|
+
def add_actuator(self, act_name, settings):
|
|
283
|
+
self.dblogger.add_actuators([dict(name=act_name, xml_settings=settings)])
|
|
284
|
+
|
|
285
|
+
def add_data(self, data):
|
|
286
|
+
self.dblogger.add_data(data)
|
|
287
|
+
self.settings.child('N_saved').setValue(
|
|
288
|
+
self.settings.child('N_saved').value() + 1)
|
|
289
|
+
|
|
290
|
+
def stop_logger(self):
|
|
291
|
+
pass
|
|
292
|
+
|
|
293
|
+
def close(self):
|
|
294
|
+
pass
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
if __name__ == '__main__':
|
|
298
|
+
db = DbLogger('preset_default')
|
|
299
|
+
db.connect_db()
|
|
300
|
+
pass
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
3
|
+
from sqlalchemy.orm import sessionmaker, relationship
|
|
4
|
+
from sqlalchemy import Column, Integer, String, Float, ForeignKey
|
|
5
|
+
from sqlalchemy.dialects.postgresql import ARRAY as Array
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Base = declarative_base()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Configuration(Base):
|
|
12
|
+
__tablename__ = 'configurations'
|
|
13
|
+
id = Column(Integer, primary_key=True)
|
|
14
|
+
timestamp = Column(Integer, nullable=False, index=True)
|
|
15
|
+
settings_xml = Column(String)
|
|
16
|
+
|
|
17
|
+
def __repr__(self):
|
|
18
|
+
return f"<Config(date='{datetime.datetime.fromtimestamp(self.timestamp).isoformat()}', settings_xml='{self.settings_xml[0:20]}')>"
|
|
19
|
+
|
|
20
|
+
# class Actuator(Base):
|
|
21
|
+
# __tablename__ = 'actuators'
|
|
22
|
+
# id = Column(Integer, primary_key=True)
|
|
23
|
+
# name = Column(String(128))
|
|
24
|
+
# settings_xml = Column(String)
|
|
25
|
+
# datas0D = relationship("Data0D", backref='actuators')
|
|
26
|
+
#
|
|
27
|
+
#
|
|
28
|
+
# class Detector(Base):
|
|
29
|
+
# __tablename__ = 'detectors'
|
|
30
|
+
# id = Column(Integer, primary_key=True)
|
|
31
|
+
# name = Column(String(128))
|
|
32
|
+
# settings_xml = Column(String)
|
|
33
|
+
# datas0D = relationship("Data0D", backref='detectors')
|
|
34
|
+
# datas1D = relationship("Data1D", backref='detectors')
|
|
35
|
+
# datas2D = relationship("Data2D", backref='detectors')
|
|
36
|
+
#
|
|
37
|
+
# def __repr__(self):
|
|
38
|
+
# return f"<Detector(name='{self.name}', settings_xml='{self.settings_xml[0:20]}')>"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ControlModule(Base):
|
|
42
|
+
__tablename__ = 'control_modules'
|
|
43
|
+
id = Column(Integer, primary_key=True)
|
|
44
|
+
name = Column(String(128))
|
|
45
|
+
module_type = Column(String(128))
|
|
46
|
+
settings_xml = Column(String)
|
|
47
|
+
datas0D = relationship("Data0D", backref='control_modules')
|
|
48
|
+
datas1D = relationship("Data1D", backref='control_modules')
|
|
49
|
+
datas2D = relationship("Data2D", backref='control_modules')
|
|
50
|
+
|
|
51
|
+
def __repr__(self):
|
|
52
|
+
return f"<Control Module {self.type} (name='{self.name}', settings_xml='{self.settings_xml[0:20]}')>"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class LogInfo(Base):
|
|
56
|
+
__tablename__ = 'loginfo'
|
|
57
|
+
id = Column(Integer, primary_key=True)
|
|
58
|
+
value = Column(String)
|
|
59
|
+
|
|
60
|
+
def __repr__(self):
|
|
61
|
+
return f"<Loginfo(timestamp='{self.timestamp}', value='{self.value}')>"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Data0D(Base):
|
|
65
|
+
__tablename__ = 'datas0D'
|
|
66
|
+
|
|
67
|
+
id = Column(Integer, primary_key=True)
|
|
68
|
+
timestamp = Column(Integer, nullable=False, index=True)
|
|
69
|
+
control_module_id = Column(Integer, ForeignKey('control_modules.id'), index=True)
|
|
70
|
+
channel = Column(String(128))
|
|
71
|
+
value = Column(Float)
|
|
72
|
+
|
|
73
|
+
def __repr__(self):
|
|
74
|
+
return f"<Data0D(channel='{self.channel}', timestamp='{self.timestamp}', value='{self.value}')>"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Data1D(Base):
|
|
78
|
+
__tablename__ = 'datas1D'
|
|
79
|
+
|
|
80
|
+
id = Column(Integer, primary_key=True)
|
|
81
|
+
timestamp = Column(Integer, nullable=False, index=True)
|
|
82
|
+
control_module_id = Column(Integer, ForeignKey('control_modules.id'), index=True)
|
|
83
|
+
channel = Column(String(128))
|
|
84
|
+
value = Column(Array(Float, dimensions=1))
|
|
85
|
+
|
|
86
|
+
def __repr__(self):
|
|
87
|
+
return f"<Data1D(channel='{self.channel}', timestamp='{self.timestamp}', value='{self.value}')>"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Data2D(Base):
|
|
91
|
+
__tablename__ = 'datas2D'
|
|
92
|
+
|
|
93
|
+
id = Column(Integer, primary_key=True)
|
|
94
|
+
timestamp = Column(Integer, nullable=False, index=True)
|
|
95
|
+
control_module_id = Column(Integer, ForeignKey('control_modules.id'), index=True)
|
|
96
|
+
channel = Column(String(128))
|
|
97
|
+
value = Column(Array(Float, dimensions=2))
|
|
98
|
+
|
|
99
|
+
def __repr__(self):
|
|
100
|
+
return f"<Data2D(channel='{self.channel}', timestamp='{self.timestamp}', value='{self.value}')>"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created the 15/11/2022
|
|
4
|
+
|
|
5
|
+
@author: Sebastien Weber
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
12
|
+
from pymodaq_utils.config import Config
|
|
13
|
+
from pymodaq_gui.h5modules.saving import H5Saver
|
|
14
|
+
from pymodaq_data.data import DataToExport
|
|
15
|
+
|
|
16
|
+
from pymodaq.utils.managers.modules_manager import ModulesManager
|
|
17
|
+
from pymodaq.utils.h5modules import module_saving
|
|
18
|
+
from .abstract import AbstractLogger
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
config = Config()
|
|
22
|
+
|
|
23
|
+
logger = set_logger(get_module_name(__file__))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class H5LogHandler(logging.StreamHandler):
|
|
27
|
+
def __init__(self, h5saver):
|
|
28
|
+
super().__init__()
|
|
29
|
+
self.h5saver = h5saver
|
|
30
|
+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
31
|
+
self.setFormatter(formatter)
|
|
32
|
+
|
|
33
|
+
def emit(self, record):
|
|
34
|
+
msg = self.format(record)
|
|
35
|
+
self.h5saver.add_log(msg)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class H5Logger(AbstractLogger):
|
|
39
|
+
def __init__(self, modules_manager, *args, **kwargs):
|
|
40
|
+
|
|
41
|
+
self.title = self.__class__.__name__
|
|
42
|
+
|
|
43
|
+
self.modules_manager: ModulesManager = modules_manager
|
|
44
|
+
self.h5saver = H5Saver(*args, save_type='logger', **kwargs)
|
|
45
|
+
|
|
46
|
+
self.module_and_data_saver = module_saving.LoggerSaver(self)
|
|
47
|
+
for det in self.modules_manager.detectors_all:
|
|
48
|
+
det.module_and_data_saver = module_saving.DetectorTimeSaver(det)
|
|
49
|
+
self.module_and_data_saver.h5saver = self.h5saver # will update its h5saver and all submodules's h5saver
|
|
50
|
+
|
|
51
|
+
def close(self):
|
|
52
|
+
self.h5saver.close_file()
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def settings_tree(self):
|
|
56
|
+
return self.h5saver.settings_tree
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def settings(self):
|
|
60
|
+
return self.h5saver.settings
|
|
61
|
+
|
|
62
|
+
def init_logger(self, settings):
|
|
63
|
+
self.h5saver.init_file(update_h5=True, metadata=dict(settings=settings))
|
|
64
|
+
self.h5saver.flush()
|
|
65
|
+
self.module_and_data_saver.h5saver = self.h5saver
|
|
66
|
+
logger_node = self.module_and_data_saver.get_set_node(new=True)
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
def get_handler(self):
|
|
70
|
+
return H5LogHandler(self.h5saver)
|
|
71
|
+
|
|
72
|
+
def add_detector(self, name, settings):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
def add_actuator(self, name, settings):
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
def add_data(self, dte: DataToExport):
|
|
79
|
+
self.module_and_data_saver.add_data(dte)
|
|
80
|
+
|
|
81
|
+
self.settings.child('N_saved').setValue(self.settings.child('N_saved').value() + 1)
|
|
82
|
+
|
|
83
|
+
def stop_logger(self):
|
|
84
|
+
self.h5saver.flush()
|