#ifndef CONFIDENCE_H
#define CONFIDENCE_H

#include <gsl/gsl_rng.h>



//!Obtain poisson confidence limits for the mean of a poisson distribution
//  uses chi-square estimates from
//     http://ms.mcmaster.ca/peter/s743/poissonalpha.html 
// - Counts: Observed counts
// - alpha : confidence level for bounds (0->1, exclusive)
// - lBound : lower bound
// - uBound : upper bound
// - Note upper and lower bounds are absolutes, not delta.
// - Poisson confidence limits of poisson rate parameter, given some observed counts
// - technically "counts" is integral
void poissonConfidenceLimit(float counts, float alpha, float &lBound, float &uBound);

//!Brute-force poisson ratio confidence estimator.
/*!Performs monte-carlo trials to determine the distribution of Z=X/Y.
 where X~Poisson(L1), Y~Poisson(L2)
 Biased, as it enforces  1, in the denominator of L1/L2  (ie L2=0 has p=0)
 returns false if either bound could not be computed
 - lambda1  : Poisson rate 1 (must be +ve)
 - lambda2 : Poisson rate 2 (must be +ve)
 - alpha : confidence interval in distribution
 - nTrials : number of computations of Z.
 - lBound : returned lower bound at confidence alpha. This is interpolated, so is a real number
 - uBound : returned upper bound at confidence alpha. This is interpolated, so is a real number. 

 Note that the estimator seems to slightly biased to the number of trials, and needs to be improved. 
*/
bool numericalEstimatePoissRatioConf(float lambda1,float lambda2, float alpha, 
			unsigned int nTrials, gsl_rng *r, float &lBound, float &uBound );


//!Brute-force guassian ratio confidence estimator.
/*!Performs monte-carlo trials to determine the distribution of Z=X/Y.
 where X~Gaussian(L1), Y~max(Gaussian(L2),1)
 
 Biased, as it enforces  1, in the denominator of L1/L2  (ie L2=0 has p=0)
 returns false if either bound could not be computed
 - mu1  : Mean 1 (must be +ve)
 - mu2 : Mean 2 (must be +ve)
 - var1  : Variance 1 (must be +ve)
 - var2 : Variance 2 (must be +ve)
 - alpha : confidence interval in distribution
 - nTrials : number of computations of Z.
 - lBound : returned lower bound at confidence alpha
 - uBound : returned upper bound at confidence alpha

 Note that the estimator seems to biased to the number of trials, and needs to be improved.
*/
bool numericalEstimateGaussRatioConf(float mu1,float mu2,float var1, float var2, float alpha, 
			unsigned int nTrials, gsl_rng *r,float &lBound, float &uBound );

//!Brute-force the confidence bounds of a skellam distribution
/*!Performs monte-carlo trials to determine Z = X - Y, where X, Y are poisson (Lambda1, Lambda2).
 - Lambda1 : poisson rate for X
 - Lambda2: poisson rate for Y
 - alpha : confidence bound
 - nTrials : number of computations of Z.
 - lBound : returned lower bound at confidence alpha. This is interpolated, so is a real number
 - uBound : returned upper bound at confidence alpha. This is interpolated, so is a real number
*/
bool numericalEstimateSkellamConf(float lambda1, float lambda2, float alpha,
			unsigned int nTrials, gsl_rng *r, float &lBound,float &uBound);

//!Provides a best estimate for true signal when true signal, background
// are poisson distributed, summed together, you have observed the sum,
// but want to subtract the background.
/*! 
  Nuclear Instruments and Methods in Physics Research A, 1989 608-610
   "Upper limits in Experiments with Background or Measurement Errors"
 * This is numerically unstable for large counts
 * A similar problem is tackled by Bityukov, arxiv:hep-ex/0108020v1
    Equation 3.5, but is less numerically stable

 lambdaBack : background rate
 observation : Observed signal+background
 alpha : confidence parameter, (0,1)
 estimate : estimate for signal at confidence bound, specified by alpha
 Returns true if calculation succeeds, false otherwise. 
 	Note :this involves a root-finding approach, so may be slow

 NOTE: may not be numerically stable for high lambdaback/observation,
 or lambdaback>>observation. This may cause GSL to error out.
*/
bool zechConfidenceLimits(float lambdaBack, unsigned int observation, float alpha,
				float &estimate);

#ifdef DEBUG
bool runConfidenceTests();
#endif

#endif
