QuLab 2.0.1__cp311-cp311-win_amd64.whl → 2.0.3__cp311-cp311-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.1
3
+ Version: 2.0.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>
@@ -30,10 +30,14 @@ Requires-Dist: dill >=0.3.6
30
30
  Requires-Dist: GitPython >=3.1.14
31
31
  Requires-Dist: ipython >=7.4.0
32
32
  Requires-Dist: ipywidgets >=7.4.2
33
+ Requires-Dist: loguru >=0.7.2
33
34
  Requires-Dist: matplotlib >=3.7.2
35
+ Requires-Dist: nevergrad >=1.0.2
34
36
  Requires-Dist: numpy >=1.13.3
35
37
  Requires-Dist: ply >=3.11
38
+ Requires-Dist: pyzmq >=25.1.0
36
39
  Requires-Dist: scipy >=1.0.0
40
+ Requires-Dist: watchdog >=4.0.0
37
41
 
38
42
  # QuLab
39
43
  [![View build status](https://travis-ci.org/feihoo87/QuLab.svg?branch=master)](https://travis-ci.org/feihoo87/QuLab)
@@ -1,7 +1,7 @@
1
1
  qulab/__init__.py,sha256=8zLGg-DfQhnDl2Ky0n-zXpN-8e-g7iR0AcaI4l4Vvpk,32
2
- qulab/__main__.py,sha256=pprldpRI_kZ3ufoH1JByhi7WIqqwW7MpaRoL0kGchQk,395
3
- qulab/fun.cp311-win_amd64.pyd,sha256=7CHV79bVQ9FtrOxpQNUC4dcWTYdz-oNXh3s_pNBAY54,31232
4
- qulab/version.py,sha256=pMl7p0vBanIg04EfboBE80RyG_KP7M0m9V3-qTl0YLQ,21
2
+ qulab/__main__.py,sha256=OlYQe7go_eFLKR0uU6D1kIpTKvbpx3WRJFFdoYoFjdE,456
3
+ qulab/fun.cp311-win_amd64.pyd,sha256=mPXp36Aw_1_IQZH_GaOYUJK9JZElr_Uy3bKRPiJ46Wg,31232
4
+ qulab/version.py,sha256=HFL2NgNf74s56viRPRlgp_rAmKP1MzrtnJeQ8LxF_8M,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,14 +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=sjw3_wUL8G2AyDKSl9jhvoCbqLGg2DEmloXJHfO067A,220
16
- qulab/scan/base.py,sha256=4KYjT42qNuIc1axac6Qz4Tkcu9_ZtEpZ1QhxDS17haI,17691
17
- qulab/scan/dataset.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- qulab/scan/expression.py,sha256=aTHplJPlvuW2R73X6oMcV5Gzeo8NSCre8Q3hE7mkCxI,15253
19
- qulab/scan/optimize.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- qulab/scan/scanner.py,sha256=PXQwFPkpUIMwoL40FFbXvk693eXxP7YYaHQHAY1Ome4,8072
21
- qulab/scan/transforms.py,sha256=OWiHE36qKqeOJI-vwo3BOjGi5Ya_xcYU0g7D2DDIGo4,268
22
- qulab/scan/utils.py,sha256=DHGC-RcGbY7RmMEDvazPkC_nFqlj_N8Cr9spm_CGfuE,1061
15
+ qulab/scan/__init__.py,sha256=O_m7HAjbavGUxl7MayY-PCGCXfzoASmeE-FX5zEIjCs,127
16
+ qulab/scan/curd.py,sha256=bEXtcmiaoAv5APToXx5O5tvmqAhE2_LkvdwLsI_8D5M,4662
17
+ qulab/scan/expression.py,sha256=vwUM9E0OFQal4bljlUtLR3NJu4zGRyuWYrdyZSs3QTU,16199
18
+ qulab/scan/models.py,sha256=TkiVHF_fUZzYHs4MsCTRh391thpf4Ozd3R_LAU0Gxkg,17657
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=jDsjyOPf15DV8rk1q2CYH7aDO6ypaP6n7t3LmNaY03o,23187
23
+ qulab/scan/utils.py,sha256=XM-eKL5Xkm0hihhGS7Kq4g654Ye7n7TcU_f95gxtXq8,2634
23
24
  qulab/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
25
  qulab/storage/__main__.py,sha256=6-EjN0waX1yfcMPJXqpIr9UlrIEsSCFApm5G-ZeaPMQ,1742
25
26
  qulab/storage/base_dataset.py,sha256=28y3-OZrqJ52p5sbirEpUgjb7hqwLLpd38KU9DCkD24,12217
@@ -67,16 +68,17 @@ qulab/sys/rpc/server.py,sha256=W3bPwe8um1IeR_3HLx-ad6iCcbeuUQcSg11Ze4w6DJg,742
67
68
  qulab/sys/rpc/socket.py,sha256=W3bPwe8um1IeR_3HLx-ad6iCcbeuUQcSg11Ze4w6DJg,742
68
69
  qulab/sys/rpc/utils.py,sha256=BurIcqh8CS-Hsk1dYP6IiefK4qHivaEqD9_rBY083SA,619
69
70
  qulab/sys/rpc/worker.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ qulab/sys/rpc/zmq_socket.py,sha256=Ep4Uy36mV04tkzKtLsRSu5dQ0AT7cPeLhqZxRYgaxTQ,8135
70
72
  qulab/visualization/__init__.py,sha256=Bkt9AK5c45d6HFLlT-f8cIppywXziHtJqhDtVxOoKKo,6317
71
73
  qulab/visualization/__main__.py,sha256=WduINFl21B-XMsi2rg2cVhIyU11hKKX3zOsjc56QLiQ,1710
72
- qulab/visualization/_autoplot.py,sha256=JLvyr36wQRUU7i61_TMqcODizWZvTizY5CSGS_ZZsCw,14234
74
+ qulab/visualization/_autoplot.py,sha256=JFLR3e71bryPaUkOCWFzD9C4Nk-ulqIdBb1YN4QnZic,14562
73
75
  qulab/visualization/plot_layout.py,sha256=yAnMONOms7_szCdng-8wPpUMPis5UnbaNNzV4KFBgso,13941
74
76
  qulab/visualization/plot_seq.py,sha256=h9D0Yl_yO64IwlvBgzMu9EBKr9gg6y8QE55gu2PfTns,2783
75
77
  qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
76
78
  qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
77
- QuLab-2.0.1.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
78
- QuLab-2.0.1.dist-info/METADATA,sha256=NI3Uarm6V21L_ZOfXyn-HEQDCu_l_GNfOCKmE33Wm5c,3480
79
- QuLab-2.0.1.dist-info/WHEEL,sha256=nSybvzWlmdJnHiUQSY-d7V1ycwEVUTqXiTvr2eshg44,102
80
- QuLab-2.0.1.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
81
- QuLab-2.0.1.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
82
- QuLab-2.0.1.dist-info/RECORD,,
79
+ QuLab-2.0.3.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
80
+ QuLab-2.0.3.dist-info/METADATA,sha256=CBLJJtH8PMO1np50hxS8-Xbs1Bj4lFN1T7AwYCFI47Q,3609
81
+ QuLab-2.0.3.dist-info/WHEEL,sha256=nSybvzWlmdJnHiUQSY-d7V1ycwEVUTqXiTvr2eshg44,102
82
+ QuLab-2.0.3.dist-info/entry_points.txt,sha256=ohBzutEnQimP_BZWiuXdSliu4QAYSHHcN0PZD8c7ZCY,46
83
+ QuLab-2.0.3.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
84
+ QuLab-2.0.3.dist-info/RECORD,,
qulab/__main__.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import click
2
2
 
3
3
  from .monitor.__main__ import main as monitor
4
+ from .scan.recorder import record
4
5
  from .sys.net.cli import dht
5
6
  from .visualization.__main__ import plot
6
7
 
@@ -19,6 +20,7 @@ def hello():
19
20
  main.add_command(monitor)
20
21
  main.add_command(plot)
21
22
  main.add_command(dht)
23
+ main.add_command(record)
22
24
 
23
25
  if __name__ == '__main__':
24
26
  main()
Binary file
qulab/scan/__init__.py CHANGED
@@ -1,4 +1,3 @@
1
- from .base import (BaseOptimizer, Begin, End, OptimizerConfig, StepStatus,
2
- Tracker, scan_iters)
3
1
  from .expression import Expression, Symbol
4
- from .scanner import Atom, Optimizer, OptimizeSpace, Scan
2
+ from .query_record import get_record, lookup, lookup_list
3
+ from .scan import Scan
qulab/scan/curd.py ADDED
@@ -0,0 +1,144 @@
1
+ from datetime import date, datetime, timezone
2
+ from typing import Sequence, Type, Union
3
+
4
+ from sqlalchemy.orm import Query, Session, aliased
5
+ from sqlalchemy.orm.exc import NoResultFound
6
+ from sqlalchemy.orm.session import Session
7
+ from waveforms.dicttree import foldDict
8
+
9
+ from .models import Comment, Record, Report, Sample, Tag
10
+
11
+
12
+ def tag(session: Session, tag_text: str) -> Tag:
13
+ """Get a tag from the database or create a new if not exists."""
14
+ try:
15
+ return session.query(Tag).filter(Tag.text == tag_text).one()
16
+ except NoResultFound:
17
+ tag = Tag(text=tag_text)
18
+ return tag
19
+
20
+
21
+ def tag_it(session: Session, tag_text: str, obj: Union[Sample, Record,
22
+ Report]) -> Tag:
23
+ """Tag an object."""
24
+ if obj.id is None:
25
+ session.add(obj)
26
+ obj.tags.append(tag(session, tag_text))
27
+ else:
28
+ session.query(type(obj)).filter(
29
+ type(obj).id == obj.id).one().tags.append(tag(session, tag_text))
30
+ session.commit()
31
+
32
+
33
+ def get_object_with_tags(session: Session,
34
+ cls: Union[Type[Comment], Type[Sample], Type[Record],
35
+ Type[Report]], *tags: str) -> Query:
36
+ """
37
+ Query objects with the given tags.
38
+
39
+ Parameters
40
+ ----------
41
+ session : :class:`sqlalchemy.orm.Session`
42
+ The database session.
43
+ cls : :class:`sqlalchemy.orm.Mapper`
44
+ The object class.
45
+ tags : str
46
+ The tags.
47
+
48
+ Returns
49
+ -------
50
+ :class:`sqlalchemy.orm.Query`
51
+ The query.
52
+ """
53
+ if isinstance(session, Query):
54
+ q = session
55
+ else:
56
+ q = session.query(cls)
57
+ if not hasattr(cls, 'tags'):
58
+ return []
59
+
60
+ aliase = {tag: aliased(Tag) for tag in tags}
61
+
62
+ for tag, a in aliase.items():
63
+ q = q.join(a, cls.tags)
64
+ if '*' in tag:
65
+ q = q.filter(a.text.like(tag.replace('*', '%')))
66
+ else:
67
+ q = q.filter(a.text == tag)
68
+ return q
69
+
70
+
71
+ def query_record(session: Session,
72
+ offset: int = 0,
73
+ limit: int = 10,
74
+ app: str | None = None,
75
+ tags: Sequence[str] = (),
76
+ before: datetime | date | None = None,
77
+ after: datetime | date | None = None):
78
+ tz_offset = datetime.now(timezone.utc).astimezone().utcoffset()
79
+ table = {'header': ['ID', 'App', 'tags', 'created time'], 'body': []}
80
+ apps = sorted(
81
+ set([
82
+ n for n, *_ in get_object_with_tags(session.query(Record.app),
83
+ Record, *tags).all()
84
+ ]))
85
+ apps = foldDict(dict([(app, None) for app in apps]))
86
+
87
+ query = get_object_with_tags(session, Record, *tags)
88
+
89
+ if app is not None:
90
+ if app.endswith('*'):
91
+ query = query.filter(Record.app.like(app[:-1] + '%'))
92
+ else:
93
+ query = query.filter(Record.app == app)
94
+ if before is not None:
95
+ if isinstance(before, date):
96
+ before = datetime(before.year, before.month, before.day)
97
+ query = query.filter(Record.ctime <= before - tz_offset)
98
+ if after is not None:
99
+ if isinstance(after, date):
100
+ after = datetime(after.year, after.month, after.day)
101
+ query = query.filter(Record.ctime >= after - tz_offset)
102
+ total = query.count()
103
+ for r in query.order_by(Record.ctime.desc()).limit(limit).offset(offset):
104
+ tags = sorted([t.text for t in r.tags])
105
+ ctime = r.ctime + tz_offset
106
+ row = [r.id, r.app, tags, ctime]
107
+ table['body'].append(row)
108
+
109
+ return total, apps, table
110
+
111
+
112
+ def update_tags(session: Session,
113
+ record_id: int,
114
+ tags: Sequence[str],
115
+ append: bool = False):
116
+ record = session.get(Record, record_id)
117
+ if record is None:
118
+ return False
119
+ if append:
120
+ old = [t.text for t in record.tags]
121
+ for t in old:
122
+ if t not in tags:
123
+ tags.append(t)
124
+ record.tags = [tag(session, t) for t in tags]
125
+ try:
126
+ session.commit()
127
+ except Exception:
128
+ session.rollback()
129
+ return False
130
+ return True
131
+
132
+
133
+ def remove_tags(session: Session, record_id: int, tags: Sequence[str]):
134
+ record = session.get(Record, record_id)
135
+ if record is None:
136
+ return False
137
+ old = [t.text for t in record.tags]
138
+ record.tags = [tag(session, t) for t in old if t not in tags]
139
+ try:
140
+ session.commit()
141
+ except Exception:
142
+ session.rollback()
143
+ return False
144
+ return True
qulab/scan/expression.py CHANGED
@@ -323,6 +323,14 @@ class UnaryExpression(Expression):
323
323
  self.a = a
324
324
  self.op = op
325
325
 
326
+ def __getstate__(self) -> dict:
327
+ return {'a': self.a, 'op': self.op}
328
+
329
+ def __setstate__(self, state: dict):
330
+ self.a = state['a']
331
+ self.op = state['op']
332
+ self.cache = _empty
333
+
326
334
  def symbols(self) -> list[str]:
327
335
  if isinstance(self.a, Expression):
328
336
  return self.a.symbols()
@@ -362,6 +370,15 @@ class BinaryExpression(Expression):
362
370
  self.b = b
363
371
  self.op = op
364
372
 
373
+ def __getstate__(self) -> dict:
374
+ return {'a': self.a, 'b': self.b, 'op': self.op}
375
+
376
+ def __setstate__(self, state: dict):
377
+ self.a = state['a']
378
+ self.b = state['b']
379
+ self.op = state['op']
380
+ self.cache = _empty
381
+
365
382
  def symbols(self) -> list[str]:
366
383
  symbs = set()
367
384
  if isinstance(self.a, Expression):
@@ -419,6 +436,15 @@ class ObjectMethod(Expression):
419
436
  self.method = method
420
437
  self.args = args
421
438
 
439
+ def __getstate__(self) -> dict:
440
+ return {'obj': self.obj, 'method': self.method, 'args': self.args}
441
+
442
+ def __setstate__(self, state: dict):
443
+ self.obj = state['obj']
444
+ self.method = state['method']
445
+ self.args = state['args']
446
+ self.cache = _empty
447
+
422
448
  def symbols(self) -> list[str]:
423
449
  symbs = set()
424
450
  if isinstance(self.obj, Expression):
@@ -439,7 +465,7 @@ class ObjectMethod(Expression):
439
465
  return ObjectMethod(obj, self.method, *args)
440
466
  else:
441
467
  return getattr(obj, self.method)(*args)
442
-
468
+
443
469
  def __repr__(self):
444
470
  if self.method == '__call__':
445
471
  return f"{self.obj!r}({', '.join(map(repr, self.args))})"
@@ -453,6 +479,13 @@ class Symbol(Expression):
453
479
  super().__init__()
454
480
  self.name = name
455
481
 
482
+ def __getstate__(self) -> dict:
483
+ return {'name': self.name}
484
+
485
+ def __setstate__(self, state: dict):
486
+ self.name = state['name']
487
+ self.cache = _empty
488
+
456
489
  def symbols(self) -> list[str]:
457
490
  return [self.name]
458
491