rbbt-util 5.38.1 → 5.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rbbt/hpc/batch.rb +13 -3
  3. data/lib/rbbt/hpc/lsf.rb +1 -1
  4. data/lib/rbbt/hpc/orchestrate/rules.rb +8 -1
  5. data/lib/rbbt/hpc/orchestrate.rb +21 -17
  6. data/lib/rbbt/hpc/pbs.rb +177 -0
  7. data/lib/rbbt/hpc/slurm.rb +1 -1
  8. data/lib/rbbt/hpc.rb +1 -0
  9. data/lib/rbbt/resource/util.rb +1 -1
  10. data/lib/rbbt/resource.rb +6 -2
  11. data/lib/rbbt/tsv/util.rb +4 -0
  12. data/lib/rbbt/util/R/plot.rb +85 -0
  13. data/lib/rbbt/util/cmd.rb +8 -4
  14. data/lib/rbbt/util/concurrency/processes.rb +1 -1
  15. data/lib/rbbt/util/migrate.rb +1 -2
  16. data/lib/rbbt/util/misc/inspect.rb +1 -0
  17. data/lib/rbbt/util/open.rb +6 -0
  18. data/lib/rbbt/util/ssh.rb +1 -1
  19. data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +1 -1
  20. data/lib/rbbt/workflow/step/dependencies.rb +3 -4
  21. data/lib/rbbt/workflow/step.rb +2 -2
  22. data/lib/rbbt/workflow/usage.rb +1 -1
  23. data/lib/rbbt/workflow/util/trace.rb +2 -1
  24. data/lib/rbbt/workflow.rb +3 -2
  25. data/share/Rlib/util.R +12 -0
  26. data/share/rbbt_commands/hpc/list +2 -0
  27. data/share/rbbt_commands/hpc/orchestrate +1 -1
  28. data/share/rbbt_commands/hpc/task +8 -7
  29. data/share/rbbt_commands/lsf/list +2 -0
  30. data/share/rbbt_commands/lsf/orchestrate +1 -1
  31. data/share/rbbt_commands/lsf/task +8 -7
  32. data/share/rbbt_commands/resource/claims +57 -0
  33. data/share/rbbt_commands/slurm/list +2 -0
  34. data/share/rbbt_commands/slurm/orchestrate +1 -1
  35. data/share/rbbt_commands/slurm/task +8 -7
  36. data/share/rbbt_commands/workflow/task +2 -2
  37. data/test/rbbt/hpc/test_pbs.rb +43 -0
  38. data/test/rbbt/test_tsv.rb +16 -1
  39. data/test/rbbt/tsv/parallel/test_traverse.rb +2 -2
  40. data/test/rbbt/tsv/test_util.rb +14 -0
  41. data/test/rbbt/util/test_migrate.rb +2 -2
  42. metadata +100 -96
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1121593dec25c29d7986047727d555ed0e75df6b158f9f1332764ad4886462c5
4
- data.tar.gz: c8e39ef65e23445cf5d0c8817af961a9206016c5e3665d87e042f0fadec2b8df
3
+ metadata.gz: '088ac190b36a176e420d4bb1d7b8d28d777133568e45530219f6a0212a1a1144'
4
+ data.tar.gz: 47bdc31d247e5fd5d944f493690e8181bcc236cee74c61fefd5ce25711edf7da
5
5
  SHA512:
6
- metadata.gz: 22c87766544a52c9c6f0d6da369422a452f553d1a61b82a54674f676a3867a6c1d29028c2efd031563f982cdadbce56d36950c8e100bd34ac2a7e95b39af8a58
7
- data.tar.gz: 0a79edc89dad388bca9b94dfeccba1df64c4294e84c4f19743608038e55f8800181911d787980adae3ec1c715a993430ccbf2bc07d6212485b89843ada93de74
6
+ metadata.gz: 9afce115c221695ee896c1e1f884be9a1ba0f0ae98789a485a906e438252afe8292c5422f3eef57d77089bf55cc0b425988ab9b479b1f422eaa0abb7005cfdfa
7
+ data.tar.gz: 4cf4d1e86ce3ab256609aff4c66a3412ea1a9c0c87db08fd5cdad1b98c95147d452cc69d96009c9791cf698ea43903873ed0e4cebbc861bda85097864bed68e8
@@ -1,5 +1,5 @@
1
1
  module HPC
2
- class SBATCH < Exception;
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::SBATCH, batch_dir
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
@@ -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
- if orchestration_rules_file = options[:orchestration_rules]
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"
@@ -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
+
@@ -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::SBATCH, batch_dir
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
@@ -4,3 +4,4 @@ require 'rbbt/hpc/batch'
4
4
  require 'rbbt/hpc/orchestrate'
5
5
  require 'rbbt/hpc/slurm'
6
6
  require 'rbbt/hpc/lsf'
7
+ require 'rbbt/hpc/pbs'
@@ -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
- unlocated[self.subdir] = "" if self.subdir
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
@@ -400,5 +400,9 @@ module TSV
400
400
  end
401
401
  index
402
402
  end
403
+
404
+ def merge(other)
405
+ self.annotate(super(other))
406
+ end
403
407
  end
404
408
 
@@ -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
- claim, test, block, cmd = TOOLS[tool]
30
+
27
31
  begin
28
32
  if test
29
33
  CMD.cmd(test + " ")
30
34
  else
31
- CMD.cmd("#{tool} --help")
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("#{tool} #{f} 2>&1", :nofail => true).read
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
- tool.to_s
61
+ cmd
58
62
  end
59
63
 
60
64
  def self.versions
@@ -245,7 +245,7 @@ class RbbtProcessQueue
245
245
  end
246
246
  end if @callback_queue
247
247
 
248
- @callback_thread.report_on_exception = false
248
+ @callback_thread.report_on_exception = false if @callback_thread
249
249
 
250
250
  end
251
251
 
@@ -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.medium "Migrating #{source_path} #{options[:files].length} files to #{target} - #{Misc.fingerprint(options[:files])}}" if options[:files]
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? '/'
@@ -455,6 +455,7 @@ module Misc
455
455
  end
456
456
 
457
457
  def self.scan_version_text(text, cmd = nil)
458
+ text = Misc.fixutf8 text
458
459
  cmd = "NOCMDGIVE" if cmd.nil? || cmd.empty?
459
460
  text.split("\n").each do |line|
460
461
  next unless line =~ /\W#{cmd}\W/i
@@ -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
@@ -9,7 +9,7 @@ class SSHLine
9
9
  @ssh = Net::SSH.start(@host, @user)
10
10
 
11
11
  @ch = @ssh.open_channel do |ch|
12
- ch.exec 'bash'
12
+ ch.exec 'bash -l'
13
13
  end
14
14
 
15
15
  @ch.on_data do |_,data|
@@ -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.medium "Migrating #{migrate_dependencies.length} dependencies from #{Misc.fingerprint job_list} to #{ server }"
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 self.done? && connected && ! updatable?
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
@@ -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|
@@ -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 and task.input_options[i][:select_options]
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('tidyverse')
84
+ rbbt.require('dplyr')
85
+ rbbt.require('tidyr')
85
86
  rbbt.require('ggplot2')
86
87
 
87
88
  names(data) <- make.names(names(data))