wrnap 0.12.2 → 1.0.1
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 +4 -4
- data/lib/wrnap.rb +34 -35
- data/lib/wrnap/etl/infernal.rb +9 -8
- data/lib/wrnap/etl/stockholm.rb +6 -6
- data/lib/wrnap/global/yaml.rb +14 -0
- data/lib/wrnap/graphing/r.rb +8 -4
- data/lib/wrnap/package/base.rb +4 -7
- data/lib/wrnap/package/fold.rb +1 -1
- data/lib/wrnap/package/fold_constrained.rb +24 -0
- data/lib/wrnap/package/mfpt.rb +1 -1
- data/lib/wrnap/package/rnabor.rb +2 -2
- data/lib/wrnap/package/varna.rb +4 -3
- data/lib/wrnap/package/xbor.rb +2 -2
- data/lib/wrnap/rna.rb +197 -0
- data/lib/wrnap/rna/box.rb +43 -0
- data/lib/wrnap/rna/constraints.rb +119 -0
- data/lib/wrnap/rna/context.rb +139 -0
- data/lib/wrnap/rna/extensions.rb +102 -0
- data/lib/wrnap/rna/metadata.rb +46 -0
- data/lib/wrnap/rna/motifs.rb +72 -0
- data/lib/wrnap/rna/tree.rb +136 -0
- data/lib/wrnap/rna/wrapper.rb +9 -0
- data/lib/wrnap/version.rb +1 -1
- metadata +14 -9
- data/lib/wrnap/global/rna.rb +0 -190
- data/lib/wrnap/global/rna/context.rb +0 -141
- data/lib/wrnap/global/rna/extensions.rb +0 -104
- data/lib/wrnap/global/rna/helix.rb +0 -36
- data/lib/wrnap/global/rna/metadata.rb +0 -48
- data/lib/wrnap/global/rna/tree.rb +0 -87
@@ -0,0 +1,72 @@
|
|
1
|
+
module Wrnap
|
2
|
+
class Rna
|
3
|
+
module Motifs
|
4
|
+
def helices
|
5
|
+
array = base_pairs.sort_by(&:first).map(&:to_a)
|
6
|
+
|
7
|
+
unless array.empty?
|
8
|
+
array[1..-1].inject([[array.first]]) do |bins, (i, j)|
|
9
|
+
bins.tap { bins[-1][-1] == [i - 1, j + 1] ? bins[-1] << [i, j] : bins << [[i, j]] }
|
10
|
+
end
|
11
|
+
else
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def collapsed_helices(lonely_bp: false)
|
17
|
+
helices.map { |((i, j), *rest)| Helix.new(i, j, rest.length + 1) }.select { |helix| lonely_bp ? helix : helix.length > 1 }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Helix
|
22
|
+
attr_reader :i, :j, :length
|
23
|
+
|
24
|
+
def initialize(i, j, length)
|
25
|
+
@i, @j, @length = i, j, length
|
26
|
+
end
|
27
|
+
|
28
|
+
def k; i + length - 1; end
|
29
|
+
def l; j - length + 1; end
|
30
|
+
|
31
|
+
def to_loops
|
32
|
+
[Loop.new(i, k), Loop.new(l, j)]
|
33
|
+
end
|
34
|
+
|
35
|
+
def reindex!(rna)
|
36
|
+
tap do
|
37
|
+
if i < 0 && j < 0
|
38
|
+
@i = rna.len + i
|
39
|
+
@j = rna.len + j
|
40
|
+
else
|
41
|
+
@i = i - rna.len
|
42
|
+
@j = j - rna.len
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def name
|
48
|
+
"(%d..%d, %d..%d)" % [i, k, l, j]
|
49
|
+
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
"#<Helix: %s>" % name
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Loop
|
57
|
+
attr_reader :i, :j
|
58
|
+
|
59
|
+
def initialize(i, j)
|
60
|
+
@i, @j = i, j
|
61
|
+
end
|
62
|
+
|
63
|
+
def name
|
64
|
+
"(%d, %d)" % [i, j]
|
65
|
+
end
|
66
|
+
|
67
|
+
def inspect
|
68
|
+
"#<Loop: %s>" % name
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module Wrnap
|
2
|
+
class Rna
|
3
|
+
module TreeFunctions
|
4
|
+
def with_tree
|
5
|
+
meta_rna { |metadata| tree(TreePlanter.new(metadata.__rna__)) }
|
6
|
+
end
|
7
|
+
|
8
|
+
def trunk
|
9
|
+
md[:tree] || with_tree.trunk
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TreeStem < Tree::TreeNode
|
14
|
+
extend Forwardable
|
15
|
+
include Enumerable
|
16
|
+
|
17
|
+
STEM_NOTATION_REGEX = /^p((\d+_)*(\d+))(_?([ijkl]))?$/
|
18
|
+
|
19
|
+
def_delegators :@content, :i, :j
|
20
|
+
def_delegator :@content, :length, :stem_length
|
21
|
+
|
22
|
+
def method_missing(name, *args, &block)
|
23
|
+
if name.to_s =~ STEM_NOTATION_REGEX
|
24
|
+
if $2 && child = children[$2.to_i - 1]
|
25
|
+
child.send("p%s" % name.to_s.gsub(/^p\d+_/, ""))
|
26
|
+
elsif child = children[$1.to_i - 1]
|
27
|
+
$5 ? child.content.send($5) : child.content
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
else super end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class TreePlanter
|
36
|
+
attr_reader :rna, :root
|
37
|
+
|
38
|
+
def initialize(rna, tree = false)
|
39
|
+
@rna = rna
|
40
|
+
@root = tree || build_tree(rna.collapsed_helices)
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_tree(helices)
|
44
|
+
helices.inject(TreeStem.new(:root, rna)) do |tree, helix|
|
45
|
+
add_node(tree, TreeStem.new(helix.name, helix))
|
46
|
+
end.root
|
47
|
+
end
|
48
|
+
|
49
|
+
def extend_tree(*helices)
|
50
|
+
self.class.new(rna, rebuild_tree(helices))
|
51
|
+
end
|
52
|
+
|
53
|
+
def extend_tree!(*helices)
|
54
|
+
tap { @root = rebuild_tree(helices) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def rebuild_tree(helices)
|
58
|
+
build_tree((root.map(&:content).select { |helix| helix.is_a?(Helix) } + helices.flatten).sort_by(&:i))
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_node(subtree, node)
|
62
|
+
# This function has an implicit, *very important* expectation that nodes are added in a depth-first, preorder traversal fashion.
|
63
|
+
# What this means is that given a tree containing two sibling nodes (i, j), (k, l), you can't later add another node (m, n) which
|
64
|
+
# makes (i, j), (k, l) into a multiloop. (m, n) *must* be added before any of it's children for the resulting structure to be accurate.
|
65
|
+
|
66
|
+
# Case 1: the tree is empty.
|
67
|
+
if subtree.is_root? && subtree.size == 1
|
68
|
+
subtree << node
|
69
|
+
# Case 2: the node to add is after the current stem.
|
70
|
+
elsif node.i > subtree.j
|
71
|
+
# It's a sibling, pop up until we're at its parent node.
|
72
|
+
subtree = subtree.parent until subtree.is_root? || subtree.j > node.i
|
73
|
+
node.tap { subtree << node }
|
74
|
+
# Case 3: the node to add is within the current stem.
|
75
|
+
elsif node.j < subtree.j
|
76
|
+
# Going deeper.
|
77
|
+
subtree << node
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def coalesce
|
82
|
+
self.class.new(rna, root.dup).tap { |tree| tree.merge_interior_loops! }
|
83
|
+
end
|
84
|
+
|
85
|
+
def coalesce!
|
86
|
+
tap { merge_interior_loops! }
|
87
|
+
end
|
88
|
+
|
89
|
+
def merge_interior_loops!
|
90
|
+
root.tap do
|
91
|
+
self.class.postorder_traversal(root) do |node|
|
92
|
+
if node.children.count == 1 && !node.is_root?
|
93
|
+
child = node.children.first
|
94
|
+
node.parent.add(child)
|
95
|
+
node.remove_from_parent!
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
extend_tree!
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def depth_signature
|
104
|
+
root.map(&:node_depth)
|
105
|
+
end
|
106
|
+
|
107
|
+
def pp
|
108
|
+
root.print_tree and nil
|
109
|
+
end
|
110
|
+
|
111
|
+
def inspect
|
112
|
+
"#<TreePlanter: %s>" % depth_signature.inspect
|
113
|
+
end
|
114
|
+
|
115
|
+
alias :to_s :inspect
|
116
|
+
|
117
|
+
def method_missing(name, *args, &block)
|
118
|
+
if name.to_s =~ TreeStem::STEM_NOTATION_REGEX
|
119
|
+
root.send(name, *args, &block)
|
120
|
+
else super end
|
121
|
+
end
|
122
|
+
|
123
|
+
class << self
|
124
|
+
def preorder_traversal(node, &block)
|
125
|
+
node.children.map { |child| preorder_traversal(child, &block) }
|
126
|
+
yield node
|
127
|
+
end
|
128
|
+
|
129
|
+
def postorder_traversal(node, &block)
|
130
|
+
node.children.map { |child| postorder_traversal(child, &block) }
|
131
|
+
yield node
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/lib/wrnap/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wrnap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Senter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-07-
|
11
|
+
date: 2014-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -168,13 +168,8 @@ files:
|
|
168
168
|
- lib/wrnap/global/chainer.rb
|
169
169
|
- lib/wrnap/global/entrez.rb
|
170
170
|
- lib/wrnap/global/parser.rb
|
171
|
-
- lib/wrnap/global/rna.rb
|
172
|
-
- lib/wrnap/global/rna/context.rb
|
173
|
-
- lib/wrnap/global/rna/extensions.rb
|
174
|
-
- lib/wrnap/global/rna/helix.rb
|
175
|
-
- lib/wrnap/global/rna/metadata.rb
|
176
|
-
- lib/wrnap/global/rna/tree.rb
|
177
171
|
- lib/wrnap/global/runner.rb
|
172
|
+
- lib/wrnap/global/yaml.rb
|
178
173
|
- lib/wrnap/graphing/r.rb
|
179
174
|
- lib/wrnap/package/base.rb
|
180
175
|
- lib/wrnap/package/energy_grid_2d.rb
|
@@ -188,6 +183,7 @@ files:
|
|
188
183
|
- lib/wrnap/package/ffthairpin.rb
|
189
184
|
- lib/wrnap/package/fftmultiloop.rb
|
190
185
|
- lib/wrnap/package/fold.rb
|
186
|
+
- lib/wrnap/package/fold_constrained.rb
|
191
187
|
- lib/wrnap/package/heat.rb
|
192
188
|
- lib/wrnap/package/kinwalker.rb
|
193
189
|
- lib/wrnap/package/mfpt.rb
|
@@ -199,6 +195,15 @@ files:
|
|
199
195
|
- lib/wrnap/package/tabu_path.rb
|
200
196
|
- lib/wrnap/package/varna.rb
|
201
197
|
- lib/wrnap/package/xbor.rb
|
198
|
+
- lib/wrnap/rna.rb
|
199
|
+
- lib/wrnap/rna/box.rb
|
200
|
+
- lib/wrnap/rna/constraints.rb
|
201
|
+
- lib/wrnap/rna/context.rb
|
202
|
+
- lib/wrnap/rna/extensions.rb
|
203
|
+
- lib/wrnap/rna/metadata.rb
|
204
|
+
- lib/wrnap/rna/motifs.rb
|
205
|
+
- lib/wrnap/rna/tree.rb
|
206
|
+
- lib/wrnap/rna/wrapper.rb
|
202
207
|
- lib/wrnap/version.rb
|
203
208
|
- wrnap.gemspec
|
204
209
|
homepage: ''
|
@@ -221,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
221
226
|
version: '0'
|
222
227
|
requirements: []
|
223
228
|
rubyforge_project:
|
224
|
-
rubygems_version: 2.
|
229
|
+
rubygems_version: 2.2.2
|
225
230
|
signing_key:
|
226
231
|
specification_version: 4
|
227
232
|
summary: A comprehensive wrapper (wRNApper) for various RNA CLI programs.
|
data/lib/wrnap/global/rna.rb
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
module Wrnap
|
2
|
-
module Global
|
3
|
-
class Rna
|
4
|
-
extend Forwardable
|
5
|
-
include Extensions
|
6
|
-
include Metadata
|
7
|
-
include TreeFunctions
|
8
|
-
include HelixFunctions
|
9
|
-
|
10
|
-
CANONICAL_BASES = Set.new << Set.new([?G, ?C]) << Set.new([?A, ?U]) << Set.new([?G, ?U])
|
11
|
-
|
12
|
-
attr_accessor :comment
|
13
|
-
attr_reader :sequence, :structure, :second_structure, :metadata
|
14
|
-
|
15
|
-
class << self
|
16
|
-
def init_from_string(sequence, structure = nil, second_structure = nil, comment = nil, &block)
|
17
|
-
new(
|
18
|
-
sequence: sequence,
|
19
|
-
structure: structure,
|
20
|
-
second_structure: second_structure,
|
21
|
-
comment: comment,
|
22
|
-
&block
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
def init_from_hash(hash, &block)
|
27
|
-
new(
|
28
|
-
sequence: hash[:sequence] || hash[:seq],
|
29
|
-
structure: hash[:structure] || hash[:str_1] || hash[:str],
|
30
|
-
second_structure: hash[:second_structure] || hash[:str_2],
|
31
|
-
comment: hash[:comment] || hash[:name],
|
32
|
-
&block
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
def init_from_array(array, &block)
|
37
|
-
init_from_string(*array, &block)
|
38
|
-
end
|
39
|
-
|
40
|
-
def init_from_fasta(string, &block)
|
41
|
-
if File.exist?(string)
|
42
|
-
comment = File.basename(string, string.include?(?.) ? ".%s" % string.split(?.)[-1] : "")
|
43
|
-
string = File.read(string).chomp
|
44
|
-
end
|
45
|
-
|
46
|
-
init_from_string(*string.split(/\n/).reject { |line| line.start_with?(">") }[0, 3], &block).tap do |rna|
|
47
|
-
if (line = string.split(/\n/).first).start_with?(">") && !(file_comment = line.gsub(/^>\s*/, "")).empty?
|
48
|
-
rna.comment = file_comment
|
49
|
-
elsif comment
|
50
|
-
rna.comment = comment
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def init_from_context(*context, coords: {}, rna: {}, &block)
|
56
|
-
Context.init_from_entrez(*context, coords: coords, rna: rna, &block)
|
57
|
-
end
|
58
|
-
|
59
|
-
def init_from_self(rna, &block)
|
60
|
-
# This happens when you call a Wrnap library function with the output of something like Wrnap::Fold.run(...).mfe
|
61
|
-
new(
|
62
|
-
sequence: rna.sequence,
|
63
|
-
strucutre: rna.structure,
|
64
|
-
second_strucutre: rna.second_structure,
|
65
|
-
comment: rna.comment,
|
66
|
-
&block
|
67
|
-
)
|
68
|
-
end
|
69
|
-
|
70
|
-
alias_method :placeholder, :new
|
71
|
-
end
|
72
|
-
|
73
|
-
def initialize(sequence: "", structure: "", second_structure: "", comment: "", &block)
|
74
|
-
@sequence, @comment, @metadata = (sequence.kind_of?(Rna) ? sequence.seq : sequence).upcase, comment, Metadata::Container.new(self)
|
75
|
-
|
76
|
-
[:structure, :second_structure].each do |structure_symbol|
|
77
|
-
instance_variable_set(
|
78
|
-
:"@#{structure_symbol}",
|
79
|
-
case structure_value = eval("#{structure_symbol}")
|
80
|
-
when :empty then empty_structure
|
81
|
-
when :mfe then RNA(sequence).run(:fold).mfe_rna.structure
|
82
|
-
when String then structure_value
|
83
|
-
when Hash then
|
84
|
-
if structure_value.keys.count > 1
|
85
|
-
Wrnap.debugger { "The following options hash has more than one key. This will probably produce unpredictable results: %s" % structure_value.inspect }
|
86
|
-
end
|
87
|
-
|
88
|
-
RNA(sequence).run(*structure_value.keys, *structure_value.values).mfe_rna.structure
|
89
|
-
end
|
90
|
-
)
|
91
|
-
end
|
92
|
-
|
93
|
-
metadata.instance_eval(&block) if block_given?
|
94
|
-
|
95
|
-
if str && seq.length != str.length
|
96
|
-
Wrnap.debugger { "The sequence length (%d) doesn't match the structure length (%d)" % [seq, str].map(&:length) }
|
97
|
-
end
|
98
|
-
|
99
|
-
if str_2 && str_1.length != str_2.length
|
100
|
-
Wrnap.debugger { "The first structure length (%d) doesn't match the second structure length (%d)" % [str_1, str_2].map(&:length) }
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
alias :seq :sequence
|
105
|
-
alias :str :structure
|
106
|
-
alias :str_1 :structure
|
107
|
-
alias :str_2 :second_structure
|
108
|
-
alias :name :comment
|
109
|
-
|
110
|
-
def copy_name_from(rna)
|
111
|
-
tap { @comment = rna.name }
|
112
|
-
end
|
113
|
-
|
114
|
-
def empty_structure
|
115
|
-
"." * seq.length
|
116
|
-
end
|
117
|
-
|
118
|
-
alias :empty_str :empty_structure
|
119
|
-
|
120
|
-
def no_structure
|
121
|
-
self.class.init_from_string(seq, nil, nil, name)
|
122
|
-
end
|
123
|
-
|
124
|
-
alias :no_str :no_structure
|
125
|
-
|
126
|
-
def one_structure(structure_1)
|
127
|
-
self.class.init_from_string(seq, structure_1.is_a?(Symbol) ? send(structure_1) : structure_1, nil, name)
|
128
|
-
end
|
129
|
-
|
130
|
-
alias :one_str :one_structure
|
131
|
-
|
132
|
-
def two_structures(structure_1, structure_2)
|
133
|
-
self.class.init_from_string(
|
134
|
-
seq,
|
135
|
-
*[structure_1, structure_2].map { |argument| argument.is_a?(Symbol) ? send(argument) : argument },
|
136
|
-
name
|
137
|
-
)
|
138
|
-
end
|
139
|
-
|
140
|
-
alias :two_str :two_structures
|
141
|
-
|
142
|
-
def write_fa!(filename)
|
143
|
-
filename.tap do |filename|
|
144
|
-
File.open(filename, ?w) do |file|
|
145
|
-
file.write("> %s\n" % name) if name
|
146
|
-
file.write("%s\n" % seq) if seq
|
147
|
-
file.write("%s\n" % str_1) if str_1
|
148
|
-
file.write("%s\n" % str_2) if str_2
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def temp_fa_file!
|
154
|
-
write_fa!(Tempfile.new("rna")).path
|
155
|
-
end
|
156
|
-
|
157
|
-
def run(package_name, options = {})
|
158
|
-
Wrnap::Package.lookup(package_name).run(self, options)
|
159
|
-
end
|
160
|
-
|
161
|
-
def ==(other_rna)
|
162
|
-
other_rna.kind_of?(Wrnap::Global::Rna) ? [seq, str_1, str_2] == [other_rna.seq, other_rna.str_1, other_rna.str_2] : super
|
163
|
-
end
|
164
|
-
|
165
|
-
def method_missing(name, *args, &block)
|
166
|
-
if (name_str = "#{name}") =~ /^run_\w+$/
|
167
|
-
run(name_str.gsub(/^run_/, ""), *args)
|
168
|
-
else super end
|
169
|
-
end
|
170
|
-
|
171
|
-
def pp
|
172
|
-
puts("> %s" % name) if name
|
173
|
-
puts("%s" % seq) if seq
|
174
|
-
puts("%s" % str_1) if str_1
|
175
|
-
puts("%s" % str_2) if str_2
|
176
|
-
puts("%s" % meta.inspect) if meta
|
177
|
-
end
|
178
|
-
|
179
|
-
def inspect
|
180
|
-
"#<RNA: %s>" % [
|
181
|
-
("#{seq[0, 20] + (seq.length > 20 ? '... [%d]' % seq.length : '')}" if seq && !seq.empty?),
|
182
|
-
("#{str_1[0, 20] + (str_1.length > 20 ? ' [%d]' % seq.length : '')}" if str_1 && !str_1.empty?),
|
183
|
-
("#{str_2[0, 20] + (str_2.length > 20 ? ' [%d]' % seq.length : '')}" if str_2 && !str_1.empty?),
|
184
|
-
(md.inspect unless md.nil? || md.empty?),
|
185
|
-
(name ? name : "#{self.class.name}")
|
186
|
-
].compact.join(", ")
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|