#!/usr/bin/perl


## Script written by Elisenda Feliu, January 2010 ##

## This script computes the P-value of finding at least l near-native decoys when selecting p decoys from a pool of d decoys containing n near-native ones. ##

use strict;
use warnings;

use Getopt::Long;

select(STDERR);

my ($help,$ndec,$n0,$pick,$atleast);

&GetOptions("d=s"   => \$ndec,
             "n=s" => \$n0,
             "p=s" => \$pick,
	     "l=s" => \$atleast,
             "h"     => \$help       );

unless (defined $ndec && defined $n0 && defined $pick && not defined $help){
   printf "** This script computes the P-value of finding at least l near-native decoys when selecting p decoys from a pool of d decoys containing n near-native ones.**\nUsage:\n\t./compute_prob.pl -d [Total number of decoys] -n [Number of near-native decoys in the set] -p [Number of decoys to pick] -l [Minimum number of hits]\n\nOption specification is required for all options but -l which defaults to 1.
          \n";
   exit;
}

if(not defined $atleast){ $atleast=1;}
my ($k,$prob,$min);


# Compute the probability of at least one hit at p predictions, for this type of family (depends on n0)
if($n0!=0){ 
	$min=&min($n0,$pick);
	$prob=0;
	foreach $k ($atleast..$min){   # prob of l guesses among p predictions. l must be lower than n0 and p
		$prob += &probability($n0,$ndec-$n0,$k,$pick);
	}
}

print  "The probability of getting at least $atleast hit taking $pick decoys from a set of $ndec from which there are $n0 near-native decoys is:\n$prob \n";

sub probability {
	my ($n0,$n1,$k,$m)=@_;
	my ($prob,$j);
	if($k>$m) {$prob=0; return($prob); }
	if($k>$n0){ $prob=0; return($prob);}
	if($k<$m-$n1){$prob=0; return($prob);}
	$prob=1;
	for($j=$n0;$j>=$n0-$k+1;$j=$j-1){
		$prob=$prob*$j;	
	}
	for($j=$n0+$n1;$j>=$n1+$k+1;$j=$j-1){
		$prob=$prob*($j-$m)/$j;	
	}
	for($j=$n1+$k;$j>=$n1+1;$j=$j-1){
		$prob=$prob/$j;
	}

 	for($j=$m;$j>=$m-$k+1;$j=$j-1){
 		$prob=$prob*$j;	
 	}
	$prob=$prob/&factorial($k);
	return($prob);	
}

sub factorial {
	my ($n)=@_;
	if($n<0){ print "Negative factorial \n"; exit}
	my $i;
	my $prod;
	if($n==0 || $n==1){
		$prod=1;
	}
	else{
		$prod=1;
		for($i=2;$i<=$n;$i++){ 	$prod=$prod*$i;}
	}
	return($prod);
}

sub min {
	my @n=@_;
	my $min;
	if($n[0]>$n[1]){ $min=$n[1];}
	else{ $min=$n[0];}
	return($min);
}

