QuLab 2.7.6__tar.gz → 2.7.8__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 (113) hide show
  1. {qulab-2.7.6 → qulab-2.7.8}/PKG-INFO +1 -1
  2. {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/PKG-INFO +1 -1
  3. {qulab-2.7.6 → qulab-2.7.8}/qulab/__init__.py +2 -2
  4. {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/cli.py +2 -2
  5. {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/load.py +11 -11
  6. {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/schedule.py +183 -168
  7. {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/storage.py +61 -52
  8. {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/transform.py +5 -5
  9. {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/utils.py +33 -33
  10. qulab-2.7.8/qulab/typing.py +2 -0
  11. qulab-2.7.8/qulab/version.py +1 -0
  12. qulab-2.7.6/qulab/typing.py +0 -2
  13. qulab-2.7.6/qulab/version.py +0 -1
  14. {qulab-2.7.6 → qulab-2.7.8}/LICENSE +0 -0
  15. {qulab-2.7.6 → qulab-2.7.8}/MANIFEST.in +0 -0
  16. {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/SOURCES.txt +0 -0
  17. {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/dependency_links.txt +0 -0
  18. {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/entry_points.txt +0 -0
  19. {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/requires.txt +0 -0
  20. {qulab-2.7.6 → qulab-2.7.8}/QuLab.egg-info/top_level.txt +0 -0
  21. {qulab-2.7.6 → qulab-2.7.8}/README.md +0 -0
  22. {qulab-2.7.6 → qulab-2.7.8}/pyproject.toml +0 -0
  23. {qulab-2.7.6 → qulab-2.7.8}/qulab/__main__.py +0 -0
  24. {qulab-2.7.6 → qulab-2.7.8}/qulab/cli/__init__.py +0 -0
  25. {qulab-2.7.6 → qulab-2.7.8}/qulab/cli/commands.py +0 -0
  26. {qulab-2.7.6 → qulab-2.7.8}/qulab/cli/config.py +0 -0
  27. {qulab-2.7.6 → qulab-2.7.8}/qulab/dicttree.py +0 -0
  28. {qulab-2.7.6 → qulab-2.7.8}/qulab/executor/__init__.py +0 -0
  29. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/__init__.py +0 -0
  30. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/__main__.py +0 -0
  31. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/config.py +0 -0
  32. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/dataset.py +0 -0
  33. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/event_queue.py +0 -0
  34. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/mainwindow.py +0 -0
  35. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/monitor.py +0 -0
  36. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/ploter.py +0 -0
  37. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/qt_compat.py +0 -0
  38. {qulab-2.7.6 → qulab-2.7.8}/qulab/monitor/toolbar.py +0 -0
  39. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/__init__.py +0 -0
  40. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/curd.py +0 -0
  41. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/expression.py +0 -0
  42. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/models.py +0 -0
  43. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/optimize.py +0 -0
  44. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/query.py +0 -0
  45. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/record.py +0 -0
  46. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/scan.py +0 -0
  47. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/server.py +0 -0
  48. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/space.py +0 -0
  49. {qulab-2.7.6 → qulab-2.7.8}/qulab/scan/utils.py +0 -0
  50. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/__init__.py +0 -0
  51. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/__main__.py +0 -0
  52. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/backend/__init__.py +0 -0
  53. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/backend/redis.py +0 -0
  54. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/base_dataset.py +0 -0
  55. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/chunk.py +0 -0
  56. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/dataset.py +0 -0
  57. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/file.py +0 -0
  58. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/__init__.py +0 -0
  59. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/base.py +0 -0
  60. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/config.py +0 -0
  61. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/file.py +0 -0
  62. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/ipy.py +0 -0
  63. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/models.py +0 -0
  64. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/record.py +0 -0
  65. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/report.py +0 -0
  66. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/models/tag.py +0 -0
  67. {qulab-2.7.6 → qulab-2.7.8}/qulab/storage/storage.py +0 -0
  68. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/__init__.py +0 -0
  69. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/chat.py +0 -0
  70. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/__init__.py +0 -0
  71. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/basedevice.py +0 -0
  72. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/loader.py +0 -0
  73. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/device/utils.py +0 -0
  74. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/drivers/FakeInstrument.py +0 -0
  75. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/drivers/__init__.py +0 -0
  76. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/ipy_events.py +0 -0
  77. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/__init__.py +0 -0
  78. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/bencoder.py +0 -0
  79. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/cli.py +0 -0
  80. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/dhcp.py +0 -0
  81. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/dhcpd.py +0 -0
  82. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/kad.py +0 -0
  83. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/kcp.py +0 -0
  84. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/net/nginx.py +0 -0
  85. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/progress.py +0 -0
  86. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/__init__.py +0 -0
  87. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/client.py +0 -0
  88. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/exceptions.py +0 -0
  89. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/msgpack.py +0 -0
  90. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/msgpack.pyi +0 -0
  91. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/router.py +0 -0
  92. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/rpc.py +0 -0
  93. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/serialize.py +0 -0
  94. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/server.py +0 -0
  95. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/socket.py +0 -0
  96. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/utils.py +0 -0
  97. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/worker.py +0 -0
  98. {qulab-2.7.6 → qulab-2.7.8}/qulab/sys/rpc/zmq_socket.py +0 -0
  99. {qulab-2.7.6 → qulab-2.7.8}/qulab/utils.py +0 -0
  100. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/__init__.py +0 -0
  101. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/__main__.py +0 -0
  102. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/_autoplot.py +0 -0
  103. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/plot_circ.py +0 -0
  104. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/plot_layout.py +0 -0
  105. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/plot_seq.py +0 -0
  106. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/qdat.py +0 -0
  107. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/rot3d.py +0 -0
  108. {qulab-2.7.6 → qulab-2.7.8}/qulab/visualization/widgets.py +0 -0
  109. {qulab-2.7.6 → qulab-2.7.8}/setup.cfg +0 -0
  110. {qulab-2.7.6 → qulab-2.7.8}/setup.py +0 -0
  111. {qulab-2.7.6 → qulab-2.7.8}/src/qulab.h +0 -0
  112. {qulab-2.7.6 → qulab-2.7.8}/tests/test_kad.py +0 -0
  113. {qulab-2.7.6 → qulab-2.7.8}/tests/test_scan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: QuLab
3
- Version: 2.7.6
3
+ Version: 2.7.8
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.2
2
2
  Name: QuLab
3
- Version: 2.7.6
3
+ Version: 2.7.8
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,5 +1,5 @@
1
- from .executor.storage import find_result
2
- from .executor.storage import get_result_by_index as get_result
1
+ from .executor.storage import find_report
2
+ from .executor.storage import get_report_by_index as get_report
3
3
  from .executor.utils import debug_analyze
4
4
  from .scan import Scan, get_record, load_record, lookup, lookup_list
5
5
  from .version import __version__
@@ -149,7 +149,7 @@ def get(key, api):
149
149
 
150
150
  @click.command()
151
151
  @click.argument('workflow')
152
- @click.option('--plot', '-p', is_flag=True, help='Plot the result.')
152
+ @click.option('--plot', '-p', is_flag=True, help='Plot the report.')
153
153
  @click.option('--no-dependents',
154
154
  '-n',
155
155
  is_flag=True,
@@ -221,7 +221,7 @@ def run(workflow, code, data, api, plot, no_dependents, retry, freeze):
221
221
  @click.command()
222
222
  @click.argument('workflow')
223
223
  @click.option('--retry', '-r', default=1, type=int, help='Retry times.')
224
- @click.option('--plot', '-p', is_flag=True, help='Plot the result.')
224
+ @click.option('--plot', '-p', is_flag=True, help='Plot the report.')
225
225
  @log_options
226
226
  @command_option('maintain')
227
227
  def maintain(workflow, code, data, api, retry, plot):
@@ -15,7 +15,7 @@ from typing import Any
15
15
 
16
16
  from loguru import logger
17
17
 
18
- from .storage import Result
18
+ from .storage import Report
19
19
 
20
20
 
21
21
  class SetConfigWorkflow():
@@ -29,7 +29,7 @@ class SetConfigWorkflow():
29
29
  def depends(self):
30
30
  return []
31
31
 
32
- def check_state(self, history: Result) -> bool:
32
+ def check_state(self, history: Report) -> bool:
33
33
  from . import transform
34
34
  try:
35
35
  return self._equal(history.parameters[self.key],
@@ -45,21 +45,21 @@ class SetConfigWorkflow():
45
45
  value = eval(input(f'"{self.key}": '))
46
46
  return value
47
47
 
48
- def analyze(self, result: Result, history: Result):
49
- result.state = 'OK'
50
- result.parameters = {self.key: result.data}
51
- return result
48
+ def analyze(self, report: Report, history: Report):
49
+ report.state = 'OK'
50
+ report.parameters = {self.key: report.data}
51
+ return report
52
52
 
53
53
  def check(self):
54
54
  return self.calibrate()
55
55
 
56
- def check_analyze(self, result: Result, history: Result | None):
56
+ def check_analyze(self, report: Report, history: Report | None):
57
57
  if self.check_state(history):
58
- result.state = 'OK'
59
- result.parameters = {self.key: history.data}
58
+ report.state = 'OK'
59
+ report.parameters = {self.key: history.data}
60
60
  else:
61
- result.state = 'Outdated'
62
- return result
61
+ report.state = 'Outdated'
62
+ return report
63
63
 
64
64
  @staticmethod
65
65
  def _equal(a, b):
@@ -7,28 +7,28 @@ from pathlib import Path
7
7
  from loguru import logger
8
8
 
9
9
  from .load import WorkflowType, get_dependents
10
- from .storage import (Result, find_result, get_heads, renew_result,
11
- revoke_result, save_result)
10
+ from .storage import (Report, find_report, get_head, get_heads, renew_report,
11
+ revoke_report, save_report)
12
12
  from .transform import current_config, obey_the_oracle, update_parameters
13
13
 
14
14
  __session_id = None
15
15
  __session_cache = {}
16
16
 
17
17
 
18
- def set_cache(session_id, key, result: Result):
18
+ def set_cache(session_id, key, report: Report):
19
19
  global __session_id
20
20
  if __session_id is None:
21
21
  __session_id = session_id
22
22
  if __session_id != session_id:
23
23
  __session_cache.clear()
24
- if result.workflow.startswith('cfg:'):
25
- __session_cache[key] = result
24
+ if report.workflow.startswith('cfg:'):
25
+ __session_cache[key] = report
26
26
  else:
27
- __session_cache[key] = result.base_path, result.path
27
+ __session_cache[key] = report.base_path, report.path
28
28
 
29
29
 
30
- def get_cache(session_id, key) -> Result:
31
- from .storage import load_result
30
+ def get_cache(session_id, key) -> Report:
31
+ from .storage import load_report
32
32
  global __session_id
33
33
  if __session_id is None or __session_id != session_id:
34
34
  return None
@@ -37,8 +37,8 @@ def get_cache(session_id, key) -> Result:
37
37
  return None
38
38
  if isinstance(index, tuple):
39
39
  base_path, path = index
40
- return load_result(base_path, path)
41
- elif isinstance(index, Result):
40
+ return load_report(base_path, path)
41
+ elif isinstance(index, Report):
42
42
  return index
43
43
  else:
44
44
  return None
@@ -56,14 +56,14 @@ def is_pickleable(obj) -> bool:
56
56
  return False
57
57
 
58
58
 
59
- def veryfy_analyzed_result(result: Result, script: str, method: str):
60
- if not isinstance(result, Result):
61
- raise TypeError(f'"{script}" : "{method}" must return a Result object')
62
- if not is_pickleable(result.parameters):
59
+ def veryfy_analyzed_report(report: Report, script: str, method: str):
60
+ if not isinstance(report, Report):
61
+ raise TypeError(f'"{script}" : "{method}" must return a Report object')
62
+ if not is_pickleable(report.parameters):
63
63
  raise TypeError(
64
64
  f'"{script}" : "{method}" return not pickleable data in .parameters'
65
65
  )
66
- if not is_pickleable(result.other_infomation):
66
+ if not is_pickleable(report.other_infomation):
67
67
  raise TypeError(
68
68
  f'"{script}" : "{method}" return not pickleable data in .other_infomation'
69
69
  )
@@ -80,8 +80,8 @@ def check_state(workflow: WorkflowType, code_path: str | Path,
80
80
  4. All dependencies pass check state.
81
81
  """
82
82
  logger.debug(f'check_state: "{workflow.__workflow_id__}"')
83
- result = find_result(workflow.__workflow_id__, state_path)
84
- if not result:
83
+ report = find_report(workflow.__workflow_id__, state_path)
84
+ if not report:
85
85
  logger.debug(
86
86
  f'check_state failed: No history found for "{workflow.__workflow_id__}"'
87
87
  )
@@ -90,23 +90,23 @@ def check_state(workflow: WorkflowType, code_path: str | Path,
90
90
  logger.debug(
91
91
  f'check_state: "{workflow.__workflow_id__}" has custom check_state method'
92
92
  )
93
- return workflow.check_state(result)
93
+ return workflow.check_state(report)
94
94
  if workflow.__timeout__ is not None and datetime.now(
95
- ) > result.checked_time + timedelta(seconds=workflow.__timeout__):
95
+ ) > report.checked_time + timedelta(seconds=workflow.__timeout__):
96
96
  logger.debug(
97
97
  f'check_state failed: "{workflow.__workflow_id__}" has expired')
98
98
  return False
99
- if not result.in_spec:
99
+ if not report.in_spec:
100
100
  logger.debug(
101
101
  f'check_state failed: "{workflow.__workflow_id__}" is out of spec')
102
102
  return False
103
- if result.bad_data:
103
+ if report.bad_data:
104
104
  logger.debug(
105
105
  f'check_state failed: "{workflow.__workflow_id__}" has bad data')
106
106
  return False
107
107
  for n in get_dependents(workflow, code_path):
108
- r = find_result(n.__workflow_id__, state_path)
109
- if r is None or r.checked_time > result.checked_time:
108
+ r = find_report(n.__workflow_id__, state_path)
109
+ if r is None or r.checked_time > report.checked_time:
110
110
  logger.debug(
111
111
  f'check_state failed: "{workflow.__workflow_id__}" has outdated dependencies'
112
112
  )
@@ -120,71 +120,134 @@ def check_state(workflow: WorkflowType, code_path: str | Path,
120
120
  return True
121
121
 
122
122
 
123
- def call_analyzer(node,
124
- result: Result,
125
- history: Result | None,
126
- check=False,
127
- plot=False) -> Result:
128
- if check:
129
- result = node.check_analyze(result, history=history)
130
- veryfy_analyzed_result(result, node.__workflow_id__, "check_analyze")
131
- result.fully_calibrated = False
123
+ @logger.catch()
124
+ def call_plot(node: WorkflowType, report: Report, check=False):
125
+ if hasattr(node, 'plot') and callable(node.plot):
126
+ node.plot(report)
127
+
128
+
129
+ def call_check(workflow: WorkflowType, session_id: str, state_path: Path):
130
+ report = get_cache(session_id, (workflow, 'check'))
131
+ if report is not None:
132
+ logger.debug(f'Cache hit for "{workflow.__workflow_id__}:check"')
133
+ return report
134
+
135
+ data = workflow.check()
136
+ if not is_pickleable(data):
137
+ raise TypeError(
138
+ f'"{workflow.__workflow_id__}" : "check" return not pickleable data'
139
+ )
140
+ report = Report(workflow=workflow.__workflow_id__,
141
+ data=data,
142
+ config_path=current_config(state_path),
143
+ base_path=state_path,
144
+ heads=get_heads(state_path),
145
+ previous_path=get_head(workflow.__workflow_id__,
146
+ state_path))
147
+
148
+ save_report(workflow.__workflow_id__, report, state_path)
149
+
150
+ set_cache(session_id, (workflow, 'check'), report)
151
+ return report
152
+
153
+
154
+ def call_calibrate(workflow: WorkflowType, session_id: str, state_path: Path):
155
+ report = get_cache(session_id, (workflow, 'calibrate'))
156
+ if report is not None:
157
+ logger.debug(f'Cache hit for "{workflow.__workflow_id__}:calibrate"')
158
+ return report
159
+
160
+ data = workflow.calibrate()
161
+ if not is_pickleable(data):
162
+ raise TypeError(
163
+ f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
164
+ )
165
+ report = Report(workflow=workflow.__workflow_id__,
166
+ data=data,
167
+ config_path=current_config(state_path),
168
+ base_path=state_path,
169
+ heads=get_heads(state_path),
170
+ previous_path=get_head(workflow.__workflow_id__,
171
+ state_path))
172
+
173
+ save_report(workflow.__workflow_id__, report, state_path)
174
+
175
+ set_cache(session_id, (workflow, 'calibrate'), report)
176
+ return report
177
+
178
+
179
+ def call_check_analyzer(node: WorkflowType,
180
+ report: Report,
181
+ history: Report | None,
182
+ state_path: Path,
183
+ plot=False) -> Report:
184
+ report = node.check_analyze(report, history=history)
185
+ veryfy_analyzed_report(report, node.__workflow_id__, "check_analyze")
186
+ report.fully_calibrated = False
187
+ if report.in_spec:
188
+ logger.debug(
189
+ f'"{node.__workflow_id__}": checked in spec, renewing report')
190
+ renew_report(node.__workflow_id__, report.previous, state_path)
132
191
  else:
133
- result = node.analyze(result, history=history)
134
- veryfy_analyzed_result(result, node.__workflow_id__, "analyze")
135
- if hasattr(node, 'oracle') and callable(node.oracle):
136
- logger.debug(
137
- f'"{node.__workflow_id__}" has oracle method, calling ...')
138
- try:
139
- result = node.oracle(result,
140
- history=history,
141
- system_state=get_heads(result.base_path))
142
- except Exception as e:
143
- logger.exception(e)
144
- result.oracle = {}
145
- if not isinstance(result, Result):
146
- raise TypeError(
147
- f'"{node.__workflow_id__}" : function "oracle" must return a Result object'
148
- )
149
- if not is_pickleable(result.oracle):
150
- raise TypeError(
151
- f'"{node.__workflow_id__}" : function "oracle" return not pickleable data'
152
- )
153
- result.fully_calibrated = True
154
- if plot:
155
- call_plot(node, result)
156
- return result
192
+ logger.debug(
193
+ f'"{node.__workflow_id__}": checked out of spec, revoking report')
194
+ revoke_report(node.__workflow_id__, report.previous, state_path)
195
+ return report
157
196
 
158
197
 
159
- @logger.catch()
160
- def call_plot(node, result: Result, check=False):
161
- if hasattr(node, 'plot') and callable(node.plot):
162
- node.plot(result)
198
+ def call_analyzer(node: WorkflowType,
199
+ report: Report,
200
+ history: Report | None,
201
+ state_path: Path,
202
+ plot=False) -> Report:
203
+
204
+ report = node.analyze(report, history=history)
205
+ veryfy_analyzed_report(report, node.__workflow_id__, "analyze")
206
+ if hasattr(node, 'oracle') and callable(node.oracle):
207
+ logger.debug(
208
+ f'"{node.__workflow_id__}" has oracle method, calling ...')
209
+ try:
210
+ report = node.oracle(report,
211
+ history=history,
212
+ system_state=get_heads(report.base_path))
213
+ except Exception as e:
214
+ logger.exception(e)
215
+ report.oracle = {}
216
+ if not isinstance(report, Report):
217
+ raise TypeError(
218
+ f'"{node.__workflow_id__}" : function "oracle" must return a Report object'
219
+ )
220
+ if not is_pickleable(report.oracle):
221
+ raise TypeError(
222
+ f'"{node.__workflow_id__}" : function "oracle" return not pickleable data'
223
+ )
224
+ report.fully_calibrated = True
225
+ save_report(node.__workflow_id__, report, state_path, overwrite=True)
226
+ if plot:
227
+ call_plot(node, report)
228
+ return report
163
229
 
164
230
 
165
- def check_data(workflow: WorkflowType, code_path: str | Path,
166
- state_path: str | Path, plot: bool, session_id: str) -> Result:
231
+ def check_data(workflow: WorkflowType, state_path: str | Path, plot: bool,
232
+ session_id: str) -> Report:
167
233
  """
168
234
  check data answers two questions:
169
235
  Is the parameter associated with this cal in spec,
170
236
  and is the cal scan working as expected?
171
237
  """
172
- result = get_cache(session_id, (workflow, 'check_data'))
173
- if result is not None:
174
- logger.debug(f'Cache hit for "{workflow.__workflow_id__}:check_data"')
175
- return result
176
-
177
- history = find_result(workflow.__workflow_id__, state_path)
238
+ history = find_report(workflow.__workflow_id__, state_path)
178
239
 
179
240
  if history is None:
180
241
  logger.debug(f'No history found for "{workflow.__workflow_id__}"')
181
- result = Result(workflow=workflow.__workflow_id__,
242
+ report = Report(workflow=workflow.__workflow_id__,
182
243
  config_path=current_config(state_path),
183
244
  base_path=state_path,
184
- heads=get_heads(state_path))
185
- result.in_spec = False
186
- result.bad_data = False
187
- return result
245
+ heads=get_heads(state_path),
246
+ previous_path=get_head(workflow.__workflow_id__,
247
+ state_path))
248
+ report.in_spec = False
249
+ report.bad_data = False
250
+ return report
188
251
 
189
252
  if history.bad_data:
190
253
  logger.debug(
@@ -202,92 +265,48 @@ def check_data(workflow: WorkflowType, code_path: str | Path,
202
265
  workflow, 'check_analyze') and callable(workflow.check_analyze):
203
266
  logger.debug(
204
267
  f'Checking "{workflow.__workflow_id__}" with "check" method ...')
205
- data = workflow.check()
206
- if not is_pickleable(data):
207
- raise TypeError(
208
- f'"{workflow.__workflow_id__}" : "check" return not pickleable data'
209
- )
210
- result = Result(workflow=workflow.__workflow_id__,
211
- data=data,
212
- config_path=current_config(state_path),
213
- base_path=state_path,
214
- heads=get_heads(state_path))
215
- #save_result(workflow.__workflow_id__, result, state_path)
268
+
269
+ report = call_check(workflow, session_id, state_path)
216
270
 
217
271
  logger.debug(f'Checked "{workflow.__workflow_id__}" !')
218
- result = call_analyzer(workflow,
219
- result,
220
- history,
221
- check=True,
222
- plot=plot)
223
- if result.in_spec:
224
- logger.debug(
225
- f'"{workflow.__workflow_id__}": checked in spec, renewing result'
226
- )
227
- renew_result(workflow.__workflow_id__, state_path)
228
- else:
229
- logger.debug(
230
- f'"{workflow.__workflow_id__}": checked out of spec, revoking result'
231
- )
232
- revoke_result(workflow.__workflow_id__, state_path)
272
+ report = call_check_analyzer(workflow,
273
+ report,
274
+ history,
275
+ state_path,
276
+ plot=plot)
233
277
  else:
234
278
  logger.debug(
235
279
  f'Checking "{workflow.__workflow_id__}" with "calibrate" method ...'
236
280
  )
237
- data = workflow.calibrate()
238
- if not is_pickleable(data):
239
- raise TypeError(
240
- f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
241
- )
242
- result = Result(workflow=workflow.__workflow_id__,
243
- data=data,
244
- config_path=current_config(state_path),
245
- base_path=state_path,
246
- heads=get_heads(state_path))
247
- save_result(workflow.__workflow_id__, result, state_path)
281
+
282
+ report = call_calibrate(workflow, session_id, state_path)
248
283
 
249
284
  logger.debug(f'Calibrated "{workflow.__workflow_id__}" !')
250
- result = call_analyzer(workflow,
251
- result,
285
+ report = call_analyzer(workflow,
286
+ report,
252
287
  history,
253
- check=False,
288
+ state_path,
254
289
  plot=plot)
255
- save_result(workflow.__workflow_id__,
256
- result,
257
- state_path,
258
- overwrite=True)
290
+ return report
259
291
 
260
- set_cache(session_id, (workflow, 'check_data'), result)
261
- return result
262
292
 
293
+ def calibrate(workflow: WorkflowType, state_path: str | Path, plot: bool,
294
+ session_id: str) -> Report:
295
+ history = find_report(workflow.__workflow_id__, state_path)
263
296
 
264
- def calibrate(workflow: WorkflowType, code_path: str | Path,
265
- state_path: str | Path, plot: bool, session_id: str) -> Result:
266
- result = get_cache(session_id, (workflow, 'calibrate'))
267
- if result is not None:
268
- logger.debug(f'Cache hit for "{workflow.__workflow_id__}:calibrate"')
269
- return result
297
+ logger.debug(f'Calibrating "{workflow.__workflow_id__}" ...')
270
298
 
271
- history = find_result(workflow.__workflow_id__, state_path)
299
+ report = call_calibrate(workflow, session_id, state_path)
272
300
 
273
- logger.debug(f'Calibrating "{workflow.__workflow_id__}" ...')
274
- data = workflow.calibrate()
275
- if not is_pickleable(data):
276
- raise TypeError(
277
- f'"{workflow.__workflow_id__}" : "calibrate" return not pickleable data'
278
- )
279
- result = Result(workflow=workflow.__workflow_id__,
280
- data=data,
281
- config_path=current_config(state_path),
282
- base_path=state_path,
283
- heads=get_heads(state_path))
284
- save_result(workflow.__workflow_id__, result, state_path)
285
301
  logger.debug(f'Calibrated "{workflow.__workflow_id__}" !')
286
- result = call_analyzer(workflow, result, history, check=False, plot=plot)
287
- save_result(workflow.__workflow_id__, result, state_path, overwrite=True)
288
302
 
289
- set_cache(session_id, (workflow, 'calibrate'), result)
290
- return result
303
+ report = call_analyzer(workflow,
304
+ report,
305
+ history,
306
+ state_path,
307
+ check=False,
308
+ plot=plot)
309
+ return report
291
310
 
292
311
 
293
312
  def diagnose(workflow: WorkflowType, code_path: str | Path,
@@ -297,16 +316,16 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
297
316
  '''
298
317
  logger.debug(f'diagnose "{workflow.__workflow_id__}"')
299
318
  # check_data
300
- result = check_data(workflow, code_path, state_path, plot, session_id)
319
+ report = check_data(workflow, state_path, plot, session_id)
301
320
  # in spec case
302
- if result.in_spec:
321
+ if report.in_spec:
303
322
  logger.debug(
304
323
  f'"{workflow.__workflow_id__}": Checked! In spec, no need to diagnose'
305
324
  )
306
325
  return False
307
326
  # bad data case
308
327
  recalibrated = []
309
- if result.bad_data:
328
+ if report.bad_data:
310
329
  logger.debug(
311
330
  f'"{workflow.__workflow_id__}": Bad data, diagnosing dependents')
312
331
  recalibrated = [
@@ -314,7 +333,7 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
314
333
  for n in get_dependents(workflow, code_path)
315
334
  ]
316
335
  if not any(recalibrated):
317
- if result.bad_data:
336
+ if report.bad_data:
318
337
  raise CalibrationFailedError(
319
338
  f'"{workflow.__workflow_id__}": bad data but no dependents recalibrated.'
320
339
  )
@@ -325,27 +344,27 @@ def diagnose(workflow: WorkflowType, code_path: str | Path,
325
344
  logger.debug(
326
345
  f'recalibrate "{workflow.__workflow_id__}" because some dependents recalibrated.'
327
346
  )
328
- elif not result.in_spec and not result.bad_data:
347
+ elif not report.in_spec and not report.bad_data:
329
348
  logger.debug(
330
349
  f'recalibrate "{workflow.__workflow_id__}" because out of spec.')
331
- elif result.in_spec:
350
+ elif report.in_spec:
332
351
  logger.error(
333
352
  f'Never reach: recalibrate "{workflow.__workflow_id__}" because in spec.'
334
353
  )
335
- elif result.bad_data:
354
+ elif report.bad_data:
336
355
  logger.error(
337
356
  f'Never reach: recalibrate "{workflow.__workflow_id__}" because bad data.'
338
357
  )
339
358
  else:
340
359
  logger.error(f'Never reach: recalibrate "{workflow.__workflow_id__}"')
341
360
 
342
- result = calibrate(workflow, code_path, state_path, plot, session_id)
343
- if result.bad_data or not result.in_spec:
344
- obey_the_oracle(result, state_path)
361
+ report = calibrate(workflow, state_path, plot, session_id)
362
+ if report.bad_data or not report.in_spec:
363
+ obey_the_oracle(report, state_path)
345
364
  raise CalibrationFailedError(
346
365
  f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
347
366
  )
348
- update_parameters(result, state_path)
367
+ update_parameters(report, state_path)
349
368
  return True
350
369
 
351
370
 
@@ -382,13 +401,13 @@ def maintain(workflow: WorkflowType,
382
401
  f'"{workflow.__workflow_id__}": In spec, no need to maintain')
383
402
  return
384
403
  # check_data
385
- result = check_data(workflow, code_path, state_path, plot, session_id)
386
- if result.in_spec:
404
+ report = check_data(workflow, state_path, plot, session_id)
405
+ if report.in_spec:
387
406
  if not run:
388
407
  logger.debug(
389
408
  f'"{workflow.__workflow_id__}": In spec, no need to maintain')
390
409
  return
391
- elif result.bad_data:
410
+ elif report.bad_data:
392
411
  logger.debug(
393
412
  f'"{workflow.__workflow_id__}": Bad data, diagnosing dependents')
394
413
  for n in get_dependents(workflow, code_path):
@@ -401,15 +420,15 @@ def maintain(workflow: WorkflowType,
401
420
  f'"{workflow.__workflow_id__}": All dependents diagnosed')
402
421
  # calibrate
403
422
  logger.debug(f'recalibrate "{workflow.__workflow_id__}"')
404
- result = calibrate(workflow, code_path, state_path, plot, session_id)
405
- if result.bad_data or not result.in_spec:
423
+ report = calibrate(workflow, state_path, plot, session_id)
424
+ if report.bad_data or not report.in_spec:
406
425
  if not freeze:
407
- obey_the_oracle(result, state_path)
426
+ obey_the_oracle(report, state_path)
408
427
  raise CalibrationFailedError(
409
428
  f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
410
429
  )
411
430
  if not freeze:
412
- update_parameters(result, state_path)
431
+ update_parameters(report, state_path)
413
432
  return
414
433
 
415
434
 
@@ -421,17 +440,13 @@ def run(workflow: WorkflowType,
421
440
  freeze: bool = False):
422
441
  session_id = uuid.uuid4().hex
423
442
  logger.debug(f'run "{workflow.__workflow_id__}" without dependences.')
424
- result = calibrate(workflow,
425
- code_path,
426
- state_path,
427
- plot,
428
- session_id=session_id)
429
- if result.bad_data or not result.in_spec:
443
+ report = calibrate(workflow, state_path, plot, session_id=session_id)
444
+ if report.bad_data or not report.in_spec:
430
445
  if not freeze:
431
- obey_the_oracle(result, state_path)
446
+ obey_the_oracle(report, state_path)
432
447
  raise CalibrationFailedError(
433
448
  f'"{workflow.__workflow_id__}": All dependents passed, but calibration failed!'
434
449
  )
435
450
  if not freeze:
436
- update_parameters(result, state_path)
451
+ update_parameters(report, state_path)
437
452
  return