]> git.donarmstrong.com Git - biopieces.git/blob - code_ruby/lib/maasha/embl.rb
changed Seq.new argument to hash
[biopieces.git] / code_ruby / lib / maasha / embl.rb
1 # Copyright (C) 2007-2011 Martin A. Hansen.
2
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16
17 # http://www.gnu.org/copyleft/gpl.html
18
19 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
20
21 # This software is part of the Biopieces framework (www.biopieces.org).
22
23 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
24
25 require 'maasha/locator'
26 require 'maasha/seq'
27 require 'maasha/filesys'
28 require 'pp'
29
30 # Error class for all exceptions to do with EMBL.
31 class EMBLError < StandardError; end
32
33 class EMBL < Filesys
34   def initialize(io)
35     @io      = io
36     @entry   = []
37   end
38
39   # Iterator method for parsing EMBL entries.
40   def each(hash_keys = nil, hash_feats = nil, hash_quals = nil)
41     while @entry = get_entry do
42       keys = get_keys(hash_keys)
43       seq  = get_seq
44
45       features = EMBLFeatures.new(@entry, hash_feats, hash_quals)
46
47       features.each do |record|
48         keys.each_pair { |key,val| record[key] = val }
49
50                                 loc = Locator.new(record[:LOCATOR], seq)
51                                 record[:SEQ]     = loc.subseq.seq
52         record[:SEQ_LEN] = loc.subseq.length
53                                 record[:STRAND]  = loc.strand
54                                 record[:S_BEG]   = loc.s_beg
55                                 record[:S_END]   = loc.s_end
56
57         yield record
58       end
59     end
60   end
61
62   private
63
64   # Method to get the next Genbank entry form an ios and return this.
65   def get_entry
66     block = @io.gets("//" + $/)
67     return nil if block.nil?
68
69     block.chomp!("//" + $/ )
70
71     entry = block.tr("\r", "\n").split $/
72
73     return nil if entry.empty?
74
75     entry
76   end
77
78   # Method to get the DNA sequence from an EMBL entry and return
79   # this as a Seq object.
80   def get_seq
81     i = @entry.size
82     j = i - 1
83
84     while @entry[j] and @entry[j] !~ /^[A-Z]/
85       j -= 1
86     end
87
88     seq = @entry[j + 1 .. i].join.delete(" 0123456789")
89
90     Seq.new(seq: seq, type: :dna) if seq
91   end
92
93   # Method to get the base keys from EMBL entry and return these
94   # in a hash.
95   def get_keys(hash_keys)
96     keys = {}
97     i    = 0
98     j    = 0
99
100     while @entry[i]
101       key, val = @entry[i].split(/\s+/, 2)
102       break if key == "FH"
103       unless key == "XX"
104         if want_key?(hash_keys, key)
105           j = i + 1
106
107           while @entry[j]
108             next_key, next_val = @entry[j].split(/\s+/, 2)
109             if key == next_key
110               val << " " + next_val
111               j += 1
112             else
113               break
114             end
115           end
116
117           if keys[key.to_sym]
118             keys[key.to_sym] << " " + val
119           else
120             keys[key.to_sym] = val
121           end
122         end
123       end
124
125       j > i ? i = j : i += 1
126     end
127
128     keys
129   end
130
131   def want_key?(hash_keys, key)
132     if hash_keys
133       if hash_keys[key.to_sym]
134         return true
135       else
136         return false
137       end
138     else
139       return true
140     end
141   end
142 end
143
144 class EMBLFeatures
145   def initialize(entry, hash_feats, hash_quals)
146     @entry      = entry
147     @hash_feats = hash_feats
148     @hash_quals = hash_quals
149         @i          = 0
150         @j          = 0
151   end
152
153   def each
154     while @entry[@i] and @entry[@i][0 ... 2] != "SQ"
155       if @entry[@i] =~ /^FT\s{3}([53'A-Za-z_-]+)/
156         if want_feat? $1
157           record = {}
158
159           key, feat, loc = @entry[@i].split(/\s+/, 3)
160
161           @j = @i + 1
162
163           while @entry[@j] and @entry[@j][0 ... 2] == "FT" and @entry[@j] !~ /^FT(\s{19}\/|\s{3}[53'A-Za-z_-])/
164             loc << @entry[@j].split(/\s+/, 2).last
165             @j += 1
166           end
167
168           get_quals.each_pair { |k,v|
169             record[k.upcase.to_sym] = v
170           }
171
172           record[:FEATURE] = feat
173           record[:LOCATOR] = loc
174
175           yield record
176         end
177       end
178
179       @j > @i ? @i = @j : @i += 1
180     end
181   end
182
183   private
184
185   def get_quals
186     quals = {}
187     k     = 0
188
189     while @entry[@j] and @entry[@j][0 ... 2] == "FT" and @entry[@j] !~ /^FT\s{3}[53'A-Za-z_-]/
190       if @entry[@j] =~ /^FT\s{19}\/([^=]+)="([^"]+)/
191         qual = $1
192         val  = $2
193
194         if want_qual? qual
195           k = @j + 1
196
197           while @entry[k] and @entry[k][0 ... 2] == "FT" and @entry[k] !~ /^FT(\s{19}\/|\s{3}[53'A-Za-z_-])/
198             val << @entry[k].split(/\s+/, 2).last.chomp('"')
199             k += 1
200           end
201
202           if quals[qual]
203             quals[qual] << ";" + val
204           else
205             quals[qual] = val
206           end
207         end
208       end
209
210       k > @j ? @j = k : @j += 1
211     end
212
213     quals
214   end
215
216   def want_feat?(feat)
217     if @hash_feats
218       if @hash_feats[feat.upcase.to_sym]
219         return true
220       else
221         return false
222       end
223     else
224       return true
225     end
226   end
227
228   def want_qual?(qual)
229     if @hash_quals
230       if @hash_quals[qual.upcase.to_sym]
231         return true
232       else
233         return false
234       end
235     else
236       return true
237     end
238   end
239 end
240
241 __END__