macroape 4.0.2 → 4.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -17
  3. data/Gemfile +4 -4
  4. data/LICENSE +22 -22
  5. data/README.md +70 -70
  6. data/Rakefile.rb +49 -49
  7. data/TODO.txt +46 -46
  8. data/benchmark/benchmark_helper.rb +4 -4
  9. data/benchmark/similarity_benchmark.rb +52 -52
  10. data/bin/align_motifs +4 -4
  11. data/bin/eval_alignment +4 -4
  12. data/bin/eval_similarity +4 -4
  13. data/bin/find_pvalue +4 -4
  14. data/bin/find_threshold +4 -4
  15. data/bin/preprocess_collection +4 -4
  16. data/bin/scan_collection +4 -4
  17. data/lib/macroape.rb +14 -11
  18. data/lib/macroape/aligned_pair_intersection.rb +61 -62
  19. data/lib/macroape/cli.rb +191 -188
  20. data/lib/macroape/cli/align_motifs.rb +120 -100
  21. data/lib/macroape/cli/eval_alignment.rb +157 -156
  22. data/lib/macroape/cli/eval_similarity.rb +138 -137
  23. data/lib/macroape/cli/find_pvalue.rb +93 -87
  24. data/lib/macroape/cli/find_threshold.rb +103 -96
  25. data/lib/macroape/cli/preprocess_collection.rb +169 -161
  26. data/lib/macroape/cli/scan_collection.rb +171 -163
  27. data/lib/macroape/collection.rb +29 -0
  28. data/lib/macroape/motif_with_thresholds.rb +18 -0
  29. data/lib/macroape/pwm_compare.rb +39 -44
  30. data/lib/macroape/pwm_compare_aligned.rb +139 -130
  31. data/lib/macroape/{counting.rb → pwm_counting.rb} +175 -121
  32. data/lib/macroape/support/inverf.rb +13 -0
  33. data/lib/macroape/support/partial_sums.rb +17 -0
  34. data/lib/macroape/version.rb +4 -4
  35. data/macroape.gemspec +19 -19
  36. data/spec/count_distribution_spec.rb +112 -109
  37. data/spec/inverf_spec.rb +23 -0
  38. data/spec/partial_sums_spec.rb +28 -0
  39. data/spec/spec_helper.rb +11 -11
  40. data/test/align_motifs_test.rb +42 -43
  41. data/test/data/AHR_si.pwm +10 -10
  42. data/test/data/KLF3_f1.pcm +16 -16
  43. data/test/data/KLF3_f1.pwm +16 -16
  44. data/test/data/KLF4_f2.pcm +11 -11
  45. data/test/data/KLF4_f2.pwm +11 -11
  46. data/test/data/KLF4_f2_scan_results_all.txt +2 -2
  47. data/test/data/KLF4_f2_scan_results_default_cutoff.txt +1 -1
  48. data/test/data/KLF4_f2_scan_results_precise_mode.txt +2 -2
  49. data/test/data/SP1_f1.pcm +12 -12
  50. data/test/data/SP1_f1.pwm +12 -12
  51. data/test/data/SP1_f1_revcomp.pcm +12 -12
  52. data/test/data/SP1_f1_revcomp.pwm +12 -12
  53. data/test/data/medium_motif.pwm +8 -8
  54. data/test/data/short_motif.pwm +7 -7
  55. data/test/data/test_collection.yaml +231 -214
  56. data/test/data/test_collection/GABPA_f1.pwm +14 -14
  57. data/test/data/test_collection/KLF4_f2.pwm +10 -10
  58. data/test/data/test_collection/SP1_f1.pwm +12 -12
  59. data/test/data/test_collection_pcm/GABPA_f1.pcm +14 -14
  60. data/test/data/test_collection_pcm/KLF4_f2.pcm +11 -11
  61. data/test/data/test_collection_pcm/SP1_f1.pcm +12 -12
  62. data/test/data/test_collection_single_file.txt +38 -38
  63. data/test/data/test_collection_single_file_pcm.txt +37 -37
  64. data/test/data/test_collection_weak.yaml +231 -214
  65. data/test/eval_alignment_test.rb +90 -111
  66. data/test/eval_similarity_test.rb +105 -123
  67. data/test/find_pvalue_test.rb +34 -39
  68. data/test/find_threshold_test.rb +87 -91
  69. data/test/preprocess_collection_test.rb +56 -65
  70. data/test/scan_collection_test.rb +42 -48
  71. data/test/test_helper.rb +159 -160
  72. metadata +14 -10
  73. data/test/data/collection_pcm_without_thresholds.yaml +0 -188
  74. data/test/data/collection_without_thresholds.yaml +0 -188
@@ -0,0 +1,13 @@
1
+ module Math
2
+ def self.inverf(x)
3
+ sign = x < 0 ? -1 : 1
4
+ x = x.abs
5
+ a = 8 / (3*Math::PI) * (Math::PI-3) / (4-Math::PI)
6
+ part0 = ( 2/(Math::PI*a) + (Math.log(1-x*x)) / 2 )**2
7
+ part = -2 / (Math::PI * a) - Math.log(1-x*x)/2 + Math.sqrt(-1/a * Math.log(1-x*x) + part0)
8
+ sign * Math.sqrt(part)
9
+ end
10
+ def inverf(x)
11
+ Math.inverf(x)
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ class Array
2
+ def partial_sums(initial = 0.0)
3
+ sums = initial
4
+ map{|el| sums += el}
5
+ end
6
+ end
7
+
8
+ class Hash
9
+ # {1 => 5, 4 => 3, 3 => 2}.partial_sums == {1=>5, 3=>7, 4=>10}
10
+ def partial_sums(initial = 0.0)
11
+ sums = initial
12
+ sort.each_with_object({}){|(k,v), hsh|
13
+ sums += v
14
+ hsh[k] = sums
15
+ }
16
+ end
17
+ end
@@ -1,4 +1,4 @@
1
- module Macroape
2
- VERSION = "4.0.2"
3
- STANDALONE = false
4
- end
1
+ module Macroape
2
+ VERSION = "4.1.0"
3
+ STANDALONE = false
4
+ end
@@ -1,19 +1,19 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/macroape/version', __FILE__)
3
-
4
- Gem::Specification.new do |gem|
5
- gem.authors = ["Ilya Vorontsov"]
6
- gem.email = ["prijutme4ty@gmail.com"]
7
- gem.description = %q{Macroape is an abbreviation for MAtrix CompaRisOn by Approximate P-value Estimation. It's a bioinformatic tool for evaluating similarity measure and best alignment between a pair of Position Weight Matrices(PWM), finding thresholds by P-values and vice versa and even searching a collection of motifs for the most similar ones. Used approach and application described in manual at https://docs.google.com/document/pub?id=1_jsxhMNzMzy4d2d_byAd3n6Szg5gEcqG_Sf7w9tEqWw}
8
- gem.summary = %q{PWM comparison tool using MACROAPE approach}
9
- gem.homepage = "http://autosome.ru/macroape/"
10
-
11
- gem.files = `git ls-files`.split($/)
12
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
- gem.name = "macroape"
15
- gem.require_paths = ["lib"]
16
- gem.version = Macroape::VERSION
17
-
18
- gem.add_dependency('bioinform', '~> 0.1.10')
19
- end
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/macroape/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Ilya Vorontsov"]
6
+ gem.email = ["prijutme4ty@gmail.com"]
7
+ gem.description = %q{Macroape is an abbreviation for MAtrix CompaRisOn by Approximate P-value Estimation. It's a bioinformatic tool for evaluating similarity measure and best alignment between a pair of Position Weight Matrices(PWM), finding thresholds by P-values and vice versa and even searching a collection of motifs for the most similar ones. Used approach and application described in manual at https://docs.google.com/document/pub?id=1_jsxhMNzMzy4d2d_byAd3n6Szg5gEcqG_Sf7w9tEqWw}
8
+ gem.summary = %q{PWM comparison tool using MACROAPE approach}
9
+ gem.homepage = "http://autosome.ru/macroape/"
10
+
11
+ gem.files = `git ls-files`.split($/)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "macroape"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Macroape::VERSION
17
+
18
+ gem.add_dependency('bioinform', '~> 0.2.0')
19
+ end
@@ -1,109 +1,112 @@
1
- require_relative 'spec_helper'
2
- require_relative '../lib/macroape/counting'
3
-
4
- describe Bioinform::PWM do
5
- let :matrix_first do [[1,2,3,4],[10,20,30,40],[100,200,300,400]] end
6
- let :matrix_second do [[1,2,3,4],[2,3,4,5]] end
7
- let :pwm_first do Bioinform::PWM.new(matrix_first) end
8
- let :pwm_second do Bioinform::PWM.new(matrix_second) end
9
- let :background do [0.1,0.4,0.4,0.1] end
10
- let :pwm_first_on_background do pwm_first.tap{|pwm| pwm.set_parameters(background: background)} end
11
- let :pwm_second_on_background do pwm_second.tap{|pwm| pwm.set_parameters(background: background)} end
12
-
13
- context '#count_distribution_after_threshold' do
14
-
15
- it 'should return hash of score => count for all scores >= threshold' do
16
- distribution_first = pwm_first.count_distribution_after_threshold(0)
17
- distribution_first.keys.should == Array.product(*matrix_first).map{|score_row| score_row.inject(&:+)}
18
- distribution_first.values.uniq.should == [1]
19
-
20
- distribution_second = pwm_second.count_distribution_after_threshold(0)
21
- distribution_second.should == { 3=>1, 4=>2, 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 }
22
-
23
- distribution_second = pwm_second.count_distribution_after_threshold(5)
24
- distribution_second.should == { 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 }
25
- end
26
-
27
- it 'for PWMs on different background it should contain the same scores (keys of hash)' do
28
- pwm_first.count_distribution_after_threshold(0).keys.sort.should == pwm_first_on_background.count_distribution_after_threshold(0).keys.sort
29
- pwm_first.count_distribution_after_threshold(13).keys.sort.should == pwm_first_on_background.count_distribution_after_threshold(13).keys.sort
30
- end
31
-
32
- it 'should return hash of score => count for all scores >= threshold when calculated on background' do
33
- distribution_second = pwm_second_on_background.count_distribution_after_threshold(0)
34
- distribution_second.should have_nearly_the_same_values({ 3=>0.01, 4=>0.08, 5=>0.24, 6=>0.34, 7=>0.24, 8=>0.08, 9=>0.01 }, 1e-7 )
35
-
36
- distribution_second = pwm_second_on_background.count_distribution_after_threshold(5)
37
- distribution_second.should have_nearly_the_same_values({ 5=>0.24, 6=>0.34, 7=>0.24, 8=>0.08, 9=>0.01 }, 1e-7 )
38
- end
39
-
40
- it 'should use existing precalculated hash @count_distribution if it exists' do
41
- pwm = pwm_second;
42
- pwm.instance_variable_set :@count_distribution, { 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 }
43
-
44
- distribution_second = pwm.count_distribution_after_threshold(0)
45
- distribution_second.should == { 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 }
46
-
47
- distribution_second = pwm.count_distribution_after_threshold(5)
48
- distribution_second.should == { 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 }
49
- end
50
- end
51
-
52
- context '#count_distribution' do
53
- it 'should return hash of score => count for all available scores' do
54
- pwm_second.count_distribution.should == { 3=>1, 4=>2, 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 }
55
- end
56
-
57
- it 'should cache calculation in @count_distribution' do
58
- pwm = pwm_second;
59
- pwm.instance_variable_set :@count_distribution, { 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 }
60
- pwm.count_distribution.should == { 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 }
61
-
62
- pwm.instance_variable_set :@count_distribution, nil
63
- pwm.count_distribution.should == { 3=>1, 4=>2, 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 }
64
- end
65
- end
66
-
67
- context '#pvalue_by_threshold' do
68
- it 'should return probability to be >= than threshold' do
69
- pwm_second.pvalue_by_threshold(7).should be_within(1e-7).of(6.0/16)
70
- end
71
- it 'should return probability to be >= than threshold when calculated on background' do
72
- pwm_second_on_background.pvalue_by_threshold(7).should be_within(1e-7).of(0.33)
73
- end
74
- end
75
- context '#threshold' do
76
- it 'should return threshold such that according pvalue doesn\'t exceed requested value' do
77
- requested_pvalue = 6.0/16
78
- threshold = pwm_second.threshold(requested_pvalue)
79
- pwm_second.pvalue_by_threshold(threshold).should <= requested_pvalue
80
- end
81
- it 'should return threshold such that according pvalue doesn\'t exceed requested value when calculated on background' do
82
- requested_pvalue = 0.33
83
- threshold = pwm_second_on_background.threshold(requested_pvalue)
84
- pwm_second_on_background.pvalue_by_threshold(threshold).should <= requested_pvalue
85
- end
86
- it 'should return threshold such that according pvalue doesn\'t exceed requested value when actual pvalue isn\'t exact equal to requested' do
87
- requested_pvalue = 0.335
88
- threshold = pwm_second_on_background.threshold(requested_pvalue)
89
- pwm_second_on_background.pvalue_by_threshold(threshold).should <= requested_pvalue
90
- end
91
- end
92
- context '#weak_threshold' do
93
- it 'should return threshold such that according pvalue exceed requested value' do
94
- requested_pvalue = 6.0/16
95
- threshold = pwm_second.weak_threshold(requested_pvalue)
96
- pwm_second.pvalue_by_threshold(threshold).should >= requested_pvalue
97
- end
98
- it 'should return threshold such that according pvalue exceed requested value when calculated on background' do
99
- requested_pvalue = 0.33
100
- threshold = pwm_second_on_background.weak_threshold(requested_pvalue)
101
- pwm_second_on_background.pvalue_by_threshold(threshold).should >= requested_pvalue
102
- end
103
- it 'should return threshold such that according pvalue exceed requested value when actual pvalue isn\'t exact equal to requested' do
104
- requested_pvalue = 0.335
105
- threshold = pwm_second_on_background.weak_threshold(requested_pvalue)
106
- pwm_second_on_background.pvalue_by_threshold(threshold).should >= requested_pvalue
107
- end
108
- end
109
- end
1
+ require_relative 'spec_helper'
2
+ require_relative '../lib/macroape/pwm_counting'
3
+
4
+ describe Bioinform::MotifModel::PWM do
5
+ let :matrix_first do [[1,2,3,4],[10,20,30,40],[100,200,300,400]] end
6
+ let :matrix_second do [[1,2,3,4],[2,3,4,5]] end
7
+ let :pwm_first do Bioinform::MotifModel::PWM.new(matrix_first) end
8
+ let :pwm_second do Bioinform::MotifModel::PWM.new(matrix_second) end
9
+ let :background do Bioinform::Frequencies.new([0.1,0.4,0.4,0.1]) end
10
+
11
+ let :counting_first do Macroape::PWMCounting.new(pwm_first) end
12
+ let :counting_second do Macroape::PWMCounting.new(pwm_second) end
13
+ let :counting_first_on_background do Macroape::PWMCounting.new(pwm_first, background: background) end
14
+ let :counting_second_on_background do Macroape::PWMCounting.new(pwm_second, background: background) end
15
+
16
+ context '#count_distribution_after_threshold' do
17
+
18
+ it 'should return hash of score => count for all scores >= threshold' do
19
+ distribution_first = counting_first.count_distribution_after_threshold(0)
20
+ expect(distribution_first.keys).to eq (matrix_first.first).product(*matrix_first[1..-1]).map{|score_row| score_row.inject(&:+)}
21
+ expect(distribution_first.values.uniq).to eq [1]
22
+
23
+ distribution_second = counting_second.count_distribution_after_threshold(0)
24
+ expect(distribution_second).to eq({ 3=>1, 4=>2, 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 })
25
+
26
+ distribution_second = counting_second.count_distribution_after_threshold(5)
27
+ expect(distribution_second).to eq({ 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 })
28
+ end
29
+
30
+ it 'for PWMs on different background it should contain the same scores (keys of hash)' do
31
+ expect(counting_first.count_distribution_after_threshold(0).keys.sort).to eq counting_first_on_background.count_distribution_after_threshold(0).keys.sort
32
+ expect(counting_first.count_distribution_after_threshold(13).keys.sort).to eq counting_first_on_background.count_distribution_after_threshold(13).keys.sort
33
+ end
34
+
35
+ it 'should return hash of score => count for all scores >= threshold when calculated on background' do
36
+ distribution_second = counting_second_on_background.count_distribution_after_threshold(0)
37
+ expect(distribution_second).to have_nearly_the_same_values({ 3=>0.01, 4=>0.08, 5=>0.24, 6=>0.34, 7=>0.24, 8=>0.08, 9=>0.01 }, 1e-7 )
38
+
39
+ distribution_second = counting_second_on_background.count_distribution_after_threshold(5)
40
+ expect(distribution_second).to have_nearly_the_same_values({ 5=>0.24, 6=>0.34, 7=>0.24, 8=>0.08, 9=>0.01 }, 1e-7 )
41
+ end
42
+
43
+ it 'should use existing precalculated hash @count_distribution if it exists' do
44
+ counting = counting_second;
45
+ counting.instance_variable_set :@count_distribution, { 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 }
46
+
47
+ distribution_second = counting.count_distribution_after_threshold(0)
48
+ expect(distribution_second).to eq({ 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 })
49
+
50
+ distribution_second = counting.count_distribution_after_threshold(5)
51
+ expect(distribution_second).to eq({ 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 })
52
+ end
53
+ end
54
+
55
+ context '#count_distribution' do
56
+ it 'should return hash of score => count for all available scores' do
57
+ expect(counting_second.count_distribution).to eq({ 3=>1, 4=>2, 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 })
58
+ end
59
+
60
+ it 'should cache calculation in @count_distribution' do
61
+ counting = counting_second;
62
+ counting.instance_variable_set :@count_distribution, { 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 }
63
+ expect(counting.count_distribution).to eq({ 3=>10, 4=>20, 5=>30, 6=>40, 7=>30, 8=>20, 9=>10 })
64
+
65
+ counting.instance_variable_set :@count_distribution, nil
66
+ expect(counting.count_distribution).to eq({ 3=>1, 4=>2, 5=>3, 6=>4, 7=>3, 8=>2, 9=>1 })
67
+ end
68
+ end
69
+
70
+ context '#pvalue_by_threshold' do
71
+ it 'should return probability to be >= than threshold' do
72
+ expect(counting_second.pvalue_by_threshold(7)).to be_within(1e-7).of(6.0/16)
73
+ end
74
+ it 'should return probability to be >= than threshold when calculated on background' do
75
+ expect(counting_second_on_background.pvalue_by_threshold(7)).to be_within(1e-7).of(0.33)
76
+ end
77
+ end
78
+ context '#threshold' do
79
+ it 'should return threshold such that according pvalue doesn\'t exceed requested value' do
80
+ requested_pvalue = 6.0/16
81
+ threshold = counting_second.threshold(requested_pvalue)
82
+ expect(counting_second.pvalue_by_threshold(threshold)).to be <= requested_pvalue
83
+ end
84
+ it 'should return threshold such that according pvalue doesn\'t exceed requested value when calculated on background' do
85
+ requested_pvalue = 0.33
86
+ threshold = counting_second_on_background.threshold(requested_pvalue)
87
+ expect(counting_second_on_background.pvalue_by_threshold(threshold)).to be <= requested_pvalue
88
+ end
89
+ it 'should return threshold such that according pvalue doesn\'t exceed requested value when actual pvalue isn\'t exact equal to requested' do
90
+ requested_pvalue = 0.335
91
+ threshold = counting_second_on_background.threshold(requested_pvalue)
92
+ expect(counting_second_on_background.pvalue_by_threshold(threshold)).to be <= requested_pvalue
93
+ end
94
+ end
95
+ context '#weak_threshold' do
96
+ it 'should return threshold such that according pvalue exceed requested value' do
97
+ requested_pvalue = 6.0/16
98
+ threshold = counting_second.weak_threshold(requested_pvalue)
99
+ expect(counting_second.pvalue_by_threshold(threshold)).to be >= requested_pvalue
100
+ end
101
+ it 'should return threshold such that according pvalue exceed requested value when calculated on background' do
102
+ requested_pvalue = 0.33
103
+ threshold = counting_second_on_background.weak_threshold(requested_pvalue)
104
+ expect(counting_second_on_background.pvalue_by_threshold(threshold)).to be >= requested_pvalue
105
+ end
106
+ it 'should return threshold such that according pvalue exceed requested value when actual pvalue isn\'t exact equal to requested' do
107
+ requested_pvalue = 0.335
108
+ threshold = counting_second_on_background.weak_threshold(requested_pvalue)
109
+ expect(counting_second_on_background.pvalue_by_threshold(threshold)).to be >= requested_pvalue
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'spec_helper'
2
+ require 'macroape/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|
11
+ expect(el).to be <= 0.001
12
+ }
13
+ end
14
+ it 'should be erf(inverf(x)) == x' do
15
+ rng = (-5..5).step(1)
16
+ arr = rng.to_a
17
+ arr2 = rng.map{|x| Math.erf(x)}.map{|x| Math.inverf(x)}
18
+ delta = arr.each_index.map{|i| (arr[i] - arr2[i]).abs }
19
+ delta.each{|el|
20
+ expect(el).to be <= 0.01
21
+ }
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ require_relative 'spec_helper'
2
+ require 'macroape/support/partial_sums'
3
+
4
+ describe 'Array#partial_sums' do
5
+ context 'when no initial value given' do
6
+ it 'should return an array of the same size with partial sums of elements 0..ind inclusive with float elements' do
7
+ expect([2,3,4,5].partial_sums).to eq [2, 5, 9, 14]
8
+ expect([2,3,4,5].partial_sums.last).to be_kind_of(Float)
9
+ end
10
+ end
11
+ it 'should start counting from argument when it\'s given. Type of values depends on type of initial value' do
12
+ expect([2,3,4,5].partial_sums(100)).to eq [102,105,109,114]
13
+ expect([2,3,4,5].partial_sums(100).last).to be_kind_of(Integer)
14
+ end
15
+ end
16
+
17
+ describe 'Hash#partial_sums' do
18
+ context 'when no initial value given' do
19
+ it 'should return a hash with float values of the same size with partial sums of elements that has keys <= than argument' do
20
+ expect({1 => 5, 4 => 3, 3 => 2}.partial_sums).to eq({1=>5, 3=>7, 4=>10})
21
+ expect({1 => 5, 4 => 3, 3 => 2}.partial_sums.values.last).to be_kind_of(Float)
22
+ end
23
+ end
24
+ it 'should start counting from argument when it\'s given. Type of values depends on type of initial value' do
25
+ expect({1 => 5, 4 => 3, 3 => 2}.partial_sums(100)).to eq({1=>105, 3=>107, 4=>110})
26
+ expect({1 => 5, 4 => 3, 3 => 2}.partial_sums(100).values.last).to be_kind_of(Integer)
27
+ end
28
+ end
@@ -1,11 +1,11 @@
1
- $bioinform_folder = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bioinform', 'lib'))
2
- $LOAD_PATH.unshift $bioinform_folder
3
-
4
- require 'rspec'
5
-
6
- # comparing hashes with float values
7
- RSpec::Matchers.define :have_nearly_the_same_values do |expected, vicinity|
8
- match do |actual|
9
- expected.all?{|key, _| actual.has_key?(key)} && actual.all?{|key, _| expected.has_key?(key)} && expected.all?{|key, value| (actual[key] - value).abs <= vicinity }
10
- end
11
- end
1
+ $bioinform_folder = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bioinform', 'lib'))
2
+ $LOAD_PATH.unshift $bioinform_folder
3
+
4
+ require 'rspec'
5
+
6
+ # comparing hashes with float values
7
+ RSpec::Matchers.define :have_nearly_the_same_values do |expected, vicinity|
8
+ match do |actual|
9
+ expected.all?{|key, _| actual.has_key?(key)} && actual.all?{|key, _| expected.has_key?(key)} && expected.all?{|key, value| (actual[key] - value).abs <= vicinity }
10
+ end
11
+ end
@@ -1,43 +1,42 @@
1
- require_relative 'test_helper'
2
-
3
- class TestAlignmotifs < Test::Unit::TestCase
4
- def setup
5
- @start_dir = Dir.pwd
6
- Dir.chdir File.join(File.dirname(__FILE__), 'data')
7
- end
8
- def teardown
9
- Dir.chdir(@start_dir)
10
- end
11
-
12
- def test_align_motifs
13
- assert_equal [%w[KLF4_f2.pwm 0 direct],
14
- %w[KLF3_f1.pwm -4 direct],
15
- %w[SP1_f1_revcomp.pwm -1 revcomp]],
16
- Helpers.align_motifs_output('KLF4_f2.pwm KLF3_f1.pwm SP1_f1_revcomp.pwm')
17
- end
18
- def test_align_pcm_motifs
19
- assert_equal [%w[KLF4_f2.pcm 0 direct],
20
- %w[KLF3_f1.pcm -4 direct],
21
- %w[SP1_f1_revcomp.pcm -1 revcomp]],
22
- Helpers.align_motifs_output('--pcm KLF4_f2.pcm KLF3_f1.pcm SP1_f1_revcomp.pcm')
23
- end
24
- def test_names_from_stdin_leader_specified
25
- assert_equal [%w[KLF4_f2.pwm 0 direct],
26
- %w[KLF3_f1.pwm -4 direct],
27
- %w[SP1_f1_revcomp.pwm -1 revcomp]],
28
- Helpers.provide_stdin('KLF3_f1.pwm SP1_f1_revcomp.pwm'){ Helpers.align_motifs_output('KLF4_f2.pwm') }
29
- end
30
- def test_names_from_stdin_leader_not_specified
31
- assert_equal [%w[KLF4_f2.pwm 0 direct],
32
- %w[KLF3_f1.pwm -4 direct],
33
- %w[SP1_f1_revcomp.pwm -1 revcomp]],
34
- Helpers.provide_stdin('KLF4_f2.pwm KLF3_f1.pwm SP1_f1_revcomp.pwm'){ Helpers.align_motifs_output('') }
35
- end
36
- def test_names_from_stdin_duplicate_leader
37
- assert_equal [%w[KLF4_f2.pwm 0 direct],
38
- %w[KLF3_f1.pwm -4 direct],
39
- %w[SP1_f1_revcomp.pwm -1 revcomp]],
40
- Helpers.provide_stdin('KLF3_f1.pwm KLF4_f2.pwm SP1_f1_revcomp.pwm'){ Helpers.align_motifs_output('KLF4_f2.pwm') }
41
- end
42
-
43
- end
1
+ require_relative 'test_helper'
2
+
3
+ class TestAlignmotifs < Test::Unit::TestCase
4
+ def setup
5
+ @start_dir = Dir.pwd
6
+ Dir.chdir File.join(File.dirname(__FILE__), 'data')
7
+ end
8
+ def teardown
9
+ Dir.chdir(@start_dir)
10
+ end
11
+
12
+ def test_align_motifs
13
+ assert_equal [%w[KLF4_f2.pwm 0 direct],
14
+ %w[KLF3_f1.pwm -4 direct],
15
+ %w[SP1_f1_revcomp.pwm -1 revcomp]],
16
+ Helpers.align_motifs_output('KLF4_f2.pwm KLF3_f1.pwm SP1_f1_revcomp.pwm')
17
+ end
18
+ def test_align_pcm_motifs
19
+ assert_equal [%w[KLF4_f2.pcm 0 direct],
20
+ %w[KLF3_f1.pcm -4 direct],
21
+ %w[SP1_f1_revcomp.pcm -1 revcomp]],
22
+ Helpers.align_motifs_output('--pcm KLF4_f2.pcm KLF3_f1.pcm SP1_f1_revcomp.pcm')
23
+ end
24
+ def test_names_from_stdin_leader_specified
25
+ assert_equal [%w[KLF4_f2.pwm 0 direct],
26
+ %w[KLF3_f1.pwm -4 direct],
27
+ %w[SP1_f1_revcomp.pwm -1 revcomp]],
28
+ Helpers.provide_stdin('KLF3_f1.pwm SP1_f1_revcomp.pwm'){ Helpers.align_motifs_output('KLF4_f2.pwm') }
29
+ end
30
+ def test_names_from_stdin_leader_not_specified
31
+ assert_equal [%w[KLF4_f2.pwm 0 direct],
32
+ %w[KLF3_f1.pwm -4 direct],
33
+ %w[SP1_f1_revcomp.pwm -1 revcomp]],
34
+ Helpers.provide_stdin('KLF4_f2.pwm KLF3_f1.pwm SP1_f1_revcomp.pwm'){ Helpers.align_motifs_output('') }
35
+ end
36
+ def test_names_from_stdin_duplicate_leader
37
+ assert_equal [%w[KLF4_f2.pwm 0 direct],
38
+ %w[KLF3_f1.pwm -4 direct],
39
+ %w[SP1_f1_revcomp.pwm -1 revcomp]],
40
+ Helpers.provide_stdin('KLF3_f1.pwm KLF4_f2.pwm SP1_f1_revcomp.pwm'){ Helpers.align_motifs_output('KLF4_f2.pwm') }
41
+ end
42
+ end