QuLab 2.5.5__cp311-cp311-win_amd64.whl → 2.6.0__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.2
2
2
  Name: QuLab
3
- Version: 2.5.5
3
+ Version: 2.6.0
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,19 +1,19 @@
1
1
  qulab/__init__.py,sha256=pdlicy07Dx39pTEGZ0i41Ox9tuuuKKIdsFIrE13bneg,249
2
2
  qulab/__main__.py,sha256=FL4YsGZL1jEtmcPc5WbleArzhOHLMsWl7OH3O-1d1ss,72
3
3
  qulab/dicttree.py,sha256=ZoSJVWK4VMqfzj42gPb_n5RqLlM6K1Me0WmLIfLEYf8,14195
4
- qulab/fun.cp311-win_amd64.pyd,sha256=tIPc3llk15Bgolq5q4lOYC466t4UWjxWhR91_x1v_oY,31744
4
+ qulab/fun.cp311-win_amd64.pyd,sha256=R2K04NJ-G_TMiEmC0froVy1S8aEeM4Q13gXJLRJMpvY,31744
5
5
  qulab/typing.py,sha256=3c0eKa1avEHIi5wPvh3-4l6Of5mu5Rn1MWPnMeLGNX0,71
6
- qulab/version.py,sha256=MDur6AV_Dwa0PNW31e6addEkEKMAh_dHbKFdazRMbHo,21
6
+ qulab/version.py,sha256=TVXgO9sDvQmPtUVfR1AoRwJlJS-Z7ydYZ2XkEU-nChs,21
7
7
  qulab/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  qulab/cli/commands.py,sha256=6xd2eYw32k1NmfAuYSu__1kaP12Oz1QVqwbkYXdWno4,588
9
9
  qulab/cli/config.py,sha256=tNmH4ggdgrFqcQa2WZKLpidiYTg95_UnT0paDJ4fi4c,3204
10
10
  qulab/executor/__init__.py,sha256=LosPzOMaljSZY1thy_Fxtbrgq7uubJszMABEB7oM7tU,101
11
- qulab/executor/cli.py,sha256=ZGnQdUFZmU812gsnqbKhaJzwWLdoPt42CukPbZ7Yv8k,6684
11
+ qulab/executor/cli.py,sha256=MjwXe_ZEolVzNkGYq6G4cp-iHI0TiAlNkSuX2p0ZZQk,6760
12
12
  qulab/executor/load.py,sha256=t48vZQVAViIwGBPnoRbfBafv5jSR4ix3z4pkvyGyX-w,17759
13
- qulab/executor/schedule.py,sha256=DCZmqtNzrvsA1wOTxEldI22n6UWlHtxEx6QKsHn1S8k,13344
14
- qulab/executor/storage.py,sha256=u7uAmZU8D-pvd6UNek1zzxbUBIZQpftSiXdag6hlkG8,7533
15
- qulab/executor/transform.py,sha256=AazWdlkEoOBaUJpTYsT5J4f0RanzCEeo-ThwEg8BB4Y,1262
16
- qulab/executor/utils.py,sha256=VZ_VPYT2MFIfrCtfEW1I7T4NKFIbOvfVac8Sv377MTY,4221
13
+ qulab/executor/schedule.py,sha256=U3DnkDojkxz40wa0oqIhB4kgghfoL3BrU3TsZZLN8jE,13808
14
+ qulab/executor/storage.py,sha256=0EWgnJoG76xKCrmR_7b07QPqxfHzWJp3vskht5rQlPk,7857
15
+ qulab/executor/transform.py,sha256=00MH8G7Ad7mKfFsyGsrqhXqzi-vR7OcmNJJy5i_lYT0,2947
16
+ qulab/executor/utils.py,sha256=rY12SHIfBsjeUF7P5gyJmiiRpCY6xBuMpmCI3SuhJs8,4928
17
17
  qulab/monitor/__init__.py,sha256=xEVDkJF8issrsDeLqQmDsvtRmrf-UiViFcGTWuzdlFU,43
18
18
  qulab/monitor/__main__.py,sha256=k2H1H5Zf9LLXTDLISJkbikLH-z0f1e5i5i6wXXYPOrE,105
19
19
  qulab/monitor/config.py,sha256=y_5StMkdrbZO1ziyKBrvIkB7Jclp9RCPK1QbsOhCxnY,785
@@ -93,9 +93,9 @@ qulab/visualization/plot_seq.py,sha256=Uo1-dB1YE9IN_A9tuaOs9ZG3S5dKDQ_l98iD2Wbxp
93
93
  qulab/visualization/qdat.py,sha256=HubXFu4nfcA7iUzghJGle1C86G6221hicLR0b-GqhKQ,5887
94
94
  qulab/visualization/rot3d.py,sha256=jGHJcqj1lEWBUV-W4GUGONGacqjrYvuFoFCwPse5h1Y,757
95
95
  qulab/visualization/widgets.py,sha256=HcYwdhDtLreJiYaZuN3LfofjJmZcLwjMfP5aasebgDo,3266
96
- QuLab-2.5.5.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
97
- QuLab-2.5.5.dist-info/METADATA,sha256=mYU52jH0wnkH_K_jA_KXqmMENLaoSz5KSmKVhQo2AfE,3803
98
- QuLab-2.5.5.dist-info/WHEEL,sha256=yNnHoQL2GZYIUXm9YvoaBpFjGlUoK9qq9oqYeudrWlE,101
99
- QuLab-2.5.5.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
100
- QuLab-2.5.5.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
101
- QuLab-2.5.5.dist-info/RECORD,,
96
+ QuLab-2.6.0.dist-info/LICENSE,sha256=b4NRQ-GFVpJMT7RuExW3NwhfbrYsX7AcdB7Gudok-fs,1086
97
+ QuLab-2.6.0.dist-info/METADATA,sha256=cEnjwuM71ZAjnXDaTVR3dwjuCSvSZCefrOsLs4TGTIs,3803
98
+ QuLab-2.6.0.dist-info/WHEEL,sha256=yNnHoQL2GZYIUXm9YvoaBpFjGlUoK9qq9oqYeudrWlE,101
99
+ QuLab-2.6.0.dist-info/entry_points.txt,sha256=b0v1GXOwmxY-nCCsPN_rHZZvY9CtTbWqrGj8u1m8yHo,45
100
+ QuLab-2.6.0.dist-info/top_level.txt,sha256=3T886LbAsbvjonu_TDdmgxKYUn939BVTRPxPl9r4cEg,6
101
+ QuLab-2.6.0.dist-info/RECORD,,
qulab/executor/cli.py CHANGED
@@ -102,7 +102,7 @@ def set(key, value, api):
102
102
  from . import transform
103
103
  if api is not None:
104
104
  api = importlib.import_module(api)
105
- set_config_api(api.query_config, api.update_config)
105
+ set_config_api(api.query_config, api.update_config, api.export_config)
106
106
  try:
107
107
  value = eval(value)
108
108
  except:
@@ -124,7 +124,7 @@ def get(key, api):
124
124
  from . import transform
125
125
  if api is not None:
126
126
  api = importlib.import_module(api)
127
- set_config_api(api.query_config, api.update_config)
127
+ set_config_api(api.query_config, api.update_config, api.export_config)
128
128
  click.echo(transform.query_config(key))
129
129
 
130
130
 
@@ -147,7 +147,7 @@ def run(workflow, code, data, api, plot, no_dependents, update):
147
147
  )
148
148
  if api is not None:
149
149
  api = importlib.import_module(api)
150
- set_config_api(api.query_config, api.update_config)
150
+ set_config_api(api.query_config, api.update_config, api.export_config)
151
151
  if code is None:
152
152
  code = Path.cwd()
153
153
  if data is None:
@@ -197,7 +197,7 @@ def maintain(workflow, code, data, api, plot):
197
197
  )
198
198
  if api is not None:
199
199
  api = importlib.import_module(api)
200
- set_config_api(api.query_config, api.update_config)
200
+ set_config_api(api.query_config, api.update_config, api.export_config)
201
201
  if code is None:
202
202
  code = Path.cwd()
203
203
  if data is None:
@@ -9,7 +9,7 @@ from loguru import logger
9
9
  from .load import WorkflowType, get_dependents
10
10
  from .storage import (Result, find_result, renew_result, revoke_result,
11
11
  save_result)
12
- from .transform import update_parameters
12
+ from .transform import current_config, update_parameters
13
13
 
14
14
 
15
15
  class CalibrationFailedError(Exception):
@@ -124,7 +124,8 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
124
124
 
125
125
  if history is None:
126
126
  logger.debug(f'No history found for "{workflow.__workflow_id__}"')
127
- result = Result()
127
+ result = Result(workflow=workflow.__workflow_id__,
128
+ config_path=current_config(state_path))
128
129
  result.in_spec = False
129
130
  result.bad_data = False
130
131
  return result
@@ -150,8 +151,9 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
150
151
  raise TypeError(
151
152
  f'"{workflow.__workflow_id__}" : "check" return not pickleable data'
152
153
  )
153
- result = Result()
154
- result.data = data
154
+ result = Result(workflow=workflow.__workflow_id__,
155
+ data=data,
156
+ config_path=current_config(state_path))
155
157
  #save_result(workflow.__workflow_id__, result, state_path)
156
158
 
157
159
  logger.debug(f'Checked "{workflow.__workflow_id__}" !')
@@ -179,8 +181,9 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
179
181
  raise TypeError(
180
182
  f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
181
183
  )
182
- result = Result()
183
- result.data = data
184
+ result = Result(workflow=workflow.__workflow_id__,
185
+ data=data,
186
+ config_path=current_config(state_path))
184
187
  save_result(workflow.__workflow_id__, result, state_path)
185
188
 
186
189
  logger.debug(f'Calibrated "{workflow}" !')
@@ -208,8 +211,9 @@ def calibrate(workflow: WorkflowType, code_path: str | Path,
208
211
  raise TypeError(
209
212
  f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
210
213
  )
211
- result = Result()
212
- result.data = data
214
+ result = Result(workflow=workflow.__workflow_id__,
215
+ data=data,
216
+ config_path=current_config(state_path))
213
217
  save_result(workflow.__workflow_id__, result, state_path)
214
218
  logger.debug(f'Calibrated "{workflow.__workflow_id__}" !')
215
219
  result = call_analyzer(workflow, result, history, check=False, plot=plot)
@@ -271,7 +275,7 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
271
275
  raise CalibrationFailedError(
272
276
  f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
273
277
  )
274
- update_parameters(result)
278
+ update_parameters(result, state_path)
275
279
  return True
276
280
 
277
281
 
@@ -327,7 +331,7 @@ def maintain(workflow: WorkflowType,
327
331
  f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
328
332
  )
329
333
  if update:
330
- update_parameters(result)
334
+ update_parameters(result, state_path)
331
335
  return
332
336
 
333
337
 
@@ -349,5 +353,5 @@ def run(workflow: WorkflowType,
349
353
  f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
350
354
  )
351
355
  if update:
352
- update_parameters(result)
356
+ update_parameters(result, state_path)
353
357
  return
qulab/executor/storage.py CHANGED
@@ -14,6 +14,7 @@ from ..cli.config import get_config_value
14
14
 
15
15
  @dataclass
16
16
  class Result():
17
+ workflow: str = ''
17
18
  in_spec: bool = False
18
19
  bad_data: bool = False
19
20
  fully_calibrated: bool = False
@@ -26,6 +27,7 @@ class Result():
26
27
  index: int = -1
27
28
  previous_path: Path | None = None
28
29
  base_path: Path | None = None
30
+ config_path: Path | None = None
29
31
 
30
32
  @property
31
33
  def previous(self):
@@ -46,6 +48,14 @@ class Result():
46
48
  state = 'Outdated'
47
49
  return state
48
50
 
51
+ @property
52
+ def config(self):
53
+ from . import transform
54
+ if self.config_path is not None and self.base_path is not None:
55
+ return transform._load_config(self.config_path, self.base_path)
56
+ else:
57
+ return None
58
+
49
59
  @state.setter
50
60
  def state(self, state: Literal['OK', 'Bad', 'Outdated', 'In spec',
51
61
  'Out of spec', 'Bad data']):
@@ -1,5 +1,13 @@
1
+ import functools
2
+ import hashlib
3
+ import lzma
4
+ import pickle
5
+ from pathlib import Path
6
+
1
7
  from .storage import Result
2
8
 
9
+ __config_id = None
10
+
3
11
 
4
12
  def _query_config(name: str, default=None):
5
13
  import pickle
@@ -29,15 +37,73 @@ def _update_config(updates):
29
37
  pickle.dump(parameters, f)
30
38
 
31
39
 
32
- def update_parameters(result: Result):
40
+ def _export_config() -> dict:
41
+ import pickle
42
+
43
+ try:
44
+ with open('parameters.pkl', 'rb') as f:
45
+ parameters = pickle.load(f)
46
+ except:
47
+ parameters = {}
48
+
49
+ return parameters
50
+
51
+
52
+ def update_parameters(result: Result, data_path):
53
+ global __config_id
33
54
  update_config(result.parameters)
55
+ cfg = export_config()
56
+ __config_id = _save_config(cfg, data_path)
57
+
58
+
59
+ def current_config(data_path):
60
+ global __config_id
61
+ if __config_id is None:
62
+ cfg = export_config()
63
+ __config_id = _save_config(cfg, data_path)
64
+ return __config_id
65
+
66
+
67
+ def _save_config(cfg, data_path):
68
+ global __config_id
69
+ i = 0
70
+ buf = pickle.dumps(cfg)
71
+ buf = lzma.compress(buf)
72
+ h = hashlib.md5(buf)
73
+
74
+ while True:
75
+ salt = f"{i:08d}".encode()
76
+ h.update(salt)
77
+ hashstr = h.hexdigest()
78
+ cfg_id = Path(hashstr[:2]) / hashstr[2:4] / hashstr[4:]
79
+ path = Path(data_path) / 'config' / cfg_id
80
+ if not path.exists():
81
+ path.parent.mkdir(parents=True, exist_ok=True)
82
+ with open(path, 'wb') as f:
83
+ f.write(buf)
84
+ break
85
+ elif path.read_bytes() == buf:
86
+ break
87
+ i += 1
88
+ __config_id = str(cfg_id)
89
+ return __config_id
90
+
91
+
92
+ @functools.lru_cache(maxsize=1024)
93
+ def _load_config(id, data_path):
94
+ path = Path(data_path) / 'config' / id
95
+ with open(path, 'rb') as f:
96
+ buf = f.read()
97
+ cfg = pickle.loads(lzma.decompress(buf))
98
+ return cfg
34
99
 
35
100
 
36
101
  query_config = _query_config
37
102
  update_config = _update_config
103
+ export_config = _export_config
38
104
 
39
105
 
40
- def set_config_api(query_method, update_method):
106
+ def set_config_api(query_method, update_method, export_method):
41
107
  """
42
108
  Set the query and update methods for the config.
43
109
 
@@ -47,9 +113,10 @@ def set_config_api(query_method, update_method):
47
113
  update_method: The update method.
48
114
  the method should take a dict of updates.
49
115
  """
50
- global query_config, update_config
116
+ global query_config, update_config, export_config
51
117
 
52
118
  query_config = query_method
53
119
  update_config = update_method
120
+ export_config = export_method
54
121
 
55
- return query_config, update_config
122
+ return query_config, update_config, export_config
qulab/executor/utils.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from pathlib import Path
2
2
 
3
+ from ..cli.config import get_config_value
3
4
  from .load import load_workflow
4
5
 
5
6
 
@@ -133,3 +134,23 @@ def check_analyze(result: Result, history: Result | None = None) -> Result:
133
134
 
134
135
  return result
135
136
  """
137
+
138
+
139
+ def debug_analyze(
140
+ result_index: int,
141
+ code_path: str | Path = get_config_value('code_path', Path),
142
+ data_path: str | Path = get_config_value('data_path', Path),
143
+ ) -> None:
144
+ from .storage import get_result_by_index
145
+
146
+ result = get_result_by_index(result_index, data_path)
147
+ if result is None:
148
+ raise ValueError(f'Invalid result index: {result_index}')
149
+ workflow = result.workflow
150
+ wf = load_workflow(workflow, code_path)
151
+ if wf is None:
152
+ raise ValueError(f'Invalid workflow: {workflow}')
153
+ result = wf.analyze(result)
154
+ if hasattr(wf, 'plot'):
155
+ wf.plot(result)
156
+ return result
Binary file
qulab/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.5.5"
1
+ __version__ = "2.6.0"
File without changes
File without changes