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.
- {qulab-2.7.5 → qulab-2.7.7}/PKG-INFO +1 -1
- {qulab-2.7.5 → qulab-2.7.7}/QuLab.egg-info/PKG-INFO +1 -1
- {qulab-2.7.5 → qulab-2.7.7}/qulab/__init__.py +2 -2
- {qulab-2.7.5 → qulab-2.7.7}/qulab/executor/cli.py +3 -2
- {qulab-2.7.5 → qulab-2.7.7}/qulab/executor/load.py +14 -11
- {qulab-2.7.5 → qulab-2.7.7}/qulab/executor/schedule.py +172 -114
- {qulab-2.7.5 → qulab-2.7.7}/qulab/executor/storage.py +59 -52
- {qulab-2.7.5 → qulab-2.7.7}/qulab/executor/transform.py +5 -5
- {qulab-2.7.5 → qulab-2.7.7}/qulab/executor/utils.py +33 -33
- qulab-2.7.7/qulab/typing.py +2 -0
- qulab-2.7.7/qulab/version.py +1 -0
- qulab-2.7.5/qulab/typing.py +0 -2
- qulab-2.7.5/qulab/version.py +0 -1
- {qulab-2.7.5 → qulab-2.7.7}/LICENSE +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/MANIFEST.in +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/QuLab.egg-info/SOURCES.txt +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/QuLab.egg-info/dependency_links.txt +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/QuLab.egg-info/entry_points.txt +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/QuLab.egg-info/requires.txt +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/QuLab.egg-info/top_level.txt +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/README.md +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/pyproject.toml +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/__main__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/cli/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/cli/commands.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/cli/config.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/dicttree.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/executor/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/__main__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/config.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/dataset.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/event_queue.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/mainwindow.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/monitor.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/ploter.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/qt_compat.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/monitor/toolbar.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/curd.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/expression.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/models.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/optimize.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/query.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/record.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/scan.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/server.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/space.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/scan/utils.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/__main__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/backend/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/backend/redis.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/base_dataset.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/chunk.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/dataset.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/file.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/base.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/config.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/file.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/ipy.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/models.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/record.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/report.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/models/tag.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/storage/storage.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/chat.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/device/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/device/basedevice.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/device/loader.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/device/utils.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/drivers/FakeInstrument.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/drivers/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/ipy_events.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/bencoder.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/cli.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/dhcp.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/dhcpd.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/kad.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/kcp.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/net/nginx.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/progress.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/client.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/exceptions.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/msgpack.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/msgpack.pyi +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/router.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/rpc.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/serialize.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/server.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/socket.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/utils.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/worker.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/sys/rpc/zmq_socket.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/utils.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/__init__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/__main__.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/_autoplot.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/plot_circ.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/plot_layout.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/plot_seq.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/qdat.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/rot3d.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/qulab/visualization/widgets.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/setup.cfg +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/setup.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/src/qulab.h +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/tests/test_kad.py +0 -0
- {qulab-2.7.5 → qulab-2.7.7}/tests/test_scan.py +0 -0
@@ -1,5 +1,5 @@
|
|
1
|
-
from .executor.storage import
|
2
|
-
from .executor.storage import
|
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
|
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
|
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
|
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:
|
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,
|
49
|
-
|
50
|
-
|
51
|
-
return
|
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,
|
56
|
+
def check_analyze(self, report: Report, history: Report | None):
|
57
57
|
if self.check_state(history):
|
58
|
-
|
59
|
-
|
58
|
+
report.state = 'OK'
|
59
|
+
report.parameters = {self.key: history.data}
|
60
60
|
else:
|
61
|
-
|
62
|
-
return
|
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 (
|
11
|
-
|
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
|
28
|
-
if not isinstance(
|
29
|
-
raise TypeError(f'"{script}" : "{method}" must return a
|
30
|
-
if not is_pickleable(
|
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(
|
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
|
-
|
52
|
-
if not
|
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(
|
93
|
+
return workflow.check_state(report)
|
62
94
|
if workflow.__timeout__ is not None and datetime.now(
|
63
|
-
) >
|
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
|
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
|
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 =
|
77
|
-
if r is None or r.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
|
-
|
93
|
-
history:
|
123
|
+
def call_analyzer(node: WorkflowType,
|
124
|
+
report: Report,
|
125
|
+
history: Report | None,
|
94
126
|
check=False,
|
95
|
-
plot=False) ->
|
127
|
+
plot=False) -> Report:
|
96
128
|
if check:
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
102
|
-
|
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
|
-
|
139
|
+
report = node.oracle(report,
|
108
140
|
history=history,
|
109
|
-
system_state=get_heads(
|
141
|
+
system_state=get_heads(report.base_path))
|
110
142
|
except Exception as e:
|
111
143
|
logger.exception(e)
|
112
|
-
|
113
|
-
if not isinstance(
|
144
|
+
report.oracle = {}
|
145
|
+
if not isinstance(report, Report):
|
114
146
|
raise TypeError(
|
115
|
-
f'"{node.__workflow_id__}" : function "oracle" must return a
|
147
|
+
f'"{node.__workflow_id__}" : function "oracle" must return a Report object'
|
116
148
|
)
|
117
|
-
if not is_pickleable(
|
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
|
-
|
153
|
+
report.fully_calibrated = True
|
122
154
|
if plot:
|
123
|
-
call_plot(node,
|
124
|
-
return
|
155
|
+
call_plot(node, report)
|
156
|
+
return report
|
125
157
|
|
126
158
|
|
127
159
|
@logger.catch()
|
128
|
-
def call_plot(node,
|
160
|
+
def call_plot(node: WorkflowType, report: Report, check=False):
|
129
161
|
if hasattr(node, 'plot') and callable(node.plot):
|
130
|
-
node.plot(
|
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) ->
|
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 =
|
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
|
-
|
225
|
+
report = Report(workflow=workflow.__workflow_id__,
|
146
226
|
config_path=current_config(state_path),
|
147
|
-
base_path=state_path
|
148
|
-
|
149
|
-
|
150
|
-
|
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
|
-
|
169
|
-
|
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
|
-
|
181
|
-
|
253
|
+
report = call_analyzer(workflow,
|
254
|
+
report,
|
182
255
|
history,
|
183
256
|
check=True,
|
184
257
|
plot=plot)
|
185
|
-
if
|
258
|
+
if report.in_spec:
|
186
259
|
logger.debug(
|
187
|
-
f'"{workflow.__workflow_id__}": checked in spec, renewing
|
260
|
+
f'"{workflow.__workflow_id__}": checked in spec, renewing report'
|
188
261
|
)
|
189
|
-
|
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
|
265
|
+
f'"{workflow.__workflow_id__}": checked out of spec, revoking report'
|
193
266
|
)
|
194
|
-
|
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
|
-
|
200
|
-
|
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
|
-
|
212
|
-
|
276
|
+
report = call_analyzer(workflow,
|
277
|
+
report,
|
213
278
|
history,
|
214
279
|
check=False,
|
215
280
|
plot=plot)
|
216
|
-
|
217
|
-
|
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) ->
|
227
|
-
history =
|
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
|
-
|
231
|
-
|
232
|
-
|
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
|
-
|
242
|
-
|
243
|
-
|
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
|
-
|
311
|
+
report = check_data(workflow, code_path, state_path, plot, session_id)
|
254
312
|
# in spec case
|
255
|
-
if
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
296
|
-
if
|
297
|
-
obey_the_oracle(
|
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(
|
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
|
-
|
339
|
-
if
|
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
|
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
|
-
|
358
|
-
if
|
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(
|
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(
|
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
|
-
|
435
|
+
report = calibrate(workflow,
|
378
436
|
code_path,
|
379
437
|
state_path,
|
380
438
|
plot,
|
381
439
|
session_id=session_id)
|
382
|
-
if
|
440
|
+
if report.bad_data or not report.in_spec:
|
383
441
|
if not freeze:
|
384
|
-
obey_the_oracle(
|
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(
|
447
|
+
update_parameters(report, state_path)
|
390
448
|
return
|