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