scout-gear 10.1.0 → 10.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vimproject +49 -3
- data/VERSION +1 -1
- data/lib/scout/tsv/transformer.rb +17 -13
- data/lib/scout/tsv/util/melt.rb +13 -0
- data/lib/scout/tsv/util.rb +1 -0
- data/lib/scout/tsv.rb +7 -4
- data/lib/scout/workflow/definition.rb +10 -4
- data/lib/scout/workflow/step/dependencies.rb +1 -1
- data/lib/scout/workflow/step/file.rb +2 -1
- data/lib/scout/workflow/step/provenance.rb +2 -2
- data/lib/scout/workflow/step/status.rb +4 -4
- data/lib/scout/workflow/step.rb +11 -2
- data/lib/scout/workflow/task/inputs.rb +6 -2
- data/lib/scout/workflow/usage.rb +4 -2
- data/lib/scout/workflow/util.rb +5 -0
- data/scout-gear.gemspec +12 -4
- data/scout_commands/batch/clean +211 -0
- data/scout_commands/batch/list +357 -0
- data/scout_commands/log +45 -0
- data/scout_commands/rbbt +2 -1
- data/scout_commands/workflow/prov +133 -0
- data/scout_commands/workflow/task +6 -5
- data/scout_commands/workflow/trace +49 -0
- data/scout_commands/workflow/write_info +69 -0
- data/test/scout/offsite/test_ssh.rb +1 -1
- data/test/scout/test_tsv.rb +21 -0
- data/test/scout/tsv/util/test_melt.rb +28 -0
- metadata +11 -3
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
|
5
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
6
|
+
|
7
|
+
options = SOPT.setup <<EOF
|
8
|
+
|
9
|
+
Examine the provenance of a job result
|
10
|
+
|
11
|
+
$ #{$0} [<options>] <filename> [<other|->]*
|
12
|
+
|
13
|
+
-h--help Help
|
14
|
+
-p--plot* draw the dependency plot into <file.png>
|
15
|
+
-i--inputs* List of inputs to print
|
16
|
+
-if--info_fields* List of info fields to print
|
17
|
+
-t--touch Update modification times to be consistent
|
18
|
+
-e--expand_repeats Show all the dependency tree even if reapeated dependencies have already been seen before
|
19
|
+
EOF
|
20
|
+
if options[:help]
|
21
|
+
if defined? scout_usage
|
22
|
+
scout_usage
|
23
|
+
else
|
24
|
+
puts SOPT.doc
|
25
|
+
end
|
26
|
+
exit 0
|
27
|
+
end
|
28
|
+
|
29
|
+
$inputs = (options[:inputs] || "").split(",")
|
30
|
+
$info_fields = (options[:info_fields] || "").split(",")
|
31
|
+
|
32
|
+
file = ARGV.shift
|
33
|
+
|
34
|
+
$seen = []
|
35
|
+
def get_step(file)
|
36
|
+
file = File.expand_path(file) if File.exist?(file)
|
37
|
+
file = file.sub(/\.(info|files)$/,'')
|
38
|
+
$seen << file
|
39
|
+
Step.new file
|
40
|
+
end
|
41
|
+
|
42
|
+
def touch(step)
|
43
|
+
return unless File.exist?(step.path)
|
44
|
+
step.dependencies.each do |dep|
|
45
|
+
next unless Open.exists?(dep.path)
|
46
|
+
if Open.mtime(dep.path) > Open.mtime(step.path) + 1
|
47
|
+
Log.debug("Updating #{step.path} to #{dep.path}")
|
48
|
+
Open.update_mtime(dep.path, step.path)
|
49
|
+
end
|
50
|
+
touch(dep)
|
51
|
+
end if step.dependencies
|
52
|
+
end
|
53
|
+
|
54
|
+
step = get_step file
|
55
|
+
$main_mtime = Open.exist?(step.path) ? Open.mtime(step.path) : nil
|
56
|
+
|
57
|
+
def adjacency(step)
|
58
|
+
|
59
|
+
info = step.info || {}
|
60
|
+
path = step.path
|
61
|
+
status = info[:status] || :missing
|
62
|
+
status = "remote" if Open.remote?(path)
|
63
|
+
if status == 'remote'
|
64
|
+
workflow, task, name = path.sub(/\{.*/,'').split("/")[-3..-1]
|
65
|
+
else
|
66
|
+
workflow, task, name = path.split("/")[-3..-1]
|
67
|
+
end
|
68
|
+
name = name.split(":").last
|
69
|
+
status = :unsync if status == :done and not Open.exist? path
|
70
|
+
shapes = Hash.new "circle"
|
71
|
+
edge_info = {:status => status, :workflow => workflow, :task => task, :name => name, :label => task, :shape => shapes[workflow], :color => status == 'remote' ? 'blue' : 'green'}
|
72
|
+
id = Misc.digest(path)
|
73
|
+
edges = []
|
74
|
+
node_info = {}
|
75
|
+
node_info[id] = edge_info
|
76
|
+
if info[:dependencies]
|
77
|
+
info[:dependencies].each do |task,name,path|
|
78
|
+
dep = get_step path
|
79
|
+
_id, _edges, _node_info = adjacency(dep)
|
80
|
+
edges << [_id, id]
|
81
|
+
edges.concat _edges
|
82
|
+
node_info.merge!(_node_info)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
[id, edges, node_info]
|
87
|
+
end
|
88
|
+
|
89
|
+
if options[:touch]
|
90
|
+
touch(step)
|
91
|
+
end
|
92
|
+
|
93
|
+
if options[:plot]
|
94
|
+
id, edges, node_info = adjacency(step)
|
95
|
+
node_info[id][:color] = 'red'
|
96
|
+
TmpFile.with_file do |edge_file|
|
97
|
+
Open.write(edge_file) do |f|
|
98
|
+
f.puts "from,to"
|
99
|
+
edges.uniq.each do |from,to|
|
100
|
+
f.puts [from,to]*","
|
101
|
+
end
|
102
|
+
end
|
103
|
+
TmpFile.with_file do |node_info_file|
|
104
|
+
Open.write(node_info_file) do |f|
|
105
|
+
fields = node_info.first.last.keys
|
106
|
+
f.puts "id," + fields * ","
|
107
|
+
node_info.each do |id,info|
|
108
|
+
f.puts ([id] + info.values_at(*fields)) * ","
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
require 'rbbt/util/R'
|
113
|
+
|
114
|
+
R.run <<-EOF
|
115
|
+
nodes <- read.csv("#{node_info_file}", header=T, as.is=T)
|
116
|
+
links <- read.csv("#{edge_file}", header=T, as.is=T)
|
117
|
+
|
118
|
+
rbbt.require('igraph')
|
119
|
+
|
120
|
+
net <- graph.data.frame(links, nodes, directed=T)
|
121
|
+
net <- simplify(net, remove.multiple = F, remove.loops = T)
|
122
|
+
|
123
|
+
png("#{options[:plot]}", width=1000, height=1000)
|
124
|
+
plot(net, edge.arrow.size=0.4, vertex.label=net$label, vertex.color=net$color)
|
125
|
+
dev.off()
|
126
|
+
EOF
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
else
|
131
|
+
puts Step.prov_report(step, 0, nil, [], options[:expand_repeats])
|
132
|
+
end
|
133
|
+
|
@@ -21,7 +21,7 @@ $ #{$0} [<options>] <workflow> <task>
|
|
21
21
|
--deploy* Deploy mode: serial, local, or SLURM (default 'serial')
|
22
22
|
-jn--jobname* Name to use as job identifier
|
23
23
|
-li--load_inputs* Directory with inputs files to load
|
24
|
-
-pf--
|
24
|
+
-pf--printpath Print the file path
|
25
25
|
-prov--provenance Print the step provenance
|
26
26
|
-cl--clean Clean the last step
|
27
27
|
-rcl--recursive_clean Clean all steps
|
@@ -39,8 +39,8 @@ task = workflow.tasks[task_name.to_sym] if task_name
|
|
39
39
|
|
40
40
|
options[:help] = true if task.nil?
|
41
41
|
|
42
|
-
help, provenance, clean, recursive_clean, clean_task, load_inputs, jobname,
|
43
|
-
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :jobname, :
|
42
|
+
help, provenance, clean, recursive_clean, clean_task, load_inputs, jobname, printpath, deploy, override_deps = IndiferentHash.process_options options,
|
43
|
+
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :jobname, :printpath, :deploy, :override_deps,
|
44
44
|
:deploy => 'serial'
|
45
45
|
|
46
46
|
if help
|
@@ -102,8 +102,9 @@ else
|
|
102
102
|
when "slurm"
|
103
103
|
require 'rbbt-scout'
|
104
104
|
require_relative '../../modules/rbbt-util/lib/rbbt/hpc'
|
105
|
+
slurm_options = {}
|
105
106
|
HPC::BATCH_MODULE = HPC.batch_system "SLURM"
|
106
|
-
HPC::BATCH_MODULE.orchestrate_job(job,
|
107
|
+
HPC::BATCH_MODULE.orchestrate_job(job, slurm_options)
|
107
108
|
job.grace
|
108
109
|
else
|
109
110
|
if deploy.end_with?('-slurm')
|
@@ -116,7 +117,7 @@ else
|
|
116
117
|
job.run
|
117
118
|
end unless job.done?
|
118
119
|
|
119
|
-
if
|
120
|
+
if printpath
|
120
121
|
job.join
|
121
122
|
path = job.path
|
122
123
|
path = path.find if Path === path
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
|
5
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
6
|
+
|
7
|
+
options = SOPT.setup <<EOF
|
8
|
+
|
9
|
+
Description of the tool
|
10
|
+
|
11
|
+
$ #{$0} [<options>] <job-result>
|
12
|
+
|
13
|
+
-h--help Help
|
14
|
+
-fg--fix_gap Remove execution gaps
|
15
|
+
-rk--report_keys* Config keys and info fields to report
|
16
|
+
-p--plot* Plot file
|
17
|
+
-w--width* Image Width
|
18
|
+
-h--height* Image Height
|
19
|
+
-s--size* Image Size (Height and Width)
|
20
|
+
-pd--plot_data Print plot data
|
21
|
+
EOF
|
22
|
+
if options[:help]
|
23
|
+
if defined? scout_usage
|
24
|
+
scout_usage
|
25
|
+
else
|
26
|
+
puts SOPT.doc
|
27
|
+
end
|
28
|
+
exit 0
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'rbbt/workflow/util/trace'
|
32
|
+
require 'rbbt/util/R'
|
33
|
+
|
34
|
+
|
35
|
+
files = ARGV
|
36
|
+
plot = options[:plot]
|
37
|
+
|
38
|
+
def get_step(file)
|
39
|
+
file = File.expand_path(file)
|
40
|
+
file = file.sub(/\.(info|files)/,'')
|
41
|
+
Step.new file
|
42
|
+
end
|
43
|
+
|
44
|
+
jobs = []
|
45
|
+
jobs = files.collect do |file|
|
46
|
+
get_step file
|
47
|
+
end
|
48
|
+
|
49
|
+
puts Workflow.trace(jobs, options)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
|
5
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
6
|
+
|
7
|
+
options = SOPT.setup <<EOF
|
8
|
+
Examine the info of a job result
|
9
|
+
|
10
|
+
$ #{$0} <job-result> <key> <value>
|
11
|
+
|
12
|
+
-h--help Help
|
13
|
+
-f--force Write info even if key is already present
|
14
|
+
-r--recursive Write info for all dependencies as well
|
15
|
+
-p--check_pid Check that recursive jobs where created by the same process
|
16
|
+
EOF
|
17
|
+
if options[:help]
|
18
|
+
if defined? scout_usage
|
19
|
+
scout_usage
|
20
|
+
else
|
21
|
+
puts SOPT.doc
|
22
|
+
end
|
23
|
+
exit 0
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
file, key, value = ARGV
|
28
|
+
|
29
|
+
force, recursive, check_pid = options.values_at :force, :recursive, :check_pid
|
30
|
+
|
31
|
+
def get_step(file)
|
32
|
+
file = file.sub(/\.(info|files)/,'')
|
33
|
+
step = Step.new file
|
34
|
+
step
|
35
|
+
end
|
36
|
+
|
37
|
+
raise ParameterException if key.nil? || value.nil?
|
38
|
+
|
39
|
+
if %w(DELETE nil).include? value
|
40
|
+
value = nil
|
41
|
+
force = true
|
42
|
+
end
|
43
|
+
|
44
|
+
step = get_step file
|
45
|
+
|
46
|
+
step.set_info key, value if force || ! step.info.include?(key)
|
47
|
+
|
48
|
+
pid = step.info[:pid]
|
49
|
+
host = step.info[:pid_hostname]
|
50
|
+
|
51
|
+
step.rec_dependencies.each do |dep|
|
52
|
+
begin
|
53
|
+
dep.set_info key, value if (force || ! dep.info.include?(key)) && (!check_pid || dep.info[:pid].to_s == pid and dep.info[:pid_hostname] == host)
|
54
|
+
rescue
|
55
|
+
Log.warn "Could no set info #{key} for #{dep.path}: #{$!.message}"
|
56
|
+
end
|
57
|
+
end if recursive
|
58
|
+
|
59
|
+
if recursive && step.info[:archived_info]
|
60
|
+
ad = step.info[:archived_info]
|
61
|
+
ad.each do |d,info|
|
62
|
+
begin
|
63
|
+
info[key] = value if (force || ! info.include?(key)) && (!check_pid || info[:pid].to_s == pid and info[:pid_hostname] == host)
|
64
|
+
rescue
|
65
|
+
Log.warn "Could no set info #{key} for archived_dep #{info[:path]}: #{$!.message}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
step.set_info :archived_info, ad
|
69
|
+
end
|
data/test/scout/test_tsv.rb
CHANGED
@@ -85,6 +85,27 @@ row2 a a id3
|
|
85
85
|
assert_equal %w(A a), tsv["row2"][0]
|
86
86
|
end
|
87
87
|
|
88
|
+
def test_open_persist_path
|
89
|
+
content =<<-'EOF'
|
90
|
+
#: :sep=/\s+/#:type=:double#:merge=:concat
|
91
|
+
#Id ValueA ValueB OtherID
|
92
|
+
row1 a|aa|aaa b Id1|Id2
|
93
|
+
row2 A B Id3
|
94
|
+
row2 a a id3
|
95
|
+
EOF
|
96
|
+
|
97
|
+
TmpFile.with_file do |persist_path|
|
98
|
+
orig = TmpFile.with_file(content) do |filename|
|
99
|
+
TSV.open(filename, :persist => true, :merge => true, :persist_path => persist_path)
|
100
|
+
end
|
101
|
+
|
102
|
+
tsv = ScoutCabinet.open persist_path, false
|
103
|
+
assert_equal tsv.persistence_path, persist_path
|
104
|
+
assert_equal orig, tsv
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
88
109
|
def test_headerless_fields
|
89
110
|
content =<<-EOF
|
90
111
|
row1 a|aa|aaa b Id1|Id2
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
require 'scout/tsv'
|
5
|
+
|
6
|
+
class TestClass < Test::Unit::TestCase
|
7
|
+
def test_melt
|
8
|
+
txt =<<-EOF
|
9
|
+
#: :sep=,#:type=:list
|
10
|
+
#Size,System1,System2
|
11
|
+
10,20,30
|
12
|
+
20,40,60
|
13
|
+
EOF
|
14
|
+
|
15
|
+
target =<<-EOF
|
16
|
+
#: :sep=,#:type=:list
|
17
|
+
#ID,Size,Time,System
|
18
|
+
10:0,10,20,System1
|
19
|
+
10:1,10,30,System2
|
20
|
+
20:0,20,40,System1
|
21
|
+
20:1,20,60,System2
|
22
|
+
EOF
|
23
|
+
|
24
|
+
tsv = TSV.open(txt)
|
25
|
+
assert_equal tsv.melt_columns("Time", "System"), TSV.open(target)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout-gear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.
|
4
|
+
version: 10.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: scout-essentials
|
@@ -169,6 +169,7 @@ files:
|
|
169
169
|
- lib/scout/tsv/traverse.rb
|
170
170
|
- lib/scout/tsv/util.rb
|
171
171
|
- lib/scout/tsv/util/filter.rb
|
172
|
+
- lib/scout/tsv/util/melt.rb
|
172
173
|
- lib/scout/tsv/util/process.rb
|
173
174
|
- lib/scout/tsv/util/reorder.rb
|
174
175
|
- lib/scout/tsv/util/select.rb
|
@@ -201,9 +202,12 @@ files:
|
|
201
202
|
- lib/workflow-scout.rb
|
202
203
|
- scout-gear.gemspec
|
203
204
|
- scout_commands/alias
|
205
|
+
- scout_commands/batch/clean
|
206
|
+
- scout_commands/batch/list
|
204
207
|
- scout_commands/doc
|
205
208
|
- scout_commands/find
|
206
209
|
- scout_commands/glob
|
210
|
+
- scout_commands/log
|
207
211
|
- scout_commands/offsite
|
208
212
|
- scout_commands/rbbt
|
209
213
|
- scout_commands/resource/produce
|
@@ -212,7 +216,10 @@ files:
|
|
212
216
|
- scout_commands/workflow/info
|
213
217
|
- scout_commands/workflow/install
|
214
218
|
- scout_commands/workflow/list
|
219
|
+
- scout_commands/workflow/prov
|
215
220
|
- scout_commands/workflow/task
|
221
|
+
- scout_commands/workflow/trace
|
222
|
+
- scout_commands/workflow/write_info
|
216
223
|
- share/color/color_names
|
217
224
|
- share/color/diverging_colors.hex
|
218
225
|
- share/software/install_helpers
|
@@ -242,6 +249,7 @@ files:
|
|
242
249
|
- test/scout/tsv/test_traverse.rb
|
243
250
|
- test/scout/tsv/test_util.rb
|
244
251
|
- test/scout/tsv/util/test_filter.rb
|
252
|
+
- test/scout/tsv/util/test_melt.rb
|
245
253
|
- test/scout/tsv/util/test_process.rb
|
246
254
|
- test/scout/tsv/util/test_reorder.rb
|
247
255
|
- test/scout/tsv/util/test_select.rb
|
@@ -285,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
285
293
|
- !ruby/object:Gem::Version
|
286
294
|
version: '0'
|
287
295
|
requirements: []
|
288
|
-
rubygems_version: 3.
|
296
|
+
rubygems_version: 3.5.0.dev
|
289
297
|
signing_key:
|
290
298
|
specification_version: 4
|
291
299
|
summary: basic gear for scouts
|