viral_seq 0.3.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +7 -1
- data/lib/viral_seq/Integer.rb +16 -0
- data/lib/viral_seq/constant.rb +7 -0
- data/lib/viral_seq/enumerable.rb +132 -0
- data/lib/viral_seq/hash.rb +45 -0
- data/lib/viral_seq/hivdr.rb +454 -0
- data/lib/viral_seq/math.rb +128 -380
- data/lib/viral_seq/muscle.rb +60 -82
- data/lib/viral_seq/pid.rb +26 -0
- data/lib/viral_seq/ref_seq.rb +35 -0
- data/lib/viral_seq/rubystats.rb +172 -0
- data/lib/viral_seq/seq_hash.rb +1043 -0
- data/lib/viral_seq/seq_hash_pair.rb +219 -0
- data/lib/viral_seq/sequence.rb +571 -348
- data/lib/viral_seq/string.rb +119 -0
- data/lib/viral_seq/version.rb +1 -1
- data/lib/viral_seq.rb +14 -15
- metadata +13 -12
- data/lib/viral_seq/a3g.rb +0 -172
- data/lib/viral_seq/fasta.rb +0 -154
- data/lib/viral_seq/hcv_dr.rb +0 -54
- data/lib/viral_seq/locator.rb +0 -299
- data/lib/viral_seq/misc.rb +0 -103
- data/lib/viral_seq/nt_variation.rb +0 -148
- data/lib/viral_seq/poisson_cutoff.rb +0 -68
- data/lib/viral_seq/refseq.rb +0 -45
- data/lib/viral_seq/sdrm_core.rb +0 -652
- data/lib/viral_seq/tcs_core.rb +0 -556
data/lib/viral_seq/math.rb
CHANGED
@@ -1,401 +1,149 @@
|
|
1
|
-
# lib/math.rb
|
2
|
-
|
3
|
-
# math and statistic functions
|
4
|
-
# inlcuding the following methods
|
5
|
-
# ViralSeq::count
|
6
|
-
# ViralSeq::count_percentage
|
7
|
-
# ViralSeq::poisson_distribution
|
8
|
-
# ViralSeq::r_binom_CI
|
9
|
-
# Enumerable#median
|
10
|
-
# Enumerable#sum
|
11
|
-
# Enumerable#mean
|
12
|
-
# Enumerable#sample_variance
|
13
|
-
# Enumerable#stdev
|
14
|
-
# Enumerable#upper_quartile
|
15
|
-
# Enumerable#lower_quartile
|
16
|
-
# Integer#!
|
17
|
-
# Rubystats::FishersExactTest
|
18
|
-
# RandomGaussian::new
|
19
|
-
# RandomGaussian#rand
|
20
1
|
|
21
2
|
module ViralSeq
|
22
3
|
|
23
|
-
#
|
24
|
-
# =Usage
|
25
|
-
# array = %w{cat dog monkey cat cat cat monkey}
|
26
|
-
# ViralSeq.count(array)
|
27
|
-
# => {"cat"=>4, "dog"=>1, "monkey"=>2}
|
28
|
-
|
29
|
-
def self.count(array)
|
30
|
-
hash = Hash.new(0)
|
31
|
-
array.each do |element|
|
32
|
-
hash[element] +=1
|
33
|
-
end
|
34
|
-
return hash
|
35
|
-
end
|
4
|
+
# math functions reqruied for ViralSeq
|
36
5
|
|
37
|
-
|
38
|
-
# default decimal as 2
|
39
|
-
# =Usage
|
40
|
-
# array = %w{cat dog monkey cat cat cat monkey}
|
41
|
-
# ViralSeq.count_percentage(array)
|
42
|
-
# => {"cat"=>0.57, "dog"=>0.14, "monkey"=>0.29}
|
43
|
-
|
44
|
-
def self.count_percentage(array,decimal = 2)
|
45
|
-
hash1 = Hash.new(0)
|
46
|
-
array.each do |element|
|
47
|
-
hash1[element] += 1
|
48
|
-
end
|
49
|
-
total_elements = array.size
|
50
|
-
hash2 = Hash.new(0)
|
51
|
-
hash1.each do |key,value|
|
52
|
-
hash2[key] = (value/total_elements.to_f).round(decimal)
|
53
|
-
end
|
54
|
-
return hash2
|
55
|
-
end
|
56
|
-
|
57
|
-
# poisson distribution. input lambda and maximum k, return a hash with keys as k
|
58
|
-
# default k value is 5, meaning calculate up to 5 events.
|
59
|
-
#
|
60
|
-
# Poisson Distribution (https://en.wikipedia.org/wiki/Poisson_distribution)
|
61
|
-
# An event can occur 0, 1, 2, … times in an interval.
|
62
|
-
# The average number of events in an interval is designated λ (lambda).
|
63
|
-
# λ is the event rate, also called the rate parameter.
|
64
|
-
# The probability of observing k events in an interval is given by the equation
|
65
|
-
#
|
66
|
-
# P(k events in interval) = e^(-λ) * λ^k / k!
|
67
|
-
#
|
68
|
-
# λ is the average number of events per interval
|
69
|
-
# e is the number 2.71828... (Euler's number) the base of the natural logarithms
|
70
|
-
# k takes values 0, 1, 2, …
|
71
|
-
# k! = k × (k − 1) × (k − 2) × … × 2 × 1 is the factorial of k.
|
72
|
-
#
|
73
|
-
# =USAGE
|
74
|
-
# # We assume the mutaiton rate is 0.005 (event rate λ),
|
75
|
-
# # we would like to calculate the probablity of 3 mutations on one sequence
|
76
|
-
# prob_hash = ViralSeq::poisson_distribution(0.005)
|
77
|
-
# => {0=>0.9950124791926823, 1=>0.004975062395963412, 2=>1.243765598990853e-05, 3=>2.072942664984755e-08, 4=>2.5911783312309436e-11, 5=>2.591178331230944e-14}
|
78
|
-
# prob_hash[3]
|
79
|
-
# => 2.072942664984755e-08
|
80
|
-
|
81
|
-
def self.poisson_distribution(rate,k = 5)
|
82
|
-
out_hash = {}
|
83
|
-
(0..k).each do |n|
|
84
|
-
p = (rate**n * Math::E**(-rate))/!n
|
85
|
-
out_hash[n] = p
|
86
|
-
end
|
87
|
-
return out_hash
|
88
|
-
end
|
6
|
+
module Math
|
89
7
|
|
8
|
+
# Generate values from the standard normal distribution with given mean and standard deviation
|
9
|
+
# @see http://en.wikipedia.org/wiki/Box-Muller_transform Wikipedia explanation
|
90
10
|
|
91
|
-
|
92
|
-
# calculate binomial 95% confidence intervals by R. refer to R function binom.test
|
93
|
-
# input number x and n, return an array as [lower_interval, upper_interval]
|
94
|
-
#
|
95
|
-
# =USAGE
|
96
|
-
# # mutation M184V found in 3 out of 923 sequences, the 95% confidence interval is
|
97
|
-
# ViralSeq.r_binom_CI(3, 923)
|
98
|
-
# => [0.02223, 0.19234]
|
99
|
-
#
|
100
|
-
def self.r_binom_CI(x= 0, n= 0)
|
101
|
-
r_output = `Rscript -e 'binom.test(#{x},#{n})$conf.int[1];binom.test(#{x},#{n})$conf.int[2]'`
|
102
|
-
lines = r_output.split "\n"
|
103
|
-
low = lines[0].chomp[4..-1].to_f
|
104
|
-
high = lines[1].chomp[4..-1].to_f
|
105
|
-
return [low.round(5), high.round(5)]
|
106
|
-
end
|
11
|
+
class RandomGaussian
|
107
12
|
|
108
|
-
|
109
|
-
|
110
|
-
#
|
111
|
-
# :median :sum :mean :sample_variance :stdev :upper_quartile :lower_quartile
|
112
|
-
# =USAGE
|
113
|
-
# array = [1,2,3,4,5,6,7,8,9,10]
|
114
|
-
# array.median
|
115
|
-
# => 5.5
|
116
|
-
# array.sum
|
117
|
-
# => 55
|
118
|
-
# array.mean
|
119
|
-
# => 5.5
|
120
|
-
# array.sample_variance
|
121
|
-
# => 9.166666666666666
|
122
|
-
# array.stdev
|
123
|
-
# => 3.0276503540974917
|
124
|
-
# array.upper_quartile
|
125
|
-
# => 7.5
|
126
|
-
# array.lower_quartile
|
127
|
-
# => 3.5
|
128
|
-
|
129
|
-
module Enumerable
|
130
|
-
def median
|
131
|
-
len = self.length
|
132
|
-
sorted = self.sort
|
133
|
-
len % 2 == 1 ? sorted[len/2] : (sorted[len/2 - 1] + sorted[len/2]).to_f / 2
|
134
|
-
end
|
135
|
-
|
136
|
-
def sum
|
137
|
-
self.inject(0){|accum, i| accum + i }
|
138
|
-
end
|
139
|
-
|
140
|
-
def mean
|
141
|
-
self.sum/self.length.to_f
|
142
|
-
end
|
143
|
-
|
144
|
-
def sample_variance
|
145
|
-
m = self.mean
|
146
|
-
sum = self.inject(0){|accum, i| accum + (i-m)**2 }
|
147
|
-
sum/(self.length - 1).to_f
|
148
|
-
end
|
149
|
-
|
150
|
-
def stdev
|
151
|
-
return Math.sqrt(self.sample_variance)
|
152
|
-
end
|
153
|
-
|
154
|
-
def upper_quartile
|
155
|
-
return nil if self.empty?
|
156
|
-
sorted_array = self.sort
|
157
|
-
u = (0.25*(3*sorted_array.length))
|
158
|
-
if (u-u.truncate).is_a?(Integer)
|
159
|
-
return sorted_array[(u-u.truncate)-1]
|
160
|
-
else
|
161
|
-
sample = sorted_array[u.truncate.abs-1]
|
162
|
-
sample1 = sorted_array[(u.truncate.abs)]
|
163
|
-
return sample+((sample1-sample)*(u-u.truncate))
|
164
|
-
end
|
165
|
-
end
|
13
|
+
# generate RandomGaussian instance with given mean and standard deviation
|
14
|
+
# @param mean [Float] mean value.
|
15
|
+
# @param sd [Float] standard deviation value.
|
166
16
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
u = 0.25*sorted_array.length + 1
|
171
|
-
if (u-u.truncate).is_a?(Integer)
|
172
|
-
return sorted_array[(u-u.truncate)-1]
|
173
|
-
else
|
174
|
-
sample = sorted_array[u.truncate.abs-1]
|
175
|
-
sample1 = sorted_array[(u.truncate.abs)]
|
176
|
-
return sample+((sample1-sample)*(u-u.truncate))
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
# factorial method for an Integer
|
182
|
-
# Integer.!
|
183
|
-
class Integer
|
184
|
-
def !
|
185
|
-
if self == 0
|
186
|
-
return 1
|
187
|
-
else
|
188
|
-
(1..self).inject(:*)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
|
194
|
-
# Fisher's Exact Test Function Library
|
195
|
-
#
|
196
|
-
# Based on JavaScript version created by: Oyvind Langsrud
|
197
|
-
# Ported to Ruby by Bryan Donovan
|
198
|
-
|
199
|
-
module Rubystats
|
200
|
-
class FishersExactTest
|
201
|
-
|
202
|
-
def initialize
|
203
|
-
@sn11 = 0.0
|
204
|
-
@sn1_ = 0.0
|
205
|
-
@sn_1 = 0.0
|
206
|
-
@sn = 0.0
|
207
|
-
@sprob = 0.0
|
208
|
-
|
209
|
-
@sleft = 0.0
|
210
|
-
@sright = 0.0
|
211
|
-
@sless = 0.0
|
212
|
-
@slarg = 0.0
|
213
|
-
|
214
|
-
@left = 0.0
|
215
|
-
@right = 0.0
|
216
|
-
@twotail = 0.0
|
217
|
-
end
|
218
|
-
|
219
|
-
# Reference: "Lanczos, C. 'A precision approximation
|
220
|
-
# of the gamma function', J. SIAM Numer. Anal., B, 1, 86-96, 1964."
|
221
|
-
# Translation of Alan Miller's FORTRAN-implementation
|
222
|
-
# See http://lib.stat.cmu.edu/apstat/245
|
223
|
-
def lngamm(z)
|
224
|
-
x = 0
|
225
|
-
x += 0.0000001659470187408462 / (z+7)
|
226
|
-
x += 0.000009934937113930748 / (z+6)
|
227
|
-
x -= 0.1385710331296526 / (z+5)
|
228
|
-
x += 12.50734324009056 / (z+4)
|
229
|
-
x -= 176.6150291498386 / (z+3)
|
230
|
-
x += 771.3234287757674 / (z+2)
|
231
|
-
x -= 1259.139216722289 / (z+1)
|
232
|
-
x += 676.5203681218835 / (z)
|
233
|
-
x += 0.9999999999995183
|
234
|
-
|
235
|
-
return(Math.log(x)-5.58106146679532777-z+(z-0.5) * Math.log(z+6.5))
|
236
|
-
end
|
237
|
-
|
238
|
-
def lnfact(n)
|
239
|
-
if n <= 1
|
240
|
-
return 0
|
241
|
-
else
|
242
|
-
return lngamm(n+1)
|
17
|
+
def initialize(mean = 0.0, sd = 1.0, rng = lambda { Kernel.rand })
|
18
|
+
@mean, @sd, @rng = mean, sd, rng
|
19
|
+
@compute_next_pair = false
|
243
20
|
end
|
244
|
-
end
|
245
21
|
|
246
|
-
|
247
|
-
return
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
@sn11 = n11i
|
264
|
-
return @sprob
|
265
|
-
end
|
266
|
-
if n11i == @sn11-1
|
267
|
-
@sprob *= ((@sn11)/(@sn1_-n11i.to_f))*((@sn11+@sn-@sn1_-@sn_1)/(@sn_1-n11i.to_f))
|
268
|
-
@sn11 = n11i
|
269
|
-
return @sprob
|
270
|
-
end
|
22
|
+
# generate a random number that falls in the pre-defined gaussian distribution
|
23
|
+
# @return [Float]
|
24
|
+
# @example generate 10 random number that falls in the a gaussian distribution with mean at 0 and standard deviation at 1.0
|
25
|
+
# a = RandomGaussian.new
|
26
|
+
# numbers = []
|
27
|
+
# 10.times {numbers << a.rand.round(5)}
|
28
|
+
# numbers
|
29
|
+
# => [-1.83457, 1.24439, -0.30109, 0.13977, 0.61556, 1.3548, 1.72878, 2.46171, 0.97031, -0.29496]
|
30
|
+
|
31
|
+
def rand
|
32
|
+
if (@compute_next_pair = !@compute_next_pair)
|
33
|
+
theta = 2 * ::Math::PI * @rng.call
|
34
|
+
scale = @sd * ::Math.sqrt(-2 * Math.log(1 - @rng.call))
|
35
|
+
@g1 = @mean + scale * ::Math.sin(theta)
|
36
|
+
@g0 = @mean + scale * ::Math.cos(theta)
|
37
|
+
else
|
38
|
+
@g1
|
271
39
|
end
|
272
|
-
@sn11 = n11i
|
273
|
-
else
|
274
|
-
@sn11 = n11i
|
275
|
-
@sn1_ = n1_i
|
276
|
-
@sn_1 = n_1i
|
277
|
-
@sn = ni
|
278
|
-
end
|
279
|
-
@sprob = hyper_323(@sn11,@sn1_,@sn_1,@sn)
|
280
|
-
return @sprob
|
281
|
-
end
|
282
|
-
|
283
|
-
def exact(n11,n1_,n_1,n)
|
284
|
-
|
285
|
-
p = i = j = prob = 0.0
|
286
|
-
|
287
|
-
max = n1_
|
288
|
-
max = n_1 if n_1 < max
|
289
|
-
min = n1_ + n_1 - n
|
290
|
-
min = 0 if min < 0
|
291
|
-
|
292
|
-
if min == max
|
293
|
-
@sless = 1
|
294
|
-
@sright = 1
|
295
|
-
@sleft = 1
|
296
|
-
@slarg = 1
|
297
|
-
return 1
|
298
|
-
end
|
299
|
-
|
300
|
-
prob = hyper0(n11,n1_,n_1,n)
|
301
|
-
@sleft = 0
|
302
|
-
|
303
|
-
p = hyper(min)
|
304
|
-
i = min + 1
|
305
|
-
while p < (0.99999999 * prob)
|
306
|
-
@sleft += p
|
307
|
-
p = hyper(i)
|
308
|
-
i += 1
|
309
40
|
end
|
310
41
|
|
311
|
-
|
42
|
+
end
|
312
43
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
44
|
+
# class for poisson distribution.
|
45
|
+
# An event can occur 0, 1, 2, … times in an interval.
|
46
|
+
# The average number of events in an interval is designated λ (lambda).
|
47
|
+
# λ is the event rate, also called the rate parameter.
|
48
|
+
# The probability of observing k events in an interval is given by the equation
|
49
|
+
#
|
50
|
+
# P(k events in interval) = e^(-λ) * λ^k / k!
|
51
|
+
#
|
52
|
+
# λ is the average number of events per interval
|
53
|
+
# e is the number 2.71828... (Euler's number) the base of the natural logarithms
|
54
|
+
# k takes values 0, 1, 2, …
|
55
|
+
# k! = k × (k − 1) × (k − 2) × … × 2 × 1 is the factorial of k.
|
56
|
+
# @see https://en.wikipedia.org/wiki/Poisson_distribution Poisson Distribution (Wikipedia).
|
57
|
+
# @example given the mutation rate at 0.01 and sequence length of 1000 bp,
|
58
|
+
# calculate the probablity of 3 mutations on one sequence
|
59
|
+
# new_poisson_dist = ViralSeq::Math::PoissonDist.new(0.01)
|
60
|
+
# prob_hash = new_poisson_dist.poisson_hash
|
61
|
+
# 1000 * prob_hash[3].round(5)
|
62
|
+
# => 0.00017
|
63
|
+
class PoissonDist
|
64
|
+
# initialize with given event rate λ, default events upper limit set to 5
|
65
|
+
def initialize(rate,k = 5)
|
66
|
+
@rate = rate
|
67
|
+
@k = k
|
68
|
+
@poisson_hash = {}
|
69
|
+
(0..k).each do |n|
|
70
|
+
p = (rate**n * ::Math::E**(-rate))/!n
|
71
|
+
@poisson_hash[n] = p
|
72
|
+
end
|
317
73
|
end
|
318
74
|
|
319
|
-
@
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
75
|
+
# @return [Float] event rate λ
|
76
|
+
attr_accessor :rate
|
77
|
+
# @return [Integer] maxinum events number shows in @poisson_hash
|
78
|
+
attr_accessor :k
|
79
|
+
# @return [Hash] probablity hash of :event_number => :probablity
|
80
|
+
attr_reader :poisson_hash
|
81
|
+
end # end of PoissonDist
|
82
|
+
|
83
|
+
# Use R to calculate binomial 95% confidence intervals. Require R function binom.test.
|
84
|
+
# @example mutation M184V found in 3 out of 923 sequences, calculate 95% confidence interval
|
85
|
+
# freq = ViralSeq::Math::BinomCI.new(3,923)
|
86
|
+
# freq.mean.round(5)
|
87
|
+
# => 0.00325
|
88
|
+
# freq.lower.round(5)
|
89
|
+
# => 0.00067
|
90
|
+
# freq.upper.round(5)
|
91
|
+
# => 0.00947
|
92
|
+
|
93
|
+
class BinomCI
|
94
|
+
# initialize with numerator @n1 and denominator @n2 as Integer
|
95
|
+
def initialize(n1, n2)
|
96
|
+
@n1 = n1
|
97
|
+
@n2 = n2
|
98
|
+
@mean = n1/n2.to_f
|
99
|
+
r_output = `Rscript -e 'binom.test(#{n1},#{n2})$conf.int[1];binom.test(#{n1},#{n2})$conf.int[2]'`
|
100
|
+
lines = r_output.split "\n"
|
101
|
+
@lower = lines[0].chomp[4..-1].to_f
|
102
|
+
@upper = lines[1].chomp[4..-1].to_f
|
327
103
|
end
|
328
|
-
j += 1
|
329
104
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
105
|
+
# @return [Integer] number of observations
|
106
|
+
attr_accessor :n1
|
107
|
+
# @return [Integer] total numbers
|
108
|
+
attr_accessor :n2
|
109
|
+
# @return [Float] mean
|
110
|
+
attr_reader :mean
|
111
|
+
# @return [Float] lower limit of 95% CI
|
112
|
+
attr_reader :lower
|
113
|
+
# @return [Float] upper limit of 95% CI
|
114
|
+
attr_reader :upper
|
115
|
+
|
116
|
+
end # end of BinomCI
|
117
|
+
|
118
|
+
|
119
|
+
# A function to calcuate cut-off for offspring primer IDs.
|
120
|
+
# @see https://www.ncbi.nlm.nih.gov/pubmed/26041299 reference at Zhou et al. JVI 2016.
|
121
|
+
# @param m [Integer] PID abundance
|
122
|
+
# @param error_rate [Float] estimated platform error rate, the model supports error rate from 0.003 to 0.03.
|
123
|
+
# @return [Integer] an abundance cut-off (Integer) for offspring Primer IDs.
|
124
|
+
|
125
|
+
def self.calculate_pid_cut_off(m, error_rate = 0.02)
|
126
|
+
if m <= 10
|
127
|
+
return 2
|
334
128
|
end
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
129
|
+
n = 0
|
130
|
+
case error_rate
|
131
|
+
when 0...0.0075
|
132
|
+
n = -9.59*10**-27*m**6 + 3.27*10**-21*m**5 - 3.05*10**-16*m**4 + 1.2*10**-11*m**3 - 2.19*10**-7*m**2 + 0.004044*m + 2.273
|
133
|
+
when 0.0075...0.015
|
134
|
+
n = 1.09*10**-26*m**6 + 7.82*10**-22*m**5 - 1.93*10**-16*m**4 + 1.01*10**-11*m**3 - 2.31*10**-7*m**2 + 0.00645*m + 2.872
|
135
|
+
when 0.015..0.03
|
136
|
+
if m <= 8500
|
137
|
+
n = -1.24*10**-21*m**6 + 3.53*10**-17*m**5 - 3.90*10**-13*m**4 + 2.12*10**-9*m**3 - 6.06*10**-6*m**2 + 1.80*10**-2*m + 3.15
|
138
|
+
else
|
139
|
+
n = 0.0079 * m + 9.4869
|
140
|
+
end
|
339
141
|
else
|
340
|
-
|
341
|
-
@slarg = @sright
|
142
|
+
raise ArgumentError.new('Error_rate has be between 0 to 0.03')
|
342
143
|
end
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
n21_ *= -1 if n21_ < 0
|
350
|
-
n22_ *= -1 if n22_ < 0
|
351
|
-
n1_ = n11_ + n12_
|
352
|
-
n_1 = n11_ + n21_
|
353
|
-
n = n11_ + n12_ + n21_ + n22_
|
354
|
-
exact(n11_,n1_,n_1,n)
|
355
|
-
left = @sless
|
356
|
-
right = @slarg
|
357
|
-
twotail = @sleft + @sright
|
358
|
-
twotail = 1 if twotail > 1
|
359
|
-
values_hash = { :left =>left, :right =>right, :twotail =>twotail }
|
360
|
-
return values_hash
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
|
366
|
-
# generate values from the standard normal distribution with given mean and standard deviation
|
367
|
-
# See http://en.wikipedia.org/wiki/Box-Muller_transform
|
368
|
-
#
|
369
|
-
# RandomGaussian.new(mean, sd, rng)
|
370
|
-
# # generate RandomGaussian instance with given mean and standard deviation
|
371
|
-
# # default value: mean = 0.0, sd = 1.0
|
372
|
-
#
|
373
|
-
# RandomGaussian.rand
|
374
|
-
# # generate a random number that falls in the pre-defined gaussian distribution
|
375
|
-
# =USAGE
|
376
|
-
# # example
|
377
|
-
# a = RandomGaussian.new
|
378
|
-
# a.rand
|
379
|
-
# numbers = []
|
380
|
-
# 10.times {numbers << a.rand.round(5)}
|
381
|
-
# numbers
|
382
|
-
# [-1.83457, 1.24439, -0.30109, 0.13977, 0.61556, 1.3548, 1.72878, 2.46171, 0.97031, -0.29496]
|
383
|
-
|
384
|
-
|
385
|
-
class RandomGaussian
|
386
|
-
def initialize(mean = 0.0, sd = 1.0, rng = lambda { Kernel.rand })
|
387
|
-
@mean, @sd, @rng = mean, sd, rng
|
388
|
-
@compute_next_pair = false
|
389
|
-
end
|
390
|
-
|
391
|
-
def rand
|
392
|
-
if (@compute_next_pair = !@compute_next_pair)
|
393
|
-
theta = 2 * Math::PI * @rng.call
|
394
|
-
scale = @sd * Math.sqrt(-2 * Math.log(1 - @rng.call))
|
395
|
-
@g1 = @mean + scale * Math.sin(theta)
|
396
|
-
@g0 = @mean + scale * Math.cos(theta)
|
397
|
-
else
|
398
|
-
@g1
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
144
|
+
n = n.round
|
145
|
+
n = 2 if n < 3
|
146
|
+
return n
|
147
|
+
end # end of .calculate_pid_cut_off
|
148
|
+
end # end of Math
|
149
|
+
end # end of ViralSeq
|