rbbt-util 5.2.3 → 5.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/bin/rbbt +27 -1
- data/bin/rbbt_monitor.rb +6 -2
- data/lib/rbbt/persist.rb +4 -4
- data/lib/rbbt/persist/tsv.rb +1 -1
- data/lib/rbbt/tsv/attach.rb +8 -2
- data/lib/rbbt/tsv/attach/util.rb +1 -1
- data/lib/rbbt/util/log.rb +1 -1
- data/lib/rbbt/util/misc.rb +32 -0
- data/lib/rbbt/util/simpleopt.rb +168 -7
- data/lib/rbbt/workflow.rb +7 -6
- data/lib/rbbt/workflow/step.rb +15 -8
- data/lib/rbbt/workflow/usage.rb +4 -36
- data/share/rbbt_commands/app/start +2 -1
- data/share/rbbt_commands/workflow/task +36 -17
- data/test/rbbt/test_tsv.rb +16 -0
- data/test/rbbt/util/test_misc.rb +4 -0
- metadata +5 -27
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZjIwN2RhYmRjNDg2MjMzMWNmYWU4NGQ5ZDUyYjcyNGU4MmExMzJhYw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NzAyMmUyMjg3ZWRmY2I1N2EwNDk1OGVlNTBmNWUyNmIyNTUxN2QwNg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
M2M0OTlkODVmMjY1ZWNjZWIzYjhjMTE2M2MyOGNiNWY5YjZiYjNiNDdkMTQx
|
10
|
+
MjkyNTk0MWRkZGM4ZjU3OTVjOTQ3ODg3YmNhNjVmZjljZDlmZGU3YTI4YWIw
|
11
|
+
MmFkZjcwMTE5OGFlNmI3MjRkZWI0NTQwZDBlZTg3ZTUwMWJhYjY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZTIxNTBhZGQyZjg0ZjNiYjhlZjU3MTQ4M2YzMzgyNWNlZWE4MWMxNDg2OWUw
|
14
|
+
MzRlMzQyMzkyZWJiNDM1NjQ3ODljNmUwYjg1ZjJhYzYxOWE3MTZjZjc1ZDM3
|
15
|
+
OTI1ZjMzMTNmZDE4Mzc4OTQ3NDJmY2UyYTQzNWRjZDg0MjhlOWI=
|
data/bin/rbbt
CHANGED
@@ -1,8 +1,30 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'rbbt'
|
4
|
+
require 'rbbt/util/simpleopt'
|
4
5
|
|
5
|
-
|
6
|
+
options = SOPT.get("--log* Log level from 0 (debug) 7 (errors):--command_dir* Directory from where to load commands")
|
7
|
+
|
8
|
+
if options[:log]
|
9
|
+
Log.severity = options[:log].to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
if options[:command_dir]
|
13
|
+
$rbbt_command_dir = Path.setup(options[:command_dir])
|
14
|
+
else
|
15
|
+
$rbbt_command_dir = Rbbt.share.rbbt_commands
|
16
|
+
end
|
17
|
+
|
18
|
+
SOPT.synopsys = "rbbt <command> <subcommand> ... -a --arg1 --arg2='value'"
|
19
|
+
SOPT.summary = "Ruby bioinformatics toolkit"
|
20
|
+
SOPT.description = <<-EOF
|
21
|
+
This command controls many aspects of the Rbbt framework, from configuration tasks to running applications.
|
22
|
+
|
23
|
+
Commands are implemented in separate files under the Rbbt path#{
|
24
|
+
} '#{$rbbt_command_dir}'. Known locations are: #{
|
25
|
+
([$rbbt_command_dir] + $rbbt_command_dir.find_all) * ", "
|
26
|
+
}. You can place your own commads at #{$rbbt_command_dir.find(:user)}.
|
27
|
+
EOF
|
6
28
|
|
7
29
|
def commands(prev)
|
8
30
|
rbbt_command_dir = $rbbt_command_dir
|
@@ -35,6 +57,10 @@ while ARGV.any?
|
|
35
57
|
end
|
36
58
|
end
|
37
59
|
|
60
|
+
puts SOPT.doc
|
61
|
+
|
62
|
+
puts "## COMMANDS"
|
63
|
+
puts
|
38
64
|
puts "Command:"
|
39
65
|
puts
|
40
66
|
puts " #{File.basename($0)} #{prev * " "}"
|
data/bin/rbbt_monitor.rb
CHANGED
@@ -50,6 +50,8 @@ def list_jobs(options)
|
|
50
50
|
end
|
51
51
|
|
52
52
|
color = case
|
53
|
+
when (not info)
|
54
|
+
Log::SEVERITY_COLOR[3]
|
53
55
|
when info[:status] == :error
|
54
56
|
Log::SEVERITY_COLOR[3]
|
55
57
|
when (info[:pid] and not running? info)
|
@@ -57,6 +59,8 @@ def list_jobs(options)
|
|
57
59
|
end
|
58
60
|
|
59
61
|
case
|
62
|
+
when (not info)
|
63
|
+
print_job file, info, color
|
60
64
|
when (not omit_ok)
|
61
65
|
print_job file, info, color
|
62
66
|
when options[:zombies]
|
@@ -89,9 +93,9 @@ def clean_jobs(options)
|
|
89
93
|
case
|
90
94
|
when options[:all]
|
91
95
|
remove_job file
|
92
|
-
when (options[:
|
96
|
+
when (options[:errors] and (not info or info[:status] == :error))
|
93
97
|
remove_job file
|
94
|
-
when (options[:
|
98
|
+
when (options[:zombies] and info[:pid] and not running? info)
|
95
99
|
remove_job file
|
96
100
|
end
|
97
101
|
|
data/lib/rbbt/persist.rb
CHANGED
@@ -249,11 +249,11 @@ module Persist
|
|
249
249
|
|
250
250
|
else
|
251
251
|
if is_persisted?(path, persist_options)
|
252
|
-
Log.
|
252
|
+
Log.low "Persist up-to-date: #{ path } - #{persist_options.inspect[0..100]}"
|
253
253
|
return nil if persist_options[:no_load]
|
254
254
|
return load_file(path, type)
|
255
255
|
else
|
256
|
-
Log.
|
256
|
+
Log.medium "Persist create: #{ path } - #{persist_options.inspect[0..100]}"
|
257
257
|
end
|
258
258
|
begin
|
259
259
|
res = yield
|
@@ -262,8 +262,8 @@ module Persist
|
|
262
262
|
end
|
263
263
|
res
|
264
264
|
rescue
|
265
|
-
Log.high "Error in persist. Erasing '#{ path }'"
|
266
|
-
FileUtils.rm path if File.exists? path
|
265
|
+
Log.high "Error in persist. #{File.exists?(path) ? "Erasing '#{ path }'" : ""}"
|
266
|
+
FileUtils.rm path if File.exists? path
|
267
267
|
raise $!
|
268
268
|
end
|
269
269
|
end
|
data/lib/rbbt/persist/tsv.rb
CHANGED
@@ -158,7 +158,7 @@ module Persist
|
|
158
158
|
lock_filename = Persist.persistence_path(path, {:dir => Rbbt.tmp.tsv_open_locks.find})
|
159
159
|
return Misc.lock(lock_filename) do open_tokyocabinet(path, false); end
|
160
160
|
else
|
161
|
-
Log.
|
161
|
+
Log.medium "TSV persistence creating: #{ path }"
|
162
162
|
end
|
163
163
|
|
164
164
|
FileUtils.rm path if File.exists? path
|
data/lib/rbbt/tsv/attach.rb
CHANGED
@@ -48,13 +48,16 @@ module TSV
|
|
48
48
|
end
|
49
49
|
|
50
50
|
# Merge two files with the same keys and different fields
|
51
|
-
def self.merge_different_fields(file1, file2, output, sep = "\t")
|
51
|
+
def self.merge_different_fields(file1, file2, output, sep = "\t", monitor = false)
|
52
52
|
case
|
53
53
|
when (String === file1 and not file1 =~ /\n/ and file1.length < 250 and File.exists?(file1))
|
54
|
+
size = CMD.cmd("wc -l '#{file1}'").read.to_f if monitor
|
54
55
|
file1 = CMD.cmd("sort -k1,1 -t'#{sep}' #{ file1 } | grep -v '^#{sep}' ", :pipe => true)
|
55
56
|
when (String === file1 or StringIO === file1)
|
57
|
+
size = file1.length if monitor
|
56
58
|
file1 = CMD.cmd("sort -k1,1 -t'#{sep}' | grep -v '^#{sep}'", :in => file1, :pipe => true)
|
57
59
|
when TSV === file1
|
60
|
+
size = file1.size if monitor
|
58
61
|
file1 = CMD.cmd("sort -k1,1 -t'#{sep}' | grep -v '^#{sep}'", :in => file1.to_s(:sort, true), :pipe => true)
|
59
62
|
end
|
60
63
|
|
@@ -88,6 +91,8 @@ module TSV
|
|
88
91
|
cols2 = parts2.length
|
89
92
|
end
|
90
93
|
|
94
|
+
progress_monitor = Progress::Bar.new(size, 0, 100, "Merging fields") if monitor
|
95
|
+
|
91
96
|
key = key1 < key2 ? key1 : key2
|
92
97
|
parts = [""] * (cols1 + cols2)
|
93
98
|
while not (done1 and done2)
|
@@ -99,6 +104,7 @@ module TSV
|
|
99
104
|
while key1.nil? and not done1
|
100
105
|
if file1.eof?; done1 = true; else key1, *parts1 = file1.gets.sub("\n",'').split(sep, -1) end
|
101
106
|
end
|
107
|
+
progress_monitor.tick if monitor
|
102
108
|
end
|
103
109
|
while (not done2 and key2 == key)
|
104
110
|
parts2.each_with_index do |part, i|
|
@@ -151,7 +157,7 @@ module TSV
|
|
151
157
|
end
|
152
158
|
|
153
159
|
other_filename = other.respond_to?(:filename) ? other.filename : other.inspect
|
154
|
-
Log.
|
160
|
+
Log.low("Attaching fields:#{fields.inspect} from #{other_filename}.")
|
155
161
|
|
156
162
|
case
|
157
163
|
when key_field == other.key_field
|
data/lib/rbbt/tsv/attach/util.rb
CHANGED
@@ -229,7 +229,7 @@ module TSV
|
|
229
229
|
|
230
230
|
traversal_ids = path.collect{|p| p.first}
|
231
231
|
|
232
|
-
Log.
|
232
|
+
Log.debug "Found Traversal: #{traversal_ids * " => "}"
|
233
233
|
|
234
234
|
data_key, data_file = path.shift
|
235
235
|
data_index = if data_key == data_file.key_field
|
data/lib/rbbt/util/log.rb
CHANGED
@@ -25,7 +25,7 @@ module Log
|
|
25
25
|
# @severity
|
26
26
|
#end
|
27
27
|
|
28
|
-
SEVERITY_COLOR = ["0;37m", "0;32m", "0;33m", "0;31m", "
|
28
|
+
SEVERITY_COLOR = ["0;37m", "0;32m", "0;33m", "0;31m","0;37m", "0;32m", "0;33m"].collect{|e| "\033[#{e}"}
|
29
29
|
|
30
30
|
def self.log(message, severity = MEDIUM)
|
31
31
|
message ||= ""
|
data/lib/rbbt/util/misc.rb
CHANGED
@@ -19,6 +19,38 @@ end
|
|
19
19
|
module Misc
|
20
20
|
class FieldNotFoundError < StandardError;end
|
21
21
|
|
22
|
+
def self.correct_icgc_mutation(pos, ref, mut_str)
|
23
|
+
mut = mut_str
|
24
|
+
mut = '-' * (mut_str.length - 1) if mut =~/^-[ACGT]/
|
25
|
+
[pos, [mut]]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.correct_vcf_mutation(pos, ref, mut_str)
|
29
|
+
muts = mut_str.nil? ? [] : mut_str.split(',')
|
30
|
+
|
31
|
+
while ref.length >= 1 and muts.reject{|m| m[0] == ref[0]}.empty?
|
32
|
+
ref = ref[1..-1]
|
33
|
+
pos = pos + 1
|
34
|
+
muts = muts.collect{|m| m[1..-1]}
|
35
|
+
end
|
36
|
+
|
37
|
+
muts = muts.collect do |m|
|
38
|
+
case
|
39
|
+
when ref.empty?
|
40
|
+
"+" << m
|
41
|
+
when (m.length < ref.length and (m.empty? or ref.index(m)))
|
42
|
+
"-" * (ref.length - m.length)
|
43
|
+
when (ref.length == 1 and m.length == 1)
|
44
|
+
m
|
45
|
+
else
|
46
|
+
Log.debug "Cannot understand: #{[ref, m]} (#{ muts })"
|
47
|
+
'-' * ref.length + m
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
[pos, muts]
|
52
|
+
end
|
53
|
+
|
22
54
|
def self.pid_exists?(pid)
|
23
55
|
return false if pid.nil?
|
24
56
|
begin
|
data/lib/rbbt/util/simpleopt.rb
CHANGED
@@ -1,17 +1,178 @@
|
|
1
1
|
module SOPT
|
2
|
+
class << self
|
3
|
+
attr_accessor :command, :summary, :synopsys, :description
|
4
|
+
attr_accessor :inputs, :input_shortcuts, :input_types, :input_descriptions, :input_defaults
|
5
|
+
|
6
|
+
def command
|
7
|
+
@command ||= File.basename($0)
|
8
|
+
end
|
9
|
+
|
10
|
+
def summary
|
11
|
+
@summary ||= ""
|
12
|
+
end
|
13
|
+
|
14
|
+
def synopsys
|
15
|
+
@synopsys ||= begin
|
16
|
+
"#{command} " <<
|
17
|
+
inputs.collect{|name|
|
18
|
+
"[" << input_format(name, input_types[name] || :string, input_defaults[name], input_shortcuts[name]).sub(/:$/,'') << "]"
|
19
|
+
} * " "
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def description
|
24
|
+
@description ||= "Missing"
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def shortcuts
|
29
|
+
@shortcuts ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
def all
|
33
|
+
@all ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def inputs
|
37
|
+
@inputs ||= []
|
38
|
+
end
|
39
|
+
|
40
|
+
def input_shortcuts
|
41
|
+
@input_shortcuts ||= {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def input_types
|
45
|
+
@input_types ||= {}
|
46
|
+
end
|
47
|
+
|
48
|
+
def input_descriptions
|
49
|
+
@input_descriptions ||= {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def input_defaults
|
53
|
+
@input_defaults ||= {}
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def reset
|
58
|
+
@shortcuts = []
|
59
|
+
@all = {}
|
60
|
+
end
|
61
|
+
|
62
|
+
def record(info)
|
63
|
+
input = info[:long].sub("--", '')
|
64
|
+
inputs << input
|
65
|
+
input_types[input] = info[:arg] ? :string : :boolean
|
66
|
+
input_descriptions[input] = info[:description]
|
67
|
+
input_defaults[input] = info[:default]
|
68
|
+
input_shortcuts[input] = info[:short]? info[:short].sub("-",'') : nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def self.short_for(name)
|
74
|
+
short = []
|
75
|
+
chars = name.to_s.chars.to_a
|
76
|
+
|
77
|
+
short << chars.shift
|
78
|
+
shortcuts = input_shortcuts.values.compact.flatten
|
79
|
+
while shortcuts.include? short * "" and chars.any?
|
80
|
+
short << chars.shift
|
81
|
+
end
|
82
|
+
return nil if chars.empty?
|
83
|
+
|
84
|
+
short * ""
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.input_format(name, type = nil, default = nil, short = "")
|
88
|
+
short = short_for(name) if not short.nil? and short.empty?
|
89
|
+
|
90
|
+
input_str = short.nil? ? "--#{name}" : "-#{short}, --#{name}"
|
91
|
+
input_str << case type
|
92
|
+
when nil
|
93
|
+
"#{default != nil ? " (default '#{default}')" : ""}:"
|
94
|
+
when :boolean
|
95
|
+
"[=false]#{default != nil ? " (default '#{default}')" : ""}:"
|
96
|
+
when :tsv, :text
|
97
|
+
"=<filename.#{type}|->#{default != nil ? " (default '#{default}')" : ""}; Use '-' for STDIN:"
|
98
|
+
when :array
|
99
|
+
"=<string[,string]*|filename.list|->#{default != nil ? " (default '#{default}')" : ""}; Use '-' for STDIN:"
|
100
|
+
else
|
101
|
+
"=<#{ type }>#{default != nil ? " (default '#{default}')" : ""}:"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil)
|
106
|
+
type = description = default = nil
|
107
|
+
shortcut = ""
|
108
|
+
inputs.collect do |name|
|
109
|
+
|
110
|
+
type = input_types[name] unless input_types.nil?
|
111
|
+
description = input_descriptions[name] unless input_descriptions.nil?
|
112
|
+
default = input_defaults[name] unless input_defaults.nil?
|
113
|
+
shortcut = input_shortcuts[name] unless input_shortcuts.nil?
|
114
|
+
|
115
|
+
type = :string if type.nil?
|
116
|
+
|
117
|
+
str = " * " << SOPT.input_format(name, type.to_sym, default, shortcut) << "\n"
|
118
|
+
str << " " << description << "\n" if description and not description.empty?
|
119
|
+
str
|
120
|
+
end * "\n"
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.doc
|
124
|
+
doc = <<-EOF
|
125
|
+
#{command}(1) -- #{summary}
|
126
|
+
#{"=" * (command.length + summary.length + 7)}
|
127
|
+
|
128
|
+
## SYNOPSYS
|
129
|
+
|
130
|
+
#{synopsys}
|
131
|
+
|
132
|
+
## DESCRIPTION
|
133
|
+
|
134
|
+
#{description}
|
135
|
+
|
136
|
+
## OPTIONS
|
137
|
+
|
138
|
+
#{input_doc(inputs, input_types, input_descriptions, input_defaults, input_shortcuts)}
|
139
|
+
EOF
|
140
|
+
end
|
141
|
+
|
2
142
|
def self.name(info)
|
3
143
|
(info[:long] || info[:short]).sub(/^-*/,'')
|
4
144
|
end
|
5
145
|
|
6
146
|
def self.parse(opts)
|
7
147
|
info = {}
|
148
|
+
|
8
149
|
opts.split(/:/).each do |opt|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
150
|
+
next if opt.strip.empty?
|
151
|
+
|
152
|
+
short, long = opt.strip.sub(/(^[^\s]*)\*/,'\1').split('--').values_at(0,1)
|
153
|
+
long, short = short, nil if long.nil?
|
154
|
+
|
155
|
+
if long.index(" ")
|
156
|
+
long, description = long.match(/^([^\s]+)\s+(.*)/).values_at 1, 2
|
157
|
+
else
|
158
|
+
description = nil
|
159
|
+
end
|
160
|
+
|
161
|
+
i= { :arg => !!opt.match(/^[^\s]*\*/) }
|
162
|
+
|
163
|
+
i[:short] = short unless short.nil? || short.empty?
|
164
|
+
i[:long] = '--' + long unless long.nil? || long.empty?
|
165
|
+
i[:description] = description unless description.nil? || description.empty?
|
166
|
+
|
167
|
+
if shortcuts.include? short
|
168
|
+
i[:short] = short_for(i[:long])
|
169
|
+
Log.debug("Short for #{ long } is taken. Changed to #{i[:short]}")
|
170
|
+
else
|
171
|
+
shortcuts << i[:short] if short
|
172
|
+
end
|
173
|
+
|
174
|
+
record(i)
|
175
|
+
|
15
176
|
info[name(i)] = i
|
16
177
|
end
|
17
178
|
|
@@ -51,7 +212,7 @@ module SOPT
|
|
51
212
|
end
|
52
213
|
options[name.to_sym] = value
|
53
214
|
else
|
54
|
-
options[name.to_sym] = true
|
215
|
+
options[name.to_sym] = value == "false" ? false : true
|
55
216
|
end
|
56
217
|
else
|
57
218
|
rest << orig_arg
|
data/lib/rbbt/workflow.rb
CHANGED
@@ -41,14 +41,14 @@ module Workflow
|
|
41
41
|
when ((File.exists?(wf_name.find) and not File.directory?(wf_name.find)) or File.exists?(wf_name.find + '.rb'))
|
42
42
|
$LOAD_PATH.unshift(File.join(File.expand_path(File.dirname(wf_name.find)), 'lib'))
|
43
43
|
require wf_name.find
|
44
|
-
Log.
|
44
|
+
Log.medium "Workflow loaded from file: #{ wf_name }"
|
45
45
|
return true
|
46
46
|
|
47
47
|
# Points to workflow dir
|
48
48
|
when (File.exists?(wf_name.find) and File.directory?(wf_name.find) and File.exists?(File.join(wf_name.find, 'workflow.rb')))
|
49
49
|
$LOAD_PATH.unshift(File.join(File.expand_path(wf_name.find), 'lib'))
|
50
50
|
require File.join(wf_name.find, 'workflow.rb')
|
51
|
-
Log.
|
51
|
+
Log.medium "Workflow loaded from directory: #{ wf_name }"
|
52
52
|
return true
|
53
53
|
|
54
54
|
else
|
@@ -61,7 +61,7 @@ module Workflow
|
|
61
61
|
when ((File.exists?(wf_name) and not File.directory?(wf_name)) or File.exists?(wf_name + '.rb'))
|
62
62
|
$LOAD_PATH.unshift(File.join(File.expand_path(File.dirname(wf_name)), 'lib'))
|
63
63
|
require wf_name
|
64
|
-
Log.
|
64
|
+
Log.medium "Workflow loaded from file: #{ wf_name }"
|
65
65
|
return true
|
66
66
|
|
67
67
|
when (defined?(Rbbt) and Rbbt.etc.workflow_dir.exists?)
|
@@ -69,21 +69,21 @@ module Workflow
|
|
69
69
|
dir = File.join(dir, wf_name)
|
70
70
|
$LOAD_PATH.unshift(File.join(File.expand_path(dir), 'lib'))
|
71
71
|
require File.join(dir, 'workflow.rb')
|
72
|
-
Log.
|
72
|
+
Log.medium "Workflow #{wf_name} loaded from workflow_dir: #{ dir }"
|
73
73
|
return true
|
74
74
|
|
75
75
|
when defined?(Rbbt)
|
76
76
|
path = Rbbt.workflows[wf_name].find
|
77
77
|
$LOAD_PATH.unshift(File.join(File.expand_path(path), 'lib'))
|
78
78
|
require File.join(path, 'workflow.rb')
|
79
|
-
Log.
|
79
|
+
Log.medium "Workflow #{wf_name} loaded from Rbbt.workflows: #{ path }"
|
80
80
|
return true
|
81
81
|
|
82
82
|
else
|
83
83
|
path = File.join(ENV['HOME'], '.workflows', wf_name)
|
84
84
|
$LOAD_PATH.unshift(File.join(File.expand_path(path), 'lib'))
|
85
85
|
require File.join(path, 'workflow.rb')
|
86
|
-
Log.
|
86
|
+
Log.medium "Workflow #{wf_name} loaded from .workflows: #{ path }"
|
87
87
|
return true
|
88
88
|
end
|
89
89
|
end
|
@@ -211,6 +211,7 @@ module Workflow
|
|
211
211
|
path = File.join(workdir, id)
|
212
212
|
task = task_for path
|
213
213
|
step = Step.new path, tasks[task.to_sym]
|
214
|
+
step.info
|
214
215
|
if step.info.include? :dependencies
|
215
216
|
step.dependencies = step.info[:dependencies].collect do |task, job|
|
216
217
|
load_id(File.join(task.to_s, job))
|
data/lib/rbbt/workflow/step.rb
CHANGED
@@ -68,16 +68,14 @@ class Step
|
|
68
68
|
|
69
69
|
def join
|
70
70
|
if @pid.nil?
|
71
|
-
|
72
|
-
sleep 5
|
73
|
-
end
|
71
|
+
self
|
74
72
|
else
|
75
|
-
Log.debug "Waiting for pid: #{@pid}"
|
76
73
|
begin
|
77
|
-
|
74
|
+
Log.debug "Waiting for pid: #{@pid}"
|
75
|
+
Process.waitpid @pid
|
78
76
|
rescue Errno::ECHILD
|
79
77
|
Log.debug "Process #{ @pid } already finished: #{ path }"
|
80
|
-
end
|
78
|
+
end if Misc.pid_exists? @pid
|
81
79
|
@pid = nil
|
82
80
|
end
|
83
81
|
self
|
@@ -108,7 +106,8 @@ class Step
|
|
108
106
|
end
|
109
107
|
}
|
110
108
|
|
111
|
-
|
109
|
+
Log.medium("Starting task #{task.name || ""} [#{Process.pid}]: #{ path }")
|
110
|
+
set_info :status, :started
|
112
111
|
|
113
112
|
set_info :started, Time.now
|
114
113
|
|
@@ -147,6 +146,8 @@ class Step
|
|
147
146
|
end
|
148
147
|
|
149
148
|
set_info :status, :done
|
149
|
+
set_info :done, Time.now
|
150
|
+
Log.medium("Completed task #{task.name || ""} [#{Process.pid}]: #{ path }")
|
150
151
|
res
|
151
152
|
end
|
152
153
|
|
@@ -164,6 +165,12 @@ class Step
|
|
164
165
|
FileUtils.mkdir_p File.dirname(path) unless File.exists? File.dirname(path)
|
165
166
|
begin
|
166
167
|
run
|
168
|
+
rescue Exception
|
169
|
+
Log.debug("Exception caught on forked process: #{$!.message}")
|
170
|
+
exit -1
|
171
|
+
end
|
172
|
+
|
173
|
+
begin
|
167
174
|
children_pids = info[:children_pids]
|
168
175
|
if children_pids
|
169
176
|
children_pids.each do |pid|
|
@@ -177,7 +184,7 @@ class Step
|
|
177
184
|
end
|
178
185
|
end
|
179
186
|
rescue Exception
|
180
|
-
Log.debug("Exception
|
187
|
+
Log.debug("Exception waiting for children: #{$!.message}")
|
181
188
|
exit -1
|
182
189
|
end
|
183
190
|
set_info :pid, nil
|
data/lib/rbbt/workflow/usage.rb
CHANGED
@@ -1,28 +1,11 @@
|
|
1
|
+
require 'rbbt/util/simpleopt'
|
1
2
|
|
2
3
|
module Task
|
3
4
|
def doc(deps = nil)
|
4
|
-
|
5
5
|
puts "## #{ name }:"
|
6
6
|
puts "\n" << description if description and not description.empty?
|
7
|
-
puts
|
8
|
-
|
9
|
-
inputs.each do |name|
|
10
|
-
short = name.to_s.chars.first
|
11
|
-
|
12
|
-
description = input_descriptions[name]
|
13
|
-
default = input_defaults[name]
|
14
|
-
type = input_types[name]
|
15
|
-
|
16
|
-
|
17
|
-
if type.to_sym == :boolean
|
18
|
-
puts " * -#{short}, --#{name}[=<true|false>]#{default != nil ? " (default: #{default})" : ""}:"
|
19
|
-
else
|
20
|
-
puts " * -#{short}, --#{name}=<#{ type }>#{default != nil ? " (default: #{default})" : ""}:"
|
21
|
-
end
|
22
|
-
|
23
|
-
puts " " << description if description and not description.empty?
|
24
|
-
puts
|
25
|
-
end
|
7
|
+
puts
|
8
|
+
puts SOPT.input_doc(inputs, input_types, input_descriptions, input_defaults)
|
26
9
|
|
27
10
|
if deps and deps.any?
|
28
11
|
puts
|
@@ -31,22 +14,7 @@ module Task
|
|
31
14
|
deps.each do |dep|
|
32
15
|
puts " #{dep.name}:"
|
33
16
|
puts
|
34
|
-
dep.inputs.
|
35
|
-
short = name.to_s.chars.first
|
36
|
-
|
37
|
-
description = dep.input_descriptions[name]
|
38
|
-
default = dep.input_defaults[name]
|
39
|
-
type = dep.input_types[name]
|
40
|
-
|
41
|
-
if type.to_sym == :boolean
|
42
|
-
puts " * -#{short}, --#{name}[=<true|false>]#{default != nil ? " (default: #{default})" : ""}:"
|
43
|
-
else
|
44
|
-
puts " * -#{short}, --#{name}=<#{ type }>#{default != nil ? " (default: #{default})" : ""}:"
|
45
|
-
end
|
46
|
-
|
47
|
-
puts " " << description if description and not description.empty?
|
48
|
-
puts
|
49
|
-
end
|
17
|
+
puts SOPT.input_doc(dep.inputs, dep.input_types, dep.input_descriptions, dep.input_defaults)
|
50
18
|
end
|
51
19
|
end
|
52
20
|
end
|
@@ -14,5 +14,6 @@ app_dir = app_dir[app]
|
|
14
14
|
server = options[:server] || 'thin'
|
15
15
|
|
16
16
|
Misc.in_dir(app_dir) do
|
17
|
-
|
17
|
+
`env RBBT_LOG=#{Log.severity} #{options.include?(:environment)? "env RACK_ENV=#{options[:environment]}" : ""} \
|
18
|
+
#{server} start -p #{options[:port]} #{ARGV.collect{|a| "'#{a}'"} * " "}`
|
18
19
|
end
|
@@ -5,6 +5,9 @@ require 'rbbt/workflow'
|
|
5
5
|
require 'rbbt/workflow/usage'
|
6
6
|
|
7
7
|
def usage(workflow = nil, task = nil)
|
8
|
+
puts SOPT.doc
|
9
|
+
puts "## WORKFLOW"
|
10
|
+
puts
|
8
11
|
if workflow.nil?
|
9
12
|
puts "No workflow specified"
|
10
13
|
exit -1
|
@@ -14,6 +17,9 @@ def usage(workflow = nil, task = nil)
|
|
14
17
|
workflow.load_tasks if workflow.respond_to? :load_tasks
|
15
18
|
workflow.doc
|
16
19
|
else
|
20
|
+
puts workflow.to_s
|
21
|
+
puts "=" * workflow.to_s.length
|
22
|
+
puts
|
17
23
|
workflow.doc(task)
|
18
24
|
end
|
19
25
|
|
@@ -94,7 +100,14 @@ def fix_options(workflow, task, job_options)
|
|
94
100
|
job_options_cleaned
|
95
101
|
end
|
96
102
|
|
97
|
-
options = SOPT.get
|
103
|
+
options = SOPT.get <<EOF
|
104
|
+
-h--help Show this help:
|
105
|
+
-as--array_separator* Change the character that separates elements of Arrays, ',', '|', or '\\n' by default:
|
106
|
+
-cl--clean Clean the last step of the job so that it gets recomputed:
|
107
|
+
-rcl--recursive_clean Clean the last step and its dependencies to recompute the job completely:
|
108
|
+
-n--name* Job name to use. The name 'Default' is used by default:
|
109
|
+
-pn--printname Print the name of the job and exit without starting it:
|
110
|
+
EOF
|
98
111
|
|
99
112
|
workflow = ARGV.shift
|
100
113
|
usage if workflow.nil?
|
@@ -103,9 +116,9 @@ task = ARGV.shift
|
|
103
116
|
|
104
117
|
|
105
118
|
# Set log, fork, clean, recursive_clean and help
|
106
|
-
Log.severity = options[:log].to_i if options.include? :log
|
107
119
|
help = !!options.delete(:help)
|
108
120
|
do_fork = !!options.delete(:fork)
|
121
|
+
do_exec = !!options.delete(:exec)
|
109
122
|
clean = !!options.delete(:clean)
|
110
123
|
recursive_clean = !!options.delete(:recursive_clean)
|
111
124
|
$array_separator = options.delete(:array_separator)
|
@@ -155,7 +168,7 @@ job_options = fix_options(workflow, task, job_options)
|
|
155
168
|
job = workflow.job(task.name, name, job_options)
|
156
169
|
|
157
170
|
# clean job
|
158
|
-
if clean and job.done?
|
171
|
+
if clean and job.done? != false
|
159
172
|
job.clean
|
160
173
|
sleep 1
|
161
174
|
job = workflow.job(task.name, name, job_options)
|
@@ -168,6 +181,21 @@ if recursive_clean and job.done?
|
|
168
181
|
end
|
169
182
|
|
170
183
|
# run
|
184
|
+
if do_exec
|
185
|
+
res = job.exec
|
186
|
+
case
|
187
|
+
when Array === res
|
188
|
+
puts res * "\n"
|
189
|
+
when TSV === res
|
190
|
+
puts res
|
191
|
+
when Hash === res
|
192
|
+
puts res.to_yaml
|
193
|
+
else
|
194
|
+
puts res
|
195
|
+
end
|
196
|
+
exit 0
|
197
|
+
end
|
198
|
+
|
171
199
|
if do_fork
|
172
200
|
job.fork
|
173
201
|
while not job.done?
|
@@ -175,30 +203,21 @@ if do_fork
|
|
175
203
|
sleep 2
|
176
204
|
end
|
177
205
|
raise job.messages.last if job.error?
|
178
|
-
if $array_separator
|
179
|
-
res = job.load(:sep2 => $array_separator)
|
180
|
-
else
|
181
|
-
res = job.load
|
182
|
-
end
|
183
206
|
else
|
184
|
-
res = job.run
|
207
|
+
res = job.run(true)
|
185
208
|
end
|
186
209
|
|
187
210
|
if options.delete(:printname)
|
188
211
|
puts job.name
|
189
|
-
exit
|
212
|
+
exit 0
|
190
213
|
else
|
191
214
|
Log.low "Job name: #{job.name}"
|
192
215
|
end
|
193
216
|
|
194
|
-
|
195
|
-
|
196
|
-
puts res * "\n"
|
197
|
-
when TSV === res
|
198
|
-
puts res
|
199
|
-
when Hash === res
|
200
|
-
puts res.to_yaml
|
217
|
+
if Step === res
|
218
|
+
puts Open.read(res.path)
|
201
219
|
else
|
202
220
|
puts res
|
203
221
|
end
|
204
222
|
|
223
|
+
exit 0
|
data/test/rbbt/test_tsv.rb
CHANGED
@@ -420,6 +420,22 @@ row2 b bbb bbbb bb
|
|
420
420
|
end
|
421
421
|
end
|
422
422
|
|
423
|
+
def test_flat_key
|
424
|
+
content =<<-EOF
|
425
|
+
#Id ValueA
|
426
|
+
row1 a aa aaa
|
427
|
+
row2 b bbb bbbb bb aa
|
428
|
+
EOF
|
429
|
+
|
430
|
+
TmpFile.with_file(content) do |filename|
|
431
|
+
tsv = TSV.open(filename, :sep => /\s+/, :merge => true, :type => :flat, :key_field => "ValueA")
|
432
|
+
assert_equal ["row1"], tsv["a"]
|
433
|
+
assert_equal ["row1", "row2"], tsv["aa"]
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
|
438
|
+
|
423
439
|
def test_zipped
|
424
440
|
content =<<-EOF
|
425
441
|
#Id ValueA ValueB
|
data/test/rbbt/util/test_misc.rb
CHANGED
@@ -220,4 +220,8 @@ class TestMisc < Test::Unit::TestCase
|
|
220
220
|
assert_equal "ACRONIM_test", Misc.snake_case(str1)
|
221
221
|
assert_equal "ACRONIM_test", Misc.snake_case(str2)
|
222
222
|
end
|
223
|
+
|
224
|
+
def test_correct_vcf_mutations
|
225
|
+
assert_equal [737407, ["-----", "-----G", "-----GTTAAT"]], Misc.correct_vcf_mutation(737406, "GTTAAT", "G,GG,GGTTAAT")
|
226
|
+
end
|
223
227
|
end
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.2.
|
5
|
-
prerelease:
|
4
|
+
version: 5.2.4
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Miguel Vazquez
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-27 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ! '>='
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ! '>='
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: spreadsheet
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ! '>='
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ! '>='
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: ruby-prof
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ! '>='
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ! '>='
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -62,7 +55,6 @@ dependencies:
|
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: tokyocabinet
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - ! '>='
|
68
60
|
- !ruby/object:Gem::Version
|
@@ -70,7 +62,6 @@ dependencies:
|
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
66
|
- - ! '>='
|
76
67
|
- !ruby/object:Gem::Version
|
@@ -78,7 +69,6 @@ dependencies:
|
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: progress-monitor
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
73
|
- - ! '>='
|
84
74
|
- !ruby/object:Gem::Version
|
@@ -86,7 +76,6 @@ dependencies:
|
|
86
76
|
type: :runtime
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
80
|
- - ! '>='
|
92
81
|
- !ruby/object:Gem::Version
|
@@ -94,7 +83,6 @@ dependencies:
|
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: lockfile
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
87
|
- - ! '>='
|
100
88
|
- !ruby/object:Gem::Version
|
@@ -102,7 +90,6 @@ dependencies:
|
|
102
90
|
type: :runtime
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
94
|
- - ! '>='
|
108
95
|
- !ruby/object:Gem::Version
|
@@ -110,7 +97,6 @@ dependencies:
|
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: RubyInline
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
101
|
- - ! '>='
|
116
102
|
- !ruby/object:Gem::Version
|
@@ -118,7 +104,6 @@ dependencies:
|
|
118
104
|
type: :runtime
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
108
|
- - ! '>='
|
124
109
|
- !ruby/object:Gem::Version
|
@@ -126,7 +111,6 @@ dependencies:
|
|
126
111
|
- !ruby/object:Gem::Dependency
|
127
112
|
name: narray
|
128
113
|
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
114
|
requirements:
|
131
115
|
- - ! '>='
|
132
116
|
- !ruby/object:Gem::Version
|
@@ -134,7 +118,6 @@ dependencies:
|
|
134
118
|
type: :runtime
|
135
119
|
prerelease: false
|
136
120
|
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
121
|
requirements:
|
139
122
|
- - ! '>='
|
140
123
|
- !ruby/object:Gem::Version
|
@@ -142,7 +125,6 @@ dependencies:
|
|
142
125
|
- !ruby/object:Gem::Dependency
|
143
126
|
name: simplews
|
144
127
|
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
128
|
requirements:
|
147
129
|
- - ! '>='
|
148
130
|
- !ruby/object:Gem::Version
|
@@ -150,7 +132,6 @@ dependencies:
|
|
150
132
|
type: :runtime
|
151
133
|
prerelease: false
|
152
134
|
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
135
|
requirements:
|
155
136
|
- - ! '>='
|
156
137
|
- !ruby/object:Gem::Version
|
@@ -158,7 +139,6 @@ dependencies:
|
|
158
139
|
- !ruby/object:Gem::Dependency
|
159
140
|
name: highline
|
160
141
|
requirement: !ruby/object:Gem::Requirement
|
161
|
-
none: false
|
162
142
|
requirements:
|
163
143
|
- - ! '>='
|
164
144
|
- !ruby/object:Gem::Version
|
@@ -166,7 +146,6 @@ dependencies:
|
|
166
146
|
type: :runtime
|
167
147
|
prerelease: false
|
168
148
|
version_requirements: !ruby/object:Gem::Requirement
|
169
|
-
none: false
|
170
149
|
requirements:
|
171
150
|
- - ! '>='
|
172
151
|
- !ruby/object:Gem::Version
|
@@ -286,27 +265,26 @@ files:
|
|
286
265
|
- bin/rbbt_dangling_locks.rb
|
287
266
|
homepage: http://github.com/mikisvaz/rbbt-util
|
288
267
|
licenses: []
|
268
|
+
metadata: {}
|
289
269
|
post_install_message:
|
290
270
|
rdoc_options: []
|
291
271
|
require_paths:
|
292
272
|
- lib
|
293
273
|
required_ruby_version: !ruby/object:Gem::Requirement
|
294
|
-
none: false
|
295
274
|
requirements:
|
296
275
|
- - ! '>='
|
297
276
|
- !ruby/object:Gem::Version
|
298
277
|
version: '0'
|
299
278
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
300
|
-
none: false
|
301
279
|
requirements:
|
302
280
|
- - ! '>='
|
303
281
|
- !ruby/object:Gem::Version
|
304
282
|
version: '0'
|
305
283
|
requirements: []
|
306
284
|
rubyforge_project:
|
307
|
-
rubygems_version:
|
285
|
+
rubygems_version: 2.0.3
|
308
286
|
signing_key:
|
309
|
-
specification_version:
|
287
|
+
specification_version: 4
|
310
288
|
summary: Utilities for the Ruby Bioinformatics Toolkit (rbbt)
|
311
289
|
test_files:
|
312
290
|
- test/rbbt/tsv/test_accessor.rb
|