pymodaq 5.1.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. pymodaq/__init__.py +98 -0
  2. pymodaq/control_modules/__init__.py +1 -0
  3. pymodaq/control_modules/daq_move.py +1238 -0
  4. pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
  5. pymodaq/control_modules/daq_move_ui/factory.py +48 -0
  6. pymodaq/control_modules/daq_move_ui/ui_base.py +359 -0
  7. pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
  8. pymodaq/control_modules/daq_move_ui/uis/binary.py +139 -0
  9. pymodaq/control_modules/daq_move_ui/uis/original.py +120 -0
  10. pymodaq/control_modules/daq_move_ui/uis/relative.py +124 -0
  11. pymodaq/control_modules/daq_move_ui/uis/simple.py +126 -0
  12. pymodaq/control_modules/daq_viewer.py +1517 -0
  13. pymodaq/control_modules/daq_viewer_ui.py +407 -0
  14. pymodaq/control_modules/mocks.py +57 -0
  15. pymodaq/control_modules/move_utility_classes.py +1141 -0
  16. pymodaq/control_modules/thread_commands.py +137 -0
  17. pymodaq/control_modules/ui_utils.py +72 -0
  18. pymodaq/control_modules/utils.py +591 -0
  19. pymodaq/control_modules/viewer_utility_classes.py +670 -0
  20. pymodaq/daq_utils/__init__.py +0 -0
  21. pymodaq/daq_utils/daq_utils.py +6 -0
  22. pymodaq/dashboard.py +2396 -0
  23. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.aliases +3 -0
  24. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvlps +3 -0
  25. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.lvproj +32 -0
  26. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Client.vi +0 -0
  27. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_1Dgaussian.vi +0 -0
  28. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_Server_2Dgaussian.vi +0 -0
  29. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_cmd.vi +0 -0
  30. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_float.vi +0 -0
  31. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_read_int.vi +0 -0
  32. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_data.vi +0 -0
  33. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_int.vi +0 -0
  34. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_scalar.vi +0 -0
  35. pymodaq/examples/Labview_TCP_Client/DAQ_TCP_send_string.vi +0 -0
  36. pymodaq/examples/Labview_TCP_Client/client_state.ctl +0 -0
  37. pymodaq/examples/Labview_TCP_Client/cmd_types.ctl +0 -0
  38. pymodaq/examples/__init__.py +0 -0
  39. pymodaq/examples/function_plotter.py +160 -0
  40. pymodaq/examples/nonlinearscanner.py +126 -0
  41. pymodaq/examples/qt_less_standalone_module.py +165 -0
  42. pymodaq/examples/tcp_client.py +97 -0
  43. pymodaq/extensions/__init__.py +25 -0
  44. pymodaq/extensions/adaptive/__init__.py +2 -0
  45. pymodaq/extensions/adaptive/adaptive_optimization.py +179 -0
  46. pymodaq/extensions/adaptive/loss_function/_1d_loss_functions.py +73 -0
  47. pymodaq/extensions/adaptive/loss_function/_2d_loss_functions.py +73 -0
  48. pymodaq/extensions/adaptive/loss_function/__init__.py +3 -0
  49. pymodaq/extensions/adaptive/loss_function/loss_factory.py +110 -0
  50. pymodaq/extensions/adaptive/utils.py +123 -0
  51. pymodaq/extensions/bayesian/__init__.py +2 -0
  52. pymodaq/extensions/bayesian/acquisition/__init__.py +2 -0
  53. pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +80 -0
  54. pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +105 -0
  55. pymodaq/extensions/bayesian/bayesian_optimization.py +143 -0
  56. pymodaq/extensions/bayesian/utils.py +180 -0
  57. pymodaq/extensions/console.py +73 -0
  58. pymodaq/extensions/daq_logger/__init__.py +1 -0
  59. pymodaq/extensions/daq_logger/abstract.py +52 -0
  60. pymodaq/extensions/daq_logger/daq_logger.py +519 -0
  61. pymodaq/extensions/daq_logger/db/__init__.py +0 -0
  62. pymodaq/extensions/daq_logger/db/db_logger.py +300 -0
  63. pymodaq/extensions/daq_logger/db/db_logger_models.py +100 -0
  64. pymodaq/extensions/daq_logger/h5logging.py +84 -0
  65. pymodaq/extensions/daq_scan.py +1218 -0
  66. pymodaq/extensions/daq_scan_ui.py +241 -0
  67. pymodaq/extensions/data_mixer/__init__.py +0 -0
  68. pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +97 -0
  69. pymodaq/extensions/data_mixer/data_mixer.py +262 -0
  70. pymodaq/extensions/data_mixer/model.py +108 -0
  71. pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  72. pymodaq/extensions/data_mixer/models/equation_model.py +91 -0
  73. pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +65 -0
  74. pymodaq/extensions/data_mixer/parser.py +53 -0
  75. pymodaq/extensions/data_mixer/utils.py +23 -0
  76. pymodaq/extensions/h5browser.py +9 -0
  77. pymodaq/extensions/optimizers_base/__init__.py +0 -0
  78. pymodaq/extensions/optimizers_base/optimizer.py +1016 -0
  79. pymodaq/extensions/optimizers_base/thread_commands.py +22 -0
  80. pymodaq/extensions/optimizers_base/utils.py +427 -0
  81. pymodaq/extensions/pid/__init__.py +16 -0
  82. pymodaq/extensions/pid/actuator_controller.py +14 -0
  83. pymodaq/extensions/pid/daq_move_PID.py +154 -0
  84. pymodaq/extensions/pid/pid_controller.py +1016 -0
  85. pymodaq/extensions/pid/utils.py +189 -0
  86. pymodaq/extensions/utils.py +111 -0
  87. pymodaq/icon.ico +0 -0
  88. pymodaq/post_treatment/__init__.py +6 -0
  89. pymodaq/post_treatment/load_and_plot.py +352 -0
  90. pymodaq/resources/__init__.py +0 -0
  91. pymodaq/resources/config_template.toml +57 -0
  92. pymodaq/resources/preset_default.xml +1 -0
  93. pymodaq/resources/setup_plugin.py +73 -0
  94. pymodaq/splash.png +0 -0
  95. pymodaq/utils/__init__.py +0 -0
  96. pymodaq/utils/array_manipulation.py +6 -0
  97. pymodaq/utils/calibration_camera.py +180 -0
  98. pymodaq/utils/chrono_timer.py +203 -0
  99. pymodaq/utils/config.py +53 -0
  100. pymodaq/utils/conftests.py +5 -0
  101. pymodaq/utils/daq_utils.py +158 -0
  102. pymodaq/utils/data.py +128 -0
  103. pymodaq/utils/enums.py +6 -0
  104. pymodaq/utils/exceptions.py +38 -0
  105. pymodaq/utils/gui_utils/__init__.py +10 -0
  106. pymodaq/utils/gui_utils/loader_utils.py +75 -0
  107. pymodaq/utils/gui_utils/utils.py +18 -0
  108. pymodaq/utils/gui_utils/widgets/lcd.py +8 -0
  109. pymodaq/utils/h5modules/__init__.py +2 -0
  110. pymodaq/utils/h5modules/module_saving.py +526 -0
  111. pymodaq/utils/leco/__init__.py +25 -0
  112. pymodaq/utils/leco/daq_move_LECODirector.py +217 -0
  113. pymodaq/utils/leco/daq_xDviewer_LECODirector.py +163 -0
  114. pymodaq/utils/leco/director_utils.py +74 -0
  115. pymodaq/utils/leco/leco_director.py +166 -0
  116. pymodaq/utils/leco/pymodaq_listener.py +364 -0
  117. pymodaq/utils/leco/rpc_method_definitions.py +43 -0
  118. pymodaq/utils/leco/utils.py +74 -0
  119. pymodaq/utils/logger.py +6 -0
  120. pymodaq/utils/managers/__init__.py +0 -0
  121. pymodaq/utils/managers/batchscan_manager.py +346 -0
  122. pymodaq/utils/managers/modules_manager.py +589 -0
  123. pymodaq/utils/managers/overshoot_manager.py +242 -0
  124. pymodaq/utils/managers/preset_manager.py +229 -0
  125. pymodaq/utils/managers/preset_manager_utils.py +262 -0
  126. pymodaq/utils/managers/remote_manager.py +484 -0
  127. pymodaq/utils/math_utils.py +6 -0
  128. pymodaq/utils/messenger.py +6 -0
  129. pymodaq/utils/parameter/__init__.py +10 -0
  130. pymodaq/utils/parameter/utils.py +6 -0
  131. pymodaq/utils/scanner/__init__.py +5 -0
  132. pymodaq/utils/scanner/scan_config.py +16 -0
  133. pymodaq/utils/scanner/scan_factory.py +259 -0
  134. pymodaq/utils/scanner/scan_selector.py +477 -0
  135. pymodaq/utils/scanner/scanner.py +324 -0
  136. pymodaq/utils/scanner/scanners/_1d_scanners.py +174 -0
  137. pymodaq/utils/scanner/scanners/_2d_scanners.py +299 -0
  138. pymodaq/utils/scanner/scanners/__init__.py +1 -0
  139. pymodaq/utils/scanner/scanners/sequential.py +224 -0
  140. pymodaq/utils/scanner/scanners/tabular.py +319 -0
  141. pymodaq/utils/scanner/utils.py +110 -0
  142. pymodaq/utils/svg/__init__.py +6 -0
  143. pymodaq/utils/svg/svg_renderer.py +20 -0
  144. pymodaq/utils/svg/svg_view.py +35 -0
  145. pymodaq/utils/svg/svg_viewer2D.py +50 -0
  146. pymodaq/utils/tcp_ip/__init__.py +6 -0
  147. pymodaq/utils/tcp_ip/mysocket.py +12 -0
  148. pymodaq/utils/tcp_ip/serializer.py +13 -0
  149. pymodaq/utils/tcp_ip/tcp_server_client.py +772 -0
  150. pymodaq-5.1.6.dist-info/METADATA +238 -0
  151. pymodaq-5.1.6.dist-info/RECORD +154 -0
  152. pymodaq-5.1.6.dist-info/WHEEL +4 -0
  153. pymodaq-5.1.6.dist-info/entry_points.txt +7 -0
  154. pymodaq-5.1.6.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,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()