1 #ifndef ROOT_TEfficiency_cxx
2 #define ROOT_TEfficiency_cxx
36 const Double_t kDefBetaAlpha = 1;
37 const Double_t kDefBetaBeta = 1;
38 const Double_t kDefConfLevel = 0.682689492137;
39 const TEfficiency::EStatOption kDefStatOpt = TEfficiency::kFCP;
40 const Double_t kDefWeight = 1;
42 ClassImp(TEfficiency);
619 TEfficiency::TEfficiency():
620 fBeta_alpha(kDefBetaAlpha),
621 fBeta_beta(kDefBetaBeta),
623 fConfLevel(kDefConfLevel),
632 SetStatisticOption(kDefStatOpt);
635 fPassedHistogram =
new TH1F(
"h_passed",
"passed",10,0,10);
636 fTotalHistogram =
new TH1F(
"h_total",
"total",10,0,10);
658 TEfficiency::TEfficiency(
const TH1& passed,
const TH1& total):
659 fBeta_alpha(kDefBetaAlpha),
660 fBeta_beta(kDefBetaBeta),
661 fConfLevel(kDefConfLevel),
669 if(CheckConsistency(passed,total)) {
670 Bool_t bStatus = TH1::AddDirectoryStatus();
671 TH1::AddDirectory(kFALSE);
672 fTotalHistogram = (TH1*)total.Clone();
673 fPassedHistogram = (TH1*)passed.Clone();
674 TH1::AddDirectory(bStatus);
676 TString newName = total.GetName();
677 newName += TString(
"_clone");
681 if(CheckWeights(passed,total))
683 Info(
"TEfficiency",
"given histograms are filled with weights");
684 SetUseWeightedEvents();
688 Error(
"TEfficiency(const TH1&,const TH1&)",
"histograms are not consistent -> results are useless");
689 Warning(
"TEfficiency(const TH1&,const TH1&)",
"using two empty TH1D('h1','h1',10,0,10)");
691 Bool_t bStatus = TH1::AddDirectoryStatus();
692 TH1::AddDirectory(kFALSE);
693 fTotalHistogram =
new TH1D(
"h1_total",
"h1 (total)",10,0,10);
694 fPassedHistogram =
new TH1D(
"h1_passed",
"h1 (passed)",10,0,10);
695 TH1::AddDirectory(bStatus);
698 SetBit(kPosteriorMode,
false);
699 SetBit(kShortestInterval,
false);
701 SetStatisticOption(kDefStatOpt);
724 TEfficiency::TEfficiency(
const char* name,
const char* title,Int_t nbins,
725 const Double_t* xbins):
726 fBeta_alpha(kDefBetaAlpha),
727 fBeta_beta(kDefBetaBeta),
728 fConfLevel(kDefConfLevel),
735 Bool_t bStatus = TH1::AddDirectoryStatus();
736 TH1::AddDirectory(kFALSE);
737 fTotalHistogram =
new TH1D(
"total",
"total",nbins,xbins);
738 fPassedHistogram =
new TH1D(
"passed",
"passed",nbins,xbins);
739 TH1::AddDirectory(bStatus);
763 TEfficiency::TEfficiency(
const char* name,
const char* title,Int_t nbinsx,
764 Double_t xlow,Double_t xup):
765 fBeta_alpha(kDefBetaAlpha),
766 fBeta_beta(kDefBetaBeta),
767 fConfLevel(kDefConfLevel),
774 Bool_t bStatus = TH1::AddDirectoryStatus();
775 TH1::AddDirectory(kFALSE);
776 fTotalHistogram =
new TH1D(
"total",
"total",nbinsx,xlow,xup);
777 fPassedHistogram =
new TH1D(
"passed",
"passed",nbinsx,xlow,xup);
778 TH1::AddDirectory(bStatus);
805 TEfficiency::TEfficiency(
const char* name,
const char* title,Int_t nbinsx,
806 Double_t xlow,Double_t xup,Int_t nbinsy,
807 Double_t ylow,Double_t yup):
808 fBeta_alpha(kDefBetaAlpha),
809 fBeta_beta(kDefBetaBeta),
810 fConfLevel(kDefConfLevel),
817 Bool_t bStatus = TH1::AddDirectoryStatus();
818 TH1::AddDirectory(kFALSE);
819 fTotalHistogram =
new TH2D(
"total",
"total",nbinsx,xlow,xup,nbinsy,ylow,yup);
820 fPassedHistogram =
new TH2D(
"passed",
"passed",nbinsx,xlow,xup,nbinsy,ylow,yup);
821 TH1::AddDirectory(bStatus);
848 TEfficiency::TEfficiency(
const char* name,
const char* title,Int_t nbinsx,
849 const Double_t* xbins,Int_t nbinsy,
850 const Double_t* ybins):
851 fBeta_alpha(kDefBetaAlpha),
852 fBeta_beta(kDefBetaBeta),
853 fConfLevel(kDefConfLevel),
860 Bool_t bStatus = TH1::AddDirectoryStatus();
861 TH1::AddDirectory(kFALSE);
862 fTotalHistogram =
new TH2D(
"total",
"total",nbinsx,xbins,nbinsy,ybins);
863 fPassedHistogram =
new TH2D(
"passed",
"passed",nbinsx,xbins,nbinsy,ybins);
864 TH1::AddDirectory(bStatus);
894 TEfficiency::TEfficiency(
const char* name,
const char* title,Int_t nbinsx,
895 Double_t xlow,Double_t xup,Int_t nbinsy,
896 Double_t ylow,Double_t yup,Int_t nbinsz,
897 Double_t zlow,Double_t zup):
898 fBeta_alpha(kDefBetaAlpha),
899 fBeta_beta(kDefBetaBeta),
900 fConfLevel(kDefConfLevel),
907 Bool_t bStatus = TH1::AddDirectoryStatus();
908 TH1::AddDirectory(kFALSE);
909 fTotalHistogram =
new TH3D(
"total",
"total",nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup);
910 fPassedHistogram =
new TH3D(
"passed",
"passed",nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup);
911 TH1::AddDirectory(bStatus);
941 TEfficiency::TEfficiency(
const char* name,
const char* title,Int_t nbinsx,
942 const Double_t* xbins,Int_t nbinsy,
943 const Double_t* ybins,Int_t nbinsz,
944 const Double_t* zbins):
945 fBeta_alpha(kDefBetaAlpha),
946 fBeta_beta(kDefBetaBeta),
947 fConfLevel(kDefConfLevel),
954 Bool_t bStatus = TH1::AddDirectoryStatus();
955 TH1::AddDirectory(kFALSE);
956 fTotalHistogram =
new TH3D(
"total",
"total",nbinsx,xbins,nbinsy,ybins,nbinsz,zbins);
957 fPassedHistogram =
new TH3D(
"passed",
"passed",nbinsx,xbins,nbinsy,ybins,nbinsz,zbins);
958 TH1::AddDirectory(bStatus);
980 TEfficiency::TEfficiency(
const TEfficiency& rEff):
985 fBeta_alpha(rEff.fBeta_alpha),
986 fBeta_beta(rEff.fBeta_beta),
987 fBeta_bin_params(rEff.fBeta_bin_params),
988 fConfLevel(rEff.fConfLevel),
993 fWeight(rEff.fWeight)
996 ((TObject&)rEff).Copy(*
this);
998 Bool_t bStatus = TH1::AddDirectoryStatus();
999 TH1::AddDirectory(kFALSE);
1000 fTotalHistogram = (TH1*)((rEff.fTotalHistogram)->Clone());
1001 fPassedHistogram = (TH1*)((rEff.fPassedHistogram)->Clone());
1002 TH1::AddDirectory(bStatus);
1004 TString name = rEff.GetName();
1007 TString title =
"[copy] ";
1008 title += rEff.GetTitle();
1011 SetStatisticOption(rEff.GetStatisticOption());
1016 rEff.TAttLine::Copy(*
this);
1017 rEff.TAttFill::Copy(*
this);
1018 rEff.TAttMarker::Copy(*
this);
1024 TEfficiency::~TEfficiency()
1030 fFunctions->SetBit(kInvalidObject);
1032 while ((obj = fFunctions->First())) {
1033 while(fFunctions->Remove(obj)) { }
1034 if (!obj->TestBit(kNotDeleted)) {
1045 fDirectory->Remove(
this);
1047 delete fTotalHistogram;
1048 delete fPassedHistogram;
1074 Double_t TEfficiency::AgrestiCoull(Double_t total,Double_t passed,Double_t level,Bool_t bUpper)
1076 Double_t alpha = (1.0 - level)/2;
1077 Double_t kappa = ROOT::Math::normal_quantile(1 - alpha,1);
1079 Double_t mode = (passed + 0.5 * kappa * kappa) / (total + kappa * kappa);
1080 Double_t delta = kappa * std::sqrt(mode * (1 - mode) / (total + kappa * kappa));
1083 return ((mode + delta) > 1) ? 1.0 : (mode + delta);
1085 return ((mode - delta) < 0) ? 0.0 : (mode - delta);
1097 Double_t TEfficiency::FeldmanCousins(Double_t total,Double_t passed,Double_t level,Bool_t bUpper)
1101 if (!FeldmanCousinsInterval(total,passed,level, lower, upper)) {
1102 ::Error(
"FeldmanCousins",
"Error running FC method - return 0 or 1");
1104 return (bUpper) ? upper : lower;
1130 Bool_t TEfficiency::FeldmanCousinsInterval(Double_t total,Double_t passed,Double_t level,Double_t & lower, Double_t & upper)
1132 FeldmanCousinsBinomialInterval fc;
1133 double alpha = 1.-level;
1135 fc.Calculate(passed, total);
1155 Double_t TEfficiency::MidPInterval(Double_t total,Double_t passed,Double_t level,Bool_t bUpper)
1157 const double alpha = 1. - level;
1158 const bool equal_tailed =
true;
1159 const double alpha_min = equal_tailed ? alpha/2 : alpha;
1160 const double tol = 1e-9;
1170 if ( passed > 0 && passed < 1) {
1171 double p0 = MidPInterval(total,0.0,level,bUpper);
1172 double p1 = MidPInterval(total,1.0,level,bUpper);
1173 p = (p1 - p0) * passed + p0;
1177 while (std::abs(pmax - pmin) > tol) {
1178 p = (pmin + pmax)/2;
1181 double v = 0.5 * ROOT::Math::beta_pdf(p, passed+1., total-passed+1)/(total+1);
1184 if ( (passed-1) >= 0) v += ROOT::Math::beta_cdf_c(p, passed, total-passed+1);
1186 double vmin = (bUpper) ? alpha_min : 1.- alpha_min;
1249 Double_t TEfficiency::Bayesian(Double_t total,Double_t passed,Double_t level,Double_t alpha,Double_t beta,Bool_t bUpper, Bool_t bShortest)
1251 Double_t a = double(passed)+alpha;
1252 Double_t b = double(total-passed)+beta;
1257 BetaShortestInterval(level,a,b,lower,upper);
1258 return (bUpper) ? upper : lower;
1261 return BetaCentralInterval(level, a, b, bUpper);
1273 Double_t TEfficiency::BetaCentralInterval(Double_t level,Double_t a,Double_t b,Bool_t bUpper)
1276 if((a > 0) && (b > 0))
1277 return ROOT::Math::beta_quantile((1+level)/2,a,b);
1279 gROOT->Error(
"TEfficiency::BayesianCentral",
"Invalid input parameters - return 1");
1284 if((a > 0) && (b > 0))
1285 return ROOT::Math::beta_quantile((1-level)/2,a,b);
1287 gROOT->Error(
"TEfficiency::BayesianCentral",
"Invalid input parameters - return 0");
1293 struct Beta_interval_length {
1294 Beta_interval_length(Double_t level,Double_t alpha,Double_t beta ) :
1295 fCL(level), fAlpha(alpha), fBeta(beta)
1298 Double_t LowerMax() {
1300 return ROOT::Math::beta_quantile_c(fCL, fAlpha,fBeta);
1303 Double_t operator() (
double lower)
const {
1305 Double_t plow = ROOT::Math::beta_cdf(lower, fAlpha, fBeta);
1306 Double_t pup = plow + fCL;
1307 double upper = ROOT::Math::beta_quantile(pup, fAlpha,fBeta);
1329 Bool_t TEfficiency::BetaShortestInterval(Double_t level,Double_t a,Double_t b, Double_t & lower, Double_t & upper)
1331 if (a <= 0 || b <= 0) {
1332 lower = 0; upper = 1;
1333 gROOT->Error(
"TEfficiency::BayesianShortest",
"Invalid input parameters - return [0,1]");
1338 double mode = BetaMode(a,b);
1341 upper = ROOT::Math::beta_quantile(level, a, b);
1345 lower = ROOT::Math::beta_quantile_c(level, a, b);
1352 if ( a==b && a<=1.0) {
1353 lower = BetaCentralInterval(level,a,b,kFALSE);
1354 upper = BetaCentralInterval(level,a,b,kTRUE);
1360 Beta_interval_length intervalLength(level,a,b);
1362 ROOT::Math::WrappedFunction<const Beta_interval_length &> func(intervalLength);
1363 ROOT::Math::BrentMinimizer1D minim;
1364 minim.SetFunction(func, 0, intervalLength.LowerMax() );
1366 bool ret = minim.Minimize(100, 1.E-10,1.E-10);
1368 gROOT->Error(
"TEfficiency::BayesianShortes",
"Error finding the shortest interval");
1371 lower = minim.XMinimum();
1372 upper = lower + minim.FValMinimum();
1383 Double_t TEfficiency::BetaMean(Double_t a,Double_t b)
1385 if (a <= 0 || b <= 0 ) {
1386 gROOT->Error(
"TEfficiency::BayesianMean",
"Invalid input parameters - return 0");
1390 Double_t mean = a / (a + b);
1406 Double_t TEfficiency::BetaMode(Double_t a,Double_t b)
1408 if (a <= 0 || b <= 0 ) {
1409 gROOT->Error(
"TEfficiency::BayesianMode",
"Invalid input parameters - return 0");
1412 if ( a <= 1 || b <= 1) {
1413 if ( a < b)
return 0;
1414 if ( a > b)
return 1;
1415 if (a == b)
return 0.5;
1419 Double_t mode = (a - 1.0) / (a + b -2.0);
1430 void TEfficiency::Build(
const char* name,
const char* title)
1435 SetStatisticOption(kDefStatOpt);
1436 SetDirectory(gDirectory);
1438 SetBit(kPosteriorMode,
false);
1439 SetBit(kShortestInterval,
false);
1440 SetBit(kUseWeights,
false);
1443 fPassedHistogram->SetNormFactor(0);
1444 fTotalHistogram->SetNormFactor(0);
1452 Bool_t TEfficiency::CheckBinning(
const TH1& pass,
const TH1& total)
1455 const TAxis* ax1 = 0;
1456 const TAxis* ax2 = 0;
1459 for(Int_t j = 0; j < pass.GetDimension(); ++j) {
1462 ax1 = pass.GetXaxis();
1463 ax2 = total.GetXaxis();
1466 ax1 = pass.GetYaxis();
1467 ax2 = total.GetYaxis();
1470 ax1 = pass.GetZaxis();
1471 ax2 = total.GetZaxis();
1475 if(ax1->GetNbins() != ax2->GetNbins()) {
1476 gROOT->Info(
"TEfficiency::CheckBinning",
"Histograms are not consistent: they have different number of bins");
1480 for(Int_t i = 1; i <= ax1->GetNbins() + 1; ++i)
1481 if(!TMath::AreEqualRel(ax1->GetBinLowEdge(i), ax2->GetBinLowEdge(i), 1.E-15)) {
1482 gROOT->Info(
"TEfficiency::CheckBinning",
"Histograms are not consistent: they have different bin edges");
1501 Bool_t TEfficiency::CheckConsistency(
const TH1& pass,
const TH1& total, Option_t*)
1503 if(pass.GetDimension() != total.GetDimension()) {
1504 gROOT->Error(
"TEfficiency::CheckConsistency",
"passed TEfficiency objects have different dimensions");
1508 if(!CheckBinning(pass,total)) {
1509 gROOT->Error(
"TEfficiency::CheckConsistency",
"passed TEfficiency objects have different binning");
1513 if(!CheckEntries(pass,total)) {
1514 gROOT->Error(
"TEfficiency::CheckConsistency",
"passed TEfficiency objects do not have consistent bin contents");
1533 Bool_t TEfficiency::CheckEntries(
const TH1& pass,
const TH1& total, Option_t*)
1537 Int_t nbinsx, nbinsy, nbinsz, nbins;
1539 nbinsx = pass.GetNbinsX();
1540 nbinsy = pass.GetNbinsY();
1541 nbinsz = pass.GetNbinsZ();
1543 switch(pass.GetDimension()) {
1544 case 1: nbins = nbinsx + 2;
break;
1545 case 2: nbins = (nbinsx + 2) * (nbinsy + 2);
break;
1546 case 3: nbins = (nbinsx + 2) * (nbinsy + 2) * (nbinsz + 2);
break;
1550 for(Int_t i = 0; i < nbins; ++i) {
1551 if(pass.GetBinContent(i) > total.GetBinContent(i)) {
1552 gROOT->Info(
"TEfficiency::CheckEntries",
"Histograms are not consistent: passed bin content > total bin content");
1563 Bool_t TEfficiency::CheckWeights(
const TH1& pass,
const TH1& total)
1565 if (pass.GetSumw2N() == 0 && total.GetSumw2N() == 0)
return false;
1568 Double_t statpass[TH1::kNstat];
1569 Double_t stattotal[TH1::kNstat];
1571 pass.GetStats(statpass);
1572 total.GetStats(stattotal);
1574 double tolerance = (total.IsA() == TH1F::Class() ) ? 1.E-5 : 1.E-12;
1577 if(!TMath::AreEqualRel(statpass[0],statpass[1],tolerance) ||
1578 !TMath::AreEqualRel(stattotal[0],stattotal[1],tolerance) ) {
1592 TGraphAsymmErrors * TEfficiency::CreateGraph(Option_t * opt)
const
1594 if (GetDimension() != 1) {
1595 Error(
"CreatePaintingGraph",
"Call this function only for dimension == 1");
1600 Int_t npoints = fTotalHistogram->GetNbinsX();
1601 TGraphAsymmErrors * graph =
new TGraphAsymmErrors(npoints);
1602 graph->SetName(
"eff_graph");
1603 FillGraph(graph,opt);
1613 void TEfficiency::FillGraph(TGraphAsymmErrors * graph, Option_t * opt)
const
1615 TString option = opt;
1618 Bool_t plot0Bins =
false;
1619 if (option.Contains(
"e0") ) plot0Bins =
true;
1621 Double_t x,y,xlow,xup,ylow,yup;
1628 double * px = graph->GetX();
1629 double * py = graph->GetY();
1630 double * exl = graph->GetEXlow();
1631 double * exh = graph->GetEXhigh();
1632 double * eyl = graph->GetEYlow();
1633 double * eyh = graph->GetEYhigh();
1634 Int_t npoints = fTotalHistogram->GetNbinsX();
1635 for (Int_t i = 0; i < npoints; ++i) {
1636 if (!plot0Bins && fTotalHistogram->GetBinContent(i+1) == 0 )
continue;
1637 x = fTotalHistogram->GetBinCenter(i+1);
1638 y = GetEfficiency(i+1);
1639 xlow = fTotalHistogram->GetBinCenter(i+1) - fTotalHistogram->GetBinLowEdge(i+1);
1640 xup = fTotalHistogram->GetBinWidth(i+1) - xlow;
1641 ylow = GetEfficiencyErrorLow(i+1);
1642 yup = GetEfficiencyErrorUp(i+1);
1644 if (j >= graph->GetN() ) {
1645 graph->SetPoint(j,x,y);
1646 graph->SetPointError(j,xlow,xup,ylow,yup);
1662 TString oldTitle = graph->GetTitle();
1663 TString newTitle = GetTitle();
1664 if (oldTitle != newTitle ) {
1665 graph->SetTitle(newTitle);
1669 TString xlabel = fTotalHistogram->GetXaxis()->GetTitle();
1670 TString ylabel = fTotalHistogram->GetYaxis()->GetTitle();
1671 if (xlabel) graph->GetXaxis()->SetTitle(xlabel);
1672 if (ylabel) graph->GetYaxis()->SetTitle(ylabel);
1675 TAttLine::Copy(*graph);
1676 TAttFill::Copy(*graph);
1677 TAttMarker::Copy(*graph);
1681 graph->GetHistogram();
1689 TH2 * TEfficiency::CreateHistogram(Option_t *)
const
1691 if (GetDimension() != 2) {
1692 Error(
"CreatePaintingistogram",
"Call this function only for dimension == 2");
1696 Int_t nbinsx = fTotalHistogram->GetNbinsX();
1697 Int_t nbinsy = fTotalHistogram->GetNbinsY();
1698 TAxis * xaxis = fTotalHistogram->GetXaxis();
1699 TAxis * yaxis = fTotalHistogram->GetYaxis();
1702 if (xaxis->IsVariableBinSize() && yaxis->IsVariableBinSize() )
1703 hist =
new TH2F(
"eff_histo",GetTitle(),nbinsx,xaxis->GetXbins()->GetArray(),
1704 nbinsy,yaxis->GetXbins()->GetArray());
1705 else if (xaxis->IsVariableBinSize() && ! yaxis->IsVariableBinSize() )
1706 hist =
new TH2F(
"eff_histo",GetTitle(),nbinsx,xaxis->GetXbins()->GetArray(),
1707 nbinsy,yaxis->GetXmin(), yaxis->GetXmax());
1708 else if (!xaxis->IsVariableBinSize() && yaxis->IsVariableBinSize() )
1709 hist =
new TH2F(
"eff_histo",GetTitle(),nbinsx,xaxis->GetXmin(), xaxis->GetXmax(),
1710 nbinsy,yaxis->GetXbins()->GetArray());
1712 hist =
new TH2F(
"eff_histo",GetTitle(),nbinsx,xaxis->GetXmin(), xaxis->GetXmax(),
1713 nbinsy,yaxis->GetXmin(), yaxis->GetXmax());
1716 hist->SetDirectory(0);
1718 FillHistogram(hist);
1727 void TEfficiency::FillHistogram(TH2 * hist )
const
1730 hist->SetTitle(GetTitle());
1733 TString xlabel = fTotalHistogram->GetXaxis()->GetTitle();
1734 TString ylabel = fTotalHistogram->GetYaxis()->GetTitle();
1735 TString zlabel = fTotalHistogram->GetZaxis()->GetTitle();
1736 if (xlabel) hist->GetXaxis()->SetTitle(xlabel);
1737 if (ylabel) hist->GetYaxis()->SetTitle(ylabel);
1738 if (zlabel) hist->GetZaxis()->SetTitle(zlabel);
1741 Int_t nbinsx = hist->GetNbinsX();
1742 Int_t nbinsy = hist->GetNbinsY();
1743 for(Int_t i = 0; i < nbinsx + 2; ++i) {
1744 for(Int_t j = 0; j < nbinsy + 2; ++j) {
1745 bin = GetGlobalBin(i,j);
1746 hist->SetBinContent(bin,GetEfficiency(bin));
1751 TAttLine::Copy(*hist);
1752 TAttFill::Copy(*hist);
1753 TAttMarker::Copy(*hist);
1803 Double_t TEfficiency::ClopperPearson(Double_t total,Double_t passed,Double_t level,Bool_t bUpper)
1805 Double_t alpha = (1.0 - level) / 2;
1807 return ((passed == total) ? 1.0 : ROOT::Math::beta_quantile(1 - alpha,passed + 1,total-passed));
1809 return ((passed == 0) ? 0.0 : ROOT::Math::beta_quantile(alpha,passed,total-passed+1.0));
1899 Double_t TEfficiency::Combine(Double_t& up,Double_t& low,Int_t n,
1900 const Int_t* pass,
const Int_t* total,
1901 Double_t alpha, Double_t beta,
1902 Double_t level,
const Double_t* w,Option_t* opt)
1904 TString option(opt);
1916 for (
int i = 0; i < n ; ++i) {
1917 if(pass[i] > total[i]) {
1918 ::Error(
"TEfficiency::Combine",
"total events = %i < passed events %i",total[i],pass[i]);
1919 ::Info(
"TEfficiency::Combine",
"stop combining");
1923 ntot += w[i] * total[i];
1924 ktot += w[i] * pass[i];
1929 double norm = sumw/sumw2;
1933 ::Error(
"TEfficiency::Combine",
"total = %f < passed %f",ntot,ktot);
1934 ::Info(
"TEfficiency::Combine",
"stop combining");
1938 double a = ktot + alpha;
1939 double b = ntot - ktot + beta;
1941 double mean = a/(a+b);
1942 double mode = BetaMode(a,b);
1945 Bool_t shortestInterval = option.Contains(
"sh") || ( option.Contains(
"mode") && !option.Contains(
"cent") );
1947 if (shortestInterval)
1948 BetaShortestInterval(level, a, b, low, up);
1950 low = BetaCentralInterval(level, a, b,
false);
1951 up = BetaCentralInterval(level, a, b,
true);
1954 if (option.Contains(
"mode"))
return mode;
1989 TGraphAsymmErrors* TEfficiency::Combine(TCollection* pList,Option_t* option,
1990 Int_t n,
const Double_t* w)
1992 TString opt = option;
1996 Double_t alpha = -1;
2001 Bool_t bStrict =
false;
2002 Bool_t bOutput =
false;
2003 Bool_t bWeights =
false;
2005 std::vector<TH1*> vTotal; vTotal.reserve(n);
2006 std::vector<TH1*> vPassed; vPassed.reserve(n);
2007 std::vector<Double_t> vWeights; vWeights.reserve(n);
2011 if(opt.Contains(
"s")) {
2012 opt.ReplaceAll(
"s",
"");
2016 if(opt.Contains(
"v")) {
2017 opt.ReplaceAll(
"v",
"");
2021 if(opt.Contains(
"cl=")) {
2022 Ssiz_t pos = opt.Index(
"cl=") + 3;
2023 level = atof( opt(pos,opt.Length() ).Data() );
2024 if((level <= 0) || (level >= 1))
2026 opt.ReplaceAll(
"cl=",
"");
2032 for(Int_t k = 0; k < n; ++k) {
2034 vWeights.push_back(w[k]);
2036 gROOT->Error(
"TEfficiency::Combine",
"invalid custom weight found w = %.2lf",w[k]);
2037 gROOT->Info(
"TEfficiency::Combine",
"stop combining");
2045 TEfficiency* pEff = 0;
2046 while((obj = next())) {
2047 pEff =
dynamic_cast<TEfficiency*
>(obj);
2050 if(pEff->GetDimension() > 1)
2052 if(!level) level = pEff->GetConfidenceLevel();
2054 if(alpha<1) alpha = pEff->GetBetaAlpha();
2055 if(beta<1) beta = pEff->GetBetaBeta();
2059 if(alpha != pEff->GetBetaAlpha())
2061 if(beta != pEff->GetBetaBeta())
2063 if(!pEff->UsesBayesianStat())
2067 vTotal.push_back(pEff->fTotalHistogram);
2068 vPassed.push_back(pEff->fPassedHistogram);
2072 vWeights.push_back(pEff->fWeight);
2087 if(vTotal.empty()) {
2088 gROOT->Error(
"TEfficiency::Combine",
"no TEfficiency objects in given list");
2089 gROOT->Info(
"TEfficiency::Combine",
"stop combining");
2094 if(bWeights && (n != (Int_t)vTotal.size())) {
2095 gROOT->Error(
"TEfficiency::Combine",
"number of weights n=%i differs from number of TEfficiency objects k=%i which should be combined",n,(Int_t)vTotal.size());
2096 gROOT->Info(
"TEfficiency::Combine",
"stop combining");
2100 Int_t nbins_max = vTotal.at(0)->GetNbinsX();
2102 for(UInt_t i=0; i<vTotal.size(); ++i) {
2103 if (!TEfficiency::CheckBinning(*vTotal.at(0),*vTotal.at(i)) )
2104 gROOT->Warning(
"TEfficiency::Combine",
"histograms have not the same binning -> results may be useless");
2105 if(vTotal.at(i)->GetNbinsX() < nbins_max) nbins_max = vTotal.at(i)->GetNbinsX();
2110 gROOT->Info(
"TEfficiency::Combine",
"combining %i TEfficiency objects",(Int_t)vTotal.size());
2112 gROOT->Info(
"TEfficiency::Combine",
"using custom weights");
2114 gROOT->Info(
"TEfficiency::Combine",
"using the following prior probability for the efficiency: P(e) ~ Beta(e,%.3lf,%.3lf)",alpha,beta);
2117 gROOT->Info(
"TEfficiency::Combine",
"using individual priors of each TEfficiency object");
2118 gROOT->Info(
"TEfficiency::Combine",
"confidence level = %.2lf",level);
2122 std::vector<Double_t> x(nbins_max);
2123 std::vector<Double_t> xlow(nbins_max);
2124 std::vector<Double_t> xhigh(nbins_max);
2125 std::vector<Double_t> eff(nbins_max);
2126 std::vector<Double_t> efflow(nbins_max);
2127 std::vector<Double_t> effhigh(nbins_max);
2131 Int_t num = vTotal.size();
2132 std::vector<Int_t> pass(num);
2133 std::vector<Int_t> total(num);
2138 for(Int_t i=1; i <= nbins_max; ++i) {
2140 x[i-1] = vTotal.at(0)->GetBinCenter(i);
2141 xlow[i-1] = x[i-1] - vTotal.at(0)->GetBinLowEdge(i);
2142 xhigh[i-1] = vTotal.at(0)->GetBinWidth(i) - xlow[i-1];
2144 for(Int_t j = 0; j < num; ++j) {
2145 pass[j] = (Int_t)(vPassed.at(j)->GetBinContent(i) + 0.5);
2146 total[j] = (Int_t)(vTotal.at(j)->GetBinContent(i) + 0.5);
2150 eff[i-1] = Combine(up,low,num,&pass[0],&total[0],alpha,beta,level,&vWeights[0],opt.Data());
2152 if(eff[i-1] == -1) {
2153 gROOT->Error(
"TEfficiency::Combine",
"error occurred during combining");
2154 gROOT->Info(
"TEfficiency::Combine",
"stop combining");
2157 efflow[i-1]= eff[i-1] - low;
2158 effhigh[i-1]= up - eff[i-1];
2161 TGraphAsymmErrors* gr =
new TGraphAsymmErrors(nbins_max,&x[0],&eff[0],&xlow[0],&xhigh[0],&efflow[0],&effhigh[0]);
2174 Int_t TEfficiency::DistancetoPrimitive(Int_t px, Int_t py)
2176 if (fPaintGraph)
return fPaintGraph->DistancetoPrimitive(px,py);
2177 if (fPaintHisto)
return fPaintHisto->DistancetoPrimitive(px,py);
2195 void TEfficiency::Draw(Option_t* opt)
2198 TString option = opt;
2201 if (option.IsNull() ) option =
"ap";
2203 if(gPad && !option.Contains(
"same"))
2207 if (!option.Contains(
"a") ) option +=
"a";
2211 if (!option.Contains(
"p") ) option +=
"p";
2214 AppendPad(option.Data());
2228 void TEfficiency::ExecuteEvent(Int_t event, Int_t px, Int_t py)
2230 if (fPaintGraph) fPaintGraph->ExecuteEvent(event,px,py);
2231 else if (fPaintHisto) fPaintHisto->ExecuteEvent(event,px,py);
2244 void TEfficiency::Fill(Bool_t bPassed,Double_t x,Double_t y,Double_t z)
2246 switch(GetDimension()) {
2248 fTotalHistogram->Fill(x);
2250 fPassedHistogram->Fill(x);
2253 ((TH2*)(fTotalHistogram))->Fill(x,y);
2255 ((TH2*)(fPassedHistogram))->Fill(x,y);
2258 ((TH3*)(fTotalHistogram))->Fill(x,y,z);
2260 ((TH3*)(fPassedHistogram))->Fill(x,y,z);
2278 void TEfficiency::FillWeighted(Bool_t bPassed,Double_t weight,Double_t x,Double_t y,Double_t z)
2280 if(!TestBit(kUseWeights))
2283 SetUseWeightedEvents();
2286 switch(GetDimension()) {
2288 fTotalHistogram->Fill(x,weight);
2290 fPassedHistogram->Fill(x,weight);
2293 ((TH2*)(fTotalHistogram))->Fill(x,y,weight);
2295 ((TH2*)(fPassedHistogram))->Fill(x,y,weight);
2298 ((TH3*)(fTotalHistogram))->Fill(x,y,z,weight);
2300 ((TH3*)(fPassedHistogram))->Fill(x,y,z,weight);
2314 Int_t TEfficiency::FindFixBin(Double_t x,Double_t y,Double_t z)
const
2316 Int_t nx = fTotalHistogram->GetXaxis()->FindFixBin(x);
2320 switch(GetDimension()) {
2321 case 3: nz = fTotalHistogram->GetZaxis()->FindFixBin(z);
2322 case 2: ny = fTotalHistogram->GetYaxis()->FindFixBin(y);
break;
2325 return GetGlobalBin(nx,ny,nz);
2338 TFitResultPtr TEfficiency::Fit(TF1* f1,Option_t* opt)
2340 TString option = opt;
2344 Bool_t bDeleteOld =
true;
2345 if(option.Contains(
"+")) {
2346 option.ReplaceAll(
"+",
"");
2350 TBinomialEfficiencyFitter Fitter(fPassedHistogram,fTotalHistogram);
2352 TFitResultPtr result = Fitter.Fit(f1,option.Data());
2355 TF1* pFunc =
new TF1(*f1);
2358 TIter next(fFunctions);
2360 while((obj = next())) {
2361 if(obj->InheritsFrom(TF1::Class())) {
2362 fFunctions->Remove(obj);
2370 fFunctions =
new TList();
2372 fFunctions->Add(pFunc);
2398 TH1* TEfficiency::GetCopyPassedHisto()
const
2400 Bool_t bStatus = TH1::AddDirectoryStatus();
2401 TH1::AddDirectory(kFALSE);
2402 TH1* tmp = (TH1*)(fPassedHistogram->Clone());
2403 TH1::AddDirectory(bStatus);
2429 TH1* TEfficiency::GetCopyTotalHisto()
const
2431 Bool_t bStatus = TH1::AddDirectoryStatus();
2432 TH1::AddDirectory(kFALSE);
2433 TH1* tmp = (TH1*)(fTotalHistogram->Clone());
2434 TH1::AddDirectory(bStatus);
2442 Int_t TEfficiency::GetDimension()
const
2444 return fTotalHistogram->GetDimension();
2464 Double_t TEfficiency::GetEfficiency(Int_t bin)
const
2466 Double_t total = fTotalHistogram->GetBinContent(bin);
2467 Double_t passed = fPassedHistogram->GetBinContent(bin);
2469 if(TestBit(kIsBayesian)) {
2472 Double_t alpha = TestBit(kUseBinPrior) ? GetBetaAlpha(bin) : GetBetaAlpha();
2473 Double_t beta = TestBit(kUseBinPrior) ? GetBetaBeta(bin) : GetBetaBeta();
2476 if(TestBit(kUseWeights))
2478 Double_t tw = fTotalHistogram->GetBinContent(bin);
2479 Double_t tw2 = fTotalHistogram->GetSumw2()->At(bin);
2480 Double_t pw = fPassedHistogram->GetBinContent(bin);
2482 if (tw2 <= 0 )
return pw/tw;
2485 double norm = tw/tw2;
2486 aa = pw * norm + alpha;
2487 bb = (tw - pw) * norm + beta;
2491 aa = passed + alpha;
2492 bb = total - passed + beta;
2495 if (!TestBit(kPosteriorMode) )
2496 return BetaMean(aa,bb);
2498 return BetaMode(aa,bb);
2502 return (total)? ((Double_t)passed)/total : 0;
2515 Double_t TEfficiency::GetEfficiencyErrorLow(Int_t bin)
const
2517 Double_t total = fTotalHistogram->GetBinContent(bin);
2518 Double_t passed = fPassedHistogram->GetBinContent(bin);
2520 Double_t eff = GetEfficiency(bin);
2523 if(TestBit(kUseWeights))
2525 Double_t tw = fTotalHistogram->GetBinContent(bin);
2526 Double_t tw2 = fTotalHistogram->GetSumw2()->At(bin);
2527 Double_t pw = fPassedHistogram->GetBinContent(bin);
2528 Double_t pw2 = fPassedHistogram->GetSumw2()->At(bin);
2530 if(TestBit(kIsBayesian))
2532 Double_t alpha = TestBit(kUseBinPrior) ? GetBetaAlpha(bin) : GetBetaAlpha();
2533 Double_t beta = TestBit(kUseBinPrior) ? GetBetaBeta(bin) : GetBetaBeta();
2535 if (tw2 <= 0)
return 0;
2538 Double_t norm = tw/tw2;
2539 Double_t aa = pw * norm + alpha;
2540 Double_t bb = (tw - pw) * norm + beta;
2543 if(TestBit(kShortestInterval)) {
2544 TEfficiency::BetaShortestInterval(fConfLevel,aa,bb,low,upper);
2547 low = TEfficiency::BetaCentralInterval(fConfLevel,aa,bb,
false);
2554 if(fStatisticOption != kFNormal)
2556 Warning(
"GetEfficiencyErrorLow",
"frequentist confidence intervals for weights are only supported by the normal approximation");
2557 Info(
"GetEfficiencyErrorLow",
"setting statistic option to kFNormal");
2558 const_cast<TEfficiency*
>(
this)->SetStatisticOption(kFNormal);
2561 Double_t variance = ( pw2 * (1. - 2 * eff) + tw2 * eff *eff ) / ( tw * tw) ;
2562 Double_t sigma = sqrt(variance);
2564 Double_t prob = 0.5 * (1.- fConfLevel);
2565 Double_t delta = ROOT::Math::normal_quantile_c(prob, sigma);
2568 return (eff - delta < 0) ? eff : delta;
2573 if(TestBit(kIsBayesian))
2576 Double_t alpha = TestBit(kUseBinPrior) ? GetBetaAlpha(bin) : GetBetaAlpha();
2577 Double_t beta = TestBit(kUseBinPrior) ? GetBetaBeta(bin) : GetBetaBeta();
2578 return (eff - Bayesian(total,passed,fConfLevel,alpha,beta,
false,TestBit(kShortestInterval)));
2581 return (eff - fBoundary(total,passed,fConfLevel,
false));
2595 Double_t TEfficiency::GetEfficiencyErrorUp(Int_t bin)
const
2597 Double_t total = fTotalHistogram->GetBinContent(bin);
2598 Double_t passed = fPassedHistogram->GetBinContent(bin);
2600 Double_t eff = GetEfficiency(bin);
2603 if(TestBit(kUseWeights))
2605 Double_t tw = fTotalHistogram->GetBinContent(bin);
2606 Double_t tw2 = fTotalHistogram->GetSumw2()->At(bin);
2607 Double_t pw = fPassedHistogram->GetBinContent(bin);
2608 Double_t pw2 = fPassedHistogram->GetSumw2()->At(bin);
2610 if(TestBit(kIsBayesian))
2612 Double_t alpha = TestBit(kUseBinPrior) ? GetBetaAlpha(bin) : GetBetaAlpha();
2613 Double_t beta = TestBit(kUseBinPrior) ? GetBetaBeta(bin) : GetBetaBeta();
2615 if (tw2 <= 0)
return 0;
2618 Double_t norm = tw/tw2;
2619 Double_t aa = pw * norm + alpha;
2620 Double_t bb = (tw - pw) * norm + beta;
2623 if(TestBit(kShortestInterval)) {
2624 TEfficiency::BetaShortestInterval(fConfLevel,aa,bb,low,upper);
2627 upper = TEfficiency::BetaCentralInterval(fConfLevel,aa,bb,
true);
2634 if(fStatisticOption != kFNormal)
2636 Warning(
"GetEfficiencyErrorUp",
"frequentist confidence intervals for weights are only supported by the normal approximation");
2637 Info(
"GetEfficiencyErrorUp",
"setting statistic option to kFNormal");
2638 const_cast<TEfficiency*
>(
this)->SetStatisticOption(kFNormal);
2641 Double_t variance = ( pw2 * (1. - 2 * eff) + tw2 * eff *eff ) / ( tw * tw) ;
2642 Double_t sigma = sqrt(variance);
2644 Double_t prob = 0.5 * (1.- fConfLevel);
2645 Double_t delta = ROOT::Math::normal_quantile_c(prob, sigma);
2647 return (eff + delta > 1) ? 1.-eff : delta;
2652 if(TestBit(kIsBayesian))
2655 Double_t alpha = TestBit(kUseBinPrior) ? GetBetaAlpha(bin) : GetBetaAlpha();
2656 Double_t beta = TestBit(kUseBinPrior) ? GetBetaBeta(bin) : GetBetaBeta();
2657 return (Bayesian(total,passed,fConfLevel,alpha,beta,
true,TestBit(kShortestInterval)) - eff);
2660 return fBoundary(total,passed,fConfLevel,
true) - eff;
2673 Int_t TEfficiency::GetGlobalBin(Int_t binx,Int_t biny,Int_t binz)
const
2675 return fTotalHistogram->GetBin(binx,biny,binz);
2680 TList* TEfficiency::GetListOfFunctions()
2682 return (fFunctions) ? fFunctions : fFunctions =
new TList();
2698 Long64_t TEfficiency::Merge(TCollection* pList)
2700 if(!pList->IsEmpty()) {
2703 TEfficiency* pEff = 0;
2704 while((obj = next())) {
2705 pEff =
dynamic_cast<TEfficiency*
>(obj);
2711 return (Long64_t)fTotalHistogram->GetEntries();
2735 Double_t TEfficiency::Normal(Double_t total,Double_t passed,Double_t level,Bool_t bUpper)
2737 Double_t alpha = (1.0 - level)/2;
2738 if (total == 0)
return (bUpper) ? 1 : 0;
2739 Double_t average = passed / total;
2740 Double_t sigma = std::sqrt(average * (1 - average) / total);
2741 Double_t delta = ROOT::Math::normal_quantile(1 - alpha,sigma);
2744 return ((average + delta) > 1) ? 1.0 : (average + delta);
2746 return ((average - delta) < 0) ? 0.0 : (average - delta);
2762 TEfficiency& TEfficiency::operator+=(
const TEfficiency& rhs)
2765 if (fTotalHistogram == 0 && fPassedHistogram == 0) {
2770 else if (fTotalHistogram == 0 || fPassedHistogram == 0) {
2771 Fatal(
"operator+=",
"Adding to a non consistent TEfficiency object which has not a total or a passed histogram ");
2775 if (rhs.fTotalHistogram == 0 && rhs.fPassedHistogram == 0 ) {
2776 Warning(
"operator+=",
"no operation: adding an empty object");
2779 else if (rhs.fTotalHistogram == 0 || rhs.fPassedHistogram == 0 ) {
2780 Fatal(
"operator+=",
"Adding a non consistent TEfficiency object which has not a total or a passed histogram ");
2784 fTotalHistogram->ResetBit(TH1::kIsAverage);
2785 fPassedHistogram->ResetBit(TH1::kIsAverage);
2787 fTotalHistogram->Add(rhs.fTotalHistogram);
2788 fPassedHistogram->Add(rhs.fPassedHistogram);
2790 SetWeight((fWeight * rhs.GetWeight())/(fWeight + rhs.GetWeight()));
2804 TEfficiency& TEfficiency::operator=(
const TEfficiency& rhs)
2809 SetStatisticOption(rhs.GetStatisticOption());
2810 SetConfidenceLevel(rhs.GetConfidenceLevel());
2811 SetBetaAlpha(rhs.GetBetaAlpha());
2812 SetBetaBeta(rhs.GetBetaBeta());
2813 SetWeight(rhs.GetWeight());
2817 fFunctions->Delete();
2820 delete fTotalHistogram;
2821 delete fPassedHistogram;
2823 Bool_t bStatus = TH1::AddDirectoryStatus();
2824 TH1::AddDirectory(kFALSE);
2825 fTotalHistogram = (TH1*)(rhs.fTotalHistogram->Clone());
2826 fPassedHistogram = (TH1*)(rhs.fPassedHistogram->Clone());
2827 TH1::AddDirectory(bStatus);
2836 rhs.TAttLine::Copy(*
this);
2837 rhs.TAttFill::Copy(*
this);
2838 rhs.TAttMarker::Copy(*
this);
2862 void TEfficiency::Paint(
const Option_t* opt)
2871 if(GetDimension() == 1) {
2873 fPaintGraph = CreateGraph(opt);
2877 FillGraph(fPaintGraph, opt);
2881 fPaintGraph->Paint(opt);
2888 TIter next(fFunctions);
2890 while((obj = next())) {
2891 if(obj->InheritsFrom(TF1::Class())) {
2892 fPaintGraph->PaintStats((TF1*)obj);
2893 ((TF1*)obj)->Paint(
"sameC");
2902 if(GetDimension() == 2) {
2904 fPaintHisto = CreateHistogram();
2907 FillHistogram(fPaintHisto);
2910 fPaintHisto->Paint(opt);
2913 Warning(
"Paint",
"Painting 3D efficiency is not implemented");
2919 void TEfficiency::SavePrimitive(std::ostream& out,Option_t* opt)
2921 Bool_t equi_bins =
true;
2924 TString indent =
" ";
2927 static Int_t naxis = 0;
2928 TString sxaxis=
"xAxis",syaxis=
"yAxis",szaxis=
"zAxis";
2931 switch(GetDimension()) {
2933 equi_bins = equi_bins && !fTotalHistogram->GetZaxis()->GetXbins()->fArray
2934 && !fTotalHistogram->GetZaxis()->GetXbins()->fN;
2936 equi_bins = equi_bins && !fTotalHistogram->GetYaxis()->GetXbins()->fArray
2937 && !fTotalHistogram->GetYaxis()->GetXbins()->fN;
2939 equi_bins = equi_bins && !fTotalHistogram->GetXaxis()->GetXbins()->fArray
2940 && !fTotalHistogram->GetXaxis()->GetXbins()->fN;
2951 out << indent <<
"Double_t " << sxaxis <<
"["
2952 << fTotalHistogram->GetXaxis()->GetXbins()->fN <<
"] = {";
2953 for (i = 0; i < fTotalHistogram->GetXaxis()->GetXbins()->fN; ++i) {
2954 if (i != 0) out <<
", ";
2955 out << fTotalHistogram->GetXaxis()->GetXbins()->fArray[i];
2957 out <<
"}; " << std::endl;
2959 if(GetDimension() > 1) {
2960 out << indent <<
"Double_t " << syaxis <<
"["
2961 << fTotalHistogram->GetYaxis()->GetXbins()->fN <<
"] = {";
2962 for (i = 0; i < fTotalHistogram->GetYaxis()->GetXbins()->fN; ++i) {
2963 if (i != 0) out <<
", ";
2964 out << fTotalHistogram->GetYaxis()->GetXbins()->fArray[i];
2966 out <<
"}; " << std::endl;
2969 if(GetDimension() > 2) {
2970 out << indent <<
"Double_t " << szaxis <<
"["
2971 << fTotalHistogram->GetZaxis()->GetXbins()->fN <<
"] = {";
2972 for (i = 0; i < fTotalHistogram->GetZaxis()->GetXbins()->fN; ++i) {
2973 if (i != 0) out <<
", ";
2974 out << fTotalHistogram->GetZaxis()->GetXbins()->fArray[i];
2976 out <<
"}; " << std::endl;
2981 static Int_t eff_count = 0;
2983 TString eff_name = GetName();
2984 eff_name += eff_count;
2986 const char* name = eff_name.Data();
2989 const char quote =
'"';
2990 out << indent << std::endl;
2991 out << indent << ClassName() <<
" * " << name <<
" = new " << ClassName()
2992 <<
"(" << quote << GetName() << quote <<
"," << quote
2993 << GetTitle() << quote <<
",";
2996 out << fTotalHistogram->GetXaxis()->GetNbins() <<
","
2997 << fTotalHistogram->GetXaxis()->GetXmin() <<
","
2998 << fTotalHistogram->GetXaxis()->GetXmax();
2999 if(GetDimension() > 1) {
3000 out <<
"," << fTotalHistogram->GetYaxis()->GetNbins() <<
","
3001 << fTotalHistogram->GetYaxis()->GetXmin() <<
","
3002 << fTotalHistogram->GetYaxis()->GetXmax();
3004 if(GetDimension() > 2) {
3005 out <<
"," << fTotalHistogram->GetZaxis()->GetNbins() <<
","
3006 << fTotalHistogram->GetZaxis()->GetXmin() <<
","
3007 << fTotalHistogram->GetZaxis()->GetXmax();
3012 out << fTotalHistogram->GetXaxis()->GetNbins() <<
"," << sxaxis;
3013 if(GetDimension() > 1)
3014 out <<
"," << fTotalHistogram->GetYaxis()->GetNbins() <<
","
3016 if(GetDimension() > 2)
3017 out <<
"," << fTotalHistogram->GetZaxis()->GetNbins() <<
","
3020 out <<
");" << std::endl;
3021 out << indent << std::endl;
3024 out << indent << name <<
"->SetConfidenceLevel(" << fConfLevel <<
");"
3026 out << indent << name <<
"->SetBetaAlpha(" << fBeta_alpha <<
");"
3028 out << indent << name <<
"->SetBetaBeta(" << fBeta_beta <<
");" << std::endl;
3029 out << indent << name <<
"->SetWeight(" << fWeight <<
");" << std::endl;
3030 out << indent << name <<
"->SetStatisticOption(" << fStatisticOption <<
");"
3032 out << indent << name <<
"->SetPosteriorMode(" << TestBit(kPosteriorMode) <<
");" << std::endl;
3033 out << indent << name <<
"->SetShortestInterval(" << TestBit(kShortestInterval) <<
");" << std::endl;
3034 if(TestBit(kUseWeights))
3035 out << indent << name <<
"->SetUseWeightedEvents();" << std::endl;
3038 for(
unsigned int i = 0; i < fBeta_bin_params.size(); ++i)
3040 out << indent << name <<
"->SetBetaBinParameters(" << i <<
"," << fBeta_bin_params.at(i).first
3041 <<
"," << fBeta_bin_params.at(i).second <<
");" << std::endl;
3045 Int_t nbins = fTotalHistogram->GetNbinsX() + 2;
3046 if(GetDimension() > 1)
3047 nbins *= fTotalHistogram->GetNbinsY() + 2;
3048 if(GetDimension() > 2)
3049 nbins *= fTotalHistogram->GetNbinsZ() + 2;
3052 for(Int_t i = 0; i < nbins; ++i) {
3053 out << indent << name <<
"->SetTotalEvents(" << i <<
"," <<
3054 fTotalHistogram->GetBinContent(i) <<
");" << std::endl;
3055 out << indent << name <<
"->SetPassedEvents(" << i <<
"," <<
3056 fPassedHistogram->GetBinContent(i) <<
");" << std::endl;
3060 TIter next(fFunctions);
3062 while((obj = next())) {
3063 obj->SavePrimitive(out,
"nodraw");
3064 if(obj->InheritsFrom(TF1::Class())) {
3065 out << indent << name <<
"->GetListOfFunctions()->Add("
3066 << obj->GetName() <<
");" << std::endl;
3071 SaveFillAttributes(out,name);
3072 SaveLineAttributes(out,name);
3073 SaveMarkerAttributes(out,name);
3076 TString option = opt;
3078 if (!option.Contains(
"nodraw"))
3079 out<< indent << name<<
"->Draw(" << quote << opt << quote <<
");"
3093 void TEfficiency::SetBetaAlpha(Double_t alpha)
3096 fBeta_alpha = alpha;
3098 Warning(
"SetBetaAlpha(Double_t)",
"invalid shape parameter %.2lf",alpha);
3111 void TEfficiency::SetBetaBeta(Double_t beta)
3116 Warning(
"SetBetaBeta(Double_t)",
"invalid shape parameter %.2lf",beta);
3132 void TEfficiency::SetBetaBinParameters(Int_t bin, Double_t alpha, Double_t beta)
3134 if (!fPassedHistogram || !fTotalHistogram)
return;
3135 TH1 * h1 = fTotalHistogram;
3137 UInt_t n = h1->GetBin(h1->GetNbinsX()+1, h1->GetNbinsY()+1, h1->GetNbinsZ()+1 ) + 1;
3140 if (fBeta_bin_params.size() != n )
3141 fBeta_bin_params = std::vector<std::pair<Double_t, Double_t> >(n, std::make_pair(fBeta_alpha, fBeta_beta) );
3144 fBeta_bin_params[bin] = std::make_pair(alpha,beta);
3145 SetBit(kUseBinPrior,
true);
3153 Bool_t TEfficiency::SetBins(Int_t nx, Double_t xmin, Double_t xmax)
3155 if (GetDimension() != 1) {
3156 Error(
"SetBins",
"Using wrong SetBins function for a %d-d histogram",GetDimension());
3159 if (fTotalHistogram->GetEntries() != 0 ) {
3160 Warning(
"SetBins",
"Histogram entries will be lost after SetBins");
3161 fPassedHistogram->Reset();
3162 fTotalHistogram->Reset();
3164 fPassedHistogram->SetBins(nx,xmin,xmax);
3165 fTotalHistogram->SetBins(nx,xmin,xmax);
3173 Bool_t TEfficiency::SetBins(Int_t nx,
const Double_t *xBins)
3175 if (GetDimension() != 1) {
3176 Error(
"SetBins",
"Using wrong SetBins function for a %d-d histogram",GetDimension());
3179 if (fTotalHistogram->GetEntries() != 0 ) {
3180 Warning(
"SetBins",
"Histogram entries will be lost after SetBins");
3181 fPassedHistogram->Reset();
3182 fTotalHistogram->Reset();
3184 fPassedHistogram->SetBins(nx,xBins);
3185 fTotalHistogram->SetBins(nx,xBins);
3193 Bool_t TEfficiency::SetBins(Int_t nx, Double_t xmin, Double_t xmax, Int_t ny, Double_t ymin, Double_t ymax)
3195 if (GetDimension() != 2) {
3196 Error(
"SetBins",
"Using wrong SetBins function for a %d-d histogram",GetDimension());
3199 if (fTotalHistogram->GetEntries() != 0 ) {
3200 Warning(
"SetBins",
"Histogram entries will be lost after SetBins");
3201 fPassedHistogram->Reset();
3202 fTotalHistogram->Reset();
3204 fPassedHistogram->SetBins(nx,xmin,xmax,ny,ymin,ymax);
3205 fTotalHistogram->SetBins(nx,xmin,xmax,ny,ymin,ymax);
3213 Bool_t TEfficiency::SetBins(Int_t nx,
const Double_t *xBins, Int_t ny,
const Double_t *yBins)
3215 if (GetDimension() != 2) {
3216 Error(
"SetBins",
"Using wrong SetBins function for a %d-d histogram",GetDimension());
3219 if (fTotalHistogram->GetEntries() != 0 ) {
3220 Warning(
"SetBins",
"Histogram entries will be lost after SetBins");
3221 fPassedHistogram->Reset();
3222 fTotalHistogram->Reset();
3224 fPassedHistogram->SetBins(nx,xBins,ny,yBins);
3225 fTotalHistogram->SetBins(nx,xBins,ny,yBins);
3233 Bool_t TEfficiency::SetBins(Int_t nx, Double_t xmin, Double_t xmax, Int_t ny, Double_t ymin, Double_t ymax,
3234 Int_t nz, Double_t zmin, Double_t zmax)
3236 if (GetDimension() != 3) {
3237 Error(
"SetBins",
"Using wrong SetBins function for a %d-d histogram",GetDimension());
3240 if (fTotalHistogram->GetEntries() != 0 ) {
3241 Warning(
"SetBins",
"Histogram entries will be lost after SetBins");
3242 fPassedHistogram->Reset();
3243 fTotalHistogram->Reset();
3245 fPassedHistogram->SetBins(nx,xmin,xmax,ny,ymin,ymax,nz,zmin,zmax);
3246 fTotalHistogram->SetBins (nx,xmin,xmax,ny,ymin,ymax,nz,zmin,zmax);
3254 Bool_t TEfficiency::SetBins(Int_t nx,
const Double_t *xBins, Int_t ny,
const Double_t *yBins, Int_t nz,
3255 const Double_t *zBins )
3257 if (GetDimension() != 3) {
3258 Error(
"SetBins",
"Using wrong SetBins function for a %d-d histogram",GetDimension());
3261 if (fTotalHistogram->GetEntries() != 0 ) {
3262 Warning(
"SetBins",
"Histogram entries will be lost after SetBins");
3263 fPassedHistogram->Reset();
3264 fTotalHistogram->Reset();
3266 fPassedHistogram->SetBins(nx,xBins,ny,yBins,nz,zBins);
3267 fTotalHistogram->SetBins(nx,xBins,ny,yBins,nz,zBins);
3275 void TEfficiency::SetConfidenceLevel(Double_t level)
3277 if((level > 0) && (level < 1))
3280 Warning(
"SetConfidenceLevel(Double_t)",
"invalid confidence level %.2lf",level);
3294 void TEfficiency::SetDirectory(TDirectory* dir)
3296 if(fDirectory == dir)
3299 fDirectory->Remove(
this);
3302 fDirectory->Append(
this);
3311 void TEfficiency::SetName(
const char* name)
3313 TNamed::SetName(name);
3316 TString name_total = name + TString(
"_total");
3317 TString name_passed = name + TString(
"_passed");
3318 fTotalHistogram->SetName(name_total);
3319 fPassedHistogram->SetName(name_passed);
3330 Bool_t TEfficiency::SetPassedEvents(Int_t bin,Int_t events)
3332 if(events <= fTotalHistogram->GetBinContent(bin)) {
3333 fPassedHistogram->SetBinContent(bin,events);
3337 Error(
"SetPassedEvents(Int_t,Int_t)",
"total number of events (%.1lf) in bin %i is less than given number of passed events %i",fTotalHistogram->GetBinContent(bin),bin,events);
3361 Bool_t TEfficiency::SetPassedHistogram(
const TH1& rPassed,Option_t* opt)
3363 TString option = opt;
3366 Bool_t bReplace = option.Contains(
"f");
3369 bReplace = CheckConsistency(rPassed,*fTotalHistogram);
3372 delete fPassedHistogram;
3373 Bool_t bStatus = TH1::AddDirectoryStatus();
3374 TH1::AddDirectory(kFALSE);
3375 fPassedHistogram = (TH1*)(rPassed.Clone());
3376 fPassedHistogram->SetNormFactor(0);
3377 TH1::AddDirectory(bStatus);
3380 fFunctions->Delete();
3383 bool useWeights = CheckWeights(rPassed,*fTotalHistogram);
3385 SetUseWeightedEvents(useWeights);
3425 void TEfficiency::SetStatisticOption(EStatOption option)
3427 fStatisticOption = option;
3432 fBoundary = &ClopperPearson;
3433 SetBit(kIsBayesian,
false);
3436 fBoundary = &Normal;
3437 SetBit(kIsBayesian,
false);
3440 fBoundary = &Wilson;
3441 SetBit(kIsBayesian,
false);
3444 fBoundary = &AgrestiCoull;
3445 SetBit(kIsBayesian,
false);
3448 fBoundary = &FeldmanCousins;
3449 SetBit(kIsBayesian,
false);
3452 fBoundary = &MidPInterval;
3453 SetBit(kIsBayesian,
false);
3458 SetBit(kIsBayesian,
true);
3459 SetBit(kUseBinPrior,
false);
3464 SetBit(kIsBayesian,
true);
3465 SetBit(kUseBinPrior,
false);
3468 SetBit(kIsBayesian,
true);
3471 fStatisticOption = kFCP;
3472 fBoundary = &ClopperPearson;
3473 SetBit(kIsBayesian,
false);
3489 void TEfficiency::SetTitle(
const char* title)
3493 TString title_passed = title;
3494 TString title_total = title;
3495 Ssiz_t pos = title_passed.First(
";");
3497 title_passed.Insert(pos,
" (passed)");
3498 title_total.Insert(pos,
" (total)");
3501 title_passed.Append(
" (passed)");
3502 title_total.Append(
" (total)");
3504 fPassedHistogram->SetTitle(title_passed);
3505 fTotalHistogram->SetTitle(title_total);
3509 TString teffTitle = fTotalHistogram->GetTitle();
3510 teffTitle.ReplaceAll(
" (total)",
"");
3511 TNamed::SetTitle(teffTitle);
3523 Bool_t TEfficiency::SetTotalEvents(Int_t bin,Int_t events)
3525 if(events >= fPassedHistogram->GetBinContent(bin)) {
3526 fTotalHistogram->SetBinContent(bin,events);
3530 Error(
"SetTotalEvents(Int_t,Int_t)",
"passed number of events (%.1lf) in bin %i is bigger than given number of total events %i",fPassedHistogram->GetBinContent(bin),bin,events);
3554 Bool_t TEfficiency::SetTotalHistogram(
const TH1& rTotal,Option_t* opt)
3556 TString option = opt;
3559 Bool_t bReplace = option.Contains(
"f");
3562 bReplace = CheckConsistency(*fPassedHistogram,rTotal);
3565 delete fTotalHistogram;
3566 Bool_t bStatus = TH1::AddDirectoryStatus();
3567 TH1::AddDirectory(kFALSE);
3568 fTotalHistogram = (TH1*)(rTotal.Clone());
3569 fTotalHistogram->SetNormFactor(0);
3570 TH1::AddDirectory(bStatus);
3573 fFunctions->Delete();
3576 bool useWeights = CheckWeights(*fPassedHistogram,rTotal);
3577 SetUseWeightedEvents(useWeights);
3587 void TEfficiency::SetUseWeightedEvents(
bool on)
3589 if (on && !TestBit(kUseWeights) )
3590 gROOT->Info(
"TEfficiency::SetUseWeightedEvents",
"Handle weighted events for computing efficiency");
3592 SetBit(kUseWeights,on);
3594 if (on && fTotalHistogram->GetSumw2N() != fTotalHistogram->GetNcells())
3595 fTotalHistogram->Sumw2();
3596 if (on && fPassedHistogram->GetSumw2N() != fTotalHistogram->GetNcells() )
3597 fPassedHistogram->Sumw2();
3605 void TEfficiency::SetWeight(Double_t weight)
3610 Warning(
"SetWeight",
"invalid weight %.2lf",weight);
3635 Double_t TEfficiency::Wilson(Double_t total,Double_t passed,Double_t level,Bool_t bUpper)
3637 Double_t alpha = (1.0 - level)/2;
3638 if (total == 0)
return (bUpper) ? 1 : 0;
3639 Double_t average = ((Double_t)passed) / total;
3640 Double_t kappa = ROOT::Math::normal_quantile(1 - alpha,1);
3642 Double_t mode = (passed + 0.5 * kappa * kappa) / (total + kappa * kappa);
3643 Double_t delta = kappa / (total + kappa*kappa) * std::sqrt(total * average
3644 * (1 - average) + kappa * kappa / 4);
3646 return ((mode + delta) > 1) ? 1.0 : (mode + delta);
3648 return ((mode - delta) < 0) ? 0.0 : (mode - delta);
3661 const TEfficiency operator+(
const TEfficiency& lhs,
const TEfficiency& rhs)
3663 TEfficiency tmp(lhs);