vienna_rna 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 31ec4e6771f342a7ebc0093f628748a1d39ef940
4
+ data.tar.gz: f3e2f41a3957ca6a84cd38aaa390ae383a49f712
5
+ SHA512:
6
+ metadata.gz: 949a4476d1acda83e807966ccc34b6bdfa57b93fdae096bd848b83970fca94383502fa36e2f06b45158c2347d64e5dfc138461f6d5cd83d35233b388cecb5321
7
+ data.tar.gz: 717e42a7999cffe4fa6994652c22edafcc66e01f35bb41b58305e2ab900572eb81c5e0d2aa4cea44fa5504a89b7f88e4ddc4e2c84833f3804d0423f9e2b5a300
@@ -20,7 +20,8 @@ module ViennaRna
20
20
  !%x[which rna#{name.to_s.downcase}].empty?
21
21
  end
22
22
 
23
- def run(data, flags = {})
23
+ def run(*data)
24
+ flags = data.length > 1 && data.last.is_a?(Hash) ? data.pop : {}
24
25
  new(data).run(flags)
25
26
  end
26
27
 
@@ -65,11 +66,14 @@ module ViennaRna
65
66
  end
66
67
 
67
68
  def initialize(data)
68
- @data = case data
69
- when Bio::FastaFormat then data
70
- when Rna then data
71
- when String then Rna.new(data)
72
- when Hash then Rna.new(data[:sequence] || data[:seq], data[:structure] || data[:str])
69
+ data = [data] unless data.is_a?(Array)
70
+
71
+ @data = case data.map(&:class)
72
+ when [Rna] then data.first
73
+ when [String], [String, String] then Rna.init_from_string(*data)
74
+ when [Hash] then Rna.init_from_hash(*data)
75
+ when [Array] then Rna.init_from_array(*data)
76
+ else raise TypeError.new("Unsupported ViennaRna::Rna#initialize format: #{data}")
73
77
  end
74
78
  end
75
79
 
@@ -3,7 +3,7 @@ module ViennaRna
3
3
  attr_reader :mfe
4
4
 
5
5
  def post_process
6
- @mfe = Parser.mfe(@response)
6
+ @mfe = Parser.rnafold_mfe(@response)
7
7
  end
8
8
  end
9
9
  end
@@ -9,21 +9,6 @@ module ViennaRna
9
9
  standalone: "FFTbor"
10
10
  }
11
11
 
12
- def run_command(flags = {})
13
- flags = { mode: :standalone }.merge(flags)
14
-
15
- unless MODES[flags[:mode]]
16
- STDERR.puts "ERROR: The mode requested (%s) is not available" % flags[:mode]
17
- end
18
-
19
- case mode = flags.delete(:mode)
20
- when :standalone then
21
- super(flags)
22
- when :dispatch then
23
- "%s -m 6 -tr 0 -s %s -ss '%s'" % [MODES[mode], data.seq, data.safe_structure]
24
- end
25
- end
26
-
27
12
  def partition
28
13
  response.split(/\n/).find { |line| line =~ /^Scaling factor.*:\s+(\d+\.\d+)/ }
29
14
  BigDecimal.new($1)
@@ -37,32 +22,5 @@ module ViennaRna
37
22
  def distribution
38
23
  self.class.parse(response).map { |row| BigDecimal.new(row[1]) }
39
24
  end
40
-
41
- def windows
42
- # This is starting to feel pretty hackety.
43
- response.gsub(/Sum.*\n+Window size:\s+\d+/) { |match| "[:separator:]" + match }.split("[:separator:]").map do |window_response|
44
- window_size = window_response.match(/Window size:\s+(\d+)/)[1].to_i
45
- window_index = window_response.match(/Window starting index:\s+(\d+)/)[1].to_i
46
-
47
- self.class.new(seq: data.seq[window_index - 1, window_size], str: data.safe_structure[window_index - 1, window_size]).tap do |window_run|
48
- class << window_run
49
- attr_accessor :response, :window_size, :window_index
50
- end
51
-
52
- window_run.response = window_response
53
- window_run.window_size = window_size
54
- window_run.window_index = window_index
55
- end
56
- end
57
- end
58
-
59
- def compare
60
- {
61
- dispatch: self.class.new(data).run(mode: :dispatch).distribution,
62
- standalone: self.class.new(data).run(mode: :standalone).distribution
63
- }.tap do |hash|
64
- hash[:tvd] = Diverge.new(hash[:dispatch], hash[:standalone]).tvd
65
- end
66
- end
67
25
  end
68
26
  end
@@ -0,0 +1,5 @@
1
+ module ViennaRna
2
+ class Fftbor2d < Fftbor
3
+
4
+ end
5
+ end
@@ -7,12 +7,12 @@ module ViennaRna
7
7
  attr_reader :mfe_rna, :structure, :mfe
8
8
 
9
9
  def post_process
10
- structure = @response.split(/\n/).last.gsub(Parser::REGEXP[:mfe], "")
10
+ structure = Parser.rnafold_mfe_structure(@response)
11
11
 
12
12
  unless data.seq.length == structure.length
13
13
  raise "Sequence: '#{data.seq}'\nStructure: '#{structure}'"
14
14
  else
15
- @mfe_rna, @structure, @mfe = ViennaRna::Rna.new(data.seq, structure), structure, Parser.mfe(@response)
15
+ @mfe_rna, @structure, @mfe = ViennaRna::Rna.init_from_string(data.seq, structure), structure, Parser.rnafold_mfe(@response)
16
16
  end
17
17
  end
18
18
 
@@ -5,8 +5,12 @@ module ViennaRna
5
5
  }
6
6
 
7
7
  class << self
8
- def mfe(response)
9
- response.split(/\n/).last.match(REGEXP[:mfe])[1].to_f
8
+ def rnafold_mfe_structure(response)
9
+ response.split(/\n/)[1].split(/\s+/).first
10
+ end
11
+
12
+ def rnafold_mfe(response)
13
+ response.split(/\n/)[1].match(REGEXP[:mfe])[1].to_f
10
14
  end
11
15
  end
12
16
  end
@@ -2,32 +2,69 @@ module ViennaRna
2
2
  class Rna
3
3
  include ViennaRna::RnaExtensions
4
4
 
5
- attr_reader :sequence, :structure
5
+ attr_reader :sequence, :structure, :raw_data
6
6
 
7
- def initialize(sequence, structure = nil)
8
- if sequence.class == self.class
9
- # Too bad you can't do this in a cleaner way without method chaining initialize
10
- @sequence = sequence.sequence
11
- @structure = sequence.structure
12
- else
13
- @sequence = sequence.upcase
14
- @structure = (structure == :mfe ? ViennaRna::Fold.run(seq).structure : structure)
7
+ class << self
8
+ def init_from_string(sequence, structure = nil)
9
+ new(sequence, structure)
10
+ end
11
+
12
+ def init_from_hash(hash)
13
+ new(hash[:sequence] || hash[:seq], hash[:structure] || hash[:str], hash)
14
+ end
15
+
16
+ def init_from_array(array)
17
+ new(*array)
18
+ end
19
+
20
+ def init_from_fasta(string)
21
+ init_from_string(*string.split(/\n/).reject { |line| line.start_with?(">") })
22
+ end
23
+
24
+ def init_from_self(rna)
25
+ # This happens when you call a ViennaRna library function with the output of something like ViennaRna::Fold.run(...).mfe
26
+ new(rna.sequence, rna.structure, rna.raw_data)
27
+ end
28
+ end
29
+
30
+ def initialize(sequence, structure, raw_data = {})
31
+ @sequence, @raw_data = sequence, raw_data
32
+
33
+ @structure = case structure
34
+ when :empty then empty_structure
35
+ when :mfe then ViennaRna::Fold.run(ViennaRna::Rna.init_from_string(seq)).structure
36
+ when String then structure
15
37
  end
16
38
  end
17
-
39
+
18
40
  alias :seq :sequence
19
41
  alias :str :structure
20
-
21
- def safe_structure
22
- structure || empty_structure
42
+
43
+ def inspect
44
+ case [sequence.present?, structure.present?]
45
+ when [true, true] then
46
+ "#<ViennaRna::#{self.class.name} #{seq[0, 20] + (seq.length > 20 ? '...' : '')} #{str[0, 20] + (str.length > 20 ? ' [truncated]' : '')}>"
47
+ when [true, false] then
48
+ "#<ViennaRna::#{self.class.name} #{seq[0, 20] + (seq.length > 20 ? '...' : '')}>"
49
+ when [false, false] then
50
+ "#<ViennaRna::#{self.class.name}>"
51
+ end
52
+ end
53
+
54
+ def write_fa!(filename, comment = "")
55
+ (File.basename(filename, ".fa") + ".fa").tap do |filename|
56
+ File.open(filename, "w") do |file|
57
+ file.write("> %s\n" % comment) if comment
58
+ file.write("%s\n" % seq) if seq
59
+ file.write("%s\n" % str) if str
60
+ end
61
+ end
23
62
  end
63
+
64
+ private
24
65
 
25
66
  def empty_structure
26
67
  "." * seq.length
27
68
  end
28
-
29
- def inspect
30
- "#<ViennaRna::#{self.class.name} #{seq[0, 20] + ('...' if seq.length > 20)} #{str[0, 20] + ('[truncated]' if seq.length > 20)}>"
31
- end
32
69
  end
33
70
  end
@@ -18,7 +18,7 @@ module ViennaRna
18
18
  module ClassMethods
19
19
  def generate_sequence(sequence_length)
20
20
  # 0th order Markov chain w/ uniform probability distribution
21
- sequence_length.times.inject("") { |string, _| string + %w[A U C G][rand(4)] }
21
+ Rna.init_from_string(sequence_length.times.inject("") { |string, _| string + %w[A U C G][rand(4)] })
22
22
  end
23
23
 
24
24
  def shuffle(sequence, token_length = 2)
@@ -3,7 +3,7 @@ module ViennaRna
3
3
  attr_reader :structures
4
4
 
5
5
  def post_process
6
- @structures = @response.split(/\n/)
6
+ @structures = @response.split(/\n/)[1..-1].map { |output| ViennaRna::Rna.init_from_string(data.seq, output.split(/\s+/).first) }
7
7
  end
8
8
 
9
9
  def bin(count = 1)
@@ -33,10 +33,12 @@ module ViennaRna
33
33
  def plot(data, options = {})
34
34
  Gnuplot.open do |gnuplot|
35
35
  Gnuplot::Plot.new(gnuplot) do |plot|
36
+ plot.autoscale
37
+
36
38
  case options[:output]
37
39
  when /file/i then
38
40
  plot.output(options[:filename])
39
- plot.terminal("png size 800,600")
41
+ plot.terminal("png size %s" % (options[:dimensions] || "800,600"))
40
42
  end
41
43
 
42
44
  (options[:plot] || {}).keys.each do |option|
@@ -45,7 +47,9 @@ module ViennaRna
45
47
 
46
48
  plot.data = data.map do |data_hash|
47
49
  Gnuplot::DataSet.new([data_hash[:x], data_hash[:y]]) do |dataset|
48
- dataset.with = data_hash[:style] || "points"
50
+ dataset.with = data_hash[:style] || "points"
51
+ dataset.linecolor = "rgb '#{data_hash[:color]}'" if data_hash[:color]
52
+
49
53
  data_hash[:title] ? dataset.title = data_hash[:title] : dataset.notitle
50
54
  end
51
55
  end
@@ -59,6 +63,8 @@ module ViennaRna
59
63
 
60
64
  Gnuplot.open do |gnuplot|
61
65
  Gnuplot::SPlot.new(gnuplot) do |plot|
66
+ plot.autoscale
67
+
62
68
  case options[:output]
63
69
  when /file/i then
64
70
  plot.output(options[:filename])
@@ -78,6 +84,42 @@ module ViennaRna
78
84
  end
79
85
  end
80
86
 
87
+ def histogram(data, title = "", options = {})
88
+ bin_size = options.delete(:bin_size) || 1
89
+ half = bin_size / 2.0
90
+ range = Range.new((data.min - half).floor, (data.max + half).ceil)
91
+ groups = (range.min + half).step(range.max, bin_size).map { |x| [x, data.count { |i| i >= x - half && i < x + half }] }
92
+
93
+ options.merge!(output: "file") if options[:filename]
94
+ options.merge!({
95
+ plot: {
96
+ title: title,
97
+ yrange: "[0:#{groups.map(&:last).max * 1.1}]",
98
+ xtics: "#{[bin_size, 5].max}",
99
+ style: "fill solid 0.5 border"
100
+ }
101
+ })
102
+
103
+ plot([{ x: groups.map(&:first), y: groups.map(&:last), style: "boxes" }], options)
104
+ end
105
+
106
+ def roc(data, title = "", options = {})
107
+ # data = [[true_score_1, true_score_2, ...], [false_score_1, false_score_2, ...]]
108
+ # This 'twiddle' removes duplicates by adding a very small random number to any repeated value
109
+ data = data.map { |scores| scores.group_by(&:_ident).values.inject([]) { |array, values| array + (values.size > 1 ? values.map { |i| i + 1e-8 * (rand - 0.5) } : values) } }
110
+
111
+ roc_curve = ROC.curve_points({ 1 => data[0], -1 => data[1] }.inject([]) { |data, (truth, values)| data.concat(values.map { |i| [i, truth] })})
112
+ area = roc_curve.each_cons(2).inject(0) do |sum, (a, b)|
113
+ delta_x, delta_y = b[0] - a[0], b[1] - a[1]
114
+ sum + (delta_x * delta_y / 2 + delta_x * [a[1], b[1]].min)
115
+ end
116
+
117
+ options.merge!(output: "file") if options[:filename]
118
+ options.merge!({ plot: { title: "%s %s %.4f" % [title, "AUC:", area] } })
119
+
120
+ plot([{ x: roc_curve.map(&:first), y: roc_curve.map(&:last), style: "lines" }], options)
121
+ end
122
+
81
123
  def quick_plot(data, title = "", options = {})
82
124
  quick_overlay([{ data: data }], title, options)
83
125
  end
@@ -12,9 +12,11 @@ module ViennaRna
12
12
  def run_command(flags = {})
13
13
  file = Tempfile.new("rna")
14
14
  file.write("%s\n" % data.seq)
15
- file.write("%s\n" % data.safe_structure)
15
+ file.write("%s\n" % data.str)
16
16
  file.close
17
17
 
18
+ debugger { "Running FFTbor on #{data.inspect}" }
19
+
18
20
  "%s %s %s" % [
19
21
  exec_name,
20
22
  stringify_flags(BASE_FLAGS.merge(self.class.const_defined?(:FLAGS) ? self.class.const_get(:FLAGS) : {}).merge(flags)),
@@ -22,6 +24,14 @@ module ViennaRna
22
24
  ]
23
25
  end
24
26
 
27
+ def self.bootstrap_from_file(path, klass = self)
28
+ log = File.read(path)
29
+ sequence = log.split(/\n/).first.split(/\s+/)[1]
30
+ structure = log.split(/\n/).first.split(/\s+/)[2]
31
+
32
+ klass.bootstrap(ViennaRna::Rna.init_from_string(sequence, structure), log)
33
+ end
34
+
25
35
  def self.parse(response)
26
36
  response.split(/\n/).select { |line| line =~ /^\d+\t-?\d+/ }.map { |line| line.split(/\t/) }
27
37
  end
data/lib/vienna_rna.rb CHANGED
@@ -3,6 +3,7 @@ require "bio"
3
3
  require "shuffle"
4
4
  require "matrix"
5
5
  require "gnuplot"
6
+ require "rroc"
6
7
  require "active_support/inflector"
7
8
  require "active_support/core_ext/class"
8
9
  require "active_support/core_ext/module/aliasing"
metadata CHANGED
@@ -1,80 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vienna_rna
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Evan Senter
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-11-05 00:00:00.000000000 Z
11
+ date: 2013-04-29 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bio
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 1.4.2
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 1.4.2
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: activesupport
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '3.2'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '3.2'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: shuffle
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: 0.1.0
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: 0.1.0
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: gnuplot
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: 2.5.0
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: 2.5.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rroc
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.1.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.1.1
78
83
  description: A Ruby API for interacting with the Vienna RNA package.
79
84
  email: evansenter@gmail.com
80
85
  executables: []
@@ -85,6 +90,7 @@ files:
85
90
  - lib/vienna_rna/modules/batch.rb
86
91
  - lib/vienna_rna/modules/eval.rb
87
92
  - lib/vienna_rna/modules/fftbor.rb
93
+ - lib/vienna_rna/modules/fftbor2d.rb
88
94
  - lib/vienna_rna/modules/ffthairpin.rb
89
95
  - lib/vienna_rna/modules/fftmultiloop.rb
90
96
  - lib/vienna_rna/modules/fold.rb
@@ -100,26 +106,25 @@ files:
100
106
  - README.md
101
107
  homepage: http://rubygems.org/gems/vienna_rna
102
108
  licenses: []
109
+ metadata: {}
103
110
  post_install_message:
104
111
  rdoc_options: []
105
112
  require_paths:
106
113
  - lib
107
114
  required_ruby_version: !ruby/object:Gem::Requirement
108
- none: false
109
115
  requirements:
110
- - - ! '>='
116
+ - - '>='
111
117
  - !ruby/object:Gem::Version
112
118
  version: '0'
113
119
  required_rubygems_version: !ruby/object:Gem::Requirement
114
- none: false
115
120
  requirements:
116
- - - ! '>='
121
+ - - '>='
117
122
  - !ruby/object:Gem::Version
118
123
  version: '0'
119
124
  requirements: []
120
125
  rubyforge_project:
121
- rubygems_version: 1.8.24
126
+ rubygems_version: 2.0.2
122
127
  signing_key:
123
- specification_version: 3
128
+ specification_version: 4
124
129
  summary: Bindings to the Vienna RNA package.
125
130
  test_files: []