seqtrimnext 2.0.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +114 -0
  3. data/PostInstall.txt +7 -0
  4. data/README.rdoc +159 -0
  5. data/Rakefile +38 -0
  6. data/bin/create_graphs.rb +46 -0
  7. data/bin/extract_seqs.rb +45 -0
  8. data/bin/extract_seqs_from_fasta.rb +56 -0
  9. data/bin/extract_seqs_from_fastq.rb +45 -0
  10. data/bin/fasta2fastq.rb +38 -0
  11. data/bin/fastq2fasta.rb +35 -0
  12. data/bin/gen_qual.rb +46 -0
  13. data/bin/get_seq.rb +46 -0
  14. data/bin/group_by_range.rb +17 -0
  15. data/bin/join_ilumina_paired.rb +130 -0
  16. data/bin/parse_amplicons.rb +95 -0
  17. data/bin/parse_json_results.rb +66 -0
  18. data/bin/parse_params.rb +82 -0
  19. data/bin/resume_clusters.rb +48 -0
  20. data/bin/resume_rejected.sh +9 -0
  21. data/bin/reverse_paired.rb +49 -0
  22. data/bin/seqtrimnext +368 -0
  23. data/bin/split_fastq.rb +42 -0
  24. data/bin/split_ilumina_paired.rb +65 -0
  25. data/bin/split_paired.rb +70 -0
  26. data/lib/seqtrimnext/actions/action_ab_adapter.rb +32 -0
  27. data/lib/seqtrimnext/actions/action_ab_far_adapter.rb +32 -0
  28. data/lib/seqtrimnext/actions/action_ab_left_adapter.rb +32 -0
  29. data/lib/seqtrimnext/actions/action_empty_insert.rb +22 -0
  30. data/lib/seqtrimnext/actions/action_ignore_repeated.rb +24 -0
  31. data/lib/seqtrimnext/actions/action_indetermination.rb +30 -0
  32. data/lib/seqtrimnext/actions/action_induced_low_complexity.rb +29 -0
  33. data/lib/seqtrimnext/actions/action_insert.rb +32 -0
  34. data/lib/seqtrimnext/actions/action_is_contaminated.rb +30 -0
  35. data/lib/seqtrimnext/actions/action_key.rb +30 -0
  36. data/lib/seqtrimnext/actions/action_left_adapter.rb +32 -0
  37. data/lib/seqtrimnext/actions/action_left_primer.rb +17 -0
  38. data/lib/seqtrimnext/actions/action_linker.rb +30 -0
  39. data/lib/seqtrimnext/actions/action_low_complexity.rb +30 -0
  40. data/lib/seqtrimnext/actions/action_low_high_size.rb +31 -0
  41. data/lib/seqtrimnext/actions/action_low_quality.rb +33 -0
  42. data/lib/seqtrimnext/actions/action_mid.rb +30 -0
  43. data/lib/seqtrimnext/actions/action_multiple_linker.rb +29 -0
  44. data/lib/seqtrimnext/actions/action_paired_reads.rb +28 -0
  45. data/lib/seqtrimnext/actions/action_poly_a.rb +29 -0
  46. data/lib/seqtrimnext/actions/action_poly_t.rb +29 -0
  47. data/lib/seqtrimnext/actions/action_rem_adit_artifacts.rb +32 -0
  48. data/lib/seqtrimnext/actions/action_right_adapter.rb +29 -0
  49. data/lib/seqtrimnext/actions/action_right_primer.rb +25 -0
  50. data/lib/seqtrimnext/actions/action_short_insert.rb +32 -0
  51. data/lib/seqtrimnext/actions/action_unexpected_poly_t.rb +29 -0
  52. data/lib/seqtrimnext/actions/action_unexpected_vector.rb +31 -0
  53. data/lib/seqtrimnext/actions/action_vectors.rb +31 -0
  54. data/lib/seqtrimnext/actions/seqtrim_action.rb +136 -0
  55. data/lib/seqtrimnext/classes/action_manager.rb +47 -0
  56. data/lib/seqtrimnext/classes/em_classes/seqtrim_work_manager.rb +335 -0
  57. data/lib/seqtrimnext/classes/em_classes/seqtrim_worker.rb +290 -0
  58. data/lib/seqtrimnext/classes/extract_stats.rb +255 -0
  59. data/lib/seqtrimnext/classes/gnu_plot_graph.rb +140 -0
  60. data/lib/seqtrimnext/classes/graph_stats.rb +74 -0
  61. data/lib/seqtrimnext/classes/install_database.rb +43 -0
  62. data/lib/seqtrimnext/classes/install_requirements.rb +123 -0
  63. data/lib/seqtrimnext/classes/list_db.rb +49 -0
  64. data/lib/seqtrimnext/classes/make_blast_db.rb +113 -0
  65. data/lib/seqtrimnext/classes/one_blast.rb +41 -0
  66. data/lib/seqtrimnext/classes/params.rb +387 -0
  67. data/lib/seqtrimnext/classes/piro.rb +78 -0
  68. data/lib/seqtrimnext/classes/plugin_manager.rb +153 -0
  69. data/lib/seqtrimnext/classes/scan_for_restr_site.rb +138 -0
  70. data/lib/seqtrimnext/classes/scbi_stats.rb +68 -0
  71. data/lib/seqtrimnext/classes/seqtrim.rb +317 -0
  72. data/lib/seqtrimnext/classes/sequence.rb +55 -0
  73. data/lib/seqtrimnext/classes/sequence_group.rb +72 -0
  74. data/lib/seqtrimnext/classes/sequence_with_action.rb +503 -0
  75. data/lib/seqtrimnext/plugins/plugin.rb +267 -0
  76. data/lib/seqtrimnext/plugins/plugin_ab_adapters.rb +189 -0
  77. data/lib/seqtrimnext/plugins/plugin_adapters.rb +165 -0
  78. data/lib/seqtrimnext/plugins/plugin_amplicons.rb +221 -0
  79. data/lib/seqtrimnext/plugins/plugin_contaminants.rb +209 -0
  80. data/lib/seqtrimnext/plugins/plugin_extract_inserts.rb +438 -0
  81. data/lib/seqtrimnext/plugins/plugin_find_poly_at.rb +393 -0
  82. data/lib/seqtrimnext/plugins/plugin_ignore_repeated.rb +101 -0
  83. data/lib/seqtrimnext/plugins/plugin_indeterminations.rb +199 -0
  84. data/lib/seqtrimnext/plugins/plugin_key.rb +70 -0
  85. data/lib/seqtrimnext/plugins/plugin_linker.rb +232 -0
  86. data/lib/seqtrimnext/plugins/plugin_low_complexity.rb +98 -0
  87. data/lib/seqtrimnext/plugins/plugin_low_high_size.rb +74 -0
  88. data/lib/seqtrimnext/plugins/plugin_low_quality.rb +394 -0
  89. data/lib/seqtrimnext/plugins/plugin_mids.rb +231 -0
  90. data/lib/seqtrimnext/plugins/plugin_rem_adit_artifacts.rb +246 -0
  91. data/lib/seqtrimnext/plugins/plugin_short_insert.rb +244 -0
  92. data/lib/seqtrimnext/plugins/plugin_vectors.rb +191 -0
  93. data/lib/seqtrimnext/templates/amplicons.txt +16 -0
  94. data/lib/seqtrimnext/templates/genomics_454.txt +5 -0
  95. data/lib/seqtrimnext/templates/genomics_454_with_paired.txt +5 -0
  96. data/lib/seqtrimnext/templates/low_quality.txt +5 -0
  97. data/lib/seqtrimnext/templates/low_quality_and_low_complexity.txt +5 -0
  98. data/lib/seqtrimnext/templates/transcriptomics_454.txt +8 -0
  99. data/lib/seqtrimnext/templates/transcriptomics_plants.txt +8 -0
  100. data/lib/seqtrimnext/utils/extract_samples.rb +52 -0
  101. data/lib/seqtrimnext/utils/fasta2xml.rb +69 -0
  102. data/lib/seqtrimnext/utils/global_match.rb +65 -0
  103. data/lib/seqtrimnext/utils/hash_stats.rb +29 -0
  104. data/lib/seqtrimnext/utils/json_utils.rb +50 -0
  105. data/lib/seqtrimnext/utils/load_fasta_names_in_hash.rb +37 -0
  106. data/lib/seqtrimnext/utils/load_qual_in_hash.rb +37 -0
  107. data/lib/seqtrimnext/utils/recover_mid.rb +95 -0
  108. data/lib/seqtrimnext/utils/string_utils.rb +56 -0
  109. data/lib/seqtrimnext.rb +37 -0
  110. data/script/console +10 -0
  111. data/script/destroy +14 -0
  112. data/script/generate +14 -0
  113. data/test/test_helper.rb +3 -0
  114. data/test/test_seqtrimnext.rb +11 -0
  115. metadata +318 -0
@@ -0,0 +1,31 @@
1
+ require "seqtrim_action"
2
+
3
+ ########################################################
4
+ # Author: Almudena Bocinos Rioboo
5
+ #
6
+ # Defines the main methods that are necessary to execute Plugin1
7
+ # Inherit: Plugin
8
+ ########################################################
9
+
10
+ class ActionVectors < SeqtrimAction
11
+
12
+ def initialize(start_pos,end_pos)
13
+ super(start_pos,end_pos)
14
+ @cut =true
15
+
16
+ end
17
+
18
+ # def apply_to(seq)
19
+ #
20
+ # # seq.seq_fasta = seq.seq_fasta.slice(start_pos,end_pos)
21
+ # $LOG.debug " Applying #{self.class} to seq #{seq.seq_name}. BEGIN: #{@start_pos} END: #{@end_pos} "
22
+ #
23
+ # end
24
+
25
+ def apply_decoration(char)
26
+ return char.on_green
27
+ end
28
+
29
+
30
+
31
+ end
@@ -0,0 +1,136 @@
1
+ ######################################
2
+ # Author:: Almudena Bocinos Rioboo
3
+ # This class creates the structures that storage the necessary values from an action
4
+ ######################################
5
+
6
+
7
+ require 'term/ansicolor'
8
+ include Term::ANSIColor
9
+
10
+ class SeqtrimAction
11
+
12
+
13
+ attr_accessor :start_pos , :end_pos, :message, :cut , :reversed , :left_action , :right_action , :found_definition, :tag_id, :informative
14
+
15
+ # Creates the nexts values from an action: start_position, end_position, type
16
+ def initialize(start_pos,end_pos)
17
+ # puts " #{start_pos} #{end_pos} #{self.class.to_s}"
18
+
19
+ @start_pos = start_pos.to_i
20
+ @end_pos = end_pos.to_i
21
+
22
+ #@notes = ''
23
+ @left_action = false
24
+ @right_action = false
25
+ @message = ''
26
+ @found_definition=[] #array when contaminant or vectors definitions are saved, each separately
27
+ @cut = false
28
+ @informative = false
29
+ @reversed = false
30
+ # puts " #{@start_pos} #{@end_pos} #{self.class.to_s}"
31
+ @tag_id =''
32
+
33
+ end
34
+
35
+ def apply_to(seq)
36
+
37
+ $LOG.debug " Applying #{self.class} to seq #{seq.seq_name} . BEGIN: #{@start_pos} END: #{@end_pos} "
38
+
39
+ end
40
+
41
+ def description
42
+
43
+ return "Action Type: #{self.class} Begin: #{start_pos} End: #{end_pos}"
44
+ end
45
+
46
+ def inspect
47
+ description
48
+ end
49
+
50
+
51
+ def contains?(pos)
52
+ return ((pos>=@start_pos) && (pos<=@end_pos))
53
+ end
54
+
55
+
56
+ def contains_action?(start_pos,end_pos,margin=10)
57
+ #puts "#{start_pos}>=#{@start_pos-margin} && #{end_pos}<=#{@end_pos+margin} "
58
+ return ((start_pos>=@start_pos-margin) && (end_pos<=@end_pos+margin))
59
+ end
60
+
61
+ def apply_decoration(char)
62
+ return char
63
+ end
64
+
65
+
66
+
67
+ def decorate(char,pos)
68
+ if contains?(pos)
69
+ return apply_decoration(char)
70
+ else
71
+ return char
72
+ end
73
+ end
74
+
75
+ def type
76
+ return self.class.to_s
77
+ end
78
+ def action_type
79
+
80
+ a_type='INFO'
81
+ if !@informative
82
+ a_type = 'LEFT'
83
+ if right_action
84
+ a_type = 'RIGHT'
85
+ end
86
+ end
87
+ return a_type
88
+
89
+ end
90
+
91
+ def to_human(camel_cased_word)
92
+ word = camel_cased_word.to_s.dup
93
+ word.gsub!(/::/, '/')
94
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1 \2')
95
+ word.gsub!(/([a-z\d])([A-Z])/,'\1 \2')
96
+ word.tr!("-", " ")
97
+ word.downcase!
98
+ word.capitalize!
99
+ word
100
+ end
101
+
102
+ def title
103
+ return to_human(type.gsub('Action',''))
104
+ end
105
+
106
+ def near_left?(seq_fasta_size)
107
+ return ((@start_pos - 0 ) < (seq_fasta_size - @end_pos))
108
+ end
109
+
110
+
111
+ def left_action?(seq_fasta_size)
112
+ res = (@left_action || (!@right_action && near_left?(seq_fasta_size)))
113
+ # @left_action = res
114
+
115
+ return res
116
+ end
117
+
118
+ def right_action?(seq_fasta_size)
119
+ res= (@right_action || !left_action?(seq_fasta_size))
120
+ # @right_action = res
121
+ return res
122
+ end
123
+
124
+ def to_hash
125
+ a = {}
126
+
127
+ a[:type]=type
128
+ a[:start_pos]=@start_pos
129
+ a[:end_pos]=@end_pos
130
+ a[:message]=@message
131
+
132
+ return a
133
+ end
134
+
135
+
136
+ end
@@ -0,0 +1,47 @@
1
+ #########################################
2
+ # Author:: Almudena Bocinos Rioboo
3
+ # This class provided the methods to apply actions to sequences
4
+ #########################################
5
+ require 'seqtrim_action'
6
+ class ActionManager
7
+
8
+ #Storages the necessary plugins specified in 'plugin_list' and start the loading of plugins
9
+ def initialize
10
+
11
+ load_actions_from_files
12
+ end
13
+
14
+ def self.new_action(start_pos,end_pos,action_type)
15
+ action_class = Object.const_get(action_type)
16
+ # DONE mirar si la action_class es de verdad una action existente
17
+ res = nil
18
+ if !action_class.nil? && action_class.ancestors.include?(SeqtrimAction)
19
+ res= action_class.new(start_pos,end_pos)
20
+ else
21
+ #$LOG.error ' Error. Don´t exist the action: ' + action_class.to_s
22
+ puts ' Error. The action : ' + action_class.to_s+ ' does not exists'
23
+ end
24
+ return res
25
+ end
26
+
27
+
28
+
29
+
30
+ # Iterates by the files from the folder 'actions', and load it
31
+ def load_actions_from_files
32
+ ignore = ['.','..','seqtrim_action.rb']
33
+ #carpeta=Dir.open("progs/ruby/seqtrimii/actions")
34
+ actions_path = File.expand_path(File.join(File.dirname(__FILE__), "..","actions"))
35
+ if !File.exists?(actions_path)
36
+ raise "Action folder does not exists"
37
+ end
38
+ carpeta=Dir.open(actions_path)
39
+
40
+ carpeta.entries.each do |action|
41
+ if !ignore.include?(action)
42
+ require action
43
+ end # end if
44
+ end # end each
45
+ end # end def
46
+
47
+ end
@@ -0,0 +1,335 @@
1
+ require 'scbi_fasta'
2
+ require 'scbi_fastq'
3
+ # require 'work_manager'
4
+ require 'graph_stats'
5
+ require 'sequence_with_action'
6
+ require 'sequence_group'
7
+
8
+ # OUTPUT_PATH='output_files'
9
+ STATS_PATH=File.join(OUTPUT_PATH,'stats.json')
10
+ # TODO - Pasar secuencias en grupos, y hacer blast en grupos de secuencias.
11
+
12
+
13
+
14
+ class SeqtrimWorkManager < ScbiMapreduce::WorkManager
15
+
16
+ def self.init_work_manager(sequence_reader, params, chunk_size = 100, use_json=false)
17
+ @@full_stats={}
18
+ @@params= params
19
+ @@exit = false
20
+
21
+ @@chunk_size = chunk_size
22
+
23
+
24
+ # puts "CHECKPOINT: #{self.checkpoint}\n"*20
25
+
26
+ checkpoint_exists=File.exists?('scbi_drb_checkpoint')
27
+
28
+ # @@use_qual = !qual_path.nil? and File.exists?(qual_path)
29
+ @@open_mode='w'
30
+ if checkpoint_exists
31
+ @@open_mode = 'a'
32
+ if File.exists?(STATS_PATH)
33
+ # load stats
34
+ text = File.read(STATS_PATH)
35
+
36
+ # wipe text
37
+ # text=text.grep(/^\s*[^#]/).to_s
38
+
39
+ # decode json
40
+ @@full_stats = JSON.parse(text)
41
+ end
42
+ end
43
+
44
+ #open input file
45
+ @@fqr=sequence_reader
46
+
47
+ # @@use_qual = @@fqr.with_qual?
48
+ # @@use_json = use_json
49
+
50
+ @@params.set_param('use_qual',@@fqr.with_qual?)
51
+ @@params.set_param('use_json',use_json)
52
+
53
+ @@use_json=use_json
54
+
55
+ @@fqr.rewind
56
+
57
+ # open output files
58
+
59
+ if !Dir.exists?(OUTPUT_PATH)
60
+ Dir.mkdir(OUTPUT_PATH)
61
+ end
62
+
63
+ @@files={}
64
+
65
+ # @@rejected_output_file=File.open(File.join(OUTPUT_PATH,'rejected.txt'),@@open_mode)
66
+
67
+ # seqs_with_errors
68
+ @@errors_file=File.open('errors.txt',@@open_mode)
69
+
70
+ if @@use_json
71
+ @@json_output=File.open('results.json',@@open_mode)
72
+ end
73
+
74
+ @@json_separator=''
75
+
76
+ @@paired_output_files={}
77
+
78
+ @@sequences_output_files={}
79
+
80
+ @@low_complexity_output_files={}
81
+
82
+ @@sffinfo_files={}
83
+
84
+ @@low_sffinfo_files={}
85
+
86
+ end
87
+
88
+ def self.end_work_manager
89
+
90
+ puts "FULL STATS:\n" +JSON.pretty_generate(@@full_stats)
91
+
92
+ f = File.open(STATS_PATH,'w')
93
+ f.puts JSON.pretty_generate(@@full_stats)
94
+ f.close
95
+
96
+ r=File.read(STATS_PATH)
97
+
98
+ stats=JSON::parse(r)
99
+
100
+
101
+ gs=GraphStats.new(stats)
102
+
103
+ #gs=GraphStats.new(@@full_stats)
104
+
105
+
106
+ #close all files
107
+
108
+ # @@fqr.close
109
+ if @@use_json
110
+ @@json_output.close
111
+ end
112
+ @@errors_file.close
113
+ # @@rejected_output_file.close
114
+
115
+ # @@paired_output_files.each do |k,file|
116
+ # file.close
117
+ # end
118
+
119
+ @@files.each do |k,file|
120
+ file.close
121
+ end
122
+
123
+ # @@paired_qual_output_files.each do |k,file|
124
+ # file.close
125
+ # end
126
+
127
+ # @@sequences_output_files.each do |k,file|
128
+ # file.close
129
+ # end
130
+ #
131
+ # @@low_complexity_output_files.each do |k,file|
132
+ # file.close
133
+ # end
134
+ #
135
+ # @@sffinfo_files.each do |k,file|
136
+ # file.close
137
+ # end
138
+ #
139
+ # @@low_sffinfo_files.each do |k,file|
140
+ # file.close
141
+ # end
142
+
143
+
144
+ # @@qual_output_files.each do |k,file|
145
+ # file.close
146
+ # end
147
+
148
+ # more than one MID found
149
+ # if @@full_stats['mid_id'] && @@full_stats['mid_id'].count>1
150
+ #
151
+ # end
152
+
153
+ if File.exists?('scbi_drb_checkpoint')
154
+ File.delete('scbi_drb_checkpoint')
155
+ end
156
+ end
157
+
158
+
159
+ def error_received(worker_error, obj)
160
+ @@errors_file.puts "Error while processing object #{obj.inspect}\n" + worker_error.original_exception.message + ":\n" +worker_error.original_exception.backtrace.join("\n")
161
+ @@errors_file.puts "="*60
162
+ end
163
+
164
+ def too_many_errors_received
165
+ $LOG.error "Too many errors: #{@@error_count} errors on #{@@count} executed sequences, exiting before finishing"
166
+ end
167
+
168
+ def worker_initial_config
169
+ return @@params
170
+ end
171
+
172
+ def load_user_checkpoint(checkpoint)
173
+
174
+ # reset count stats since they are repeated by checkpointing
175
+
176
+ # if @@full_stats['sequences'] && @@full_stats['repeated']
177
+ # @@full_stats['sequences']['count']['repeated']=0
178
+ # end
179
+ #
180
+ # if @@full_stats['sequences'] && @@full_stats['processed']
181
+ # @@full_stats['sequences']['processed']['count']=0
182
+ # end
183
+ #
184
+ # if @@full_stats['sequences'] && @@full_stats['total']
185
+ # @@full_stats['sequences']['total']['count']=0
186
+ # end
187
+
188
+ super
189
+ # return checkpoint
190
+ end
191
+
192
+ def save_user_checkpoint
193
+
194
+ f = File.open(STATS_PATH,'w')
195
+ f.puts JSON.pretty_generate(@@full_stats)
196
+ f.close
197
+
198
+ end
199
+
200
+
201
+ # read a work that will not be processed, only to skip until checkpoint
202
+ def trash_checkpointed_work
203
+
204
+ @@chunk_size.times do
205
+ begin
206
+ n,f,q,c = @@fqr.next_seq
207
+ end while (!n.nil? && @@params.repeated_seq?(n))
208
+
209
+ if n.nil?
210
+ break
211
+ end
212
+ end
213
+
214
+ end
215
+
216
+ def next_work
217
+
218
+ if @@exit
219
+ return nil
220
+ end
221
+
222
+ begin
223
+
224
+ n,f,q,c = @@fqr.next_seq
225
+
226
+ if !n.nil? && @@params.repeated_seq?(n)
227
+ @@full_stats.add_stats({'sequences' => {'count' => {'rejected' => 1}}})
228
+ @@full_stats.add_stats({'sequences' => {'rejected' => {'repeated' => 1}}})
229
+
230
+ get_file(File.join(OUTPUT_PATH,'rejected.txt')).puts('>'+n+ ' repeated')
231
+
232
+ end
233
+
234
+ if !n.nil?
235
+ @@full_stats.add_stats({'sequences' => {'count' => {'input_count' => 1}}})
236
+ end
237
+ end while (!n.nil? && @@params.repeated_seq?(n))
238
+
239
+ if !n.nil?
240
+ return SequenceWithAction.new(n,f.upcase,q,c)
241
+ else
242
+ return nil
243
+ end
244
+
245
+
246
+ end
247
+
248
+ # def next_work
249
+ #
250
+ # if @@exit
251
+ # return nil
252
+ # end
253
+ # group = SequenceGroup.new
254
+ #
255
+ # @@chunk_size.times do
256
+ # begin
257
+ #
258
+ # n,f,q,c = @@fqr.next_seq
259
+ #
260
+ # if !n.nil? && @@params.repeated_seq?(n)
261
+ # @@full_stats.add_stats({'sequences' => {'count' => {'rejected' => 1}}})
262
+ # @@full_stats.add_stats({'sequences' => {'rejected' => {'repeated' => 1}}})
263
+ #
264
+ # get_file(File.join(OUTPUT_PATH,'rejected.txt')).puts('>'+n+ ' repeated')
265
+ #
266
+ # end
267
+ # if !n.nil?
268
+ # @@full_stats.add_stats({'sequences' => {'count' => {'input_count' => 1}}})
269
+ # end
270
+ # end while (!n.nil? && @@params.repeated_seq?(n))
271
+ #
272
+ # if !n.nil?
273
+ # # @@full_stats.add_stats({'sequences' => {'count' => {'processed' => 1}}})
274
+ # group.push SequenceWithAction.new(n,f.upcase,q,c)
275
+ # else
276
+ # break
277
+ # end
278
+ # end
279
+ #
280
+ # # puts "Processing #{group.inspect}"
281
+ #
282
+ # if group.empty?
283
+ # return nil
284
+ # else
285
+ # return group
286
+ # end
287
+ #
288
+ # end
289
+
290
+ def work_received(obj)
291
+
292
+ res = obj
293
+
294
+ # collect stats
295
+ @@full_stats.add_stats(obj.stats)
296
+
297
+ # print output in screen
298
+ puts obj.output_text
299
+
300
+ # save results to files
301
+ save_files(obj)
302
+
303
+ end
304
+
305
+ def save_files(obj)
306
+ files=obj.output_files
307
+ files.each do |file_name,content|
308
+ f=get_file(file_name)
309
+ f.puts content
310
+ end
311
+ end
312
+
313
+ def get_file(file_name)
314
+ res_file = @@files[file_name]
315
+
316
+ # if file is not already open, create it
317
+ if res_file.nil?
318
+ # create dir if necessary
319
+ dir = File.dirname(file_name)
320
+ if !File.exists?(dir)
321
+ FileUtils.mkdir_p(dir)
322
+ end
323
+
324
+ # open file
325
+ res_file=File.open(file_name,@@open_mode)
326
+
327
+ # save it in hash for next use
328
+ @@files[file_name]=res_file
329
+ end
330
+
331
+ return res_file
332
+ end
333
+
334
+
335
+ end