in progress...
[jalview.git] / forester / ruby / evoruby / lib / evo / io / parser / general_msa_parser.rb
1 #
2 # = lib/evo/io/parser/general_msa_parser - GeneralMsaParser 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/io/parser/msa_parser'
10 require 'lib/evo/msa/msa'
11
12 module Evoruby
13   class GeneralMsaParser < MsaParser
14     def initialize
15     end
16
17     def parse( path )
18       Util.check_file_for_readability( path )
19       block                       = -1
20       current_seq_index_per_block = -1
21       current_name                = nil
22       saw_ignorable = true
23       is_first      = true
24       msa = Msa.new
25
26       File.open( path ) do | file |
27         while line = file.gets
28           line.encode!("UTF-8", :invalid => :replace, :undef => :replace, :replace => "?")
29           if can_ignore?( line )
30             saw_ignorable = true
31           elsif ( is_first && is_program_name_line?( line ) )
32           elsif( line =~ /^\S+\s+.+\s*$/ || line =~ /^\s+.+\s*$/ || line =~ /^\S+\s*$/ )
33             if ( saw_ignorable )
34               block += 1
35               current_seq_index_per_block = -1
36               saw_ignorable = false
37             end
38             current_seq_index_per_block += 1
39             if ( line =~ /^(\S+)\s+(.+?)\s*$/ )
40               name = $1
41               seq  = $2.gsub( /\s/, '.' )
42               a = msa.find_by_name( name, false, false )
43               if ( a.length < 1 )
44                 msa.add( name, seq )
45               elsif ( a.length == 1 )
46                 msa.get_sequence( a[ 0 ] ).append!( seq )
47               else
48                 error_msg = "Unexpected error at line: " + line
49                 raise IOError, error_msg
50               end
51               current_name = name
52             elsif ( line =~ /^\s+(.+?)\s*$/ )
53               seq = $1.gsub( /\s/, '.' )
54               a = msa.find_by_name( current_name, false, false )
55               if ( a.length != 1  )
56                 error_msg = "Unexpected error at line: " + line
57                 raise IOError, error_msg
58               else
59                 msa.get_sequence( a[ 0 ] ).append!( seq )
60               end
61
62             elsif ( line =~ /^(\S+)\s*$/ )
63               seq = $1
64               if block == 0
65                 error_msg = "First block cannot contain unnamed sequences"
66                 raise IOError, error_msg
67               else
68                 msa.get_sequence( current_seq_index_per_block ).append!( seq )
69               end
70               current_name = nil
71             end
72           else
73             error_msg = "Unexpected line: " + line
74             raise IOError, error_msg
75           end
76           if ( is_first )
77             is_first = false
78           end
79         end
80       end
81       return msa
82     end # def parse( path )
83
84     private
85
86     def can_ignore?( line )
87       return ( line !~ /[A-Za-z\-?\*_\.]/ ||
88       line =~ /^\s+[*\.:]/ ||
89       line =~ /^\s*#/ ||
90       line =~ /^\s*%/ ||
91       line =~ /^\s*\/\// ||
92       line =~ /^\s*!!/  )
93     end
94
95     def is_program_name_line?( line )
96       return ( line =~ /^CLUSTAL\s/ ||
97       line =~ /^MUSCLE\s\(/ ||
98       line =~ /^PROBCONS\s/ )
99     end
100   end # class GeneralMsaParser
101
102 end # module Evoruby