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.
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))