bioinform 0.0.1 → 0.1.0

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.
Files changed (61) hide show
  1. data/.gitignore +18 -17
  2. data/Gemfile +4 -4
  3. data/LICENSE +21 -21
  4. data/README.md +29 -29
  5. data/Rakefile +5 -12
  6. data/bioinform.gemspec +21 -21
  7. data/lib/bioinform/data_models/collection.rb +2 -0
  8. data/lib/bioinform/data_models/{iupac.rb → old_style_models_TO_BE_REMOVED/iupac.rb} +1 -1
  9. data/lib/bioinform/data_models/{iupac_word.rb → old_style_models_TO_BE_REMOVED/iupac_word.rb} +0 -0
  10. data/lib/bioinform/data_models/{positional_count_matrix.rb → old_style_models_TO_BE_REMOVED/positional_count_matrix.rb} +0 -0
  11. data/lib/bioinform/data_models/{positional_matrix.rb → old_style_models_TO_BE_REMOVED/positional_matrix.rb} +3 -5
  12. data/lib/bioinform/data_models/{positional_probability_matrix.rb → old_style_models_TO_BE_REMOVED/positional_probability_matrix.rb} +0 -0
  13. data/lib/bioinform/data_models/{positional_weight_matrix.rb → old_style_models_TO_BE_REMOVED/positional_weight_matrix.rb} +0 -0
  14. data/lib/bioinform/data_models/parser.rb +41 -0
  15. data/lib/bioinform/data_models/parsers/array_parser.rb +17 -0
  16. data/lib/bioinform/data_models/parsers/hash_parser.rb +19 -0
  17. data/lib/bioinform/data_models/parsers/string_fantom_parser.rb +21 -0
  18. data/lib/bioinform/data_models/parsers/string_parser.rb +45 -0
  19. data/lib/bioinform/data_models/parsers.rb +4 -0
  20. data/lib/bioinform/data_models/pcm.rb +7 -0
  21. data/lib/bioinform/data_models/pm.rb +195 -0
  22. data/lib/bioinform/data_models/ppm.rb +8 -0
  23. data/lib/bioinform/data_models/pwm.rb +23 -0
  24. data/lib/bioinform/data_models.rb +5 -5
  25. data/lib/bioinform/support/callable_symbol.rb +33 -4
  26. data/lib/bioinform/support/collect_hash.rb +7 -0
  27. data/lib/bioinform/support/curry_except_self.rb +2 -2
  28. data/lib/bioinform/support/deep_dup.rb +5 -0
  29. data/lib/bioinform/support/delete_many.rb +14 -0
  30. data/lib/bioinform/support/has_keys.rb +14 -0
  31. data/lib/bioinform/support/inverf.rb +13 -0
  32. data/lib/bioinform/support/partial_sums.rb +6 -0
  33. data/lib/bioinform/support/{same.rb → same_by.rb} +1 -1
  34. data/lib/bioinform/support.rb +13 -5
  35. data/lib/bioinform/version.rb +3 -3
  36. data/lib/bioinform.rb +8 -7
  37. data/spec/data_models/parser_spec.rb +46 -0
  38. data/spec/data_models/parsers/array_parser_spec.rb +53 -0
  39. data/spec/data_models/parsers/hash_parser_spec.rb +60 -0
  40. data/spec/data_models/parsers/string_fantom_parser_spec.rb +38 -0
  41. data/spec/data_models/parsers/string_parser_spec.rb +112 -0
  42. data/spec/data_models/pm_spec.rb +369 -0
  43. data/spec/data_models/pwm_spec.rb +25 -0
  44. data/spec/spec_helper.rb +30 -0
  45. data/spec/support/callable_symbol_spec.rb +66 -0
  46. data/spec/support/collect_hash_spec.rb +15 -0
  47. data/spec/support/curry_except_self_spec.rb +9 -0
  48. data/spec/support/delete_many_spec.rb +44 -0
  49. data/spec/support/has_keys_spec.rb +48 -0
  50. data/spec/support/inverf_spec.rb +19 -0
  51. data/spec/support/multiline_squish_spec.rb +11 -0
  52. data/spec/support/partial_sums_spec.rb +9 -0
  53. data/spec/support/same_by_spec.rb +36 -0
  54. metadata +60 -21
  55. data/lib/bioinform/support/pmap.rb +0 -10
  56. data/lib/bioinform/support/ptap.rb +0 -7
  57. data/spec/callable_symbol_spec.rb +0 -37
  58. data/spec/pmap_test.rb +0 -24
  59. data/spec/positional_matrix_spec.rb +0 -169
  60. data/spec/ptap_spec.rb +0 -17
  61. data/spec/same_spec.rb +0 -19
@@ -0,0 +1,369 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/data_models/pm'
3
+
4
+ module Bioinform
5
+ describe PM do
6
+ include PM::Parser::Helpers
7
+
8
+ describe '#valid?' do
9
+ it 'should be true iff an argument is an array of arrays of 4 numerics in a column' do
10
+ PM.new.instance_eval{@matrix = [[1,2,3,4],[1,4,5,6.5]]; self }.valid?.should be_true
11
+ PM.new.instance_eval{@matrix = {A: [1,1], C: [2,4], G: [3,5], T: [4, 6.5]}; self }.valid?.should be_false
12
+ PM.new.instance_eval{@matrix = [{A:1,C:2,G:3,T:4},{A:1,C:4,G:5,T: 6.5}]; self }.valid?.should be_false
13
+ PM.new.instance_eval{@matrix = [[1,2,3,4],[1,4,6.5]]; self }.valid?.should be_false
14
+ PM.new.instance_eval{@matrix = [[1,2,3],[1,4,6.5]]; self }.valid?.should be_false
15
+ PM.new.instance_eval{@matrix = [[1,2,'3','4'],[1,'4','5',6.5]]; self }.valid?.should be_false
16
+ end
17
+ end
18
+
19
+ describe '#initialize' do
20
+ context 'when parser specified' do
21
+ before :each do
22
+ parser_stub :ParserBad, false, { matrix: [[0,0,0,0],[1,1,1,1]], name: 'Bad' }
23
+ parser_stub :ParserGood, true, { matrix: [[1,1,1,1],[1,1,1,1]], name: 'Good' }
24
+ parser_stub :ParserWithIncompleteOutput, true, { name: 'Without `matrix` key' }
25
+ parser_stub :ParserGoodWithoutName, true, { matrix: [[1,1,1,1],[1,1,1,1]] }
26
+ parser_stub :ParserWithInvalidMatrix, true, { matrix: [[1,1,1],[1,1,1]] }
27
+ end
28
+ after :each do
29
+ parser_subclasses_cleanup
30
+ end
31
+
32
+ it 'should raise an ArgumentError if parser cannot parse input' do
33
+ expect{ PM.new('my stub input', ParserBad) }.to raise_error ArgumentError
34
+ end
35
+ it 'should raise an ArgumentError if parser output doesn\'t have `matrix` key' do
36
+ expect{ PM.new('my stub input', ParserWithIncompleteOutput) }.to raise_error ArgumentError
37
+ end
38
+ it 'should raise an ArgumentError if parser output has invalid matrix' do
39
+ expect{ PM.new('my stub input', ParserWithInvalidMatrix) }.to raise_error ArgumentError
40
+ end
41
+
42
+ context 'when parse was successful' do
43
+ it 'should load matrix from parser\'s resulting hash' do
44
+ pm = PM.new('my stub input', ParserGoodWithoutName)
45
+ pm.matrix.should == [[1,1,1,1],[1,1,1,1]]
46
+ pm.name.should be_nil
47
+ end
48
+ it 'should set other available attributes from parse resulting hash' do
49
+ pm = PM.new('my stub input', ParserGood)
50
+ pm.matrix.should == [[1,1,1,1],[1,1,1,1]]
51
+ pm.name.should == 'Good'
52
+ end
53
+ end
54
+ end
55
+
56
+ context 'when parser not specified' do
57
+ after :each do
58
+ parser_subclasses_cleanup
59
+ end
60
+ it 'should raise an ArgumentError if no one parser can parse input' do
61
+ parser_stub :ParserBad, false, { matrix: [[0,0,0,0],[1,1,1,1]], name: 'Bad' }
62
+ expect{ PM.new('my stub input') }.to raise_error ArgumentError
63
+ end
64
+ it 'should use first parsed which can parse input' do
65
+ parser_stub :ParserBad, false, { matrix: [[0,0,0,0],[1,1,1,1]], name: 'Bad' }
66
+ parser_stub :ParserGoodFirst, true, { matrix: [[1,1,1,1],[1,1,1,1]], name: 'GoodFirst' }
67
+ parser_stub :ParserGoodSecond, true, { matrix: [[1,1,1,1],[1,1,1,1]], name: 'GoodSecond' }
68
+
69
+ pm = PM.new('my stub input')
70
+ pm.name.should == 'GoodFirst'
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#matrix=' do
76
+ it 'should replace matrix if argument is a valid matrix' do
77
+ @pm = PM.new()
78
+ @pm.matrix.should be_nil
79
+
80
+ @pm.matrix = [[1,2,3,4],[1,4,5,6.5]]
81
+ @pm.matrix.should == [[1,2,3,4],[1,4,5,6.5]]
82
+
83
+ @pm.matrix = [[1,4,5,6.5], [2,2,2,2]]
84
+ @pm.matrix.should == [[1,4,5,6.5],[2,2,2,2]]
85
+ end
86
+ it 'should raise an exception if argument isn\'t valid matrix' do
87
+ @pm = PM.new
88
+ expect{ @pm.matrix = [[1,2,3,4],[1,4,5]] }.to raise_error
89
+ end
90
+ end
91
+
92
+ describe '#to_s' do
93
+ before :each do
94
+ @pm = PM.new
95
+ @pm.matrix = [[1,2,3,4],[1,4,5,6.5]]
96
+ end
97
+ it 'should return string with single-tabulated multiline matrix' do
98
+ @pm.to_s.should == "1\t2\t3\t4\n1\t4\t5\t6.5"
99
+ end
100
+ it 'should return positions in rows, letters in cols' do
101
+ @pm.to_s.split("\n").size.should == 2
102
+ @pm.to_s.split("\n").map{|pos| pos.split.size}.all?{|sz| sz==4}.should be_true
103
+ end
104
+ context 'with name specified' do
105
+ before :each do
106
+ @pm.name = 'Stub name'
107
+ end
108
+ it 'should return a string with a name and a matrix from the next line' do
109
+ @pm.to_s.should == "Stub name\n1\t2\t3\t4\n1\t4\t5\t6.5"
110
+ end
111
+ it 'should not return a name if argument is set to false' do
112
+ @pm.to_s(false).should == "1\t2\t3\t4\n1\t4\t5\t6.5"
113
+ end
114
+ end
115
+ end
116
+
117
+ describe '#pretty_string' do
118
+ it 'should return a string formatted with spaces'
119
+ it 'should contain first string of ACGT letters'
120
+ context 'with name specified' do
121
+ it 'should contain name if parameter isn\'t false'
122
+ end
123
+ context 'without name specified' do
124
+ it 'should not contain name'
125
+ end
126
+ end
127
+
128
+ describe '#size' do
129
+ it 'should return number of positions' do
130
+ @pm = PM.new
131
+ @pm.matrix = [[1,2,3,4],[1,4,5,6.5]]
132
+ @pm.size.should == 2
133
+ end
134
+ end
135
+
136
+ describe '#to_hash' do
137
+ before :each do
138
+ @pm = PM.new
139
+ @pm.matrix = [[1,2,3,4],[1,4,5,6.5]]
140
+ @hsh = @pm.to_hash
141
+ end
142
+ it 'should return a hash with keys A, C, G, T' do
143
+ @hsh.should be_kind_of Hash
144
+ @hsh.keys.sort.should == %w{A C G T}
145
+ end
146
+ it 'should contain matrix elements of corresponding letter' do
147
+ @hsh['A'].should == [1, 1]
148
+ @hsh['C'].should == [2, 4]
149
+ @hsh['G'].should == [3, 5]
150
+ @hsh['T'].should == [4, 6.5]
151
+ end
152
+ it 'should be accessible both by name and symbol (e.g. pm.to_hash[:A] or pm.to_hash[\'A\'] is the same)' do
153
+ @hsh['A'].should == @hsh[:A]
154
+ @hsh['C'].should == @hsh[:C]
155
+ @hsh['G'].should == @hsh[:G]
156
+ @hsh['T'].should == @hsh[:T]
157
+ end
158
+ end
159
+
160
+ describe '#background' do
161
+ before :each do
162
+ @pm = PM.new
163
+ @pm.matrix = [[1,2,3,4],[1,4,5,6.5]]
164
+ end
165
+ context 'when none arguments passed' do
166
+ context 'when pm just created' do
167
+ it 'should be [1,1,1,1]' do
168
+ @pm.background.should == [1,1,1,1]
169
+ end
170
+ end
171
+ it 'should return background' do
172
+ @pm.instance_eval { @background = [0.2, 0.3, 0.3, 0.2] }
173
+ @pm.background.should == [0.2, 0.3, 0.3, 0.2]
174
+ end
175
+ end
176
+ context 'when one argument passed' do
177
+ it 'should set background' do
178
+ @pm.background([0.2,0.3,0.3,0.2])
179
+ @pm.background.should == [0.2, 0.3, 0.3, 0.2]
180
+ end
181
+ end
182
+ context 'when more than one argument passed' do
183
+ it 'should raise an ArgumentError' do
184
+ expect { @pm.background(:first, :second, :third) }.to raise_error ArgumentError
185
+ end
186
+ end
187
+ end
188
+
189
+ describe '#reverse_complement!' do
190
+ before :each do
191
+ @pm = PM.new
192
+ @pm.matrix = [[1, 2, 3, 4], [1, 4, 5, 6.5]]
193
+ end
194
+ it 'should return pm object itself' do
195
+ @pm.reverse_complement!.should be_equal(@pm)
196
+ end
197
+ it 'should reverse matrix rows and columns' do
198
+ @pm.reverse_complement!
199
+ @pm.matrix.should == [[6.5, 5, 4, 1], [4, 3, 2, 1]]
200
+ end
201
+ end
202
+
203
+ describe '#left_augment!' do
204
+ before :each do
205
+ @pm = PM.new
206
+ @pm.matrix = [[1, 2, 3, 4], [1, 4, 5, 6.5]]
207
+ end
208
+ it 'should return pm object itself' do
209
+ @pm.left_augment!(2).should be_equal(@pm)
210
+ end
211
+ it 'should add number of zero columns from the left' do
212
+ @pm.left_augment!(2)
213
+ @pm.matrix.should == [[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [1, 2, 3, 4], [1, 4, 5, 6.5]]
214
+ end
215
+ end
216
+
217
+ describe '#right_augment!' do
218
+ before :each do
219
+ @pm = PM.new
220
+ @pm.matrix = [[1, 2, 3, 4], [1, 4, 5, 6.5]]
221
+ end
222
+ it 'should return pm object itself' do
223
+ @pm.right_augment!(2).should be_equal(@pm)
224
+ end
225
+ it 'should add number of zero columns from the right' do
226
+ @pm.right_augment!(2)
227
+ @pm.matrix.should == [[1, 2, 3, 4], [1, 4, 5, 6.5], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
228
+ end
229
+ end
230
+
231
+ describe '#shift_to_zero!' do
232
+ before :each do
233
+ @pm = PM.new
234
+ @pm.matrix = [[1, 2, 3, 4], [5, 6.5, 3, 4]]
235
+ end
236
+ it 'should return pm object itself' do
237
+ @pm.shift_to_zero!.should be_equal(@pm)
238
+ end
239
+ it 'should make shift each column' do
240
+ @pm.shift_to_zero!
241
+ @pm.matrix.should == [[0, 1, 2, 3], [2, 3.5, 0, 1]]
242
+ end
243
+ end
244
+
245
+ describe '#discrete!' do
246
+ before :each do
247
+ @pm = PM.new
248
+ @pm.matrix = [[1.3, 2.0, 3.2, 4.9], [6.51, 6.5, 3.25, 4.633]]
249
+ end
250
+ it 'should return pm object itself' do
251
+ @pm.discrete!(10).should be_equal(@pm)
252
+ end
253
+ context 'rate is 1' do
254
+ it 'should discrete each element of matrix' do
255
+ @pm.discrete!(1)
256
+ @pm.matrix.should == [[2, 2, 4, 5], [7, 7, 4, 5]]
257
+ end
258
+ end
259
+ it 'should discrete each element of matrix multiplied by rate' do
260
+ @pm.discrete!(10)
261
+ @pm.matrix.should == [[13, 20, 32, 49], [66, 65, 33, 47]]
262
+ end
263
+ end
264
+
265
+ describe '#background_sum' do
266
+ before :each do
267
+ @pm = PM.new
268
+ @pm.matrix = [[1.3, 2.0, 3.2, 4.9], [5.0, 6.5, 3.2, 4.6]]
269
+ end
270
+ context 'when background is [1,1,1,1]' do
271
+ it 'should be 4' do
272
+ @pm.background_sum.should == 4
273
+ end
274
+ end
275
+ it 'should be sum of background' do
276
+ @pm.background( [0.2, 0.3, 0.3, 0.2] )
277
+ @pm.background_sum.should == 1.0
278
+ end
279
+ end
280
+
281
+ describe '#vocabulary_volume' do
282
+ before :each do
283
+ @pm_2_positions = PM.new
284
+ @pm_2_positions.matrix = [[1.3, 2.0, 3.2, 4.9], [5.0, 6.5, 3.2, 4.6]]
285
+ @pm_3_positions = PM.new
286
+ @pm_3_positions.matrix = [[1.3, 2.0, 3.2, 4.9], [5.0, 6.5, 3.2, 4.6], [1, 2, 3, 4]]
287
+ end
288
+ context 'when background is [1,1,1,1]' do
289
+ it 'should be equal to number of words' do
290
+ @pm_2_positions.vocabulary_volume.should == 4**2
291
+ @pm_3_positions.vocabulary_volume.should == 4**3
292
+ end
293
+ end
294
+ context 'when background is normalized probabilities' do
295
+ it 'should be 1.0' do
296
+ @pm_2_positions.background( [0.2, 0.3, 0.3, 0.2] )
297
+ @pm_2_positions.background_sum.should == 1.0
298
+
299
+ @pm_3_positions.background( [0.2, 0.3, 0.3, 0.2] )
300
+ @pm_3_positions.background_sum.should == 1.0
301
+ end
302
+ end
303
+ end
304
+
305
+ describe '#best_score' do
306
+ it 'should be equal to best score' do
307
+ @pm = PM.new
308
+ @pm.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
309
+ @pm.best_score.should == 4.9 + 7.13 + (-1.0)
310
+ end
311
+ end
312
+ describe '#worst_score' do
313
+ it 'should be equal to worst score' do
314
+ @pm = PM.new
315
+ @pm.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
316
+ @pm.worst_score.should == 1.3 + 3.25 + (-1.5)
317
+ end
318
+ end
319
+
320
+ describe '#best_suffix' do
321
+ it 'should be an array of best suffices from start of string and to empty suffix inclusive' do
322
+ @pm = PM.new
323
+ @pm.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
324
+ @pm.best_suffix.should == [(4.9 + 7.13 - 1.0), (7.13 - 1.0), (-1.0), (0.0) ]
325
+ end
326
+ end
327
+ describe '#worst_suffix' do
328
+ it 'should be an array of worst suffices from start of string and to empty suffix inclusive' do
329
+ @pm = PM.new
330
+ @pm.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
331
+ @pm.worst_suffix.should == [(1.3 + 3.25 - 1.5), (3.25 - 1.5), (- 1.5), (0.0) ]
332
+ end
333
+ end
334
+
335
+ [:shift_to_zero, :reverse_complement].each do |meth|
336
+ describe "nonbang method #{meth}" do
337
+ before :each do
338
+ @pm = PM.new
339
+ @pm.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
340
+ @pm_2 = PM.new
341
+ @pm_2.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
342
+ end
343
+ it 'should return copy of object not object itself' do
344
+ @pm.send(meth).should_not be_equal @pm
345
+ end
346
+ it 'should == to bang-method' do
347
+ @pm.send(meth).to_s.should == @pm_2.send("#{meth}!").to_s
348
+ end
349
+ end
350
+ end
351
+
352
+ [:discrete , :left_augment, :right_augment].each do |meth|
353
+ describe "nonbang method #{meth}" do
354
+ before :each do
355
+ @pm = PM.new
356
+ @pm.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
357
+ @pm_2 = PM.new
358
+ @pm_2.matrix = [[1.3, 2.0, 4.9, 3.2], [7.13, 6.5, 3.25, 4.633], [-1.0, -1.0, -1.5, -1.0]]
359
+ end
360
+ it 'should return copy of object not object itself' do
361
+ @pm.send(meth, 2).should_not be_equal @pm
362
+ end
363
+ it 'should == to bang-method' do
364
+ @pm.send(meth, 2).to_s.should == @pm_2.send("#{meth}!", 2).to_s
365
+ end
366
+ end
367
+ end
368
+ end
369
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/data_models/pwm'
3
+
4
+ module Bioinform
5
+ describe PWM do
6
+ describe '#score_mean' do
7
+ it 'should be equal to a mean score of pwm' do
8
+ pwm = PWM.new
9
+ pwm.matrix = [[1,2,1,2],[4,6,8,6],[2,2,2,2]]
10
+ pwm.score_mean.should == 1.5 + 6 + 2
11
+ end
12
+ it 'should be equal to a mean score of pwm by measure induced from background probability mean' do
13
+ pwm = PWM.new.background([0.2, 0.3, 0.3, 0.2])
14
+ pwm.matrix = [[1,2,1,2],[4,6,8,6],[2,2,2,2]]
15
+ pwm.score_mean.should == ((0.2*1+0.3*2+0.3*1+0.2*2) + (0.2*4+0.3*6+0.3*8+0.2*6) + (0.2*2+0.3*2+0.3*2+0.2*2)) / (0.2+0.3+0.3+0.2)
16
+ end
17
+ end
18
+
19
+ describe '#score_variance' do
20
+ end
21
+
22
+ describe '#gauss_estimation' do
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ $LOAD_PATH.unshift File.dirname(__FILE__)
3
+
4
+ require 'rspec'
5
+ module Bioinform
6
+ class PM
7
+ class Parser
8
+ module Helpers
9
+ def parser_stub(class_name, can_parse, result)
10
+ klass = Class.new(PM::Parser) do
11
+ define_method :can_parse? do can_parse end
12
+ define_method :parse do result end
13
+ end
14
+ #class_levels = class_name.to_s.split('::')
15
+ #class_levels[0..-2].inject(Object){|klass, level| klass.const_get level}.const_set(class_name, class_levels.last)
16
+ Bioinform.const_set(class_name.to_s.split('::').last, klass)
17
+ end
18
+ def parser_subclasses_cleanup
19
+ PM::Parser.subclasses.each do |klass|
20
+ #class_levels = klass.to_s.split('::')
21
+ #class_levels[0..-2].inject(Object){|klass, level| klass.const_get level}.const_set(class_name, class_levels.last)
22
+
23
+ Bioinform.send :remove_const, klass.name.split('::').last
24
+ end
25
+ PM::Parser.subclasses.clear
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/support/callable_symbol'
3
+
4
+ # TODO: organize and write more correct descriptions
5
+ describe Symbol do
6
+ describe '#call' do
7
+ context 'when symbol curries a block' do
8
+ it 'should pass a block to a corresponding proc' do
9
+ :map.(&:to_s).to_proc.call([1,2,3]).should == ['1','2','3']
10
+ [[1,2,3],[4,5,6]].map(&:map.(&:to_s)).should == [['1','2','3'],['4','5','6']]
11
+ [[1,2,3],[4,5,6]].map(&:map.(&:to_s.(2))).should == [['1','10','11'],['100','101','110']]
12
+ ['abc','cdef','xy','z','wwww'].select(&:size.() == 4).should == ['cdef', 'wwww']
13
+
14
+ [%w{1 2 3 4 5},%w{6 7 8 9 10}].map(&:join.().length).should == [5,6] # method chaining
15
+ ['abc','aaA','AaA','z'].count(&:upcase.().succ == 'AAB').should == 2 # method chaining with ==
16
+ [[1,2,3]].map( &:map.(&:to_s.(2)).map(&:to_i) ).should == [[1,10,11]] # method chaining with block on initial symbol and on later symbols
17
+ end
18
+ end
19
+
20
+ context 'returned object' do
21
+
22
+ it 'should have to_proc method' do
23
+ expect { :to_s.() }.to respond_to :to_proc
24
+ expect { :to_s.(2) }.to respond_to :to_proc
25
+ expect { :to_s.(2) == '110' }.to respond_to :to_proc
26
+ expect { :to_s.(2).postprocess('arg1','arg2') }.to respond_to :to_proc
27
+ end
28
+
29
+ context 'corresponding proc' do
30
+ it 'should call method, corresponding to symbol, on first argument' do
31
+ stub_obj = double('obj')
32
+ stub_obj.should_receive(:to_s).exactly(:twice)
33
+ prc_1 = :to_s.(2).to_proc
34
+ prc_2 = :to_s.(2).to_proc # When used with &, to_proc can be omitted: it's implicitly casted on call (see other examples)
35
+ prc_1.call(stub_obj) # These forms are almost equivalent, but second is much more concise
36
+ stub_obj.tap(&prc_2)
37
+ end
38
+ context 'when multiple arguments of call specified' do
39
+ it 'should call using given arguments' do
40
+ stub_obj = double('obj')
41
+ stub_obj.should_receive(:gsub).with('before','after')
42
+ prc = :gsub.('before','after')
43
+ stub_obj.tap(&prc)
44
+ end
45
+ end
46
+ context 'when the only argument of call specified' do
47
+ it 'should call using given argument' do
48
+ stub_obj = double('obj')
49
+ stub_obj.should_receive(:to_s).with(2)
50
+ prc = :to_s.(2)
51
+ stub_obj.tap(&prc)
52
+ end
53
+ end
54
+ context 'when no arguments given' do
55
+ it 'should call without any arguments' do
56
+ stub_obj = double('obj')
57
+ stub_obj.should_receive(:to_s).with()
58
+ prc = :to_s.()
59
+ stub_obj.tap(&prc)
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/support/collect_hash'
3
+
4
+ describe Enumerable do
5
+ # %w{A C G T}.collect_hash{|k| [k*2, k*3] }
6
+ # # ==> {"AA" => "AAA", "CC" => "CCC", "GG" => "GGG", "TT" => "TTT"}
7
+ context '#collect_hash' do
8
+ it 'should take a block and create a hash from collected [k,v] pairs' do
9
+ %w{A C G T}.collect_hash{|k| [k*2, k*3] }.should == {"AA" => "AAA", "CC" => "CCC", "GG" => "GGG", "TT" => "TTT"}
10
+ end
11
+ it 'should create a hash from yielded [k,v] pairs if block not given' do
12
+ %w{A C G T}.each_with_index.collect_hash.should == {"A" => 0, "C" => 1, "G" => 2, "T" => 3}
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/support/curry_except_self'
3
+
4
+ describe Proc do
5
+ describe '#curry_except_self' do
6
+ it 'should return proc'
7
+ it 'should behave like a proc where all arguments except first are curried'
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/support/delete_many'
3
+
4
+ describe Array do
5
+ before :each do
6
+ @arr = %w{a b c d e f g h i j b b}
7
+ end
8
+ describe '#delete_at_many' do
9
+ it 'should delete elements at specified indices when indices in ascending order' do
10
+ @arr.delete_at_many(1,3,7)
11
+ @arr.should == %w{a c e f g i j b b}
12
+ end
13
+ it 'should delete elements at specified indices when indices in descending order' do
14
+ @arr.delete_at_many(7,3,1)
15
+ @arr.should == %w{a c e f g i j b b}
16
+ end
17
+ it 'should delete elements at specified indices when indices in arbitrary order' do
18
+ @arr.delete_at_many(3,1,7)
19
+ @arr.should == %w{a c e f g i j b b}
20
+ end
21
+ it 'should delete at each index once' do
22
+ @arr.delete_at_many(0,0,0,2,0)
23
+ @arr.should == %w{b d e f g h i j b b}
24
+ end
25
+ end
26
+ describe '#delete_many' do
27
+ it 'should delete multiple elements with specified values' do
28
+ @arr.delete_many('b', 'd', 'h', 'b')
29
+ @arr.should == %w{a c e f g i j}
30
+ end
31
+ end
32
+ end
33
+
34
+ describe Hash do
35
+ before :each do
36
+ @arr = {A: 3, T: 6, G: 4, C: 5}
37
+ end
38
+ describe '#delete_many' do
39
+ it 'should delete specified keys' do
40
+ @arr.delete_many(:T, :C, :F, :T, :T)
41
+ @arr.should == {A: 3, G: 4}
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/support/has_keys'
3
+
4
+ describe Hash do
5
+ describe '#has_all_keys?' do
6
+ it 'should be true if all given keys are at place' do
7
+ {a: 3, b: 6, c: 7, d: 13}.has_all_keys?(:a, :c).should be_true
8
+ end
9
+
10
+ it 'should be false if any given of keys is missing' do
11
+ {a: 3, b: 6, c: 7, d: 13}.has_all_keys?(:a, :x).should be_false
12
+ end
13
+ end
14
+
15
+ describe '#has_any_key?' do
16
+ it 'should be true if any of given keys is at place' do
17
+ {a: 3, b: 6, c: 7, d: 13}.has_any_key?(:a, :x).should be_true
18
+ end
19
+
20
+ it 'should be false if no one of given is missing' do
21
+ {a: 3, b: 6, c: 7, d: 13}.has_any_key?(:x, :y).should be_false
22
+ end
23
+ end
24
+
25
+ describe '#has_none_key?' do
26
+ it 'should be true if all given keys are missing' do
27
+ {a: 3, b: 6, c: 7, d: 13}.has_none_key?(:x, :y).should be_true
28
+ end
29
+
30
+ it 'should be false if any of given keys is at place' do
31
+ {a: 3, b: 6, c: 7, d: 13}.has_none_key?(:a, :y).should be_false
32
+ end
33
+ end
34
+
35
+ describe '#has_one_key?' do
36
+ it 'should be true if one of given keys is present' do
37
+ {a: 3, b: 6, c: 7, d: 13}.has_one_key?(:x, :a).should be_true
38
+ end
39
+
40
+ it 'should be false if many of given keys are present' do
41
+ {a: 3, b: 6, c: 7, d: 13}.has_one_key?(:a, :c).should be_false
42
+ end
43
+
44
+ it 'should be false if none of given keys is at place' do
45
+ {a: 3, b: 6, c: 7, d: 13}.has_one_key?(:x, :y).should be_false
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/support/inverf'
3
+
4
+ describe 'Math#inverf' do
5
+ it 'should be erf(inverf(x)) == x' do
6
+ rng = (-0.9..0.9).step(0.1)
7
+ arr = rng.to_a
8
+ arr2 = rng.map{|x| Math.inverf(x)}.map{|x| Math.erf(x)}
9
+ delta = arr.each_index.map{|i| (arr[i] - arr2[i]).abs }
10
+ delta.each{|el| el.should <= 0.001}
11
+ end
12
+ it 'should be erf(inverf(x)) == x' do
13
+ rng = (-5..5).step(1)
14
+ arr = rng.to_a
15
+ arr2 = rng.map{|x| Math.erf(x)}.map{|x| Math.inverf(x)}
16
+ delta = arr.each_index.map{|i| (arr[i] - arr2[i]).abs }
17
+ delta.each{|el| el.should <= 0.01}
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+ require 'bioinform/support/multiline_squish'
3
+
4
+ describe String do
5
+ describe '#multiline_squish' do
6
+ it 'should replace multiple spaces with one space'
7
+ it 'should replace tabs with a space'
8
+ it 'should replace \r\n with \n'
9
+ it 'should preserve rows pagination'
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ describe 'Array#partial_sums' do
2
+ it 'should return an array of the same size with partial sums of elements 0..ind inclusive with float elements' do
3
+ [2,3,4,5].partial_sums.should == [2, 5, 9, 14]
4
+ [2,3,4,5].partial_sums.last.should be_kind_of(Float)
5
+ end
6
+ it 'should start counting from argument when it\'s given' do
7
+ [2,3,4,5].partial_sums(100).should == [102,105,109,114]
8
+ end
9
+ end