vienna_rna 0.8.6 → 0.9.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vienna_rna/global/parser.rb +19 -0
  3. data/lib/vienna_rna/global/rna.rb +115 -0
  4. data/lib/vienna_rna/global/rna_extensions.rb +109 -0
  5. data/lib/vienna_rna/{modules/graphing.rb → graphing/r.rb} +49 -111
  6. data/lib/vienna_rna/package/base.rb +117 -0
  7. data/lib/vienna_rna/package/energy_grid_2d.rb +69 -0
  8. data/lib/vienna_rna/package/eval.rb +11 -0
  9. data/lib/vienna_rna/package/fftbor.rb +19 -0
  10. data/lib/vienna_rna/package/fftbor2d.rb +25 -0
  11. data/lib/vienna_rna/package/fold.rb +31 -0
  12. data/lib/vienna_rna/package/heat.rb +15 -0
  13. data/lib/vienna_rna/package/rna2dfold.rb +27 -0
  14. data/lib/vienna_rna/package/rnabor.rb +32 -0
  15. data/lib/vienna_rna/package/subopt.rb +19 -0
  16. data/lib/vienna_rna/package/xbor.rb +63 -0
  17. data/lib/vienna_rna.rb +27 -14
  18. metadata +22 -38
  19. data/lib/vienna_rna/modules/base.rb +0 -124
  20. data/lib/vienna_rna/modules/batch.rb +0 -26
  21. data/lib/vienna_rna/modules/energy_grid_2d.rb +0 -63
  22. data/lib/vienna_rna/modules/eval.rb +0 -9
  23. data/lib/vienna_rna/modules/fftbor.rb +0 -21
  24. data/lib/vienna_rna/modules/fftbor2d.rb +0 -23
  25. data/lib/vienna_rna/modules/ffthairpin.rb +0 -4
  26. data/lib/vienna_rna/modules/fftmultiloop.rb +0 -4
  27. data/lib/vienna_rna/modules/fold.rb +0 -29
  28. data/lib/vienna_rna/modules/heat.rb +0 -13
  29. data/lib/vienna_rna/modules/parser.rb +0 -17
  30. data/lib/vienna_rna/modules/rna.rb +0 -113
  31. data/lib/vienna_rna/modules/rna2dfold.rb +0 -25
  32. data/lib/vienna_rna/modules/rna_extensions.rb +0 -101
  33. data/lib/vienna_rna/modules/rnabor.rb +0 -33
  34. data/lib/vienna_rna/modules/subopt.rb +0 -17
  35. data/lib/vienna_rna/modules/utils.rb +0 -34
  36. data/lib/vienna_rna/modules/xbor.rb +0 -64
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99cbd2a9afe1fb15daae72432caf558589d780f9
4
- data.tar.gz: fbb4a27a788983898147fbb67bcbf91cae0cbaed
3
+ metadata.gz: 1fc492c40bf3f4d1c52ecf1afd09810c9798471a
4
+ data.tar.gz: 2a7ea6a2eeaca132e055e6aacc3cb1f0456990ef
5
5
  SHA512:
6
- metadata.gz: 17f72d39b411f7ad5b19aaa60d11e91e392a86eae84712f95c804ce121648f55b85adbb904bf536ec137b590707f70d6b66b4a85cdf501501e0e68b8286f224f
7
- data.tar.gz: 550bb20dbbc67f04cec01471db211378aa50e5784296c603f1871e2ab60d3bda6f02e2924d97cba4cbd39ab5d4b268392aa2634a55b1758e089187b3252e7ce1
6
+ metadata.gz: 16e9902e83a11b8143b598b565ce2d9acf78e0dcd59a89079cecace6d40e9eff4108fa331e1488ed29ce6b281d2d76a132e6fa84d377ec4a0c14004f19be1d2f
7
+ data.tar.gz: 191f17dea3941c52c2c990d29e881bd331bc96cdee50857f42f7acfa5b27a252c61966600e7e13e88a6f6fbbf75571afd5c31f0cd98cc75773060f96eb2f86fc
@@ -0,0 +1,19 @@
1
+ module ViennaRna
2
+ module Global
3
+ module Parser
4
+ REGEXP = {
5
+ mfe: / \(\s*(-?\d*\.\d*)\)$/
6
+ }
7
+
8
+ class << self
9
+ def rnafold_mfe_structure(response)
10
+ response.split(/\n/)[1].split(/\s+/).first
11
+ end
12
+
13
+ def rnafold_mfe(response)
14
+ response.split(/\n/)[1].match(REGEXP[:mfe])[1].to_f
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,115 @@
1
+ module ViennaRna
2
+ module Global
3
+ class Rna
4
+ include RnaExtensions
5
+
6
+ attr_reader :sequence, :structure, :second_structure, :raw_data
7
+
8
+ class << self
9
+ def init_from_string(sequence, structure = nil, second_structure = nil)
10
+ new(
11
+ sequence: sequence,
12
+ structure: structure,
13
+ second_structure: second_structure
14
+ )
15
+ end
16
+
17
+ def init_from_hash(hash)
18
+ new(
19
+ sequence: hash[:sequence] || hash[:seq],
20
+ structure: hash[:structure] || hash[:str_1] || hash[:str],
21
+ second_structure: hash[:second_structure] || hash[:str_2],
22
+ raw_data: hash
23
+ )
24
+ end
25
+
26
+ def init_from_array(array)
27
+ init_from_string(*array)
28
+ end
29
+
30
+ def init_from_fasta(string)
31
+ string = File.read(string).chomp if File.exist?(string)
32
+ init_from_string(*string.split(/\n/).reject { |line| line.start_with?(">") }[0, 3])
33
+ end
34
+
35
+ def init_from_self(rna)
36
+ # This happens when you call a ViennaRna library function with the output of something like ViennaRna::Fold.run(...).mfe
37
+ new(
38
+ sequence: rna.sequence,
39
+ strucutre: rna.structure,
40
+ second_strucutre: rna.second_structure,
41
+ raw_data: rna.raw_data
42
+ )
43
+ end
44
+
45
+ alias_method :placeholder, :new
46
+ end
47
+
48
+ def initialize(sequence: "", structure: "", second_structure: "", raw_data: {})
49
+ @sequence, @raw_data = sequence, raw_data
50
+
51
+ [:structure, :second_structure].each do |structure_symbol|
52
+ instance_variable_set(
53
+ :"@#{structure_symbol}",
54
+ case structure_value = eval("#{structure_symbol}")
55
+ when :empty then empty_structure
56
+ when :mfe then RNA(sequence).run(:fold).mfe_rna.structure
57
+ when String then structure_value
58
+ end
59
+ )
60
+ end
61
+
62
+ if str && seq.length != str.length
63
+ ViennaRna.debugger { "The sequence length (%d) doesn't match the structure length (%d)" % [seq, str].map(&:length) }
64
+ end
65
+
66
+ if str_2 && str_1.length != str_2.length
67
+ ViennaRna.debugger { "The first structure length (%d) doesn't match the second structure length (%d)" % [str_1, str_2].map(&:length) }
68
+ end
69
+ end
70
+
71
+ alias :seq :sequence
72
+ alias :str :structure
73
+ alias :str_1 :structure
74
+ alias :str_2 :second_structure
75
+
76
+ def empty_structure
77
+ "." * seq.length
78
+ end
79
+
80
+ alias :empty_str :empty_structure
81
+
82
+ def write_fa!(filename, comment = nil)
83
+ filename.tap do |filename|
84
+ File.open(filename, ?w) do |file|
85
+ file.write("> %s\n" % comment) if comment
86
+ file.write("%s\n" % seq) if seq
87
+ file.write("%s\n" % str_1) if str_1
88
+ file.write("%s\n" % str_2) if str_2
89
+ end
90
+ end
91
+ end
92
+
93
+ def temp_fa_file!
94
+ write_fa!(Tempfile.new("")).path
95
+ end
96
+
97
+ def run(module_name, options = {})
98
+ if rna_module = ViennaRna.const_missing("#{module_name}".camelize)
99
+ rna_module.run(self, options)
100
+ else
101
+ raise ArgumentError.new("#{module_name} can't be resolved as an executable")
102
+ end
103
+ end
104
+
105
+ def inspect
106
+ "#<%s>" % [
107
+ "#{self.class.name}",
108
+ ("#{seq[0, 20] + (seq.length > 20 ? '...' : '')}" if seq && !seq.empty?),
109
+ ("#{str_1[0, 20] + (str_1.length > 20 ? ' [truncated]' : '')}" if str_1 && !str_1.empty?),
110
+ ("#{str_2[0, 20] + (str_2.length > 20 ? ' [truncated]' : '')}" if str_2 && !str_1.empty?),
111
+ ].compact.join(" ")
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,109 @@
1
+ module ViennaRna
2
+ module Global
3
+ module RnaExtensions
4
+ def self.included(base)
5
+ base.send(:include, InstanceMethods)
6
+ base.extend(ClassMethods)
7
+ base.extend(OneStructureBasedMethods)
8
+ base.extend(TwoStructureBasedMethods)
9
+
10
+ base.class_eval do
11
+ OneStructureBasedMethods.public_instance_methods.each do |class_method|
12
+ define_method(class_method) do |*args|
13
+ self.class.send(class_method, *[structure].concat(args))
14
+ end
15
+ end
16
+
17
+ TwoStructureBasedMethods.public_instance_methods.each do |class_method|
18
+ define_method(class_method) do |*args|
19
+ self.class.send(class_method, *[str_1, str_2].concat(args))
20
+ end
21
+ end
22
+ end
23
+
24
+ base.send(:include, InstanceMethods)
25
+ end
26
+
27
+ module ClassMethods
28
+ def generate_sequence(sequence_length)
29
+ # 0th order Markov chain w/ uniform probability distribution
30
+ Rna.init_from_string(sequence_length.times.inject("") { |string, _| string + %w[A U C G][rand(4)] })
31
+ end
32
+
33
+ def shuffle(sequence, token_length = 2)
34
+ Shuffle.new(sequence).shuffle(token_length)
35
+ end
36
+ end
37
+
38
+ module InstanceMethods
39
+ def dishuffle
40
+ self.class.shuffle(sequence, 2)
41
+ end
42
+
43
+ def gc_content
44
+ seq.split(//).select { |i| i =~ /[GC]/i }.size.to_f / seq.size
45
+ end
46
+ end
47
+
48
+ module OneStructureBasedMethods
49
+ def max_bp_distance(structure)
50
+ base_pairs(structure).count + ((structure.length - 3) / 2.0).floor
51
+ end
52
+
53
+ def base_pairs(structure)
54
+ get_pairings(structure).each_with_index.inject(Set.new) do |set, (j, i)|
55
+ j >= 0 ? set << Set[i, j] : set
56
+ end
57
+ end
58
+
59
+ def get_pairings(structure)
60
+ stack = []
61
+
62
+ structure.each_char.each_with_index.inject(Array.new(structure.length, -1)) do |array, (symbol, index)|
63
+ array.tap do
64
+ case symbol
65
+ when "(" then stack.push(index)
66
+ when ")" then
67
+ if stack.empty?
68
+ raise "Too many ')' in '#{structure}'"
69
+ else
70
+ stack.pop.tap do |opening|
71
+ array[opening] = index
72
+ array[index] = opening
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end.tap do
78
+ raise "Too many '(' in '#{structure}'" unless stack.empty?
79
+ end
80
+ end
81
+ end
82
+
83
+ module TwoStructureBasedMethods
84
+ def bp_distance(structure_1, structure_2)
85
+ # Takes two structures and calculates the distance between them by |symmetric difference(bp_in_a, bp_in_b)|
86
+ raise "The two structures are not the same length" unless structure_1.length == structure_2.length
87
+
88
+ bp_set_1, bp_set_2 = base_pairs(structure_1), base_pairs(structure_2)
89
+
90
+ ((bp_set_1 - bp_set_2) + (bp_set_2 - bp_set_1)).count
91
+ end
92
+
93
+ def symmetric_bp_distance(structure_1, structure_2)
94
+ # Takes two structures and calculates the distance between them by: sum { ((x_j - x_i) - (y_j - y_i)).abs }
95
+ raise "The two structures are not the same length" unless structure_1.length == structure_2.length
96
+
97
+ bp_dist = ->(array, i) { array[i] == -1 ? 0 : array[i] - i }
98
+
99
+ structure_1_pairings = get_pairings(structure_1)
100
+ structure_2_pairings = get_pairings(structure_2)
101
+
102
+ structure_1.length.times.inject(0) do |distance, i|
103
+ distance + (bp_dist[structure_1_pairings, i] - bp_dist[structure_2_pairings, i]).abs
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -9,31 +9,70 @@ module ViennaRna
9
9
  raise unless e.message == "Unsupported data type on R's end"
10
10
  end
11
11
  end
12
-
13
- def line_graph(data, title: nil, type: "l", x_label: "Independent", y_label: "Dependent", filename: false)
12
+
13
+ def overlay(data, title: nil, type: ?l, x_label: "Independent", y_label: "Dependent", legend: "topleft", filename: false)
14
+ # data: [{ data: [[x_0, y_0], ..., [x_n, y_n]], legend: "Line 1" }, ...]
15
+
16
+ x_points = data.map { |hash| hash[:data].map(&:first) }
17
+ y_points = data.map { |hash| hash[:data].map(&:last) }
18
+ x_range = Range.new(x_points.map(&:min).min.floor, x_points.map(&:max).max.ceil)
19
+ y_range = Range.new(y_points.map(&:min).min.floor, y_points.map(&:max).max.ceil)
20
+
14
21
  graph do |r|
15
- r.assign("line_graph.x", data.map(&:first))
16
- r.assign("line_graph.y", data.map(&:last))
17
-
18
22
  r.eval("%s('%s', 6, 6)" % [
19
23
  writing_file?(filename) ? "pdf" : "quartz",
20
24
  writing_file?(filename) ? filename : "Graph",
21
25
  ])
22
26
 
27
+ r.assign("legend.titles", data.each_with_index.map { |hash, index| hash[:legend] || "Line #{index + 1}" })
28
+ r.eval("line.colors <- rainbow(%d)" % data.size)
29
+ r.eval("plot(0, 0, type = 'n', cex = .75, xlab = '', ylab = '', xlim = c(%d, %d), ylim = c(%d, %d))" % [
30
+ x_range.min, x_range.max, y_range.min, y_range.max
31
+ ])
32
+
33
+ data.each_with_index do |hash, index|
34
+ r.assign("line_graph.x.%d" % index, x_points[index])
35
+ r.assign("line_graph.y.%d" % index, y_points[index])
36
+
37
+ r.eval <<-STR
38
+ lines(
39
+ line_graph.x.#{index},
40
+ line_graph.y.#{index},
41
+ col = line.colors[#{index + 1}],
42
+ type = "#{type}",
43
+ pch = #{index}
44
+ )
45
+ STR
46
+ end
47
+
23
48
  r.eval <<-STR
24
- plot(
25
- line_graph.x,
26
- line_graph.y,
49
+ title(
27
50
  xlab = "#{x_label}",
28
51
  ylab = "#{y_label}",
29
- main = "#{title || 'Line Graph'}",
30
- type = "#{type}"
52
+ main = "#{title || 'Line Graph'}"
31
53
  )
32
54
  STR
55
+
56
+ if legend
57
+ r.eval <<-STR
58
+ legend(
59
+ "#{legend}",
60
+ legend.titles,
61
+ bty = "n",
62
+ col = line.colors,
63
+ lty = rep(1, #{data.size}),
64
+ pch = 0:#{data.size}
65
+ )
66
+ STR
67
+ end
33
68
 
34
69
  r.eval("dev.off()") if writing_file?(filename)
35
70
  end
36
71
  end
72
+
73
+ def line_graph(data, title: nil, type: ?l, x_label: "Independent", y_label: "Dependent", filename: false)
74
+ overlay([{ data: data }], title: title, type: type, x_label: x_label, y_label: y_label, legend: false, filename: filename)
75
+ end
37
76
 
38
77
  def histogram(data, title: nil, x_label: "Bins", bin_size: 1, relative: false, filename: false)
39
78
  half = bin_size / 2.0
@@ -150,106 +189,5 @@ module ViennaRna
150
189
  end
151
190
  end
152
191
  end
153
-
154
- module Gnuplot
155
- class << self
156
- def plot(data, options = {})
157
- Gnuplot.open do |gnuplot|
158
- Gnuplot::Plot.new(gnuplot) do |plot|
159
- plot.autoscale
160
-
161
- case options[:output]
162
- when /file/i then
163
- plot.output(options[:filename])
164
- plot.terminal("png size %s" % (options[:dimensions] || "800,600"))
165
- end
166
-
167
- (options[:plot] || {}).keys.each do |option|
168
- plot.send(option, options[:plot][option])
169
- end
170
-
171
- plot.data = data.map do |data_hash|
172
- Gnuplot::DataSet.new([data_hash[:x], data_hash[:y]]) do |dataset|
173
- dataset.with = data_hash[:style] || "points"
174
- dataset.linecolor = "rgb '#{data_hash[:color]}'" if data_hash[:color]
175
-
176
- data_hash[:title] ? dataset.title = data_hash[:title] : dataset.notitle
177
- end
178
- end
179
- end
180
- end
181
- end
182
-
183
- def splot(data, options = {})
184
- # [[x_1, y_1, z_1], [x_2, y_2, z_2], ...]
185
- orthogonal_data = data.inject([[], [], []]) { |array, list| array.zip(list).map { |a, e| a << e } }
186
-
187
- Gnuplot.open do |gnuplot|
188
- Gnuplot::SPlot.new(gnuplot) do |plot|
189
- plot.autoscale
190
-
191
- case options[:output]
192
- when /file/i then
193
- plot.output(options[:filename])
194
- plot.terminal("png size 800,600")
195
- end
196
-
197
- (options[:plot] || {}).keys.each do |option|
198
- plot.send(option, options[:plot][option])
199
- end
200
-
201
- plot.data = [
202
- Gnuplot::DataSet.new(orthogonal_data) do |dataset|
203
- dataset.with = options[:style] || "lines"
204
- end
205
- ]
206
- end
207
- end
208
- end
209
-
210
- def histogram(data, title = "", options = {})
211
- bin_size = options.delete(:bin_size) || 1
212
- half = bin_size / 2.0
213
- range = Range.new((data.min - half).floor, (data.max + half).ceil)
214
- groups = (range.min + half).step(range.max, bin_size).map { |x| [x, data.count { |i| i >= x - half && i < x + half }] }
215
-
216
- options.merge!(output: "file") if options[:filename]
217
- options[:plot] = (options[:plot] || {}).merge({
218
- title: title,
219
- yrange: "[0:#{groups.map(&:last).max * 1.1}]",
220
- xtics: "#{[bin_size, 5].max}",
221
- style: "fill solid 0.5 border"
222
- })
223
-
224
- plot([{ x: groups.map(&:first), y: groups.map(&:last), style: "boxes" }], options)
225
- end
226
-
227
- def roc(data, title = "", options = {})
228
- # data = [[true_score_1, true_score_2, ...], [false_score_1, false_score_2, ...]]~
229
- roc_curve = ROC.curve_points({ 1 => data[0], -1 => data[1] }.inject([]) { |data, (truth, values)| data.concat(values.map { |i| [i, truth] })})
230
- area = roc_curve.each_cons(2).inject(0) do |sum, (a, b)|
231
- delta_x, delta_y = b[0] - a[0], b[1] - a[1]
232
- sum + (delta_x * delta_y / 2 + delta_x * [a[1], b[1]].min)
233
- end
234
-
235
- options.merge!(output: "file") if options[:filename]
236
- options.merge!({ plot: { title: "%s %s %.4f" % [title, "AUC:", area] } })
237
-
238
- plot([{ x: roc_curve.map(&:first), y: roc_curve.map(&:last), style: "lines" }], options)
239
- end
240
-
241
- def quick_plot(data, title = "", options = {})
242
- quick_overlay([{ data: data }], title, options)
243
- end
244
-
245
- def quick_overlay(data, title = "", options = {})
246
- # [{ data: [[x_0, y_0], [x_1, y_1], ...], label: "Label" }, { data: [[x_0, y_0], [x_1, y_1], ...] }]
247
- options[:plot] = ((options[:plot] || {}).merge(title: title))
248
- options.merge!(output: "file") if options[:filename]
249
-
250
- plot(data.map { |hash| { title: hash[:label], x: hash[:data].map(&:first), y: hash[:data].map(&:last), style: "linespoints" }.merge(hash[:options] || {}) }, options)
251
- end
252
- end
253
- end
254
192
  end
255
193
  end
@@ -0,0 +1,117 @@
1
+ module ViennaRna
2
+ module Package
3
+ class Base
4
+ class_attribute :executable_name
5
+
6
+ class << self
7
+ def method_added(name)
8
+ if name == :run
9
+ unless @chaining
10
+ @chaining = true
11
+ alias_method_chain :run, :hooks
12
+ else
13
+ remove_instance_variable(:@chaining)
14
+ end
15
+ end
16
+ end
17
+
18
+ def exec_exists?(name)
19
+ !%x[which RNA#{name.to_s.downcase}].empty?
20
+ end
21
+
22
+ def run(*data)
23
+ flags = data.length > 1 && data.last.is_a?(Hash) ? data.pop : {}
24
+ new(data).run(flags)
25
+ end
26
+
27
+ def bootstrap(data: nil, output: "")
28
+ new(data).tap do |object|
29
+ object.instance_variable_set(:@response, File.exist?(output) ? File.read(output).chomp : output)
30
+ end
31
+ end
32
+ end
33
+
34
+ attr_reader :data, :response, :runtime
35
+
36
+ def exec_name
37
+ if executable_name
38
+ executable_name.respond_to?(:call) ? self.class.module_exec(&executable_name) : executable_name
39
+ else
40
+ "RNA#{self.class.name.split('::').last.underscore}"
41
+ end
42
+ end
43
+
44
+ def exec_sequence_format
45
+ if data.str
46
+ '"%s
47
+ %s"' % [data.seq, data.str]
48
+ else
49
+ data.seq
50
+ end
51
+ end
52
+
53
+ def initialize(data)
54
+ data = [data] unless data.is_a?(Array)
55
+
56
+ @data = case data.map(&:class)
57
+ when [ViennaRna::Global::Rna] then data.first
58
+ when *(1..3).map { |i| [String] * i } then RNA.from_string(*data)
59
+ when [Hash] then RNA.from_hash(*data)
60
+ when [Array] then RNA.from_array(*data)
61
+ when [NilClass] then ViennaRna::Global::Rna.placeholder
62
+ else raise TypeError.new("Unsupported ViennaRna::Global::Rna#initialize format: #{data}")
63
+ end
64
+ end
65
+
66
+ def run_with_hooks(flags = {})
67
+ unless @response
68
+ tap do
69
+ @runtime = Benchmark.measure do
70
+ pre_run_check unless respond_to?(:run_command)
71
+ @response = run_without_hooks(flags)
72
+ post_process if respond_to?(:post_process)
73
+ end
74
+
75
+ ViennaRna.debugger { "Total runtime: %.3f sec." % runtime.real }
76
+ end
77
+ else
78
+ self
79
+ end
80
+ end
81
+
82
+ def pre_run_check
83
+ if %x[which #{exec_name}].empty?
84
+ raise RuntimeError.new("#{exec_name} is not defined on this machine")
85
+ end
86
+ end
87
+
88
+ def stringify_flags(flags)
89
+ base_flags = self.class.const_defined?(:BASE_FLAGS) ? self.class.const_get(:BASE_FLAGS) : {}
90
+
91
+ flags.merge(base_flags).inject("") do |string, (flag, value)|
92
+ (string + (value == :empty ? " -%s" % flag : " -%s %s" % [flag, value])).strip
93
+ end
94
+ end
95
+
96
+ def run(flags = {})
97
+ command = if respond_to?(:run_command)
98
+ method(:run_command).arity.zero? ? run_command : run_command(flags)
99
+ else
100
+ "echo #{exec_sequence_format} | #{exec_name} #{stringify_flags(flags)}"
101
+ end
102
+
103
+ ViennaRna.debugger { command }
104
+
105
+ %x[#{command}]
106
+ end
107
+
108
+ def serialize
109
+ YAML.dump(self)
110
+ end
111
+
112
+ def debugger(&block)
113
+ self.class.debugger(&block)
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,69 @@
1
+ module ViennaRna
2
+ module Package
3
+ class EnergyGrid2d < Base
4
+ include Enumerable
5
+
6
+ def self.inherited(subclass)
7
+ subclass.class_eval { prepend EnergyGrid2dWrapper }
8
+ end
9
+
10
+ module EnergyGrid2dWrapper
11
+ def distribution
12
+ super.map { |row| Row2d.new(*row) }.select { |row| row.p > 0 }.sort
13
+ end
14
+ end
15
+
16
+ class Row2d
17
+ attr_reader :i, :j, :p, :ensemble
18
+
19
+ def initialize(i, j, p, ensemble)
20
+ @i, @j, @p, @ensemble = i.to_i, j.to_i, BigDecimal.new(p.to_s), BigDecimal.new(ensemble.to_s)
21
+ end
22
+
23
+ def position
24
+ [i, j]
25
+ end
26
+
27
+ def <=>(other_row)
28
+ i == other_row.i ? j <=> other_row.j : i <=> other_row.i
29
+ end
30
+
31
+ def inspect
32
+ "#<Row2d (%d, %d), p: %s, ensemble: %s>" % [i, j, p, ensemble]
33
+ end
34
+ end
35
+
36
+ def self.aligned_distributions(*energy_grids)
37
+ point_set = set_of_points(*energy_grids)
38
+
39
+ energy_grids.map do |grid|
40
+ (grid.distribution + (point_set - grid.map(&:position)).map { |i, j| Row2d.new(i, j, 0, Float::INFINITY) }).sort
41
+ end
42
+ end
43
+
44
+ def self.set_of_points(*energy_grids)
45
+ energy_grids.inject([]) { |list, grid| list + grid.map(&:position) }.uniq.sort
46
+ end
47
+
48
+ def each(&block)
49
+ distribution.each(&block)
50
+ end
51
+
52
+ def quick_plot(num_colors: 8)
53
+ Graphing::R.matrix_heatmap(
54
+ distribution.map(&:i),
55
+ distribution.map(&:j),
56
+ distribution.map { |row| Math.log(row.p) },
57
+ title: "#{self.class.name} Matrix Heatmap",
58
+ x_label: "Distance from structure 2",
59
+ y_label: "Distance from structure 1",
60
+ num_colors: num_colors
61
+ )
62
+ end
63
+
64
+ def inspect
65
+ "#<#{self.class.name} on #{data.inspect}>"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ module ViennaRna
2
+ module Package
3
+ class Eval < Base
4
+ attr_reader :mfe
5
+
6
+ def post_process
7
+ @mfe = ViennaRna::Global::Parser.rnafold_mfe(@response)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module ViennaRna
2
+ module Package
3
+ class Fftbor < Xbor
4
+ def partition
5
+ response.split(/\n/).find { |line| line =~ /^Scaling factor.*:\s+(\d+\.\d+)/ }
6
+ BigDecimal.new($1)
7
+ end
8
+
9
+ def total_count
10
+ response.split(/\n/).find { |line| line =~ /^Number of structures: (\d+)/ }
11
+ $1.to_i
12
+ end
13
+
14
+ def distribution
15
+ self.class.parse(response).map { |row| BigDecimal.new(row[1]) }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ module ViennaRna
2
+ module Package
3
+ class Fftbor2d < EnergyGrid2d
4
+ BASE_FLAGS = {
5
+ S: :empty
6
+ }
7
+
8
+ self.executable_name = "FFTbor2D"
9
+
10
+ def run_command(flags = {})
11
+ ViennaRna.debugger { "Running #{exec_name} on #{data.inspect}" }
12
+
13
+ "%s %s %s" % [
14
+ exec_name,
15
+ stringify_flags(BASE_FLAGS.merge(self.class.const_defined?(:FLAGS) ? self.class.const_get(:FLAGS) : {}).merge(flags)),
16
+ data.temp_fa_file!
17
+ ]
18
+ end
19
+
20
+ def distribution
21
+ response.split(/\n/).map { |line| line.split(/\t/) }
22
+ end
23
+ end
24
+ end
25
+ end