00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "RooAbsFunc.h"
00018 #include "RooAbsReal.h"
00019 #include "RooRealVar.h"
00020 #include "RooArgSet.h"
00021 #include "RooBrentRootFinder.h"
00022 #include "RooFormulaVar.h"
00023 #include "RooGenericPdf.h"
00024 #include "RooPlot.h"
00025 #include "RooProdPdf.h"
00026
00027
00028 #include "RooStats/BayesianCalculator.h"
00029 #include "RooStats/ModelConfig.h"
00030 #include "RooStats/RooStatsUtils.h"
00031
00032 #include "Math/IFunction.h"
00033 #include "Math/IntegratorMultiDim.h"
00034 #include "Math/Integrator.h"
00035 #include "Math/RootFinder.h"
00036 #include "Math/BrentMinimizer1D.h"
00037 #include "RooFunctor.h"
00038 #include "RooFunctor1DBinding.h"
00039 #include "RooTFnBinding.h"
00040 #include "RooMsgService.h"
00041
00042 #include "TAxis.h"
00043 #include "TF1.h"
00044 #include "TH1.h"
00045 #include "TMath.h"
00046 #include "TCanvas.h"
00047
00048 #include <map>
00049 #include <cmath>
00050
00051
00052 #include "RConfigure.h"
00053
00054 ClassImp(RooStats::BayesianCalculator)
00055
00056 namespace RooStats {
00057
00058
00059
00060
00061 #ifdef R__HAS_MATHMORE
00062 const ROOT::Math::RootFinder::EType kRootFinderType = ROOT::Math::RootFinder::kGSL_BRENT;
00063 #else
00064 const ROOT::Math::RootFinder::EType kRootFinderType = ROOT::Math::RootFinder::kBRENT;
00065 #endif
00066
00067
00068
00069
00070 struct LikelihoodFunction {
00071 LikelihoodFunction(RooFunctor & f, double offset = 0) : fFunc(f), fOffset(offset) {}
00072
00073 double operator() (const double *x ) const {
00074 double nll = fFunc(x) - fOffset;
00075 double likelihood = std::exp(-nll);
00076
00077
00078 return likelihood;
00079 }
00080
00081
00082 double operator() (double x) const {
00083 double tmp = x;
00084 return (*this)(&tmp);
00085 }
00086
00087 RooFunctor & fFunc;
00088 double fOffset;
00089 };
00090
00091 class PosteriorCdfFunction : public ROOT::Math::IGenFunction {
00092
00093 public:
00094 PosteriorCdfFunction(ROOT::Math::IntegratorMultiDim & ig, double * xmin, double * xmax) :
00095 fIntegrator(ig), fXmin(xmin), fXmax(xmax), fNorm(1.0), fOffset(0.0), fMaxX(xmax[0]),
00096 fHasNorm(false), fUseOldValues(true)
00097 {
00098
00099 fNorm = (*this)(xmax[0] );
00100 fHasNorm = true;
00101 fNormCdfValues.insert(std::make_pair(xmin[0], 0) );
00102 fNormCdfValues.insert(std::make_pair(xmax[0], 1.0) );
00103
00104 }
00105
00106
00107
00108
00109
00110
00111 ROOT::Math::IGenFunction * Clone() const {
00112 ooccoutD((TObject*)0,NumIntegration) << " cloning function .........." << std::endl;
00113 return new PosteriorCdfFunction(*this);
00114 }
00115
00116 void SetOffset(double offset) { fOffset = offset; }
00117
00118 private:
00119 double DoEval (double x) const {
00120
00121 fXmax[0] = x;
00122 if (x <= fXmin[0] ) return -fOffset;
00123
00124 if (x >= fMaxX && fHasNorm) return 1. - fOffset;
00125
00126
00127 double normcdf0 = 0;
00128 if (fHasNorm && fUseOldValues) {
00129
00130 std::map<double,double>::iterator itr = fNormCdfValues.upper_bound(x);
00131 itr--;
00132 if (itr != fNormCdfValues.end() ) {
00133 fXmin[0] = itr->first;
00134 normcdf0 = itr->second;
00135 ooccoutD((TObject*)0,NumIntegration) << "PosteriorCdfFunction: position for x = " << x << " is = " << itr->first << std::endl;
00136 }
00137 }
00138
00139
00140 double cdf = fIntegrator.Integral(fXmin,fXmax);
00141 double error = fIntegrator.Error();
00142 double normcdf = cdf/fNorm;
00143 ooccoutD((TObject*)0,NumIntegration) << "PosteriorCdfFunction: x0 = " << fXmin[0] << " x = "
00144 << x << " cdf(x) = " << cdf << " +/- " << error
00145 << " norm-cdf(x) = " << normcdf << std::endl;
00146 if (cdf != 0 && error/cdf > 0.2 )
00147 oocoutW((TObject*)0,NumIntegration) << "PosteriorCdfFunction: integration error is larger than 20 % x0 = " << fXmin[0]
00148 << " x = " << x << " cdf(x) = " << cdf << " +/- " << error << std::endl;
00149
00150 if (!fHasNorm) {
00151 oocoutI((TObject*)0,NumIntegration) << "PosteriorCdfFunction - integral of posterior = "
00152 << cdf << " +/- " << error << std::endl;
00153 return cdf;
00154 }
00155
00156 normcdf += normcdf0;
00157
00158
00159 if (fUseOldValues) {
00160 fNormCdfValues.insert(std::make_pair(x, normcdf) );
00161 }
00162
00163 if (normcdf > 1. + 3 * error/fNorm) {
00164 oocoutW((TObject*)0,NumIntegration) << "PosteriorCdfFunction: normalized cdf values is larger than 1"
00165 << " x = " << x << " normcdf(x) = " << normcdf << " +/- " << error/fNorm << std::endl;
00166 }
00167
00168 return normcdf - fOffset;
00169 }
00170
00171 ROOT::Math::IntegratorMultiDim & fIntegrator;
00172 mutable double * fXmin;
00173 mutable double * fXmax;
00174 double fNorm;
00175 double fOffset;
00176 double fMaxX;
00177 bool fHasNorm;
00178 bool fUseOldValues;
00179 mutable std::map<double,double> fNormCdfValues;
00180 };
00181
00182 class PosteriorFunction : public ROOT::Math::IGenFunction {
00183
00184 public:
00185
00186
00187 PosteriorFunction(RooAbsReal & nll, RooRealVar & poi, RooArgList & nuisParams, const char * integType = 0, double norm = 1.0, double nllOffset = 0) :
00188 fFunctor(nll, nuisParams, RooArgList() ),
00189 fLikelihood(fFunctor, nllOffset),
00190 fPoi(&poi),
00191 fXmin(nuisParams.getSize() ),
00192 fXmax(nuisParams.getSize() ),
00193 fNorm(norm)
00194 {
00195
00196 for (unsigned int i = 0; i < fXmin.size(); ++i) {
00197 RooRealVar & var = (RooRealVar &) nuisParams[i];
00198 fXmin[i] = var.getMin();
00199 fXmax[i] = var.getMax();
00200 }
00201 if (fXmin.size() == 1) {
00202 fIntegratorOneDim = std::auto_ptr<ROOT::Math::Integrator>(
00203 new ROOT::Math::Integrator(ROOT::Math::IntegratorOneDim::GetType(integType) ) );
00204 fIntegratorOneDim->SetFunction(fLikelihood);
00205
00206
00207 }
00208 else if (fXmin.size() > 1) {
00209 fIntegratorMultiDim =
00210 std::auto_ptr<ROOT::Math::IntegratorMultiDim>(
00211 new ROOT::Math::IntegratorMultiDim(ROOT::Math::IntegratorMultiDim::GetType(integType) ) );
00212 fIntegratorMultiDim->SetFunction(fLikelihood, fXmin.size());
00213
00214 }
00215 }
00216
00217
00218 ROOT::Math::IGenFunction * Clone() const {
00219 assert(1);
00220 return 0;
00221 }
00222
00223 private:
00224 double DoEval (double x) const {
00225
00226
00227 fPoi->setVal(x);
00228 double f = 0;
00229 double error = 0;
00230 if (fXmin.size() == 1) {
00231 f = fIntegratorOneDim->Integral(fXmin[0],fXmax[0]);
00232 error = fIntegratorOneDim->Error();
00233 }
00234 else if (fXmin.size() > 1) {
00235 f = fIntegratorMultiDim->Integral(&fXmin[0],&fXmax[0]);
00236 error = fIntegratorMultiDim->Error();
00237 } else {
00238
00239 f = fLikelihood(&x);
00240 }
00241
00242 if (f != 0 && error/f > 0.2 )
00243 ooccoutW((TObject*)0,NumIntegration) << "PosteriorFunction::DoEval - Error from integration in "
00244 << fXmin.size() << " Dim is larger than 20 % "
00245 << "x = " << x << " p(x) = " << f << " +/- " << error << std::endl;
00246
00247 return f / fNorm;
00248 }
00249
00250 RooFunctor fFunctor;
00251 LikelihoodFunction fLikelihood;
00252 RooRealVar * fPoi;
00253 std::auto_ptr<ROOT::Math::Integrator> fIntegratorOneDim;
00254 std::auto_ptr<ROOT::Math::IntegratorMultiDim> fIntegratorMultiDim;
00255 std::vector<double> fXmin;
00256 std::vector<double> fXmax;
00257 double fNorm;
00258 };
00259
00260
00261
00262
00263
00264 BayesianCalculator::BayesianCalculator() :
00265 fData(0),
00266 fPdf(0),
00267 fPriorPOI(0),
00268 fProductPdf (0), fLogLike(0), fLikelihood (0), fIntegratedLikelihood (0), fPosteriorPdf(0),
00269 fPosteriorFunction(0), fApproxPosterior(0),
00270 fLower(0), fUpper(0),
00271 fNLLMin(0),
00272 fSize(0.05), fLeftSideFraction(0.5),
00273 fBrfPrecision(0.00005),
00274 fNScanBins(-1),
00275 fValidInterval(false)
00276 {
00277
00278 }
00279
00280 BayesianCalculator::BayesianCalculator(
00281 RooAbsData& data,
00282 RooAbsPdf& pdf,
00283 const RooArgSet& POI,
00284 RooAbsPdf& priorPOI,
00285 const RooArgSet* nuisanceParameters ) :
00286
00287 fData(&data),
00288 fPdf(&pdf),
00289 fPOI(POI),
00290 fPriorPOI(&priorPOI),
00291 fProductPdf (0), fLogLike(0), fLikelihood (0), fIntegratedLikelihood (0), fPosteriorPdf(0),
00292 fPosteriorFunction(0), fApproxPosterior(0),
00293 fLower(0), fUpper(0),
00294 fNLLMin(0),
00295 fSize(0.05), fLeftSideFraction(0.5),
00296 fBrfPrecision(0.00005),
00297 fNScanBins(-1),
00298 fValidInterval(false)
00299 {
00300
00301 if (nuisanceParameters) fNuisanceParameters.add(*nuisanceParameters);
00302 }
00303
00304 BayesianCalculator::BayesianCalculator( RooAbsData& data,
00305 ModelConfig & model) :
00306 fData(&data),
00307 fPdf(model.GetPdf()),
00308 fPriorPOI( model.GetPriorPdf()),
00309 fProductPdf (0), fLogLike(0), fLikelihood (0), fIntegratedLikelihood (0), fPosteriorPdf(0),
00310 fPosteriorFunction(0), fApproxPosterior(0),
00311 fLower(0), fUpper(0),
00312 fNLLMin(0),
00313 fSize(0.05), fLeftSideFraction(0.5),
00314 fBrfPrecision(0.00005),
00315 fNScanBins(-1),
00316 fValidInterval(false)
00317 {
00318
00319 SetModel(model);
00320 }
00321
00322
00323 BayesianCalculator::~BayesianCalculator()
00324 {
00325
00326 ClearAll();
00327 }
00328
00329 void BayesianCalculator::ClearAll() const {
00330
00331 if (fProductPdf) delete fProductPdf;
00332 if (fLogLike) delete fLogLike;
00333 if (fLikelihood) delete fLikelihood;
00334 if (fIntegratedLikelihood) delete fIntegratedLikelihood;
00335 if (fPosteriorPdf) delete fPosteriorPdf;
00336 if (fPosteriorFunction) delete fPosteriorFunction;
00337 if (fApproxPosterior) delete fApproxPosterior;
00338 fPosteriorPdf = 0;
00339 fPosteriorFunction = 0;
00340 fProductPdf = 0;
00341 fLogLike = 0;
00342 fLikelihood = 0;
00343 fIntegratedLikelihood = 0;
00344 fLower = 0;
00345 fUpper = 0;
00346 fNLLMin = 0;
00347 fValidInterval = false;
00348 }
00349
00350 void BayesianCalculator::SetModel(const ModelConfig & model) {
00351
00352 fPdf = model.GetPdf();
00353 fPriorPOI = model.GetPriorPdf();
00354
00355 fPOI.removeAll();
00356 fNuisanceParameters.removeAll();
00357 if (model.GetParametersOfInterest()) fPOI.add( *(model.GetParametersOfInterest()) );
00358 if (model.GetNuisanceParameters()) fNuisanceParameters.add( *(model.GetNuisanceParameters() ) );
00359
00360
00361 ClearAll();
00362 }
00363
00364
00365
00366 RooAbsReal* BayesianCalculator::GetPosteriorFunction() const
00367 {
00368
00369
00370
00371
00372
00373
00374
00375 if (fIntegratedLikelihood) return fIntegratedLikelihood;
00376 if (fLikelihood) return fLikelihood;
00377
00378
00379 if (!fPdf ) {
00380 coutE(InputArguments) << "BayesianCalculator::GetPosteriorPdf - missing pdf model" << std::endl;
00381 return 0;
00382 }
00383 if (!fPriorPOI) {
00384 coutE(InputArguments) << "BayesianCalculator::GetPosteriorPdf - missing prior pdf" << std::endl;
00385 return 0;
00386 }
00387 if (fPOI.getSize() == 0) {
00388 coutE(InputArguments) << "BayesianCalculator::GetPosteriorPdf - missing parameter of interest" << std::endl;
00389 return 0;
00390 }
00391 if (fPOI.getSize() > 1) {
00392 coutE(InputArguments) << "BayesianCalculator::GetPosteriorPdf - current implementation works only on 1D intervals" << std::endl;
00393 return 0;
00394 }
00395
00396
00397 TString prodName = TString("product_") + TString(fPdf->GetName()) + TString("_") + TString(fPriorPOI->GetName() );
00398 fProductPdf = new RooProdPdf(prodName,"",RooArgList(*fPdf,*fPriorPOI));
00399
00400 RooArgSet* constrainedParams = fProductPdf->getParameters(*fData);
00401
00402 RemoveConstantParameters(constrainedParams);
00403
00404
00405
00406
00407 fLogLike = fProductPdf->createNLL(*fData, RooFit::Constrain(*constrainedParams) );
00408
00409 ccoutD(Eval) << "BayesianCalculator::GetPosteriorFunction : "
00410 << " pdf x priors = " << fProductPdf->getVal()
00411 << " neglogLikelihood = " << fLogLike->getVal() << std::endl;
00412
00413
00414
00415
00416 fLogLike->setEvalErrorLoggingMode(RooAbsReal::CountErrors);
00417
00418
00419
00420
00421
00422
00423 RooFunctor * nllFunc = fLogLike->functor(fPOI);
00424 ROOT::Math::Functor1D wnllFunc(*nllFunc);
00425 RooRealVar* poi = dynamic_cast<RooRealVar*>( fPOI.first() );
00426 assert(poi);
00427
00428 ROOT::Math::BrentMinimizer1D minim;
00429 minim.SetFunction(wnllFunc,poi->getMin(),poi->getMax() );
00430 bool ret = minim.Minimize(100,1.E-3,1.E-3);
00431 fNLLMin = 0;
00432 if (ret) fNLLMin = minim.FValMinimum();
00433
00434 ccoutD(Eval) << "BayesianCalculator::GetPosteriorFunction : minimum of NLL vs POI for POI = "
00435 << poi->getVal() << " min NLL = " << fNLLMin << std::endl;
00436
00437 delete nllFunc;
00438 delete constrainedParams;
00439
00440 if ( fNuisanceParameters.getSize() == 0 || fIntegrationType.Contains("ROOFIT") ) {
00441
00442 ccoutD(Eval) << "BayesianCalculator::GetPosteriorFunction : use ROOFIT integration "
00443 << std::endl;
00444
00445
00446
00447 TString likeName = TString("likelihood_") + TString(fProductPdf->GetName());
00448 TString formula;
00449 formula.Form("exp(-@0+%f)",fNLLMin);
00450 fLikelihood = new RooFormulaVar(likeName,formula,RooArgList(*fLogLike));
00451
00452
00453 if (fNuisanceParameters.getSize() == 0) return fLikelihood;
00454
00455
00456 fIntegratedLikelihood = fLikelihood->createIntegral(fNuisanceParameters);
00457 }
00458
00459 else {
00460
00461
00462
00463 RooArgList nuisParams(fNuisanceParameters);
00464 fPosteriorFunction = new PosteriorFunction(*fLogLike, *poi, nuisParams, fIntegrationType, 1.,fNLLMin );
00465
00466 TString name = "posteriorfunction_from_";
00467 name += fLogLike->GetName();
00468 fIntegratedLikelihood = new RooFunctor1DBinding(name,name,*fPosteriorFunction,*poi);
00469
00470 }
00471
00472 fIntegratedLikelihood->setEvalErrorLoggingMode(RooAbsReal::CountErrors);
00473
00474 ccoutD(Eval) << "BayesianCalculator::GetPosteriorFunction : use ROOT numerical integration algorithm. ";
00475 ccoutD(Eval) << " Integrated log-likelihood = " << fIntegratedLikelihood->getVal() << std::endl;
00476
00477
00478 return fIntegratedLikelihood;
00479 }
00480
00481 RooAbsPdf* BayesianCalculator::GetPosteriorPdf() const
00482 {
00483
00484
00485
00486 RooAbsReal * plike = GetPosteriorFunction();
00487
00488
00489 TString posteriorName = this->GetName() + TString("_posteriorPdf_") + plike->GetName();
00490
00491 RooAbsPdf * posteriorPdf = new RooGenericPdf(posteriorName,"@0",*plike);
00492
00493 return posteriorPdf;
00494 }
00495
00496
00497 RooPlot* BayesianCalculator::GetPosteriorPlot(bool norm, double precision ) const
00498 {
00499
00500
00501 if (!fLikelihood) GetPosteriorFunction();
00502
00503
00504 if (fNScanBins > 0) ApproximatePosterior();
00505
00506 RooAbsReal * posterior = fIntegratedLikelihood;
00507 if (norm) posterior = fPosteriorPdf;
00508 if (!posterior) {
00509 posterior = GetPosteriorFunction();
00510 if (norm) {
00511 if (fPosteriorPdf) delete fPosteriorPdf;
00512 fPosteriorPdf = GetPosteriorPdf();
00513 posterior = fPosteriorPdf;
00514 }
00515 }
00516 if (!posterior) return 0;
00517
00518 if (!fValidInterval) GetInterval();
00519
00520 RooAbsRealLValue* poi = dynamic_cast<RooAbsRealLValue*>( fPOI.first() );
00521 assert(poi);
00522
00523
00524 RooPlot* plot = poi->frame();
00525
00526
00527 posterior->setEvalErrorLoggingMode(RooAbsReal::CountErrors);
00528
00529 plot->SetTitle(TString("Posterior probability of parameter \"")+TString(poi->GetName())+TString("\""));
00530 posterior->plotOn(plot,RooFit::Range(fLower,fUpper,kFALSE),RooFit::VLines(),RooFit::DrawOption("F"),RooFit::MoveToBack(),RooFit::FillColor(kGray),RooFit::Precision(precision));
00531 posterior->plotOn(plot);
00532 plot->GetYaxis()->SetTitle("posterior function");
00533
00534 return plot;
00535 }
00536
00537 void BayesianCalculator::SetIntegrationType(const char * type) {
00538 fIntegrationType = TString(type);
00539 fIntegrationType.ToUpper();
00540 }
00541
00542
00543
00544 SimpleInterval* BayesianCalculator::GetInterval() const
00545 {
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 if (fValidInterval)
00558 coutW(Eval) << "BayesianCalculator::GetInterval - recomputing interval for the same CL and same model" << std::endl;
00559
00560 RooRealVar* poi = dynamic_cast<RooRealVar*>( fPOI.first() );
00561 if (!poi) {
00562 coutE(Eval) << "BayesianCalculator::GetInterval - no parameter of interest is set " << std::endl;
00563 return 0;
00564 }
00565
00566 if (fLeftSideFraction < 0 ) {
00567
00568 ComputeShortestInterval();
00569 }
00570 else {
00571
00572
00573 double lowerCutOff = fLeftSideFraction * fSize;
00574 double upperCutOff = 1. - (1.- fLeftSideFraction) * fSize;
00575
00576
00577 if (fNScanBins > 0) {
00578 ComputeIntervalFromApproxPosterior(lowerCutOff, upperCutOff);
00579 }
00580
00581 else {
00582
00583 if (fNuisanceParameters.getSize() > 0) {
00584 ComputeIntervalFromCdf(lowerCutOff, upperCutOff);
00585
00586 }
00587 else {
00588 ComputeIntervalUsingRooFit(lowerCutOff, upperCutOff);
00589 }
00590 }
00591 }
00592
00593 fValidInterval = true;
00594 coutI(Eval) << "BayesianCalculator::GetInterval - found a valid interval : [" << fLower << " , "
00595 << fUpper << " ]" << std::endl;
00596
00597 TString interval_name = TString("BayesianInterval_a") + TString(this->GetName());
00598 SimpleInterval * interval = new SimpleInterval(interval_name,*poi,fLower,fUpper,ConfidenceLevel());
00599 interval->SetTitle("SimpleInterval from BayesianCalculator");
00600
00601 return interval;
00602 }
00603
00604 double BayesianCalculator::GetMode() const {
00605
00606
00607
00608
00609
00610
00611 ApproximatePosterior();
00612 TH1 * h = fApproxPosterior->GetHistogram();
00613 return h->GetBinCenter(h->GetMaximumBin() );
00614
00615 }
00616
00617 void BayesianCalculator::ComputeIntervalUsingRooFit(double lowerCutOff, double upperCutOff ) const {
00618
00619
00620 coutI(Eval) << "BayesianCalculator: Compute interval using RooFit: posteriorPdf + createCdf + RooBrentRootFinder " << std::endl;
00621
00622 RooRealVar* poi = dynamic_cast<RooRealVar*>( fPOI.first() );
00623 assert(poi);
00624
00625 if (!fPosteriorPdf) fPosteriorPdf = (RooAbsPdf*) GetPosteriorPdf();
00626
00627 RooAbsReal* cdf = fPosteriorPdf->createCdf(fPOI,RooFit::ScanNoCdf());
00628
00629 RooAbsFunc* cdf_bind = cdf->bindVars(fPOI,&fPOI);
00630 RooBrentRootFinder brf(*cdf_bind);
00631 brf.setTol(fBrfPrecision);
00632
00633 double tmpVal = poi->getVal();
00634
00635 bool ret = true;
00636 if (lowerCutOff > 0) {
00637 double y = lowerCutOff;
00638 ret &= brf.findRoot(fLower,poi->getMin(),poi->getMax(),y);
00639 }
00640 else
00641 fLower = poi->getMin();
00642
00643 if (upperCutOff < 1.0) {
00644 double y=upperCutOff;
00645 ret &= brf.findRoot(fUpper,poi->getMin(),poi->getMax(),y);
00646 }
00647 else
00648 fUpper = poi->getMax();
00649 if (!ret) coutE(Eval) << "BayesianCalculator::GetInterval "
00650 << "Error returned from Root finder, estimated interval is not fully correct"
00651 << std::endl;
00652
00653 poi->setVal(tmpVal);
00654
00655 delete cdf_bind;
00656 delete cdf;
00657 }
00658
00659 void BayesianCalculator::ComputeIntervalFromCdf(double lowerCutOff, double upperCutOff ) const {
00660
00661
00662 coutI(Eval) << "BayesianCalculator: Compute the interval from the posterior cdf " << std::endl;
00663
00664 RooRealVar* poi = dynamic_cast<RooRealVar*>( fPOI.first() );
00665 assert(poi);
00666 GetPosteriorFunction();
00667
00668
00669 RooArgList bindParams;
00670 bindParams.add(fPOI);
00671 bindParams.add(fNuisanceParameters);
00672
00673
00674
00675 RooFunctor functor_nll(*fLogLike, bindParams, RooArgList());
00676
00677
00678
00679 LikelihoodFunction fll(functor_nll, fNLLMin);
00680
00681 ROOT::Math::IntegratorMultiDim ig(ROOT::Math::IntegratorMultiDim::GetType(fIntegrationType));
00682 ig.SetFunction(fll,bindParams.getSize());
00683
00684 std::vector<double> pmin(bindParams.getSize());
00685 std::vector<double> pmax(bindParams.getSize());
00686 std::vector<double> par(bindParams.getSize());
00687 for (unsigned int i = 0; i < pmin.size(); ++i) {
00688 RooRealVar & var = (RooRealVar &) bindParams[i];
00689 pmin[i] = var.getMin();
00690 pmax[i] = var.getMax();
00691 par[i] = var.getVal();
00692 }
00693
00694
00695
00696
00697 PosteriorCdfFunction cdf(ig, &pmin[0], &pmax[0] );
00698
00699
00700
00701
00702 ROOT::Math::RootFinder rf(kRootFinderType);
00703
00704 ccoutD(Eval) << "BayesianCalculator::GetInterval - finding roots of posterior using RF " << rf.Name()
00705 << " with precision = " << fBrfPrecision;
00706
00707 if (lowerCutOff > 0) {
00708 cdf.SetOffset(lowerCutOff);
00709 ccoutD(NumIntegration) << "Integrating posterior to get cdf and search lower limit at p =" << lowerCutOff << std::endl;
00710 bool ok = rf.Solve(cdf, poi->getMin(),poi->getMax() , 200,fBrfPrecision, fBrfPrecision);
00711 if (!ok)
00712 coutE(NumIntegration) << "BayesianCalculator::GetInterval - Error from root finder when searching lower limit !" << std::endl;
00713 fLower = rf.Root();
00714 }
00715 else {
00716 fLower = poi->getMin();
00717 }
00718 if (upperCutOff < 1.0) {
00719 cdf.SetOffset(upperCutOff);
00720 ccoutD(NumIntegration) << "Integrating posterior to get cdf and search upper interval limit at p =" << upperCutOff << std::endl;
00721 bool ok = rf.Solve(cdf, fLower,poi->getMax() , 200, fBrfPrecision, fBrfPrecision);
00722 if (!ok)
00723 coutE(NumIntegration) << "BayesianCalculator::GetInterval - Error from root finder when searching upper limit !" << std::endl;
00724
00725 fUpper = rf.Root();
00726 }
00727 else {
00728 fUpper = poi->getMax();
00729 }
00730 }
00731
00732 void BayesianCalculator::ApproximatePosterior() const {
00733
00734
00735
00736 if (fApproxPosterior) {
00737
00738 if (fApproxPosterior->GetNpx() >= fNScanBins) return;
00739
00740 delete fApproxPosterior;
00741 fApproxPosterior = 0;
00742 }
00743
00744 RooAbsReal * posterior = GetPosteriorFunction();
00745
00746
00747 posterior->setEvalErrorLoggingMode(RooAbsReal::CountErrors);
00748
00749 TF1 * tmp = posterior->asTF(fPOI);
00750 assert(tmp != 0);
00751
00752 if (fNScanBins > 0) tmp->SetNpx(fNScanBins);
00753
00754 coutI(Eval) << "BayesianCalculator - scan posterior function in nbins = " << tmp->GetNpx() << std::endl;
00755
00756 fApproxPosterior = (TF1*) tmp->Clone();
00757
00758
00759 delete tmp;
00760 TString name = posterior->GetName() + TString("_approx");
00761 TString title = posterior->GetTitle() + TString("_approx");
00762 RooAbsReal * posterior2 = new RooTFnBinding(name,title,fApproxPosterior,fPOI);
00763 if (posterior == fIntegratedLikelihood) {
00764 delete fIntegratedLikelihood;
00765 fIntegratedLikelihood = posterior2;
00766 }
00767 else if (posterior == fLikelihood) {
00768 delete fLikelihood;
00769 fLikelihood = posterior2;
00770 }
00771 else {
00772 assert(1);
00773 }
00774 }
00775
00776 void BayesianCalculator::ComputeIntervalFromApproxPosterior(double lowerCutOff, double upperCutOff ) const {
00777
00778
00779 ccoutD(Eval) << "BayesianCalculator: Compute interval from the approximate posterior " << std::endl;
00780
00781 ApproximatePosterior();
00782
00783 double prob[2];
00784 double limits[2];
00785 prob[0] = lowerCutOff;
00786 prob[1] = upperCutOff;
00787 fApproxPosterior->GetQuantiles(2,limits,prob);
00788 fLower = limits[0];
00789 fUpper = limits[1];
00790 }
00791
00792 void BayesianCalculator::ComputeShortestInterval( ) const {
00793
00794 coutI(Eval) << "BayesianCalculator - computing shortest interval with CL = " << 1.-fSize << std::endl;
00795
00796
00797 ApproximatePosterior();
00798 TH1D * h1 = dynamic_cast<TH1D*>(fApproxPosterior->GetHistogram() );
00799 assert(h1 != 0);
00800 h1->SetName(fApproxPosterior->GetName());
00801
00802 double * bins = h1->GetArray();
00803 int n = h1->GetSize()-2;
00804 std::vector<int> index(n);
00805 TMath::Sort(n, bins, &index[0]);
00806
00807 double sum = 0;
00808 double actualCL = 0;
00809 double upper = h1->GetXaxis()->GetXmin();
00810 double lower = h1->GetXaxis()->GetXmax();
00811 double norm = h1->GetSumOfWeights();
00812
00813 for (int i = 0; i < n; ++i) {
00814 int idx = index[i];
00815 double p = bins[ idx] / norm;
00816 sum += p;
00817 if (sum > 1.-fSize ) {
00818 actualCL = sum - p;
00819 break;
00820 }
00821
00822 if ( h1->GetBinLowEdge(idx) < lower)
00823 lower = h1->GetBinLowEdge(idx);
00824 if ( h1->GetXaxis()->GetBinUpEdge(idx) > upper)
00825 upper = h1->GetXaxis()->GetBinUpEdge(idx);
00826 }
00827
00828 ccoutD(Eval) << "BayesianCalculator::ComputeShortestInterval - actual interval CL = "
00829 << actualCL << " difference from requested is " << (actualCL-(1.-fSize))/fSize*100. << "% "
00830 << " limits are [ " << lower << " , " << " upper ] " << std::endl;
00831
00832
00833 if (lower < upper) {
00834 fLower = lower;
00835 fUpper = upper;
00836
00837
00838
00839 if ( std::abs(actualCL-(1.-fSize)) > 0.1*(1.-fSize) )
00840 coutW(Eval) << "BayesianCalculator::ComputeShortestInterval - actual interval CL = "
00841 << actualCL << " differs more than 10% from desired CL value - must increase nbins "
00842 << n << " to an higher value " << std::endl;
00843 }
00844 else
00845 coutE(Eval) << "BayesianCalculator::ComputeShortestInterval " << n << " bins are not sufficient " << std::endl;
00846
00847
00848 }
00849
00850
00851 }
00852