27 #include <gsl/gsl_cdf.h> 28 #include <gsl/gsl_randist.h> 29 #include <gsl/gsl_histogram.h> 33 #include <gsl/gsl_errno.h> 34 #include <gsl/gsl_math.h> 35 #include <gsl/gsl_roots.h> 48 template <
class T,
class T2>
49 typename std::iterator_traits<T>::value_type
kahansum(T begin, T end, T2 other) {
50 typedef typename std::iterator_traits<T>::value_type real;
52 real running_error = real();
54 for ( ; begin != end; ++begin) {
55 real difference = *begin - running_error;
56 real temp = sum + difference;
57 running_error = (temp - sum) - difference;
69 unsigned int nTrials, gsl_rng *r,
float &lBound,
float &uBound )
72 values.resize(nTrials);
80 vMin=std::numeric_limits<float>::max();
84 v=gsl_ran_poisson(r,lambda1)/(float)std::max(gsl_ran_poisson(r,lambda2),1u);
85 vMin=std::min(v,vMin);
86 vMax=std::max(v,vMax);
93 const unsigned int nBins=sqrt(values.size())/2.0f;
94 gsl_histogram *h=gsl_histogram_alloc(nBins);
95 gsl_histogram_set_ranges_uniform(h,vMin,vMax);
97 gsl_histogram_increment(h,v);
102 for(
auto ui=0u;ui<nBins;ui++)
103 df[ui]=gsl_histogram_get(h,ui);
105 gsl_histogram_free(h);
124 auto alphaIt = std::lower_bound(df.begin(),df.end(),alpha);
126 if(alphaIt == df.end())
129 unsigned int offset = std::distance(df.begin(),alphaIt);
133 float dy= df[offset] - df[offset-1];
134 float dx= (vMax-vMin)/(
float)df.size();
136 uBound = (alpha-df[offset-1])*dx/dy + (offset-1)*dx + vMin;
144 alphaIt = std::upper_bound(df.begin(),df.end(),1.0-alpha);
145 if(alphaIt==df.begin())
150 offset = std::distance(df.begin(),alphaIt);
152 if(offset < df.size()-1)
154 float dy= df[offset] - df[offset-1];
155 float dx= (vMax-vMin)/(
float)df.size();
157 lBound = ((1.0-alpha)-df[offset])*dx/dy + offset*dx +vMin;
165 ASSERT(lBound<=lambda1/lambda2);
166 ASSERT(uBound>=lambda1/lambda2);
174 unsigned int nTrials, gsl_rng *r,
float &lBound,
float &uBound )
176 vector<float> values;
177 values.resize(nTrials);
181 vMin=std::numeric_limits<float>::max();
183 for(
auto &v : values)
186 v1=gsl_ran_poisson(r,lambda1);
187 v2=gsl_ran_poisson(r,lambda2);
190 vMin=std::min(v,vMin);
191 vMax=std::max(v,vMax);
195 const unsigned int nBins=sqrt(values.size())/2.0f;
196 gsl_histogram *h=gsl_histogram_alloc(nBins);
197 gsl_histogram_set_ranges_uniform(h,vMin,vMax);
199 gsl_histogram_increment(h,v);
206 for(
auto ui=0u;ui<nBins;ui++)
207 df[ui]=gsl_histogram_get(h,ui);
209 gsl_histogram_free(h);
228 auto alphaIt = std::lower_bound(df.begin(),df.end(),alpha);
230 if(alphaIt == df.end())
233 unsigned int offset = std::distance(df.begin(),alphaIt);
237 float dy= df[offset] - df[offset-1];
238 float dx= (vMax-vMin)/(
float)df.size();
240 uBound = (alpha-df[offset-1])*dx/dy + (offset-1)*dx + vMin;
248 alphaIt = std::upper_bound(df.begin(),df.end(),1.0-alpha);
249 if(alphaIt==df.begin())
254 offset = std::distance(df.begin(),alphaIt);
256 if(offset < df.size()-1)
258 float dy= df[offset] - df[offset-1];
259 float dx= (vMax-vMin)/(
float)df.size();
261 lBound = ((1.0-alpha)-df[offset])*dx/dy + offset*dx +vMin;
276 unsigned int nTrials, gsl_rng *r,
float &lBound,
float &uBound )
278 vector<float> values;
279 values.resize(nTrials);
283 vMin=std::numeric_limits<float>::max();
285 for(
auto &v : values)
287 v=(gsl_ran_gaussian(r,sqrt(var1))+mu1)/
288 std::max(gsl_ran_gaussian(r,sqrt(var2))+mu2,1.0);
289 vMin=std::min(v,vMin);
290 vMax=std::max(v,vMax);
297 const unsigned int nBins=sqrt(values.size())/2.0f;
298 gsl_histogram *h=gsl_histogram_alloc(nBins);
299 gsl_histogram_set_ranges_uniform(h,vMin,vMax);
301 gsl_histogram_increment(h,v);
306 for(
auto ui=0u;ui<nBins;ui++)
307 df[ui]=gsl_histogram_get(h,ui);
309 gsl_histogram_free(h);
328 auto alphaIt = std::lower_bound(df.begin(),df.end(),alpha);
330 if(alphaIt == df.end())
333 unsigned int offset = std::distance(df.begin(),alphaIt);
337 float dy= df[offset] - df[offset-1];
338 float dx= (vMax-vMin)/(
float)df.size();
340 uBound = (alpha-df[offset-1])*dx/dy + (offset-1)*dx + vMin;
348 alphaIt = std::upper_bound(df.begin(),df.end(),1.0-alpha);
349 if(alphaIt==df.begin())
354 offset = std::distance(df.begin(),alphaIt);
356 if(offset < df.size()-1)
358 float dy= df[offset] - df[offset-1];
359 float dx= (vMax-vMin)/(
float)df.size();
361 lBound = ((1.0-alpha)-df[offset])*dx/dy + offset*dx +vMin;
395 epsilon+= gsl_ran_poisson_pdf(i,sigGuess+zr->
lambdaBack);
402 return epsilon-zr->
alpha;
424 float xHi=std::max((
float)observation,lambdaBack)*5.0f;
427 gsl_root_fsolver *s = gsl_root_fsolver_alloc (gsl_root_fsolver_brent);
428 gsl_root_fsolver_set (s, &F, xLow,xHi);
431 const unsigned int MAXITS=1000;
437 gsl_root_fsolver_iterate (s);
438 xLow = gsl_root_fsolver_x_lower (s);
439 xHi = gsl_root_fsolver_x_upper (s);
440 status = gsl_root_test_interval (xLow, xHi,
443 if (status == GSL_SUCCESS)
445 }
while(status ==GSL_CONTINUE && it < MAXITS);
448 estimate = gsl_root_fsolver_root (s);
449 gsl_root_fsolver_free(s);
452 if(estimate<0 || isnan(estimate) || it >=MAXITS)
461 void cumTrapezoid(
const vector<T> &x,
const vector<T> &vals, vector<T> &res)
463 ASSERT(vals.size() ==x.size());
466 sumVals.resize(vals.size()+1);
470 kahansum(vals.begin(),vals.begin()+vals.size(),sumVals.begin()+1);
472 res.resize(x.size());
474 for(
auto ui=1u;ui<vals.size();ui++)
475 res[ui] = 0.5*(sumVals[ui-1] + sumVals[ui])*(x[ui]-x[ui-1]);
489 double a = sqrt(x*x/varX + 1.0/varY);
490 double b =muX/varX*x + muY/varY;
491 double c = muX*muX/varX + muY*muY/varY;
492 double lnD = (b*b - c*a*a)/(2.0*a*a);
498 double theta1 = 0.5*(1.0+erf(bDivA/sqrt(2.0)));
499 double theta2 = 0.5*(1.0+erf(-bDivA/sqrt(2.0)));
501 double p1 = b*d/(a*a*a)*1/(sqrt(2*
M_PI*varX*varY))*(theta1-theta2);
503 double p2 = 1.0/(a*a*
M_PI*sqrt(varX*varY))*exp(-c/2.0);
511 ASSERT(alpha>0 && alpha < 1);
513 float a = gsl_cdf_chisq_Pinv(alpha,1);
516 lBound = counts + a/2.0 - sqrtf(a*(counts+a/4.0));
517 uBound = counts + a/2.0 + sqrtf(a*(counts+a/4.0));
614 bool runConfidenceTests()
616 using std::make_pair;
624 map<pair<float,float>,
float> skelMap;
630 skelMap[make_pair(100,100)]=141;
631 skelMap[make_pair(1,10)]=15;
636 for(
auto v : skelMap)
646 ASSERT(fabs(uBound - res)/uBound < 0.5);
653 map<pair<float,float>, pair<float,float> > confMap;
654 confMap[make_pair(1,10)]= make_pair(3.659,19.17);
656 const float ALPHA=0.99;
657 for(
auto &v : confMap)
661 v.first.second,ALPHA,high),
"Zech UB");
663 v.first.second,1.0-ALPHA,low),
"Zech LB");
665 auto confPair = v.second;
666 TEST(low < confPair.first+0.5f,
"Low confidence bound");
667 TEST(high > confPair.second-0.5f,
"High confidence bound");
675 map<unsigned int,pair<float,float> > poissConfVals;
677 poissConfVals[1] = make_pair(0.1765,5.6649);
678 poissConfVals[3] = make_pair(1.0203,8.8212);
679 poissConfVals[5] = make_pair(2.1357,11.7058);
686 for(
auto v : poissConfVals)
688 float lPBound,uPBound;
690 ASSERT(fabs(v.second.first -lPBound) < 0.01);
691 ASSERT(fabs(v.second.second - uPBound) < 0.01);
700 const unsigned int NREPEATS=250;
701 for(
auto ui=0;ui<NREPEATS;ui++)
704 v1=gsl_ran_poisson(rng,360);
705 v2=gsl_ran_poisson(rng,125);
714 0.95,1000,rng,lBound,uBound);
bool numericalEstimateSkellamConf(float lambda1, float lambda2, float alpha, unsigned int nTrials, gsl_rng *r, float &lBound, float &uBound)
Brute-force the confidence bounds of a skellam distribution.
double gauss_ratio_pdf(double x, double muX, double muY, double varX, double varY)
bool zechConfidenceLimits(float lambdaBack, unsigned int observation, float alpha, float &estimate)
Provides a best estimate for true signal when true signal, background.
void cumTrapezoid(const vector< T > &x, const vector< T > &vals, vector< T > &res)
double zechRoot(double sigGuess, void *params)
std::iterator_traits< T >::value_type kahansum(T begin, T end, T2 other)
void poissonConfidenceObservation(float counts, float alpha, float &lBound, float &uBound)
Obtain poisson confidence limits for the mean of a poisson distribution.
bool numericalEstimatePoissRatioConf(float lambda1, float lambda2, float alpha, unsigned int nTrials, gsl_rng *r, float &lBound, float &uBound)
Brute-force poisson ratio confidence estimator. Returns the confidence interval in the estimate of th...
bool numericalEstimateGaussRatioConf(float mu1, float mu2, float var1, float var2, float alpha, unsigned int nTrials, gsl_rng *r, float &lBound, float &uBound)
Brute-force guassian ratio confidence estimator.
gsl_rng * getRng() const
Obtain a GSL random number generator.