QuLab 2.1.4__tar.gz → 2.2.3__tar.gz

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.
Files changed (95) hide show
  1. {qulab-2.1.4 → qulab-2.2.3}/PKG-INFO +1 -1
  2. {qulab-2.1.4 → qulab-2.2.3}/QuLab.egg-info/PKG-INFO +1 -1
  3. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/query.py +3 -1
  4. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/record.py +25 -0
  5. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/scan.py +34 -13
  6. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/server.py +22 -8
  7. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/space.py +6 -6
  8. qulab-2.2.3/qulab/version.py +1 -0
  9. qulab-2.1.4/qulab/version.py +0 -1
  10. {qulab-2.1.4 → qulab-2.2.3}/LICENSE +0 -0
  11. {qulab-2.1.4 → qulab-2.2.3}/MANIFEST.in +0 -0
  12. {qulab-2.1.4 → qulab-2.2.3}/QuLab.egg-info/SOURCES.txt +0 -0
  13. {qulab-2.1.4 → qulab-2.2.3}/QuLab.egg-info/dependency_links.txt +0 -0
  14. {qulab-2.1.4 → qulab-2.2.3}/QuLab.egg-info/entry_points.txt +0 -0
  15. {qulab-2.1.4 → qulab-2.2.3}/QuLab.egg-info/requires.txt +0 -0
  16. {qulab-2.1.4 → qulab-2.2.3}/QuLab.egg-info/top_level.txt +0 -0
  17. {qulab-2.1.4 → qulab-2.2.3}/README.md +0 -0
  18. {qulab-2.1.4 → qulab-2.2.3}/pyproject.toml +0 -0
  19. {qulab-2.1.4 → qulab-2.2.3}/qulab/__init__.py +0 -0
  20. {qulab-2.1.4 → qulab-2.2.3}/qulab/__main__.py +0 -0
  21. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/__init__.py +0 -0
  22. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/__main__.py +0 -0
  23. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/config.py +0 -0
  24. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/dataset.py +0 -0
  25. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/event_queue.py +0 -0
  26. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/mainwindow.py +0 -0
  27. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/monitor.py +0 -0
  28. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/ploter.py +0 -0
  29. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/qt_compat.py +0 -0
  30. {qulab-2.1.4 → qulab-2.2.3}/qulab/monitor/toolbar.py +0 -0
  31. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/__init__.py +0 -0
  32. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/curd.py +0 -0
  33. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/expression.py +0 -0
  34. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/models.py +0 -0
  35. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/optimize.py +0 -0
  36. {qulab-2.1.4 → qulab-2.2.3}/qulab/scan/utils.py +0 -0
  37. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/__init__.py +0 -0
  38. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/__main__.py +0 -0
  39. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/backend/__init__.py +0 -0
  40. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/backend/redis.py +0 -0
  41. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/base_dataset.py +0 -0
  42. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/chunk.py +0 -0
  43. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/dataset.py +0 -0
  44. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/file.py +0 -0
  45. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/__init__.py +0 -0
  46. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/base.py +0 -0
  47. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/config.py +0 -0
  48. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/file.py +0 -0
  49. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/ipy.py +0 -0
  50. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/models.py +0 -0
  51. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/record.py +0 -0
  52. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/report.py +0 -0
  53. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/models/tag.py +0 -0
  54. {qulab-2.1.4 → qulab-2.2.3}/qulab/storage/storage.py +0 -0
  55. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/__init__.py +0 -0
  56. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/chat.py +0 -0
  57. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/device/__init__.py +0 -0
  58. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/device/basedevice.py +0 -0
  59. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/device/loader.py +0 -0
  60. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/device/utils.py +0 -0
  61. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/drivers/FakeInstrument.py +0 -0
  62. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/drivers/__init__.py +0 -0
  63. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/ipy_events.py +0 -0
  64. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/__init__.py +0 -0
  65. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/bencoder.py +0 -0
  66. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/cli.py +0 -0
  67. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/dhcp.py +0 -0
  68. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/dhcpd.py +0 -0
  69. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/kad.py +0 -0
  70. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/kcp.py +0 -0
  71. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/net/nginx.py +0 -0
  72. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/progress.py +0 -0
  73. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/__init__.py +0 -0
  74. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/client.py +0 -0
  75. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/exceptions.py +0 -0
  76. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/msgpack.py +0 -0
  77. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/msgpack.pyi +0 -0
  78. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/rpc.py +0 -0
  79. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/serialize.py +0 -0
  80. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/server.py +0 -0
  81. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/socket.py +0 -0
  82. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/utils.py +0 -0
  83. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/worker.py +0 -0
  84. {qulab-2.1.4 → qulab-2.2.3}/qulab/sys/rpc/zmq_socket.py +0 -0
  85. {qulab-2.1.4 → qulab-2.2.3}/qulab/visualization/__init__.py +0 -0
  86. {qulab-2.1.4 → qulab-2.2.3}/qulab/visualization/__main__.py +0 -0
  87. {qulab-2.1.4 → qulab-2.2.3}/qulab/visualization/_autoplot.py +0 -0
  88. {qulab-2.1.4 → qulab-2.2.3}/qulab/visualization/plot_layout.py +0 -0
  89. {qulab-2.1.4 → qulab-2.2.3}/qulab/visualization/plot_seq.py +0 -0
  90. {qulab-2.1.4 → qulab-2.2.3}/qulab/visualization/qdat.py +0 -0
  91. {qulab-2.1.4 → qulab-2.2.3}/qulab/visualization/widgets.py +0 -0
  92. {qulab-2.1.4 → qulab-2.2.3}/setup.cfg +0 -0
  93. {qulab-2.1.4 → qulab-2.2.3}/setup.py +0 -0
  94. {qulab-2.1.4 → qulab-2.2.3}/src/qulab.h +0 -0
  95. {qulab-2.1.4 → qulab-2.2.3}/tests/test_scan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: QuLab
3
- Version: 2.1.4
3
+ Version: 2.2.3
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: QuLab
3
- Version: 2.1.4
3
+ Version: 2.2.3
4
4
  Summary: contral instruments and manage data
5
5
  Author-email: feihoo87 <feihoo87@gmail.com>
6
6
  Maintainer-email: feihoo87 <feihoo87@gmail.com>
@@ -12,8 +12,8 @@ from sqlalchemy.orm import sessionmaker
12
12
  from qulab.sys.rpc.zmq_socket import ZMQContextManager
13
13
 
14
14
  from .record import Record
15
- from .server import get_local_record
16
15
  from .scan import default_server
16
+ from .server import get_local_record
17
17
 
18
18
 
19
19
  def get_record(id, database=default_server) -> Record:
@@ -24,6 +24,8 @@ def get_record(id, database=default_server) -> Record:
24
24
  'record_id': id
25
25
  })
26
26
  d = dill.loads(socket.recv_pyobj())
27
+ if isinstance(d, None):
28
+ raise ValueError(f'No record with id {id}')
27
29
  d.id = id
28
30
  d.database = database
29
31
  d._file = None
@@ -1,4 +1,6 @@
1
1
  import itertools
2
+ import lzma
3
+ import pickle
2
4
  import sys
3
5
  import uuid
4
6
  import zipfile
@@ -12,6 +14,7 @@ import zmq
12
14
 
13
15
  from qulab.sys.rpc.zmq_socket import ZMQContextManager
14
16
 
17
+ from .curd import get_config
15
18
  from .space import OptimizeSpace, Space
16
19
 
17
20
  _not_given = object()
@@ -326,6 +329,28 @@ class Record():
326
329
  def axis(self):
327
330
  return self.description.get('axis', {})
328
331
 
332
+ def config(self, cls=dict, session=None, datapath=None):
333
+ config_id = self.description.get('config', None)
334
+ if config_id is None:
335
+ return None
336
+ if isinstance(config_id, dict):
337
+ return cls(config_id)
338
+ if self.is_remote_record():
339
+ with ZMQContextManager(zmq.DEALER,
340
+ connect=self.database) as socket:
341
+ socket.send_pyobj({
342
+ 'method': 'config_get',
343
+ 'config_id': config_id
344
+ })
345
+ buf = socket.recv_pyobj()
346
+ return cls(pickle.loads(lzma.decompress(buf)))
347
+ else:
348
+ assert session is not None, "session is required for local record"
349
+ assert datapath is not None, "datapath is required for local record"
350
+ config = get_config(session, config_id, base=datapath / 'objects')
351
+ session.commit()
352
+ return cls(config)
353
+
329
354
  def is_local_record(self):
330
355
  return not self.is_cache_record() and not self.is_remote_record()
331
356
 
@@ -145,17 +145,6 @@ async def create_config(config: dict, database=default_server, socket=None):
145
145
  return await socket.recv_pyobj()
146
146
 
147
147
 
148
- async def get_config(config_id: int, database=default_server, socket=None):
149
- async with ZMQContextManager(zmq.DEALER, connect=database,
150
- socket=socket) as socket:
151
- await socket.send_pyobj({
152
- 'method': 'config_get',
153
- 'config_id': config_id
154
- })
155
- buf = await socket.recv_pyobj()
156
- return pickle.loads(lzma.decompress(buf))
157
-
158
-
159
148
  def task_uuid():
160
149
  return uuid.uuid3(__process_uuid, str(next(__task_counter)))
161
150
 
@@ -332,7 +321,9 @@ class Scan():
332
321
  async def _emit(self, current_level, step, position, variables: dict[str,
333
322
  Any]):
334
323
  for key, value in list(variables.items()):
335
- if inspect.isawaitable(value) and not self.hiden(key):
324
+ if key.startswith('*'):
325
+ await _unpack(key, variables)
326
+ elif inspect.isawaitable(value) and not self.hiden(key):
336
327
  variables[key] = await value
337
328
  if self._sock is not None:
338
329
  await self._sock.send_pyobj({
@@ -362,7 +353,8 @@ class Scan():
362
353
  self._hide_pattern_re = re.compile('|'.join(self.description['hiden']))
363
354
 
364
355
  def hiden(self, name: str) -> bool:
365
- return bool(self._hide_pattern_re.match(name))
356
+ return bool(
357
+ self._hide_pattern_re.match(name)) and not name.startswith('*')
366
358
 
367
359
  async def _filter(self, variables: dict[str, Any], level: int = 0):
368
360
  try:
@@ -971,9 +963,15 @@ async def _iter_level(variables,
971
963
 
972
964
  variables.update(await call_many_functions(order, getters, variables))
973
965
 
966
+ if opts:
967
+ for key in list(variables.keys()):
968
+ if key.startswith('*'):
969
+ await _unpack(key, variables)
970
+
974
971
  for name, opt in opts.items():
975
972
  opt_cfg = optimizers[name]
976
973
  args = [variables[n] for n in opt_cfg.dimensions.keys()]
974
+
977
975
  if name not in variables:
978
976
  raise ValueError(f'{name} not in variables.')
979
977
  fun = variables[name]
@@ -1012,3 +1010,26 @@ async def call_many_functions(order: list[list[str]],
1012
1010
  results = await asyncio.gather(*coros)
1013
1011
  ret.update(dict(zip(waited, results)))
1014
1012
  return ret
1013
+
1014
+
1015
+ async def _unpack(key, variables):
1016
+ x = variables[key]
1017
+ if inspect.isawaitable(x):
1018
+ x = await x
1019
+ if key.startswith('**'):
1020
+ assert isinstance(x, dict), f"Should promise a dict for `**` symbol."
1021
+ if "{key}" in key:
1022
+ for k, v in x.items():
1023
+ variables[key[2:].format(key=k)] = v
1024
+ else:
1025
+ variables.update(x)
1026
+ elif key.startswith('*'):
1027
+ assert isinstance(
1028
+ x, (list, tuple,
1029
+ np.ndarray)), f"Should promise a list for `*` symbol."
1030
+ for i, v in enumerate(x):
1031
+ k = key[1:].format(i=i)
1032
+ variables[k] = v
1033
+ else:
1034
+ return
1035
+ del variables[key]
@@ -65,6 +65,8 @@ def flush_cache():
65
65
 
66
66
  def get_local_record(session: Session, id: int, datapath: Path) -> Record:
67
67
  record_in_db = session.get(RecordInDB, id)
68
+ if record_in_db is None:
69
+ return None
68
70
  record_in_db.atime = utcnow()
69
71
 
70
72
  if record_in_db.file.endswith('.zip'):
@@ -220,21 +222,33 @@ async def handle(session: Session, request: Request, datapath: Path):
220
222
  await reply(request, config.id)
221
223
  case 'submit':
222
224
  from .scan import Scan
225
+ finished = [(id, queried) for id, (task, queried) in pool.items()
226
+ if not isinstance(task, int) and task.finished()]
227
+ for id, queried in finished:
228
+ if not queried:
229
+ pool[id] = [pool[id].record.id, False]
230
+ else:
231
+ pool.pop(id)
223
232
  description = dill.loads(msg['description'])
224
233
  task = Scan()
225
234
  task.description = description
226
235
  task.start()
227
- pool[task.id] = task
236
+ pool[task.id] = [task, False]
228
237
  await reply(request, task.id)
229
238
  case 'get_record_id':
230
- task = pool.get(msg['id'])
231
- for _ in range(10):
232
- if task.record:
233
- await reply(request, task.record.id)
234
- break
235
- await asyncio.sleep(1)
239
+ task, queried = pool.get(msg['id'])
240
+ if isinstance(task, int):
241
+ await reply(request, task)
242
+ pool.pop(msg['id'])
236
243
  else:
237
- await reply(request, None)
244
+ for _ in range(10):
245
+ if task.record:
246
+ await reply(request, task.record.id)
247
+ pool[msg['id']] = [task, True]
248
+ break
249
+ await asyncio.sleep(1)
250
+ else:
251
+ await reply(request, None)
238
252
  case _:
239
253
  logger.error(f"Unknown method: {msg['method']}")
240
254
 
@@ -23,11 +23,11 @@ class Space():
23
23
  return len(self.toarray())
24
24
 
25
25
  @classmethod
26
- def fromarray(cls, array):
27
- if isinstance(array, Space):
28
- return array
29
- if isinstance(array, (list, tuple)):
30
- array = np.array(array)
26
+ def fromarray(cls, space):
27
+ if isinstance(space, Space):
28
+ return space
29
+ if isinstance(space, (list, tuple)):
30
+ array = np.array(space)
31
31
  try:
32
32
  a = np.linspace(array[0], array[-1], len(array), dtype=array.dtype)
33
33
  if np.allclose(a, array):
@@ -81,7 +81,7 @@ class Space():
81
81
  dtype=array.dtype)
82
82
  except:
83
83
  pass
84
- return array
84
+ return space
85
85
 
86
86
  def toarray(self):
87
87
  return getattr(np, self.function)(*self.args, **self.kwds)
@@ -0,0 +1 @@
1
+ __version__ = "2.2.3"
@@ -1 +0,0 @@
1
- __version__ = "2.1.4"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes