rbbt-util 5.38.1 → 5.40.0
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/lib/rbbt/hpc/batch.rb +13 -3
- data/lib/rbbt/hpc/lsf.rb +1 -1
- data/lib/rbbt/hpc/orchestrate/rules.rb +8 -1
- data/lib/rbbt/hpc/orchestrate.rb +21 -17
- data/lib/rbbt/hpc/pbs.rb +177 -0
- data/lib/rbbt/hpc/slurm.rb +1 -1
- data/lib/rbbt/hpc.rb +1 -0
- data/lib/rbbt/resource/util.rb +1 -1
- data/lib/rbbt/resource.rb +6 -2
- data/lib/rbbt/tsv/util.rb +4 -0
- data/lib/rbbt/util/R/plot.rb +85 -0
- data/lib/rbbt/util/cmd.rb +8 -4
- data/lib/rbbt/util/concurrency/processes.rb +1 -1
- data/lib/rbbt/util/migrate.rb +1 -2
- data/lib/rbbt/util/misc/inspect.rb +1 -0
- data/lib/rbbt/util/open.rb +6 -0
- data/lib/rbbt/util/ssh.rb +1 -1
- data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +1 -1
- data/lib/rbbt/workflow/step/dependencies.rb +3 -4
- data/lib/rbbt/workflow/step.rb +2 -2
- data/lib/rbbt/workflow/usage.rb +1 -1
- data/lib/rbbt/workflow/util/trace.rb +2 -1
- data/lib/rbbt/workflow.rb +3 -2
- data/share/Rlib/util.R +12 -0
- data/share/rbbt_commands/hpc/list +2 -0
- data/share/rbbt_commands/hpc/orchestrate +1 -1
- data/share/rbbt_commands/hpc/task +8 -7
- data/share/rbbt_commands/lsf/list +2 -0
- data/share/rbbt_commands/lsf/orchestrate +1 -1
- data/share/rbbt_commands/lsf/task +8 -7
- data/share/rbbt_commands/resource/claims +57 -0
- data/share/rbbt_commands/slurm/list +2 -0
- data/share/rbbt_commands/slurm/orchestrate +1 -1
- data/share/rbbt_commands/slurm/task +8 -7
- data/share/rbbt_commands/workflow/task +2 -2
- data/test/rbbt/hpc/test_pbs.rb +43 -0
- data/test/rbbt/test_tsv.rb +16 -1
- data/test/rbbt/tsv/parallel/test_traverse.rb +2 -2
- data/test/rbbt/tsv/test_util.rb +14 -0
- data/test/rbbt/util/test_migrate.rb +2 -2
- metadata +100 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '088ac190b36a176e420d4bb1d7b8d28d777133568e45530219f6a0212a1a1144'
|
4
|
+
data.tar.gz: 47bdc31d247e5fd5d944f493690e8181bcc236cee74c61fefd5ce25711edf7da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9afce115c221695ee896c1e1f884be9a1ba0f0ae98789a485a906e438252afe8292c5422f3eef57d77089bf55cc0b425988ab9b479b1f422eaa0abb7005cfdfa
|
7
|
+
data.tar.gz: 4cf4d1e86ce3ab256609aff4c66a3412ea1a9c0c87db08fd5cdad1b98c95147d452cc69d96009c9791cf698ea43903873ed0e4cebbc861bda85097864bed68e8
|
data/lib/rbbt/hpc/batch.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module HPC
|
2
|
-
class
|
2
|
+
class BATCH_DRY_RUN < Exception;
|
3
3
|
attr_accessor :directory
|
4
4
|
def initialize(directory)
|
5
5
|
@directory = directory
|
@@ -12,24 +12,32 @@ module HPC
|
|
12
12
|
HPC::SLURM
|
13
13
|
when 'lsf'
|
14
14
|
HPC::LSF
|
15
|
+
when 'pbs'
|
16
|
+
HPC::PBS
|
15
17
|
when 'auto'
|
16
18
|
case $previous_commands.last
|
17
19
|
when 'slurm'
|
18
20
|
HPC::SLURM
|
19
21
|
when 'lsf'
|
20
22
|
HPC::LSF
|
23
|
+
when 'pbs'
|
24
|
+
HPC::PBS
|
21
25
|
else
|
22
26
|
case Rbbt::Config.get(:batch_system, :batch, :batch_system, :hpc, :HPC, :BATCH).to_s.downcase
|
23
27
|
when 'slurm'
|
24
28
|
HPC::SLURM
|
25
29
|
when 'lsf'
|
26
30
|
HPC::LSF
|
31
|
+
when 'pbd'
|
32
|
+
HPC::PBS
|
27
33
|
else
|
28
34
|
case ENV["BATCH_SYSTEM"].to_s.downcase
|
29
35
|
when 'slurm'
|
30
36
|
HPC::SLURM
|
31
37
|
when 'lsf'
|
32
38
|
HPC::LSF
|
39
|
+
when 'pbs'
|
40
|
+
HPC::PBS
|
33
41
|
end
|
34
42
|
end
|
35
43
|
end
|
@@ -564,8 +572,8 @@ env > #{batch_options[:fenv]}
|
|
564
572
|
def run_job(job, options = {})
|
565
573
|
system = self.to_s.split("::").last
|
566
574
|
|
567
|
-
batch_base_dir, clean_batch_job, remove_batch_dir, procpath, tail, batch_dependencies, dry_run = Misc.process_options options,
|
568
|
-
:batch_base_dir, :clean_batch_job, :remove_batch_dir, :batch_procpath, :tail, :batch_dependencies, :dry_run,
|
575
|
+
batch_base_dir, clean_batch_job, remove_batch_dir, procpath, tail, batch_dependencies, dry_run, orchestration_rules_file = Misc.process_options options,
|
576
|
+
:batch_base_dir, :clean_batch_job, :remove_batch_dir, :batch_procpath, :tail, :batch_dependencies, :dry_run, :orchestration_rules,
|
569
577
|
:batch_base_dir => File.expand_path(File.join('~/rbbt-batch'))
|
570
578
|
|
571
579
|
if (batch_job = job.info[:batch_job]) && job_queued(batch_job)
|
@@ -586,6 +594,8 @@ env > #{batch_options[:fenv]}
|
|
586
594
|
workflow = job.original_workflow ||job.workflow
|
587
595
|
task_name = job.original_task_name || job.task_name
|
588
596
|
|
597
|
+
options = options.merge(HPC::Orchestration.job_rules(HPC::Orchestration.orchestration_rules(orchestration_rules_file), job)) if orchestration_rules_file
|
598
|
+
|
589
599
|
workflows_to_load = job.rec_dependencies.select{|d| Step === d}.collect{|d| d.workflow }.compact.collect(&:to_s) - [workflow.to_s]
|
590
600
|
|
591
601
|
TmpFile.with_file(nil, remove_batch_dir, :tmpdir => batch_base_dir, :prefix => "#{system}_rbbt_job-#{workflow.to_s}-#{task_name}-") do |batch_dir|
|
data/lib/rbbt/hpc/lsf.rb
CHANGED
@@ -99,7 +99,7 @@ export BATCH_SYSTEM=#{batch_system}
|
|
99
99
|
elsif dry_run
|
100
100
|
STDERR.puts Log.color(:magenta, "To execute run: ") + Log.color(:blue, cmd)
|
101
101
|
STDERR.puts Log.color(:magenta, "To monitor progress run (needs local rbbt): ") + Log.color(:blue, "rbbt lsf tail '#{batch_dir}'")
|
102
|
-
raise HPC::
|
102
|
+
raise HPC::BATCH_DRY_RUN, batch_dir
|
103
103
|
else
|
104
104
|
Open.rm fsync
|
105
105
|
Open.rm fexit
|
@@ -65,6 +65,13 @@ module HPC
|
|
65
65
|
merge_rules(rules[workflow][task], workflow_rules)
|
66
66
|
end
|
67
67
|
|
68
|
-
|
68
|
+
def self.job_rules(rules, job)
|
69
|
+
return {} if job.done? or job.error?
|
70
|
+
job_rules = task_specific_rules(rules, job.workflow.to_s, job.task_name.to_s)
|
71
|
+
job.dependencies.each do |dep|
|
72
|
+
job_rules = accumulate_rules(job_rules, job_rules(rules, dep))
|
73
|
+
end
|
74
|
+
job_rules
|
75
|
+
end
|
69
76
|
end
|
70
77
|
end
|
data/lib/rbbt/hpc/orchestrate.rb
CHANGED
@@ -22,6 +22,25 @@ module HPC
|
|
22
22
|
|
23
23
|
end
|
24
24
|
|
25
|
+
def self.orchestration_rules(orchestration_rules_file = nil)
|
26
|
+
rules = {}
|
27
|
+
if orchestration_rules_file
|
28
|
+
if Open.exists?(orchestration_rules_file)
|
29
|
+
rules = Misc.load_yaml(orchestration_rules_file)
|
30
|
+
elsif Rbbt.etc.batch[orchestration_rules_file].exists?
|
31
|
+
rules = Misc.load_yaml(Rbbt.etc.batch[orchestration_rules_file])
|
32
|
+
elsif Rbbt.etc.batch[orchestration_rules_file + '.yaml'].exists?
|
33
|
+
rules = Misc.load_yaml(Rbbt.etc.batch[orchestration_rules_file + '.yaml'])
|
34
|
+
else
|
35
|
+
raise "Orchestration rules file not found: #{orchestration_rules_file}"
|
36
|
+
end
|
37
|
+
elsif Rbbt.etc.batch["default.yaml"].exists?
|
38
|
+
rules = Misc.load_yaml(Rbbt.etc.batch["default.yaml"])
|
39
|
+
end
|
40
|
+
|
41
|
+
IndiferentHash.setup(rules)
|
42
|
+
end
|
43
|
+
|
25
44
|
def orchestrate_job(job, options)
|
26
45
|
options.delete "recursive_clean"
|
27
46
|
options.delete "clean_task"
|
@@ -33,26 +52,11 @@ module HPC
|
|
33
52
|
options.delete "load_inputs"
|
34
53
|
options.delete "provenance"
|
35
54
|
|
55
|
+
|
36
56
|
Log.high "Prepare for exec"
|
37
57
|
prepare_for_execution(job)
|
38
58
|
|
39
|
-
|
40
|
-
if Open.exists?(orchestration_rules_file)
|
41
|
-
rules = Misc.load_yaml(orchestration_rules_file)
|
42
|
-
elsif Rbbt.etc.slurm(orchestration_rules_file).exists?
|
43
|
-
rules = Misc.load_yaml(Rbbt.etc.slurm(orchestration_rules_file))
|
44
|
-
elsif Rbbt.etc.slurm(orchestration_rules_file + '.yaml').exists?
|
45
|
-
rules = Misc.load_yaml(Rbbt.etc.slurm(orchestration_rules_file + '.yaml'))
|
46
|
-
else
|
47
|
-
raise "Orchestration rules file not found: #{options[:orchestration_rules]}"
|
48
|
-
end
|
49
|
-
elsif Rbbt.etc.slurm["default.yaml"].exists?
|
50
|
-
rules = Misc.load_yaml(Rbbt.etc.slurm["default.yaml"])
|
51
|
-
else
|
52
|
-
rules = {}
|
53
|
-
end
|
54
|
-
|
55
|
-
IndiferentHash.setup(rules)
|
59
|
+
rules = HPC::Orchestration.orchestration_rules(options[:orchestration_rules])
|
56
60
|
|
57
61
|
batches = HPC::Orchestration.job_batches(rules, job)
|
58
62
|
Log.high "Compute #{batches.length} batches"
|
data/lib/rbbt/hpc/pbs.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'rbbt/hpc/batch'
|
2
|
+
require 'rbbt/hpc/orchestrate'
|
3
|
+
|
4
|
+
module HPC
|
5
|
+
module PBS
|
6
|
+
extend HPC::TemplateGeneration
|
7
|
+
extend HPC::Orchestration
|
8
|
+
|
9
|
+
def self.batch_system
|
10
|
+
"PBS"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.batch_system_variables
|
14
|
+
<<-EOF
|
15
|
+
let TOTAL_PROCESORS="$(cat /proc/cpuinfo|grep ^processor |wc -l)"
|
16
|
+
let MAX_MEMORY_DEFAULT="$(grep MemTotal /proc/meminfo|grep -o "[[:digit:]]*") / ( (1024 * $TOTAL_PROCESORS) / $PBS_CPUS_PER_TASK )"
|
17
|
+
MAX_MEMORY="$MAX_MEMORY_DEFAULT"
|
18
|
+
[ ! -z $PBS_MEM_PER_CPU ] && let MAX_MEMORY="$PBS_MEM_PER_CPU * $PBS_CPUS_PER_TASK"
|
19
|
+
[ ! -z $PBS_MEM_PER_NODE ] && MAX_MEMORY="$PBS_MEM_PER_NODE"
|
20
|
+
export MAX_MEMORY_DEFAULT
|
21
|
+
export MAX_MEMORY
|
22
|
+
export BATCH_JOB_ID=$PBS_JOBID
|
23
|
+
export BATCH_SYSTEM=#{batch_system}
|
24
|
+
|
25
|
+
cd ${PBS_O_WORKDIR}
|
26
|
+
EOF
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.header(options = {})
|
30
|
+
options = options.dup
|
31
|
+
|
32
|
+
workdir = Misc.process_options options, :workdir
|
33
|
+
batch_dir = Misc.process_options options, :batch_dir
|
34
|
+
batch_name = Misc.process_options options, :batch_name
|
35
|
+
|
36
|
+
queue = Misc.process_options options, :queue
|
37
|
+
account = Misc.process_options options, :account
|
38
|
+
time = Misc.process_options options, :time
|
39
|
+
nodes = Misc.process_options options, :nodes
|
40
|
+
|
41
|
+
# PBS
|
42
|
+
place = Misc.process_options options, :place, :place => 'scatter'
|
43
|
+
system = Misc.process_options options, :partition
|
44
|
+
filesystems = Misc.process_options options, :filesystems
|
45
|
+
|
46
|
+
filesystems = filesystems * "," if Array === filesystems
|
47
|
+
|
48
|
+
# NOT USED
|
49
|
+
partition = Misc.process_options options, :partition
|
50
|
+
task_cpus = Misc.process_options options, :task_cpus
|
51
|
+
exclusive = Misc.process_options options, :exclusive
|
52
|
+
highmem = Misc.process_options options, :highmem
|
53
|
+
licenses = Misc.process_options options, :licenses
|
54
|
+
constraint = Misc.process_options options, :constraint
|
55
|
+
gres = Misc.process_options options, :gres
|
56
|
+
|
57
|
+
constraint = [constraint, "highmem"].compact * "&" if highmem
|
58
|
+
|
59
|
+
mem = Misc.process_options options, :mem
|
60
|
+
mem_per_cpu = Misc.process_options options, :mem_per_cpu
|
61
|
+
|
62
|
+
fout = File.join(batch_dir, 'std.out')
|
63
|
+
ferr = File.join(batch_dir, 'std.err')
|
64
|
+
|
65
|
+
time = Misc.format_seconds Misc.timespan(time) unless time.include? ":"
|
66
|
+
|
67
|
+
qsub_params = { "-l filesystems=" => filesystems,
|
68
|
+
"-l system=" => system,
|
69
|
+
"-l select=" => nodes,
|
70
|
+
"-l place=" => place,
|
71
|
+
"-l walltime=" => time,
|
72
|
+
"-q " => queue,
|
73
|
+
"-A " => account,
|
74
|
+
"-o " => fout,
|
75
|
+
"-e " => ferr,
|
76
|
+
"-k doe" => true,
|
77
|
+
# "cpus-per-task" => task_cpus,
|
78
|
+
# "nodes" => nodes,
|
79
|
+
# "time" => time,
|
80
|
+
# "constraint" => constraint,
|
81
|
+
# "exclusive" => exclusive,
|
82
|
+
# "licenses" => licenses,
|
83
|
+
# "gres" => gres,
|
84
|
+
# "mem" => mem,
|
85
|
+
# "mem-per-cpu" => mem_per_cpu,
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
header =<<-EOF
|
90
|
+
#!/bin/bash
|
91
|
+
EOF
|
92
|
+
|
93
|
+
qsub_params.each do |name,value|
|
94
|
+
next if value.nil? || value == ""
|
95
|
+
if TrueClass === value
|
96
|
+
header << "#PBS #{name}" << "\n"
|
97
|
+
elsif Array === value
|
98
|
+
value.each do |v|
|
99
|
+
header << "#PBS #{name}\"#{v}\"" << "\n"
|
100
|
+
end
|
101
|
+
else
|
102
|
+
header << "#PBS #{name}\"#{value}\"" << "\n"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
header
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.run_template(batch_dir, dry_run)
|
110
|
+
|
111
|
+
fout = File.join(batch_dir, 'std.out')
|
112
|
+
ferr = File.join(batch_dir, 'std.err')
|
113
|
+
fjob = File.join(batch_dir, 'job.id')
|
114
|
+
fdep = File.join(batch_dir, 'dependencies.list')
|
115
|
+
fcfdep = File.join(batch_dir, 'canfail_dependencies.list')
|
116
|
+
fexit = File.join(batch_dir, 'exit.status')
|
117
|
+
fsync = File.join(batch_dir, 'sync.log')
|
118
|
+
fcmd = File.join(batch_dir, 'command.batch')
|
119
|
+
|
120
|
+
return if Open.exists?(fexit)
|
121
|
+
|
122
|
+
Log.info "Issuing PBS file: #{fcmd}"
|
123
|
+
Log.debug Open.read(fcmd)
|
124
|
+
|
125
|
+
if File.exist?(fjob)
|
126
|
+
job = Open.read(fjob).to_i
|
127
|
+
else
|
128
|
+
|
129
|
+
dependencies = Open.read(fdep).split("\n") if File.exist? fdep
|
130
|
+
canfail_dependencies = Open.read(fcfdep).split("\n") if File.exist? fcfdep
|
131
|
+
|
132
|
+
normal_dep_str = dependencies && dependencies.any? ? "afterok:" + dependencies * ":" : nil
|
133
|
+
canfail_dep_str = canfail_dependencies && canfail_dependencies.any? ? "afterany:" + canfail_dependencies * ":" : nil
|
134
|
+
|
135
|
+
if normal_dep_str.nil? && canfail_dep_str.nil?
|
136
|
+
dep_str = ""
|
137
|
+
else
|
138
|
+
dep_str = '-W depend=' + [normal_dep_str, canfail_dep_str].compact * ","
|
139
|
+
end
|
140
|
+
|
141
|
+
cmd = "qsub #{dep_str} '#{fcmd}'"
|
142
|
+
|
143
|
+
if File.exist?(fout)
|
144
|
+
return
|
145
|
+
elsif dry_run
|
146
|
+
STDERR.puts Log.color(:magenta, "To execute run: ") + Log.color(:blue, "squb '#{fcmd}'")
|
147
|
+
STDERR.puts Log.color(:magenta, "To monitor progress run (needs local rbbt): ") + Log.color(:blue, "rbbt pbs tail '#{batch_dir}'")
|
148
|
+
raise HPC::BATCH_DRY_RUN, batch_dir
|
149
|
+
else
|
150
|
+
Open.rm fsync
|
151
|
+
Open.rm fexit
|
152
|
+
Open.rm fout
|
153
|
+
Open.rm ferr
|
154
|
+
|
155
|
+
job = CMD.cmd(cmd).read.scan(/\d+/).first.to_i
|
156
|
+
Log.debug "SBATCH job id: #{job}"
|
157
|
+
Open.write(fjob, job.to_s)
|
158
|
+
job
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.job_status(job = nil)
|
164
|
+
if job.nil?
|
165
|
+
CMD.cmd("qstat").read
|
166
|
+
else
|
167
|
+
begin
|
168
|
+
CMD.cmd("qstat #{job}").read
|
169
|
+
rescue
|
170
|
+
""
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
data/lib/rbbt/hpc/slurm.rb
CHANGED
@@ -130,7 +130,7 @@ export BATCH_SYSTEM=#{batch_system}
|
|
130
130
|
elsif dry_run
|
131
131
|
STDERR.puts Log.color(:magenta, "To execute run: ") + Log.color(:blue, "sbatch '#{fcmd}'")
|
132
132
|
STDERR.puts Log.color(:magenta, "To monitor progress run (needs local rbbt): ") + Log.color(:blue, "rbbt slurm tail '#{batch_dir}'")
|
133
|
-
raise HPC::
|
133
|
+
raise HPC::BATCH_DRY_RUN, batch_dir
|
134
134
|
else
|
135
135
|
Open.rm fsync
|
136
136
|
Open.rm fexit
|
data/lib/rbbt/hpc.rb
CHANGED
data/lib/rbbt/resource/util.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Path
|
2
2
|
|
3
|
-
def self.caller_lib_dir(file = nil, relative_to = ['lib', 'bin'])
|
3
|
+
def self.caller_lib_dir(file = nil, relative_to = ['lib', 'bin', 'LICENSE'])
|
4
4
|
#file = caller.reject{|l|
|
5
5
|
# l =~ /rbbt\/(?:resource\.rb|workflow\.rb)/ or
|
6
6
|
# l =~ /rbbt\/resource\/path\.rb/ or
|
data/lib/rbbt/resource.rb
CHANGED
@@ -354,7 +354,7 @@ url='#{url}'
|
|
354
354
|
path = File.expand_path(path)
|
355
355
|
path += "/" if File.directory?(path)
|
356
356
|
resource ||= Rbbt
|
357
|
-
locations = (Path::STANDARD_SEARCH + resource.search_order + resource.search_paths.keys)
|
357
|
+
locations = (Path::STANDARD_SEARCH + resource.search_order + resource.search_paths.keys).uniq
|
358
358
|
locations -= [:current, "current"]
|
359
359
|
locations << :current
|
360
360
|
search_paths = IndiferentHash.setup(resource.search_paths)
|
@@ -374,7 +374,11 @@ url='#{url}'
|
|
374
374
|
if ! m.named_captures.include?("PKGDIR") || m["PKGDIR"] == resource.pkgdir
|
375
375
|
unlocated = ([m["TOPLEVEL"],m["SUBPATH"],m["REST"]] * "/")
|
376
376
|
unlocated.gsub!(/\/+/,'/')
|
377
|
-
|
377
|
+
if self.subdir && ! self.subdir.empty?
|
378
|
+
subdir = self.subdir
|
379
|
+
subdir += "/" unless subdir.end_with?("/")
|
380
|
+
unlocated[subdir] = ""
|
381
|
+
end
|
378
382
|
choices << self.annotate(unlocated)
|
379
383
|
end
|
380
384
|
end
|
data/lib/rbbt/tsv/util.rb
CHANGED
data/lib/rbbt/util/R/plot.rb
CHANGED
@@ -1,6 +1,91 @@
|
|
1
1
|
module R
|
2
2
|
module SVG
|
3
3
|
|
4
|
+
def self.plot(filename, data = nil, script = nil, width = nil, height = nil, options = {}, &block)
|
5
|
+
width ||= 600
|
6
|
+
height ||= 600
|
7
|
+
values = []
|
8
|
+
|
9
|
+
script ||= ""
|
10
|
+
if block_given?
|
11
|
+
s = StringIO.new
|
12
|
+
class << s
|
13
|
+
def method_missing(name, *args)
|
14
|
+
name = name.to_s
|
15
|
+
if name[-1] == '='
|
16
|
+
arg = args.first
|
17
|
+
value = if String === arg
|
18
|
+
arg
|
19
|
+
else
|
20
|
+
R.ruby2R arg
|
21
|
+
end
|
22
|
+
add("" << name[0..-2] << "=" << value)
|
23
|
+
else
|
24
|
+
args_strs = []
|
25
|
+
args.each do |arg|
|
26
|
+
value = if String === arg
|
27
|
+
arg
|
28
|
+
else
|
29
|
+
R.ruby2R arg
|
30
|
+
end
|
31
|
+
args_strs << value
|
32
|
+
end
|
33
|
+
add("" << name << "(" << args_strs * ", " << ")")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def add(line)
|
38
|
+
self.write line << "\n"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
block.call(s)
|
42
|
+
s.rewind
|
43
|
+
script << "\n" << s.read
|
44
|
+
end
|
45
|
+
sources = [:plot, options[:source]].flatten.compact
|
46
|
+
|
47
|
+
if data
|
48
|
+
data.each do |k,v|
|
49
|
+
v = Array === v ? v : [v]
|
50
|
+
next if v == "NA" or v.nil? or v.include? "NA" or v.include? nil
|
51
|
+
values = v
|
52
|
+
break
|
53
|
+
end
|
54
|
+
|
55
|
+
values = [values] unless values.nil? or Array === values
|
56
|
+
|
57
|
+
field_classes = values.collect do |v|
|
58
|
+
case v
|
59
|
+
when FalseClass, TrueClass
|
60
|
+
"'logical'"
|
61
|
+
when Numeric
|
62
|
+
"'numeric'"
|
63
|
+
when String
|
64
|
+
if v.strip =~ /^[-+]?[\d\.]+$/
|
65
|
+
"'numeric'"
|
66
|
+
else
|
67
|
+
"'character'"
|
68
|
+
end
|
69
|
+
when Symbol
|
70
|
+
"'factor'"
|
71
|
+
else
|
72
|
+
":NA"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
options[:R_open] ||= "colClasses=c('character'," + field_classes * ", " + ')' if field_classes.any?
|
77
|
+
|
78
|
+
data.R <<-EOF, :plot, options
|
79
|
+
rbbt.svg_plot("#{ filename }", width=#{ width }, height = #{ height }, function(){ #{script} })
|
80
|
+
data = NULL
|
81
|
+
EOF
|
82
|
+
else
|
83
|
+
R.run <<-EOF, :plot, options
|
84
|
+
rbbt.svg_plot("#{ filename }", width=#{ width }, height = #{ height }, function(){ #{script} })
|
85
|
+
EOF
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
4
89
|
def self.ggplotSVG(*args)
|
5
90
|
ggplot(*args)
|
6
91
|
end
|
data/lib/rbbt/util/cmd.rb
CHANGED
@@ -22,13 +22,17 @@ module CMD
|
|
22
22
|
return tool.to_s unless TOOLS[tool]
|
23
23
|
|
24
24
|
@@init_cmd_tool ||= IndiferentHash.setup({})
|
25
|
+
|
26
|
+
claim, test, block, cmd = TOOLS[tool]
|
27
|
+
cmd = tool.to_s if cmd.nil?
|
28
|
+
|
25
29
|
if !@@init_cmd_tool[tool]
|
26
|
-
|
30
|
+
|
27
31
|
begin
|
28
32
|
if test
|
29
33
|
CMD.cmd(test + " ")
|
30
34
|
else
|
31
|
-
CMD.cmd("#{
|
35
|
+
CMD.cmd("#{cmd} --help")
|
32
36
|
end
|
33
37
|
rescue
|
34
38
|
if claim
|
@@ -41,7 +45,7 @@ module CMD
|
|
41
45
|
version = nil
|
42
46
|
["--version", "-version", "--help", ""].each do |f|
|
43
47
|
begin
|
44
|
-
version_txt += CMD.cmd("#{
|
48
|
+
version_txt += CMD.cmd("#{cmd} #{f} 2>&1", :nofail => true).read
|
45
49
|
version = Misc.scan_version_text(version_txt, tool)
|
46
50
|
break if version
|
47
51
|
rescue
|
@@ -54,7 +58,7 @@ module CMD
|
|
54
58
|
return cmd if cmd
|
55
59
|
end
|
56
60
|
|
57
|
-
|
61
|
+
cmd
|
58
62
|
end
|
59
63
|
|
60
64
|
def self.versions
|
data/lib/rbbt/util/migrate.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Rbbt
|
2
2
|
|
3
|
-
prepare_for_execution(job)
|
4
3
|
def self.migrate_source_paths(path, resource = Rbbt, source = nil)
|
5
4
|
if source
|
6
5
|
lpath, *paths = Misc.ssh_run(source, <<-EOF).split("\n")
|
@@ -60,7 +59,7 @@ puts resource[path].find(search_path)
|
|
60
59
|
test_str = options[:test] ? '-nv' : ''
|
61
60
|
|
62
61
|
real_paths.each do |source_path|
|
63
|
-
Log.
|
62
|
+
Log.low "Migrating #{source_path} #{options[:files].length} files to #{target} - #{Misc.fingerprint(options[:files])}}" if options[:files]
|
64
63
|
if File.directory?(source_path) || source_path.end_with?("/")
|
65
64
|
source_path += "/" unless source_path.end_with? '/'
|
66
65
|
target += "/" unless target.end_with? '/'
|
data/lib/rbbt/util/open.rb
CHANGED
@@ -530,16 +530,22 @@ module Open
|
|
530
530
|
|
531
531
|
def self.gzip?(file)
|
532
532
|
file = file.find if Path === file
|
533
|
+
file = file.filename if File === file
|
534
|
+
return false unless String === file
|
533
535
|
!! (file =~ /\.gz$/)
|
534
536
|
end
|
535
537
|
|
536
538
|
def self.bgzip?(file)
|
537
539
|
file = file.find if Path === file
|
540
|
+
file = file.filename if File === file
|
541
|
+
return false unless String === file
|
538
542
|
!! (file =~ /\.bgz$/)
|
539
543
|
end
|
540
544
|
|
541
545
|
def self.zip?(file)
|
542
546
|
file = file.find if Path === file
|
547
|
+
file = file.filename if File === file
|
548
|
+
return false unless String === file
|
543
549
|
!! (file =~ /\.zip$/)
|
544
550
|
end
|
545
551
|
|
data/lib/rbbt/util/ssh.rb
CHANGED
@@ -253,7 +253,7 @@ job.clean
|
|
253
253
|
Step.wait_for_jobs missing_deps
|
254
254
|
|
255
255
|
migrate_dependencies = all_deps.keys.collect{|d| [d] + d.rec_dependencies + d.input_dependencies }.flatten.select{|d| d.done? }.collect{|d| d.path }
|
256
|
-
Log.
|
256
|
+
Log.low "Migrating #{migrate_dependencies.length} dependencies from #{Misc.fingerprint job_list} to #{ server }"
|
257
257
|
Step.migrate(migrate_dependencies, search_path, :target => server) if migrate_dependencies.any?
|
258
258
|
end
|
259
259
|
|
@@ -145,9 +145,9 @@ class Step
|
|
145
145
|
end
|
146
146
|
|
147
147
|
def input_dependencies
|
148
|
-
@input_dependencies ||= recursive_inputs.flatten.
|
148
|
+
@input_dependencies ||= recursive_inputs(true).flatten.
|
149
149
|
select{|i| Step === i || (defined?(RemoteStep) && RemoteStep === i) } +
|
150
|
-
recursive_inputs.flatten.
|
150
|
+
recursive_inputs(true).flatten.
|
151
151
|
select{|dep| Path === dep && Step === dep.resource }.
|
152
152
|
#select{|dep| ! dep.resource.started? }. # Ignore input_deps already started
|
153
153
|
collect{|dep| dep.resource }
|
@@ -581,7 +581,6 @@ class Step
|
|
581
581
|
#but dependencies are absent, meanining that the file could have been dropped
|
582
582
|
#in
|
583
583
|
def rec_dependencies(connected = false, seen = [])
|
584
|
-
|
585
584
|
# A step result with no info_file means that it was manually
|
586
585
|
# placed. In that case, do not consider its dependencies
|
587
586
|
return [] if ! (defined? WorkflowRemoteClient && WorkflowRemoteClient::RemoteStep === self) && ! Open.exists?(self.info_file) && Open.exists?(self.path.to_s)
|
@@ -599,7 +598,7 @@ class Step
|
|
599
598
|
#next if self.done? && Open.exists?(info_file) && info[:dependencies] && info[:dependencies].select{|task,name,path| path == step.path }.empty?
|
600
599
|
next if archived_deps.include? step.path
|
601
600
|
next if seen.include? step
|
602
|
-
next if
|
601
|
+
next if step.done? && connected && ! step.updatable?
|
603
602
|
|
604
603
|
r = step.rec_dependencies(connected, new_dependencies)
|
605
604
|
new_dependencies.concat r
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -90,7 +90,7 @@ class Step
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
def recursive_inputs
|
93
|
+
def recursive_inputs(connected = false)
|
94
94
|
if NamedArray === inputs
|
95
95
|
i = {}
|
96
96
|
inputs.zip(inputs.fields).each do |v,f|
|
@@ -99,7 +99,7 @@ class Step
|
|
99
99
|
else
|
100
100
|
i = {}
|
101
101
|
end
|
102
|
-
rec_dependencies.each do |dep|
|
102
|
+
rec_dependencies(connected).each do |dep|
|
103
103
|
next unless NamedArray === dep.inputs
|
104
104
|
|
105
105
|
dep.inputs.zip(dep.inputs.fields).each do |v,f|
|
data/lib/rbbt/workflow/usage.rb
CHANGED
@@ -20,7 +20,7 @@ module Task
|
|
20
20
|
task_inputs = dep_inputs deps, workflow
|
21
21
|
task_inputs.each do |task,new_inputs|
|
22
22
|
new_inputs.zip(task.input_types.values_at(*new_inputs)).select do |i,t|
|
23
|
-
t.to_sym == :select
|
23
|
+
t.to_sym == :select && task.input_options.include?(i) && task.input_options[i][:select_options]
|
24
24
|
end.each do |i,t|
|
25
25
|
selects << [i, task.input_options[i][:select_options]]
|
26
26
|
end
|
@@ -81,7 +81,8 @@ module Workflow
|
|
81
81
|
|
82
82
|
def self.plot_trace_job_times(data, plot, width=800, height=800)
|
83
83
|
data.R <<-EOF, [:svg]
|
84
|
-
rbbt.require('
|
84
|
+
rbbt.require('dplyr')
|
85
|
+
rbbt.require('tidyr')
|
85
86
|
rbbt.require('ggplot2')
|
86
87
|
|
87
88
|
names(data) <- make.names(names(data))
|