in progress
[jalview.git] / forester / ruby / evoruby / lib / evo / apps / domain_sequence_extractor_new.rb
1 #
2 # = lib/evo/apps/domain_sequence_extractor.rb - DomainSequenceExtractor class
3 #
4 # Copyright::  Copyright (C) 2012 Christian M. Zmasek
5 # License::    GNU Lesser General Public License (LGPL)
6 #
7 # $Id:Exp $
8
9
10 require 'lib/evo/util/constants'
11 require 'lib/evo/util/util'
12 require 'lib/evo/util/command_line_arguments'
13 require 'lib/evo/io/parser/hmmscan_domain_extractor'
14
15 module Evoruby
16
17   class DomainSequenceExtractor
18
19     PRG_NAME       = "dsx"
20     PRG_VERSION    = "1.000"
21     PRG_DESC       = "extraction of domain sequences from hmmscan output"
22     PRG_DATE       = "20120906"
23     COPYRIGHT      = "2012 Christian M Zmasek"
24     CONTACT        = "phylosoft@gmail.com"
25     WWW            = "www.phylosoft.org"
26
27     E_VALUE_THRESHOLD_OPTION           = 'e'
28     LENGTH_THRESHOLD_OPTION            = 'l'
29     ADD_POSITION_OPTION                = 'p'
30     ADD_DOMAIN_NUMBER_OPTION           = 'd'
31     ADD_DOMAIN_NUMBER_OPTION_AS_DIGIT  = 'dd'
32     ADD_DOMAIN_NUMBER_OPTION_AS_LETTER = 'dl'
33     ADD_SPECIES                        = 's'
34     TRIM_OPTION                        = 't'
35     LOG_FILE_SUFFIX                    = '_domain_seq_extr.log'
36     PASSED_SEQS_SUFFIX                 = '_domain_seq_extr_passed'
37     FAILED_SEQS_SUFFIX                 = '_domain_seq_extr_failed'
38     HELP_OPTION_1                      = 'help'
39     HELP_OPTION_2                      = 'h'
40
41     def run()
42
43       Util.print_program_information( PRG_NAME,
44         PRG_VERSION,
45         PRG_DESC ,
46         PRG_DATE,
47         COPYRIGHT,
48         CONTACT,
49         WWW,
50         STDOUT )
51
52       ld = Constants::LINE_DELIMITER
53
54       begin
55         cla = CommandLineArguments.new( ARGV )
56       rescue ArgumentError
57         Util.fatal_error( PRG_NAME, "error: " + $!, STDOUT )
58       end
59
60       if ( cla.is_option_set?( HELP_OPTION_1 ) ||
61            cla.is_option_set?( HELP_OPTION_2 ) )
62         print_help
63         exit( 0 )
64       end
65
66       if ( cla.get_number_of_files != 4 )
67         print_help
68         exit( -1 )
69       end
70
71       allowed_opts = Array.new
72       allowed_opts.push( E_VALUE_THRESHOLD_OPTION )
73       allowed_opts.push( ADD_POSITION_OPTION )
74       allowed_opts.push( ADD_DOMAIN_NUMBER_OPTION )
75       allowed_opts.push( LENGTH_THRESHOLD_OPTION )
76       allowed_opts.push( ADD_DOMAIN_NUMBER_OPTION_AS_DIGIT )
77       allowed_opts.push( ADD_DOMAIN_NUMBER_OPTION_AS_LETTER )
78       allowed_opts.push( TRIM_OPTION )
79       allowed_opts.push( ADD_SPECIES )
80
81       disallowed = cla.validate_allowed_options_as_str( allowed_opts )
82       if ( disallowed.length > 0 )
83         Util.fatal_error( PRG_NAME,
84           "unknown option(s): " + disallowed,
85           STDOUT )
86       end
87
88       domain_id           = cla.get_file_name( 0 )
89       hmmsearch_output    = cla.get_file_name( 1 )
90       fasta_sequence_file = cla.get_file_name( 2 )
91       outfile             = cla.get_file_name( 3 )
92
93       add_position = false
94       if ( cla.is_option_set?( ADD_POSITION_OPTION ) )
95         add_position = true
96       end
97
98       trim = false
99       if ( cla.is_option_set?( TRIM_OPTION ) )
100         trim = true
101       end
102
103       add_domain_number           = false
104       add_domain_number_as_letter = false
105       add_domain_number_as_digit  = false
106
107       if ( cla.is_option_set?( ADD_DOMAIN_NUMBER_OPTION ) )
108         add_domain_number = true
109       end
110       if ( cla.is_option_set?( ADD_DOMAIN_NUMBER_OPTION_AS_LETTER ) )
111         add_domain_number_as_letter = true
112       end
113       if ( cla.is_option_set?( ADD_DOMAIN_NUMBER_OPTION_AS_DIGIT ) )
114         add_domain_number_as_digit = true
115       end
116
117       add_species = false
118       if cla.is_option_set? ADD_SPECIES
119         add_species = true
120       end
121
122       if ( add_domain_number_as_letter && add_domain_number_as_digit )
123         puts( "attempt to add domain number as letter and digit at the same time" )
124         print_help
125         exit( -1 )
126       end
127
128       e_value_threshold = -1.0
129       if ( cla.is_option_set?( E_VALUE_THRESHOLD_OPTION ) )
130         begin
131           e_value_threshold = cla.get_option_value_as_float( E_VALUE_THRESHOLD_OPTION )
132         rescue ArgumentError => e
133           Forester::Util.fatal_error( PRG_NAME, "error: " + e.to_s, STDOUT )
134         end
135         if ( e_value_threshold < 0.0 )
136           Forester::Util.fatal_error( PRG_NAME, "attempt to use a negative E-value threshold", STDOUT )
137         end
138       end
139
140       length_threshold = -1
141       if ( cla.is_option_set?( LENGTH_THRESHOLD_OPTION ) )
142         begin
143           length_threshold = cla.get_option_value_as_int( LENGTH_THRESHOLD_OPTION )
144         rescue ArgumentError => e
145           Forester::Util.fatal_error( PRG_NAME, "error: " + e.to_s, STDOUT )
146         end
147         if ( length_threshold < 0)
148           Forester::Util.fatal_error( PRG_NAME, "attempt to use a negative length threshold", STDOUT )
149         end
150       end
151
152       log = String.new
153
154       puts()
155       puts( "Domain                                 : " + domain_id )
156       log << "Domain                                 : " + domain_id + ld
157       puts( "Hmmscan outputfile                     : " + hmmsearch_output )
158       log << "Hmmscan outputfile                     : " + hmmsearch_output + ld
159       puts( "Fasta sequencefile (complete sequences): " + fasta_sequence_file )
160       log << "Fasta sequencefile (complete sequences): " + fasta_sequence_file + ld
161       puts( "Outputfile                             : " + outfile )
162       log << "Outputfile                             : " + outfile + ld
163       puts( "Passed sequences outfile (fasta)       : " + outfile + PASSED_SEQS_SUFFIX )
164       log << "Passed sequences outfile (fasta)       : " + outfile + PASSED_SEQS_SUFFIX + ld
165       puts( "Failed sequences outfile (fasta)       : " + outfile + FAILED_SEQS_SUFFIX )
166       log << "Failed sequences outfile (fasta)       : " + outfile + FAILED_SEQS_SUFFIX + ld
167       puts( "Logfile                                : " + outfile + LOG_FILE_SUFFIX )
168       log <<  "Logfile                                : " + outfile + LOG_FILE_SUFFIX + ld
169       if ( e_value_threshold >= 0.0 )
170         puts( "E-value threshold : " + e_value_threshold.to_s )
171         log << "E-value threshold : " + e_value_threshold.to_s + ld
172       else
173         puts( "E-value threshold : no threshold" )
174         log << "E-value threshold : no threshold" + ld
175       end
176       if ( length_threshold > 0 )
177         puts( "Length threshold  : " + length_threshold.to_s )
178         log << "Length threshold  : " + length_threshold.to_s + ld
179       else
180         puts( "Length threshold  : no threshold" )
181         log << "Length threshold  : no threshold" + ld
182       end
183
184       if ( trim )
185         puts( "Trim last 2 chars : true" )
186         log << "Trim last 2 chars : true" + ld
187       else
188         puts( "Trim names        : false" )
189         log << "Trim names        : false" + ld
190       end
191
192
193       if ( add_position )
194         puts( "Add positions (rel to complete seq) to extracted domains: true" )
195         log << "Add positions (rel to complete seq) to extracted domains: true" + ld
196       else
197         puts( "Add positions (rel to complete seq) to extracted domains: false" )
198         log << "Add positions (rel to complete seq) to extracted domains: false" + ld
199       end
200
201       if ( add_domain_number || add_domain_number_as_digit || add_domain_number_as_letter )
202         puts( "Add numbers to extracted domains (in case of more than one domain per complete seq): true" )
203         log << "Add numbers to extracted domains (in case of more than one domain per complete seq): true" + ld
204       else
205         puts( "Add numbers to extracted domains (in case of more than one domain per complete seq): false" )
206         log << "Add numbers to extracted domains (in case of more than one domain per complete seq): false" + ld
207       end
208
209       puts
210
211       domain_count = 0
212       begin
213         parser = HmmscanDomainExtractor.new()
214         domain_count = parser.parse( domain_id,
215           hmmsearch_output,
216           fasta_sequence_file,
217           outfile,
218           outfile + PASSED_SEQS_SUFFIX,
219           outfile + FAILED_SEQS_SUFFIX,
220           e_value_threshold,
221           length_threshold,
222           add_position,
223           add_domain_number,
224           add_domain_number_as_digit,
225           add_domain_number_as_letter,
226           trim,
227           add_species,
228           log )
229       rescue ArgumentError, IOError, StandardError => e
230         Util.fatal_error( PRG_NAME, "error: " + e.to_s, STDOUT )
231       rescue Exception => e
232         Util.fatal_error( PRG_NAME, "unexpected exception!: " + e.to_s, STDOUT )
233       end
234
235       puts
236       Util.print_message( PRG_NAME, "extracted a total of " + domain_count.to_s + " domains" )
237       Util.print_message( PRG_NAME, "wrote;               " + outfile )
238       Util.print_message( PRG_NAME, "wrote:               " + outfile + LOG_FILE_SUFFIX )
239       Util.print_message( PRG_NAME, "(wrote:              " + outfile + PASSED_SEQS_SUFFIX + ")" )
240       Util.print_message( PRG_NAME, "(wrote:              " + outfile + FAILED_SEQS_SUFFIX + ")" )
241
242       begin
243         f = File.open( outfile + LOG_FILE_SUFFIX, 'a' )
244         f.print( log )
245         f.close
246       rescue Exception => e
247         Util.fatal_error( PRG_NAME, "error: " + e.to_s )
248       end
249
250       puts
251       Util.print_message( PRG_NAME, "OK" )
252       puts
253
254     end
255
256     def print_help()
257       puts()
258       puts( "Usage:" )
259       puts()
260       puts( "  " + PRG_NAME + ".rb [options] <domain> <hmmscan outputfile> <file containing complete sequences in fasta format> <outputfile>" )
261       puts()
262       puts( "  options: -" + E_VALUE_THRESHOLD_OPTION  + "=<f>: E-value threshold, default is no threshold" )
263       puts( "           -" + LENGTH_THRESHOLD_OPTION   + "=<i>: length threshold, default is no threshold" )
264       puts( "           -" + ADD_POSITION_OPTION  + ": to add positions (rel to complete seq) to extracted domains" )
265       puts( "           -" + ADD_DOMAIN_NUMBER_OPTION  + ": to add numbers to extracted domains (in case of more than one domain per complete seq) (example \"domain~2-3\")" )
266       puts( "           -" + ADD_DOMAIN_NUMBER_OPTION_AS_DIGIT  + ": to add numbers to extracted domains as digit (example \"domain2\")" )
267       puts( "           -" + ADD_DOMAIN_NUMBER_OPTION_AS_LETTER  + ": to add numbers to extracted domains as letter (example \"domaina\")" )
268       puts( "           -" + TRIM_OPTION  + ": to remove the last 2 characters from sequence names" )
269       puts( "           -" + ADD_SPECIES  + ": to add species [in brackets]" )
270       puts()
271     end
272
273   end # class DomainSequenceExtractor
274
275 end # module Evoruby