QuLab 2.0.2__cp311-cp311-macosx_10_9_universal2.whl → 2.0.4__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.
- {QuLab-2.0.2.dist-info → QuLab-2.0.4.dist-info}/METADATA +2 -1
- {QuLab-2.0.2.dist-info → QuLab-2.0.4.dist-info}/RECORD +14 -13
- qulab/__main__.py +2 -0
- qulab/fun.cpython-311-darwin.so +0 -0
- qulab/scan/query_record.py +0 -1
- qulab/scan/recorder.py +109 -48
- qulab/scan/scan.py +411 -308
- qulab/scan/server.py +106 -0
- qulab/scan/utils.py +80 -34
- qulab/version.py +1 -1
- {QuLab-2.0.2.dist-info → QuLab-2.0.4.dist-info}/LICENSE +0 -0
- {QuLab-2.0.2.dist-info → QuLab-2.0.4.dist-info}/WHEEL +0 -0
- {QuLab-2.0.2.dist-info → QuLab-2.0.4.dist-info}/entry_points.txt +0 -0
- {QuLab-2.0.2.dist-info → QuLab-2.0.4.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: QuLab
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
4
4
|
Summary: contral instruments and manage data
|
|
5
5
|
Author-email: feihoo87 <feihoo87@gmail.com>
|
|
6
6
|
Maintainer-email: feihoo87 <feihoo87@gmail.com>
|
|
@@ -32,6 +32,7 @@ Requires-Dist: ipython >=7.4.0
|
|
|
32
32
|
Requires-Dist: ipywidgets >=7.4.2
|
|
33
33
|
Requires-Dist: loguru >=0.7.2
|
|
34
34
|
Requires-Dist: matplotlib >=3.7.2
|
|
35
|
+
Requires-Dist: nevergrad >=1.0.2
|
|
35
36
|
Requires-Dist: numpy >=1.13.3
|
|
36
37
|
Requires-Dist: ply >=3.11
|
|
37
38
|
Requires-Dist: pyzmq >=25.1.0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
qulab/__init__.py,sha256=8zLGg-DfQhnDl2Ky0n-zXpN-8e-g7iR0AcaI4l4Vvpk,32
|
|
2
|
-
qulab/__main__.py,sha256=
|
|
3
|
-
qulab/fun.cpython-311-darwin.so,sha256=
|
|
4
|
-
qulab/version.py,sha256=
|
|
2
|
+
qulab/__main__.py,sha256=eupSsrNVfnTFRpjgrY_knPvZIs0-Dk577LaN7qB15hI,487
|
|
3
|
+
qulab/fun.cpython-311-darwin.so,sha256=Ts0LNKfAATzvuQVYqCs5zehDzRYyYEXNHT824hdGaGA,159616
|
|
4
|
+
qulab/version.py,sha256=vd1KwOWsA9E1XbsJopSk63EogXGb_qCx8XG7lzXJd8Y,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
|
|
@@ -17,10 +17,11 @@ qulab/scan/curd.py,sha256=ntpK62ArZiF2mrDDewcw227VMR1E_8no0yLJSrgdgng,4518
|
|
|
17
17
|
qulab/scan/expression.py,sha256=-aTYbjFQNI1mwOcoSBztqhKfGJpu_n4a1QnWro_xnTU,15694
|
|
18
18
|
qulab/scan/models.py,sha256=S8Q9hC8nOzxyoNB10EYg-miDKqoNMnjyAECjD-TuORw,17117
|
|
19
19
|
qulab/scan/optimize.py,sha256=vErjRTCtn2MwMF5Xyhs1P4gHF2IFHv_EqxsUvH_4y7k,2287
|
|
20
|
-
qulab/scan/query_record.py,sha256=
|
|
21
|
-
qulab/scan/recorder.py,sha256=
|
|
22
|
-
qulab/scan/scan.py,sha256=
|
|
23
|
-
qulab/scan/
|
|
20
|
+
qulab/scan/query_record.py,sha256=BVkNgv3yfbMXX_Kguq18fvowKOBmBiiTvUwj_CqpiF4,11493
|
|
21
|
+
qulab/scan/recorder.py,sha256=3-9iqYIg11Ne3vJ2Q8uk9Hp5x6elKBLlfh5EwslkgBA,17611
|
|
22
|
+
qulab/scan/scan.py,sha256=a07dEFJE2JIVRFuySIuINYYdKzIyjbTcnO-i9oaC6_8,25598
|
|
23
|
+
qulab/scan/server.py,sha256=W8z3vr0cqSSKWzIG6_b0d-lpBpDXGpHSwN6VJuv3w9U,2844
|
|
24
|
+
qulab/scan/utils.py,sha256=n5yquKlz2QYMzciPgD9vkpBJVgzVzOqAlfvB4Qu6oOk,2551
|
|
24
25
|
qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
26
|
qulab/storage/__main__.py,sha256=3emxxRry8BB0m8hUZvJ_oBqkPy7ksV7flHB_KEDXZuI,1692
|
|
26
27
|
qulab/storage/base_dataset.py,sha256=4aKhqBNdZfdlm_z1Qy5dv0HrvgpvMdy8pbyfua8uE-4,11865
|
|
@@ -76,9 +77,9 @@ qulab/visualization/plot_layout.py,sha256=clNw9QjE_kVNpIIx2Ob4YhAz2fucPGMuzkoIrO
|
|
|
76
77
|
qulab/visualization/plot_seq.py,sha256=lphYF4VhkEdc_wWr1kFBwrx2yujkyFPFaJ3pjr61awI,2693
|
|
77
78
|
qulab/visualization/qdat.py,sha256=ZeevBYWkzbww4xZnsjHhw7wRorJCBzbG0iEu-XQB4EA,5735
|
|
78
79
|
qulab/visualization/widgets.py,sha256=6KkiTyQ8J-ei70LbPQZAK35wjktY47w2IveOa682ftA,3180
|
|
79
|
-
QuLab-2.0.
|
|
80
|
-
QuLab-2.0.
|
|
81
|
-
QuLab-2.0.
|
|
82
|
-
QuLab-2.0.
|
|
83
|
-
QuLab-2.0.
|
|
84
|
-
QuLab-2.0.
|
|
80
|
+
QuLab-2.0.4.dist-info/LICENSE,sha256=PRzIKxZtpQcH7whTG6Egvzl1A0BvnSf30tmR2X2KrpA,1065
|
|
81
|
+
QuLab-2.0.4.dist-info/METADATA,sha256=ITxP9PCKiTxbultRyfTgA92HFzX5jch7pWrHZSVyCgE,3510
|
|
82
|
+
QuLab-2.0.4.dist-info/WHEEL,sha256=eupBwbXGAhwNAPJSvj5BiShZwdZO8jnQ5yHfv-9aUGw,115
|
|
83
|
+
QuLab-2.0.4.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
|
|
84
|
+
QuLab-2.0.4.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
|
|
85
|
+
QuLab-2.0.4.dist-info/RECORD,,
|
qulab/__main__.py
CHANGED
|
@@ -2,6 +2,7 @@ import click
|
|
|
2
2
|
|
|
3
3
|
from .monitor.__main__ import main as monitor
|
|
4
4
|
from .scan.recorder import record
|
|
5
|
+
from .scan.server import server
|
|
5
6
|
from .sys.net.cli import dht
|
|
6
7
|
from .visualization.__main__ import plot
|
|
7
8
|
|
|
@@ -21,6 +22,7 @@ main.add_command(monitor)
|
|
|
21
22
|
main.add_command(plot)
|
|
22
23
|
main.add_command(dht)
|
|
23
24
|
main.add_command(record)
|
|
25
|
+
main.add_command(server)
|
|
24
26
|
|
|
25
27
|
if __name__ == '__main__':
|
|
26
28
|
main()
|
qulab/fun.cpython-311-darwin.so
CHANGED
|
Binary file
|
qulab/scan/query_record.py
CHANGED
qulab/scan/recorder.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import os
|
|
2
3
|
import pickle
|
|
3
4
|
import sys
|
|
4
5
|
import time
|
|
5
6
|
import uuid
|
|
7
|
+
from collections import defaultdict
|
|
6
8
|
from pathlib import Path
|
|
9
|
+
from threading import Lock
|
|
7
10
|
|
|
8
11
|
import click
|
|
9
12
|
import dill
|
|
@@ -18,7 +21,16 @@ from .models import Record as RecordInDB
|
|
|
18
21
|
from .models import Session, create_engine, create_tables, sessionmaker, utcnow
|
|
19
22
|
|
|
20
23
|
_notgiven = object()
|
|
21
|
-
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
default_record_port = int(os.getenv('QULAB_RECORD_PORT', 6789))
|
|
27
|
+
except:
|
|
28
|
+
default_record_port = 6789
|
|
29
|
+
|
|
30
|
+
if os.getenv('QULAB_RECORD_PATH'):
|
|
31
|
+
datapath = Path(os.getenv('QULAB_RECORD_PATH'))
|
|
32
|
+
else:
|
|
33
|
+
datapath = Path.home() / 'qulab' / 'data'
|
|
22
34
|
datapath.mkdir(parents=True, exist_ok=True)
|
|
23
35
|
|
|
24
36
|
record_cache = {}
|
|
@@ -41,24 +53,49 @@ class BufferList():
|
|
|
41
53
|
self.rd = ()
|
|
42
54
|
self.pos_file = pos_file
|
|
43
55
|
self.value_file = value_file
|
|
56
|
+
self._lock = Lock()
|
|
57
|
+
|
|
58
|
+
def __getstate__(self):
|
|
59
|
+
return {
|
|
60
|
+
'pos_file': self.pos_file,
|
|
61
|
+
'value_file': self.value_file,
|
|
62
|
+
'_pos': self._pos,
|
|
63
|
+
'_value': self._value,
|
|
64
|
+
'lu': self.lu,
|
|
65
|
+
'rd': self.rd
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
def __setstate__(self, state):
|
|
69
|
+
self.pos_file = state['pos_file']
|
|
70
|
+
self.value_file = state['value_file']
|
|
71
|
+
self._pos = state['_pos']
|
|
72
|
+
self._value = state['_value']
|
|
73
|
+
self.lu = state['lu']
|
|
74
|
+
self.rd = state['rd']
|
|
75
|
+
self._lock = Lock()
|
|
44
76
|
|
|
45
77
|
@property
|
|
46
78
|
def shape(self):
|
|
47
79
|
return tuple([i - j for i, j in zip(self.rd, self.lu)])
|
|
48
80
|
|
|
49
81
|
def flush(self):
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
with self._lock:
|
|
83
|
+
if self.pos_file is not None:
|
|
84
|
+
with open(self.pos_file, 'ab') as f:
|
|
85
|
+
for pos in self._pos:
|
|
86
|
+
dill.dump(pos, f)
|
|
87
|
+
self._pos.clear()
|
|
88
|
+
if self.value_file is not None:
|
|
89
|
+
with open(self.value_file, 'ab') as f:
|
|
90
|
+
for value in self._value:
|
|
91
|
+
dill.dump(value, f)
|
|
92
|
+
self._value.clear()
|
|
93
|
+
|
|
94
|
+
def append(self, pos, value, dims=None):
|
|
95
|
+
if dims is not None:
|
|
96
|
+
if any([p != 0 for i, p in enumerate(pos) if i not in dims]):
|
|
97
|
+
return
|
|
98
|
+
pos = tuple([pos[i] for i in dims])
|
|
62
99
|
self.lu = tuple([min(i, j) for i, j in zip(pos, self.lu)])
|
|
63
100
|
self.rd = tuple([max(i + 1, j) for i, j in zip(pos, self.rd)])
|
|
64
101
|
self._pos.append(pos)
|
|
@@ -68,25 +105,27 @@ class BufferList():
|
|
|
68
105
|
|
|
69
106
|
def value(self):
|
|
70
107
|
v = []
|
|
71
|
-
if self.value_file is not None:
|
|
72
|
-
with
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
108
|
+
if self.value_file is not None and self.value_file.exists():
|
|
109
|
+
with self._lock:
|
|
110
|
+
with open(self.value_file, 'rb') as f:
|
|
111
|
+
while True:
|
|
112
|
+
try:
|
|
113
|
+
v.append(dill.load(f))
|
|
114
|
+
except EOFError:
|
|
115
|
+
break
|
|
78
116
|
v.extend(self._value)
|
|
79
117
|
return v
|
|
80
118
|
|
|
81
119
|
def pos(self):
|
|
82
120
|
p = []
|
|
83
|
-
if self.pos_file is not None:
|
|
84
|
-
with
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
121
|
+
if self.pos_file is not None and self.pos_file.exists():
|
|
122
|
+
with self._lock:
|
|
123
|
+
with open(self.pos_file, 'rb') as f:
|
|
124
|
+
while True:
|
|
125
|
+
try:
|
|
126
|
+
p.append(dill.load(f))
|
|
127
|
+
except EOFError:
|
|
128
|
+
break
|
|
90
129
|
p.extend(self._pos)
|
|
91
130
|
return p
|
|
92
131
|
|
|
@@ -114,21 +153,32 @@ class Record():
|
|
|
114
153
|
self._file = None
|
|
115
154
|
self.independent_variables = {}
|
|
116
155
|
self.constants = {}
|
|
117
|
-
|
|
118
|
-
for level, group in self.description['order'].items():
|
|
119
|
-
for names in group:
|
|
120
|
-
for name in names:
|
|
121
|
-
self._levels[name] = level
|
|
156
|
+
self.dims = {}
|
|
122
157
|
|
|
123
158
|
for name, value in self.description['consts'].items():
|
|
124
159
|
if name not in self._items:
|
|
125
160
|
self._items[name] = value
|
|
126
161
|
self.constants[name] = value
|
|
162
|
+
self.dims[name] = ()
|
|
127
163
|
for level, range_list in self.description['loops'].items():
|
|
128
164
|
for name, iterable in range_list:
|
|
129
165
|
if isinstance(iterable, (np.ndarray, list, tuple, range)):
|
|
130
166
|
self._items[name] = iterable
|
|
131
|
-
self.independent_variables[name] =
|
|
167
|
+
self.independent_variables[name] = iterable
|
|
168
|
+
self.dims[name] = (level, )
|
|
169
|
+
|
|
170
|
+
for level, group in self.description['order'].items():
|
|
171
|
+
for names in group:
|
|
172
|
+
for name in names:
|
|
173
|
+
self._levels[name] = level
|
|
174
|
+
if name not in self.dims:
|
|
175
|
+
if name not in self.description['dependents']:
|
|
176
|
+
self.dims[name] = (level, )
|
|
177
|
+
else:
|
|
178
|
+
d = set()
|
|
179
|
+
for n in self.description['dependents'][name]:
|
|
180
|
+
d.update(self.dims[n])
|
|
181
|
+
self.dims[name] = tuple(sorted(d))
|
|
132
182
|
|
|
133
183
|
if self.is_local_record():
|
|
134
184
|
self.database = Path(self.database)
|
|
@@ -203,6 +253,7 @@ class Record():
|
|
|
203
253
|
for key in set(variables.keys()) - self._last_vars:
|
|
204
254
|
if key not in self._levels:
|
|
205
255
|
self._levels[key] = level
|
|
256
|
+
self.dims[key] = tuple(range(level + 1))
|
|
206
257
|
|
|
207
258
|
self._last_vars = set(variables.keys())
|
|
208
259
|
self._keys.update(variables.keys())
|
|
@@ -237,9 +288,9 @@ class Record():
|
|
|
237
288
|
self._items[key] = BufferList()
|
|
238
289
|
self._items[key].lu = pos
|
|
239
290
|
self._items[key].rd = tuple([i + 1 for i in pos])
|
|
240
|
-
self._items[key].append(pos, value)
|
|
291
|
+
self._items[key].append(pos, value, self.dims[key])
|
|
241
292
|
elif isinstance(self._items[key], BufferList):
|
|
242
|
-
self._items[key].append(pos, value)
|
|
293
|
+
self._items[key].append(pos, value, self.dims[key])
|
|
243
294
|
elif self._levels[key] == -1 and key not in self._items:
|
|
244
295
|
self._items[key] = value
|
|
245
296
|
|
|
@@ -283,7 +334,7 @@ def flush_cache():
|
|
|
283
334
|
r.flush()
|
|
284
335
|
|
|
285
336
|
|
|
286
|
-
def get_record(session, id, datapath):
|
|
337
|
+
def get_record(session: Session, id: int, datapath: Path) -> Record:
|
|
287
338
|
if id not in record_cache:
|
|
288
339
|
record_in_db = session.get(RecordInDB, id)
|
|
289
340
|
record_in_db.atime = utcnow()
|
|
@@ -297,7 +348,7 @@ def get_record(session, id, datapath):
|
|
|
297
348
|
return record
|
|
298
349
|
|
|
299
350
|
|
|
300
|
-
def
|
|
351
|
+
def record_create(session: Session, description: dict, datapath: Path) -> int:
|
|
301
352
|
record = Record(None, datapath, description)
|
|
302
353
|
record_in_db = RecordInDB()
|
|
303
354
|
if 'app' in description:
|
|
@@ -317,6 +368,20 @@ def create_record(session, description, datapath):
|
|
|
317
368
|
raise
|
|
318
369
|
|
|
319
370
|
|
|
371
|
+
def record_append(session: Session, record_id: int, level: int, step: int,
|
|
372
|
+
position: int, variables: dict, datapath: Path):
|
|
373
|
+
record = get_record(session, record_id, datapath)
|
|
374
|
+
record.append(level, step, position, variables)
|
|
375
|
+
try:
|
|
376
|
+
record_in_db = session.get(RecordInDB, record_id)
|
|
377
|
+
record_in_db.mtime = utcnow()
|
|
378
|
+
record_in_db.atime = utcnow()
|
|
379
|
+
session.commit()
|
|
380
|
+
except:
|
|
381
|
+
session.rollback()
|
|
382
|
+
raise
|
|
383
|
+
|
|
384
|
+
|
|
320
385
|
@logger.catch
|
|
321
386
|
async def handle(session: Session, request: Request, datapath: Path):
|
|
322
387
|
|
|
@@ -327,16 +392,10 @@ async def handle(session: Session, request: Request, datapath: Path):
|
|
|
327
392
|
await reply(request, 'pong')
|
|
328
393
|
case 'record_create':
|
|
329
394
|
description = dill.loads(msg['description'])
|
|
330
|
-
await reply(request,
|
|
395
|
+
await reply(request, record_create(session, description, datapath))
|
|
331
396
|
case 'record_append':
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
msg['variables'])
|
|
335
|
-
if msg['level'] < 0:
|
|
336
|
-
record_in_db = session.get(RecordInDB, msg['record_id'])
|
|
337
|
-
record_in_db.mtime = utcnow()
|
|
338
|
-
record_in_db.atime = utcnow()
|
|
339
|
-
session.commit()
|
|
397
|
+
record_append(session, msg['record_id'], msg['level'], msg['step'],
|
|
398
|
+
msg['position'], msg['variables'], datapath)
|
|
340
399
|
case 'record_description':
|
|
341
400
|
record = get_record(session, msg['record_id'], datapath)
|
|
342
401
|
await reply(request, dill.dumps(record.description))
|
|
@@ -365,7 +424,7 @@ async def handle(session: Session, request: Request, datapath: Path):
|
|
|
365
424
|
case 'record_replace_tags':
|
|
366
425
|
update_tags(session, msg['record_id'], msg['tags'], False)
|
|
367
426
|
case _:
|
|
368
|
-
logger.error(f
|
|
427
|
+
logger.error(f"Unknown method: {msg['method']}")
|
|
369
428
|
|
|
370
429
|
|
|
371
430
|
async def _handle(session: Session, request: Request, datapath: Path):
|
|
@@ -431,7 +490,9 @@ async def main(port, datapath, url, timeout=1, buffer=1024, interval=60):
|
|
|
431
490
|
|
|
432
491
|
|
|
433
492
|
@click.command()
|
|
434
|
-
@click.option('--port',
|
|
493
|
+
@click.option('--port',
|
|
494
|
+
default=os.getenv('QULAB_RECORD_PORT', 6789),
|
|
495
|
+
help='Port of the server.')
|
|
435
496
|
@click.option('--datapath', default=datapath, help='Path of the data.')
|
|
436
497
|
@click.option('--url', default=None, help='URL of the database.')
|
|
437
498
|
@click.option('--timeout', default=1, help='Timeout of ping.')
|