]> git.donarmstrong.com Git - biopieces.git/blob - bp_bin/plot_nucleotide_distribution
added ugly fix to ruby gnuplot dumb print problem
[biopieces.git] / bp_bin / plot_nucleotide_distribution
1 #!/usr/bin/env ruby
2
3 # Copyright (C) 2007-2012 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 # Plot the nucleotide distribution in percent of sequences in the stream.
24
25 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
26
27 require 'maasha/biopieces'
28 require 'gnuplot'
29 require 'narray'
30 require 'pp'
31
32 VEC_MAX   = 10_000
33 Y_MAX     = 100
34
35 terminals = "dumb,x11,aqua,post,pdf,png,svg"
36 title     = "Nucleotide Distribution"
37 xlabel    = "Sequence position"
38 ylabel    = "Nucleotide distribution (%)"
39
40 casts = []
41 casts << {:long=>'no_stream', :short=>'x', :type=>'flag',   :mandatory=>false, :default=>nil,    :allowed=>nil,       :disallowed=>nil}
42 casts << {:long=>'count',     :short=>'c', :type=>'flag',   :mandatory=>false, :default=>nil,    :allowed=>nil,       :disallowed=>nil}
43 casts << {:long=>'data_out',  :short=>'o', :type=>'file',   :mandatory=>false, :default=>nil,    :allowed=>nil,       :disallowed=>nil}
44 casts << {:long=>'terminal',  :short=>'t', :type=>'string', :mandatory=>false, :default=>'dumb', :allowed=>terminals, :disallowed=>nil}
45 casts << {:long=>'title',     :short=>'T', :type=>'string', :mandatory=>false, :default=>title,  :allowed=>nil,       :disallowed=>nil}
46 casts << {:long=>'xlabel',    :short=>'X', :type=>'string', :mandatory=>false, :default=>xlabel, :allowed=>nil,       :disallowed=>nil}
47 casts << {:long=>'ylabel',    :short=>'Y', :type=>'string', :mandatory=>false, :default=>ylabel, :allowed=>nil,       :disallowed=>nil}
48
49 options = Biopieces.options_parse(ARGV, casts)
50
51 max_len = 0 
52
53 vec_a   = NArray.int(VEC_MAX)
54 vec_t   = NArray.int(VEC_MAX)
55 vec_c   = NArray.int(VEC_MAX)
56 vec_g   = NArray.int(VEC_MAX)
57 vec_n   = NArray.int(VEC_MAX)
58 vec_tot = NArray.float(VEC_MAX)
59
60 Biopieces.open(options[:stream_in], options[:stream_out]) do |input, output|
61   input.each_record do |record|
62     if record[:SEQ]
63       seq = record[:SEQ].upcase
64
65       unless seq.empty?
66         raise BiopiecesError, "sequence too long: #{seq.length} > #{VEC_MAX}" if seq.length > VEC_MAX
67
68         vec_seq = NArray.to_na(seq, "byte")
69
70         vec_a[0 ... seq.length]   += vec_seq.eq('A'.ord)
71         vec_t[0 ... seq.length]   += vec_seq.eq('T'.ord)
72         vec_c[0 ... seq.length]   += vec_seq.eq('C'.ord)
73         vec_g[0 ... seq.length]   += vec_seq.eq('G'.ord)
74         vec_n[0 ... seq.length]   += vec_seq.eq('N'.ord)
75         vec_tot[0 ... seq.length] += 1
76
77         max_len = seq.length if seq.length > max_len
78       end
79     end
80
81     output.puts record unless options[:no_stream]
82   end
83 end
84
85 if max_len > 0
86   x = (1 .. max_len).to_a
87   a = ((vec_a / vec_tot) * 100)[0 ... max_len].to_a
88   t = ((vec_t / vec_tot) * 100)[0 ... max_len].to_a
89   c = ((vec_c / vec_tot) * 100)[0 ... max_len].to_a
90   g = ((vec_g / vec_tot) * 100)[0 ... max_len].to_a
91   n = ((vec_n / vec_tot) * 100)[0 ... max_len].to_a
92
93   vec_tot *= (Y_MAX / vec_tot.max(0).to_f)
94   y = vec_tot.to_a
95
96   a.unshift 0.0
97   t.unshift 0.0
98   c.unshift 0.0
99   g.unshift 0.0
100   n.unshift 0.0
101
102   Gnuplot.open do |gp|
103     Gnuplot::Plot.new(gp) do |plot|
104       plot.terminal options[:terminal]
105       plot.title    options[:title]
106       plot.xlabel   options[:xlabel]
107       plot.ylabel   options[:ylabel]
108       plot.output   options[:data_out] || "/dev/stderr"
109       plot.ytics    "out"
110       plot.xtics    "out"
111       plot.yrange   "[0:#{Y_MAX}]"
112       plot.xrange   "[0:#{max_len}]"
113       plot.auto     "fix"
114       plot.offsets  "1"
115       plot.key      "outside right top vertical Left reverse enhanced autotitles columnhead nobox"
116       plot.key      "invert samplen 4 spacing 1 width 0 height 0"
117       plot.style    "fill solid 0.5 border"
118       plot.style    "histogram rowstacked"
119       plot.style    "data histograms"
120       plot.boxwidth "0.75 absolute"
121
122       plot.data << Gnuplot::DataSet.new(n) do |ds|
123         ds.using = "1"
124         ds.with  = "histogram lt rgb \"black\""
125         ds.title = "N"
126       end
127
128       plot.data << Gnuplot::DataSet.new(g) do |ds|
129         ds.using = "1"
130         ds.with  = "histogram lt rgb \"yellow\""
131         ds.title = "G"
132       end
133
134       plot.data << Gnuplot::DataSet.new(c) do |ds|
135         ds.using = "1"
136         ds.with  = "histogram lt rgb \"blue\""
137         ds.title = "C"
138       end
139
140       plot.data << Gnuplot::DataSet.new(t) do |ds|
141         ds.using = "1"
142         ds.with  = "histogram lt rgb \"green\""
143         ds.title = "T"
144       end
145
146       plot.data << Gnuplot::DataSet.new(a) do |ds|
147         ds.using = "1"
148         ds.with  = "histogram lt rgb \"red\""
149         ds.title = "A"
150       end
151
152       if options[:count]
153         plot.data << Gnuplot::DataSet.new([x, y]) do |ds|
154           ds.with  = "lines lt rgb \"black\""
155           ds.title = "count"
156         end
157       end
158     end
159   end
160 end
161
162 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
163
164
165 __END__