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.
- checksums.yaml +4 -4
- data/lib/vienna_rna/global/parser.rb +19 -0
- data/lib/vienna_rna/global/rna.rb +115 -0
- data/lib/vienna_rna/global/rna_extensions.rb +109 -0
- data/lib/vienna_rna/{modules/graphing.rb → graphing/r.rb} +49 -111
- data/lib/vienna_rna/package/base.rb +117 -0
- data/lib/vienna_rna/package/energy_grid_2d.rb +69 -0
- data/lib/vienna_rna/package/eval.rb +11 -0
- data/lib/vienna_rna/package/fftbor.rb +19 -0
- data/lib/vienna_rna/package/fftbor2d.rb +25 -0
- data/lib/vienna_rna/package/fold.rb +31 -0
- data/lib/vienna_rna/package/heat.rb +15 -0
- data/lib/vienna_rna/package/rna2dfold.rb +27 -0
- data/lib/vienna_rna/package/rnabor.rb +32 -0
- data/lib/vienna_rna/package/subopt.rb +19 -0
- data/lib/vienna_rna/package/xbor.rb +63 -0
- data/lib/vienna_rna.rb +27 -14
- metadata +22 -38
- data/lib/vienna_rna/modules/base.rb +0 -124
- data/lib/vienna_rna/modules/batch.rb +0 -26
- data/lib/vienna_rna/modules/energy_grid_2d.rb +0 -63
- data/lib/vienna_rna/modules/eval.rb +0 -9
- data/lib/vienna_rna/modules/fftbor.rb +0 -21
- data/lib/vienna_rna/modules/fftbor2d.rb +0 -23
- data/lib/vienna_rna/modules/ffthairpin.rb +0 -4
- data/lib/vienna_rna/modules/fftmultiloop.rb +0 -4
- data/lib/vienna_rna/modules/fold.rb +0 -29
- data/lib/vienna_rna/modules/heat.rb +0 -13
- data/lib/vienna_rna/modules/parser.rb +0 -17
- data/lib/vienna_rna/modules/rna.rb +0 -113
- data/lib/vienna_rna/modules/rna2dfold.rb +0 -25
- data/lib/vienna_rna/modules/rna_extensions.rb +0 -101
- data/lib/vienna_rna/modules/rnabor.rb +0 -33
- data/lib/vienna_rna/modules/subopt.rb +0 -17
- data/lib/vienna_rna/modules/utils.rb +0 -34
- data/lib/vienna_rna/modules/xbor.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fc492c40bf3f4d1c52ecf1afd09810c9798471a
|
4
|
+
data.tar.gz: 2a7ea6a2eeaca132e055e6aacc3cb1f0456990ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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,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
|