vienna_rna 0.8.6 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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