File Coverage

Bio/Tools/RandomDistFunctions.pm
Criterion Covered Total %
statement 37 44 84.0
branch 4 14 28.5
condition 4 12 33.3
subroutine 8 8 100.0
pod 3 4 75.0
total 56 82 68.2


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::Tools::RandomDistFunctions
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Jason Stajich
7             #
8             # Copyright Jason Stajich
9             #
10             # You may distribute this module under the same terms as perl itself
11              
12             # POD documentation - main docs before the code
13              
14             =head1 NAME
15              
16             Bio::Tools::RandomDistFunctions - A set of routines useful for
17             generating random data in different distributions
18              
19             =head1 SYNOPSIS
20              
21             use Bio::Tools::RandomDistFunctions;
22             my $dist = Bio::Tools::RandomDistFunctions->new();
23             for my $v ( 1..1000 ) {
24             my $birth_dist = $dist->rand_birth_distribution($lambda);
25             # ... do something with the variable
26             }
27              
28             =head1 DESCRIPTION
29              
30             Most of the code is based on the C implementation of these routines in
31             Mike Sanderson's r8s's package. See http://loco.biosci.arizona.edu/r8s/ for
32             information on his software.
33              
34             =for comment
35             This code tries to be fast and use available faster BigInt and GMP
36             library methods when those modules are available.
37              
38             =head1 FEEDBACK
39              
40             =head2 Mailing Lists
41              
42             User feedback is an integral part of the evolution of this and other
43             Bioperl modules. Send your comments and suggestions preferably to
44             the Bioperl mailing list. Your participation is much appreciated.
45              
46             bioperl-l@bioperl.org - General discussion
47             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
48              
49             =head2 Support
50              
51             Please direct usage questions or support issues to the mailing list:
52              
53             I
54              
55             rather than to the module maintainer directly. Many experienced and
56             reponsive experts will be able look at the problem and quickly
57             address it. Please include a thorough description of the problem
58             with code and data examples if at all possible.
59              
60             =head2 Reporting Bugs
61              
62             Report bugs to the Bioperl bug tracking system to help us keep track
63             of the bugs and their resolution. Bug reports can be submitted via the
64             web:
65              
66             https://github.com/bioperl/bioperl-live/issues
67              
68             =head1 AUTHOR - Jason Stajich
69              
70             Email jason-at-bioperl.org
71              
72             =head1 CONTRIBUTORS
73              
74             Thanks to Mike Sanderson for assistance in the getting this
75             implementation together.
76              
77             =head1 APPENDIX
78              
79             The rest of the documentation details each of the object methods.
80             Internal methods are usually preceded with a _
81              
82             =cut
83              
84              
85             # Let the code begin...
86              
87              
88             package Bio::Tools::RandomDistFunctions;
89             require Exporter;
90 3     3   412 use vars qw(%LOADED @EXPORT_OK); use strict;
  3     3   5  
  3         116  
  3         14  
  3         5  
  3         52  
91              
92             #use Math::BigFloat lib => 'GMP,Bit::Vector';
93             #use Math::BigInt lib => 'GMP,Bit::Vector';
94 3     3   789 use POSIX;
  3         13811  
  3         13  
95              
96 3     3   6647 use base qw(Bio::Root::Root);
  3         6  
  3         998  
97              
98             =head2 birth_distribution
99              
100             Title : rand_birth_distribution
101             Usage : my $randvar = $dist->
102             rand_birth_distribution($lambda);
103             Function: Returns a random number from a birth process waiting
104             time with a fixed interval
105             1.0. Times are measured from 0=present,1=root;
106             Returns : floating point number
107             Args : $lambda ( > 0 )
108             References : This is based on code by Mike Sanders in r8s.
109             Ross, Stochastic Processes, p. 145 for the density
110              
111             =cut
112              
113             sub rand_birth_distribution{
114 962     962 0 2164 my ($self,$lambda) = @_;
115 962 0 33     2569 if( ! ref($self) &&
116             $self !~ /RandomDistFunctions/ ) {
117 0         0 $lambda = $self;
118             }
119 962 50       2295 unless( $lambda ) {
120 0         0 $self->throw("Cannot call birth_distribution without a valid lambda value (>0)");
121             }
122 962         6915 return 1 - (log(rand(1) * (exp($lambda) - 1)+1)/ $lambda);
123             }
124              
125              
126             =head2 rand_geometric_distribution
127              
128             Title : rand_geometric_distribution
129             Usage : my $randvar = $dist->rand_geometric_distribution($param);
130             Function: Returns a random geometric variate distributed with
131             parameter $param, according to
132             c.d.f. 1 - ( 1- param) ^ n
133             Returns : integer
134             Args : $param ( 0 > $param < 1 )
135              
136              
137             =cut
138              
139             sub rand_geometric_distribution{
140 1     1 1 2 my ($self,$param) = @_;
141 1 0 33     3 if( ! ref($self) &&
142             $self !~ /RandomDistFunctions/ ) {
143 0         0 $param = $self;
144             }
145 1 50       3 unless( $param ) {
146 0         0 $self->throw("Cannot call rand_geometric_distribution without a valid param value (>0)");
147             }
148              
149 1         1 my $den;
150 1 50       3 if( $param < 1e-8) {
151 0         0 $den = (-1 * $param) - ( $param * $param ) / 2;
152             } else {
153 1         3 $den = log(1 - $param);
154             }
155 1         3 my $z = log(1 - rand(1)) / $den;
156 1         7 return POSIX::floor($z) + 1;
157             # MSanderson comments from r8s code
158             # Is this the right truncation of the real-valued expression above?
159             # YES
160             # Checked by reference to the expected mean of the distribution in
161             # 100,000 replicates
162             # EX = 1/param Var = (1-param)/param^2 See Olkin, Gleser, and
163             # Derman, p. 193ff. Probability Models and Applications, 1980.
164             }
165              
166             =head2 rand_exponentional_distribution
167              
168             Title : rand_exponentional_distribution
169             Usage : my $var = $dist->rand_exponentional_distribution($param);
170             Function: Returns a random exponential variate distributed with parameter
171             $param, according to c.d.f 1 - e^(-param * x)
172             Returns : floating point number
173             Args : $param ( > 0 )
174              
175              
176             =cut
177              
178             sub rand_exponentional_distribution {
179 1     1 1 2 my ($self,$param) = @_;
180 1 0 33     4 if( ! ref($self) &&
181             $self !~ /RandomDistFunctions/ ) {
182 0         0 $param = $self;
183             }
184 1 50       3 unless( $param ) {
185 0         0 $self->throw("Cannot call rand_exponentional_distribution without a valid param value (>0)");
186             }
187 1         30 return log( 1- rand(1)) / $param;
188             }
189              
190             =head2 rand_normal_distribution
191              
192             Title : rand_normal_distribution
193             Usage : my $var = $dist->rand_normal_distribution()
194             Function: Returns a random normal (gaussian) variate distributed
195             Returns : floating point number
196             Args : none
197              
198              
199             =cut
200              
201             sub rand_normal_distribution{
202 1     1 1 2 my $gset;
203 1         2 my ($rsq,$v1,$v2) = ( 0,0,0);
204 1   33     2 do {
205 1         3 $v1 = 2 * rand(1) - 1;
206 1         2 $v2 = 2 * rand(1) - 1;
207 1         7 $rsq= $v1**2 + $v2 ** 2;
208             } while( $rsq >= 1 || $rsq == 0);
209 1         3 my $fac = sqrt(-2.0 * log($rsq) / $rsq );
210 1         2 $gset = $v1 * $fac;
211 1         2 return $v2 * $fac;
212             }
213              
214             1;