BayesianAnalysisToolkit  0.9.3
Functions | Variables
BCMath Namespace Reference

Some useful mathematic functions. More...

Functions

double LogGaus (double x, double mean=0, double sigma=1, bool norm=false)
 
double LogPoisson (double x, double par)
 
double ApproxBinomial (int n, int k, double p)
 
double LogApproxBinomial (int n, int k, double p)
 
double LogBinomFactor (int n, int k)
 
double ApproxLogFact (double x)
 
double LogNoverK (int n, int k)
 
double LogFact (int n)
 
int Nint (double x)
 
double LogBreitWignerNonRel (double x, double mean, double Gamma, bool norm=false)
 
double LogBreitWignerRel (double x, double mean, double Gamma)
 
double LogChi2 (double x, int n)
 
double LogVoigtian (double x, double sigma, double gamma)
 
double LogGammaPDF (double x, double alpha, double beta)
 
double LogLogNormal (double x, double mean=0, double sigma=1)
 
void RandomChi2 (std::vector< double > &randoms, int K)
 
TH1D * ECDF (const std::vector< double > &data)
 
std::vector< int > longestRuns (const std::vector< bool > &bitStream)
 
std::vector< double > longestRunsChi2 (const std::vector< double > &yMeasured, const std::vector< double > &yExpected, const std::vector< double > &sigma)
 
double longestRunFrequency (unsigned int longestObserved, unsigned int nTrials)
 
double SplitGaussian (double *x, double *par)
 
void CacheFactorial (unsigned int n)
 
double Rvalue (const std::vector< double > &chain_means, const std::vector< double > &chain_variances, const unsigned &chain_length, const bool &strict=true) throw (std::invalid_argument, std::domain_error)
 
double chi2 (double *x, double *par)
 
double longestRunFrequency (unsigned longestObserved, unsigned int nTrials)
 
p value methods
double CorrectPValue (const double &pvalue, const unsigned &npar, const unsigned &nobservations) throw (std::domain_error)
 
double FastPValue (const std::vector< unsigned > &observed, const std::vector< double > &expected, unsigned nIterations=1e5, unsigned seed=0) throw (std::invalid_argument)
 

Variables

static unsigned int nCacheFact = 10000
 
static double * logfact = 0
 

Detailed Description

Some useful mathematic functions.

Author
Daniel Kollar
Kevin Kröninger
Jing Liu
Frederik Beaujean
Version
1.0
Date
08.2008 A namespace which encapsulates some mathematical functions necessary for BAT.

Function Documentation

double BCMath::ApproxBinomial ( int  n,
int  k,
double  p 
)

Calculates Binomial probability using approximations for factorial calculations if calculation for number greater than 20 required using the BCMath::ApproxLogFact function.

Definition at line 73 of file BCMath.cxx.

74 {
75  return exp(LogApproxBinomial(n, k, p));
76 }
double BCMath::ApproxLogFact ( double  x)

Calculates natural logarithm of the n-factorial (n!) using Srinivasa Ramanujan approximation log(n!) = n*log(n) - n + log(n*(1.+4.*n*(1.+2.*n)))/6. + log(PI)/2. if n > 20. If n <= 20 it uses BCMath::LogFact to calculate it exactly.

Definition at line 125 of file BCMath.cxx.

126 {
127  if (x > BCMath::nCacheFact)
128  return x * log(x) - x + log(x * (1. + 4. * x * (1. + 2. * x))) / 6. + log(M_PI) / 2.;
129 
130  else
131  return LogFact(static_cast<int>(floor(x + 0.5f)));
132 }
void BCMath::CacheFactorial ( unsigned int  n)

Cache factorials for first

  • n integers. The cache is filled upon first call of LogFact().

Definition at line 169 of file BCMath.cxx.

170 {
171  nCacheFact = n;
172 }
double BCMath::chi2 ( double *  x,
double *  par 
)

Definition at line 312 of file BCMath.cxx.

313 {
314  return ROOT::Math::chisquared_pdf(x[0], par[0]);
315 }
double BCMath::CorrectPValue ( const double &  pvalue,
const unsigned &  npar,
const unsigned &  nobservations 
)
throw (std::domain_error
)

Correct a p value by transforming to a chi^2 with dof=nobservations, then back to a pvalue with dof reduced by number of fit parameters.

Parameters
pvalueThe p value to correct.
nparThe number of fit parameters.
nobservationsThe number of data points.
Returns
corrected p value

Definition at line 665 of file BCMath.cxx.

666 {
667  // avoid pathologies
668  if (pvalue < 0 or pvalue > 1)
669  throw std::domain_error(Form("BCMath::CorrectPValue: pvalue (%g) out of range", pvalue));
670 
671  if (pvalue < 1e-150)
672  return 0;
673 
674  // dof = nobs - npar
675  if (npar >= nobservations)
676  throw std::domain_error(Form("BCMath::CorrectPValue: "
677  "npar exceeds nobservations, %u vs %u", npar, nobservations));
678 
679  // convert upper-tail p value to a chi squared
680  const double chi2 = ROOT::Math::chisquared_quantile_c(pvalue, nobservations);
681 
682  // corrected degrees of freedom
683  const unsigned dof = nobservations - npar;
684 
685  // transform back to p value
686  return TMath::Prob(chi2, dof);
687 }
TH1D * BCMath::ECDF ( const std::vector< double > &  data)

Calculate the empirical cumulative distribution function for one dimensional data vector. For consistency, the ECDF of value smaller than the minimum observed (underflow bin) is zero, and for larger than maximum (overflow bin) it is one.

Parameters
datathe observations
Returns
histogram with normalized ECDF

Definition at line 333 of file BCMath.cxx.

334 {
335  int N = data.size();
336 
337  std::set<double> uniqueObservations;
338  // sort and filter out multiple instances
339  for (int i = 0; i < N; ++i)
340  uniqueObservations.insert(data[i]);
341 
342  // extract lower edges for CDF histogram
343  unsigned nUnique = uniqueObservations.size();
344  std::vector<double> lowerEdges(nUnique);
345 
346  // traverse the set
347  std::set<double>::iterator iter;
348  int counter = 0;
349  for (iter = uniqueObservations.begin(); iter != uniqueObservations.end(); ++iter) {
350  lowerEdges[counter] = *iter;
351  counter++;
352  }
353 
354  // create histogram where
355  // lower edge of first bin = min. data
356  // upper edge of last bin = max. data
357  TH1D * ECDF = new TH1D("ECDF", "Empirical cumulative distribution function", nUnique - 1, &lowerEdges[0]);
358 
359  // fill the data in to find multiplicities
360  for (int i = 0; i < N; ++i)
361  ECDF -> Fill(data[i]);
362 
363  // just in case, empty the underflow
364  ECDF -> SetBinContent(0, 0.0);
365 
366  // construct the ecdf
367  for (int nBin = 1; nBin <= ECDF->GetNbinsX(); nBin++) {
368  double previousBin = ECDF -> GetBinContent(nBin - 1);
369  double thisBin = ECDF -> GetBinContent(nBin) / double(N);
370  ECDF -> SetBinContent(nBin, thisBin + previousBin);
371 
372  // the uncertainty is only correctly estimated in the model
373  ECDF -> SetBinError(nBin, 0.0);
374  }
375 
376  // set the endpoint to 1, so all larger values are at CDF=1
377  ECDF -> SetBinContent(ECDF->GetNbinsX() + 1, 1.);
378 
379  // adjust for nice plotting
380  ECDF -> SetMinimum(0.);
381  ECDF -> SetMaximum(1.);
382 
383  return ECDF;
384 }
double BCMath::FastPValue ( const std::vector< unsigned > &  observed,
const std::vector< double > &  expected,
unsigned  nIterations = 1e5,
unsigned  seed = 0 
)
throw (std::invalid_argument
)

Calculate the p value using fast MCMC for a histogram and the likelihood as test statistic. The method is explained in the appendix of http://arxiv.org/abs/1011.1674

Parameters
observedThe counts of observed events
expectedThe expected number of events (Poisson means)
nIterationsControls number of pseudo data sets
seedSet to nonzero value for reproducible results.
Returns
The p value

Definition at line 690 of file BCMath.cxx.

692 {
693  size_t nbins = observed.size();
694  if (nbins != expected.size())
695  {
696  throw std::invalid_argument(Form("BCMath::FastPValue: "
697  "size of expected and observed do not match, %u vs %u", unsigned(expected.size()), unsigned(nbins)));
698  }
699 
700  // temporary histogram to be modified in each MCMC step
701  std::vector<unsigned> histogram(nbins, 0);
702 
703  // fix seed to iterations for reproducible results
704  TRandom3 rng(seed);
705 
706  // keep track of log of probability and count data sets with larger value
707  double logp = 0;
708  double logp_start = 0;
709  int counter_pvalue = 0;
710 
711  // define starting distribution as histogram with most likely entries
712  for (size_t ibin = 0; ibin < nbins; ++ibin) {
713 
714  // get the number of expected events
715  double yexp = expected[ibin];
716 
717  //most likely observed value = int(expected value)
718  histogram[ibin] = size_t(yexp);
719 
720  // calculate test statistic (= likelihood of entire histogram) for starting distr.
721  logp += LogPoisson(size_t(yexp), yexp);
722 
723  //statistic of the observed data set
724  logp_start += LogPoisson(observed[ibin], yexp);
725  }
726 
727  // loop over iterations
728  for (unsigned iiter = 0; iiter < nIterations; ++iiter) {
729  // loop over bins
730  for (size_t ibin = 0; ibin < nbins; ++ibin) {
731  // random step up or down in statistics for this bin
732  double ptest = rng.Rndm() - 0.5;
733 
734  // increase statistics by 1
735  if (ptest > 0) {
736  // calculate factor of probability
737  double r = expected[ibin] / double(histogram[ibin] + 1);
738 
739  // walk, or don't (this is the Metropolis part)
740  if (rng.Rndm() < r) {
741  ++histogram[ibin];
742  logp += log(r);
743  }
744  }
745 
746  // decrease statistics by 1
747  else if (ptest <= 0 && histogram[ibin] > 0) {
748  // calculate factor of probability
749  double r = double(histogram[ibin]) / expected[ibin];
750 
751  // walk, or don't (this is the Metropolis part)
752  if (rng.Rndm() < r) {
753  --histogram[ibin];
754  logp += log(r);
755  }
756  }
757  } // end of looping over bins
758 
759  // increase counter
760  if (logp <= logp_start)
761  ++counter_pvalue;
762  // handle the case where a -b +b > a because of precision loss
763  else if (logp_start && logp != logp_start && fabs((logp - logp_start) / logp_start) < 1e-15)
764  ++counter_pvalue;
765 
766  } // end of looping over iterations
767 
768  // calculate p-value
769  return double(counter_pvalue) / nIterations;
770 }
double BCMath::LogApproxBinomial ( int  n,
int  k,
double  p 
)

Calculates natural logarithm of the Binomial probability using approximations for factorial calculations if calculation for number greater than 20 required using the BCMath::ApproxLogFact function.

Definition at line 80 of file BCMath.cxx.

81 {
82  // check p
83  if (p == 0)
84  return -1e99;
85 
86  else if (p == 1)
87  return 0;
88 
89  // switch parameters if n < k
90  if (n < k) {
91  int a = n;
92  n = k;
93  k = a;
94  }
95 
96  return LogBinomFactor(n, k) + (double) k * log(p) + (double) (n - k) * log(1. - p);
97 }
double BCMath::LogBinomFactor ( int  n,
int  k 
)

Calculates natural logarithm of the Binomial factor "n over k" using approximations for factorial calculations if calculation for number greater than 20 required using the BCMath::ApproxLogFact function. Even for large numbers the calculation is performed precisely, if n-k < 5

Definition at line 101 of file BCMath.cxx.

102 {
103  // switch parameters if n < k
104  if (n < k) {
105  int a = n;
106  n = k;
107  k = a;
108  }
109 
110  if (n == k || k == 0)
111  return 0.;
112  if (k == 1 || k == n - 1)
113  return log((double) n);
114 
115  // if no approximation needed
116  if ( n < BCMATH_NFACT_ALIMIT || (n < (int) BCMath::nCacheFact && (n - k) < 10) )
117  return LogNoverK(n, k);
118 
119  // calculate final log(n over k) using approximations if necessary
120  return ApproxLogFact((double)n) - ApproxLogFact((double)k) - ApproxLogFact((double)(n - k));
121 }
double BCMath::LogBreitWignerNonRel ( double  x,
double  mean,
double  Gamma,
bool  norm = false 
)

Calculates the logarithm of the non-relativistic Breit-Wigner distribution.

Definition at line 225 of file BCMath.cxx.

226 {
227  double bw = log(Gamma) - log((x - mean) * (x - mean) + Gamma*Gamma / 4.);
228 
229  if (norm)
230  bw -= log(2. * M_PI);
231 
232  return bw;
233 }
double BCMath::LogBreitWignerRel ( double  x,
double  mean,
double  Gamma 
)

Definition at line 237 of file BCMath.cxx.

238 {
239  return -log((x*x - mean*mean) * (x*x - mean*mean) + mean*mean * Gamma*Gamma);
240 }
double BCMath::LogChi2 ( double  x,
int  n 
)

Calculates the logarithm of chi square function: chi2(double x; size_t n)

Definition at line 244 of file BCMath.cxx.

245 {
246  if (x < 0) {
247  BCLog::OutWarning("BCMath::LogChi2 : parameter cannot be negative!");
248  return -1e99;
249  }
250 
251  if (x == 0 && n == 1) {
252  BCLog::OutWarning("BCMath::LogChi2 : returned value is infinity!");
253  return 1e99;
254  }
255 
256  double nOver2 = ((double) n) / 2.;
257 
258  return (nOver2 - 1.) * log(x) - x / 2. - nOver2 * log(2) - log(TMath::Gamma(nOver2));
259 }
double BCMath::LogFact ( int  n)

Calculates natural logarithm of the n-factorial (n!)

Definition at line 135 of file BCMath.cxx.

136 {
137  // return NaN for negative argument
138  if (n<0)
139  return std::numeric_limits<double>::quiet_NaN();
140 
141  // cache the factorials on first call
142  if ( !BCMath::logfact) {
143  BCMath::logfact = new double[BCMath::nCacheFact+1];
144  double tmplogfact = 0;
145  BCMath::logfact[0] = tmplogfact;
146  for (unsigned int i=1; i<=BCMath::nCacheFact; i++) {
147  tmplogfact += log((double) i);
148  BCMath::logfact[i] = tmplogfact;
149  }
150  }
151 
152  // return cached value if available
153  if (n <= (int) BCMath::nCacheFact)
154  return BCMath::logfact[n];
155 
156  // calculate factorial starting from the highest cached value
157  double ln(0.);
158  if (BCMath::logfact)
160 
161  for (int i = BCMath::nCacheFact+1; i <= n; i++)
162  ln += log((double) i);
163 
164  return ln;
165 }
double BCMath::LogGammaPDF ( double  x,
double  alpha,
double  beta 
)

Returns the log of the Gamma PDF.

Definition at line 273 of file BCMath.cxx.

274 {
275  return alpha * log(beta) - TMath::LnGamma(alpha) + (alpha - 1) * log(x) - beta * x;
276 }
double BCMath::LogGaus ( double  x,
double  mean = 0,
double  sigma = 1,
bool  norm = false 
)

Calculate the natural logarithm of a gaussian function with mean and sigma. If norm=true (default is false) the result is multiplied by the normalization constant, i.e. divided by sqrt(2*Pi)*sigma.

Definition at line 33 of file BCMath.cxx.

34 {
35  // if we have a delta function, return fixed value
36  if (sigma == 0.)
37  return 0;
38 
39  // if sigma is negative use absolute value
40  if (sigma < 0.)
41  sigma *= -1.;
42 
43  double arg = (x - mean) / sigma;
44  double result = -.5 * arg * arg;
45 
46  // check if we should add the normalization constant
47  if (!norm)
48  return result;
49 
50  // subtract the log of the denominator of the normalization constant
51  // and return
52  return result - log(sqrt(2. * M_PI) * sigma);
53 }
double BCMath::LogLogNormal ( double  x,
double  mean = 0,
double  sigma = 1 
)

Return the log of the log normal distribution

Definition at line 279 of file BCMath.cxx.

280 {
281  // if we have a delta function, return fixed value
282  if (sigma == 0.)
283  return 0;
284 
285  // if sigma is negative use absolute value
286  if (sigma < 0.)
287  sigma *= -1.;
288 
289  double arg = (log(x) - mean) / sigma;
290  double result = -.5 * arg * arg;
291 
292  return result - log(x * sqrt(2. * M_PI) * sigma);
293 }
double BCMath::LogNoverK ( int  n,
int  k 
)

Calculates natural logarithm of the Binomial factor "n over k".

Definition at line 176 of file BCMath.cxx.

177 {
178  // switch parameters if n < k
179  if (n < k) {
180  int a = n;
181  n = k;
182  k = a;
183  }
184 
185  if (n == k || k == 0)
186  return 0.;
187  if (k == 1 || k == n - 1)
188  return log((double) n);
189 
190  int lmax = std::max(k, n - k);
191  int lmin = std::min(k, n - k);
192 
193  double ln = 0.;
194 
195  for (int i = n; i > lmax; i--)
196  ln += log((double) i);
197  ln -= LogFact(lmin);
198 
199  return ln;
200 }
double BCMath::LogPoisson ( double  x,
double  par 
)

Calculate the natural logarithm of a poisson distribution.

Definition at line 57 of file BCMath.cxx.

58 {
59  if (par > 899)
60  return LogGaus(x, par, sqrt(par), true);
61 
62  if (x < 0)
63  return 0;
64 
65  if (x == 0.)
66  return -par;
67 
68  return x * log(par) - par - ApproxLogFact(x);
69 }
double BCMath::LogVoigtian ( double  x,
double  sigma,
double  gamma 
)

Calculates the logarithm of normalized voigtian function: voigtian(double x, double sigma, double gamma)

voigtian is a convolution of the following two functions: gaussian(x) = 1/(sqrt(2*pi)*sigma) * exp(x*x/(2*sigma*sigma) and lorentz(x) = (1/pi)*(gamma/2) / (x*x + (gamma/2)*(gamma/2))

it is singly peaked at x=0. The width of the peak is decided by sigma and gamma, so they should be positive.

Definition at line 262 of file BCMath.cxx.

263 {
264  if (sigma <= 0 || gamma <= 0) {
265  BCLog::OutWarning("BCMath::LogVoigtian : widths are negative or zero!");
266  return -1e99;
267  }
268 
269  return log(TMath::Voigt(x, sigma, gamma));
270 }
double BCMath::longestRunFrequency ( unsigned int  longestObserved,
unsigned int  nTrials 
)

Find the sampling probability that, given n independent Bernoulli trials with success rate = failure rate = 1/2, the longest run of consecutive successes is greater than the longest observed run. Key idea from Burr, E.J. & Cane, G. Longest Run of Consecutive Observations Having a Specified Attribute. Biometrika 48, 461-465 (1961).

Parameters
longestObservedactual longest run
nTrialsnumber of independent trials
Returns
frequency
double BCMath::longestRunFrequency ( unsigned  longestObserved,
unsigned int  nTrials 
)

Definition at line 506 of file BCMath.cxx.

507 {
508  // can't observe run that's longer than the whole sequence
509  if (longestObserved >= nTrials)
510  return 0.;
511 
512  // return value
513  double prob = 0.;
514 
515  // short cuts
516  typedef unsigned int uint;
517  uint Lobs = longestObserved;
518  uint n = nTrials;
519 
520  // the result of the inner loop is the cond. P given r successes
521  double conditionalProb;
522 
523  /* first method: use the gamma function for the factorials: bit slower and more inaccurate
524  * in fact may return NaN for n >= 1000.
525  * alternative using log factorial approximations, is faster and more accurate
526  */
527 
528  double tempLog = 0;
529  for (uint r = 0; r <= n; r++) {
530  conditionalProb = 0.0;
531 
532  for (uint i = 1; (i <= n - r + 1) && (i <= uint(r / double(Lobs + 1))); i++) {
533  tempLog = ApproxLogFact(n - i * (Lobs + 1)) - ApproxLogFact(i)
534  - ApproxLogFact(n - r - i + 1)
535  - ApproxLogFact(r - i * (Lobs + 1));
536  if (i % 2)
537  conditionalProb += exp(tempLog);
538  else
539  conditionalProb -= exp(tempLog);
540  }
541  prob += (1 + n - r) * conditionalProb;
542  }
543 
544  // Bernoulli probability of each permutation
545  prob *= pow(2., -double(n));
546 
547  return prob;
548 }
std::vector< int > BCMath::longestRuns ( const std::vector< bool > &  bitStream)

Find the longest runs of zeros and ones in the bit stream

Parameters
bitStreaminput sequence of boolean values
Returns
runs first entry the longest zeros run, second entry the longest ones run

Definition at line 388 of file BCMath.cxx.

389 {
390  // initialize counter variables
391  unsigned int maxRunAbove, maxRunBelow, currRun;
392  maxRunAbove = 0;
393  maxRunBelow = 0;
394  currRun = 1;
395  // set both entries to zero
396  std::vector<int> runs(2, 0);
397 
398  if (bitStream.empty())
399  return runs;
400 
401  // flag about kind of the currently considered run
402  bool aboveRun = bitStream.at(0);
403 
404  // start at second variable
405  std::vector<bool>::const_iterator iter = bitStream.begin();
406  ++iter;
407  while (iter != bitStream.end()) {
408 
409  // increase counter if run continues
410  if (*(iter - 1) == *iter)
411  currRun++;
412  else {
413  // compare terminated run to maximum
414  if (aboveRun)
415  maxRunAbove = std::max(maxRunAbove, currRun);
416  else
417  maxRunBelow = std::max(maxRunBelow, currRun);
418  // set flag to run of opposite kind
419  aboveRun = !aboveRun;
420  // restart at length one
421  currRun = 1;
422  }
423  // move to next bit
424  ++iter;
425  }
426 
427  // check last run
428  if (aboveRun)
429  maxRunAbove = std::max(maxRunAbove, currRun);
430  else
431  maxRunBelow = std::max(maxRunBelow, currRun);
432 
433  // save the longest runs
434  runs.at(0) = maxRunBelow;
435  runs.at(1) = maxRunAbove;
436 
437  return runs;
438 }
std::vector< double > BCMath::longestRunsChi2 ( const std::vector< double > &  yMeasured,
const std::vector< double > &  yExpected,
const std::vector< double > &  sigma 
)

Find the longest success/failure run in set of norm. distributed variables. Success = observation >= expectation. Runs are weighted by the total chi^2 of all elements in the run

Parameters
yMeasuredthe observations
yExpectedthe expected values
sigmathe theoretical uncertainties on the expectations
Returns
runs first entry the max. weight failure run, second entry the max. success run

Definition at line 441 of file BCMath.cxx.

444 {
445  //initialize counter variables
446  double maxRunAbove, maxRunBelow, currRun;
447  maxRunAbove = 0;
448  maxRunBelow = 0;
449  currRun = 0;
450  //set both entries to zero
451  std::vector<double> runs(2, 0);
452 
453  //check input size
454  if (yMeasured.size() != yExpected.size() || yMeasured.size() != sigma.size()
455  || yExpected.size() != sigma.size()) {
456  //should throw exception
457  return runs;
458  }
459 
460  //exclude zero uncertainty
461  //...
462 
463  int N = yMeasured.size();
464  if ( N<=0)
465  return runs;
466  //BCLog::OutDebug(Form("N = %d", N));
467 
468 
469  //flag about kind of the currently considered run
470  double residue = (yMeasured.at(0) - yExpected.at(0)) / sigma.at(0);
471  bool aboveRun = residue >= 0 ? true : false;
472  currRun = residue * residue;
473 
474  //start at second variable
475  for (int i = 1; i < N; i++) {
476  residue = (yMeasured.at(i) - yExpected.at(i)) / sigma.at(i);
477  //run continues
478  if ((residue >= 0) == aboveRun) {
479  currRun += residue * residue;
480  } else {
481  //compare terminated run to maximum
482  if (aboveRun)
483  maxRunAbove = std::max(maxRunAbove, currRun);
484  else
485  maxRunBelow = std::max(maxRunBelow, currRun);
486  //set flag to run of opposite kind
487  aboveRun = !aboveRun;
488  //restart at current residual
489  currRun = residue * residue;
490  }
491  }
492 
493  //check last run
494  if (aboveRun)
495  maxRunAbove = std::max(maxRunAbove, currRun);
496  else
497  maxRunBelow = std::max(maxRunBelow, currRun);
498 
499  //save the longest runs
500  runs.at(0) = maxRunBelow;
501  runs.at(1) = maxRunAbove;
502 
503  return runs;
504 }
int BCMath::Nint ( double  x)

Returns the nearest integer of a double number.

Definition at line 204 of file BCMath.cxx.

205 {
206  // round to integer
207  int i;
208 
209  if (x >= 0) {
210  i = (int) (x + .5);
211  if (x + .5 == (double) i && (i&1))
212  i--;
213  }
214  else {
215  i = int(x - 0.5);
216  if (x - 0.5 == double(i) && (i&1))
217  i++;
218  }
219 
220  return i;
221 }
void BCMath::RandomChi2 ( std::vector< double > &  randoms,
int  K 
)

Get N random numbers distributed according to chi square function with K degrees of freedom

Definition at line 318 of file BCMath.cxx.

319 {
320  // fixed upper cutoff to 1000, might be too small
321  TF1 *f = new TF1("chi2", chi2, 0.0, 1000, 1);
322  f->SetParameter(0, K);
323  f->SetNpx(500);
324  // uses inverse-transform method
325  // fortunately CDF only built once
326  for (unsigned int i = 0; i < randoms.size(); i++)
327  randoms.at(i) = f->GetRandom();
328 
329  delete f;
330 }
double BCMath::Rvalue ( const std::vector< double > &  chain_means,
const std::vector< double > &  chain_variances,
const unsigned &  chain_length,
const bool &  strict = true 
)
throw (std::invalid_argument,
std::domain_error
)

Compute the R-value according to Gelman-Rubin, GR1992 : Gelman, A. and Rubin, D.B. Inference from Iterative Simulation Using Multiple Sequences Statistical Science, Vol. 7, No. 4 (Nov. 1992), pp. 457-472

Parameters
chain_means
chain_variances
chain_length
strictIf true, use the algorithm laid forth in the paper, else use a relaxed version which generally leads to smaller R-values.
Returns
R-value

Definition at line 551 of file BCMath.cxx.

553 {
554  if (chain_means.size() != chain_variances.size())
555  throw std::invalid_argument("BCMath::RValue: chain means and chain variances are not aligned!");
556 
557  const double n = chain_length;
558  const double m = chain_means.size();
559 
560  if (m <= 1)
561  throw std::invalid_argument("BCMath:RValue: Need at least two chains to compute R-value!");
562 
563  // init
564  double variance_of_means = 0.0;
565  double mean_of_means = 0.0;
566  double mean_of_variances = 0.0;
567  double variance_of_variances = 0.0;
568 
569  // use Welford's method here as well with temporary variables
570  double previous_mean_of_means = 0;
571  double previous_mean_of_variances = 0;
572  for (unsigned i = 0 ; i < m ; ++i)
573  {
574  if (0 == i)
575  {
576  mean_of_means = chain_means.front();
577  variance_of_means = 0;
578  mean_of_variances = chain_variances.front();
579  variance_of_variances = 0;
580 
581  continue;
582  }
583 
584  // temporarily store previous mean of step (i-1)
585  previous_mean_of_means = mean_of_means;
586  previous_mean_of_variances = mean_of_variances;
587 
588  // update step
589  mean_of_means += (chain_means[i] - previous_mean_of_means) / (i + 1.0);
590  variance_of_means += (chain_means[i] - previous_mean_of_means) * (chain_means[i] - mean_of_means);
591  mean_of_variances += (chain_variances[i] - previous_mean_of_variances) / (i + 1.0);
592  variance_of_variances += (chain_variances[i] - previous_mean_of_variances) * (chain_variances[i] - mean_of_variances);
593  }
594 
595  variance_of_means /= m - 1.0;
596  variance_of_variances /= m - 1.0;
597 
598  //use Gelman/Rubin notation
599  double B = variance_of_means * n;
600  double W = mean_of_variances;
601  double sigma_squared = (n - 1.0) / n * W + B / n;
602 
603  // avoid case with no variance whatsoever
604  if (0.0 == W && 0.0 == B)
605  {
606  BCLog::OutDebug("BCMath::Rvalue: All samples in all chains identical!");
607  return 1.0;
608  }
609  // avoid NaN due to divide by zero
610  if (0.0 == W)
611  {
612  BCLog::OutDebug("BCMath::Rvalue: W = 0. Avoiding R = NaN.");
613  return std::numeric_limits<double>::max();
614  }
615 
616  // the lax implementation stops here
617  if (!strict)
618  return sqrt(sigma_squared / W);
619 
620  //estimated scale reduction
621  double R = 0.0;
622 
623  // compute covariances using the means from above
624  double covariance_22 = 0.0; // cov(s_i^2, \bar{x_i}^2
625  double covariance_21 = 0.0; // cov(s_i^2, \bar{x_i}
626 
627  for (unsigned i = 0 ; i < m ; ++i)
628  {
629  covariance_21 += (chain_variances[i] - mean_of_variances) * (chain_means.at(i) - mean_of_means);
630  covariance_22 += (chain_variances[i] - mean_of_variances) * (chain_means[i] * chain_means[i] - mean_of_means * mean_of_means);
631  }
632 
633  covariance_21 /= m - 1.0;
634  covariance_22 /= m - 1.0;
635 
636  // scale of t-distribution
637  double V = sigma_squared + B / (m * n);
638 
639  // estimation of scale variance
640  double a = (n - 1.0) * (n - 1.0) / (n * n * m) * variance_of_variances;
641  double b = (m + 1) * (m + 1) / (m * n * m * n) * 2.0 / (m - 1) * B * B;
642  double c = 2.0 * (m + 1.0) * (n - 1.0) / (m * n * n) * n / m * (covariance_22 - 2.0 * mean_of_means * covariance_21);
643  double variance_of_V = a + b + c;
644 
645  // degrees of freedom of t-distribution
646  double df = 2.0 * V * V / variance_of_V;
647 
648  if (df <= 2)
649  {
650  BCLog::OutDebug(Form("BCMath::Rvalue: DoF (%g) below 2. Avoiding R = NaN.", df));
651  return std::numeric_limits<double>::max();;
652  }
653 
654  // sqrt of estimated scale reduction if sampling were continued
655  R = sqrt(V / W * df / (df - 2.0));
656 
657  // R smaller, but close to 1 is OK.
658  if (R < 0.99 && n > 100)
659  throw std::domain_error(Form("BCMath::Rvalue: %g < 0.99. Check for a bug in the implementation!", R));
660 
661  return R;
662 }
double BCMath::SplitGaussian ( double *  x,
double *  par 
)

Gaussian with different uncertainties to either side of the mode. Interface to use with TF1.

Parameters
xRandom variable
parMean, sigmadown, sigmaup
Returns
density f(x)

Definition at line 296 of file BCMath.cxx.

297 {
298  double mean = par[0];
299  double sigmadown = par[1];
300  double sigmaup = par[2];
301 
302  double sigma = sigmadown;
303 
304  if (x[0] > mean)
305  sigma = sigmaup;
306 
307  return 1.0/sqrt(2.0*M_PI)/sigma * exp(- (x[0]-mean)*(x[0]-mean)/2./sigma/sigma);
308 }

Variable Documentation

double* BCMath::logfact = 0
static

Definition at line 29 of file BCMath.cxx.

unsigned int BCMath::nCacheFact = 10000
static

Definition at line 28 of file BCMath.cxx.