QuLab 2.0.2__cp312-cp312-win_amd64.whl → 2.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: QuLab
3
- Version: 2.0.2
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=OlYQe7go_eFLKR0uU6D1kIpTKvbpx3WRJFFdoYoFjdE,456
3
- qulab/fun.cp312-win_amd64.pyd,sha256=Ei2QoHBZ2Tz1_gOMrkqRa2SqgwlInpoicV3PDKjUXZM,31744
4
- qulab/version.py,sha256=xARS6PXiulA1Bog5UZUM6hqQfydeRzKLyWtOyUBL-Ss,21
2
+ qulab/__main__.py,sha256=XN2wrhlmEkTIPq_ZeSaO8rWXfYgD2Czkm9DVFVoCw_U,515
3
+ qulab/fun.cp312-win_amd64.pyd,sha256=jenFpbWSaien3YWNHNttD3jn-8mdPvcL6GdWDtRfacU,31744
4
+ qulab/version.py,sha256=vd1KwOWsA9E1XbsJopSk63EogXGb_qCx8XG7lzXJd8Y,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
@@ -17,10 +17,11 @@ 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_record.py,sha256=gRUBjablvjWhDM-nZEunMVxQbUeaFF8qG7sROy9kIbs,11882
21
- qulab/scan/recorder.py,sha256=EgS7NzARFqZeWUJp188iFQWr-_fa7Akm0Op-tvGqh7A,15849
22
- qulab/scan/scan.py,sha256=1hfnV4TpGPw-EtBzoMorqAjulDG6WrjX3y5lUBbI7YE,23731
23
- qulab/scan/utils.py,sha256=DHGC-RcGbY7RmMEDvazPkC_nFqlj_N8Cr9spm_CGfuE,1061
20
+ qulab/scan/query_record.py,sha256=rpw4U3NjLzlv9QMwKdCvEUGHjzPF8u1UpodfLW8aoTY,11853
21
+ qulab/scan/recorder.py,sha256=MuXnRA9_p8MvigT4GnBpJDv3sk4faJIW0R0dQdgaW-Q,18119
22
+ qulab/scan/scan.py,sha256=-jHWb5PEhnFZOnEshTOrCtkJxfyuCq6JFtIdw8k8VYM,26402
23
+ qulab/scan/server.py,sha256=zDZfG6bOB3EUubfByQMq0BSQ9C6IV_Av0tDinzgpGjQ,2950
24
+ qulab/scan/utils.py,sha256=XM-eKL5Xkm0hihhGS7Kq4g654Ye7n7TcU_f95gxtXq8,2634
24
25
  qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
26
  qulab/storage/__main__.py,sha256=6-EjN0waX1yfcMPJXqpIr9UlrIEsSCFApm5G-ZeaPMQ,1742
26
27
  qulab/storage/base_dataset.py,sha256=28y3-OZrqJ52p5sbirEpUgjb7hqwLLpd38KU9DCkD24,12217
@@ -76,9 +77,9 @@ qulab/visualization/plot_layout.py,sha256=yAnMONOms7_szCdng-8wPpUMPis5UnbaNNzV4K
76
77
  qulab/visualization/plot_seq.py,sha256=h9D0Yl_yO64IwlvBgzMu9EBKr9gg6y8QE55gu2PfTns,2783
77
78
  qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
78
79
  qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
79
- QuLab-2.0.2.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
80
- QuLab-2.0.2.dist-info/METADATA,sha256=4OR_9ZAdwX58Fsqa5EVFdtZWRfVn2YiHHlG01SZrmoU,3575
81
- QuLab-2.0.2.dist-info/WHEEL,sha256=fZWyj_84lK0cA-ZNCsdwhbJl0OTrpWkxInEn424qrSs,102
82
- QuLab-2.0.2.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
83
- QuLab-2.0.2.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
84
- QuLab-2.0.2.dist-info/RECORD,,
80
+ QuLab-2.0.4.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
81
+ QuLab-2.0.4.dist-info/METADATA,sha256=3yPITY1eWKzHwPjuMVMAgmRSgPrtst0lLJg0a0xUHdM,3609
82
+ QuLab-2.0.4.dist-info/WHEEL,sha256=fZWyj_84lK0cA-ZNCsdwhbJl0OTrpWkxInEn424qrSs,102
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()
Binary file
@@ -20,7 +20,6 @@ def get_record(id, database='tcp://127.0.0.1:6789'):
20
20
  'record_id': id
21
21
  })
22
22
  d = dill.loads(socket.recv_pyobj())
23
- print(d.keys())
24
23
  return Record(id, database, d)
25
24
  else:
26
25
  from .models import Record as RecordInDB
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
- datapath = Path.home() / 'qulab' / 'data'
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
- if self.pos_file is not None:
51
- with open(self.pos_file, 'ab') as f:
52
- for pos in self._pos:
53
- dill.dump(pos, f)
54
- self._pos.clear()
55
- if self.value_file is not None:
56
- with open(self.value_file, 'ab') as f:
57
- for value in self._value:
58
- dill.dump(value, f)
59
- self._value.clear()
60
-
61
- def append(self, pos, value):
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 open(self.value_file, 'rb') as f:
73
- while True:
74
- try:
75
- v.append(dill.load(f))
76
- except EOFError:
77
- break
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 open(self.pos_file, 'rb') as f:
85
- while True:
86
- try:
87
- p.append(dill.load(f))
88
- except EOFError:
89
- break
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] = (level, iterable)
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 create_record(session, description, datapath):
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, create_record(session, description, datapath))
395
+ await reply(request, record_create(session, description, datapath))
331
396
  case 'record_append':
332
- record = get_record(session, msg['record_id'], datapath)
333
- record.append(msg['level'], msg['step'], msg['position'],
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'Unknown method: {msg["method"]}')
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', default=6789, help='Port of the server.')
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.')