rbbt-util 5.44.1 → 6.0.4
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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/bin/rbbt +67 -90
- data/bin/rbbt_exec.rb +2 -2
- data/etc/app.d/base.rb +2 -2
- data/etc/app.d/semaphores.rb +3 -3
- data/lib/rbbt/annotations/annotated_array.rb +207 -207
- data/lib/rbbt/annotations/refactor.rb +27 -0
- data/lib/rbbt/annotations/util.rb +282 -282
- data/lib/rbbt/annotations.rb +343 -320
- data/lib/rbbt/association/database.rb +200 -225
- data/lib/rbbt/association/index.rb +294 -291
- data/lib/rbbt/association/item.rb +227 -227
- data/lib/rbbt/association/open.rb +35 -34
- data/lib/rbbt/association/util.rb +0 -169
- data/lib/rbbt/association.rb +2 -4
- data/lib/rbbt/entity/identifiers.rb +119 -118
- data/lib/rbbt/entity/refactor.rb +12 -0
- data/lib/rbbt/entity.rb +319 -315
- data/lib/rbbt/hpc/batch.rb +72 -53
- data/lib/rbbt/hpc/lsf.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
- data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
- data/lib/rbbt/hpc/orchestrate.rb +19 -13
- data/lib/rbbt/hpc/slurm.rb +18 -18
- data/lib/rbbt/knowledge_base/entity.rb +13 -5
- data/lib/rbbt/knowledge_base/query.rb +2 -2
- data/lib/rbbt/knowledge_base/registry.rb +32 -31
- data/lib/rbbt/knowledge_base/traverse.rb +1 -1
- data/lib/rbbt/knowledge_base.rb +1 -1
- data/lib/rbbt/monitor.rb +36 -25
- data/lib/rbbt/persist/refactor.rb +166 -0
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
- data/lib/rbbt/persist/tsv.rb +187 -185
- data/lib/rbbt/persist.rb +556 -551
- data/lib/rbbt/refactor.rb +20 -0
- data/lib/rbbt/resource/path/refactor.rb +178 -0
- data/lib/rbbt/resource/path.rb +317 -497
- data/lib/rbbt/resource/util.rb +0 -48
- data/lib/rbbt/resource.rb +3 -390
- data/lib/rbbt/tsv/accessor.rb +2 -838
- data/lib/rbbt/tsv/attach.rb +303 -299
- data/lib/rbbt/tsv/change_id.rb +244 -245
- data/lib/rbbt/tsv/csv.rb +87 -85
- data/lib/rbbt/tsv/dumper.rb +2 -100
- data/lib/rbbt/tsv/excel.rb +26 -24
- data/lib/rbbt/tsv/field_index.rb +4 -1
- data/lib/rbbt/tsv/filter.rb +3 -2
- data/lib/rbbt/tsv/index.rb +2 -284
- data/lib/rbbt/tsv/manipulate.rb +750 -747
- data/lib/rbbt/tsv/marshal.rb +3 -3
- data/lib/rbbt/tsv/matrix.rb +2 -2
- data/lib/rbbt/tsv/parallel/through.rb +2 -1
- data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
- data/lib/rbbt/tsv/parser.rb +678 -678
- data/lib/rbbt/tsv/refactor.rb +195 -0
- data/lib/rbbt/tsv/stream.rb +253 -251
- data/lib/rbbt/tsv/util.rb +420 -420
- data/lib/rbbt/tsv.rb +210 -208
- data/lib/rbbt/util/R/eval.rb +4 -4
- data/lib/rbbt/util/R/plot.rb +62 -166
- data/lib/rbbt/util/R.rb +21 -18
- data/lib/rbbt/util/cmd.rb +2 -318
- data/lib/rbbt/util/color.rb +269 -269
- data/lib/rbbt/util/colorize.rb +89 -89
- data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
- data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
- data/lib/rbbt/util/concurrency/processes.rb +389 -386
- data/lib/rbbt/util/config.rb +169 -167
- data/lib/rbbt/util/filecache.rb +1 -1
- data/lib/rbbt/util/iruby.rb +20 -0
- data/lib/rbbt/util/log/progress/report.rb +241 -241
- data/lib/rbbt/util/log/progress/util.rb +99 -99
- data/lib/rbbt/util/log/progress.rb +102 -102
- data/lib/rbbt/util/log/refactor.rb +49 -0
- data/lib/rbbt/util/log.rb +486 -532
- data/lib/rbbt/util/migrate.rb +2 -2
- data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
- data/lib/rbbt/util/misc/development.rb +12 -11
- data/lib/rbbt/util/misc/exceptions.rb +117 -112
- data/lib/rbbt/util/misc/format.rb +2 -230
- data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
- data/lib/rbbt/util/misc/inspect.rb +2 -476
- data/lib/rbbt/util/misc/lock.rb +109 -106
- data/lib/rbbt/util/misc/omics.rb +9 -1
- data/lib/rbbt/util/misc/pipes.rb +765 -793
- data/lib/rbbt/util/misc/refactor.rb +20 -0
- data/lib/rbbt/util/misc/ssw.rb +27 -17
- data/lib/rbbt/util/misc/system.rb +92 -105
- data/lib/rbbt/util/misc.rb +39 -20
- data/lib/rbbt/util/named_array/refactor.rb +4 -0
- data/lib/rbbt/util/named_array.rb +3 -220
- data/lib/rbbt/util/open/refactor.rb +7 -0
- data/lib/rbbt/util/open.rb +3 -857
- data/lib/rbbt/util/procpath.rb +6 -6
- data/lib/rbbt/util/python/paths.rb +27 -0
- data/lib/rbbt/util/python/run.rb +115 -0
- data/lib/rbbt/util/python/script.rb +110 -0
- data/lib/rbbt/util/python/util.rb +3 -3
- data/lib/rbbt/util/python.rb +22 -81
- data/lib/rbbt/util/semaphore.rb +152 -148
- data/lib/rbbt/util/simpleopt.rb +9 -8
- data/lib/rbbt/util/ssh/refactor.rb +19 -0
- data/lib/rbbt/util/ssh.rb +122 -118
- data/lib/rbbt/util/tar.rb +117 -115
- data/lib/rbbt/util/tmpfile.rb +69 -67
- data/lib/rbbt/util/version.rb +2 -0
- data/lib/rbbt/workflow/refactor/entity.rb +11 -0
- data/lib/rbbt/workflow/refactor/export.rb +66 -0
- data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
- data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
- data/lib/rbbt/workflow/refactor/task_info.rb +66 -0
- data/lib/rbbt/workflow/refactor.rb +150 -0
- data/lib/rbbt/workflow/remote_workflow/driver/rest.rb +1 -2
- data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
- data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
- data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
- data/lib/rbbt/workflow/remote_workflow.rb +6 -1
- data/lib/rbbt/workflow/step/run.rb +766 -766
- data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
- data/lib/rbbt/workflow/step.rb +2 -362
- data/lib/rbbt/workflow/task.rb +118 -118
- data/lib/rbbt/workflow/usage.rb +289 -287
- data/lib/rbbt/workflow/util/archive.rb +6 -5
- data/lib/rbbt/workflow/util/data.rb +1 -1
- data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
- data/lib/rbbt/workflow/util/trace.rb +79 -44
- data/lib/rbbt/workflow.rb +4 -882
- data/lib/rbbt-util.rb +21 -13
- data/lib/rbbt.rb +16 -3
- data/python/rbbt/__init__.py +96 -4
- data/python/rbbt/workflow/remote.py +104 -0
- data/python/rbbt/workflow.py +64 -0
- data/python/test.py +10 -0
- data/share/Rlib/plot.R +37 -37
- data/share/Rlib/svg.R +22 -5
- data/share/install/software/lib/install_helpers +1 -1
- data/share/rbbt_commands/hpc/list +2 -3
- data/share/rbbt_commands/hpc/orchestrate +4 -4
- data/share/rbbt_commands/hpc/tail +2 -0
- data/share/rbbt_commands/hpc/task +10 -7
- data/share/rbbt_commands/lsf/list +2 -3
- data/share/rbbt_commands/lsf/orchestrate +4 -4
- data/share/rbbt_commands/lsf/tail +2 -0
- data/share/rbbt_commands/lsf/task +10 -7
- data/share/rbbt_commands/migrate +1 -1
- data/share/rbbt_commands/pbs/list +2 -3
- data/share/rbbt_commands/pbs/orchestrate +4 -4
- data/share/rbbt_commands/pbs/tail +2 -0
- data/share/rbbt_commands/pbs/task +10 -7
- data/share/rbbt_commands/resource/produce +8 -1
- data/share/rbbt_commands/slurm/list +2 -3
- data/share/rbbt_commands/slurm/orchestrate +4 -4
- data/share/rbbt_commands/slurm/tail +2 -0
- data/share/rbbt_commands/slurm/task +10 -7
- data/share/rbbt_commands/system/clean +5 -5
- data/share/rbbt_commands/system/status +5 -5
- data/share/rbbt_commands/tsv/get +2 -3
- data/share/rbbt_commands/tsv/info +10 -13
- data/share/rbbt_commands/tsv/keys +18 -14
- data/share/rbbt_commands/tsv/slice +2 -2
- data/share/rbbt_commands/tsv/transpose +6 -2
- data/share/rbbt_commands/workflow/info +20 -24
- data/share/rbbt_commands/workflow/list +1 -1
- data/share/rbbt_commands/workflow/prov +20 -13
- data/share/rbbt_commands/workflow/retry +43 -0
- data/share/rbbt_commands/workflow/server +12 -2
- data/share/rbbt_commands/workflow/task +80 -73
- data/share/rbbt_commands/workflow/write_info +26 -9
- data/share/software/opt/ssw/ssw.c +861 -0
- data/share/software/opt/ssw/ssw.h +130 -0
- data/share/workflow_config.ru +3 -3
- metadata +45 -6
data/lib/rbbt-util.rb
CHANGED
@@ -1,18 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
Open.
|
1
|
+
require_relative 'rbbt'
|
2
|
+
require_relative 'rbbt/util/misc'
|
3
|
+
require 'scout/open'
|
4
|
+
Open.remote_cache_dir = Rbbt.var.cache["open-remote"].find :user
|
5
5
|
|
6
|
-
require '
|
7
|
-
Persist.cachedir = Rbbt.var.cache.persistence
|
6
|
+
require 'scout/path'
|
8
7
|
|
9
|
-
require '
|
10
|
-
|
8
|
+
require 'set'
|
9
|
+
require 'scout/persist'
|
11
10
|
|
12
|
-
require '
|
13
|
-
TmpFile.tmpdir = Rbbt.tmp.find :user
|
11
|
+
require 'scout/resource'
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
require_relative 'rbbt/util/filecache'
|
14
|
+
|
15
|
+
require_relative 'rbbt/util/tmpfile'
|
16
|
+
|
17
|
+
require_relative 'rbbt/util/cmd'
|
18
|
+
require_relative 'rbbt/tsv'
|
19
|
+
|
20
|
+
require_relative 'rbbt/workflow'
|
21
|
+
|
22
|
+
Persist.cache_dir = Rbbt.var.cache.persistence
|
23
|
+
FileCache.cachedir = Rbbt.var.cache.filecache.find
|
24
|
+
TmpFile.tmpdir = Rbbt.tmp.find
|
25
|
+
Resource.default_resource = Rbbt
|
17
26
|
|
18
|
-
require 'rbbt/util/config'
|
data/lib/rbbt.rb
CHANGED
@@ -1,7 +1,20 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.unshift File.join(__dir__)
|
2
|
+
$LOAD_PATH.unshift File.join(__dir__, '../../lib')
|
3
|
+
|
4
|
+
require 'scout/path'
|
5
|
+
require 'scout/resource'
|
6
|
+
Path.add_path :rbbt_util, File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}")
|
2
7
|
module Rbbt
|
3
8
|
extend Resource
|
4
|
-
|
9
|
+
|
10
|
+
self.pkgdir = 'rbbt'
|
5
11
|
end
|
12
|
+
Path.default_pkgdir = Rbbt
|
13
|
+
Resource.set_software_env Rbbt.software
|
14
|
+
|
15
|
+
require_relative 'rbbt/util/version'
|
16
|
+
require 'scout/log'
|
17
|
+
require_relative 'rbbt/refactor'
|
6
18
|
|
7
|
-
require '
|
19
|
+
require 'scout/config'
|
20
|
+
Rbbt::Config = Scout::Config
|
data/python/rbbt/__init__.py
CHANGED
@@ -1,22 +1,29 @@
|
|
1
|
-
import warnings
|
2
1
|
import sys
|
3
2
|
import os
|
4
3
|
import subprocess
|
4
|
+
import tempfile
|
5
|
+
import shutil
|
6
|
+
import pandas
|
7
|
+
import numpy
|
5
8
|
|
6
|
-
|
9
|
+
|
10
|
+
def cmd(cmd=None):
|
7
11
|
if cmd is None:
|
8
12
|
print("Rbbt")
|
9
13
|
else:
|
10
14
|
return subprocess.run('rbbt_exec.rb', input=cmd.encode('utf-8'), capture_output=True).stdout.decode()
|
11
15
|
|
16
|
+
|
12
17
|
def libdir():
|
13
|
-
return
|
18
|
+
return cmd('puts Rbbt.find(:lib)').rstrip()
|
19
|
+
|
14
20
|
|
15
21
|
def add_libdir():
|
16
22
|
pythondir = os.path.join(libdir(), 'python')
|
17
23
|
sys.path.insert(0, pythondir)
|
18
24
|
|
19
|
-
|
25
|
+
|
26
|
+
def path(subdir=None, base_dir=None):
|
20
27
|
from pathlib import Path
|
21
28
|
import os
|
22
29
|
|
@@ -52,6 +59,15 @@ def log_tsv(tsv):
|
|
52
59
|
print(tsv)
|
53
60
|
print(tsv.keys())
|
54
61
|
|
62
|
+
def benchmark():
|
63
|
+
import time
|
64
|
+
tic: float = time.perf_counter()
|
65
|
+
try:
|
66
|
+
yield
|
67
|
+
finally:
|
68
|
+
toc: float = time.perf_counter()
|
69
|
+
print(f"Computation time = {1000*(toc - tic):.3f}ms")
|
70
|
+
|
55
71
|
def tsv_preamble(line, comment_char="#"):
|
56
72
|
import re
|
57
73
|
header = dict()
|
@@ -127,3 +143,79 @@ def tsv_pandas(filename, sep="\t", comment_char="#", index_col=0, **kwargs):
|
|
127
143
|
def tsv(*args, **kwargs):
|
128
144
|
return tsv_pandas(*args, **kwargs)
|
129
145
|
|
146
|
+
def save_tsv(filename, df, key=None):
|
147
|
+
if (key == None):
|
148
|
+
key = df.index.name
|
149
|
+
if (key == None):
|
150
|
+
key = "Key"
|
151
|
+
key = "#" + key
|
152
|
+
df.to_csv(filename, sep="\t", index_label=key)
|
153
|
+
|
154
|
+
def save_job_inputs(data):
|
155
|
+
temp_dir = tempfile.mkdtemp() # Create a temporary directory
|
156
|
+
|
157
|
+
for name, value in data.items():
|
158
|
+
file_path = os.path.join(temp_dir, name)
|
159
|
+
|
160
|
+
if isinstance(value, str):
|
161
|
+
file_path += ".txt"
|
162
|
+
with open(file_path, "w") as f:
|
163
|
+
f.write(value)
|
164
|
+
|
165
|
+
elif isinstance(value, (bool)):
|
166
|
+
with open(file_path, "w") as f:
|
167
|
+
if value:
|
168
|
+
f.write('true')
|
169
|
+
else:
|
170
|
+
f.write('false')
|
171
|
+
|
172
|
+
elif isinstance(value, (int, float)):
|
173
|
+
with open(file_path, "w") as f:
|
174
|
+
f.write(str(value))
|
175
|
+
|
176
|
+
elif isinstance(value, pandas.DataFrame):
|
177
|
+
file_path += ".tsv"
|
178
|
+
save_tsv(file_path, value)
|
179
|
+
|
180
|
+
elif isinstance(value, numpy.ndarray) or isinstance(value, list):
|
181
|
+
file_path += ".list"
|
182
|
+
with open(file_path, "w") as f:
|
183
|
+
f.write("\n".join(value))
|
184
|
+
|
185
|
+
else:
|
186
|
+
raise TypeError(f"Unsupported data type for argument '{name}': {type(value)}")
|
187
|
+
|
188
|
+
return temp_dir
|
189
|
+
|
190
|
+
|
191
|
+
def run_job(workflow, task, name='Default', fork=False, clean=False, **kwargs):
|
192
|
+
inputs_dir = save_job_inputs(kwargs)
|
193
|
+
cmd = ['rbbt', 'workflow', 'task', workflow, task, '--jobname', name, '--load_inputs', inputs_dir, '--nocolor']
|
194
|
+
|
195
|
+
if fork:
|
196
|
+
cmd.append('--fork')
|
197
|
+
cmd.append('--detach')
|
198
|
+
|
199
|
+
if clean:
|
200
|
+
if clean == 'recursive':
|
201
|
+
cmd.append('--recursive_clean')
|
202
|
+
else:
|
203
|
+
cmd.append('--clean')
|
204
|
+
|
205
|
+
proc = subprocess.run(
|
206
|
+
cmd,
|
207
|
+
capture_output=True, # Capture both stdout and stderr
|
208
|
+
text=True # Automatically decode outputs to strings
|
209
|
+
)
|
210
|
+
shutil.rmtree(inputs_dir)
|
211
|
+
if proc.returncode != 0:
|
212
|
+
output = proc.stderr.strip()
|
213
|
+
if output == '' :
|
214
|
+
output = proc.stdout.strip()
|
215
|
+
raise RuntimeError(output) # Raise error with cleaned stderr content
|
216
|
+
return proc.stdout.strip()
|
217
|
+
|
218
|
+
if __name__ == "__main__":
|
219
|
+
import json
|
220
|
+
res = run_job('Baking', 'bake_muffin_tray', 'test', add_blueberries=True, fork=True)
|
221
|
+
print(res)
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import requests
|
2
|
+
import logging
|
3
|
+
import json
|
4
|
+
from urllib.parse import urlencode, urljoin
|
5
|
+
from time import sleep
|
6
|
+
import itertools
|
7
|
+
|
8
|
+
def request_post(url, params):
|
9
|
+
response = requests.post(url, params)
|
10
|
+
return response
|
11
|
+
|
12
|
+
def request_get(url, params):
|
13
|
+
query = urlencode(params)
|
14
|
+
full_url = f"{url}?{query}"
|
15
|
+
response = requests.get(full_url)
|
16
|
+
return response
|
17
|
+
|
18
|
+
def get_json(url, params={}):
|
19
|
+
params['_format'] = 'json'
|
20
|
+
response = request_get(url, params)
|
21
|
+
if response.status_code == 200:
|
22
|
+
return json.loads(response.content) # parse the JSON content from the response
|
23
|
+
else:
|
24
|
+
logging.error("Failed to initialize remote tasks")
|
25
|
+
|
26
|
+
def get_raw(url, params={}):
|
27
|
+
params['_format'] = 'raw'
|
28
|
+
response = request_get(url, params)
|
29
|
+
if response.status_code == 200:
|
30
|
+
return response.content # parse the JSON content from the response
|
31
|
+
else:
|
32
|
+
logging.error("Failed to initialize remote tasks")
|
33
|
+
|
34
|
+
def join(url, *subpaths):
|
35
|
+
return url + "/" + "/".join(subpaths)
|
36
|
+
|
37
|
+
class RemoteStep:
|
38
|
+
def __init__(self, url):
|
39
|
+
self.url = url
|
40
|
+
|
41
|
+
def info(self):
|
42
|
+
return get_json(join(self.url, 'info'))
|
43
|
+
def status(self):
|
44
|
+
return self.info()['status']
|
45
|
+
|
46
|
+
def done(self):
|
47
|
+
return self.status() == 'done'
|
48
|
+
|
49
|
+
def error(self):
|
50
|
+
return self.status() == 'error' or self.status() == 'aborted'
|
51
|
+
|
52
|
+
def running(self):
|
53
|
+
return not (self.done() or self.error())
|
54
|
+
|
55
|
+
def wait(self, time=1):
|
56
|
+
while self.running():
|
57
|
+
sleep(time)
|
58
|
+
|
59
|
+
|
60
|
+
def raw(self):
|
61
|
+
return get_raw(self.url)
|
62
|
+
|
63
|
+
def json(self):
|
64
|
+
return get_json(self.url)
|
65
|
+
|
66
|
+
class RemoteWorkflow:
|
67
|
+
def __init__(self, url):
|
68
|
+
self.url = url
|
69
|
+
self.task_exports = {}
|
70
|
+
self.init_remote_tasks()
|
71
|
+
|
72
|
+
def init_remote_tasks(self):
|
73
|
+
self.task_exports = get_json(self.url)
|
74
|
+
self.tasks = []
|
75
|
+
self.tasks += self.task_exports['asynchronous']
|
76
|
+
self.tasks += self.task_exports['synchronous']
|
77
|
+
self.tasks += self.task_exports['exec']
|
78
|
+
|
79
|
+
def task_info(self, name):
|
80
|
+
return get_json(join(self.url, name, '/info'))
|
81
|
+
|
82
|
+
def job(self, task, **kwargs):
|
83
|
+
kwargs['_format'] = 'jobname'
|
84
|
+
response = request_post(join(self.url, task), kwargs)
|
85
|
+
if response.status_code == 200:
|
86
|
+
jobname = response.content.decode('utf-8')
|
87
|
+
step_url = join(self.url, task, jobname)
|
88
|
+
print(step_url)
|
89
|
+
return RemoteStep(step_url)
|
90
|
+
else:
|
91
|
+
logging.error("Failed to initialize remote tasks")
|
92
|
+
|
93
|
+
|
94
|
+
if __name__ == "__main__":
|
95
|
+
wf = RemoteWorkflow('http://localhost:1900/Baking')
|
96
|
+
print(wf.tasks)
|
97
|
+
print(wf.task_info('bake_muffin_tray'))
|
98
|
+
|
99
|
+
step = wf.job('bake_muffin_tray', add_blueberries=True)
|
100
|
+
step.wait()
|
101
|
+
print(step.json())
|
102
|
+
|
103
|
+
|
104
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
from . import cmd, run_job
|
2
|
+
import subprocess
|
3
|
+
import json
|
4
|
+
import time
|
5
|
+
|
6
|
+
def save_inputs(directory, inputs, types):
|
7
|
+
return
|
8
|
+
|
9
|
+
class Workflow:
|
10
|
+
def __init__(self, name):
|
11
|
+
self.name = name
|
12
|
+
|
13
|
+
def tasks(self):
|
14
|
+
ruby=f'Workflow.require_workflow("{self.name}").tasks.keys * "\n"'
|
15
|
+
return cmd(ruby).strip().split("\n")
|
16
|
+
|
17
|
+
def task_info(self, name):
|
18
|
+
ruby=f'Workflow.require_workflow("{self.name}").task_info("{name}").to_json'
|
19
|
+
return cmd(ruby)
|
20
|
+
|
21
|
+
def run(self, task, **kwargs):
|
22
|
+
return run_job(self.name, task, **kwargs)
|
23
|
+
|
24
|
+
def fork(self, task, **kwargs):
|
25
|
+
path = run_job(self.name, task, fork=True, **kwargs)
|
26
|
+
return Step(path)
|
27
|
+
|
28
|
+
class Step:
|
29
|
+
def __init__(self, path):
|
30
|
+
self.path = path
|
31
|
+
self.info_content = None
|
32
|
+
|
33
|
+
def info(self):
|
34
|
+
if self.info_content:
|
35
|
+
return self.info_content
|
36
|
+
ruby=f'puts Step.load("{self.path}").info.to_json'
|
37
|
+
txt = cmd(ruby)
|
38
|
+
info_content = json.loads(txt)
|
39
|
+
status = info_content["status"]
|
40
|
+
if status == "done" or status == "error" or status == "aborted":
|
41
|
+
self.info_content = info_content
|
42
|
+
return info_content
|
43
|
+
|
44
|
+
def status(self):
|
45
|
+
return self.info()["status"]
|
46
|
+
|
47
|
+
def done(self):
|
48
|
+
return self.status() == 'done'
|
49
|
+
|
50
|
+
def error(self):
|
51
|
+
return self.status() == 'error'
|
52
|
+
|
53
|
+
def aborted(self):
|
54
|
+
return self.status() == 'aborted'
|
55
|
+
|
56
|
+
def join(self):
|
57
|
+
while not (self.done() or self.error() or self.aborted()):
|
58
|
+
time.sleep(1)
|
59
|
+
|
60
|
+
def load(self):
|
61
|
+
ruby=f'puts Step.load("{self.path}").load.to_json'
|
62
|
+
txt = cmd(ruby)
|
63
|
+
return json.loads(txt)
|
64
|
+
|
data/python/test.py
ADDED
data/share/Rlib/plot.R
CHANGED
@@ -1,42 +1,42 @@
|
|
1
1
|
rbbt.require('ggplot2')
|
2
2
|
|
3
|
-
geom_entity <- function (real.geom = NULL, mapping = NULL, data = NULL, stat = "identity",
|
4
|
-
position = "identity", ...) {
|
5
|
-
rg <- real.geom(mapping = mapping, data = data, stat = stat,
|
6
|
-
position = position, ...)
|
7
|
-
|
8
|
-
rg$geom <-
|
9
|
-
draw <- function(., data, ...) {
|
10
|
-
grobs <- list()
|
11
|
-
|
12
|
-
for (i in 1:nrow(data)) {
|
13
|
-
grob <- .super$draw(., data[i,], ...)
|
14
|
-
if (is.null(data$entity.type))
|
15
|
-
grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity)
|
16
|
-
else
|
17
|
-
grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity, `data-entity-type`=data[i,]$entity.type)
|
18
|
-
}
|
19
|
-
|
20
|
-
ggplot2:::ggname("geom_entity", gTree(children = do.call("gList", grobs)))
|
21
|
-
}
|
22
|
-
|
23
|
-
draw_groups <- function(., data, ...) {
|
24
|
-
grobs <- list()
|
25
|
-
|
26
|
-
for (i in 1:nrow(data)) {
|
27
|
-
grob <- .super$draw_groups(., data[i,], ...)
|
28
|
-
if (is.null(data$entity.type))
|
29
|
-
grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity)
|
30
|
-
else
|
31
|
-
grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity, `data-entity-type`=data[i,]$entity.type)
|
32
|
-
}
|
33
|
-
|
34
|
-
ggplot2:::ggname("geom_entity", gTree(children = do.call("gList", grobs)))
|
35
|
-
}
|
36
|
-
})
|
37
|
-
|
38
|
-
rg
|
39
|
-
}
|
3
|
+
#geom_entity <- function (real.geom = NULL, mapping = NULL, data = NULL, stat = "identity",
|
4
|
+
# position = "identity", ...) {
|
5
|
+
# rg <- real.geom(mapping = mapping, data = data, stat = stat,
|
6
|
+
# position = position, ...)
|
7
|
+
#
|
8
|
+
# rg$geom <- ggproto(rg$geom, {
|
9
|
+
# draw <- function(., data, ...) {
|
10
|
+
# grobs <- list()
|
11
|
+
#
|
12
|
+
# for (i in 1:nrow(data)) {
|
13
|
+
# grob <- .super$draw(., data[i,], ...)
|
14
|
+
# if (is.null(data$entity.type))
|
15
|
+
# grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity)
|
16
|
+
# else
|
17
|
+
# grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity, `data-entity-type`=data[i,]$entity.type)
|
18
|
+
# }
|
19
|
+
#
|
20
|
+
# ggplot2:::ggname("geom_entity", gTree(children = do.call("gList", grobs)))
|
21
|
+
# }
|
22
|
+
#
|
23
|
+
# draw_groups <- function(., data, ...) {
|
24
|
+
# grobs <- list()
|
25
|
+
#
|
26
|
+
# for (i in 1:nrow(data)) {
|
27
|
+
# grob <- .super$draw_groups(., data[i,], ...)
|
28
|
+
# if (is.null(data$entity.type))
|
29
|
+
# grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity)
|
30
|
+
# else
|
31
|
+
# grobs[[i]] <- garnishGrob(grob, `data-entity`=data[i,]$entity, `data-entity-type`=data[i,]$entity.type)
|
32
|
+
# }
|
33
|
+
#
|
34
|
+
# ggplot2:::ggname("geom_entity", gTree(children = do.call("gList", grobs)))
|
35
|
+
# }
|
36
|
+
# })
|
37
|
+
#
|
38
|
+
# rg
|
39
|
+
#}
|
40
40
|
|
41
41
|
rbbt.ggplot2.rotate_x_labels <- function(){ theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1)) }
|
42
42
|
|
data/share/Rlib/svg.R
CHANGED
@@ -9,12 +9,17 @@ rbbt.require('Cairo')
|
|
9
9
|
|
10
10
|
# Modified from http://aaronecay.com/blog/2014/02/tooltips-in-ggplot/
|
11
11
|
|
12
|
-
rbbt.SVG.extract <- function(plot, size=NULL, prefix=NULL, ...){
|
12
|
+
rbbt.SVG.extract <- function(plot, size=NULL, prefix=NULL, entity.geom='geom_point', data=NULL, ...){
|
13
|
+
|
14
|
+
if (is.null(data)) data = plot$data;
|
13
15
|
|
14
16
|
if (is.null(prefix)) prefix = rbbt.random_string();
|
17
|
+
|
18
|
+
if (!endsWith(prefix, '.'))
|
19
|
+
prefix = paste(prefix, ".", sep="")
|
20
|
+
|
15
21
|
if (is.null(size)){
|
16
22
|
print(plot, type='cairo');
|
17
|
-
mysvg <- grid.export(prefix=prefix, ...)
|
18
23
|
}else{
|
19
24
|
base.size = 10 * (7/size)
|
20
25
|
resolution = 72 * (size/7)
|
@@ -25,11 +30,23 @@ rbbt.SVG.extract <- function(plot, size=NULL, prefix=NULL, ...){
|
|
25
30
|
|
26
31
|
if (is.null(plot$theme$text$size))
|
27
32
|
plot$theme$text$size = base.size
|
28
|
-
|
29
|
-
print(plot, type='cairo')
|
30
|
-
mysvg <- grid.export(res=resolution, prefix=prefix, ...)
|
33
|
+
print(plot, type='cairo');
|
31
34
|
}
|
32
35
|
|
36
|
+
grid.force()
|
37
|
+
|
38
|
+
if (!is.null(data[["Entity"]]))
|
39
|
+
grid.garnish(entity.geom, 'data-entity'= data[["Entity"]], group = FALSE, grep = TRUE, redraw = TRUE)
|
40
|
+
else
|
41
|
+
grid.garnish(entity.geom, 'data-entity'= rownames(data), group = FALSE, grep = TRUE, redraw = TRUE)
|
42
|
+
|
43
|
+
if (!is.null(data[["Entity type"]]))
|
44
|
+
grid.garnish(entity.geom, 'data-entity_type' = data[["Entity type"]], group = FALSE, grep = TRUE, redraw = TRUE)
|
45
|
+
else if (!is.null(attributes(data)$key.field))
|
46
|
+
grid.garnish(entity.geom, 'data-entity_type' = rep(attributes(data)$key.field, length(rownames(data))), group = FALSE, grep = TRUE, redraw = TRUE)
|
47
|
+
|
48
|
+
mysvg <- grid.export(prefix=prefix, strict = FALSE, ...)
|
49
|
+
|
33
50
|
xml <- saveXML(mysvg$svg)
|
34
51
|
xml
|
35
52
|
}
|
@@ -10,7 +10,7 @@ OPT_BUILD_DIR="$SOFTWARE_DIR/.build"; [ -d $OPT_BUILD_DIR ] || mkdir -p $OPT_BUI
|
|
10
10
|
|
11
11
|
mkdir -p "$OPT_BUILD_DIR"
|
12
12
|
|
13
|
-
if realpath --help | grep
|
13
|
+
if (command -v realpath && realpath --help | grep relative) > /dev/null; then
|
14
14
|
function relative_path(){
|
15
15
|
local basedir=$1
|
16
16
|
local path=$2
|
@@ -206,7 +206,6 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
206
206
|
require 'rbbt/workflow'
|
207
207
|
step_path = step_line.split(": ").last.strip
|
208
208
|
step = Step.new step_path
|
209
|
-
step.load_dependencies_from_info
|
210
209
|
has_bar = false
|
211
210
|
[step].reverse.each do |j|
|
212
211
|
next if j.done?
|
@@ -218,6 +217,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
218
217
|
prog_rep << [rep]
|
219
218
|
end
|
220
219
|
end
|
220
|
+
prog_rep = [Log.color(step.status, step.status)] if prog_rep.empty?
|
221
221
|
end
|
222
222
|
end
|
223
223
|
workflow, task, name = step_path.split("/")[-3..-1]
|
@@ -321,7 +321,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
321
321
|
if tail && File.exist?(File.join(dir, 'std.err'))
|
322
322
|
if exit_status && exit_status != 0
|
323
323
|
puts Log.color(:magenta, "First error or exception found: ")
|
324
|
-
puts CMD.cmd("grep -i
|
324
|
+
puts CMD.cmd("grep -i 'error\\|exception' #{File.join(dir, 'std.err')} -A #{tail.to_i} |head -n #{tail.to_i}", :no_fail => true).read
|
325
325
|
elsif exit_status
|
326
326
|
puts Log.color(:magenta, "Completed jobs: ")
|
327
327
|
puts CMD.cmd("grep -i -w 'Completed step' #{File.join(dir, 'std.err')} | grep -v 'Retrying dep.' | tail -n #{tail.to_i}", :no_fail => true).read
|
@@ -337,7 +337,6 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
337
337
|
require 'rbbt/workflow'
|
338
338
|
step_path = step_line.split(": ").last.strip
|
339
339
|
step = Step.new step_path
|
340
|
-
step.load_dependencies_from_info
|
341
340
|
has_bar = false
|
342
341
|
(step.rec_dependencies + [step]).reverse.each do |j|
|
343
342
|
next if j.done?
|
@@ -18,9 +18,9 @@ $slurm_options = SOPT.get <<EOF
|
|
18
18
|
-si--singularity_img* Singularity image to use
|
19
19
|
-sm--singularity_mounts* Singularity image to use
|
20
20
|
-ug--user_group* Use alternative user group for group project directory
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
--contain* Contain in directory (using Singularity)
|
22
|
+
--sync* Contain in directory and sync jobs
|
23
|
+
--exclusive Make exclusive use of the node
|
24
24
|
-hm--highmem Make use of highmem cores
|
25
25
|
-wc--wipe_container* Wipe the jobs from the contain directory
|
26
26
|
-pd--purge_deps Purge job dependencies
|
@@ -57,7 +57,7 @@ raise ParameterException.new("Could not detect batch_system: #{Misc.fingerprint
|
|
57
57
|
|
58
58
|
class Step
|
59
59
|
def join
|
60
|
-
HPC::BATCH_MODULE.wait_for_job(@batch_job_dir)
|
60
|
+
HPC::BATCH_MODULE.wait_for_job(@batch_job_dir) unless done?
|
61
61
|
end
|
62
62
|
|
63
63
|
def run(no_load = true)
|
@@ -9,7 +9,7 @@ require 'time'
|
|
9
9
|
|
10
10
|
rbbt_options = SOPT::GOT_OPTIONS
|
11
11
|
|
12
|
-
$
|
12
|
+
$batch_options = SOPT.get <<EOF
|
13
13
|
-dr--dry_run Print only the template
|
14
14
|
-cj--clean_job Clean job
|
15
15
|
--drbbt* Use development version of rbbt
|
@@ -17,9 +17,9 @@ $slurm_options = SOPT.get <<EOF
|
|
17
17
|
-si--singularity_img* Singularity image to use
|
18
18
|
-sm--singularity_mounts* Singularity image to use
|
19
19
|
-ug--user_group* Use alternative user group for group project directory
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
--contain* Contain in directory (using Singularity)
|
21
|
+
--sync* Contain in directory and sync jobs
|
22
|
+
--exclusive Make exclusive use of the node
|
23
23
|
-hm--highmem Make use of highmem cores
|
24
24
|
-wc--wipe_container* Wipe the jobs from the contain directory
|
25
25
|
-pd--purge_deps Purge job dependencies
|
@@ -45,11 +45,14 @@ $slurm_options = SOPT.get <<EOF
|
|
45
45
|
-OR--orchestration_rules* Orchestration rules
|
46
46
|
EOF
|
47
47
|
|
48
|
-
batch_system = $
|
48
|
+
batch_system = $batch_options.delete :batch_system
|
49
49
|
batch_system ||= 'auto'
|
50
|
+
$batch_options[:log] = rbbt_options[:log]
|
51
|
+
$batch_options[:config_keys] = rbbt_options[:config_keys]
|
50
52
|
|
51
53
|
HPC::BATCH_MODULE = HPC.batch_system batch_system
|
52
54
|
|
55
|
+
|
53
56
|
raise ParameterException.new("Could not detect batch_system: #{Misc.fingerprint batch_system}") if HPC::BATCH_MODULE.nil?
|
54
57
|
|
55
58
|
class Step
|
@@ -60,7 +63,7 @@ class Step
|
|
60
63
|
else
|
61
64
|
begin
|
62
65
|
Log.debug "Issuing BATCH job for #{self.path}"
|
63
|
-
HPC::BATCH_MODULE.run_job(self, $
|
66
|
+
HPC::BATCH_MODULE.run_job(self, $batch_options)
|
64
67
|
rescue HPC::BATCH_DRY_RUN
|
65
68
|
end
|
66
69
|
end
|
@@ -70,7 +73,7 @@ end
|
|
70
73
|
module RemoteStep::SSH
|
71
74
|
|
72
75
|
def _run
|
73
|
-
RemoteWorkflow::SSH.run_slurm_job(File.join(base_url, task.to_s), @input_id, @base_name, $
|
76
|
+
RemoteWorkflow::SSH.run_slurm_job(File.join(base_url, task.to_s), @input_id, @base_name, $batch_options)
|
74
77
|
end
|
75
78
|
|
76
79
|
end
|
@@ -206,7 +206,6 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
206
206
|
require 'rbbt/workflow'
|
207
207
|
step_path = step_line.split(": ").last.strip
|
208
208
|
step = Step.new step_path
|
209
|
-
step.load_dependencies_from_info
|
210
209
|
has_bar = false
|
211
210
|
[step].reverse.each do |j|
|
212
211
|
next if j.done?
|
@@ -218,6 +217,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
218
217
|
prog_rep << [rep]
|
219
218
|
end
|
220
219
|
end
|
220
|
+
prog_rep = [Log.color(step.status, step.status)] if prog_rep.empty?
|
221
221
|
end
|
222
222
|
end
|
223
223
|
workflow, task, name = step_path.split("/")[-3..-1]
|
@@ -321,7 +321,7 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
321
321
|
if tail && File.exist?(File.join(dir, 'std.err'))
|
322
322
|
if exit_status && exit_status != 0
|
323
323
|
puts Log.color(:magenta, "First error or exception found: ")
|
324
|
-
puts CMD.cmd("grep -i
|
324
|
+
puts CMD.cmd("grep -i 'error\\|exception' #{File.join(dir, 'std.err')} -A #{tail.to_i} |head -n #{tail.to_i}", :no_fail => true).read
|
325
325
|
elsif exit_status
|
326
326
|
puts Log.color(:magenta, "Completed jobs: ")
|
327
327
|
puts CMD.cmd("grep -i -w 'Completed step' #{File.join(dir, 'std.err')} | grep -v 'Retrying dep.' | tail -n #{tail.to_i}", :no_fail => true).read
|
@@ -337,7 +337,6 @@ workdir.glob("**/command.batch").sort_by{|f| File.mtime(f)}.each do |fcmd|
|
|
337
337
|
require 'rbbt/workflow'
|
338
338
|
step_path = step_line.split(": ").last.strip
|
339
339
|
step = Step.new step_path
|
340
|
-
step.load_dependencies_from_info
|
341
340
|
has_bar = false
|
342
341
|
(step.rec_dependencies + [step]).reverse.each do |j|
|
343
342
|
next if j.done?
|