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.
@@ -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