in progress
[jalview.git] / forester / ruby / evoruby / lib / evo / util / util.rb
1 #
2 # = lib/evo/util/util.rb - Util class
3 #
4 # Copyright::    Copyright (C) 2017 Christian M. Zmasek
5 # License::      GNU Lesser General Public License (LGPL)
6 #
7 # Last modified: 2017/02/07
8
9 require 'lib/evo/util/constants'
10
11 module Evoruby
12   class Util
13     def Util.get_matching_files( files, prefix_pattern, suffix_pattern )
14       matching_files = Array.new
15       files.each { | file |
16         if ( !File.directory?( file ) &&
17         file !~ /^\./ &&
18         file =~ /^#{prefix_pattern}.*#{suffix_pattern}$/ )
19           matching_files << file
20         end
21       }
22       matching_files
23     end
24
25     def Util.normalize_seq_name( name, length, exception_if_too_long = false )
26       if name.length > length
27         if exception_if_too_long
28           error_msg = "sequence name \"#{name}\" is too long (>#{length})"
29           raise StandardError, error_msg
30         end
31         name = name[ 0, length ]
32       elsif name.length < length
33         t = length - name.length
34         t.times do
35           name = name + " "
36         end
37       end
38       name
39     end
40
41     # Returns true if char_code corresponds to: space * - . _
42     def Util.is_aa_gap_character?( char_code )
43       return ( char_code <= 32  || char_code == 42 || char_code == 45 || char_code == 46 ||char_code == 95  )
44     end
45
46     # Deletes *, digits, and whitespace, replaces BJOUZ? with X, and replaces non-(letters, -) with -
47     def Util.clean_seq_str( seq_str )
48       seq_str = seq_str.upcase
49       seq_str = seq_str.gsub( /\s+/, '' )
50       seq_str = seq_str.gsub( /\d+/, '' )
51       seq_str = seq_str.gsub( '*', '' )
52       seq_str = seq_str.gsub( /[BJOUZ?]/, 'X' )
53       seq_str = seq_str.gsub( /[^A-Z\-]/, '-' )
54       seq_str
55     end
56
57     # raises ArgumentError
58     def Util.check_file_for_readability( path )
59       unless ( File.exist?( path ) )
60         error_msg = "file [#{path}] does not exist"
61         raise IOError, error_msg
62       end
63       unless ( File.file?( path ) )
64         error_msg = "file [#{path}] is not a regular file"
65         raise IOError, error_msg
66       end
67       unless ( File.readable?( path ) )
68         error_msg = "file [#{path}] is not a readable file"
69         raise IOError, error_msg
70       end
71       if ( File.zero?( path ) )
72         error_msg = "file [#{path}] is empty"
73         raise IOError, error_msg
74       end
75     end
76
77     # raises ArgumentError
78     def Util.check_file_for_writability( path )
79       if File.directory?( path )
80         error_msg = "file [#{path}] is an existing directory"
81         raise IOError, error_msg
82       elsif File.exist?( path )
83         error_msg = "file [#{path}] already exists"
84         raise IOError, error_msg
85       elsif File.writable?( path )
86         error_msg = "file [#{path}] is not writeable"
87         raise IOError, error_msg
88       end
89     end
90
91     def Util.fatal_error_if_not_writable( prg_name, path )
92       begin
93         Util.check_file_for_writability( path )
94       rescue IOError => e
95         Util.fatal_error( prg_name, e.to_s )
96       end
97     end
98
99     def Util.fatal_error_if_not_readable( prg_name, path )
100       begin
101         Util.check_file_for_readability( path )
102       rescue IOError => e
103         Util.fatal_error( prg_name, e.to_s )
104       end
105     end
106
107     def Util.get_env_variable_value( env_variable )
108       value = ENV[env_variable]
109       if value == nil || value.empty?
110         error_msg = "apparently environment variable #{env_variable} has not been set"
111         raise StandardError, error_msg
112       end
113       value
114     end
115
116     # raises ArgumentError
117     def Util.file2array( path, split_by_semicolon )
118       Util.check_file_for_readability( path )
119       a = Array.new()
120       c = 0
121       File.open( path ) do | file |
122         while line = file.gets
123           if ( line =~ /^\s*(\S.*?)\s*$/ )
124             s = $1
125             if ( split_by_semicolon && s =~/;/ )
126               sa = s.split( /;/ )
127               for i in 0 ... sa.length()
128                 a[ c ] = sa[ i ].strip!
129               end
130             else
131               a[ c ] = s
132             end
133             c += 1
134           end
135         end
136       end
137       return a
138     end
139
140     def Util.print_program_information( prg_name,
141       prg_version,
142       prg_desc,
143       date,
144       www,
145       io = STDOUT )
146
147       ruby_version = RUBY_VERSION
148       l = prg_name.length + prg_version.length + date.length + ruby_version.length + 12
149       io.print( Evoruby::Constants::LINE_DELIMITER )
150       io.print( prg_name + " " + prg_version + " [" + date + "] [ruby " + ruby_version + "]")
151       io.print( Evoruby::Constants::LINE_DELIMITER )
152       l.times {
153         io.print( "_" )
154       }
155       io.print( Constants::LINE_DELIMITER )
156       io.print( Constants::LINE_DELIMITER )
157       io.print( prg_desc )
158       io.print( Constants::LINE_DELIMITER )
159       io.print( Constants::LINE_DELIMITER )
160       io.print( "Website: " + www )
161       io.print( Constants::LINE_DELIMITER )
162       io.print( Constants::LINE_DELIMITER )
163     end
164
165     def Util.fatal_error( prg_name, message, io = STDOUT )
166       io.print( Constants::LINE_DELIMITER )
167       if ( !Util.is_string_empty?( prg_name ) )
168         io.print( "[" + prg_name + "] > " + message )
169       else
170         io.print( " > " + message )
171       end
172       io.print( Constants::LINE_DELIMITER )
173       io.print( Constants::LINE_DELIMITER )
174       exit( -1 )
175     end
176
177     def Util.print_message( prg_name, message, io = STDOUT )
178       if ( !Util.is_string_empty?( prg_name ) )
179         io.print( "[" + prg_name + "] > " + message )
180       else
181         io.print( " > " + message )
182       end
183       io.print( Constants::LINE_DELIMITER )
184     end
185
186     def Util.print_warning_message( prg_name, message, io = STDOUT )
187       if ( !Util.is_string_empty?( prg_name ) )
188         io.print( "[" + prg_name + "] > WARNING: " + message )
189       else
190         io.print( " > " + message )
191       end
192       io.print( Constants::LINE_DELIMITER )
193     end
194
195     def Util.is_string_empty?( s )
196       return ( s == nil || s.length < 1 )
197     end
198
199     # From "Ruby Cookbook"
200     # counts_hash: key is a "name", value is the count (integer)
201     def Util.draw_histogram( counts_hash, char = "#" )
202       pairs = counts_hash.keys.collect { |x| [ x.to_s, counts_hash[ x ] ] }.sort
203       largest_key_size = pairs.max { |x, y| x[ 0 ].size <=> y[ 0 ].size }[ 0 ].size
204       pairs.inject( "" ) do | s, kv |
205         s << "#{ kv[ 0 ].ljust( largest_key_size ) }  | #{ char*kv[ 1 ] }" + Constants::LINE_DELIMITER
206       end
207     end
208
209     def Util.looks_like_fasta?( path )
210       Util.check_file_for_readability( path )
211       File.open( path ) do | file |
212         while line = file.gets
213           if ( line !~ /\S/ || line =~ /^\s*#/ )
214           elsif line =~ /^\s*>\s*(.+)/
215             return true
216           else
217             return false
218           end
219         end
220       end
221       error_msg = "unexpected format"
222       raise IOError, error_msg
223     end
224
225   end # class Util
226
227 end # module Evoruby