labmate 0.8.1__py3-none-any.whl → 0.8.3__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.
- labmate/__config__.py +1 -1
- labmate/acquisition/acquisition_loop.py +20 -7
- labmate/acquisition/acquisition_manager.py +29 -10
- labmate/acquisition/analysis_data.py +36 -18
- labmate/acquisition/analysis_loop.py +4 -2
- labmate/acquisition/custom_lint.py +4 -1
- labmate/acquisition_notebook/acquisition_analysis_manager.py +38 -13
- labmate/acquisition_notebook/display_widget.py +3 -3
- labmate/attrdict/attrdict_class.py +15 -11
- labmate/display/__init__.py +6 -5
- labmate/display/platform_utils/windows_utils.py +11 -5
- labmate/parsing/saving.py +8 -2
- labmate/utils/lint.py +4 -1
- labmate/utils/random_utils.py +6 -2
- labmate/utils/title_parsing.py +7 -2
- {labmate-0.8.1.dist-info → labmate-0.8.3.dist-info}/METADATA +1 -1
- {labmate-0.8.1.dist-info → labmate-0.8.3.dist-info}/RECORD +20 -20
- {labmate-0.8.1.dist-info → labmate-0.8.3.dist-info}/LICENCE +0 -0
- {labmate-0.8.1.dist-info → labmate-0.8.3.dist-info}/WHEEL +0 -0
- {labmate-0.8.1.dist-info → labmate-0.8.3.dist-info}/top_level.txt +0 -0
labmate/__config__.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""AcquisitionLoop class."""
|
|
2
|
+
|
|
2
3
|
from typing import Iterable, Iterator, Optional, Union, overload
|
|
3
4
|
|
|
4
5
|
import numpy as np
|
|
5
|
-
from dh5.dh5_types import SyncNp
|
|
6
6
|
from dh5 import DH5
|
|
7
|
+
from dh5.dh5_types import SyncNp
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class AcquisitionLoop(DH5):
|
|
@@ -87,11 +88,17 @@ class AcquisitionLoop(DH5):
|
|
|
87
88
|
|
|
88
89
|
@overload
|
|
89
90
|
def __call__(
|
|
90
|
-
self,
|
|
91
|
+
self,
|
|
92
|
+
start: Union[int, float],
|
|
93
|
+
stop: Union[int, float],
|
|
94
|
+
step: Union[int, float],
|
|
95
|
+
/,
|
|
91
96
|
) -> Iterator:
|
|
92
97
|
"""Return np.arange(start, stop, step) given a start, stop and step."""
|
|
93
98
|
|
|
94
|
-
def __call__(
|
|
99
|
+
def __call__(
|
|
100
|
+
self, *args, iterable: Optional[Iterable] = None, **kwds
|
|
101
|
+
) -> Optional[Iterator]:
|
|
95
102
|
"""Append_data or arange.
|
|
96
103
|
|
|
97
104
|
If kwds are provided then is same as calling append_data(kwds),
|
|
@@ -108,7 +115,7 @@ class AcquisitionLoop(DH5):
|
|
|
108
115
|
return None
|
|
109
116
|
|
|
110
117
|
if iterable is None:
|
|
111
|
-
if isinstance(args[0], (int, float, np.int_, np.
|
|
118
|
+
if isinstance(args[0], (int, float, np.int_, np.floating)): # type: ignore
|
|
112
119
|
iterable = np.arange(*args)
|
|
113
120
|
else:
|
|
114
121
|
iterable = args[0]
|
|
@@ -171,7 +178,9 @@ class AcquisitionLoop(DH5):
|
|
|
171
178
|
self[key] = SyncNp(
|
|
172
179
|
np.pad(
|
|
173
180
|
self[key],
|
|
174
|
-
pad_width=tuple(
|
|
181
|
+
pad_width=tuple(
|
|
182
|
+
(0, i - j) for i, j in zip(key_shape, self[key].shape)
|
|
183
|
+
),
|
|
175
184
|
)
|
|
176
185
|
)
|
|
177
186
|
self[key][iteration] = value
|
|
@@ -194,7 +203,9 @@ class AcquisitionLoop(DH5):
|
|
|
194
203
|
):
|
|
195
204
|
if length is None:
|
|
196
205
|
if not hasattr(iterable, "__len__"):
|
|
197
|
-
raise TypeError(
|
|
206
|
+
raise TypeError(
|
|
207
|
+
"Iterable should has __len__ method or length should be provided"
|
|
208
|
+
)
|
|
198
209
|
length = len(iterable) # type: ignore
|
|
199
210
|
|
|
200
211
|
def loop_iter(array, length):
|
|
@@ -274,7 +285,9 @@ class AcquisitionLoop(DH5):
|
|
|
274
285
|
"""
|
|
275
286
|
if key is None:
|
|
276
287
|
if not self._save_indexes:
|
|
277
|
-
raise ValueError(
|
|
288
|
+
raise ValueError(
|
|
289
|
+
"As indexes are not saved with the Loop, key should be provided."
|
|
290
|
+
)
|
|
278
291
|
key = f"__index_{self._level}__"
|
|
279
292
|
|
|
280
293
|
iteration = tuple(self._iteration[: self._level])
|
|
@@ -104,9 +104,13 @@ class AcquisitionManager:
|
|
|
104
104
|
configs: dict of configurations files to save
|
|
105
105
|
directory: directory where the data is stored
|
|
106
106
|
"""
|
|
107
|
-
acquisition_tmp_data = self._acquisition_tmp_data or self.get_temp_data(
|
|
107
|
+
acquisition_tmp_data = self._acquisition_tmp_data or self.get_temp_data(
|
|
108
|
+
self.temp_file_path
|
|
109
|
+
)
|
|
108
110
|
if acquisition_tmp_data is None:
|
|
109
|
-
raise ValueError(
|
|
111
|
+
raise ValueError(
|
|
112
|
+
"You should create a new acquisition. It will create temp.json file."
|
|
113
|
+
)
|
|
110
114
|
return acquisition_tmp_data
|
|
111
115
|
|
|
112
116
|
@acquisition_tmp_data.setter
|
|
@@ -122,7 +126,8 @@ class AcquisitionManager:
|
|
|
122
126
|
self, filename: Union[str, List[str], Tuple[str, ...]]
|
|
123
127
|
) -> "AcquisitionManager":
|
|
124
128
|
"""Set self.config_file to filename. Verify if exists.
|
|
125
|
-
Only set config file for future acquisition and will not change current acquisition
|
|
129
|
+
Only set config file for future acquisition and will not change current acquisition
|
|
130
|
+
"""
|
|
126
131
|
if not isinstance(filename, (list, set, tuple)):
|
|
127
132
|
filename = [str(filename)]
|
|
128
133
|
|
|
@@ -156,9 +161,13 @@ class AcquisitionManager:
|
|
|
156
161
|
if not experiment_path.exists():
|
|
157
162
|
experiment_path.makedirs()
|
|
158
163
|
if self._init_code and not os.path.exists(experiment_path / "init_analyse.py"):
|
|
159
|
-
with open(
|
|
164
|
+
with open(
|
|
165
|
+
experiment_path / "init_analyse.py", "w", encoding="utf-8"
|
|
166
|
+
) as file:
|
|
160
167
|
file.write(self._init_code)
|
|
161
|
-
filepath_original = filepath =
|
|
168
|
+
filepath_original = filepath = (
|
|
169
|
+
experiment_path / f"{dic.time_stamp}__{dic.experiment_name}"
|
|
170
|
+
)
|
|
162
171
|
if ignore_existence:
|
|
163
172
|
return filepath
|
|
164
173
|
|
|
@@ -183,7 +192,9 @@ class AcquisitionManager:
|
|
|
183
192
|
self.cell = cell
|
|
184
193
|
configs = read_files(self.config_files)
|
|
185
194
|
if self.config_files_eval:
|
|
186
|
-
configs = append_values_from_modules_to_files(
|
|
195
|
+
configs = append_values_from_modules_to_files(
|
|
196
|
+
configs, self.config_files_eval
|
|
197
|
+
)
|
|
187
198
|
|
|
188
199
|
dic = AcquisitionTmpData(
|
|
189
200
|
experiment_name=name,
|
|
@@ -194,7 +205,9 @@ class AcquisitionManager:
|
|
|
194
205
|
|
|
195
206
|
self.acquisition_tmp_data = dic
|
|
196
207
|
|
|
197
|
-
self._current_acquisition = self.get_acquisition(
|
|
208
|
+
self._current_acquisition = self.get_acquisition(
|
|
209
|
+
replace=True, save_on_edit=save_on_edit
|
|
210
|
+
)
|
|
198
211
|
|
|
199
212
|
return self.current_acquisition
|
|
200
213
|
|
|
@@ -208,7 +221,9 @@ class AcquisitionManager:
|
|
|
208
221
|
configs = read_files(self.config_files)
|
|
209
222
|
|
|
210
223
|
if self.config_files_eval:
|
|
211
|
-
configs = append_values_from_modules_to_files(
|
|
224
|
+
configs = append_values_from_modules_to_files(
|
|
225
|
+
configs, self.config_files_eval
|
|
226
|
+
)
|
|
212
227
|
|
|
213
228
|
if name is None:
|
|
214
229
|
name = self.current_experiment_name + "_item"
|
|
@@ -252,13 +267,17 @@ class AcquisitionManager:
|
|
|
252
267
|
|
|
253
268
|
@property
|
|
254
269
|
def current_experiment_name(self) -> str:
|
|
255
|
-
return
|
|
270
|
+
return (
|
|
271
|
+
self.acquisition_tmp_data.experiment_name
|
|
272
|
+
) # self.current_acquisition.name
|
|
256
273
|
|
|
257
274
|
def get_acquisition(
|
|
258
275
|
self, replace: Optional[bool] = False, save_on_edit: Optional[bool] = None
|
|
259
276
|
) -> NotebookAcquisitionData:
|
|
260
277
|
acquisition_tmp_data = self.acquisition_tmp_data
|
|
261
|
-
filepath = self.create_path_from_tmp_data(
|
|
278
|
+
filepath = self.create_path_from_tmp_data(
|
|
279
|
+
acquisition_tmp_data, ignore_existence=True
|
|
280
|
+
)
|
|
262
281
|
configs = acquisition_tmp_data.configs
|
|
263
282
|
configs = configs if configs else None
|
|
264
283
|
cell = self.cell
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
"""AnalysisData class."""
|
|
2
|
+
|
|
2
3
|
import os
|
|
3
4
|
from typing import List, Literal, Optional, Protocol, Tuple, TypeVar, Union
|
|
4
5
|
|
|
5
|
-
|
|
6
6
|
from dh5 import DH5
|
|
7
7
|
from dh5.path import Path
|
|
8
8
|
|
|
9
|
+
from .. import utils
|
|
9
10
|
from .analysis_loop import AnalysisLoop
|
|
10
|
-
|
|
11
11
|
from .config_file import ConfigFile
|
|
12
|
-
from .. import utils
|
|
13
12
|
from .logger_setup import logger
|
|
14
13
|
|
|
15
14
|
_T = TypeVar("_T", bound="AnalysisData")
|
|
@@ -95,7 +94,10 @@ class AnalysisData(DH5):
|
|
|
95
94
|
raise ValueError(f"File '{filepath}' does not exist.")
|
|
96
95
|
|
|
97
96
|
super().__init__(
|
|
98
|
-
filepath=filepath,
|
|
97
|
+
filepath=filepath,
|
|
98
|
+
overwrite=False,
|
|
99
|
+
read_only=False,
|
|
100
|
+
save_on_edit=save_on_edit,
|
|
99
101
|
)
|
|
100
102
|
|
|
101
103
|
self.lock_data()
|
|
@@ -146,9 +148,9 @@ class AnalysisData(DH5):
|
|
|
146
148
|
logger.warning("Analysis cell is not set. Nothing to save")
|
|
147
149
|
return self
|
|
148
150
|
|
|
149
|
-
self.unlock_data(cell_name_key).update({cell_name_key: code}).lock_data(
|
|
150
|
-
|
|
151
|
-
)
|
|
151
|
+
self.unlock_data(cell_name_key).update({cell_name_key: code}).lock_data(
|
|
152
|
+
cell_name_key
|
|
153
|
+
).save([cell_name_key])
|
|
152
154
|
|
|
153
155
|
if self._save_files:
|
|
154
156
|
assert self.filepath, "You must set self.filepath before saving"
|
|
@@ -185,13 +187,18 @@ class AnalysisData(DH5):
|
|
|
185
187
|
"inside_h5", False
|
|
186
188
|
):
|
|
187
189
|
try:
|
|
188
|
-
|
|
190
|
+
raise NotImplementedError(
|
|
191
|
+
"save_fig_inside_h5 is not implemented for the moment."
|
|
192
|
+
)
|
|
193
|
+
# import pltsave
|
|
189
194
|
|
|
190
|
-
data = pltsave.dumps(fig).to_json()
|
|
191
|
-
self[f"figures/{fig_name}"] = data
|
|
192
|
-
self.save([f"figures/{fig_name}"])
|
|
195
|
+
# data = pltsave.dumps(fig).to_json()
|
|
196
|
+
# self[f"figures/{fig_name}"] = data
|
|
197
|
+
# self.save([f"figures/{fig_name}"])
|
|
193
198
|
except Exception as error:
|
|
194
|
-
logger.exception(
|
|
199
|
+
logger.exception(
|
|
200
|
+
"Failed to save the figure inside h5 file due to %s", error
|
|
201
|
+
)
|
|
195
202
|
if tight_layout and hasattr(fig, "tight_layout"):
|
|
196
203
|
fig.tight_layout() # type: ignore
|
|
197
204
|
fig.savefig(full_fig_name, **kwargs)
|
|
@@ -229,7 +236,9 @@ class AnalysisData(DH5):
|
|
|
229
236
|
|
|
230
237
|
return "FIG" + name
|
|
231
238
|
|
|
232
|
-
def parse_config(
|
|
239
|
+
def parse_config(
|
|
240
|
+
self, config_files: Optional[Tuple[str, ...]] = None
|
|
241
|
+
) -> "ConfigFile":
|
|
233
242
|
"""Parse config files. If `config_files` are not provided takes `default_config_files`."""
|
|
234
243
|
|
|
235
244
|
config_files = config_files or self._default_config_files
|
|
@@ -240,7 +249,8 @@ class AnalysisData(DH5):
|
|
|
240
249
|
return self._parsed_configs[hash(config_files)]
|
|
241
250
|
|
|
242
251
|
config_data = sum(
|
|
243
|
-
(self.parse_config_file(config_file) for config_file in config_files),
|
|
252
|
+
(self.parse_config_file(config_file) for config_file in config_files),
|
|
253
|
+
ConfigFile(),
|
|
244
254
|
)
|
|
245
255
|
|
|
246
256
|
self._parsed_configs[hash(config_files)] = config_data
|
|
@@ -263,7 +273,9 @@ class AnalysisData(DH5):
|
|
|
263
273
|
if key_value == "filename" or key_value == "file" or key_value == "f":
|
|
264
274
|
filename = os.path.split(self.filepath)[-1]
|
|
265
275
|
keys_with_values.append(
|
|
266
|
-
utils.title_parsing.ValueForPrint(
|
|
276
|
+
utils.title_parsing.ValueForPrint(
|
|
277
|
+
key_value, filename, key_units, key_format
|
|
278
|
+
)
|
|
267
279
|
)
|
|
268
280
|
elif key_value in config_data:
|
|
269
281
|
keys_with_values.append(
|
|
@@ -316,7 +328,9 @@ class AnalysisData(DH5):
|
|
|
316
328
|
)
|
|
317
329
|
|
|
318
330
|
if config_file_name in self._parsed_configs:
|
|
319
|
-
self._parsed_configs[original_config_name] = self._parsed_configs[
|
|
331
|
+
self._parsed_configs[original_config_name] = self._parsed_configs[
|
|
332
|
+
config_file_name
|
|
333
|
+
]
|
|
320
334
|
return self._parsed_configs[config_file_name]
|
|
321
335
|
|
|
322
336
|
else:
|
|
@@ -339,7 +353,9 @@ class AnalysisData(DH5):
|
|
|
339
353
|
(config_files,) if isinstance(config_files, str) else tuple(config_files)
|
|
340
354
|
)
|
|
341
355
|
|
|
342
|
-
def get_analysis_code(
|
|
356
|
+
def get_analysis_code(
|
|
357
|
+
self, name: str = "default", /, update_code: bool = True
|
|
358
|
+
) -> str:
|
|
343
359
|
code: Optional[dict] = self.get("analysis_cells")
|
|
344
360
|
if code is None:
|
|
345
361
|
raise ValueError(
|
|
@@ -350,7 +366,9 @@ class AnalysisData(DH5):
|
|
|
350
366
|
# if isinstance(code, bytes):
|
|
351
367
|
# code = code.decode()
|
|
352
368
|
if name not in code:
|
|
353
|
-
raise KeyError(
|
|
369
|
+
raise KeyError(
|
|
370
|
+
f"Cannot get cell '{name}'. Possible cells are: {tuple(code.keys())}"
|
|
371
|
+
)
|
|
354
372
|
|
|
355
373
|
code_str: str = code[name]
|
|
356
374
|
if update_code:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
It has mainly __iter__ method and __getitem__ method for slicing.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from typing import Any, List, Optional,
|
|
5
|
+
from typing import Any, Iterable, List, Optional, Tuple, Union
|
|
6
6
|
|
|
7
7
|
from dh5 import DH5
|
|
8
8
|
|
|
@@ -39,7 +39,9 @@ class AnalysisLoop(DH5):
|
|
|
39
39
|
|
|
40
40
|
"""
|
|
41
41
|
|
|
42
|
-
def __init__(
|
|
42
|
+
def __init__(
|
|
43
|
+
self, data: Optional[dict] = None, loop_shape: Optional[List[int]] = None
|
|
44
|
+
):
|
|
43
45
|
"""Initialize an AnalysisLoop object.
|
|
44
46
|
|
|
45
47
|
Args:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Custom additional linter functions for the acquisition module."""
|
|
2
|
+
|
|
2
3
|
import ast
|
|
3
4
|
from typing import Any, Dict
|
|
4
5
|
|
|
@@ -24,7 +25,9 @@ def on_call_functions(node: ast.Call, db: Dict[str, Any]):
|
|
|
24
25
|
h = hash(tuple(get_all_args_from_call(node)))
|
|
25
26
|
data = db.setdefault("save_fig", [])
|
|
26
27
|
if h in data:
|
|
27
|
-
errors.append(
|
|
28
|
+
errors.append(
|
|
29
|
+
"save_fig with the save arguments is used more then ones."
|
|
30
|
+
)
|
|
28
31
|
|
|
29
32
|
data.append(h)
|
|
30
33
|
return errors
|
|
@@ -264,7 +264,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
264
264
|
|
|
265
265
|
def load_file(self, filename) -> "AnalysisData":
|
|
266
266
|
filename = self._get_full_filename(filename)
|
|
267
|
-
if not os.path.exists(
|
|
267
|
+
if not os.path.exists(
|
|
268
|
+
filename if filename.endswith(".h5") else filename + ".h5"
|
|
269
|
+
):
|
|
268
270
|
raise ValueError(f"File {filename} cannot be found")
|
|
269
271
|
|
|
270
272
|
data = AnalysisData(
|
|
@@ -325,7 +327,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
325
327
|
display_warning("Old data analysis")
|
|
326
328
|
|
|
327
329
|
filename = str(filepath or self._get_full_filename(filename)) # type: ignore
|
|
328
|
-
filename = (
|
|
330
|
+
filename = (
|
|
331
|
+
(filename.rsplit(".h5", 1)[0]) if filename.endswith(".h5") else filename
|
|
332
|
+
)
|
|
329
333
|
|
|
330
334
|
else:
|
|
331
335
|
self._is_old_data = False
|
|
@@ -340,7 +344,8 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
340
344
|
)
|
|
341
345
|
or (
|
|
342
346
|
acquisition_name[0] == r"^"
|
|
343
|
-
and re.match(acquisition_name, self.current_experiment_name)
|
|
347
|
+
and re.match(acquisition_name, self.current_experiment_name)
|
|
348
|
+
is None
|
|
344
349
|
)
|
|
345
350
|
):
|
|
346
351
|
raise ValueError(
|
|
@@ -374,7 +379,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
374
379
|
if cell is not None:
|
|
375
380
|
self.save_analysis_cell(cell=cell)
|
|
376
381
|
|
|
377
|
-
if (self._analysis_cell_str is not None) and (
|
|
382
|
+
if (self._analysis_cell_str is not None) and (
|
|
383
|
+
self._linting_external_vars is not None
|
|
384
|
+
):
|
|
378
385
|
from ..acquisition import custom_lint
|
|
379
386
|
from ..utils import lint
|
|
380
387
|
|
|
@@ -387,7 +394,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
387
394
|
run_on_call=custom_lint.on_call_functions,
|
|
388
395
|
)
|
|
389
396
|
for var in lint_result.external_vars:
|
|
390
|
-
logger.warning(
|
|
397
|
+
logger.warning(
|
|
398
|
+
"External variable used inside the analysis code: %s", var
|
|
399
|
+
)
|
|
391
400
|
for error in lint_result.errors:
|
|
392
401
|
logger.warning(error)
|
|
393
402
|
utils.run_functions(self._analysis_cell_prerun_hook)
|
|
@@ -417,7 +426,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
417
426
|
def parse_config_file(self, config_file_name: str, /) -> "ConfigFile":
|
|
418
427
|
return self.data.parse_config_file(config_file_name)
|
|
419
428
|
|
|
420
|
-
def parse_config(
|
|
429
|
+
def parse_config(
|
|
430
|
+
self, config_files: Optional[Tuple[str, ...]] = None
|
|
431
|
+
) -> "ConfigFile":
|
|
421
432
|
return self.data.parse_config(config_files=config_files)
|
|
422
433
|
|
|
423
434
|
@property
|
|
@@ -433,16 +444,22 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
433
444
|
return self.data.parse_config_str(values, max_length=max_length)
|
|
434
445
|
|
|
435
446
|
def linting(
|
|
436
|
-
self,
|
|
447
|
+
self,
|
|
448
|
+
allowed_variables: Optional[Iterable[str]] = None,
|
|
449
|
+
init_file: Optional[str] = None,
|
|
437
450
|
):
|
|
438
451
|
from ..utils import lint
|
|
439
452
|
|
|
440
|
-
allowed_variables =
|
|
453
|
+
allowed_variables = (
|
|
454
|
+
set() if allowed_variables is None else set(allowed_variables)
|
|
455
|
+
)
|
|
441
456
|
if init_file is not None:
|
|
442
457
|
allowed_variables.update(lint.find_variables_from_file(init_file)[0])
|
|
443
458
|
self._linting_external_vars = allowed_variables
|
|
444
459
|
|
|
445
|
-
def set_default_config_files(
|
|
460
|
+
def set_default_config_files(
|
|
461
|
+
self, config_files: Union[str, Tuple[str, ...], List[str]], /
|
|
462
|
+
):
|
|
446
463
|
self._default_config_files = (
|
|
447
464
|
(config_files,) if isinstance(config_files, str) else tuple(config_files)
|
|
448
465
|
)
|
|
@@ -452,7 +469,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
452
469
|
def set_analysis_cell_prerun_hook(
|
|
453
470
|
self,
|
|
454
471
|
hook: Union[
|
|
455
|
-
_CallableWithNoArgs,
|
|
472
|
+
_CallableWithNoArgs,
|
|
473
|
+
List[_CallableWithNoArgs],
|
|
474
|
+
Tuple[_CallableWithNoArgs, ...],
|
|
456
475
|
],
|
|
457
476
|
):
|
|
458
477
|
self._analysis_cell_prerun_hook = (
|
|
@@ -462,7 +481,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
462
481
|
def set_acquisition_cell_prerun_hook(
|
|
463
482
|
self,
|
|
464
483
|
hook: Union[
|
|
465
|
-
_CallableWithNoArgs,
|
|
484
|
+
_CallableWithNoArgs,
|
|
485
|
+
List[_CallableWithNoArgs],
|
|
486
|
+
Tuple[_CallableWithNoArgs, ...],
|
|
466
487
|
],
|
|
467
488
|
):
|
|
468
489
|
self._acquisition_cell_prerun_hook = (
|
|
@@ -502,7 +523,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
502
523
|
|
|
503
524
|
res = self.find_param_in_config(param_text)
|
|
504
525
|
if res is None:
|
|
505
|
-
logger.warning(
|
|
526
|
+
logger.warning(
|
|
527
|
+
"Parameter '%s' cannot be found in default config files.", param
|
|
528
|
+
)
|
|
506
529
|
continue
|
|
507
530
|
file, line_no = res
|
|
508
531
|
link = display.links.create_link(param_text, file, line_no, after_text)
|
|
@@ -511,7 +534,9 @@ class AcquisitionAnalysisManager(AcquisitionManager):
|
|
|
511
534
|
|
|
512
535
|
def connect_default_widget(
|
|
513
536
|
self,
|
|
514
|
-
objs: Union[
|
|
537
|
+
objs: Union[
|
|
538
|
+
"display_widget.WidgetProtocol", List["display_widget.WidgetProtocol"]
|
|
539
|
+
],
|
|
515
540
|
):
|
|
516
541
|
if not isinstance(objs, (list, tuple)):
|
|
517
542
|
objs = [objs]
|
|
@@ -198,9 +198,9 @@ def _create_file_link(aqm: "AcquisitionAnalysisManager", level_up) -> str:
|
|
|
198
198
|
if filepath is None:
|
|
199
199
|
return ""
|
|
200
200
|
link_name = os.path.basename(filepath)
|
|
201
|
-
link = "/".join(
|
|
202
|
-
"
|
|
203
|
-
)
|
|
201
|
+
link = "/".join(
|
|
202
|
+
os.path.abspath(filepath).replace("\\", "/").split("/")[-level_up:]
|
|
203
|
+
).replace(" ", "%20")
|
|
204
204
|
link = f"[{link_name}](//kyrylo-gr.github.io/h5viewer/open?url={link})"
|
|
205
205
|
return link
|
|
206
206
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""This module contains the AttrDict class."""
|
|
2
|
+
|
|
2
3
|
from typing import Any, List, Optional, Tuple, Union, overload
|
|
4
|
+
|
|
3
5
|
from ..utils import title_parsing as utils_parse
|
|
4
6
|
|
|
5
7
|
|
|
@@ -30,12 +32,10 @@ class AttrDict(dict):
|
|
|
30
32
|
return type(self)(result)
|
|
31
33
|
|
|
32
34
|
@overload
|
|
33
|
-
def find_all(self, key: str) -> List[Tuple[str, Any]]:
|
|
34
|
-
...
|
|
35
|
+
def find_all(self, key: str) -> List[Tuple[str, Any]]: ... # noqa
|
|
35
36
|
|
|
36
37
|
@overload
|
|
37
|
-
def find_all(self, key: list) -> List[List[Tuple[str, Any]]]:
|
|
38
|
-
...
|
|
38
|
+
def find_all(self, key: list) -> List[List[Tuple[str, Any]]]: ... # noqa
|
|
39
39
|
|
|
40
40
|
def find_all(self, key: Union[str, list]):
|
|
41
41
|
"""Find all keys that contain the given string.
|
|
@@ -54,12 +54,10 @@ class AttrDict(dict):
|
|
|
54
54
|
return elms
|
|
55
55
|
|
|
56
56
|
@overload
|
|
57
|
-
def find(self, key: str) -> Optional[Tuple[str, Any]]:
|
|
58
|
-
...
|
|
57
|
+
def find(self, key: str) -> Optional[Tuple[str, Any]]: ... # noqa
|
|
59
58
|
|
|
60
59
|
@overload
|
|
61
|
-
def find(self, key: list) -> List[Optional[Tuple[str, Any]]]:
|
|
62
|
-
...
|
|
60
|
+
def find(self, key: list) -> List[Optional[Tuple[str, Any]]]: ... # noqa
|
|
63
61
|
|
|
64
62
|
def find(self, key: Union[str, list]) -> Union[Optional[tuple], list]:
|
|
65
63
|
"""Find the first key that contain the given string.
|
|
@@ -94,15 +92,21 @@ class AttrDict(dict):
|
|
|
94
92
|
keys_with_values = self.__get_value_for_output(keys)
|
|
95
93
|
return utils_parse.format_title(keys_with_values, max_length=max_length)
|
|
96
94
|
|
|
97
|
-
def __get_value_for_output(
|
|
95
|
+
def __get_value_for_output(
|
|
96
|
+
self, keys: List[str]
|
|
97
|
+
) -> List[utils_parse.ValueForPrint]:
|
|
98
98
|
"""Prepare the values for output. Returns list of ValueForPrint(key, value, unit, format))."""
|
|
99
99
|
keys_with_values = []
|
|
100
100
|
for key in keys:
|
|
101
101
|
key_value, key_units, key_format = utils_parse.parse_get_format(key)
|
|
102
102
|
if key_value in self:
|
|
103
103
|
keys_with_values.append(
|
|
104
|
-
utils_parse.ValueForPrint(
|
|
104
|
+
utils_parse.ValueForPrint(
|
|
105
|
+
key_value, self[key_value], key_units, key_format
|
|
106
|
+
)
|
|
105
107
|
)
|
|
106
108
|
else:
|
|
107
|
-
raise ValueError(
|
|
109
|
+
raise ValueError(
|
|
110
|
+
f"Cannot find key={key} inside {self.__class__.__name__}"
|
|
111
|
+
)
|
|
108
112
|
return keys_with_values
|
labmate/display/__init__.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# flake8: noqa: F401
|
|
2
|
-
from typing import Any, TYPE_CHECKING
|
|
3
2
|
import importlib
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
|
-
from .main import display_html,
|
|
5
|
+
from .main import display, display_html, display_widgets, logger
|
|
6
6
|
|
|
7
7
|
__all__ = ["links", "buttons", "logger"]
|
|
8
8
|
|
|
@@ -14,7 +14,9 @@ class _LazyModule:
|
|
|
14
14
|
|
|
15
15
|
def __getattr__(self, name):
|
|
16
16
|
if self.__module is None:
|
|
17
|
-
self.__module = importlib.import_module(
|
|
17
|
+
self.__module = importlib.import_module(
|
|
18
|
+
f".{self.__name}", package=__package__
|
|
19
|
+
)
|
|
18
20
|
return getattr(self.__module, name)
|
|
19
21
|
|
|
20
22
|
# @property
|
|
@@ -29,5 +31,4 @@ buttons = _LazyModule("buttons")
|
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
if TYPE_CHECKING:
|
|
32
|
-
from . import links
|
|
33
|
-
from . import buttons
|
|
34
|
+
from . import buttons, links
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""This submodule contains functions that are specific for windows."""
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def copy_fig(
|
|
4
|
+
def copy_fig(
|
|
5
|
+
fig=None, format_=None, text_to_copy=None, **kwargs
|
|
6
|
+
): # pragma: no cover <--
|
|
5
7
|
"""Copy fig to the clipboard.
|
|
6
8
|
|
|
7
9
|
Parameters
|
|
@@ -24,10 +26,10 @@ def copy_fig(fig=None, format_=None, text_to_copy=None, **kwargs): # pragma: no
|
|
|
24
26
|
If no figure is found
|
|
25
27
|
"""
|
|
26
28
|
# from win32gui import GetWindowText, GetForegroundWindow # type: ignore import warnings
|
|
27
|
-
|
|
29
|
+
from io import BytesIO
|
|
28
30
|
|
|
29
31
|
import matplotlib.pyplot as plt
|
|
30
|
-
|
|
32
|
+
import win32clipboard # type: ignore import warnings
|
|
31
33
|
|
|
32
34
|
# Determined available values by digging into windows API
|
|
33
35
|
format_map = {
|
|
@@ -71,7 +73,9 @@ def copy_fig(fig=None, format_=None, text_to_copy=None, **kwargs): # pragma: no
|
|
|
71
73
|
im = Image.open(buf)
|
|
72
74
|
with BytesIO() as output:
|
|
73
75
|
im.convert("RGB").save(output, "BMP")
|
|
74
|
-
data = output.getvalue()[
|
|
76
|
+
data = output.getvalue()[
|
|
77
|
+
14:
|
|
78
|
+
] # The file header off-set of BMP is 14 bytes
|
|
75
79
|
format_id = win32clipboard.CF_DIB # DIB = device independent bitmap
|
|
76
80
|
|
|
77
81
|
except ImportError:
|
|
@@ -85,6 +89,8 @@ def copy_fig(fig=None, format_=None, text_to_copy=None, **kwargs): # pragma: no
|
|
|
85
89
|
win32clipboard.EmptyClipboard()
|
|
86
90
|
win32clipboard.SetClipboardData(format_id, data)
|
|
87
91
|
if text_to_copy:
|
|
88
|
-
win32clipboard.SetClipboardData(
|
|
92
|
+
win32clipboard.SetClipboardData(
|
|
93
|
+
win32clipboard.CF_TEXT, text_to_copy.encode("utf-8")
|
|
94
|
+
)
|
|
89
95
|
|
|
90
96
|
win32clipboard.CloseClipboard()
|
labmate/parsing/saving.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""This file contains functions that prepare file for saving for further parsing."""
|
|
2
|
+
|
|
2
3
|
from typing import Dict
|
|
4
|
+
|
|
3
5
|
from . import parse_str
|
|
4
6
|
|
|
5
7
|
|
|
@@ -25,7 +27,9 @@ def append_values_from_modules_to_files(
|
|
|
25
27
|
return configs
|
|
26
28
|
|
|
27
29
|
|
|
28
|
-
def append_values_from_module_to_file(
|
|
30
|
+
def append_values_from_module_to_file(
|
|
31
|
+
body: str, module, separator=" # value: "
|
|
32
|
+
) -> str:
|
|
29
33
|
"""Add values from a module to a given file body.
|
|
30
34
|
|
|
31
35
|
Args:
|
|
@@ -64,7 +68,9 @@ def append_values_from_module_to_file(body: str, module, separator=" # value: "
|
|
|
64
68
|
for key, (val, _) in parse_str(line).items():
|
|
65
69
|
real_val = variables.get(key, "")
|
|
66
70
|
if (
|
|
67
|
-
isinstance(val, str)
|
|
71
|
+
isinstance(val, str)
|
|
72
|
+
and isinstance(real_val, str)
|
|
73
|
+
and real_val != val.strip("\"'")
|
|
68
74
|
) or (
|
|
69
75
|
isinstance(val, str)
|
|
70
76
|
and isinstance(real_val, (float, int, complex))
|
labmate/utils/lint.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Linting module that detects bad practice with AcquisitionAnalysisManager."""
|
|
2
|
+
|
|
2
3
|
import ast
|
|
3
4
|
from typing import Any, Callable, Dict, List, NamedTuple, Optional, Set
|
|
4
5
|
|
|
@@ -197,7 +198,9 @@ class LintResult(NamedTuple):
|
|
|
197
198
|
errors: List[str]
|
|
198
199
|
|
|
199
200
|
|
|
200
|
-
def find_variables_from_node(
|
|
201
|
+
def find_variables_from_node(
|
|
202
|
+
node, ignore_var: Optional[set] = None, **kwargs
|
|
203
|
+
) -> LintResult:
|
|
201
204
|
"""Walk through ast.node and find the variable that was never declared inside this node, but used.
|
|
202
205
|
|
|
203
206
|
Variables from ingore_var set is allowed external variables to use.
|
labmate/utils/random_utils.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Random utilities."""
|
|
2
|
+
|
|
2
3
|
from typing import Any, Callable, List, Optional, Tuple, Union
|
|
3
4
|
|
|
4
5
|
from dh5.utils.random_utils import ( # pylint: disable=unused-import # noqa: F401
|
|
@@ -6,13 +7,16 @@ from dh5.utils.random_utils import ( # pylint: disable=unused-import # noqa: F4
|
|
|
6
7
|
get_timestamp,
|
|
7
8
|
)
|
|
8
9
|
|
|
9
|
-
|
|
10
10
|
_CallableWithNoArgs = Callable[[], Any]
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def run_functions(
|
|
14
14
|
functions: Optional[
|
|
15
|
-
Union[
|
|
15
|
+
Union[
|
|
16
|
+
_CallableWithNoArgs,
|
|
17
|
+
List[_CallableWithNoArgs],
|
|
18
|
+
Tuple[_CallableWithNoArgs, ...],
|
|
19
|
+
]
|
|
16
20
|
] = None,
|
|
17
21
|
/,
|
|
18
22
|
):
|
labmate/utils/title_parsing.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""This file contains function of title generation.
|
|
2
2
|
(parsing expected units and format, creating title)
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from typing import Any, List, NamedTuple, Optional, Tuple
|
|
5
6
|
|
|
6
7
|
|
|
@@ -47,10 +48,14 @@ def format_title(values: List[ValueForPrint], max_length: Optional[int] = None)
|
|
|
47
48
|
for value in values:
|
|
48
49
|
units = f" ({value.units})" if value.units is not None else ""
|
|
49
50
|
value_str = (
|
|
50
|
-
value.value
|
|
51
|
+
value.value
|
|
52
|
+
if value.format is None
|
|
53
|
+
else value.value.__format__(f".{value.format}")
|
|
51
54
|
)
|
|
52
55
|
new_txt = f"{value.key} = {value_str}{units}"
|
|
53
|
-
if not max_length or (
|
|
56
|
+
if not max_length or (
|
|
57
|
+
(last_line_len + len(new_txt) < max_length) or last_line_len == 0
|
|
58
|
+
):
|
|
54
59
|
txt += ("; " if txt != "" else "") + new_txt
|
|
55
60
|
last_line_len += len(new_txt) + 2
|
|
56
61
|
else:
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
labmate/__config__.py,sha256=
|
|
1
|
+
labmate/__config__.py,sha256=SjpU4iAgKRHNr6dEbjqw0YR8l6kjHwceS5UAD_5Gd2I,71
|
|
2
2
|
labmate/__init__.py,sha256=aHQiPLldCXIJqz6wwcfyFU9sGLofUR3W5sXBIRzK2n4,182
|
|
3
3
|
labmate/acquisition/__init__.py,sha256=8q3dy18lL32A9y_Du8GggpLgJqDMFcFKddHrySMavrM,269
|
|
4
4
|
labmate/acquisition/acquisition_data.py,sha256=Ic-rf8VKs9erjv1wQ8txvdlSRK87ar5Z0TUVvOrl_Bw,5534
|
|
5
|
-
labmate/acquisition/acquisition_loop.py,sha256=
|
|
6
|
-
labmate/acquisition/acquisition_manager.py,sha256=
|
|
7
|
-
labmate/acquisition/analysis_data.py,sha256=
|
|
8
|
-
labmate/acquisition/analysis_loop.py,sha256=
|
|
5
|
+
labmate/acquisition/acquisition_loop.py,sha256=ldp9Hoz9C3x89FFYiHasezOYooKto7x2MaYUjlz-NrE,11240
|
|
6
|
+
labmate/acquisition/acquisition_manager.py,sha256=rKDUgR-IbQ0dzS728DtZKGkksanhrgeYduk4AmqRX0E,10370
|
|
7
|
+
labmate/acquisition/analysis_data.py,sha256=DF9NshXBWu74gK8b_ZOGIuveabkzbLIDXfyui1c4yK8,14695
|
|
8
|
+
labmate/acquisition/analysis_loop.py,sha256=1Y8lyPkTCNwskM8DkwrMXSOt0hNmBHcWJaQjdVZ81Hs,5075
|
|
9
9
|
labmate/acquisition/config_file.py,sha256=1WwqaKTM-R5xZQHqqqGUi2QCF0PC1ag2mFgPOJuEdWI,2212
|
|
10
|
-
labmate/acquisition/custom_lint.py,sha256=
|
|
10
|
+
labmate/acquisition/custom_lint.py,sha256=x4vNoOnbH3A4Odu2DQVtBsuSPo5JfvRpo8_EP0EOmgM,1005
|
|
11
11
|
labmate/acquisition/logger_setup.py,sha256=udTp-0S4cqhGdUGQlk3G3Eg51wePEGraNG-69P9fTOo,129
|
|
12
12
|
labmate/acquisition_notebook/__init__.py,sha256=ZtOGQtmPqEM1IRrL-_JYo4xYA87lFQ5JY5GmKcZz9z0,251
|
|
13
|
-
labmate/acquisition_notebook/acquisition_analysis_manager.py,sha256=
|
|
14
|
-
labmate/acquisition_notebook/display_widget.py,sha256=
|
|
13
|
+
labmate/acquisition_notebook/acquisition_analysis_manager.py,sha256=UJR5oH4AtUMlh6BOUUxmbUvDXggN08wppOGind07iV0,19286
|
|
14
|
+
labmate/acquisition_notebook/display_widget.py,sha256=VNSo7r5nY_8biq-PAJeLvU_nzJ71kS82gFuOy-762BQ,6918
|
|
15
15
|
labmate/attrdict/__init__.py,sha256=MvuZVe7j4a0HxGMxim_K2cv-dhqZOfzdeMiTX-SRgDg,58
|
|
16
|
-
labmate/attrdict/attrdict_class.py,sha256=
|
|
17
|
-
labmate/display/__init__.py,sha256=
|
|
16
|
+
labmate/attrdict/attrdict_class.py,sha256=4lKXe7oZo_lLHefmf5vAOKhibWgGDffJcxMhaWLvGs4,4047
|
|
17
|
+
labmate/display/__init__.py,sha256=tD9kCR-2VpV2Fvm7cpw4mDgqMCEXIXh_AOO5KLawxEo,844
|
|
18
18
|
labmate/display/buttons.py,sha256=_WbtS5PVpjgH2UEaSM5MACGHqcWiCSV3xN8di-MI7hk,2861
|
|
19
19
|
labmate/display/html_output.py,sha256=SRsrszxBxuv-sQaWEkW_fyxFbImyJVj76iMTysqxKa4,425
|
|
20
20
|
labmate/display/links.py,sha256=YgCNxowca-oHxqozGWbe4oGLzwltnZ-C0v3E5fQnK0U,746
|
|
21
21
|
labmate/display/main.py,sha256=5M0-ckxhkCH0LXaZN6HD61b0noMypolKC9foEQmXx9w,1852
|
|
22
22
|
labmate/display/platform_utils/__init__.py,sha256=GOWB9vXF-wxGZfdHQJlQWy-hy2V2KXUP3JwxgN91Fq4,1136
|
|
23
|
-
labmate/display/platform_utils/windows_utils.py,sha256=
|
|
23
|
+
labmate/display/platform_utils/windows_utils.py,sha256=4Z_avuJIZ_KoXkuRZOH2667t2wEljzNBMP6fbNDknuk,3268
|
|
24
24
|
labmate/parsing/__init__.py,sha256=AHNB502jlm6PGd49_PJjvSxt97fxJeXnIfXYh8HV5x0,1312
|
|
25
25
|
labmate/parsing/brackets_score.py,sha256=zzup7z6o57YUGeMr5FOSTo3nz9Z62s2omxqFV3M9MmI,988
|
|
26
26
|
labmate/parsing/parsed_value.py,sha256=UYB_gCkV3DiFQRjcprnQUPw--FqYPqb3pii-PQsbHf0,5261
|
|
27
|
-
labmate/parsing/saving.py,sha256=
|
|
27
|
+
labmate/parsing/saving.py,sha256=pwCdYI9shrpKyFceRPNbPcbEfJbNQ7Xj0AMsDOr5qLA,2548
|
|
28
28
|
labmate/utils/__init__.py,sha256=PExO1TzVGwb9dXVZ733iML2H-ZFly-dksiHLgFU1xr4,72
|
|
29
29
|
labmate/utils/async_utils.py,sha256=mSfmpF7I3M5KePkPtoS-OcuoCkFDHPKjf-RVF0P3R48,118
|
|
30
30
|
labmate/utils/autoreload.py,sha256=wKi1GgWyRu1h101OguVRpO3zQXZ8qsFj-K-1P8PKuq8,305
|
|
31
31
|
labmate/utils/errors.py,sha256=ly7-JQStTKmPiMuT0w3eXFw1O8-1kpTsqZT2jebpJ-I,140
|
|
32
32
|
labmate/utils/file_read.py,sha256=DAalvKehwEqVZjWSPhKZm8Myh6gfFA5gGT6WM0dPmyw,1536
|
|
33
|
-
labmate/utils/lint.py,sha256=
|
|
34
|
-
labmate/utils/random_utils.py,sha256=
|
|
35
|
-
labmate/utils/title_parsing.py,sha256=
|
|
36
|
-
labmate-0.8.
|
|
37
|
-
labmate-0.8.
|
|
38
|
-
labmate-0.8.
|
|
39
|
-
labmate-0.8.
|
|
40
|
-
labmate-0.8.
|
|
33
|
+
labmate/utils/lint.py,sha256=7llJbZUAM-ikEpmU_ZzraqOwGUuJPgk1wAf3aYMJdxg,9312
|
|
34
|
+
labmate/utils/random_utils.py,sha256=ZA3gK9P-eTcd_a3BTS_ZeJI5A0GM_GXL7X3yUqnPTO4,690
|
|
35
|
+
labmate/utils/title_parsing.py,sha256=RpbiZwuKnpIq-X5S5iS90oD8iOqocWcI27MGuB4kTLU,1988
|
|
36
|
+
labmate-0.8.3.dist-info/LICENCE,sha256=J9XIxdJExlWYZuxhhKtk4oYILvUz8-JM0y_leRQCKUE,7488
|
|
37
|
+
labmate-0.8.3.dist-info/METADATA,sha256=3lNnMZu3K0M6DkQdjAkgwQ0a3s8vEJdJ7-7C7lj4yK4,3210
|
|
38
|
+
labmate-0.8.3.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
|
|
39
|
+
labmate-0.8.3.dist-info/top_level.txt,sha256=WWAn6t2zNWsp02gRq6f5cSsGebcs-4L6HBFk0XrcY0o,8
|
|
40
|
+
labmate-0.8.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|