bioinform 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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