QuLab 2.3.4__cp311-cp311-macosx_10_9_universal2.whl → 2.3.5__cp311-cp311-macosx_10_9_universal2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: QuLab
3
- Version: 2.3.4
3
+ Version: 2.3.5
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -1,7 +1,7 @@
1
1
  qulab/__init__.py,sha256=P-Mx2p4TVmL91SoxoeXcj8Qm0x4xUf5Q_FLk0Yc_gIQ,138
2
2
  qulab/__main__.py,sha256=ZC1NKaoxKyy60DaCfB8vYnB1z3RXQ2j8E1sRZ4A8sXE,428
3
- qulab/fun.cpython-311-darwin.so,sha256=VAuzZloDPT2N99qUrQIFhgFcr9_xk3BSQ_7PXUyDVJ4,159616
4
- qulab/version.py,sha256=MtmOJMh3yHY9aTdRsZDgbpPfbzm9xdycdi9jjMKzYjM,21
3
+ qulab/fun.cpython-311-darwin.so,sha256=nz9tH3sg-_U0-Vw0Sedf9P4Vjai9kxjWhQv2eXPvd3I,159616
4
+ qulab/version.py,sha256=ctNy09QkNipfMu2fxyFBsAXtRoAHMP1bEKHsc3zRmkk,21
5
5
  qulab/monitor/__init__.py,sha256=nTHelnDpxRS_fl_B38TsN0njgq8eVTEz9IAnN3NbDlM,42
6
6
  qulab/monitor/__main__.py,sha256=w3yUcqq195LzSnXTkQcuC1RSFRhy4oQ_PEBmucXguME,97
7
7
  qulab/monitor/config.py,sha256=fQ5JcsMApKc1UwANEnIvbDQZl8uYW0tle92SaYtX9lI,744
@@ -16,13 +16,13 @@ qulab/scan/__init__.py,sha256=ZX4WsvqYxvJeHLgGSrtJoAnVU94gxY7EHKMxYooMERg,130
16
16
  qulab/scan/curd.py,sha256=thq_qfi3qng3Zx-1uhNG64IQhGCuum_LR4MOKnS8cDI,6896
17
17
  qulab/scan/expression.py,sha256=ngWrP1o9CuYJ1gq5YHaV7EfxKIKUX7Gz6KG80E6XThY,20070
18
18
  qulab/scan/models.py,sha256=5Jpo25WGMWs0GtLzYLsWO61G3-FFYx5BHhBr2b6rOTE,17681
19
- qulab/scan/optimize.py,sha256=jYceGazEabuwYqmZE8P6Nnq_KsLyUP0p-p88VbbJLhM,2559
19
+ qulab/scan/optimize.py,sha256=VT9TpuqDkG7FdJJkYy60r5Pfrmjvfu5i36Ru6XvIiTI,2561
20
20
  qulab/scan/query.py,sha256=-5uHMhXSyGovK1oy_uUbGVEbRFzaMBkP78ZMNfI3jD0,11809
21
21
  qulab/scan/record.py,sha256=yIHPANf6nuBXy8Igf-dMtGJ7wuFTLYlBaaAUc0AzwyU,21280
22
- qulab/scan/scan.py,sha256=hrCnoIROMPoYXEZnU9GTZUR-aX9qP58d40wlN3DTQCE,40602
23
- qulab/scan/server.py,sha256=_4YrOJcnqDTnxryZXE8lEKGzuT4LS-8q9bN6jrTEqUQ,19950
24
- qulab/scan/space.py,sha256=X5anTvw7X0XGN83y0o0C-zhvh6bDEU-kshGgo004pNE,6076
25
- qulab/scan/utils.py,sha256=zCV_Td8hBgb16Hv3XKo64KYDDpvBw2rQ83fxq1hvjG8,4586
22
+ qulab/scan/scan.py,sha256=iXvbnXLZvHa4v88MlYiZ_LYubEB7ZfbX7OiFTMhl_1o,39479
23
+ qulab/scan/server.py,sha256=Gh5DTacqkE4FD8BtynSuBdl7Ifwc52TMlGyXknVH4q8,19957
24
+ qulab/scan/space.py,sha256=OQLepiNNP5TNYMHXeVFT59lL5n4soPmnMoMy_o9EHt0,6696
25
+ qulab/scan/utils.py,sha256=SzJ_c4cLZJzERZr_CJO1_4juOxjfwCpU2K1mkc1PWGM,6124
26
26
  qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  qulab/storage/__main__.py,sha256=3emxxRry8BB0m8hUZvJ_oBqkPy7ksV7flHB_KEDXZuI,1692
28
28
  qulab/storage/base_dataset.py,sha256=4aKhqBNdZfdlm_z1Qy5dv0HrvgpvMdy8pbyfua8uE-4,11865
@@ -78,9 +78,9 @@ qulab/visualization/plot_layout.py,sha256=clNw9QjE_kVNpIIx2Ob4YhAz2fucPGMuzkoIrO
78
78
  qulab/visualization/plot_seq.py,sha256=lphYF4VhkEdc_wWr1kFBwrx2yujkyFPFaJ3pjr61awI,2693
79
79
  qulab/visualization/qdat.py,sha256=ZeevBYWkzbww4xZnsjHhw7wRorJCBzbG0iEu-XQB4EA,5735
80
80
  qulab/visualization/widgets.py,sha256=6KkiTyQ8J-ei70LbPQZAK35wjktY47w2IveOa682ftA,3180
81
- QuLab-2.3.4.dist-info/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
82
- QuLab-2.3.4.dist-info/METADATA,sha256=Noz4IplxqE9TBtcN2Qr38B1J0vtpEkCWsjAjvRMGF_I,3633
83
- QuLab-2.3.4.dist-info/WHEEL,sha256=UDBB_KFYXAT_a6Q3uGzMOBYEG2sfuzNdKs9Nu_rq9v4,114
84
- QuLab-2.3.4.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
85
- QuLab-2.3.4.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
86
- QuLab-2.3.4.dist-info/RECORD,,
81
+ QuLab-2.3.5.dist-info/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
82
+ QuLab-2.3.5.dist-info/METADATA,sha256=oI912BvgopGv3rP89guaGd6eXLIybHJZa6SrJdaD7As,3633
83
+ QuLab-2.3.5.dist-info/WHEEL,sha256=sTDvnRQNPfF56LQlCOFLDL34fLHcZLD6rjkP3qBFMlI,114
84
+ QuLab-2.3.5.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
85
+ QuLab-2.3.5.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
86
+ QuLab-2.3.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.0)
2
+ Generator: setuptools (71.0.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp311-cp311-macosx_10_9_universal2
5
5
 
Binary file
qulab/scan/optimize.py CHANGED
@@ -72,5 +72,5 @@ class NgOptimizer():
72
72
  if history:
73
73
  ret.x_iters = self._all_x
74
74
  ret.func_vals = self._all_y
75
- ret.fun = recommendation.value
75
+ # ret.fun = recommendation.value
76
76
  return ret
qulab/scan/scan.py CHANGED
@@ -6,9 +6,7 @@ import itertools
6
6
  import lzma
7
7
  import os
8
8
  import pickle
9
- import platform
10
9
  import re
11
- import subprocess
12
10
  import sys
13
11
  import uuid
14
12
  from concurrent.futures import ProcessPoolExecutor
@@ -26,7 +24,8 @@ from .optimize import NgOptimizer
26
24
  from .record import Record
27
25
  from .server import default_record_port
28
26
  from .space import Optimizer, OptimizeSpace, Space
29
- from .utils import async_zip, call_function, dump_dict, dump_globals
27
+ from .utils import (async_zip, call_function, dump_dict, dump_globals,
28
+ get_installed_packages, get_system_info, yapf_reformat)
30
29
 
31
30
  try:
32
31
  from tqdm.notebook import tqdm
@@ -58,57 +57,34 @@ else:
58
57
  default_executor = default_server
59
58
 
60
59
 
61
- def yapf_reformat(cell_text):
62
- try:
63
- import isort
64
- import yapf.yapflib.yapf_api
65
-
66
- fname = f"f{uuid.uuid1().hex}"
67
-
68
- def wrap(source):
69
- lines = [f"async def {fname}():"]
70
- for line in source.split('\n'):
71
- lines.append(" " + line)
72
- return '\n'.join(lines)
60
+ class Promise():
61
+ __slots__ = ['task', 'key', 'attr']
73
62
 
74
- def unwrap(source):
75
- lines = []
76
- for line in source.split('\n'):
77
- if line.startswith(f"async def {fname}():"):
78
- continue
79
- lines.append(line[4:])
80
- return '\n'.join(lines)
63
+ def __init__(self, task, key=None, attr=None):
64
+ self.task = task
65
+ self.key = key
66
+ self.attr = attr
81
67
 
82
- cell_text = re.sub('^%', '#%#', cell_text, flags=re.M)
83
- reformated_text = unwrap(
84
- yapf.yapflib.yapf_api.FormatCode(wrap(isort.code(cell_text)))[0])
85
- return re.sub('^#%#', '%', reformated_text, flags=re.M)
86
- except:
87
- return cell_text
68
+ def __await__(self):
88
69
 
70
+ async def _getitem(task, key):
71
+ return (await task)[key]
89
72
 
90
- def get_installed_packages():
91
- result = subprocess.run([sys.executable, '-m', 'pip', 'freeze'],
92
- stdout=subprocess.PIPE,
93
- text=True)
73
+ async def _getattr(task, attr):
74
+ return getattr(await task, attr)
94
75
 
95
- lines = result.stdout.split('\n')
96
- packages = []
97
- for line in lines:
98
- if line:
99
- packages.append(line)
100
- return packages
76
+ if self.key is not None:
77
+ return _getitem(self.task, self.key).__await__()
78
+ elif self.attr is not None:
79
+ return _getattr(self.task, self.attr).__await__()
80
+ else:
81
+ return self.task.__await__()
101
82
 
83
+ def __getitem__(self, key):
84
+ return Promise(self.task, key, None)
102
85
 
103
- def get_system_info():
104
- info = {
105
- 'OS': platform.uname()._asdict(),
106
- 'Python': sys.version,
107
- 'PythonExecutable': sys.executable,
108
- 'PythonPath': sys.path,
109
- 'packages': get_installed_packages()
110
- }
111
- return info
86
+ def __getattr__(self, attr):
87
+ return Promise(self.task, None, attr)
112
88
 
113
89
 
114
90
  def current_notebook():
@@ -170,39 +146,185 @@ def _get_depends(func: Callable):
170
146
  return args
171
147
 
172
148
 
173
- class Promise():
174
- __slots__ = ['task', 'key', 'attr']
149
+ def _run_function_in_process(buf):
150
+ func, args, kwds = dill.loads(buf)
151
+ return func(*args, **kwds)
175
152
 
176
- def __init__(self, task, key=None, attr=None):
177
- self.task = task
178
- self.key = key
179
- self.attr = attr
180
153
 
181
- def __await__(self):
154
+ async def update_variables(variables: dict[str, Any], updates: dict[str, Any],
155
+ setters: dict[str, Callable]):
156
+ coros = []
157
+ for name, value in updates.items():
158
+ if name in setters:
159
+ coro = setters[name](value)
160
+ if inspect.isawaitable(coro):
161
+ coros.append(coro)
162
+ variables[name] = value
163
+ if coros:
164
+ await asyncio.gather(*coros)
182
165
 
183
- async def _getitem(task, key):
184
- return (await task)[key]
185
166
 
186
- async def _getattr(task, attr):
187
- return getattr(await task, attr)
167
+ async def _iter_level(variables,
168
+ iters: list[tuple[str, Iterable | Expression | Callable
169
+ | OptimizeSpace]],
170
+ order: list[list[str]],
171
+ functions: dict[str, Callable | Expression],
172
+ optimizers: dict[str, Optimizer],
173
+ setters: dict[str, Callable] = {},
174
+ getters: dict[str, Callable] = {}):
175
+ iters_d = {}
176
+ env = Env()
177
+ env.variables = variables
178
+ opts = {}
188
179
 
189
- if self.key is not None:
190
- return _getitem(self.task, self.key).__await__()
191
- elif self.attr is not None:
192
- return _getattr(self.task, self.attr).__await__()
180
+ for name, iter in iters:
181
+ if isinstance(iter, OptimizeSpace):
182
+ if iter.optimizer.name not in opts:
183
+ opts[iter.optimizer.name] = iter.optimizer.create()
184
+ elif isinstance(iter, Expression):
185
+ iters_d[name] = iter.eval(env)
186
+ elif isinstance(iter, Space):
187
+ iters_d[name] = iter.toarray()
188
+ elif callable(iter):
189
+ iters_d[name] = await call_function(iter, variables)
193
190
  else:
194
- return self.task.__await__()
191
+ iters_d[name] = iter
195
192
 
196
- def __getitem__(self, key):
197
- return Promise(self.task, key, None)
193
+ maxiter = 0xffffffff
194
+ for name, opt in opts.items():
195
+ opt_cfg = optimizers[name]
196
+ maxiter = min(maxiter, opt_cfg.maxiter)
198
197
 
199
- def __getattr__(self, attr):
200
- return Promise(self.task, None, attr)
198
+ async for args in async_zip(*iters_d.values(), range(maxiter)):
199
+ await update_variables(variables, dict(zip(iters_d.keys(), args[:-1])),
200
+ setters)
201
+ for name, opt in opts.items():
202
+ args = opt.ask()
203
+ opt_cfg = optimizers[name]
204
+ await update_variables(variables, {
205
+ n: v
206
+ for n, v in zip(opt_cfg.dimensions.keys(), args)
207
+ }, setters)
208
+
209
+ await update_variables(
210
+ variables, await call_many_functions(order, functions, variables),
211
+ setters)
201
212
 
213
+ yield variables
202
214
 
203
- def _run_function_in_process(buf):
204
- func, args, kwds = dill.loads(buf)
205
- return func(*args, **kwds)
215
+ variables.update(await call_many_functions(order, getters, variables))
216
+
217
+ if opts:
218
+ for key in list(variables.keys()):
219
+ if key.startswith('*') or ',' in key:
220
+ await _unpack(key, variables)
221
+
222
+ for name, opt in opts.items():
223
+ opt_cfg = optimizers[name]
224
+ args = [variables[n] for n in opt_cfg.dimensions.keys()]
225
+
226
+ if name not in variables:
227
+ raise ValueError(f'{name} not in variables.')
228
+ fun = variables[name]
229
+ if inspect.isawaitable(fun):
230
+ fun = await fun
231
+ if opt_cfg.minimize:
232
+ opt.tell(args, fun)
233
+ else:
234
+ opt.tell(args, -fun)
235
+
236
+ if opts:
237
+ for name, opt in opts.items():
238
+ opt_cfg = optimizers[name]
239
+ result = opt.get_result()
240
+ await update_variables(
241
+ variables, {
242
+ name: value
243
+ for name, value in zip(opt_cfg.dimensions.keys(), result.x)
244
+ }, setters)
245
+
246
+ yield variables
247
+
248
+ variables.update(await call_many_functions(order, getters, variables))
249
+
250
+ for key in list(variables.keys()):
251
+ if key.startswith('*') or ',' in key:
252
+ await _unpack(key, variables)
253
+
254
+
255
+ async def call_many_functions(order: list[list[str]],
256
+ functions: dict[str, Callable],
257
+ variables: dict[str, Any]) -> dict[str, Any]:
258
+ ret = {}
259
+ for group in order:
260
+ waited = []
261
+ coros = []
262
+ for name in group:
263
+ if name in functions:
264
+ waited.append(name)
265
+ coros.append(call_function(functions[name], variables | ret))
266
+ if coros:
267
+ results = await asyncio.gather(*coros)
268
+ ret.update(dict(zip(waited, results)))
269
+ return ret
270
+
271
+
272
+ async def _unpack(key, variables):
273
+ x = variables[key]
274
+ if inspect.isawaitable(x):
275
+ x = await x
276
+ if key.startswith('**'):
277
+ assert isinstance(
278
+ x, dict), f"Should promise a dict for `**` symbol. {key}"
279
+ if "{key}" in key:
280
+ for k, v in x.items():
281
+ variables[key[2:].format(key=k)] = v
282
+ else:
283
+ variables.update(x)
284
+ elif key.startswith('*'):
285
+ assert isinstance(
286
+ x, (list, tuple,
287
+ np.ndarray)), f"Should promise a list for `*` symbol. {key}"
288
+ for i, v in enumerate(x):
289
+ k = key[1:].format(i=i)
290
+ variables[k] = v
291
+ elif ',' in key:
292
+ keys1, keys2 = [], []
293
+ args = None
294
+ for k in key.split(','):
295
+ if k.startswith('*'):
296
+ if args is None:
297
+ args = k
298
+ else:
299
+ raise ValueError(f'Only one `*` symbol is allowed. {key}')
300
+ elif args is None:
301
+ keys1.append(k)
302
+ else:
303
+ keys2.append(k)
304
+ assert isinstance(
305
+ x,
306
+ (list, tuple,
307
+ np.ndarray)), f"Should promise a list for multiple symbols. {key}"
308
+ if args is None:
309
+ assert len(keys1) == len(
310
+ x), f"Length of keys and values should be equal. {key}"
311
+ for k, v in zip(keys1, x):
312
+ variables[k] = v
313
+ else:
314
+ assert len(keys1) + len(keys2) <= len(
315
+ x), f"Too many values for unpacking. {key}"
316
+ for k, v in zip(keys1, x[:len(keys1)]):
317
+ variables[k] = v
318
+ end = -len(keys2) if keys2 else None
319
+ for i, v in enumerate(x[len(keys1):end]):
320
+ k = args[1:].format(i=i)
321
+ variables[k] = v
322
+ if keys2:
323
+ for k, v in zip(keys2, x[end:]):
324
+ variables[k] = v
325
+ else:
326
+ return
327
+ del variables[key]
206
328
 
207
329
 
208
330
  class Scan():
@@ -232,6 +354,7 @@ class Scan():
232
354
  self.id = task_uuid()
233
355
  self.record = None
234
356
  self.config = {} if config is None else copy.deepcopy(config)
357
+ self._raw_config_copy = copy.deepcopy(self.config)
235
358
  self.description = {
236
359
  'app': app,
237
360
  'tags': tags,
@@ -252,7 +375,7 @@ class Scan():
252
375
  'filters': {},
253
376
  'total': {},
254
377
  'database': database,
255
- 'hiden': ['self', 'config', r'^__.*', r'.*__$'],
378
+ 'hiden': ['self', 'config', r'^__.*', r'.*__$', r'^#.*'],
256
379
  'entry': {
257
380
  'system': get_system_info(),
258
381
  'env': {},
@@ -386,7 +509,7 @@ class Scan():
386
509
 
387
510
  if self.config:
388
511
  self.description['config'] = await create_config(
389
- self.config, self.description['database'], self._sock)
512
+ self._raw_config_copy, self.description['database'], self._sock)
390
513
  if current_notebook() is None:
391
514
  await create_notebook('untitle', self.description['database'],
392
515
  self._sock)
@@ -464,9 +587,9 @@ class Scan():
464
587
  if depends:
465
588
  self.add_depends(name, depends)
466
589
  s = ','.join(depends)
467
- self.description['functions'][f'_tmp_{name}'] = value
590
+ self.description['functions'][f'#{name}'] = value
468
591
  self.description['functions'][name] = eval(
469
- f"lambda self, {s}: self.description['functions']['_tmp_{name}']({s})"
592
+ f"lambda self, {s}: self.description['functions']['#{name}']({s})"
470
593
  )
471
594
  else:
472
595
  self.add_depends(name, _get_depends(value))
@@ -646,7 +769,7 @@ class Scan():
646
769
  await self._run()
647
770
  else:
648
771
  if self.config:
649
- self.description['config'] = copy.deepcopy(self.config)
772
+ self.description['config'] = self._raw_config_copy
650
773
  async with self._send_msg_and_update_bar() as background_tasks:
651
774
  self._background_tasks = background_tasks
652
775
  await self._run()
@@ -1040,173 +1163,4 @@ def assymbly(description):
1040
1163
  _make_axis(description)
1041
1164
 
1042
1165
  return description
1043
-
1044
-
1045
- async def update_variables(variables: dict[str, Any], updates: dict[str, Any],
1046
- setters: dict[str, Callable]):
1047
- coros = []
1048
- for name, value in updates.items():
1049
- if name in setters:
1050
- coro = setters[name](value)
1051
- if inspect.isawaitable(coro):
1052
- coros.append(coro)
1053
- variables[name] = value
1054
- if coros:
1055
- await asyncio.gather(*coros)
1056
-
1057
-
1058
- async def _iter_level(variables,
1059
- iters: list[tuple[str, Iterable | Expression | Callable
1060
- | OptimizeSpace]],
1061
- order: list[list[str]],
1062
- functions: dict[str, Callable | Expression],
1063
- optimizers: dict[str, Optimizer],
1064
- setters: dict[str, Callable] = {},
1065
- getters: dict[str, Callable] = {}):
1066
- iters_d = {}
1067
- env = Env()
1068
- env.variables = variables
1069
- opts = {}
1070
-
1071
- for name, iter in iters:
1072
- if isinstance(iter, OptimizeSpace):
1073
- if iter.optimizer.name not in opts:
1074
- opts[iter.optimizer.name] = iter.optimizer.create()
1075
- elif isinstance(iter, Expression):
1076
- iters_d[name] = iter.eval(env)
1077
- elif isinstance(iter, Space):
1078
- iters_d[name] = iter.toarray()
1079
- elif callable(iter):
1080
- iters_d[name] = await call_function(iter, variables)
1081
- else:
1082
- iters_d[name] = iter
1083
-
1084
- maxiter = 0xffffffff
1085
- for name, opt in opts.items():
1086
- opt_cfg = optimizers[name]
1087
- maxiter = min(maxiter, opt_cfg.maxiter)
1088
-
1089
- async for args in async_zip(*iters_d.values(), range(maxiter)):
1090
- await update_variables(variables, dict(zip(iters_d.keys(), args[:-1])),
1091
- setters)
1092
- for name, opt in opts.items():
1093
- args = opt.ask()
1094
- opt_cfg = optimizers[name]
1095
- await update_variables(variables, {
1096
- n: v
1097
- for n, v in zip(opt_cfg.dimensions.keys(), args)
1098
- }, setters)
1099
-
1100
- await update_variables(
1101
- variables, await call_many_functions(order, functions, variables),
1102
- setters)
1103
-
1104
- yield variables
1105
-
1106
- variables.update(await call_many_functions(order, getters, variables))
1107
-
1108
- if opts:
1109
- for key in list(variables.keys()):
1110
- if key.startswith('*') or ',' in key:
1111
- await _unpack(key, variables)
1112
-
1113
- for name, opt in opts.items():
1114
- opt_cfg = optimizers[name]
1115
- args = [variables[n] for n in opt_cfg.dimensions.keys()]
1116
-
1117
- if name not in variables:
1118
- raise ValueError(f'{name} not in variables.')
1119
- fun = variables[name]
1120
- if inspect.isawaitable(fun):
1121
- fun = await fun
1122
- if opt_cfg.minimize:
1123
- opt.tell(args, fun)
1124
- else:
1125
- opt.tell(args, -fun)
1126
-
1127
- for name, opt in opts.items():
1128
- opt_cfg = optimizers[name]
1129
- result = opt.get_result()
1130
- await update_variables(
1131
- variables, {
1132
- name: value
1133
- for name, value in zip(opt_cfg.dimensions.keys(), result.x)
1134
- }, setters)
1135
- variables[name] = result.fun
1136
- if opts:
1137
- yield variables
1138
-
1139
-
1140
- async def call_many_functions(order: list[list[str]],
1141
- functions: dict[str, Callable],
1142
- variables: dict[str, Any]) -> dict[str, Any]:
1143
- ret = {}
1144
- for group in order:
1145
- waited = []
1146
- coros = []
1147
- for name in group:
1148
- if name in functions:
1149
- waited.append(name)
1150
- coros.append(call_function(functions[name], variables | ret))
1151
- if coros:
1152
- results = await asyncio.gather(*coros)
1153
- ret.update(dict(zip(waited, results)))
1154
- return ret
1155
-
1156
-
1157
- async def _unpack(key, variables):
1158
- x = variables[key]
1159
- if inspect.isawaitable(x):
1160
- x = await x
1161
- if key.startswith('**'):
1162
- assert isinstance(
1163
- x, dict), f"Should promise a dict for `**` symbol. {key}"
1164
- if "{key}" in key:
1165
- for k, v in x.items():
1166
- variables[key[2:].format(key=k)] = v
1167
- else:
1168
- variables.update(x)
1169
- elif key.startswith('*'):
1170
- assert isinstance(
1171
- x, (list, tuple,
1172
- np.ndarray)), f"Should promise a list for `*` symbol. {key}"
1173
- for i, v in enumerate(x):
1174
- k = key[1:].format(i=i)
1175
- variables[k] = v
1176
- elif ',' in key:
1177
- keys1, keys2 = [], []
1178
- args = None
1179
- for k in key.split(','):
1180
- if k.startswith('*'):
1181
- if args is None:
1182
- args = k
1183
- else:
1184
- raise ValueError(f'Only one `*` symbol is allowed. {key}')
1185
- elif args is None:
1186
- keys1.append(k)
1187
- else:
1188
- keys2.append(k)
1189
- assert isinstance(
1190
- x,
1191
- (list, tuple,
1192
- np.ndarray)), f"Should promise a list for multiple symbols. {key}"
1193
- if args is None:
1194
- assert len(keys1) == len(
1195
- x), f"Length of keys and values should be equal. {key}"
1196
- for k, v in zip(keys1, x):
1197
- variables[k] = v
1198
- else:
1199
- assert len(keys1) + len(keys2) <= len(
1200
- x), f"Too many values for unpacking. {key}"
1201
- for k, v in zip(keys1, x[:len(keys1)]):
1202
- variables[k] = v
1203
- end = -len(keys2) if keys2 else None
1204
- for i, v in enumerate(x[len(keys1):end]):
1205
- k = args[1:].format(i=i)
1206
- variables[k] = v
1207
- if keys2:
1208
- for k, v in zip(keys2, x[end:]):
1209
- variables[k] = v
1210
- else:
1211
- return
1212
- del variables[key]
1166
+ return description
qulab/scan/server.py CHANGED
@@ -73,14 +73,15 @@ def clear_cache():
73
73
  return
74
74
 
75
75
  logger.debug(f"clear_cache record_cache: {len(record_cache)}")
76
- for k, (t, _) in zip(sorted(record_cache.items(), key=lambda x: x[1][0]),
77
- range(len(record_cache) - CACHE_SIZE)):
76
+ for (k, (t, r),
77
+ i) in zip(sorted(record_cache.items(), key=lambda x: x[1][0]),
78
+ range(len(record_cache) - CACHE_SIZE)):
78
79
  del record_cache[k]
79
80
 
80
81
  logger.debug(f"clear_cache buffer_list_cache: {len(buffer_list_cache)}")
81
- for k, (t,
82
- _) in zip(sorted(buffer_list_cache.items(), key=lambda x: x[1][0]),
83
- range(len(buffer_list_cache) - CACHE_SIZE)):
82
+ for (k, (t, r),
83
+ i) in zip(sorted(buffer_list_cache.items(), key=lambda x: x[1][0]),
84
+ range(len(buffer_list_cache) - CACHE_SIZE)):
84
85
  del buffer_list_cache[k]
85
86
  logger.debug(f"clear_cache done.")
86
87
 
qulab/scan/space.py CHANGED
@@ -25,12 +25,27 @@ class Space():
25
25
 
26
26
  @classmethod
27
27
  def fromarray(cls, space):
28
- if isinstance(space, Space):
28
+ if isinstance(space, (Space, range, enumerate, tuple)):
29
29
  return space
30
- if isinstance(space, (list, tuple)):
31
- array = np.array(space)
30
+ if isinstance(space, list):
31
+ if isinstance(space[0], int):
32
+ try:
33
+ if all(i == j for i, j in zip(
34
+ space,
35
+ range(space[0], space[-1] + 1, space[1] -
36
+ space[0]))):
37
+ return range(space[0], space[-1] + 1,
38
+ space[1] - space[0])
39
+ except:
40
+ return space
41
+ elif isinstance(space[0], (float, complex, np.ndarray)):
42
+ array = np.array(space)
43
+ else:
44
+ return space
32
45
  elif isinstance(space, np.ndarray):
33
46
  array = space
47
+ else:
48
+ return space
34
49
  try:
35
50
  a = np.linspace(array[0], array[-1], len(array), dtype=array.dtype)
36
51
  if np.allclose(a, array):
qulab/scan/utils.py CHANGED
@@ -1,6 +1,11 @@
1
1
  import ast
2
2
  import asyncio
3
3
  import inspect
4
+ import platform
5
+ import re
6
+ import subprocess
7
+ import sys
8
+ import uuid
4
9
  import warnings
5
10
  from typing import Any, Callable
6
11
 
@@ -169,3 +174,56 @@ async def call_function(func: Callable | Expression, variables: dict[str,
169
174
  if inspect.isawaitable(ret):
170
175
  ret = await ret
171
176
  return ret
177
+
178
+
179
+ def yapf_reformat(cell_text):
180
+ try:
181
+ import isort
182
+ import yapf.yapflib.yapf_api
183
+
184
+ fname = f"f{uuid.uuid1().hex}"
185
+
186
+ def wrap(source):
187
+ lines = [f"async def {fname}():"]
188
+ for line in source.split('\n'):
189
+ lines.append(" " + line)
190
+ return '\n'.join(lines)
191
+
192
+ def unwrap(source):
193
+ lines = []
194
+ for line in source.split('\n'):
195
+ if line.startswith(f"async def {fname}():"):
196
+ continue
197
+ lines.append(line[4:])
198
+ return '\n'.join(lines)
199
+
200
+ cell_text = re.sub('^%', '#%#', cell_text, flags=re.M)
201
+ reformated_text = unwrap(
202
+ yapf.yapflib.yapf_api.FormatCode(wrap(isort.code(cell_text)))[0])
203
+ return re.sub('^#%#', '%', reformated_text, flags=re.M)
204
+ except:
205
+ return cell_text
206
+
207
+
208
+ def get_installed_packages():
209
+ result = subprocess.run([sys.executable, '-m', 'pip', 'freeze'],
210
+ stdout=subprocess.PIPE,
211
+ text=True)
212
+
213
+ lines = result.stdout.split('\n')
214
+ packages = []
215
+ for line in lines:
216
+ if line:
217
+ packages.append(line)
218
+ return packages
219
+
220
+
221
+ def get_system_info():
222
+ info = {
223
+ 'OS': platform.uname()._asdict(),
224
+ 'Python': sys.version,
225
+ 'PythonExecutable': sys.executable,
226
+ 'PythonPath': sys.path,
227
+ 'packages': get_installed_packages()
228
+ }
229
+ return info
qulab/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.3.4"
1
+ __version__ = "2.3.5"
File without changes