File Coverage

lib/Bio/SAGE/Comparison.pm
Criterion Covered Total %
statement 194 270 71.8
branch 39 98 39.8
condition 14 32 43.7
subroutine 15 17 88.2
pod 9 9 100.0
total 271 426 63.6


line stmt bran cond sub pod time code
1             # *%) $Id: Comparison.pm,v 1.1.1.1 2004/05/25 01:34:52 scottz Exp $
2             #
3             # Copyright (c) 2004 Scott Zuyderduyn .
4             # All rights reserved. This program is free software; you
5             # can redistribute it and/or modify it under the same
6             # terms as Perl itself.
7              
8             package Bio::SAGE::Comparison;
9              
10             =pod
11              
12             =head1 NAME
13              
14             Bio::SAGE::Comparison - Compares data from serial analysis of gene expression (SAGE) libraries.
15              
16             =head1 SYNOPSIS
17              
18             use Bio::SAGE::Comparison;
19             $sage = Bio::SAGE::Comparison->new();
20              
21             =head1 DESCRIPTION
22              
23             This module provides several tools for comparing
24             data generated from serial analysis of gene
25             expression (SAGE) libraries.
26              
27             =head1 README
28              
29             B
30              
31             Serial analysis of gene expression (SAGE) is a molecular
32             technique for generating a near-global snapshot of a
33             cell population’s transcriptome. Briefly, the technique
34             extracts short sequences at defined positions of
35             transcribed mRNA. These short sequences are then paired
36             to form ditags. The ditags are concatamerized to form
37             long sequences that are then cloned. The cloned DNA is
38             then sequenced. Bioinformatic techniques are then
39             employed to determine the original short tag sequences,
40             and to derive their progenitor mRNA. The number of times
41             a particular tag is observed can be used to quantitate
42             the amount of a particular transcript. The original
43             technique was described by Velculescu et al. (1995) and
44             utilized an ~14bp sequence tag. A modified protocol
45             was introduced by Saha et al. (2002) that produced ~21bp
46             tags.
47              
48             B
49              
50             This module facilitates the comparison of SAGE libraries.
51             Specifically:
52              
53             1. Calculations for determining the statistical
54             significance of expression differences.
55             2. Dynamically convert longer-tag libraries to
56             a shorter type for comparison (e.g. comparing
57             a LongSAGE vs. a regular SAGE library).
58              
59             Both regular SAGE (14mer tag) and LongSAGE (21mer tag)
60             are supported by this module.
61              
62             Statistical significance in library comparisons is
63             calculated using the method described by Audic and
64             Claverie (1997). Code was generated by directly
65             porting the authors' original C source.
66              
67             B
68              
69             Velculescu V, Zhang L, Vogelstein B, Kinzler KW. (1995)
70             Serial analysis of gene expression. Science. 270:484-487.
71              
72             Saha S, Sparks AB, Rago C, Akmaev V, Wang CJ, Vogelstein B,
73             Kinzler KW, Velculescu V. (2002) Using the transcriptome
74             to annotate the genome. Nat. Biotechnol. 20:508-512.
75              
76             Audic S, Claverie JM. (1997) The significance of digital
77             gene expression profiles. Genome Res. 7:986-995.
78              
79             =head1 INSTALLATION
80              
81             Follow the usual steps for installing any Perl module:
82              
83             perl Makefile.PL
84             make test
85             make install
86              
87             =head1 PREREQUISITES
88              
89             None.
90              
91             =head1 CHANGES
92              
93             1.00 2004.05.24 - Initial release.
94              
95             =cut
96              
97 1     1   2204 use strict;
  1         2  
  1         29  
98 1     1   1021 use diagnostics;
  1         223068  
  1         154  
99 1     1   409 use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK $DEBUG );
  1         7  
  1         2780  
100              
101             require Exporter;
102             require AutoLoader;
103              
104             @ISA = qw( Exporter AutoLoader );
105             @EXPORT = qw();
106              
107             $VERSION = "1.00";
108              
109             my $PACKAGE = "Bio::SAGE::Comparison";
110              
111             =pod
112              
113             =head1 VARIABLES
114              
115             B
116              
117             =over 2
118              
119             I<$DEBUG>
120              
121             Prints debugging output if value if >= 1.
122              
123             =back
124              
125             =cut
126              
127             $DEBUG = 0; # set this flag to non-zero to enable debugging messages
128              
129             =pod
130              
131             =head1 CLASS METHODS
132              
133             =cut
134              
135             #######################################################
136             sub new {
137             #######################################################
138             =pod
139              
140             =head2 new
141              
142             Constructor for a new Bio::SAGE::Comparison object.
143              
144             B
145              
146             None.
147              
148             B
149              
150             my $sage = Bio::SAGE::Comparison->new();
151              
152             =cut
153              
154 1     1 1 19 my $this = shift;
155 1   33     8 my $class = ref( $this ) || $this;
156 1         2 my $self = {};
157 1         3 bless( $self, $class );
158              
159             # set instance variables
160              
161 1         3 return $self;
162            
163             }
164              
165             #######################################################
166             sub calculate_significance {
167             #######################################################
168             =pod
169              
170             =head2 calculate_significance $x, $y, $Nx, $Ny, <$signedValue>
171              
172             Determines the statistical significance of the difference
173             in tag count (expression) between two libraries. This
174             function uses the method described by Audic and
175             Claverie (1997). This method can be called on an
176             instantiated object, as well as statically.
177              
178             B
179              
180             I<$x,$y>
181              
182             The number of tags in the x- and y-axis
183             libraries, respectively.
184              
185             I<$Nx,$Ny>
186              
187             The total number of tags in the x- and y-axis
188             libraries, respectively.
189              
190             I<$signedValue> (optional)
191              
192             A boolean value (>=1 is FALSE). If this flag is
193             set to TRUE, downregulated comparisons will return
194             a both p-value and either +1, -1, or 0 to indicate
195             up/down/same-regulation (i.e. -1 if the expression
196             ratio of tags in the x-axis library(s) is greater
197             than that of the y-axis library(s)). This flag
198             is FALSE by default.
199              
200             B
201              
202             The p-value for the observation. A lower number is
203             more significant. Typically, observations with
204             p <= 0.05 are considered statistically significant.
205              
206             If $signedValue is set to TRUE, the function also
207             returns a 0, -1 or +1 to indicate same/down/up-regulation.
208              
209             B
210              
211             # the function is static, so it can be accessed directly
212             my $p = Bio::SAGE::Comparison::calculate_significance( 3, 10, 50000, 60000 );
213              
214             # or:
215             my ( $p, $sign ) = Bio::SAGE::Comparison::calculate_significance( 3, 10, 50000, 60000, 1 );
216             if( $p <= 0.05 ) {
217             if( $sign == +1 ) { print "Significantly upregulated.\n"; }
218             if( $sign == -1 ) { print "Significantly downregulated.\n"; }
219             if( $sign == 0 ) { die( "Same expression should never be significant!" ); }
220             }
221              
222             =cut
223              
224 5     5 1 11 my $x = shift;
225 5 50       11 if( !defined( $x ) ) { die( $PACKAGE . "::calculate_significance no arguments provided." ); }
  0         0  
226             # was this called from object?
227 5 50 33     164 if( !ref( $x ) && ref( $x ) eq $PACKAGE ) {
228 0         0 $x = shift; # next argument is actually what we're after
229             }
230 5         7 my $y = shift;
231 5         7 my $M = shift; # cf n1
232 5         6 my $N = shift; # cf n2
233 5   50     14 my $bSign = shift || 0;
234              
235 5         9 my $p = $M / ( $M+$N );
236              
237 5         15 my $thisproba = __betai( $x+1, $y+1, $p );
238 5         15 my $thisproba2 = __betai( $y+1, $x+1, 1.0-$p );
239              
240 5 50       15 if( $bSign >= 1 ) {
241 5         10 my $ratio1 = $x / $M;
242 5         8 my $ratio2 = $y / $N;
243 5         6 my $sign = 0;
244 5 100       12 if( $ratio1 > $ratio2 ) { $sign = -1; }
  2         4  
245 5 100       12 if( $ratio1 < $ratio2 ) { $sign = +1; }
  3         130  
246 5 100       24 return ( ( $thisproba < $thisproba2 ? ( 2*$thisproba ) : ( 2*$thisproba2 ) ), $sign );
247             }
248              
249 0 0       0 return ( $thisproba < $thisproba2 ? ( 2*$thisproba ) : ( 2*$thisproba2 ) );
250              
251             }
252              
253             =pod
254              
255             =head1 INSTANCE METHODS
256              
257             =cut
258              
259             #######################################################
260             sub load_library {
261             #######################################################
262             =pod
263              
264             =head2 load_library $handle
265            
266             Takes a Perl handle to SAGE library data and prepares
267             a tag data hash (format: [tag][count]).
268              
269             B
270              
271             I<$handle>
272            
273             A Perl handle (ie. filehandle, STDIN, etc.) that
274             can be used to read in SAGE library data.
275            
276             B
277              
278             A hashref containing tag sequences
279             as keys and the number of times that tag was
280             observed as the value.
281              
282             B
283              
284             my $sage = Bio::SAGE::Comparison->new();
285             my %data = %{$sage->load_library( *STDIN )};
286             # print data in descending order of tag count
287             map { print join( "\t", $_, $data{$_} ) . "\n"; } sort { $data{$b} <=> {$a} } keys %data;
288              
289             =cut
290            
291 2     2 1 1279 my $this = shift;
292 2         8 my $handle = shift;
293              
294 2         3 my %data;
295 2         25 while( my $line = <$handle> ) {
296 9         12 chomp( $line ); $line =~ s/\r//g;
  9         12  
297 9         39 my( $tag, $cnt ) = split( /[\s\t]+/, $line );
298 9         50 $data{$tag} = $cnt;
299             }
300              
301 2         25 return \%data;
302              
303             }
304              
305              
306             #######################################################
307             sub add_library {
308             #######################################################
309             =pod
310              
311             =head2 add_library $label, \%tagData
312              
313             Adds a library to this object.
314              
315             B
316              
317             I<$label>
318              
319             A unique label for this library data. This label can
320             then be used to refer to the data.
321              
322             I<\%tagData>
323              
324             A hashref containing the library data. The keys
325             are tag sequences, the values are tag counts. A
326             properly formatted hash can be created using
327             load_library.
328              
329             B
330              
331             my $sage = Bio::SAGE::Comparison->new();
332             my %data = %{$sage->load_library( *STDIN )};
333             # or alternatively:
334             my %data = ( 'AACGACTGTT' => 100,
335             'CAGATACAAG' => 23,
336             'AGATAAAGAC' => 45 );
337             $sage->add_library( 'MYLIB', \%data );
338              
339             =cut
340              
341 2     2 1 4 my $this = shift;
342 2   50     7 my $label = shift || die( $PACKAGE . "::add_library no library label was specified." );
343 2   50     9 my $pHash = shift || die( $PACKAGE . "::add_library no tag data was specified." );
344              
345 2         3 my $tagLength = -1;
346              
347 2         4 my $total_tags = 0;
348 2         10 foreach my $tag ( keys %$pHash ) {
349 9         14 my $len = length( $tag );
350 9 100       18 if( $tagLength == -1 ) {
351 2         3 $tagLength = $len;
352             } else {
353 7 50       17 if( $tagLength != $len ) { die( $PACKAGE . "::add_library tag length not consistent ($tagLength != $len)." ); }
  0         0  
354             }
355 9         49 $this->{'libraries'}->{$label}->{$tag} = $$pHash{$tag};
356 9         22 $total_tags += $$pHash{$tag};
357             }
358 2         8 $this->{'tag_length'}->{$label} = $tagLength;
359              
360 2         8 $this->{'totals'}->{$label} = $total_tags;
361              
362             }
363              
364             #######################################################
365             sub get_library_labels {
366             #######################################################
367             =pod
368              
369             =head2 get_library_labels
370              
371             Gets the labels that identify the currently added
372             libraries.
373              
374             B
375              
376             None.
377              
378             B
379              
380             An array of library labels.
381              
382             B
383              
384             my $sage = Bio::SAGE::Comparison->new();
385             my %data = %{$sage->load_library( *STDIN )};
386             $sage->add_library( 'MYLIB', \%data );
387             print "LIBRARY_NAMES: " . join( ", " , $sage->get_library_labels() ) . "\n";
388              
389             =cut
390              
391 1     1 1 3 my $this = shift;
392              
393 1         2 my @labels;
394 1         2 push( @labels, keys %{$this->{'libraries'}} );
  1         7  
395              
396 1         5 return @labels;
397              
398             }
399              
400             #######################################################
401             sub get_library_size {
402             #######################################################
403             =pod
404              
405             =head2 get_library_size $label
406              
407             Gets the total number of tags (the sum of all observed
408             tag counts for a library(s)).
409              
410             B
411              
412             I<$label>
413              
414             This can be: a) a string denoting the library label,
415             b) a reference to a string denoting the library
416             label, or c) an arrayref containing several
417             library labels that are pooled to calculate total
418             size.
419              
420             B
421              
422             The total number of observed tags in the library(s)
423             specified.
424              
425             B
426              
427             my $sage = Bio::SAGE::Comparison->new();
428             my %data = %{$sage->load_library( *STDIN )};
429             $sage->add_library( 'MYLIB', \%data );
430             print "LIBRARY_SIZE: " . $sage->get_library_size( 'MYLIB' ) . "\n";
431              
432             =cut
433              
434 2     2 1 18 my $this = shift;
435 2   50     7 my $label = shift || die( $PACKAGE . "::get_library_size no library specified." );
436              
437 2         3 my @labels;
438              
439             # make sure the library names variables are in array ref format
440 2 50       7 if( !ref( $label ) ) { # scalar (single library name)
441 2         4 push( @labels, $label );
442             } else {
443 0         0 my $type = ref( $label );
444 0 0       0 if( $type eq 'SCALAR' ) {
    0          
445 0         0 push( @labels, $$label );
446             }
447             elsif( $type eq 'ARRAY' ) {
448 0         0 push( @labels, @$label );
449             }
450             else {
451 0         0 die( $PACKAGE . "::get_library_size libraries cannot be reference to type " . $type );
452             }
453             }
454              
455 2 50       8 if( scalar( @labels ) == 1 ) {
456 2 50       9 if( !defined( $this->{'totals'}->{$labels[0]} ) ) {
457 0         0 die( $PACKAGE . "::get_library_size library $labels[0] not found." );
458             }
459 2         13 return $this->{'totals'}->{$labels[0]};
460             }
461              
462 0         0 my $total = 0;
463 0         0 foreach my $id ( @labels ) {
464 0 0       0 if( !defined( $this->{'totals'}->{$id} ) ) {
465 0         0 die( $PACKAGE . "::get_library_size library $id not found." );
466             }
467 0         0 $total += $this->{'totals'}->{$id};
468             }
469              
470 0         0 return $total;
471              
472             }
473              
474             #######################################################
475             sub get_number_tag_sequences {
476             #######################################################
477             =pod
478              
479             =head2 get_number_tag_sequences $label
480              
481             Gets the number of discrete tag sequences present in
482             the specified library(s).
483              
484             B
485              
486             I<$label>
487              
488             This can be: a) a string denoting the library label,
489             b) a reference to a string denoting the library
490             label, or c) an arrayref containing several
491             library labels that are pooled to calculate the
492             number of tag sequences.
493              
494             B
495              
496             The number of different tags in the library(s)
497             specified.
498              
499             B
500              
501             my $sage = Bio::SAGE::Comparison->new();
502             my %data = %{$sage->load_library( *STDIN )};
503             $sage->add_library( 'MYLIB', \%data );
504             print "TAG_SEQUENCES: " . $sage->get_number_tag_sequences( 'MYLIB' ) . "\n";
505              
506             =cut
507              
508 0     0 1 0 my $this = shift;
509 0   0     0 my $label = shift || die( $PACKAGE . "::get_number_tag_sequences no library specified." );
510              
511 0         0 my @labels;
512              
513             # make sure the library names variables are in array ref format
514 0 0       0 if( !ref( $label ) ) { # scalar (single library name)
515 0         0 push( @labels, $label );
516             } else {
517 0         0 my $type = ref( $label );
518 0 0       0 if( $type eq 'SCALAR' ) {
    0          
519 0         0 push( @labels, $$label );
520             }
521             elsif( $type eq 'ARRAY' ) {
522 0         0 push( @labels, @$label );
523             }
524             else {
525 0         0 die( $PACKAGE . "::get_number_tag_sequences libraries cannot be reference to type " . $type );
526             }
527             }
528              
529 0 0       0 if( scalar( @labels ) == 1 ) {
530 0 0       0 if( !defined( $this->{'libraries'}->{$labels[0]} ) ) {
531 0         0 die( $PACKAGE . "::get_number_tag_sequences library $labels[0] not found." );
532             }
533 0         0 return scalar( keys( %{$this->{'libraries'}->{$label}} ) );
  0         0  
534             }
535              
536 0         0 my %combo;
537 0         0 foreach my $id ( @labels ) {
538 0 0       0 if( !defined( $this->{'libraries'}->{$id} ) ) {
539 0         0 die( $PACKAGE . "::get_number_tag_sequences library $id not found." );
540             }
541 0         0 map { $combo{$_}++ } keys %{$this->{'libraries'}->{$id}};
  0         0  
  0         0  
542             }
543              
544 0         0 return scalar( keys( %combo ) );
545              
546             }
547              
548              
549             #######################################################
550             sub get_library_comparison {
551             #######################################################
552             =pod
553              
554             =head2 get_library_comparison $x_axis_libraries, $y_axis_libraries
555              
556             Creates a comparison between two libraries. This method
557             returns a hash reference containing the library data and
558             a p-value for determining statistical signifance.
559              
560             If the libraries contain tags of different sizes (i.e.
561             comparing a regular SAGE library vs. a LongSAGE library)
562             the data is converted to the shortest tag length of
563             the libraries specified prior to comparison.
564              
565             B
566              
567             I<$x_axis_libraries,$y_axis_libraries>
568              
569             Library labels for the x- and y-axis, respectively.
570              
571             This can be: a) a string denoting the library label,
572             b) a reference to a string denoting the library
573             label, or c) an arrayref containing several
574             library labels that are pooled in the comparison.
575              
576             B
577              
578             A hashref is returned where the keys are tag sequences,
579             and the values are hashrefs with the keys 'x'
580             (tags in x-axis library(s)), 'y' (tags in y-axis
581             library(s)), 'reg' (0,-1,+1 denoting same/down/up-regulation),
582             and 'p' (statistical significance).
583              
584             i.e. $HASH{$tag}->{'p'} = 0.05;
585              
586             B
587              
588             my $sage = Bio::SAGE::Comparison->new();
589             open( LIB1, "lib1.tags.txt" );
590             $sage->add_library( 'LIB1', $sage->load_library( *LIB1 ) );
591             close( LIB1 );
592             open( LIB2, "lib2.tags.txt" );
593             $sage->add_library( 'LIB2', $sage->load_library( *LIB2 ) );
594             close( LIB2 );
595             my %comparison = %{$sage->get_library_comparison( 'LIB1', 'LIB2' );
596             # or alternatively:
597             my %comparison = %{$sage->get_library_comparison( ['LIB1'], ['LIB2'] );
598             # print results in ascending order of p-value (more significant first)
599             foreach my $tag ( sort { $comparison{$a}->{'p'} <=> $comparison{$b}->{'p'} } keys %comparison ) {
600             print join( "\t", $tag, map { $comparison{$tag}->{$_} } ( 'x','y','reg','p' ) ) . "\n";
601             }
602              
603             =cut
604              
605 1     1 1 25 my $this = shift;
606 1   50     4 my $pX = shift || die( $PACKAGE . "::get_library_comparison no x-axis libraries were specified." );
607 1   50     5 my $pY = shift || die( $PACKAGE . "::get_library_comparison no y-axis libraries were specified." );
608              
609             # make sure the library names variables are in array ref format
610 1 50       4 if( !ref( $pX ) ) { # scalar (single library name)
611 1         4 $pX = [ $pX ];
612             } else {
613 0         0 my $type = ref( $pX );
614 0 0       0 if( $type eq 'SCALAR' ) {
    0          
615 0         0 $pX = [ $$pX ];
616             }
617             elsif( $type eq 'ARRAY' ) {
618             # good
619             }
620             else {
621 0         0 die( $PACKAGE . "::get_library_comparison x-axis libraries cannot be reference to type " . $type );
622             }
623             }
624 1 50       4 if( !ref( $pY ) ) { # scalar (single library name)
625 1         2 $pY = [ $pY ];
626             } else {
627 0         0 my $type = ref( $pY );
628 0 0       0 if( $type eq 'SCALAR' ) {
    0          
629 0         0 $pY = [ $$pY ];
630             }
631             elsif( $type eq 'ARRAY' ) {
632             # good
633             }
634             else {
635 0         0 die( $PACKAGE . "::get_library_comparison y-axis libraries cannot be reference to type " . $type );
636             }
637             }
638              
639             # what's the shortest tag length?
640 1         3 my $tag_length = -1;
641 1         2 foreach my $label ( @$pX ) {
642 1 50       5 if( !defined( $this->{'libraries'}->{$label} ) ) {
643 0         0 die( $PACKAGE . "::get_library_comparison unrecognized library name '" . $label . "'" );
644             }
645 1         3 my $len = $this->{'tag_length'}->{$label};
646 1 50       5 if( $tag_length == -1 ) { $tag_length = $len; next; }
  1         2  
  1         3  
647 0 0       0 if( $tag_length != $len ) {
648             # library has different size tags, will have to truncate
649 0 0       0 $tag_length = ( $tag_length < $len ) ? $tag_length : $len;
650             }
651             }
652 1         3 foreach my $label ( @$pY ) {
653 1 50       5 if( !defined( $this->{'libraries'}->{$label} ) ) {
654 0         0 die( $PACKAGE . "::get_library_comparison unrecognized library name '" . $label . "'" );
655             }
656 1         4 my $len = $this->{'tag_length'}->{$label};
657 1 50       4 if( $tag_length == -1 ) { $tag_length = $len; next; }
  0         0  
  0         0  
658 1 50       5 if( $tag_length != $len ) {
659             # library has different size tags, will have to truncate
660 0 0       0 $tag_length = ( $tag_length < $len ) ? $tag_length : $len;
661             }
662             }
663              
664             # prepare properly formatted tag data
665 1         2 my %data;
666 1         2 foreach my $label ( @$pX ) {
667 1         3 my $len = $this->{'tag_length'}->{$label};
668 1 50       216 if( $len != $tag_length ) {
669             # must be shorter - create truncated version
670 0         0 $data{$label} = $this->__truncateLibrary( $label, $tag_length );
671             } else {
672 1         7 $data{$label} = $this->{'libraries'}->{$label};
673             }
674             }
675 1         4 foreach my $label ( @$pY ) {
676 1         3 my $len = $this->{'tag_length'}->{$label};
677 1 50       3 if( $len != $tag_length ) {
678             # must be shorter - create truncated version
679 0         0 $data{$label} = $this->__truncateLibrary( $label, $tag_length );
680             } else {
681 1         5 $data{$label} = $this->{'libraries'}->{$label};
682             }
683             }
684              
685             # combine tags for all libraries
686 1         2 my %tags;
687 1         3 foreach my $label ( @$pX ) {
688 1         2 foreach my $tag ( keys %{$data{$label}} ) {
  1         5  
689 4         11 $tags{$tag}++;
690             }
691             }
692 1         3 foreach my $label ( @$pY ) {
693 1         2 foreach my $tag ( keys %{$data{$label}} ) {
  1         5  
694 5         10 $tags{$tag}++;
695             }
696             }
697              
698             # get total tags for each axis
699 1         2 my $M = 0;
700 1         3 my $N = 0;
701 1         3 foreach my $label ( @$pX ) { $M += $this->{'totals'}->{$label}; }
  1         3  
702 1         4 foreach my $label ( @$pY ) { $N += $this->{'totals'}->{$label}; }
  1         3  
703              
704             # now get values for each tag
705 1         2 my %RESULTS;
706              
707             my %SIGCACHE;
708              
709 1         5 foreach my $tag ( keys %tags ) {
710              
711 5         6 my $x = 0;
712 5   100     10 foreach my $label( @$pX ) { $x += $data{$label}->{$tag} || 0; }
  5         29  
713 5         9 my $y = 0;
714 5   50     8 foreach my $label( @$pY ) { $y += $data{$label}->{$tag} || 0; }
  5         24  
715              
716             # get significance value
717 5         6 my $p = 0;
718 5         6 my $reg = 0;
719 5 50       18 if( defined( $SIGCACHE{$x.'-'.$y} ) ) {
720 0         0 $p = $SIGCACHE{$x.'-'.$y}->{'p'};
721 0         0 $reg = $SIGCACHE{$x.'-'.$y}->{'reg'};
722             } else {
723 5         13 ( $p, $reg ) = calculate_significance( $x, $y, $M, $N, 1 );
724 5         25 $SIGCACHE{$x.'-'.$y}->{'p'} = $p;
725 5         39 $SIGCACHE{$x.'-'.$y}->{'reg'} = $reg;
726             }
727              
728 5         15 $RESULTS{$tag}->{'x'} = $x;
729 5         10 $RESULTS{$tag}->{'y'} = $y;
730 5         10 $RESULTS{$tag}->{'p'} = $p;
731 5         13 $RESULTS{$tag}->{'reg'} = $reg;
732              
733             }
734              
735 1         16 return \%RESULTS;
736              
737             }
738              
739             #######################################################
740             sub print_library_comparison {
741             #######################################################
742             =pod
743              
744             =head2 print_library_comparison \%comparison
745              
746             Prints a report based on the supplied comparison result
747             hash.
748              
749             B
750              
751             I<\%comparison>
752              
753             A properly formed hashref containing library
754             comparison results. This structure can be created
755             with get_library_comparison.
756              
757             A sample output looks like:
758              
759             Tag N(x) N(y) reg p
760             AGATCAAGAT 3388 50 -1 0
761             GATAACACTT 11481 186 -1 0
762             TATAACACCA 4 607 1 4.1136713480649e-306
763             ... etc.
764              
765             B
766              
767             my $sage = Bio::SAGE::Comparison->new();
768             # load library data
769             # ...
770             $sage->print_library_comparison( $sage->get_library_comparison( 'LIB1','LIB2' ) );
771              
772             =cut
773              
774 1     1 1 3 my $this = shift;
775 1   50     5 my $pResult = shift || die( $PACKAGE . "::print_library_comparison no comparison result hash was specified." );
776              
777 1         1 my %data = %{$pResult};
  1         7  
778              
779 1         8 print join( "\t", "Tag", "N(x)", "N(y)", "reg", "p" ) . "\n";
780              
781 1         8 foreach my $tag ( sort { $data{$a}->{'p'} <=> $data{$b}->{'p'} } keys %data ) {
  8         18  
782 5         9 print join( "\t", $tag, map { $data{$tag}->{$_} } ( 'x','y','reg','p' ) ) . "\n";
  20         77  
783             }
784              
785             }
786              
787             ###################################
788             # Audic and Claverie C->Perl Port #
789             ###################################
790              
791             my $MAXIT = 500;
792             my $EPS = 3.0E-30;
793             my $FPMIN = 1.0E-30;
794              
795             my @COF = ( 76.18009172947146, -86.50532032941677,
796             24.01409824083091, -1.231739572450155,
797             0.1208650973866179E-2,-0.5395239384953E-5 );
798              
799             sub __gammln {
800              
801 30     30   35 my $xx = shift;
802              
803 30         30 my $x = $xx;
804 30         33 my $y = $xx;
805              
806 30         39 my $tmp = $x + 5.5;
807 30         60 $tmp -= ( $x + 0.5 ) * log( $tmp );
808 30         94 my $ser = 1.000000000190015;
809 30         167 for( my $j = 0; $j <= 5; $j++ ) { $ser += $COF[$j] / ++$y; }
  180         373  
810              
811 30         222 return -$tmp + log( 2.5066282746310005 * $ser / $x );
812              
813             }
814              
815             sub __betai {
816              
817 10     10   12 my $a = shift;
818 10         12 my $b = shift;
819 10         11 my $x = shift;
820              
821 10 50 33     52 if( $x < 0.0 || $x > 1.0 ) {
822 0         0 die( "Bad x in routine betai." );
823             }
824              
825 10         11 my $bt;
826              
827 10 50 33     43 if( $x == 0.0 || $x == 1.0 ) {
828 0         0 $bt = 0.0;
829             } else {
830 10         25 $bt = exp( __gammln( $a+$b ) - __gammln( $a ) - __gammln( $b ) + $a*log( $x ) + $b*log( 1.0-$x ) );
831             }
832              
833 10 100       38 if( $x < ( $a+1.0 )/( $a+$b+2.0 ) ) {
834 5         15 return $bt * __betacf( $a, $b, $x ) / $a;
835             }
836              
837 5         14 return 1.0 - $bt * __betacf( $b, $a, 1.0-$x ) / $b;
838              
839             }
840              
841             sub __fabs {
842 530     530   921 my $x = shift;
843 530 100       2077 return ( $x < 0 ? -$x : $x );
844             }
845              
846             sub __betacf {
847              
848 10     10   90 my $a = shift;
849 10         12 my $b = shift;
850 10         12 my $x = shift;
851              
852 10         12 my $qab = $a + $b;
853 10         13 my $qap = $a + 1.0;
854 10         15 my $qam = $a - 1.0;
855 10         12 my $c = 1.0;
856 10         15 my $d = 1.0 - $qab * $x / $qap;
857              
858 10 50       27 if( __fabs( $d ) < $FPMIN ) { $d = $FPMIN; }
  0         0  
859              
860 10         11 $d = 1.0 / $d; # inverse d
861 10         12 my $h = $d;
862 10         11 my $m;
863 10         25 for( $m = 1; $m <= $MAXIT; $m++ ) {
864 104         131 my $m2 = 2 * $m;
865 104         567 my $aa = $m * ( $b-$m ) * $x / ( ( $qam + $m2 ) * ( $a + $m2 ) );
866              
867 104         122 $d = 1.0 + $aa*$d;
868 104 50       162 if( __fabs( $d ) < $FPMIN ) { $d = $FPMIN; }
  0         0  
869              
870 104         131 $c = 1.0 + $aa/$c;
871 104 50       276 if( __fabs( $c ) < $FPMIN ) { $c = $FPMIN; }
  0         0  
872              
873 104         183 $d = 1.0 / $d; # inverse d
874              
875 104         115 $h *= $d*$c;
876              
877 104         179 $aa = -($a+$m)*($qab+$m)*$x/(($a+$m2)*($qap+$m2));
878              
879 104         123 $d = 1.0 + $aa * $d;
880 104 50       148 if( __fabs( $d ) < $FPMIN ) { $d = $FPMIN; }
  0         0  
881              
882 104         126 $c = 1.0 + $aa / $c;
883 104 50       139 if( __fabs( $c ) < $FPMIN ) { $c = $FPMIN; }
  0         0  
884              
885 104         114 $d = 1.0 / $d; # inverse d;
886              
887 104         279 my $del = $d*$c;
888 104         109 $h *= $del;
889 104 100       180 if( __fabs( $del-1.0 ) < $EPS ) { last; }
  10         14  
890             }
891              
892 10 50       23 if( $m > $MAXIT ) {
893 0         0 die( "a or b too big, or MAXIT too small in __betacf" );
894             }
895              
896 10         30 return $h;
897              
898             }
899              
900             sub __truncateLibrary {
901              
902 0     0     my $this = shift;
903 0           my $label = shift;
904 0           my $length = shift;
905              
906 0           my %truncated;
907 0           my %tags = %{$this->{'libraries'}->{$label}};
  0            
908 0           foreach my $tag ( keys %tags ) {
909 0           my $trunctag = substr( $tag, 0, $length );
910 0           $truncated{$trunctag} += $tags{$tag};
911             }
912              
913 0           return \%truncated;
914              
915             }
916              
917             1;
918              
919             __END__