wrnap 0.12.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,9 @@
1
+ module Wrnap
2
+ class Rna
3
+ module Wrnapper
4
+ def wrnap
5
+ Wrnap::Rna::Box.new(self)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Wrnap
2
- VERSION = "0.12.2"
2
+ VERSION = "1.0.1"
3
3
  end
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.12.2
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-18 00:00:00.000000000 Z
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.3.0
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.
@@ -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