QuLab 2.1.1__cp312-cp312-win_amd64.whl → 2.1.2__cp312-cp312-win_amd64.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.
- {QuLab-2.1.1.dist-info → QuLab-2.1.2.dist-info}/METADATA +1 -1
- {QuLab-2.1.1.dist-info → QuLab-2.1.2.dist-info}/RECORD +14 -14
- qulab/__init__.py +3 -1
- qulab/fun.cp312-win_amd64.pyd +0 -0
- qulab/scan/__init__.py +1 -1
- qulab/scan/query.py +8 -8
- qulab/scan/record.py +50 -3
- qulab/scan/recorder.py +15 -9
- qulab/scan/scan.py +29 -17
- qulab/version.py +1 -1
- {QuLab-2.1.1.dist-info → QuLab-2.1.2.dist-info}/LICENSE +0 -0
- {QuLab-2.1.1.dist-info → QuLab-2.1.2.dist-info}/WHEEL +0 -0
- {QuLab-2.1.1.dist-info → QuLab-2.1.2.dist-info}/entry_points.txt +0 -0
- {QuLab-2.1.1.dist-info → QuLab-2.1.2.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
qulab/__init__.py,sha256=
|
|
1
|
+
qulab/__init__.py,sha256=vkFybY8YSsQilYdThPRD83-btPAR41sy_WCXiM-6mME,141
|
|
2
2
|
qulab/__main__.py,sha256=XN2wrhlmEkTIPq_ZeSaO8rWXfYgD2Czkm9DVFVoCw_U,515
|
|
3
|
-
qulab/fun.cp312-win_amd64.pyd,sha256=
|
|
4
|
-
qulab/version.py,sha256=
|
|
3
|
+
qulab/fun.cp312-win_amd64.pyd,sha256=0LNFjYCaI6p4FrH8oo4ZpVsJkfTHpthA5cxToVSplUU,31744
|
|
4
|
+
qulab/version.py,sha256=FM98Inv2t7vU9Dvod2ccoaPCOtP2LV-rqmhbddOPf9U,21
|
|
5
5
|
qulab/monitor/__init__.py,sha256=xEVDkJF8issrsDeLqQmDsvtRmrf-UiViFcGTWuzdlFU,43
|
|
6
6
|
qulab/monitor/__main__.py,sha256=k2H1H5Zf9LLXTDLISJkbikLH-z0f1e5i5i6wXXYPOrE,105
|
|
7
7
|
qulab/monitor/config.py,sha256=y_5StMkdrbZO1ziyKBrvIkB7Jclp9RCPK1QbsOhCxnY,785
|
|
@@ -12,15 +12,15 @@ qulab/monitor/monitor.py,sha256=2AP-hhg1T6-38mieDm5_ONTIXnXYlIrSyOiAOxDKy0I,2398
|
|
|
12
12
|
qulab/monitor/ploter.py,sha256=dg7W28XTwEbBxHVtdPkFV135OQgoQwTi-NJCZQF-HYU,3724
|
|
13
13
|
qulab/monitor/qt_compat.py,sha256=Eq7zlA4_XstB92NhtAqebtWU_Btw4lcwFO30YxZ-TPE,804
|
|
14
14
|
qulab/monitor/toolbar.py,sha256=HxqG6ywKFyQJM2Q1s7SnhuzjbyeROczAZKwxztD1WJ8,8213
|
|
15
|
-
qulab/scan/__init__.py,sha256=
|
|
15
|
+
qulab/scan/__init__.py,sha256=RR_0NQcr8Mi3vpWdypydbijQ1rXA0D3DEidQ7xjNslM,133
|
|
16
16
|
qulab/scan/curd.py,sha256=bEXtcmiaoAv5APToXx5O5tvmqAhE2_LkvdwLsI_8D5M,4662
|
|
17
17
|
qulab/scan/expression.py,sha256=vwUM9E0OFQal4bljlUtLR3NJu4zGRyuWYrdyZSs3QTU,16199
|
|
18
18
|
qulab/scan/models.py,sha256=TkiVHF_fUZzYHs4MsCTRh391thpf4Ozd3R_LAU0Gxkg,17657
|
|
19
19
|
qulab/scan/optimize.py,sha256=MlT4y422CnP961IR384UKryyZh8riNvrPSd2z_MXLEg,2356
|
|
20
|
-
qulab/scan/query.py,sha256=
|
|
21
|
-
qulab/scan/record.py,sha256=
|
|
22
|
-
qulab/scan/recorder.py,sha256=
|
|
23
|
-
qulab/scan/scan.py,sha256=
|
|
20
|
+
qulab/scan/query.py,sha256=vT1OevzKImqG40plmiPbyvzHVTBzAETo_OxpJHa0UmU,11821
|
|
21
|
+
qulab/scan/record.py,sha256=s1bY4F_2FxIeN9ER-FILslCqc7i0JRAFv9pk0InQmcg,17477
|
|
22
|
+
qulab/scan/recorder.py,sha256=qlUlxksL-beolTU3EupBlKDBGViicrq3ZoxjH6ZVHrY,8964
|
|
23
|
+
qulab/scan/scan.py,sha256=AJ2GxdgTRL165UkNT27qZwJp_ag5j_hevNAY1-fUh7U,30607
|
|
24
24
|
qulab/scan/server.py,sha256=Q7lX9ms37WbnzuLhrv3YbNrusTsxQUNT9slFqon5VL0,2872
|
|
25
25
|
qulab/scan/space.py,sha256=OPceWIIrb2KDDQaSxD3Vkzkf9NDSuqWuQoDnKiWqtAo,5381
|
|
26
26
|
qulab/scan/utils.py,sha256=30qnYvyFyctwcWxOCUpCNxXgGysA7xdIDzYbjwxGUzA,3744
|
|
@@ -79,9 +79,9 @@ qulab/visualization/plot_layout.py,sha256=yAnMONOms7_szCdng-8wPpUMPis5UnbaNNzV4K
|
|
|
79
79
|
qulab/visualization/plot_seq.py,sha256=h9D0Yl_yO64IwlvBgzMu9EBKr9gg6y8QE55gu2PfTns,2783
|
|
80
80
|
qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
|
|
81
81
|
qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
|
|
82
|
-
QuLab-2.1.
|
|
83
|
-
QuLab-2.1.
|
|
84
|
-
QuLab-2.1.
|
|
85
|
-
QuLab-2.1.
|
|
86
|
-
QuLab-2.1.
|
|
87
|
-
QuLab-2.1.
|
|
82
|
+
QuLab-2.1.2.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
|
|
83
|
+
QuLab-2.1.2.dist-info/METADATA,sha256=BawKmH85rDyYCZUqZ1sEDQKzkUnpZX4D-Iy8iiY7AhQ,3609
|
|
84
|
+
QuLab-2.1.2.dist-info/WHEEL,sha256=fZWyj_84lK0cA-ZNCsdwhbJl0OTrpWkxInEn424qrSs,102
|
|
85
|
+
QuLab-2.1.2.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
|
|
86
|
+
QuLab-2.1.2.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
|
|
87
|
+
QuLab-2.1.2.dist-info/RECORD,,
|
qulab/__init__.py
CHANGED
qulab/fun.cp312-win_amd64.pyd
CHANGED
|
Binary file
|
qulab/scan/__init__.py
CHANGED
qulab/scan/query.py
CHANGED
|
@@ -6,10 +6,13 @@ import dill
|
|
|
6
6
|
import ipywidgets as widgets
|
|
7
7
|
import zmq
|
|
8
8
|
from IPython.display import display
|
|
9
|
+
from sqlalchemy import create_engine
|
|
10
|
+
from sqlalchemy.orm import sessionmaker
|
|
9
11
|
|
|
10
12
|
from qulab.sys.rpc.zmq_socket import ZMQContextManager
|
|
11
13
|
|
|
12
14
|
from .record import Record
|
|
15
|
+
from .recorder import get_local_record
|
|
13
16
|
from .scan import default_server
|
|
14
17
|
|
|
15
18
|
|
|
@@ -26,18 +29,15 @@ def get_record(id, database=default_server) -> Record:
|
|
|
26
29
|
d._file = None
|
|
27
30
|
return d
|
|
28
31
|
else:
|
|
29
|
-
from .models import Record as RecordInDB
|
|
30
|
-
from .models import create_engine, sessionmaker
|
|
31
|
-
|
|
32
32
|
db_file = Path(database) / 'data.db'
|
|
33
33
|
engine = create_engine(f'sqlite:///{db_file}')
|
|
34
34
|
Session = sessionmaker(bind=engine)
|
|
35
35
|
with Session() as session:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
return get_local_record(session, id, database)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def load_record(file):
|
|
40
|
+
return Record.load(file)
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def _format_tag(tag):
|
qulab/scan/record.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import sys
|
|
3
3
|
import uuid
|
|
4
|
+
import zipfile
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from threading import Lock
|
|
6
7
|
from types import EllipsisType
|
|
@@ -13,7 +14,7 @@ from qulab.sys.rpc.zmq_socket import ZMQContextManager
|
|
|
13
14
|
|
|
14
15
|
from .space import OptimizeSpace, Space
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
_not_given = object()
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
def random_path(base):
|
|
@@ -120,6 +121,18 @@ class BufferList():
|
|
|
120
121
|
yield pos, value
|
|
121
122
|
except EOFError:
|
|
122
123
|
break
|
|
124
|
+
elif isinstance(
|
|
125
|
+
self.file, tuple) and len(self.file) == 2 and isinstance(
|
|
126
|
+
self.file[0], str) and self.file[0].endswith('.zip'):
|
|
127
|
+
f, name = self.file
|
|
128
|
+
with zipfile.ZipFile(f, 'r') as z:
|
|
129
|
+
with z.open(name, 'r') as f:
|
|
130
|
+
while True:
|
|
131
|
+
try:
|
|
132
|
+
pos, value = dill.load(f)
|
|
133
|
+
yield pos, value
|
|
134
|
+
except EOFError:
|
|
135
|
+
break
|
|
123
136
|
|
|
124
137
|
def iter(self):
|
|
125
138
|
if self._data_id is None:
|
|
@@ -327,7 +340,7 @@ class Record():
|
|
|
327
340
|
ret = ret.toarray()
|
|
328
341
|
return ret
|
|
329
342
|
|
|
330
|
-
def get(self, key, default=
|
|
343
|
+
def get(self, key, default=_not_given, buffer_to_array=False, slice=None):
|
|
331
344
|
if self.is_remote_record():
|
|
332
345
|
with ZMQContextManager(zmq.DEALER,
|
|
333
346
|
connect=self.database) as socket:
|
|
@@ -355,7 +368,7 @@ class Record():
|
|
|
355
368
|
else:
|
|
356
369
|
return ret
|
|
357
370
|
else:
|
|
358
|
-
if default is
|
|
371
|
+
if default is _not_given:
|
|
359
372
|
d = self._items.get(key)
|
|
360
373
|
else:
|
|
361
374
|
d = self._items.get(key, default)
|
|
@@ -437,6 +450,40 @@ class Record():
|
|
|
437
450
|
with open(self._file, 'wb') as f:
|
|
438
451
|
dill.dump(self, f)
|
|
439
452
|
|
|
453
|
+
def export(self, file):
|
|
454
|
+
with zipfile.ZipFile(file,
|
|
455
|
+
'w',
|
|
456
|
+
compression=zipfile.ZIP_DEFLATED,
|
|
457
|
+
compresslevel=9) as z:
|
|
458
|
+
items = {}
|
|
459
|
+
for key in self.keys():
|
|
460
|
+
value = self.get(key)
|
|
461
|
+
if isinstance(value, BufferList):
|
|
462
|
+
v = BufferList()
|
|
463
|
+
v.lu = value.lu
|
|
464
|
+
v.rd = value.rd
|
|
465
|
+
v.inner_shape = value.inner_shape
|
|
466
|
+
items[key] = v
|
|
467
|
+
with z.open(f'{key}.buf', 'w') as f:
|
|
468
|
+
for pos, data in value.iter():
|
|
469
|
+
dill.dump((pos, data), f)
|
|
470
|
+
else:
|
|
471
|
+
items[key] = value
|
|
472
|
+
with z.open('record.pkl', 'w') as f:
|
|
473
|
+
dill.dump((self.description, items), f)
|
|
474
|
+
|
|
475
|
+
@classmethod
|
|
476
|
+
def load(cls, file: str):
|
|
477
|
+
with zipfile.ZipFile(file, 'r') as z:
|
|
478
|
+
with z.open('record.pkl', 'r') as f:
|
|
479
|
+
description, items = dill.load(f)
|
|
480
|
+
record = cls(None, None, description)
|
|
481
|
+
for key, value in items.items():
|
|
482
|
+
if isinstance(value, BufferList):
|
|
483
|
+
value.file = file, f'{key}.buf'
|
|
484
|
+
record._items[key] = value
|
|
485
|
+
return record
|
|
486
|
+
|
|
440
487
|
def __repr__(self):
|
|
441
488
|
return f"<Record: id={self.id} app={self.description['app']}, keys={self.keys()}>"
|
|
442
489
|
|
qulab/scan/recorder.py
CHANGED
|
@@ -28,6 +28,7 @@ else:
|
|
|
28
28
|
datapath.mkdir(parents=True, exist_ok=True)
|
|
29
29
|
|
|
30
30
|
record_cache = {}
|
|
31
|
+
CACHE_SIZE = 1024
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
class Request():
|
|
@@ -45,11 +46,11 @@ async def reply(req, resp):
|
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
def clear_cache():
|
|
48
|
-
if len(record_cache) <
|
|
49
|
+
if len(record_cache) < CACHE_SIZE:
|
|
49
50
|
return
|
|
50
51
|
|
|
51
52
|
for k, (t, _) in zip(sorted(record_cache.items(), key=lambda x: x[1][0]),
|
|
52
|
-
range(len(record_cache) -
|
|
53
|
+
range(len(record_cache) - CACHE_SIZE)):
|
|
53
54
|
del record_cache[k]
|
|
54
55
|
|
|
55
56
|
|
|
@@ -58,15 +59,20 @@ def flush_cache():
|
|
|
58
59
|
r.flush()
|
|
59
60
|
|
|
60
61
|
|
|
62
|
+
def get_local_record(session: Session, id: int, datapath: Path) -> Record:
|
|
63
|
+
record_in_db = session.get(RecordInDB, id)
|
|
64
|
+
record_in_db.atime = utcnow()
|
|
65
|
+
path = datapath / 'objects' / record_in_db.file
|
|
66
|
+
with open(path, 'rb') as f:
|
|
67
|
+
record = dill.load(f)
|
|
68
|
+
record.database = datapath
|
|
69
|
+
record._file = path
|
|
70
|
+
return record
|
|
71
|
+
|
|
72
|
+
|
|
61
73
|
def get_record(session: Session, id: int, datapath: Path) -> Record:
|
|
62
74
|
if id not in record_cache:
|
|
63
|
-
|
|
64
|
-
record_in_db.atime = utcnow()
|
|
65
|
-
path = datapath / 'objects' / record_in_db.file
|
|
66
|
-
with open(path, 'rb') as f:
|
|
67
|
-
record = dill.load(f)
|
|
68
|
-
record.database = datapath
|
|
69
|
-
record._file = path
|
|
75
|
+
record = get_local_record(session, id, datapath)
|
|
70
76
|
else:
|
|
71
77
|
record = record_cache[id][1]
|
|
72
78
|
clear_cache()
|
qulab/scan/scan.py
CHANGED
|
@@ -46,6 +46,10 @@ if os.getenv('QULAB_SERVER'):
|
|
|
46
46
|
default_server = os.getenv('QULAB_SERVER')
|
|
47
47
|
else:
|
|
48
48
|
default_server = f'tcp://127.0.0.1:{default_record_port}'
|
|
49
|
+
if os.getenv('QULAB_EXECUTOR'):
|
|
50
|
+
default_executor = os.getenv('QULAB_EXECUTOR')
|
|
51
|
+
else:
|
|
52
|
+
default_executor = default_server
|
|
49
53
|
|
|
50
54
|
|
|
51
55
|
def task_uuid():
|
|
@@ -136,6 +140,7 @@ class Scan():
|
|
|
136
140
|
'app': app,
|
|
137
141
|
'tags': tags,
|
|
138
142
|
'loops': {},
|
|
143
|
+
'intrinsic_loops': {},
|
|
139
144
|
'consts': {},
|
|
140
145
|
'functions': {},
|
|
141
146
|
'getters': {},
|
|
@@ -287,10 +292,10 @@ class Scan():
|
|
|
287
292
|
else:
|
|
288
293
|
return Symbol(name)
|
|
289
294
|
|
|
290
|
-
def
|
|
295
|
+
def _add_search_space(self, name: str, level: int, space):
|
|
291
296
|
if level not in self.description['loops']:
|
|
292
297
|
self.description['loops'][level] = []
|
|
293
|
-
self.description['loops'][level].append((name,
|
|
298
|
+
self.description['loops'][level].append((name, space))
|
|
294
299
|
|
|
295
300
|
def add_depends(self, name: str, depends: list[str]):
|
|
296
301
|
if isinstance(depends, str):
|
|
@@ -299,7 +304,7 @@ class Scan():
|
|
|
299
304
|
self.description['dependents'][name] = set()
|
|
300
305
|
self.description['dependents'][name].update(depends)
|
|
301
306
|
|
|
302
|
-
def add_filter(self, func: Callable, level: int):
|
|
307
|
+
def add_filter(self, func: Callable, level: int = -1):
|
|
303
308
|
"""
|
|
304
309
|
Add a filter function to the scan.
|
|
305
310
|
|
|
@@ -345,26 +350,33 @@ class Scan():
|
|
|
345
350
|
|
|
346
351
|
def search(self,
|
|
347
352
|
name: str,
|
|
348
|
-
|
|
353
|
+
space: Iterable | Expression | Callable | OptimizeSpace,
|
|
349
354
|
level: int | None = None,
|
|
350
|
-
setter: Callable | None = None
|
|
355
|
+
setter: Callable | None = None,
|
|
356
|
+
intrinsic: bool = False):
|
|
351
357
|
if level is not None:
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
self.
|
|
358
|
+
if not intrinsic:
|
|
359
|
+
assert level >= 0, 'level must be greater than or equal to 0.'
|
|
360
|
+
if intrinsic:
|
|
361
|
+
assert isinstance(space, (np.ndarray, list, tuple, range, Space)), \
|
|
362
|
+
'space must be an instance of np.ndarray, list, tuple, range or Space.'
|
|
363
|
+
self.description['intrinsic_loops'][name] = level
|
|
364
|
+
self.set(name, space)
|
|
365
|
+
elif isinstance(space, OptimizeSpace):
|
|
366
|
+
space.name = name
|
|
367
|
+
space.optimizer.dimensions[name] = space.space
|
|
368
|
+
self._add_search_space(name, space.optimizer.level, space)
|
|
369
|
+
self.add_depends(space.optimizer.name, [name])
|
|
358
370
|
else:
|
|
359
371
|
if level is None:
|
|
360
372
|
raise ValueError('level must be provided.')
|
|
361
373
|
try:
|
|
362
|
-
|
|
374
|
+
space = Space.fromarray(space)
|
|
363
375
|
except:
|
|
364
376
|
pass
|
|
365
|
-
self.
|
|
366
|
-
if isinstance(
|
|
367
|
-
self.add_depends(name,
|
|
377
|
+
self._add_search_space(name, level, space)
|
|
378
|
+
if isinstance(space, Expression) or callable(space):
|
|
379
|
+
self.add_depends(name, space.symbols())
|
|
368
380
|
if setter:
|
|
369
381
|
self.description['setters'][name] = setter
|
|
370
382
|
|
|
@@ -500,7 +512,7 @@ class Scan():
|
|
|
500
512
|
import asyncio
|
|
501
513
|
self._main_task = asyncio.create_task(self.run())
|
|
502
514
|
|
|
503
|
-
async def submit(self, server=
|
|
515
|
+
async def submit(self, server=default_executor):
|
|
504
516
|
assymbly(self.description)
|
|
505
517
|
async with ZMQContextManager(zmq.DEALER, connect=server) as socket:
|
|
506
518
|
await socket.send_pyobj({
|
|
@@ -740,7 +752,7 @@ def assymbly(description):
|
|
|
740
752
|
keys -= set(ready)
|
|
741
753
|
|
|
742
754
|
axis = {}
|
|
743
|
-
independent_variables = set()
|
|
755
|
+
independent_variables = set(description['intrinsic_loops'].keys())
|
|
744
756
|
|
|
745
757
|
for name in description['consts']:
|
|
746
758
|
axis[name] = ()
|
qulab/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.1.
|
|
1
|
+
__version__ = "2.1.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|