]> git.donarmstrong.com Git - biopieces.git/blob - bp_bin/slice_align
finishing slice_align biopiece
[biopieces.git] / bp_bin / slice_align
1 #!/usr/bin/env ruby
2
3 # Copyright (C) 2007-2010 Martin A. Hansen.
4
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19 # http://www.gnu.org/copyleft/gpl.html
20
21 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
22
23 # This program is part of the Biopieces framework (www.biopieces.org).
24
25 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
26
27 # Slice aligned sequences in the stream to obtain subsequences.
28
29 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
30
31 require 'maasha/biopieces'
32 require 'maasha/fasta'
33 require 'maasha/seq'
34
35 indels = Regexp.new(/-|\.|~/)
36
37 casts = []
38 casts << {long: 'beg',            short: 'b', type: 'uint',   mandatory: false, default: nil, allowed: nil, disallowed: "0"}
39 casts << {long: 'end',            short: 'e', type: 'uint',   mandatory: false, default: nil, allowed: nil, disallowed: "0"}
40 casts << {long: 'forward',        short: 'f', type: 'string', mandatory: false, default: nil, allowed: nil, disallowed: nil}
41 casts << {long: 'forward_rc',     short: 'F', type: 'string', mandatory: false, default: nil, allowed: nil, disallowed: nil}
42 casts << {long: 'reverse',        short: 'r', type: 'string', mandatory: false, default: nil, allowed: nil, disallowed: nil}
43 casts << {long: 'reverse_rc',     short: 'R', type: 'string', mandatory: false, default: nil, allowed: nil, disallowed: nil}
44 casts << {long: 'template_file',  short: 't', type: 'file!',  mandatory: false, default: nil, allowed: nil, disallowed: nil}
45 casts << {long: 'mismatches',     short: 'm', type: 'uint',   mandatory: false, default: 2,   allowed: nil, disallowed: nil}
46 casts << {long: 'insertions',     short: 'i', type: 'uint',   mandatory: false, default: 1,   allowed: nil, disallowed: nil}
47 casts << {long: 'deletions',      short: 'd', type: 'uint',   mandatory: false, default: 1,   allowed: nil, disallowed: nil}
48
49 options = Biopieces.options_parse(ARGV, casts)
50
51 if options[:beg]
52   raise "both --beg and --end must be speficied" unless options[:end]
53   options[:beg] -= 1
54   options[:end] -= 1
55   raise "--beg (#{options[:beg]}) must be less than --end (#{options[:end]})" if options[:beg] > options[:end]
56 elsif options[:forward] or options[:forward_rc]
57   raise "both --forward and --reverse or --reverse_rc must be specified" unless options[:reverse] or options[:reverse_rc]
58
59   if options[:forward_rc]
60     options[:forward] = Seq.new(seq: options[:forward_rc], type: :dna).reverse.complement.seq
61   end
62
63   if options[:reverse_rc]
64     options[:reverse] = Seq.new(seq: options[:reverse_rc], type: :dna).reverse.complement.seq
65   end
66 else
67   raise "either --beg/--end or --forward/--reverse|--reverse_rc must be specified"
68 end
69
70 if options[:template_file]
71   template = Fasta.open(options[:template_file]).get_entry
72
73   if options[:beg]
74     mbeg = options[:beg]
75     mend = options[:end]
76     i    = 0
77
78     while template.seq[i]
79       unless template.seq[i].match indels
80         if mbeg > 0
81           mbeg -= 1
82           mend -= 1
83         else
84           options[:beg] = i
85           break
86         end
87       end
88
89       i += 1
90     end
91
92     while template.seq[i]
93       unless template.seq[i].match indels
94         if mend > 0
95           mend -= 1
96         else
97           options[:end] = i
98           break
99         end
100       end
101
102       i += 1
103     end
104   end
105 end
106
107 Biopieces.open(options[:stream_in], options[:stream_out]) do |input, output|
108   input.each_record do |record|
109     if record[:SEQ]
110       entry = Seq.new(seq: record[:SEQ])
111
112       unless options[:beg]
113         raise "template length != alignment length" if template and template.length != entry.length
114         compact = template ? template : Seq.new(seq: entry.seq.dup)
115         compact.seq.delete! "-.~"
116
117         fmatch = compact.patmatch(options[:forward],
118                                   max_mismatches: options[:mismatches],
119                                   max_insertions: options[:insertions],
120                                   max_deletions: options[:deletions])
121
122         raise "forward primer: #{options[:forward]} not found" if fmatch.nil?
123
124         rmatch = compact.patmatch(options[:reverse],
125                                   max_mismatches: options[:mismatches],
126                                   max_insertions: options[:insertions],
127                                   max_deletions: options[:deletions])
128
129         raise "reverse primer: #{options[:reverse]} not found" if rmatch.nil?
130
131         mbeg = fmatch.pos
132         mend = rmatch.pos + rmatch.length - 1
133
134         i = 0
135
136         while entry.seq[i]
137           unless entry.seq[i].match indels
138             if mbeg > 0
139               mbeg -= 1
140               mend -= 1
141             else
142               options[:beg] = i
143               break
144             end
145           end
146
147           i += 1
148         end
149
150         while entry.seq[i]
151           unless entry.seq[i].match indels
152             if mend > 0
153               mend -= 1
154             else
155               options[:end] = i
156               break
157             end
158           end
159
160           i += 1
161         end
162       end
163
164       record[:SEQ]     = entry[options[:beg] .. options[:end]].seq
165       record[:SEQ_LEN] = record[:SEQ].length
166     end
167
168     output.puts record
169   end
170 end
171
172
173 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
174
175
176 __END__