Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TEfficiency.cxx
Go to the documentation of this file.
1#ifndef ROOT_TEfficiency_cxx
2#define ROOT_TEfficiency_cxx
3
4//standard header
5#include <vector>
6#include <string>
7#include <cmath>
8#include <stdlib.h>
9#include <cassert>
10
11//ROOT headers
14#include "TDirectory.h"
15#include "TF1.h"
16#include "TGraphAsymmErrors.h"
17#include "TH1.h"
18#include "TH2.h"
19#include "TH3.h"
20#include "TList.h"
21#include "TMath.h"
22#include "TROOT.h"
23#include "TStyle.h"
24#include "TVirtualPad.h"
25#include "TError.h"
28
29//custom headers
30#include "TEfficiency.h"
31
32// file with extra class for FC method
33#include "TEfficiencyHelper.h"
34
35//default values
38const Double_t kDefConfLevel = 0.682689492137; // 1 sigma
41
43
44////////////////////////////////////////////////////////////////////////////////
45/** \class TEfficiency
46 \ingroup Hist
47 \brief Class to handle efficiency histograms
48
49## I. Overview
50This class handles the calculation of efficiencies and their uncertainties. It
51provides several statistical methods for calculating frequentist and Bayesian
52confidence intervals as well as a function for combining several efficiencies.
53
54Efficiencies have a lot of applications and meanings but in principle, they can
55be described by the fraction of good/passed events k out of sample containing
56N events. One is usually interested in the dependency of the efficiency on other
57(binned) variables. The number of passed and total events is therefore stored
58internally in two histograms (TEfficiency::fTotalHistogram and TEfficiency::fPassedHistogram).
59Then the efficiency, as well as its upper and lower error, can be calculated for each bin
60individually.
61
62As the efficiency can be regarded as a parameter of a binomial distribution, the
63number of passed and total events must always be integer numbers. Therefore a
64filling with weights is not possible. However, you can assign a global weight to each
65TEfficiency object (TEfficiency::SetWeight).
66It is necessary to create one TEfficiency object
67for each weight if you investigate a process involving different weights. This
68procedure needs more effort but enables you to re-use the filled object in cases
69where you want to change one or more weights. This would not be possible if all
70events with different weights were filled in the same histogram.
71
72## II. Creating a TEfficiency object
73If you start a new analysis, it is highly recommended to use the TEfficiency class
74from the beginning. You can then use one of the constructors for fixed or
75variable bin size and your desired dimension. These constructors append the
76created TEfficiency object to the current directory. So it will be written
77automatically to a file during the next TFile::Write command.
78
79Example: create a two-dimensional TEfficiency object with
80- name = "eff"
81- title = "my efficiency"
82- axis titles: x, y and LaTeX-formatted epsilon as a label for Z axis
83- 10 bins with constant bin width (= 1) along X axis starting at 0 (lower edge
84 from the first bin) up to 10 (upper edge of last bin)
85- 20 bins with constant bin width (= 0.5) along Y axis starting at -5 (lower
86 edge from the first bin) up to 5 (upper edge of last bin)
87
88 TEfficiency* pEff = new TEfficiency("eff","my efficiency;x;y;#epsilon",10,0,10,20,-5,5);
89
90If you already have two histograms filled with the number of passed and total
91events, you will use the constructor TEfficiency(const TH1& passed,const TH1& total)
92to construct the TEfficiency object. The histograms "passed" and "total" have
93to fulfill the conditions mentioned in TEfficiency::CheckConsistency, otherwise the construction will fail.
94As the histograms already exist, the new TEfficiency is by default **not** attached
95to the current directory to avoid duplication of data. If you want to store the
96new object anyway, you can either write it directly by calling TObject::Write or attach it to a directory using TEfficiency::SetDirectory.
97This also applies to TEfficiency objects created by the copy constructor TEfficiency::TEfficiency(const TEfficiency& rEff).
98
99
100### Example 1
101
102~~~~~~~~~~~~~~~{.cpp}
103TEfficiency* pEff = 0;
104TFile* pFile = new TFile("myfile.root","recreate");
105
106//h_pass and h_total are valid and consistent histograms
107if(TEfficiency::CheckConsistency(h_pass,h_total))
108{
109 pEff = new TEfficiency(h_pass,h_total);
110 // this will write the TEfficiency object to "myfile.root"
111 // AND pEff will be attached to the current directory
112 pEff->Write();
113}
114~~~~~~~~~~~~~~~
115
116### Example 2
117
118~~~~~~~~~~~~~~~{.cpp}
119TEfficiency* pEff = 0;
120TFile* pFile = new TFile("myfile.root","recreate");
121
122//h_pass and h_total are valid and consistent histograms
123if(TEfficiency::CheckConsistency(h_pass,h_total))
124{
125 pEff = new TEfficiency(h_pass,h_total);
126 //this will attach the TEfficiency object to the current directory
127 pEff->SetDirectory(gDirectory);
128 //now all objects in gDirectory will be written to "myfile.root"
129 pFile->Write();
130}
131~~~~~~~~~~~~~~~
132
133In case you already have two filled histograms and you only want to
134plot them as a graph, you should rather use TGraphAsymmErrors::TGraphAsymmErrors(const TH1* pass,const TH1* total,Option_t* opt)
135to create a graph object.
136
137## III. Filling with events
138You can fill the TEfficiency object by calling the TEfficiency::Fill(Bool_t bPassed,Double_t x,Double_t y,Double_t z) method.
139The "bPassed" boolean flag indicates whether the current event is good
140(both histograms are filled) or not (only TEfficiency::fTotalHistogram is filled).
141The x, y and z variables determine the bin which is filled. For lower dimensions, the z- or even the y-value may be omitted.
142
143Begin_Macro(source)
144{
145 //canvas only needed for this documentation
146 TCanvas* c1 = new TCanvas("example","",600,400);
147 c1->SetFillStyle(1001);
148 c1->SetFillColor(kWhite);
149
150 //create one-dimensional TEfficiency object with fixed bin size
151 TEfficiency* pEff = new TEfficiency("eff","my efficiency;x;#epsilon",20,0,10);
152 TRandom3 rand3;
153
154 bool bPassed;
155 double x;
156 for(int i=0; i<10000; ++i)
157 {
158 //simulate events with variable under investigation
159 x = rand3.Uniform(10);
160 //check selection: bPassed = DoesEventPassSelection(x)
161 bPassed = rand3.Rndm() < TMath::Gaus(x,5,4);
162 pEff->Fill(bPassed,x);
163 }
164
165 pEff->Draw("AP");
166
167 //only for this documentation
168 return c1;
169}
170End_Macro
171
172You can also set the number of passed or total events for a bin directly by
173using the TEfficiency::SetPassedEvents or TEfficiency::SetTotalEvents method.
174
175## IV. Statistic options
176The calculation of the estimated efficiency depends on the chosen statistic
177option. Let k denotes the number of passed events and N the number of total
178events.
179
180###Frequentist methods
181The expectation value of the number of passed events is given by the true
182efficiency times the total number of events. One can estimate the efficiency
183by replacing the expected number of passed events by the observed number of
184passed events.
185
186\f[
187 k = \epsilon \times N \Rightarrow \hat{\varepsilon} = \frac{k}{N}
188\f]
189
190### Bayesian methods
191In Bayesian statistics a likelihood-function (how probable is it to get the
192observed data assuming a true efficiency) and a prior probability (what is the
193probability that a certain true efficiency is actually realised) are used to
194determine a posterior probability by using Bayes theorem. At the moment, only
195beta distributions (have 2 free parameters) are supported as prior
196probabilities.
197
198\f{eqnarray*}{
199 P(\epsilon | k ; N) &=& \frac{1}{norm} \times P(k | \epsilon ; N) \times Prior(\epsilon) \\
200 P(k | \epsilon ; N) &=& Binomial(N,k) \times \epsilon^{k} \times (1 - \epsilon)^{N - k} ...\ binomial\ distribution \\
201 Prior(\epsilon) &=& \frac{1}{B(\alpha,\beta)} \times \epsilon ^{\alpha - 1} \times (1 - \epsilon)^{\beta - 1} \equiv Beta(\epsilon; \alpha,\beta) \\
202 \Rightarrow P(\epsilon | k ; N) &=& \frac{1}{norm'} \times \epsilon^{k + \alpha - 1} \times (1 - \epsilon)^{N - k + \beta - 1} \equiv Beta(\epsilon; k + \alpha, N - k + \beta)
203\f}
204
205By default the expectation value of this posterior distribution is used as an estimator for the efficiency:
206
207\f[
208 \hat{\varepsilon} = \frac{k + \alpha}{N + \alpha + \beta}
209\f]
210
211Optionally the mode can also be used as a value for the estimated efficiency. This can be done by calling
212SetBit(kPosteriorMode) or TEfficiency::SetPosteriorMode. In this case, the estimated efficiency is:
213
214\f[
215 \hat{\varepsilon} = \frac{k + \alpha -1}{N + \alpha + \beta - 2}
216\f]
217
218In the case of a uniform prior distribution, B(x,1,1), the posterior mode is k/n, equivalent to the frequentist
219estimate (the maximum likelihood value).
220
221The statistic options also specify which confidence interval is used for calculating
222the uncertainties of the efficiency. The following properties define the error
223calculation:
224- **fConfLevel:** desired confidence level: 0 < fConfLevel < 1 (TEfficiency::GetConfidenceLevel / TEfficiency::SetConfidenceLevel)
225- **fStatisticOption** defines which method is used to calculate the boundaries of the confidence interval (TEfficiency::SetStatisticOption)
226- **fBeta_alpha, fBeta_beta:** parameters for the prior distribution which is only used in the bayesian case (TEfficiency::GetBetaAlpha / TEfficiency::GetBetaBeta / TEfficiency::SetBetaAlpha / TEfficiency::SetBetaBeta)
227- **kIsBayesian:** flag whether bayesian statistics are used or not (TEfficiency::UsesBayesianStat)
228- **kShortestInterval:** flag whether shortest interval (instead of central one) are used in case of Bayesian statistics (TEfficiency::UsesShortestInterval). Normally shortest interval should be used in combination with the mode (see TEfficiency::UsesPosteriorMode)
229- **fWeight:** global weight for this TEfficiency object which is used during combining or merging with other TEfficiency objects(TEfficiency::GetWeight / TEfficiency::SetWeight)
230
231In the following table, the implemented confidence intervals are listed
232with their corresponding statistic option. For more details on the calculation,
233please have a look at the mentioned functions.
234
235
236| name | statistic option | function | kIsBayesian | parameters |
237|------------------|------------------|---------------------|-------------|------------|
238| Clopper-Pearson | kFCP | TEfficiency::ClopperPearson |false |total events, passed events, confidence level |
239| normal approximation | kFNormal | TEfficiency::Normal | false | total events, passed events, confidence level |
240| Wilson | kFWilson | TEfficiency::Wilson | false | total events, passed events, confidence level |
241| Agresti-Coull | kFAC | TEfficiency::AgrestiCoull | false | total events, passed events. confidence level |
242| Feldman-Cousins | kFFC | TEfficiency::FeldmanCousins | false | total events, passed events, confidence level |
243| Mid-P Lancaster | kMidP | TEfficiency::MidPInterval | false | total events, passed events, confidence level |
244| Jeffrey | kBJeffrey | TEfficiency::Bayesian | true | total events, passed events, confidence level, fBeta_alpha = 0.5, fBeta_beta = 0.5 |
245| Uniform prior | kBUniform |TEfficiency::Bayesian | true |total events, passed events, confidence level, fBeta_alpha = 1, fBeta_beta = 1 |
246| custom prior | kBBayesian |TEfficiency::Bayesian | true |total events, passed events, confidence level, fBeta_alpha, fBeta_beta |
247
248The following example demonstrates the effect of different statistic options and
249confidence levels.
250
251Begin_Macro(source)
252{
253 //canvas only needed for the documentation
254 TCanvas* c1 = new TCanvas("c1","",600,400);
255 c1->Divide(2);
256 c1->SetFillStyle(1001);
257 c1->SetFillColor(kWhite);
258
259 //create one-dimensional TEfficiency object with fixed bin size
260 TEfficiency* pEff = new TEfficiency("eff","different confidence levels;x;#epsilon",20,0,10);
261 TRandom3 rand3;
262
263 bool bPassed;
264 double x;
265 for(int i=0; i<1000; ++i)
266 {
267 //simulate events with variable under investigation
268 x = rand3.Uniform(10);
269 //check selection: bPassed = DoesEventPassSelection(x)
270 bPassed = rand3.Rndm() < TMath::Gaus(x,5,4);
271 pEff->Fill(bPassed,x);
272 }
273
274 //set style attributes
275 pEff->SetFillStyle(3004);
276 pEff->SetFillColor(kRed);
277
278 //copy current TEfficiency object and set new confidence level
279 TEfficiency* pCopy = new TEfficiency(*pEff);
280 pCopy->SetConfidenceLevel(0.90);
281
282 //set style attributes
283 pCopy->SetFillStyle(3005);
284 pCopy->SetFillColor(kBlue);
285
286 c1->cd(1);
287
288 //add legend
289 TLegend* leg1 = new TLegend(0.3,0.1,0.7,0.5);
290 leg1->AddEntry(pEff,"95%","F");
291 leg1->AddEntry(pCopy,"68.3%","F");
292
293 pEff->Draw("A4");
294 pCopy->Draw("same4");
295 leg1->Draw("same");
296
297 //use same confidence level but different statistic methods
298 TEfficiency* pEff2 = new TEfficiency(*pEff);
299 TEfficiency* pCopy2 = new TEfficiency(*pEff);
300
301 pEff2->SetStatisticOption(TEfficiency::kFNormal);
302 pCopy2->SetStatisticOption(TEfficiency::kFAC);
303
304 pEff2->SetTitle("different statistic options;x;#epsilon");
305
306 //set style attributes
307 pCopy2->SetFillStyle(3005);
308 pCopy2->SetFillColor(kBlue);
309
310 c1->cd(2);
311
312 //add legend
313 TLegend* leg2 = new TLegend(0.3,0.1,0.7,0.5);
314 leg2->AddEntry(pEff2,"kFNormal","F");
315 leg2->AddEntry(pCopy2,"kFAC","F");
316
317 pEff2->Draw("a4");
318 pCopy2->Draw("same4");
319 leg2->Draw("same");
320
321 //only for this documentation
322 c1->cd(0);
323 return c1;
324}
325End_Macro
326
327The prior probability of the efficiency in Bayesian statistics can be given
328in terms of a beta distribution. The beta distribution has two positive shape
329parameters. The resulting priors for different combinations of these shape
330parameters are shown in the plot below.
331
332Begin_Macro(source)
333{
334 //canvas only needed for the documentation
335 TCanvas* c1 = new TCanvas("c1","",600,400);
336 c1->SetFillStyle(1001);
337 c1->SetFillColor(kWhite);
338
339 //create different beta distributions
340 TF1* f1 = new TF1("f1","TMath::BetaDist(x,1,1)",0,1);
341 f1->SetLineColor(kBlue);
342 TF1* f2 = new TF1("f2","TMath::BetaDist(x,0.5,0.5)",0,1);
343 f2->SetLineColor(kRed);
344 TF1* f3 = new TF1("f3","TMath::BetaDist(x,1,5)",0,1);
345 f3->SetLineColor(kGreen+3);
346 f3->SetTitle("Beta distributions as priors;#epsilon;P(#epsilon)");
347 TF1* f4 = new TF1("f4","TMath::BetaDist(x,4,3)",0,1);
348 f4->SetLineColor(kViolet);
349
350 //add legend
351 TLegend* leg = new TLegend(0.25,0.5,0.85,0.89);
352 leg->SetFillColor(kWhite);
353 leg->SetFillStyle(1001);
354 leg->AddEntry(f1,"a=1, b=1","L");
355 leg->AddEntry(f2,"a=0.5, b=0.5","L");
356 leg->AddEntry(f3,"a=1, b=5","L");
357 leg->AddEntry(f4,"a=4, b=3","L");
358
359 f3->Draw();
360 f1->Draw("same");
361 f2->Draw("Same");
362 f4->Draw("same");
363 leg->Draw("same");
364
365 //only for this documentation
366 return c1;
367}
368End_Macro
369
370
371## IV.1 Coverage probabilities for different methods
372The following pictures illustrate the actual coverage probability for the
373different values of the true efficiency and the total number of events when a
374confidence level of 95% is desired.
375
376\image html normal95.gif "Normal Approximation"
377
378
379\image html wilson95.gif "Wilson"
380
381
382\image html ac95.gif "Agresti Coull"
383
384
385\image html cp95.gif "Clopper Pearson"
386
387
388\image html uni95.gif "Bayesian with Uniform Prior"
389
390
391\image html jeffrey95.gif "Bayesian with Jeffrey Prior"
392
393The average (over all possible true efficiencies) coverage probability for
394different number of total events is shown in the next picture.
395\image html av_cov.png "Average Coverage"
396
397## V. Merging and combining TEfficiency objects
398In many applications, the efficiency should be calculated for an inhomogeneous
399sample in the sense that it contains events with different weights. In order
400to be able to determine the correct overall efficiency, it is necessary to
401use for each subsample (= all events with the same weight) a different
402TEfficiency object. After finishing your analysis you can then construct the
403overall efficiency with its uncertainty.
404
405This procedure has the advantage that you can change the weight of one
406subsample easily without rerunning the whole analysis. On the other hand, more
407effort is needed to handle several TEfficiency objects instead of one
408histogram. In the case of many different or even continuously distributed
409weights, this approach becomes cumbersome. One possibility to overcome this
410problem is the usage of binned weights.
411
412### Example
413In particle physics weights arises from the fact that you want to
414normalise your results to a certain reference value. A very common formula for
415calculating weights is
416
417\f{eqnarray*}{
418 w &=& \frac{\sigma L}{N_{gen} \epsilon_{trig}} \\
419 &-& \sigma ...\ cross\ section \\
420 &-& L ...\ luminosity \\
421 &-& N_{gen}\ ... number\ of\ generated\ events \\
422 &-& \epsilon_{trig}\ ...\ (known)\ trigger\ efficiency \\
423\f}
424
425The reason for different weights can therefore be:
426- different processes
427- other integrated luminosity
428- varying trigger efficiency
429- different sample sizes
430- ...
431- or even combination of them
432
433Depending on the actual meaning of different weights in your case, you
434should either merge or combine them to get the overall efficiency.
435
436### V.1 When should I use merging?
437If the weights are artificial and do not represent real alternative hypotheses,
438you should merge the different TEfficiency objects. That means especially for
439the Bayesian case that the prior probability should be the same for all merged
440TEfficiency objects. The merging can be done by invoking one of the following
441operations:
442- eff1.Add(eff2)
443- eff1 += eff2
444- eff1 = eff1 + eff2
445
446The result of the merging is stored in the TEfficiency object which is marked
447bold above. The contents of the internal histograms of both TEfficiency
448objects are added and a new weight is assigned. The statistic options are not
449changed.
450
451\f[
452 \frac{1}{w_{new}} = \frac{1}{w_{1}} + \frac{1}{w_{2}}
453\f]
454
455### Example:
456If you use two samples with different numbers of generated events for the same
457process and you want to normalise both to the same integrated luminosity and
458trigger efficiency, the different weights then arise just from the fact that
459you have different numbers of events. The TEfficiency objects should be merged
460because the samples do not represent true alternatives. You expect the same
461result as if you would have a big sample with all events in it.
462
463\f[
464 w_{1} = \frac{\sigma L}{\epsilon N_{1}}, w_{2} = \frac{\sigma L}{\epsilon N_{2}} \Rightarrow w_{new} = \frac{\sigma L}{\epsilon (N_{1} + N_{2})} = \frac{1}{\frac{1}{w_{1}} + \frac{1}{w_{2}}}
465\f]
466
467### V.2 When should I use combining?
468You should combine TEfficiency objects whenever the weights represent
469alternatives processes for the efficiency. As the combination of two TEfficiency
470objects is not always consistent with the representation by two internal
471histograms, the result is not stored in a TEfficiency object but a TGraphAsymmErrors
472is returned which shows the estimated combined efficiency and its uncertainty
473for each bin.
474At the moment the combination method TEfficiency::Combine only supports a combination of 1-dimensional
475efficiencies in a Bayesian approach.
476
477
478For calculating the combined efficiency and its uncertainty for each bin only Bayesian statistics
479is used. No frequentists methods are presently supported for computing the combined efficiency and
480its confidence interval.
481In the case of the Bayesian statistics, a combined posterior is constructed taking into account the
482weight of each TEfficiency object. The same prior is used for all the TEfficiency objects.
483
484\f{eqnarray*}{
485 P_{comb}(\epsilon | {w_{i}}, {k_{i}} , {N_{i}}) = \frac{1}{norm} \prod_{i}{L(k_{i} | N_{i}, \epsilon)}^{w_{i}} \Pi( \epsilon )\\
486L(k_{i} | N_{i}, \epsilon)\ is\ the\ likelihood\ function\ for\ the\ sample\ i\ (a\ Binomial\ distribution)\\
487\Pi( \epsilon)\ is\ the\ prior,\ a\ beta\ distribution\ B(\epsilon, \alpha, \beta).\\
488The\ resulting\ combined\ posterior\ is \\
489P_{comb}(\epsilon |{w_{i}}; {k_{i}}; {N_{i}}) = B(\epsilon, \sum_{i}{ w_{i} k_{i}} + \alpha, \sum_{i}{ w_{i}(n_{i}-k_{i})}+\beta) \\
490\hat{\varepsilon} = \int_{0}^{1} \epsilon \times P_{comb}(\epsilon | {k_{i}} , {N_{i}}) d\epsilon \\
491confidence\ level = 1 - \alpha \\
492\frac{\alpha}{2} = \int_{0}^{\epsilon_{low}} P_{comb}(\epsilon | {k_{i}} , {N_{i}}) d\epsilon ...\ defines\ lower\ boundary \\
4931- \frac{\alpha}{2} = \int_{0}^{\epsilon_{up}} P_{comb}(\epsilon | {k_{i}} , {N_{i}}) d\epsilon ...\ defines\ upper\ boundary
494\f}
495
496
497###Example:
498If you use cuts to select electrons which can originate from two different
499processes, you can determine the selection efficiency for each process. The
500overall selection efficiency is then the combined efficiency. The weights to be used in the
501combination should be the probability that an
502electron comes from the corresponding process.
503
504\f[
505p_{1} = \frac{\sigma_{1}}{\sigma_{1} + \sigma_{2}} = \frac{N_{1}w_{1}}{N_{1}w_{1} + N_{2}w_{2}}\\
506p_{2} = \frac{\sigma_{2}}{\sigma_{1} + \sigma_{2}} = \frac{N_{2}w_{2}}{N_{1}w_{1} + N_{2}w_{2}}
507\f]
508
509## VI. Further operations
510
511### VI.Information about the internal histograms
512The methods TEfficiency::GetPassedHistogram and TEfficiency::GetTotalHistogram
513return a constant pointer to the internal histograms. They can be used to
514obtain information about the internal histograms (e.g., the binning, number of passed / total events in a bin, mean values...).
515One can obtain a clone of the internal histograms by calling TEfficiency::GetCopyPassedHisto or TEfficiency::GetCopyTotalHisto.
516The returned histograms are completely independent from the current
517TEfficiency object. By default, they are not attached to a directory to
518avoid the duplication of data and the user is responsible for deleting them.
519
520
521~~~~~~~~~~~~~~~{.cpp}
522//open a root file which contains a TEfficiency object
523TFile* pFile = new TFile("myfile.root","update");
524
525//get TEfficiency object with name "my_eff"
526TEfficiency* pEff = (TEfficiency*)pFile->Get("my_eff");
527
528//get clone of total histogram
529TH1* clone = pEff->GetCopyTotalHisto();
530
531//change clone...
532//save changes of clone directly
533clone->Write();
534//or append it to the current directory and write the file
535//clone->SetDirectory(gDirectory);
536//pFile->Write();
537
538//delete histogram object
539delete clone;
540clone = 0;
541~~~~~~~~~~~~~~~
542
543It is also possible to set the internal total or passed histogram by using the
544methods TEfficiency::SetPassedHistogram or TEfficiency::SetTotalHistogram.
545
546In order to ensure the validity of the TEfficiency object, the consistency of the
547new histogram and the stored histogram is checked. It might be
548impossible sometimes to change the histograms in a consistent way. Therefore one can force
549the replacement by passing the "f" option. Then the user has to ensure that the
550other internal histogram is replaced as well and that the TEfficiency object is
551in a valid state.
552
553### VI.2 Fitting
554The efficiency can be fitted using the TEfficiency::Fit function which internally uses
555the TBinomialEfficiencyFitter::Fit method.
556As this method is using a maximum-likelihood-fit, it is necessary to initialise
557the given fit function with reasonable start values.
558The resulting fit function is attached to the list of associated functions and
559will be drawn automatically during the next TEfficiency::Draw command.
560The list of associated function can be modified by using the pointer returned
561by TEfficiency::GetListOfFunctions.
562
563Begin_Macro(source)
564{
565 //canvas only needed for this documentation
566 TCanvas* c1 = new TCanvas("example","",600,400);
567 c1->SetFillStyle(1001);
568 c1->SetFillColor(kWhite);
569
570 //create one-dimensional TEfficiency object with fixed bin size
571 TEfficiency* pEff = new TEfficiency("eff","my efficiency;x;#epsilon",20,0,10);
572 TRandom3 rand3;
573
574 bool bPassed;
575 double x;
576 for(int i=0; i<10000; ++i)
577 {
578 //simulate events with variable under investigation
579 x = rand3.Uniform(10);
580 //check selection: bPassed = DoesEventPassSelection(x)
581 bPassed = rand3.Rndm() < TMath::Gaus(x,5,4);
582 pEff->Fill(bPassed,x);
583 }
584
585 //create a function for fitting and do the fit
586 TF1* f1 = new TF1("f1","gaus",0,10);
587 f1->SetParameters(1,5,2);
588 pEff->Fit(f1);
589
590 //create a threshold function
591 TF1* f2 = new TF1("thres","0.8",0,10);
592 f2->SetLineColor(kRed);
593 //add it to the list of functions
594 //use add first because the parameters of the last function will be displayed
595 pEff->GetListOfFunctions()->AddFirst(f2);
596
597 pEff->Draw("AP");
598
599 //only for this documentation
600 return c1;
601}
602End_Macro
603
604### VI.3 Draw a TEfficiency object
605A TEfficiency object can be drawn by calling the usual TEfficiency::Draw method.
606At the moment drawing is only supported for 1- and 2-dimensional TEfficiency objects.
607In the 1-dimensional case, you can use the same options as for the TGraphAsymmErrors::Draw
608method. For 2-dimensional TEfficiency objects, you can pass the same options as
609for a TH2::Draw object.
610
611********************************************************************************/
612//______________________________________________________________________________
613
614////////////////////////////////////////////////////////////////////////////////
615///default constructor
616///
617///should not be used explicitly
618
620fBeta_alpha(kDefBetaAlpha),
621fBeta_beta(kDefBetaBeta),
622fBoundary(0),
623fConfLevel(kDefConfLevel),
624fDirectory(0),
625fFunctions(0),
626fPaintGraph(0),
627fPaintHisto(0),
628fPassedHistogram(0),
629fTotalHistogram(0),
630fWeight(kDefWeight)
631{
633
634 // create 2 dummy histograms
635 fPassedHistogram = new TH1F("h_passed","passed",10,0,10);
636 fTotalHistogram = new TH1F("h_total","total",10,0,10);
637}
638
639////////////////////////////////////////////////////////////////////////////////
640///constructor using two existing histograms as input
641///
642///Input: passed - contains the events fulfilling some criteria
643/// total - contains all investigated events
644///
645///Notes: - both histograms have to fulfill the conditions of CheckConsistency
646/// - dimension of the resulting efficiency object depends
647/// on the dimension of the given histograms
648/// - Clones of both histograms are stored internally
649/// - The function SetName(total.GetName() + "_clone") is called to set
650/// the names of the new object and the internal histograms..
651/// - The created TEfficiency object is NOT appended to a directory. It
652/// will not be written to disk during the next TFile::Write() command
653/// in order to prevent duplication of data. If you want to save this
654/// TEfficiency object anyway, you can either append it to a
655/// directory by calling SetDirectory(TDirectory*) or write it
656/// explicitly to disk by calling Write().
657
658TEfficiency::TEfficiency(const TH1& passed,const TH1& total):
659fBeta_alpha(kDefBetaAlpha),
660fBeta_beta(kDefBetaBeta),
661fConfLevel(kDefConfLevel),
662fDirectory(0),
663fFunctions(0),
664fPaintGraph(0),
665fPaintHisto(0),
666fWeight(kDefWeight)
667{
668 //check consistency of histograms
669 if(CheckConsistency(passed,total)) {
670 // do not add cloned histograms to gDirectory
671 TDirectory::TContext ctx(nullptr);
672 fTotalHistogram = (TH1*)total.Clone();
673 fPassedHistogram = (TH1*)passed.Clone();
674
675 TString newName = total.GetName();
676 newName += TString("_clone");
677 SetName(newName);
678
679 // are the histograms filled with weights?
680 if(CheckWeights(passed,total))
681 {
682 Info("TEfficiency","given histograms are filled with weights");
684 }
685 }
686 else {
687 Error("TEfficiency(const TH1&,const TH1&)","histograms are not consistent -> results are useless");
688 Warning("TEfficiency(const TH1&,const TH1&)","using two empty TH1D('h1','h1',10,0,10)");
689
690 // do not add new created histograms to gDirectory
691 TDirectory::TContext ctx(nullptr);
692 fTotalHistogram = new TH1D("h1_total","h1 (total)",10,0,10);
693 fPassedHistogram = new TH1D("h1_passed","h1 (passed)",10,0,10);
694 }
695
696 SetBit(kPosteriorMode,false);
698
700 SetDirectory(0);
701}
702
703////////////////////////////////////////////////////////////////////////////////
704/// Create 1-dimensional TEfficiency object with variable bin size.
705///
706/// Constructor creates two new and empty histograms with a given binning
707///
708/// Input:
709///
710/// - `name`: the common part of the name for both histograms (no blanks)
711/// fTotalHistogram has name: name + "_total"
712/// fPassedHistogram has name: name + "_passed"
713/// - `title`: the common part of the title for both histogram
714/// fTotalHistogram has title: title + " (total)"
715/// fPassedHistogram has title: title + " (passed)"
716/// It is possible to label the axis by passing a title with
717/// the following format: "title;xlabel;ylabel".
718/// - `nbins`: number of bins on the x-axis
719/// - `xbins`: array of length (nbins + 1) with low-edges for each bin
720/// xbins[nbinsx] ... lower edge for overflow bin
721
722TEfficiency::TEfficiency(const char* name,const char* title,Int_t nbins,
723 const Double_t* xbins):
724fBeta_alpha(kDefBetaAlpha),
725fBeta_beta(kDefBetaBeta),
726fConfLevel(kDefConfLevel),
727fDirectory(0),
728fFunctions(0),
729fPaintGraph(0),
730fPaintHisto(0),
731fWeight(kDefWeight)
732{
733 // do not add new created histograms to gDirectory
734 TDirectory::TContext ctx(nullptr);
735 fTotalHistogram = new TH1D("total","total",nbins,xbins);
736 fPassedHistogram = new TH1D("passed","passed",nbins,xbins);
737
738 Build(name,title);
739}
740
741////////////////////////////////////////////////////////////////////////////////
742/// Create 1-dimensional TEfficiency object with fixed bins size.
743///
744/// Constructor creates two new and empty histograms with a fixed binning.
745///
746/// Input:
747///
748/// - `name`: the common part of the name for both histograms(no blanks)
749/// fTotalHistogram has name: name + "_total"
750/// fPassedHistogram has name: name + "_passed"
751/// - `title`: the common part of the title for both histogram
752/// fTotalHistogram has title: title + " (total)"
753/// fPassedHistogram has title: title + " (passed)"
754/// It is possible to label the axis by passing a title with
755/// the following format: "title;xlabel;ylabel".
756/// - `nbinsx`: number of bins on the x-axis
757/// - `xlow`: lower edge of first bin
758/// - `xup`: upper edge of last bin
759
760TEfficiency::TEfficiency(const char* name,const char* title,Int_t nbinsx,
761 Double_t xlow,Double_t xup):
762fBeta_alpha(kDefBetaAlpha),
763fBeta_beta(kDefBetaBeta),
764fConfLevel(kDefConfLevel),
765fDirectory(0),
766fFunctions(0),
767fPaintGraph(0),
768fPaintHisto(0),
769fWeight(kDefWeight)
770{
771 // do not add new created histograms to gDirectory
772 TDirectory::TContext ctx(nullptr);
773 fTotalHistogram = new TH1D("total","total",nbinsx,xlow,xup);
774 fPassedHistogram = new TH1D("passed","passed",nbinsx,xlow,xup);
775
776 Build(name,title);
777}
778
779////////////////////////////////////////////////////////////////////////////////
780/// Create 2-dimensional TEfficiency object with fixed bin size.
781///
782/// Constructor creates two new and empty histograms with a fixed binning.
783///
784/// Input:
785///
786/// - `name`: the common part of the name for both histograms(no blanks)
787/// fTotalHistogram has name: name + "_total"
788/// fPassedHistogram has name: name + "_passed"
789/// - `title`: the common part of the title for both histogram
790/// fTotalHistogram has title: title + " (total)"
791/// fPassedHistogram has title: title + " (passed)"
792/// It is possible to label the axis by passing a title with
793/// the following format: "title;xlabel;ylabel;zlabel".
794/// - `nbinsx`: number of bins on the x-axis
795/// - `xlow`: lower edge of first x-bin
796/// - `xup`: upper edge of last x-bin
797/// - `nbinsy`: number of bins on the y-axis
798/// - `ylow`: lower edge of first y-bin
799/// - `yup`: upper edge of last y-bin
800
801TEfficiency::TEfficiency(const char* name,const char* title,Int_t nbinsx,
802 Double_t xlow,Double_t xup,Int_t nbinsy,
803 Double_t ylow,Double_t yup):
804fBeta_alpha(kDefBetaAlpha),
805fBeta_beta(kDefBetaBeta),
806fConfLevel(kDefConfLevel),
807fDirectory(0),
808fFunctions(0),
809fPaintGraph(0),
810fPaintHisto(0),
811fWeight(kDefWeight)
812{
813 // do not add new created histograms to gDirectory
814 TDirectory::TContext ctx(nullptr);
815 fTotalHistogram = new TH2D("total","total",nbinsx,xlow,xup,nbinsy,ylow,yup);
816 fPassedHistogram = new TH2D("passed","passed",nbinsx,xlow,xup,nbinsy,ylow,yup);
817
818 Build(name,title);
819}
820
821////////////////////////////////////////////////////////////////////////////////
822/// Create 2-dimensional TEfficiency object with variable bin size.
823///
824/// Constructor creates two new and empty histograms with a given binning.
825///
826/// Input:
827///
828/// - `name`: the common part of the name for both histograms(no blanks)
829/// fTotalHistogram has name: name + "_total"
830/// fPassedHistogram has name: name + "_passed"
831/// - `title`: the common part of the title for both histogram
832/// fTotalHistogram has title: title + " (total)"
833/// fPassedHistogram has title: title + " (passed)"
834/// It is possible to label the axis by passing a title with
835/// the following format: "title;xlabel;ylabel;zlabel".
836/// - `nbinsx`: number of bins on the x-axis
837/// - `xbins`: array of length (nbins + 1) with low-edges for each bin
838/// xbins[nbinsx] ... lower edge for overflow x-bin
839/// - `nbinsy`: number of bins on the y-axis
840/// - `ybins`: array of length (nbins + 1) with low-edges for each bin
841/// ybins[nbinsy] ... lower edge for overflow y-bin
842
843TEfficiency::TEfficiency(const char* name,const char* title,Int_t nbinsx,
844 const Double_t* xbins,Int_t nbinsy,
845 const Double_t* ybins):
846fBeta_alpha(kDefBetaAlpha),
847fBeta_beta(kDefBetaBeta),
848fConfLevel(kDefConfLevel),
849fDirectory(0),
850fFunctions(0),
851fPaintGraph(0),
852fPaintHisto(0),
853fWeight(kDefWeight)
854{
855 // do not add new created histograms to gDirectory
856 TDirectory::TContext ctx(nullptr);
857 fTotalHistogram = new TH2D("total","total",nbinsx,xbins,nbinsy,ybins);
858 fPassedHistogram = new TH2D("passed","passed",nbinsx,xbins,nbinsy,ybins);
859
860 Build(name,title);
861}
862
863////////////////////////////////////////////////////////////////////////////////
864/// Create 3-dimensional TEfficiency object with fixed bin size.
865///
866/// Constructor creates two new and empty histograms with a fixed binning.
867///
868/// Input:
869///
870/// - `name`: the common part of the name for both histograms(no blanks)
871/// fTotalHistogram has name: name + "_total"
872/// fPassedHistogram has name: name + "_passed"
873/// - `title`: the common part of the title for both histogram
874/// fTotalHistogram has title: title + " (total)"
875/// fPassedHistogram has title: title + " (passed)"
876/// It is possible to label the axis by passing a title with
877/// the following format: "title;xlabel;ylabel;zlabel".
878/// - `nbinsx`: number of bins on the x-axis
879/// - `xlow`: lower edge of first x-bin
880/// - `xup`: upper edge of last x-bin
881/// - `nbinsy`: number of bins on the y-axis
882/// - `ylow`: lower edge of first y-bin
883/// - `yup`: upper edge of last y-bin
884/// - `nbinsz`: number of bins on the z-axis
885/// - `zlow`: lower edge of first z-bin
886/// - `zup`: upper edge of last z-bin
887
888TEfficiency::TEfficiency(const char* name,const char* title,Int_t nbinsx,
889 Double_t xlow,Double_t xup,Int_t nbinsy,
890 Double_t ylow,Double_t yup,Int_t nbinsz,
891 Double_t zlow,Double_t zup):
892fBeta_alpha(kDefBetaAlpha),
893fBeta_beta(kDefBetaBeta),
894fConfLevel(kDefConfLevel),
895fDirectory(0),
896fFunctions(0),
897fPaintGraph(0),
898fPaintHisto(0),
899fWeight(kDefWeight)
900{
901 // do not add new created histograms to gDirectory
902 TDirectory::TContext ctx(nullptr);
903 fTotalHistogram = new TH3D("total","total",nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup);
904 fPassedHistogram = new TH3D("passed","passed",nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,zlow,zup);
905
906 Build(name,title);
907}
908
909////////////////////////////////////////////////////////////////////////////////
910/// Create 3-dimensional TEfficiency object with variable bin size.
911///
912/// Constructor creates two new and empty histograms with a given binning.
913///
914/// Input:
915///
916/// - `name`: the common part of the name for both histograms(no blanks)
917/// fTotalHistogram has name: name + "_total"
918/// fPassedHistogram has name: name + "_passed"
919/// - `title`: the common part of the title for both histogram
920/// fTotalHistogram has title: title + " (total)"
921/// fPassedHistogram has title: title + " (passed)"
922/// It is possible to label the axis by passing a title with
923/// the following format: "title;xlabel;ylabel;zlabel".
924/// - `nbinsx`: number of bins on the x-axis
925/// - `xbins`: array of length (nbins + 1) with low-edges for each bin
926/// xbins[nbinsx] ... lower edge for overflow x-bin
927/// - `nbinsy`: number of bins on the y-axis
928/// - `ybins`: array of length (nbins + 1) with low-edges for each bin
929/// xbins[nbinsx] ... lower edge for overflow y-bin
930/// - `nbinsz`: number of bins on the z-axis
931/// - `zbins`: array of length (nbins + 1) with low-edges for each bin
932/// xbins[nbinsx] ... lower edge for overflow z-bin
933
934TEfficiency::TEfficiency(const char* name,const char* title,Int_t nbinsx,
935 const Double_t* xbins,Int_t nbinsy,
936 const Double_t* ybins,Int_t nbinsz,
937 const Double_t* zbins):
938fBeta_alpha(kDefBetaAlpha),
939fBeta_beta(kDefBetaBeta),
940fConfLevel(kDefConfLevel),
941fDirectory(0),
942fFunctions(0),
943fPaintGraph(0),
944fPaintHisto(0),
945fWeight(kDefWeight)
946{
947 // do not add new created histograms to gDirectory
948 TDirectory::TContext ctx(nullptr);
949 fTotalHistogram = new TH3D("total","total",nbinsx,xbins,nbinsy,ybins,nbinsz,zbins);
950 fPassedHistogram = new TH3D("passed","passed",nbinsx,xbins,nbinsy,ybins,nbinsz,zbins);
951
952 Build(name,title);
953}
954
955////////////////////////////////////////////////////////////////////////////////
956/// Copy constructor.
957///
958///The list of associated objects (e.g. fitted functions) is not copied.
959///
960///Note:
961///
962/// - SetName(rEff.GetName() + "_copy") is called to set the names of the
963/// object and the histograms.
964/// - The titles are set by calling SetTitle("[copy] " + rEff.GetTitle()).
965/// - The copied TEfficiency object is NOT appended to a directory. It
966/// will not be written to disk during the next TFile::Write() command
967/// in order to prevent duplication of data. If you want to save this
968/// TEfficiency object anyway, you can either append it to a directory
969/// by calling SetDirectory(TDirectory*) or write it explicitly to disk
970/// by calling Write().
971
973TNamed(),
974TAttLine(),
975TAttFill(),
976TAttMarker(),
977fBeta_alpha(rEff.fBeta_alpha),
978fBeta_beta(rEff.fBeta_beta),
979fBeta_bin_params(rEff.fBeta_bin_params),
980fConfLevel(rEff.fConfLevel),
981fDirectory(0),
982fFunctions(0),
983fPaintGraph(0),
984fPaintHisto(0),
985fWeight(rEff.fWeight)
986{
987 // copy TObject bits
988 ((TObject&)rEff).Copy(*this);
989
990 // do not add cloned histograms to gDirectory
991 {
992 TDirectory::TContext ctx(nullptr);
993 fTotalHistogram = (TH1*)((rEff.fTotalHistogram)->Clone());
994 fPassedHistogram = (TH1*)((rEff.fPassedHistogram)->Clone());
995 }
996
997 TString name = rEff.GetName();
998 name += "_copy";
999 SetName(name);
1000 TString title = "[copy] ";
1001 title += rEff.GetTitle();
1002 SetTitle(title);
1003
1005
1006 SetDirectory(0);
1007
1008 //copy style
1009 rEff.TAttLine::Copy(*this);
1010 rEff.TAttFill::Copy(*this);
1011 rEff.TAttMarker::Copy(*this);
1012}
1013
1014////////////////////////////////////////////////////////////////////////////////
1015///default destructor
1016
1018{
1019 //delete all function in fFunctions
1020 // use same logic as in TH1 destructor
1021 // (see TH1::~TH1 code in TH1.cxx)
1022 if(fFunctions) {
1024 TObject* obj = 0;
1025 while ((obj = fFunctions->First())) {
1026 while(fFunctions->Remove(obj)) { }
1027 if (!obj->TestBit(kNotDeleted)) {
1028 break;
1029 }
1030 delete obj;
1031 obj = 0;
1032 }
1033 delete fFunctions;
1034 fFunctions = 0;
1035 }
1036
1037 if(fDirectory)
1038 fDirectory->Remove(this);
1039
1040 delete fTotalHistogram;
1041 delete fPassedHistogram;
1042 delete fPaintGraph;
1043 delete fPaintHisto;
1044}
1045
1046////////////////////////////////////////////////////////////////////////////////
1047/**
1048 Calculates the boundaries for the frequentist Agresti-Coull interval
1049
1050 \param total number of total events
1051 \param passed 0 <= number of passed events <= total
1052 \param level confidence level
1053 \param bUpper true - upper boundary is returned
1054 false - lower boundary is returned
1055
1056
1057 \f{eqnarray*}{
1058 \alpha &=& 1 - \frac{level}{2} \\
1059 \kappa &=& \Phi^{-1}(1 - \alpha,1)\ ... normal\ quantile\ function\\
1060 mode &=& \frac{passed + \frac{\kappa^{2}}{2}}{total + \kappa^{2}}\\
1061 \Delta &=& \kappa * \sqrt{\frac{mode * (1 - mode)}{total + \kappa^{2}}}\\
1062 return &=& max(0,mode - \Delta)\ or\ min(1,mode + \Delta)
1063 \f}
1064
1065*/
1066
1068{
1069 Double_t alpha = (1.0 - level)/2;
1070 Double_t kappa = ROOT::Math::normal_quantile(1 - alpha,1);
1071
1072 Double_t mode = (passed + 0.5 * kappa * kappa) / (total + kappa * kappa);
1073 Double_t delta = kappa * std::sqrt(mode * (1 - mode) / (total + kappa * kappa));
1074
1075 if(bUpper)
1076 return ((mode + delta) > 1) ? 1.0 : (mode + delta);
1077 else
1078 return ((mode - delta) < 0) ? 0.0 : (mode - delta);
1079}
1080
1081////////////////////////////////////////////////////////////////////////////////
1082/// Calculates the boundaries for the frequentist Feldman-Cousins interval
1083///
1084/// \param total number of total events
1085/// \param passed 0 <= number of passed events <= total
1086/// \param level confidence level
1087/// \param bUpper: true - upper boundary is returned
1088/// false - lower boundary is returned
1089
1091{
1092 Double_t lower = 0;
1093 Double_t upper = 1;
1094 if (!FeldmanCousinsInterval(total,passed,level, lower, upper)) {
1095 ::Error("FeldmanCousins","Error running FC method - return 0 or 1");
1096 }
1097 return (bUpper) ? upper : lower;
1098}
1099
1100////////////////////////////////////////////////////////////////////////////////
1101/// Calculates the interval boundaries using the frequentist methods of Feldman-Cousins
1102///
1103/// \param[in] total number of total events
1104/// \param[in] passed 0 <= number of passed events <= total
1105/// \param[in] level confidence level
1106/// \param[out] lower lower boundary returned on exit
1107/// \param[out] upper lower boundary returned on exit
1108/// \return a flag with the status of the calculation
1109///
1110/// Calculation:
1111///
1112/// The Feldman-Cousins is a frequentist method where the interval is estimated using a Neyman construction where the ordering
1113/// is based on the likelihood ratio:
1114/// \f[
1115/// LR = \frac{Binomial(k | N, \epsilon)}{Binomial(k | N, \hat{\epsilon} ) }
1116/// \f]
1117/// See G. J. Feldman and R. D. Cousins, Phys. Rev. D57 (1998) 3873
1118/// and R. D. Cousins, K. E. Hymes, J. Tucker, Nuclear Instruments and Methods in Physics Research A 612 (2010) 388
1119///
1120/// Implemented using classes developed by Jordan Tucker and Luca Lista
1121/// See File hist/hist/src/TEfficiencyHelper.h
1122
1124{
1126 double alpha = 1.-level;
1127 fc.Init(alpha);
1128 fc.Calculate(passed, total);
1129 lower = fc.Lower();
1130 upper = fc.Upper();
1131 return true;
1132}
1133
1134////////////////////////////////////////////////////////////////////////////////
1135/// Calculates the boundaries using the mid-P binomial
1136/// interval (Lancaster method) from B. Cousing and J. Tucker.
1137/// See http://arxiv.org/abs/0905.3831 for a description and references for the method
1138///
1139/// Modify equal_tailed to get the kind of interval you want.
1140/// Can also be converted to interval on ratio of poisson means X/Y by the substitutions
1141/// ~~~ {.cpp}
1142/// X = passed
1143/// total = X + Y
1144/// lower_poisson = lower/(1 - lower)
1145/// upper_poisson = upper/(1 - upper)
1146/// ~~~
1147
1149{
1150 const double alpha = 1. - level;
1151 const bool equal_tailed = true; // change if you don;t want equal tailed interval
1152 const double alpha_min = equal_tailed ? alpha/2 : alpha;
1153 const double tol = 1e-9; // tolerance
1154 double pmin = 0;
1155 double pmax = 0;
1156 double p = 0;
1157
1158 pmin = 0; pmax = 1;
1159
1160
1161 // treat special case for 0<passed<1
1162 // do a linear interpolation of the upper limit values
1163 if ( passed > 0 && passed < 1) {
1164 double p0 = MidPInterval(total,0.0,level,bUpper);
1165 double p1 = MidPInterval(total,1.0,level,bUpper);
1166 p = (p1 - p0) * passed + p0;
1167 return p;
1168 }
1169
1170 while (std::abs(pmax - pmin) > tol) {
1171 p = (pmin + pmax)/2;
1172 //double v = 0.5 * ROOT::Math::binomial_pdf(int(passed), p, int(total));
1173 // make it work for non integer using the binomial - beta relationship
1174 double v = 0.5 * ROOT::Math::beta_pdf(p, passed+1., total-passed+1)/(total+1);
1175 //if (passed > 0) v += ROOT::Math::binomial_cdf(int(passed - 1), p, int(total));
1176 // compute the binomial cdf at passed -1
1177 if ( (passed-1) >= 0) v += ROOT::Math::beta_cdf_c(p, passed, total-passed+1);
1178
1179 double vmin = (bUpper) ? alpha_min : 1.- alpha_min;
1180 if (v > vmin)
1181 pmin = p;
1182 else
1183 pmax = p;
1184 }
1185
1186 return p;
1187}
1188
1189
1190////////////////////////////////////////////////////////////////////////////////
1191/**
1192Calculates the boundaries for a Bayesian confidence interval (shortest or central interval depending on the option)
1193
1194\param[in] total number of total events
1195\param[in] passed 0 <= number of passed events <= total
1196\param[in] level confidence level
1197\param[in] alpha shape parameter > 0 for the prior distribution (fBeta_alpha)
1198\param[in] beta shape parameter > 0 for the prior distribution (fBeta_beta)
1199\param[in] bUpper
1200 - true - upper boundary is returned
1201 - false - lower boundary is returned
1202\param[in] bShortest ??
1203
1204Note: In the case central confidence interval is calculated.
1205 when passed = 0 (or passed = total) the lower (or upper)
1206 interval values will be larger than 0 (or smaller than 1).
1207
1208Calculation:
1209
1210The posterior probability in bayesian statistics is given by:
1211\f[
1212 P(\varepsilon |k,N) \propto L(\varepsilon|k,N) \times Prior(\varepsilon)
1213\f]
1214As an efficiency can be interpreted as probability of a positive outcome of
1215a Bernoullli trial the likelihood function is given by the binomial
1216distribution:
1217\f[
1218 L(\varepsilon|k,N) = Binomial(N,k) \varepsilon ^{k} (1 - \varepsilon)^{N-k}
1219\f]
1220At the moment only beta distributions are supported as prior probabilities
1221of the efficiency (\f$ B(\alpha,\beta)\f$ is the beta function):
1222\f[
1223 Prior(\varepsilon) = \frac{1}{B(\alpha,\beta)} \varepsilon ^{\alpha - 1} (1 - \varepsilon)^{\beta - 1}
1224\f]
1225The posterior probability is therefore again given by a beta distribution:
1226\f[
1227 P(\varepsilon |k,N) \propto \varepsilon ^{k + \alpha - 1} (1 - \varepsilon)^{N - k + \beta - 1}
1228\f]
1229In case of central intervals
1230the lower boundary for the equal-tailed confidence interval is given by the
1231inverse cumulative (= quantile) function for the quantile \f$ \frac{1 - level}{2} \f$.
1232The upper boundary for the equal-tailed confidence interval is given by the
1233inverse cumulative (= quantile) function for the quantile \f$ \frac{1 + level}{2} \f$.
1234Hence it is the solution \f$ \varepsilon \f$ of the following equation:
1235\f[
1236 I_{\varepsilon}(k + \alpha,N - k + \beta) = \frac{1}{norm} \int_{0}^{\varepsilon} dt t^{k + \alpha - 1} (1 - t)^{N - k + \beta - 1} = \frac{1 \pm level}{2}
1237\f]
1238In the case of shortest interval the minimum interval around the mode is found by minimizing the length of all intervals width the
1239given probability content. See TEfficiency::BetaShortestInterval
1240*/
1241
1243{
1244 Double_t a = double(passed)+alpha;
1245 Double_t b = double(total-passed)+beta;
1246
1247 if (bShortest) {
1248 double lower = 0;
1249 double upper = 1;
1250 BetaShortestInterval(level,a,b,lower,upper);
1251 return (bUpper) ? upper : lower;
1252 }
1253 else
1254 return BetaCentralInterval(level, a, b, bUpper);
1255}
1256
1257////////////////////////////////////////////////////////////////////////////////
1258/// Calculates the boundaries for a central confidence interval for a Beta distribution
1259///
1260/// \param[in] level confidence level
1261/// \param[in] a parameter > 0 for the beta distribution (for a posterior is passed + prior_alpha
1262/// \param[in] b parameter > 0 for the beta distribution (for a posterior is (total-passed) + prior_beta
1263/// \param[in] bUpper true - upper boundary is returned
1264/// false - lower boundary is returned
1265
1267{
1268 if(bUpper) {
1269 if((a > 0) && (b > 0))
1270 return ROOT::Math::beta_quantile((1+level)/2,a,b);
1271 else {
1272 gROOT->Error("TEfficiency::BayesianCentral","Invalid input parameters - return 1");
1273 return 1;
1274 }
1275 }
1276 else {
1277 if((a > 0) && (b > 0))
1278 return ROOT::Math::beta_quantile((1-level)/2,a,b);
1279 else {
1280 gROOT->Error("TEfficiency::BayesianCentral","Invalid input parameters - return 0");
1281 return 0;
1282 }
1283 }
1284}
1285
1286struct Beta_interval_length {
1287 Beta_interval_length(Double_t level,Double_t alpha,Double_t beta ) :
1288 fCL(level), fAlpha(alpha), fBeta(beta)
1289 {}
1290
1291 Double_t LowerMax() {
1292 // max allowed value of lower given the interval size
1293 return ROOT::Math::beta_quantile_c(fCL, fAlpha,fBeta);
1294 }
1295
1296 Double_t operator() (double lower) const {
1297 // return length of interval
1298 Double_t plow = ROOT::Math::beta_cdf(lower, fAlpha, fBeta);
1299 Double_t pup = plow + fCL;
1300 double upper = ROOT::Math::beta_quantile(pup, fAlpha,fBeta);
1301 return upper-lower;
1302 }
1303 Double_t fCL; // interval size (confidence level)
1304 Double_t fAlpha; // beta distribution alpha parameter
1305 Double_t fBeta; // beta distribution beta parameter
1306
1307};
1308
1309////////////////////////////////////////////////////////////////////////////////
1310/// Calculates the boundaries for a shortest confidence interval for a Beta distribution
1311///
1312/// \param[in] level confidence level
1313/// \param[in] a parameter > 0 for the beta distribution (for a posterior is passed + prior_alpha
1314/// \param[in] b parameter > 0 for the beta distribution (for a posterior is (total-passed) + prior_beta
1315/// \param[out] upper upper boundary is returned
1316/// \param[out] lower lower boundary is returned
1317///
1318/// The lower/upper boundary are then obtained by finding the shortest interval of the beta distribution
1319/// contained the desired probability level.
1320/// The length of all possible intervals is minimized in order to find the shortest one
1321
1323{
1324 if (a <= 0 || b <= 0) {
1325 lower = 0; upper = 1;
1326 gROOT->Error("TEfficiency::BayesianShortest","Invalid input parameters - return [0,1]");
1327 return kFALSE;
1328 }
1329
1330 // treat here special cases when mode == 0 or 1
1331 double mode = BetaMode(a,b);
1332 if (mode == 0.0) {
1333 lower = 0;
1334 upper = ROOT::Math::beta_quantile(level, a, b);
1335 return kTRUE;
1336 }
1337 if (mode == 1.0) {
1338 lower = ROOT::Math::beta_quantile_c(level, a, b);
1339 upper = 1.0;
1340 return kTRUE;
1341 }
1342 // special case when the shortest interval is undefined return the central interval
1343 // can happen for a posterior when passed=total=0
1344 //
1345 if ( a==b && a<=1.0) {
1346 lower = BetaCentralInterval(level,a,b,kFALSE);
1347 upper = BetaCentralInterval(level,a,b,kTRUE);
1348 return kTRUE;
1349 }
1350
1351 // for the other case perform a minimization
1352 // make a function of the length of the posterior interval as a function of lower bound
1353 Beta_interval_length intervalLength(level,a,b);
1354 // minimize the interval length
1357 minim.SetFunction(func, 0, intervalLength.LowerMax() );
1358 minim.SetNpx(2); // no need to bracket with many iterations. Just do few times to estimate some better points
1359 bool ret = minim.Minimize(100, 1.E-10,1.E-10);
1360 if (!ret) {
1361 gROOT->Error("TEfficiency::BayesianShortes","Error finding the shortest interval");
1362 return kFALSE;
1363 }
1364 lower = minim.XMinimum();
1365 upper = lower + minim.FValMinimum();
1366 return kTRUE;
1367}
1368
1369////////////////////////////////////////////////////////////////////////////////
1370/// Compute the mean (average) of the beta distribution
1371///
1372/// \param[in] a parameter > 0 for the beta distribution (for a posterior is passed + prior_alpha
1373/// \param[in] b parameter > 0 for the beta distribution (for a posterior is (total-passed) + prior_beta
1374///
1375
1377{
1378 if (a <= 0 || b <= 0 ) {
1379 gROOT->Error("TEfficiency::BayesianMean","Invalid input parameters - return 0");
1380 return 0;
1381 }
1382
1383 Double_t mean = a / (a + b);
1384 return mean;
1385}
1386
1387////////////////////////////////////////////////////////////////////////////////
1388/// Compute the mode of the beta distribution
1389///
1390/// \param[in] a parameter > 0 for the beta distribution (for a posterior is passed + prior_alpha
1391/// \param[in] b parameter > 0 for the beta distribution (for a posterior is (total-passed) + prior_beta
1392///
1393/// note the mode is defined for a Beta(a,b) only if (a,b)>1 (a = passed+alpha; b = total-passed+beta)
1394/// return then the following in case (a,b) < 1:
1395/// - if (a==b) return 0.5 (it is really undefined)
1396/// - if (a < b) return 0;
1397/// - if (a > b) return 1;
1398
1400{
1401 if (a <= 0 || b <= 0 ) {
1402 gROOT->Error("TEfficiency::BayesianMode","Invalid input parameters - return 0");
1403 return 0;
1404 }
1405 if ( a <= 1 || b <= 1) {
1406 if ( a < b) return 0;
1407 if ( a > b) return 1;
1408 if (a == b) return 0.5; // cannot do otherwise
1409 }
1410
1411 // since a and b are > 1 here denominator cannot be 0 or < 0
1412 Double_t mode = (a - 1.0) / (a + b -2.0);
1413 return mode;
1414}
1415////////////////////////////////////////////////////////////////////////////////
1416/// Building standard data structure of a TEfficiency object
1417///
1418/// Notes:
1419/// - calls: SetName(name), SetTitle(title)
1420/// - set the statistic option to the default (kFCP)
1421/// - appends this object to the current directory SetDirectory(gDirectory)
1422
1423void TEfficiency::Build(const char* name,const char* title)
1424{
1425 SetName(name);
1426 SetTitle(title);
1427
1430
1431 SetBit(kPosteriorMode,false);
1433 SetBit(kUseWeights,false);
1434
1435 //set normalisation factors to 0, otherwise the += may not work properly
1438}
1439
1440////////////////////////////////////////////////////////////////////////////////
1441/// Checks binning for each axis
1442///
1443/// It is assumed that the passed histograms have the same dimension.
1444
1446{
1447
1448 const TAxis* ax1 = 0;
1449 const TAxis* ax2 = 0;
1450
1451 //check binning along axis
1452 for(Int_t j = 0; j < pass.GetDimension(); ++j) {
1453 switch(j) {
1454 case 0:
1455 ax1 = pass.GetXaxis();
1456 ax2 = total.GetXaxis();
1457 break;
1458 case 1:
1459 ax1 = pass.GetYaxis();
1460 ax2 = total.GetYaxis();
1461 break;
1462 case 2:
1463 ax1 = pass.GetZaxis();
1464 ax2 = total.GetZaxis();
1465 break;
1466 }
1467
1468 if(ax1->GetNbins() != ax2->GetNbins()) {
1469 gROOT->Info("TEfficiency::CheckBinning","Histograms are not consistent: they have different number of bins");
1470 return false;
1471 }
1472
1473 for(Int_t i = 1; i <= ax1->GetNbins() + 1; ++i)
1474 if(!TMath::AreEqualRel(ax1->GetBinLowEdge(i), ax2->GetBinLowEdge(i), 1.E-15)) {
1475 gROOT->Info("TEfficiency::CheckBinning","Histograms are not consistent: they have different bin edges");
1476 return false;
1477 }
1478
1479
1480 }
1481
1482 return true;
1483}
1484
1485////////////////////////////////////////////////////////////////////////////////
1486/// Checks the consistence of the given histograms
1487///
1488/// The histograms are considered as consistent if:
1489/// - both have the same dimension
1490/// - both have the same binning
1491/// - pass.GetBinContent(i) <= total.GetBinContent(i) for each bin i
1492///
1493
1495{
1496 if(pass.GetDimension() != total.GetDimension()) {
1497 gROOT->Error("TEfficiency::CheckConsistency","passed TEfficiency objects have different dimensions");
1498 return false;
1499 }
1500
1501 if(!CheckBinning(pass,total)) {
1502 gROOT->Error("TEfficiency::CheckConsistency","passed TEfficiency objects have different binning");
1503 return false;
1504 }
1505
1506 if(!CheckEntries(pass,total)) {
1507 gROOT->Error("TEfficiency::CheckConsistency","passed TEfficiency objects do not have consistent bin contents");
1508 return false;
1509 }
1510
1511 return true;
1512}
1513
1514////////////////////////////////////////////////////////////////////////////////
1515/// Checks whether bin contents are compatible with binomial statistics
1516///
1517/// The following inequality has to be valid for each bin i:
1518/// total.GetBinContent(i) >= pass.GetBinContent(i)
1519///
1520///
1521///
1522/// Note:
1523///
1524/// - It is assumed that both histograms have the same dimension and binning.
1525
1527{
1528
1529 //check: pass <= total
1530 Int_t nbinsx, nbinsy, nbinsz, nbins;
1531
1532 nbinsx = pass.GetNbinsX();
1533 nbinsy = pass.GetNbinsY();
1534 nbinsz = pass.GetNbinsZ();
1535
1536 switch(pass.GetDimension()) {
1537 case 1: nbins = nbinsx + 2; break;
1538 case 2: nbins = (nbinsx + 2) * (nbinsy + 2); break;
1539 case 3: nbins = (nbinsx + 2) * (nbinsy + 2) * (nbinsz + 2); break;
1540 default: nbins = 0;
1541 }
1542
1543 for(Int_t i = 0; i < nbins; ++i) {
1544 if(pass.GetBinContent(i) > total.GetBinContent(i)) {
1545 gROOT->Info("TEfficiency::CheckEntries","Histograms are not consistent: passed bin content > total bin content");
1546 return false;
1547 }
1548 }
1549
1550 return true;
1551}
1552
1553////////////////////////////////////////////////////////////////////////////////
1554/// Check if both histogram are weighted. If they are weighted a true is returned
1555///
1557{
1558 if (pass.GetSumw2N() == 0 && total.GetSumw2N() == 0) return false;
1559
1560 // check also that the total sum of weight and weight squares are consistent
1561 Double_t statpass[TH1::kNstat];
1562 Double_t stattotal[TH1::kNstat];
1563
1564 pass.GetStats(statpass);
1565 total.GetStats(stattotal);
1566
1567 double tolerance = (total.IsA() == TH1F::Class() ) ? 1.E-5 : 1.E-12;
1568
1569 //require: sum of weights == sum of weights^2
1570 if(!TMath::AreEqualRel(statpass[0],statpass[1],tolerance) ||
1571 !TMath::AreEqualRel(stattotal[0],stattotal[1],tolerance) ) {
1572 return true;
1573 }
1574
1575 // histograms are not weighted
1576 return false;
1577
1578}
1579
1580
1581////////////////////////////////////////////////////////////////////////////////
1582/// Create the graph used be painted (for dim=1 TEfficiency)
1583/// The return object is managed by the caller
1584
1586{
1587 if (GetDimension() != 1) {
1588 Error("CreatePaintingGraph","Call this function only for dimension == 1");
1589 return 0;
1590 }
1591
1592
1593 Int_t npoints = fTotalHistogram->GetNbinsX();
1594 TGraphAsymmErrors * graph = new TGraphAsymmErrors(npoints);
1595 graph->SetName("eff_graph");
1596 FillGraph(graph,opt);
1597
1598 return graph;
1599}
1600
1601
1602////////////////////////////////////////////////////////////////////////////////
1603/// Fill the graph to be painted with information from TEfficiency
1604/// Internal method called by TEfficiency::Paint or TEfficiency::CreateGraph
1605
1607{
1608 TString option = opt;
1609 option.ToLower();
1610
1611 Bool_t plot0Bins = false;
1612 if (option.Contains("e0") ) plot0Bins = true;
1613
1614 Double_t x,y,xlow,xup,ylow,yup;
1615 //point i corresponds to bin i+1 in histogram
1616 // point j is point graph index
1617 // LM: cannot use TGraph::SetPoint because it deletes the underlying
1618 // histogram each time (see TGraph::SetPoint)
1619 // so use it only when extra points are added to the graph
1620 Int_t j = 0;
1621 double * px = graph->GetX();
1622 double * py = graph->GetY();
1623 double * exl = graph->GetEXlow();
1624 double * exh = graph->GetEXhigh();
1625 double * eyl = graph->GetEYlow();
1626 double * eyh = graph->GetEYhigh();
1627 Int_t npoints = fTotalHistogram->GetNbinsX();
1628 for (Int_t i = 0; i < npoints; ++i) {
1629 if (!plot0Bins && fTotalHistogram->GetBinContent(i+1) == 0 ) continue;
1631 y = GetEfficiency(i+1);
1633 xup = fTotalHistogram->GetBinWidth(i+1) - xlow;
1634 ylow = GetEfficiencyErrorLow(i+1);
1635 yup = GetEfficiencyErrorUp(i+1);
1636 // in the case the graph already existed and extra points have been added
1637 if (j >= graph->GetN() ) {
1638 graph->SetPoint(j,x,y);
1639 graph->SetPointError(j,xlow,xup,ylow,yup);
1640 }
1641 else {
1642 px[j] = x;
1643 py[j] = y;
1644 exl[j] = xlow;
1645 exh[j] = xup;
1646 eyl[j] = ylow;
1647 eyh[j] = yup;
1648 }
1649 j++;
1650 }
1651
1652 // tell the graph the effective number of points
1653 graph->Set(j);
1654 //refresh title before painting if changed
1655 TString oldTitle = graph->GetTitle();
1656 TString newTitle = GetTitle();
1657 if (oldTitle != newTitle ) {
1658 graph->SetTitle(newTitle);
1659 }
1660
1661 // set the axis labels
1664 if (xlabel) graph->GetXaxis()->SetTitle(xlabel);
1665 if (ylabel) graph->GetYaxis()->SetTitle(ylabel);
1666
1667 //copying style information
1671
1672 // copy axis labels if existing. Assume are there in the total histogram
1673 if (fTotalHistogram->GetXaxis()->GetLabels() != nullptr) {
1674 for (int ibin = 1; ibin <= fTotalHistogram->GetXaxis()->GetNbins(); ++ibin) {
1675 // we need to find the right bin for the Histogram representing the xaxis of the graph
1676 int grbin = graph->GetXaxis()->FindBin(fTotalHistogram->GetXaxis()->GetBinCenter(ibin));
1677 graph->GetXaxis()->SetBinLabel(grbin, fTotalHistogram->GetXaxis()->GetBinLabel(ibin));
1678 }
1679 }
1680 // this method forces the graph to compute correctly the axis
1681 // according to the given points
1682 graph->GetHistogram();
1683
1684}
1685
1686////////////////////////////////////////////////////////////////////////////////
1687/// Create the histogram used to be painted (for dim=2 TEfficiency)
1688/// The return object is managed by the caller
1689
1691{
1692 if (GetDimension() != 2) {
1693 Error("CreatePaintingistogram","Call this function only for dimension == 2");
1694 return 0;
1695 }
1696
1697 Int_t nbinsx = fTotalHistogram->GetNbinsX();
1698 Int_t nbinsy = fTotalHistogram->GetNbinsY();
1699 TAxis * xaxis = fTotalHistogram->GetXaxis();
1700 TAxis * yaxis = fTotalHistogram->GetYaxis();
1701 TH2 * hist = 0;
1702
1703 if (xaxis->IsVariableBinSize() && yaxis->IsVariableBinSize() )
1704 hist = new TH2F("eff_histo",GetTitle(),nbinsx,xaxis->GetXbins()->GetArray(),
1705 nbinsy,yaxis->GetXbins()->GetArray());
1706 else if (xaxis->IsVariableBinSize() && ! yaxis->IsVariableBinSize() )
1707 hist = new TH2F("eff_histo",GetTitle(),nbinsx,xaxis->GetXbins()->GetArray(),
1708 nbinsy,yaxis->GetXmin(), yaxis->GetXmax());
1709 else if (!xaxis->IsVariableBinSize() && yaxis->IsVariableBinSize() )
1710 hist = new TH2F("eff_histo",GetTitle(),nbinsx,xaxis->GetXmin(), xaxis->GetXmax(),
1711 nbinsy,yaxis->GetXbins()->GetArray());
1712 else
1713 hist = new TH2F("eff_histo",GetTitle(),nbinsx,xaxis->GetXmin(), xaxis->GetXmax(),
1714 nbinsy,yaxis->GetXmin(), yaxis->GetXmax());
1715
1716
1717 hist->SetDirectory(0);
1718
1719 FillHistogram(hist);
1720
1721 return hist;
1722}
1723
1724////////////////////////////////////////////////////////////////////////////////
1725/// Fill the 2d histogram to be painted with information from TEfficiency 2D
1726/// Internal method called by TEfficiency::Paint or TEfficiency::CreatePaintingGraph
1727
1729{
1730 //refresh title before each painting
1731 hist->SetTitle(GetTitle());
1732
1733 // set the axis labels
1737 if (xlabel) hist->GetXaxis()->SetTitle(xlabel);
1738 if (ylabel) hist->GetYaxis()->SetTitle(ylabel);
1739 if (zlabel) hist->GetZaxis()->SetTitle(zlabel);
1740
1741 Int_t bin;
1742 Int_t nbinsx = hist->GetNbinsX();
1743 Int_t nbinsy = hist->GetNbinsY();
1744 for(Int_t i = 0; i < nbinsx + 2; ++i) {
1745 for(Int_t j = 0; j < nbinsy + 2; ++j) {
1746 bin = GetGlobalBin(i,j);
1747 hist->SetBinContent(bin,GetEfficiency(bin));
1748 }
1749 }
1750
1751 // copy axis labels if existing. Assume are there in the total histogram
1752 if (fTotalHistogram->GetXaxis()->GetLabels() != nullptr) {
1753 for (int ibinx = 1; ibinx <= fTotalHistogram->GetXaxis()->GetNbins(); ++ibinx)
1754 hist->GetXaxis()->SetBinLabel(ibinx, fTotalHistogram->GetXaxis()->GetBinLabel(ibinx));
1755 }
1756 if (fTotalHistogram->GetYaxis()->GetLabels() != nullptr) {
1757 for (int ibiny = 1; ibiny <= fTotalHistogram->GetYaxis()->GetNbins(); ++ibiny)
1758 hist->GetYaxis()->SetBinLabel(ibiny, fTotalHistogram->GetYaxis()->GetBinLabel(ibiny));
1759 }
1760
1761 //copying style information
1762 TAttLine::Copy(*hist);
1763 TAttFill::Copy(*hist);
1764 TAttMarker::Copy(*hist);
1765 hist->SetStats(0);
1766
1767 return;
1768
1769}
1770////////////////////////////////////////////////////////////////////////////////
1771/**
1772Calculates the boundaries for the frequentist Clopper-Pearson interval
1773
1774This interval is recommended by the PDG.
1775
1776\param[in] total number of total events
1777\param[in] passed 0 <= number of passed events <= total
1778\param[in] level confidence level
1779\param[in] bUpper true - upper boundary is returned
1780 ;false - lower boundary is returned
1781
1782Calculation:
1783
1784The lower boundary of the Clopper-Pearson interval is the "exact" inversion
1785of the test:
1786 \f{eqnarray*}{
1787 P(x \geq passed; total) &=& \frac{1 - level}{2}\\
1788 P(x \geq passed; total) &=& 1 - P(x \leq passed - 1; total)\\
1789 &=& 1 - \frac{1}{norm} * \int_{0}^{1 - \varepsilon} t^{total - passed} (1 - t)^{passed - 1} dt\\
1790 &=& 1 - \frac{1}{norm} * \int_{\varepsilon}^{1} t^{passed - 1} (1 - t)^{total - passed} dt\\
1791 &=& \frac{1}{norm} * \int_{0}^{\varepsilon} t^{passed - 1} (1 - t)^{total - passed} dt\\
1792 &=& I_{\varepsilon}(passed,total - passed + 1)
1793 \f}
1794The lower boundary is therefore given by the \f$ \frac{1 - level}{2}\f$ quantile
1795of the beta distribution.
1796
1797The upper boundary of the Clopper-Pearson interval is the "exact" inversion
1798of the test:
1799 \f{eqnarray*}{
1800 P(x \leq passed; total) &=& \frac{1 - level}{2}\\
1801 P(x \leq passed; total) &=& \frac{1}{norm} * \int_{0}^{1 - \varepsilon} t^{total - passed - 1} (1 - t)^{passed} dt\\
1802 &=& \frac{1}{norm} * \int_{\varepsilon}^{1} t^{passed} (1 - t)^{total - passed - 1} dt\\
1803 &=& 1 - \frac{1}{norm} * \int_{0}^{\varepsilon} t^{passed} (1 - t)^{total - passed - 1} dt\\
1804 \Rightarrow 1 - \frac{1 - level}{2} &=& \frac{1}{norm} * \int_{0}^{\varepsilon} t^{passed} (1 - t)^{total - passed -1} dt\\
1805 \frac{1 + level}{2} &=& I_{\varepsilon}(passed + 1,total - passed)
1806 \f}
1807The upper boundary is therefore given by the \f$\frac{1 + level}{2}\f$ quantile
1808of the beta distribution.
1809
1810Note: The connection between the binomial distribution and the regularized
1811 incomplete beta function \f$ I_{\varepsilon}(\alpha,\beta)\f$ has been used.
1812*/
1813
1815{
1816 Double_t alpha = (1.0 - level) / 2;
1817 if(bUpper)
1818 return ((passed == total) ? 1.0 : ROOT::Math::beta_quantile(1 - alpha,passed + 1,total-passed));
1819 else
1820 return ((passed == 0) ? 0.0 : ROOT::Math::beta_quantile(alpha,passed,total-passed+1.0));
1821}
1822////////////////////////////////////////////////////////////////////////////////
1823/**
1824 Calculates the combined efficiency and its uncertainties
1825
1826 This method does a bayesian combination of the given samples.
1827
1828 \param[in] up contains the upper limit of the confidence interval afterwards
1829 \param[in] low contains the lower limit of the confidence interval afterwards
1830 \param[in] n number of samples which are combined
1831 \param[in] pass array of length n containing the number of passed events
1832 \param[in] total array of length n containing the corresponding numbers of total events
1833 \param[in] alpha shape parameters for the beta distribution as prior
1834 \param[in] beta shape parameters for the beta distribution as prior
1835 \param[in] level desired confidence level
1836 \param[in] w weights for each sample; if not given, all samples get the weight 1
1837 The weights do not need to be normalized, since they are internally renormalized
1838 to the number of effective entries.
1839 \param[in] opt
1840 - mode : The mode is returned instead of the mean of the posterior as best value
1841 When using the mode the shortest interval is also computed instead of the central one
1842 - shortest: compute shortest interval (done by default if mode option is set)
1843 - central: compute central interval (done by default if mode option is NOT set)
1844
1845 Calculation:
1846
1847 The combined posterior distributions is calculated from the Bayes theorem assuming a common prior Beta distribution.
1848 It is easy to proof that the combined posterior is then:
1849 \f{eqnarray*}{
1850 P_{comb}(\epsilon |{w_{i}}; {k_{i}}; {N_{i}}) &=& B(\epsilon, \sum_{i}{ w_{i} k_{i}} + \alpha, \sum_{i}{ w_{i}(n_{i}-k_{i})}+\beta)\\
1851 w_{i} &=& weight\ for\ each\ sample\ renormalized\ to\ the\ effective\ entries\\
1852 w^{'}_{i} &=& w_{i} \frac{ \sum_{i} {w_{i} } } { \sum_{i} {w_{i}^{2} } }
1853 \f}
1854
1855 The estimated efficiency is the mode (or the mean) of the obtained posterior distribution
1856
1857 The boundaries of the confidence interval for a confidence level (1 - a)
1858 are given by the a/2 and 1-a/2 quantiles of the resulting cumulative
1859 distribution.
1860
1861 Example (uniform prior distribution):
1862
1863Begin_Macro(source)
1864{
1865 TCanvas* c1 = new TCanvas("c1","",600,800);
1866 c1->Divide(1,2);
1867 c1->SetFillStyle(1001);
1868 c1->SetFillColor(kWhite);
1869
1870 TF1* p1 = new TF1("p1","TMath::BetaDist(x,19,9)",0,1);
1871 TF1* p2 = new TF1("p2","TMath::BetaDist(x,4,8)",0,1);
1872 TF1* comb = new TF1("comb2","TMath::BetaDist(x,[0],[1])",0,1);
1873 double nrm = 1./(0.6*0.6+0.4*0.4); // weight normalization
1874 double a = 0.6*18.0 + 0.4*3.0 + 1.0; // new alpha parameter of combined beta dist.
1875 double b = 0.6*10+0.4*7+1.0; // new beta parameter of combined beta dist.
1876 comb->SetParameters(nrm*a ,nrm *b );
1877 TF1* const1 = new TF1("const1","0.05",0,1);
1878 TF1* const2 = new TF1("const2","0.95",0,1);
1879
1880 p1->SetLineColor(kRed);
1881 p1->SetTitle("combined posteriors;#epsilon;P(#epsilon|k,N)");
1882 p2->SetLineColor(kBlue);
1883 comb->SetLineColor(kGreen+2);
1884
1885 TLegend* leg1 = new TLegend(0.12,0.65,0.5,0.85);
1886 leg1->AddEntry(p1,"k1 = 18, N1 = 26","l");
1887 leg1->AddEntry(p2,"k2 = 3, N2 = 10","l");
1888 leg1->AddEntry(comb,"combined: p1 = 0.6, p2=0.4","l");
1889
1890 c1->cd(1);
1891 comb->Draw();
1892 p1->Draw("same");
1893 p2->Draw("same");
1894 leg1->Draw("same");
1895 c1->cd(2);
1896 const1->SetLineWidth(1);
1897 const2->SetLineWidth(1);
1898 TGraph* gr = (TGraph*)comb->DrawIntegral();
1899 gr->SetTitle("cumulative function of combined posterior with boundaries for cl = 95%;#epsilon;CDF");
1900 const1->Draw("same");
1901 const2->Draw("same");
1902
1903 c1->cd(0);
1904 return c1;
1905}
1906End_Macro
1907
1908**/
1909////////////////////////////////////////////////////////////////////
1911 const Int_t* pass,const Int_t* total,
1912 Double_t alpha, Double_t beta,
1913 Double_t level,const Double_t* w,Option_t* opt)
1914{
1915 TString option(opt);
1916 option.ToLower();
1917
1918 //LM: new formula for combination
1919 // works only if alpha beta are the same always
1920 // the weights are normalized to w(i) -> N_eff w(i)/ Sum w(i)
1921 // i.e. w(i) -> Sum (w(i) / Sum (w(i)^2) * w(i)
1922 // norm = Sum (w(i) / Sum (w(i)^2)
1923 double ntot = 0;
1924 double ktot = 0;
1925 double sumw = 0;
1926 double sumw2 = 0;
1927 for (int i = 0; i < n ; ++i) {
1928 if(pass[i] > total[i]) {
1929 ::Error("TEfficiency::Combine","total events = %i < passed events %i",total[i],pass[i]);
1930 ::Info("TEfficiency::Combine","stop combining");
1931 return -1;
1932 }
1933
1934 ntot += w[i] * total[i];
1935 ktot += w[i] * pass[i];
1936 sumw += w[i];
1937 sumw2 += w[i]*w[i];
1938 //mean += w[i] * (pass[i] + alpha[i])/(total[i] + alpha[i] + beta[i]);
1939 }
1940 double norm = sumw/sumw2;
1941 ntot *= norm;
1942 ktot *= norm;
1943 if(ktot > ntot) {
1944 ::Error("TEfficiency::Combine","total = %f < passed %f",ntot,ktot);
1945 ::Info("TEfficiency::Combine","stop combining");
1946 return -1;
1947 }
1948
1949 double a = ktot + alpha;
1950 double b = ntot - ktot + beta;
1951
1952 double mean = a/(a+b);
1953 double mode = BetaMode(a,b);
1954
1955
1956 Bool_t shortestInterval = option.Contains("sh") || ( option.Contains("mode") && !option.Contains("cent") );
1957
1958 if (shortestInterval)
1959 BetaShortestInterval(level, a, b, low, up);
1960 else {
1961 low = BetaCentralInterval(level, a, b, false);
1962 up = BetaCentralInterval(level, a, b, true);
1963 }
1964
1965 if (option.Contains("mode")) return mode;
1966 return mean;
1967
1968}
1969////////////////////////////////////////////////////////////////////////////////
1970/// Combines a list of 1-dimensional TEfficiency objects
1971///
1972/// A TGraphAsymmErrors object is returned which contains the estimated
1973/// efficiency and its uncertainty for each bin.
1974/// If the combination fails, a zero pointer is returned.
1975///
1976/// At the moment the combining is only implemented for bayesian statistics.
1977///
1978/// \param[in] pList list containing TEfficiency objects which should be combined
1979/// only one-dimensional efficiencies are taken into account
1980/// \param[in] option
1981/// - s : strict combining; only TEfficiency objects with the same beta
1982/// prior and the flag kIsBayesian == true are combined
1983/// If not specified the prior parameter of the first TEfficiency object is used
1984/// - v : verbose mode; print information about combining
1985/// - cl=x : set confidence level (0 < cl < 1). If not specified, the
1986/// confidence level of the first TEfficiency object is used.
1987/// - mode Use mode of combined posterior as estimated value for the efficiency
1988/// - shortest: compute shortest interval (done by default if mode option is set)
1989/// - central: compute central interval (done by default if mode option is NOT set)
1990/// \param[in] n number of weights (has to be the number of one-dimensional
1991/// TEfficiency objects in pList)
1992/// If no weights are passed, the internal weights GetWeight() of
1993/// the given TEfficiency objects are used.
1994/// \param[in] w array of length n with weights for each TEfficiency object in
1995/// pList (w[0] correspond to pList->First ... w[n-1] -> pList->Last)
1996/// The weights do not have to be normalised.
1997///
1998/// For each bin the calculation is done by the Combine(double&, double& ...) method.
1999
2001 Int_t n,const Double_t* w)
2002{
2003 TString opt = option;
2004 opt.ToLower();
2005
2006 //parameter of prior distribution, confidence level and normalisation factor
2007 Double_t alpha = -1;
2008 Double_t beta = -1;
2009 Double_t level = 0;
2010
2011 //flags for combining
2012 Bool_t bStrict = false;
2013 Bool_t bOutput = false;
2014 Bool_t bWeights = false;
2015 //list of all information needed to weight and combine efficiencies
2016 std::vector<TH1*> vTotal; vTotal.reserve(n);
2017 std::vector<TH1*> vPassed; vPassed.reserve(n);
2018 std::vector<Double_t> vWeights; vWeights.reserve(n);
2019 // std::vector<Double_t> vAlpha;
2020 // std::vector<Double_t> vBeta;
2021
2022 if(opt.Contains("s")) {
2023 opt.ReplaceAll("s","");
2024 bStrict = true;
2025 }
2026
2027 if(opt.Contains("v")) {
2028 opt.ReplaceAll("v","");
2029 bOutput = true;
2030 }
2031
2032 if(opt.Contains("cl=")) {
2033 Ssiz_t pos = opt.Index("cl=") + 3;
2034 level = atof( opt(pos,opt.Length() ).Data() );
2035 if((level <= 0) || (level >= 1))
2036 level = 0;
2037 opt.ReplaceAll("cl=","");
2038 }
2039
2040 //are weights explicitly given
2041 if(n && w) {
2042 bWeights = true;
2043 for(Int_t k = 0; k < n; ++k) {
2044 if(w[k] > 0)
2045 vWeights.push_back(w[k]);
2046 else {
2047 gROOT->Error("TEfficiency::Combine","invalid custom weight found w = %.2lf",w[k]);
2048 gROOT->Info("TEfficiency::Combine","stop combining");
2049 return 0;
2050 }
2051 }
2052 }
2053
2054 TIter next(pList);
2055 TObject* obj = 0;
2056 TEfficiency* pEff = 0;
2057 while((obj = next())) {
2058 pEff = dynamic_cast<TEfficiency*>(obj);
2059 //is object a TEfficiency object?
2060 if(pEff) {
2061 if(pEff->GetDimension() > 1)
2062 continue;
2063 if(!level) level = pEff->GetConfidenceLevel();
2064
2065 if(alpha<1) alpha = pEff->GetBetaAlpha();
2066 if(beta<1) beta = pEff->GetBetaBeta();
2067
2068 //if strict combining, check priors, confidence level and statistic
2069 if(bStrict) {
2070 if(alpha != pEff->GetBetaAlpha())
2071 continue;
2072 if(beta != pEff->GetBetaBeta())
2073 continue;
2074 if(!pEff->UsesBayesianStat())
2075 continue;
2076 }
2077
2078 vTotal.push_back(pEff->fTotalHistogram);
2079 vPassed.push_back(pEff->fPassedHistogram);
2080
2081 //no weights given -> use weights of TEfficiency objects
2082 if(!bWeights)
2083 vWeights.push_back(pEff->fWeight);
2084
2085 //strict combining -> using global prior
2086 // if(bStrict) {
2087 // vAlpha.push_back(alpha);
2088 // vBeta.push_back(beta);
2089 // }
2090 // else {
2091 // vAlpha.push_back(pEff->GetBetaAlpha());
2092 // vBeta.push_back(pEff->GetBetaBeta());
2093 // }
2094 }
2095 }
2096
2097 //no TEfficiency objects found
2098 if(vTotal.empty()) {
2099 gROOT->Error("TEfficiency::Combine","no TEfficiency objects in given list");
2100 gROOT->Info("TEfficiency::Combine","stop combining");
2101 return 0;
2102 }
2103
2104 //invalid number of custom weights
2105 if(bWeights && (n != (Int_t)vTotal.size())) {
2106 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());
2107 gROOT->Info("TEfficiency::Combine","stop combining");
2108 return 0;
2109 }
2110
2111 Int_t nbins_max = vTotal.at(0)->GetNbinsX();
2112 //check binning of all histograms
2113 for(UInt_t i=0; i<vTotal.size(); ++i) {
2114 if (!TEfficiency::CheckBinning(*vTotal.at(0),*vTotal.at(i)) )
2115 gROOT->Warning("TEfficiency::Combine","histograms have not the same binning -> results may be useless");
2116 if(vTotal.at(i)->GetNbinsX() < nbins_max) nbins_max = vTotal.at(i)->GetNbinsX();
2117 }
2118
2119 //display information about combining
2120 if(bOutput) {
2121 gROOT->Info("TEfficiency::Combine","combining %i TEfficiency objects",(Int_t)vTotal.size());
2122 if(bWeights)
2123 gROOT->Info("TEfficiency::Combine","using custom weights");
2124 if(bStrict) {
2125 gROOT->Info("TEfficiency::Combine","using the following prior probability for the efficiency: P(e) ~ Beta(e,%.3lf,%.3lf)",alpha,beta);
2126 }
2127 else
2128 gROOT->Info("TEfficiency::Combine","using individual priors of each TEfficiency object");
2129 gROOT->Info("TEfficiency::Combine","confidence level = %.2lf",level);
2130 }
2131
2132 //create TGraphAsymmErrors with efficiency
2133 std::vector<Double_t> x(nbins_max);
2134 std::vector<Double_t> xlow(nbins_max);
2135 std::vector<Double_t> xhigh(nbins_max);
2136 std::vector<Double_t> eff(nbins_max);
2137 std::vector<Double_t> efflow(nbins_max);
2138 std::vector<Double_t> effhigh(nbins_max);
2139
2140 //parameters for combining:
2141 //number of objects
2142 Int_t num = vTotal.size();
2143 std::vector<Int_t> pass(num);
2144 std::vector<Int_t> total(num);
2145
2146 //loop over all bins
2147 Double_t low = 0;
2148 Double_t up = 0;
2149 for(Int_t i=1; i <= nbins_max; ++i) {
2150 //the binning of the x-axis is taken from the first total histogram
2151 x[i-1] = vTotal.at(0)->GetBinCenter(i);
2152 xlow[i-1] = x[i-1] - vTotal.at(0)->GetBinLowEdge(i);
2153 xhigh[i-1] = vTotal.at(0)->GetBinWidth(i) - xlow[i-1];
2154
2155 for(Int_t j = 0; j < num; ++j) {
2156 pass[j] = (Int_t)(vPassed.at(j)->GetBinContent(i) + 0.5);
2157 total[j] = (Int_t)(vTotal.at(j)->GetBinContent(i) + 0.5);
2158 }
2159
2160 //fill efficiency and errors
2161 eff[i-1] = Combine(up,low,num,&pass[0],&total[0],alpha,beta,level,&vWeights[0],opt.Data());
2162 //did an error occurred ?
2163 if(eff[i-1] == -1) {
2164 gROOT->Error("TEfficiency::Combine","error occurred during combining");
2165 gROOT->Info("TEfficiency::Combine","stop combining");
2166 return 0;
2167 }
2168 efflow[i-1]= eff[i-1] - low;
2169 effhigh[i-1]= up - eff[i-1];
2170 }//loop over all bins
2171
2172 TGraphAsymmErrors* gr = new TGraphAsymmErrors(nbins_max,&x[0],&eff[0],&xlow[0],&xhigh[0],&efflow[0],&effhigh[0]);
2173
2174 return gr;
2175}
2176
2177////////////////////////////////////////////////////////////////////////////////
2178/// Compute distance from point px,py to a graph.
2179///
2180/// Compute the closest distance of approach from point px,py to this line.
2181/// The distance is computed in pixels units.
2182///
2183/// Forward the call to the painted graph
2184
2186{
2187 if (fPaintGraph) return fPaintGraph->DistancetoPrimitive(px,py);
2188 if (fPaintHisto) return fPaintHisto->DistancetoPrimitive(px,py);
2189 return 0;
2190}
2191
2192
2193////////////////////////////////////////////////////////////////////////////////
2194/// Draws the current TEfficiency object
2195///
2196/// \param[in] opt
2197/// - 1-dimensional case: same options as TGraphAsymmErrors::Draw()
2198/// but as default "AP" is used
2199/// - 2-dimensional case: same options as TH2::Draw()
2200/// - 3-dimensional case: not yet supported
2201///
2202/// Specific TEfficiency drawing options:
2203/// - E0 - plot bins where the total number of passed events is zero
2204/// (the error interval will be [0,1] )
2205
2207{
2208 //check options
2209 TString option = opt;
2210 option.ToLower();
2211 // use by default "AP"
2212 if (option.IsNull() ) option = "ap";
2213
2214 if(gPad && !option.Contains("same"))
2215 gPad->Clear();
2216 else {
2217 // add always "a" if not present
2218 if (!option.Contains("a") ) option += "a";
2219 }
2220
2221 // add always p to the option
2222 if (!option.Contains("p") ) option += "p";
2223
2224
2225 AppendPad(option.Data());
2226}
2227
2228////////////////////////////////////////////////////////////////////////////////
2229/// Execute action corresponding to one event.
2230///
2231/// This member function is called when the drawn class is clicked with the locator
2232/// If Left button clicked on one of the line end points, this point
2233/// follows the cursor until button is released.
2234///
2235/// if Middle button clicked, the line is moved parallel to itself
2236/// until the button is released.
2237/// Forward the call to the underlying graph
2238
2240{
2241 if (fPaintGraph) fPaintGraph->ExecuteEvent(event,px,py);
2242 else if (fPaintHisto) fPaintHisto->ExecuteEvent(event,px,py);
2243}
2244
2245////////////////////////////////////////////////////////////////////////////////
2246/// This function is used for filling the two histograms.
2247///
2248/// \param[in] bPassed flag whether the current event passed the selection
2249/// - true: both histograms are filled
2250/// - false: only the total histogram is filled
2251/// \param[in] x x-value
2252/// \param[in] y y-value (use default=0 for 1-D efficiencies)
2253/// \param[in] z z-value (use default=0 for 2-D or 1-D efficiencies)
2254
2256{
2257 switch(GetDimension()) {
2258 case 1:
2260 if(bPassed)
2262 break;
2263 case 2:
2264 ((TH2*)(fTotalHistogram))->Fill(x,y);
2265 if(bPassed)
2266 ((TH2*)(fPassedHistogram))->Fill(x,y);
2267 break;
2268 case 3:
2269 ((TH3*)(fTotalHistogram))->Fill(x,y,z);
2270 if(bPassed)
2271 ((TH3*)(fPassedHistogram))->Fill(x,y,z);
2272 break;
2273 }
2274}
2275
2276////////////////////////////////////////////////////////////////////////////////
2277///This function is used for filling the two histograms with a weight.
2278///
2279/// \param[in] bPassed flag whether the current event passed the selection
2280/// - true: both histograms are filled
2281/// - false: only the total histogram is filled
2282/// \param[in] weight weight for the event
2283/// \param[in] x x-value
2284/// \param[in] y y-value (use default=0 for 1-D efficiencies)
2285/// \param[in] z z-value (use default=0 for 2-D or 1-D efficiencies)
2286///
2287/// Note: - this function will call SetUseWeightedEvents if it was not called by the user before
2288
2290{
2291 if(!TestBit(kUseWeights))
2292 {
2293 // Info("FillWeighted","call SetUseWeightedEvents() manually to ensure correct storage of sum of weights squared");
2295 }
2296
2297 switch(GetDimension()) {
2298 case 1:
2299 fTotalHistogram->Fill(x,weight);
2300 if(bPassed)
2301 fPassedHistogram->Fill(x,weight);
2302 break;
2303 case 2:
2304 ((TH2*)(fTotalHistogram))->Fill(x,y,weight);
2305 if(bPassed)
2306 ((TH2*)(fPassedHistogram))->Fill(x,y,weight);
2307 break;
2308 case 3:
2309 ((TH3*)(fTotalHistogram))->Fill(x,y,z,weight);
2310 if(bPassed)
2311 ((TH3*)(fPassedHistogram))->Fill(x,y,z,weight);
2312 break;
2313 }
2314}
2315
2316////////////////////////////////////////////////////////////////////////////////
2317/// Returns the global bin number containing the given values
2318///
2319/// Note:
2320///
2321/// - values which belong to dimensions higher than the current dimension
2322/// of the TEfficiency object are ignored (i.e. for 1-dimensional
2323/// efficiencies only the x-value is considered)
2324
2326{
2328 Int_t ny = 0;
2329 Int_t nz = 0;
2330
2331 switch(GetDimension()) {
2332 case 3: nz = fTotalHistogram->GetZaxis()->FindFixBin(z);
2333 case 2: ny = fTotalHistogram->GetYaxis()->FindFixBin(y);break;
2334 }
2335
2336 return GetGlobalBin(nx,ny,nz);
2337}
2338
2339////////////////////////////////////////////////////////////////////////////////
2340/// Fits the efficiency using the TBinomialEfficiencyFitter class
2341///
2342/// The resulting fit function is added to the list of associated functions.
2343///
2344/// Options:
2345/// - "+": previous fitted functions in the list are kept, by default
2346/// all functions in the list are deleted
2347/// - for more fitting options see TBinomialEfficiencyFitter::Fit
2348
2350{
2351 TString option = opt;
2352 option.ToLower();
2353
2354 //replace existing functions in list with same name
2355 Bool_t bDeleteOld = true;
2356 if(option.Contains("+")) {
2357 option.ReplaceAll("+","");
2358 bDeleteOld = false;
2359 }
2360
2362
2363 TFitResultPtr result = Fitter.Fit(f1,option.Data());
2364
2365 //create copy which is appended to the list
2366 TF1* pFunc = new TF1(*f1);
2367
2368 if(bDeleteOld) {
2369 TIter next(fFunctions);
2370 TObject* obj = 0;
2371 while((obj = next())) {
2372 if(obj->InheritsFrom(TF1::Class())) {
2373 fFunctions->Remove(obj);
2374 delete obj;
2375 }
2376 }
2377 }
2378
2379 // create list if necessary
2380 if(!fFunctions)
2381 fFunctions = new TList();
2382
2383 fFunctions->Add(pFunc);
2384
2385 return result;
2386}
2387
2388////////////////////////////////////////////////////////////////////////////////
2389/// Returns a cloned version of fPassedHistogram
2390///
2391/// Notes:
2392/// - The histogram is filled with unit weights. You might want to scale
2393/// it with the global weight GetWeight().
2394/// - The returned object is owned by the user who has to care about the
2395/// deletion of the new TH1 object.
2396/// - This histogram is by default NOT attached to the current directory
2397/// to avoid duplication of data. If you want to store it automatically
2398/// during the next TFile::Write() command, you have to attach it to
2399/// the corresponding directory.
2400///
2401/// ~~~~~~~{.cpp}
2402/// TFile* pFile = new TFile("passed.root","update");
2403/// TEfficiency* pEff = (TEfficiency*)gDirectory->Get("my_eff");
2404/// TH1* copy = pEff->GetCopyPassedHisto();
2405/// copy->SetDirectory(gDirectory);
2406/// pFile->Write();
2407/// ~~~~~~~
2408
2410{
2411 // do not add cloned histogram to gDirectory
2412 TDirectory::TContext ctx(nullptr);
2413 TH1* tmp = (TH1*)(fPassedHistogram->Clone());
2414
2415 return tmp;
2416}
2417
2418////////////////////////////////////////////////////////////////////////////////
2419/// Returns a cloned version of fTotalHistogram
2420///
2421/// Notes:
2422/// - The histogram is filled with unit weights. You might want to scale
2423/// it with the global weight GetWeight().
2424/// - The returned object is owned by the user who has to care about the
2425/// deletion of the new TH1 object.
2426/// - This histogram is by default NOT attached to the current directory
2427/// to avoid duplication of data. If you want to store it automatically
2428/// during the next TFile::Write() command, you have to attach it to
2429/// the corresponding directory.
2430///
2431/// ~~~~~~~{.cpp}
2432/// TFile* pFile = new TFile("total.root","update");
2433/// TEfficiency* pEff = (TEfficiency*)gDirectory->Get("my_eff");
2434/// TH1* copy = pEff->GetCopyTotalHisto();
2435/// copy->SetDirectory(gDirectory);
2436/// pFile->Write();
2437/// ~~~~~~~
2438
2440{
2441 // do not add cloned histogram to gDirectory
2442 TDirectory::TContext ctx(nullptr);
2443 TH1* tmp = (TH1*)(fTotalHistogram->Clone());
2444
2445 return tmp;
2446}
2447
2448////////////////////////////////////////////////////////////////////////////////
2449///returns the dimension of the current TEfficiency object
2450
2452{
2453 return fTotalHistogram->GetDimension();
2454}
2455
2456////////////////////////////////////////////////////////////////////////////////
2457/// Returns the efficiency in the given global bin
2458///
2459/// Note:
2460/// - The estimated efficiency depends on the chosen statistic option:
2461/// for frequentist ones:
2462/// \f$ \hat{\varepsilon} = \frac{passed}{total} \f$
2463/// for bayesian ones the expectation value of the resulting posterior
2464/// distribution is returned:
2465/// \f$ \hat{\varepsilon} = \frac{passed + \alpha}{total + \alpha + \beta} \f$
2466/// If the bit kPosteriorMode is set (or the method TEfficiency::UsePosteriorMode() has been called ) the
2467/// mode (most probable value) of the posterior is returned:
2468/// \f$ \hat{\varepsilon} = \frac{passed + \alpha -1}{total + \alpha + \beta -2} \f$
2469/// - If the denominator is equal to 0, an efficiency of 0 is returned.
2470/// - When \f$ passed + \alpha < 1 \f$ or \f$ total - passed + \beta < 1 \f$ the above
2471/// formula for the mode is not valid. In these cases values the estimated efficiency is 0 or 1.
2472
2474{
2477
2478 if(TestBit(kIsBayesian)) {
2479
2480 // parameters for the beta prior distribution
2483
2484 Double_t aa,bb;
2485 if(TestBit(kUseWeights))
2486 {
2488 Double_t tw2 = fTotalHistogram->GetSumw2()->At(bin);
2490
2491 if (tw2 <= 0 ) return pw/tw;
2492
2493 // tw/tw2 renormalize the weights
2494 double norm = tw/tw2;
2495 aa = pw * norm + alpha;
2496 bb = (tw - pw) * norm + beta;
2497 }
2498 else
2499 {
2500 aa = passed + alpha;
2501 bb = total - passed + beta;
2502 }
2503
2504 if (!TestBit(kPosteriorMode) )
2505 return BetaMean(aa,bb);
2506 else
2507 return BetaMode(aa,bb);
2508
2509 }
2510 else
2511 return (total)? ((Double_t)passed)/total : 0;
2512}
2513
2514////////////////////////////////////////////////////////////////////////////////
2515/// Returns the lower error on the efficiency in the given global bin
2516///
2517/// The result depends on the current confidence level fConfLevel and the
2518/// chosen statistic option fStatisticOption. See SetStatisticOption(Int_t) for
2519/// more details.
2520///
2521/// Note: If the histograms are filled with weights, only bayesian methods and the
2522/// normal approximation are supported.
2523
2525{
2528
2529 Double_t eff = GetEfficiency(bin);
2530
2531 // check whether weights have been used
2532 if(TestBit(kUseWeights))
2533 {
2535 Double_t tw2 = fTotalHistogram->GetSumw2()->At(bin);
2537 Double_t pw2 = fPassedHistogram->GetSumw2()->At(bin);
2538
2539 if(TestBit(kIsBayesian))
2540 {
2543
2544 if (tw2 <= 0) return 0;
2545
2546 // tw/tw2 renormalize the weights
2547 Double_t norm = tw/tw2;
2548 Double_t aa = pw * norm + alpha;
2549 Double_t bb = (tw - pw) * norm + beta;
2550 Double_t low = 0;
2551 Double_t upper = 1;
2554 }
2555 else {
2557 }
2558
2559 return eff - low;
2560 }
2561 else
2562 {
2564 {
2565 Warning("GetEfficiencyErrorLow","frequentist confidence intervals for weights are only supported by the normal approximation");
2566 Info("GetEfficiencyErrorLow","setting statistic option to kFNormal");
2567 const_cast<TEfficiency*>(this)->SetStatisticOption(kFNormal);
2568 }
2569
2570 Double_t variance = ( pw2 * (1. - 2 * eff) + tw2 * eff *eff ) / ( tw * tw) ;
2571 Double_t sigma = sqrt(variance);
2572
2573 Double_t prob = 0.5 * (1.- fConfLevel);
2575
2576 // avoid to return errors which makes eff-err < 0
2577 return (eff - delta < 0) ? eff : delta;
2578 }
2579 }
2580 else
2581 {
2582 if(TestBit(kIsBayesian))
2583 {
2584 // parameters for the beta prior distribution
2587 return (eff - Bayesian(total,passed,fConfLevel,alpha,beta,false,TestBit(kShortestInterval)));
2588 }
2589 else
2590 return (eff - fBoundary(total,passed,fConfLevel,false));
2591 }
2592}
2593
2594////////////////////////////////////////////////////////////////////////////////
2595/// Returns the upper error on the efficiency in the given global bin
2596///
2597/// The result depends on the current confidence level fConfLevel and the
2598/// chosen statistic option fStatisticOption. See SetStatisticOption(Int_t) for
2599/// more details.
2600///
2601/// Note: If the histograms are filled with weights, only bayesian methods and the
2602/// normal approximation are supported.
2603
2605{
2608
2609 Double_t eff = GetEfficiency(bin);
2610
2611 // check whether weights have been used
2612 if(TestBit(kUseWeights))
2613 {
2615 Double_t tw2 = fTotalHistogram->GetSumw2()->At(bin);
2617 Double_t pw2 = fPassedHistogram->GetSumw2()->At(bin);
2618
2619 if(TestBit(kIsBayesian))
2620 {
2623
2624 if (tw2 <= 0) return 0;
2625
2626 // tw/tw2 renormalize the weights
2627 Double_t norm = tw/tw2;
2628 Double_t aa = pw * norm + alpha;
2629 Double_t bb = (tw - pw) * norm + beta;
2630 Double_t low = 0;
2631 Double_t upper = 1;
2634 }
2635 else {
2636 upper = TEfficiency::BetaCentralInterval(fConfLevel,aa,bb,true);
2637 }
2638
2639 return upper - eff;
2640 }
2641 else
2642 {
2644 {
2645 Warning("GetEfficiencyErrorUp","frequentist confidence intervals for weights are only supported by the normal approximation");
2646 Info("GetEfficiencyErrorUp","setting statistic option to kFNormal");
2647 const_cast<TEfficiency*>(this)->SetStatisticOption(kFNormal);
2648 }
2649
2650 Double_t variance = ( pw2 * (1. - 2 * eff) + tw2 * eff *eff ) / ( tw * tw) ;
2651 Double_t sigma = sqrt(variance);
2652
2653 Double_t prob = 0.5 * (1.- fConfLevel);
2655
2656 return (eff + delta > 1) ? 1.-eff : delta;
2657 }
2658 }
2659 else
2660 {
2661 if(TestBit(kIsBayesian))
2662 {
2663 // parameters for the beta prior distribution
2666 return (Bayesian(total,passed,fConfLevel,alpha,beta,true,TestBit(kShortestInterval)) - eff);
2667 }
2668 else
2669 return fBoundary(total,passed,fConfLevel,true) - eff;
2670 }
2671}
2672
2673////////////////////////////////////////////////////////////////////////////////
2674/// Returns the global bin number which can be used as argument for the
2675/// following functions:
2676///
2677/// - GetEfficiency(bin), GetEfficiencyErrorLow(bin), GetEfficiencyErrorUp(bin)
2678/// - SetPassedEvents(bin), SetTotalEvents(bin)
2679///
2680/// see TH1::GetBin() for conventions on numbering bins
2681
2683{
2684 return fTotalHistogram->GetBin(binx,biny,binz);
2685}
2686
2687////////////////////////////////////////////////////////////////////////////////
2688
2690{
2691 return (fFunctions) ? fFunctions : fFunctions = new TList();
2692}
2693
2694////////////////////////////////////////////////////////////////////////////////
2695/// Merges the TEfficiency objects in the given list to the given
2696/// TEfficiency object using the operator+=(TEfficiency&)
2697///
2698/// The merged result is stored in the current object. The statistic options and
2699/// the confidence level are taken from the current object.
2700///
2701/// This function should be used when all TEfficiency objects correspond to
2702/// the same process.
2703///
2704/// The new weight is set according to:
2705/// \f$ \frac{1}{w_{new}} = \sum_{i} \frac{1}{w_{i}} \f$
2706
2708{
2709 if(!pList->IsEmpty()) {
2710 TIter next(pList);
2711 TObject* obj = 0;
2712 TEfficiency* pEff = 0;
2713 while((obj = next())) {
2714 pEff = dynamic_cast<TEfficiency*>(obj);
2715 if(pEff) {
2716 *this += *pEff;
2717 }
2718 }
2719 }
2721}
2722
2723////////////////////////////////////////////////////////////////////////////////
2724/**
2725Returns the confidence limits for the efficiency supposing that the
2726efficiency follows a normal distribution with the rms below
2727
2728\param[in] total number of total events
2729\param[in] passed 0 <= number of passed events <= total
2730\param[in] level confidence level
2731\param[in] bUpper
2732 - true - upper boundary is returned
2733 - false - lower boundary is returned
2734
2735Calculation:
2736
2737\f{eqnarray*}{
2738 \hat{\varepsilon} &=& \frac{passed}{total}\\
2739 \sigma_{\varepsilon} &=& \sqrt{\frac{\hat{\varepsilon} (1 - \hat{\varepsilon})}{total}}\\
2740 \varepsilon_{low} &=& \hat{\varepsilon} \pm \Phi^{-1}(\frac{level}{2},\sigma_{\varepsilon})
2741\f}
2742*/
2743
2745{
2746 Double_t alpha = (1.0 - level)/2;
2747 if (total == 0) return (bUpper) ? 1 : 0;
2748 Double_t average = passed / total;
2749 Double_t sigma = std::sqrt(average * (1 - average) / total);
2750 Double_t delta = ROOT::Math::normal_quantile(1 - alpha,sigma);
2751
2752 if(bUpper)
2753 return ((average + delta) > 1) ? 1.0 : (average + delta);
2754 else
2755 return ((average - delta) < 0) ? 0.0 : (average - delta);
2756}
2757
2758////////////////////////////////////////////////////////////////////////////////
2759/// Adds the histograms of another TEfficiency object to current histograms
2760///
2761/// The statistic options and the confidence level remain unchanged.
2762///
2763/// fTotalHistogram += rhs.fTotalHistogram;
2764/// fPassedHistogram += rhs.fPassedHistogram;
2765///
2766/// calculates a new weight:
2767/// current weight of this TEfficiency object = \f$ w_{1} \f$
2768/// weight of rhs = \f$ w_{2} \f$
2769/// \f$ w_{new} = \frac{w_{1} \times w_{2}}{w_{1} + w_{2}} \f$
2770
2772{
2773
2774 if (fTotalHistogram == 0 && fPassedHistogram == 0) {
2775 // efficiency is empty just copy it over
2776 *this = rhs;
2777 return *this;
2778 }
2779 else if (fTotalHistogram == 0 || fPassedHistogram == 0) {
2780 Fatal("operator+=","Adding to a non consistent TEfficiency object which has not a total or a passed histogram ");
2781 return *this;
2782 }
2783
2784 if (rhs.fTotalHistogram == 0 && rhs.fPassedHistogram == 0 ) {
2785 Warning("operator+=","no operation: adding an empty object");
2786 return *this;
2787 }
2788 else if (rhs.fTotalHistogram == 0 || rhs.fPassedHistogram == 0 ) {
2789 Fatal("operator+=","Adding a non consistent TEfficiency object which has not a total or a passed histogram ");
2790 return *this;
2791 }
2792
2795
2798
2799 SetWeight((fWeight * rhs.GetWeight())/(fWeight + rhs.GetWeight()));
2800
2801 return *this;
2802}
2803
2804////////////////////////////////////////////////////////////////////////////////
2805/// Assignment operator
2806///
2807/// The histograms, statistic option, confidence level, weight and paint styles
2808/// of rhs are copied to the this TEfficiency object.
2809///
2810/// Note: - The list of associated functions is not copied. After this
2811/// operation the list of associated functions is empty.
2812
2814{
2815 if(this != &rhs)
2816 {
2817 //statistic options
2821 SetBetaBeta(rhs.GetBetaBeta());
2822 SetWeight(rhs.GetWeight());
2823
2824 //associated list of functions
2825 if(fFunctions)
2826 fFunctions->Delete();
2827
2828 //copy histograms
2829 delete fTotalHistogram;
2830 delete fPassedHistogram;
2831
2832 // do not add cloned histogram to gDirectory
2833 {
2834 TDirectory::TContext ctx(nullptr);
2837 }
2838 //delete temporary paint objects
2839 delete fPaintHisto;
2840 delete fPaintGraph;
2841 fPaintHisto = 0;
2842 fPaintGraph = 0;
2843
2844 //copy style
2845 rhs.TAttLine::Copy(*this);
2846 rhs.TAttFill::Copy(*this);
2847 rhs.TAttMarker::Copy(*this);
2848 }
2849
2850 return *this;
2851}
2852
2853////////////////////////////////////////////////////////////////////////////////
2854/// Paints this TEfficiency object
2855///
2856/// For details on the possible option see Draw(Option_t*)
2857///
2858/// Note for 1D classes
2859/// In 1D the TEfficiency uses a TGraphAsymmErrors for drawing
2860/// The TGraph is created only the first time Paint is used. The user can manipulate the
2861/// TGraph via the method TEfficiency::GetPaintedGraph()
2862/// The TGraph creates behing an histogram for the axis. The histogram is created also only the first time.
2863/// If the axis needs to be updated because in the meantime the class changed use this trick
2864/// which will trigger a re-calculation of the axis of the graph
2865/// TEfficiency::GetPaintedGraph()->Set(0)
2866///
2867/// Note that in order to access the painted graph via GetPaintedGraph() you need either to call Paint or better
2868/// gPad->Update();
2869///
2870
2872{
2873
2874
2875 if(!gPad)
2876 return;
2877
2878
2879 //use TGraphAsymmErrors for painting
2880 if(GetDimension() == 1) {
2881 if(!fPaintGraph) {
2882 fPaintGraph = CreateGraph(opt);
2883 }
2884 else
2885 // update existing graph already created
2886 FillGraph(fPaintGraph, opt);
2887
2888 //paint graph
2889
2890 fPaintGraph->Paint(opt);
2891
2892 //paint all associated functions
2893 if(fFunctions) {
2894 //paint box with fit parameters
2895 //the fit statistics will be painted if gStyle->SetOptFit(1) has been
2896 // called by the user
2897 TIter next(fFunctions);
2898 TObject* obj = 0;
2899 while((obj = next())) {
2900 if(obj->InheritsFrom(TF1::Class())) {
2901 fPaintGraph->PaintStats((TF1*)obj);
2902 ((TF1*)obj)->Paint("sameC");
2903 }
2904 }
2905 }
2906
2907 return;
2908 }
2909
2910 //use TH2 for painting
2911 if(GetDimension() == 2) {
2912 if(!fPaintHisto) {
2914 }
2915 else
2917
2918 //paint histogram
2919 fPaintHisto->Paint(opt);
2920 return;
2921 }
2922 Warning("Paint","Painting 3D efficiency is not implemented");
2923}
2924
2925////////////////////////////////////////////////////////////////////////////////
2926/// Have histograms fixed bins along each axis?
2927
2928void TEfficiency::SavePrimitive(std::ostream& out,Option_t* opt)
2929{
2930 Bool_t equi_bins = true;
2931
2932 //indentation
2933 TString indent = " ";
2934 //names for arrays containing the bin edges
2935 //static counter needed if more objects are saved
2936 static Int_t naxis = 0;
2937 TString sxaxis="xAxis",syaxis="yAxis",szaxis="zAxis";
2938
2939 //note the missing break statements!
2940 switch(GetDimension()) {
2941 case 3:
2942 equi_bins = equi_bins && !fTotalHistogram->GetZaxis()->GetXbins()->fArray
2944 case 2:
2945 equi_bins = equi_bins && !fTotalHistogram->GetYaxis()->GetXbins()->fArray
2947 case 1:
2948 equi_bins = equi_bins && !fTotalHistogram->GetXaxis()->GetXbins()->fArray
2950 }
2951
2952 //create arrays containing the variable binning
2953 if(!equi_bins) {
2954 Int_t i;
2955 ++naxis;
2956 sxaxis += naxis;
2957 syaxis += naxis;
2958 szaxis += naxis;
2959 //x axis
2960 out << indent << "Double_t " << sxaxis << "["
2961 << fTotalHistogram->GetXaxis()->GetXbins()->fN << "] = {";
2962 for (i = 0; i < fTotalHistogram->GetXaxis()->GetXbins()->fN; ++i) {
2963 if (i != 0) out << ", ";
2964 out << fTotalHistogram->GetXaxis()->GetXbins()->fArray[i];
2965 }
2966 out << "}; " << std::endl;
2967 //y axis
2968 if(GetDimension() > 1) {
2969 out << indent << "Double_t " << syaxis << "["
2970 << fTotalHistogram->GetYaxis()->GetXbins()->fN << "] = {";
2971 for (i = 0; i < fTotalHistogram->GetYaxis()->GetXbins()->fN; ++i) {
2972 if (i != 0) out << ", ";
2973 out << fTotalHistogram->GetYaxis()->GetXbins()->fArray[i];
2974 }
2975 out << "}; " << std::endl;
2976 }
2977 //z axis
2978 if(GetDimension() > 2) {
2979 out << indent << "Double_t " << szaxis << "["
2980 << fTotalHistogram->GetZaxis()->GetXbins()->fN << "] = {";
2981 for (i = 0; i < fTotalHistogram->GetZaxis()->GetXbins()->fN; ++i) {
2982 if (i != 0) out << ", ";
2983 out << fTotalHistogram->GetZaxis()->GetXbins()->fArray[i];
2984 }
2985 out << "}; " << std::endl;
2986 }
2987 }//creating variable binning
2988
2989 //TEfficiency pointer has efficiency name + counter
2990 static Int_t eff_count = 0;
2991 ++eff_count;
2992 TString eff_name = GetName();
2993 eff_name += eff_count;
2994
2995 const char* name = eff_name.Data();
2996
2997 //construct TEfficiency object
2998 const char quote = '"';
2999 out << indent << std::endl;
3000 out << indent << ClassName() << " * " << name << " = new " << ClassName()
3001 << "(" << quote << GetName() << quote << "," << quote
3002 << GetTitle() << quote <<",";
3003 //fixed bin size -> use n,min,max constructor
3004 if(equi_bins) {
3005 out << fTotalHistogram->GetXaxis()->GetNbins() << ","
3006 << fTotalHistogram->GetXaxis()->GetXmin() << ","
3008 if(GetDimension() > 1) {
3009 out << "," << fTotalHistogram->GetYaxis()->GetNbins() << ","
3010 << fTotalHistogram->GetYaxis()->GetXmin() << ","
3012 }
3013 if(GetDimension() > 2) {
3014 out << "," << fTotalHistogram->GetZaxis()->GetNbins() << ","
3015 << fTotalHistogram->GetZaxis()->GetXmin() << ","
3017 }
3018 }
3019 //variable bin size -> use n,*bins constructor
3020 else {
3021 out << fTotalHistogram->GetXaxis()->GetNbins() << "," << sxaxis;
3022 if(GetDimension() > 1)
3023 out << "," << fTotalHistogram->GetYaxis()->GetNbins() << ","
3024 << syaxis;
3025 if(GetDimension() > 2)
3026 out << "," << fTotalHistogram->GetZaxis()->GetNbins() << ","
3027 << szaxis;
3028 }
3029 out << ");" << std::endl;
3030 out << indent << std::endl;
3031
3032 //set statistic options
3033 out << indent << name << "->SetConfidenceLevel(" << fConfLevel << ");"
3034 << std::endl;
3035 out << indent << name << "->SetBetaAlpha(" << fBeta_alpha << ");"
3036 << std::endl;
3037 out << indent << name << "->SetBetaBeta(" << fBeta_beta << ");" << std::endl;
3038 out << indent << name << "->SetWeight(" << fWeight << ");" << std::endl;
3039 out << indent << name << "->SetStatisticOption(" << fStatisticOption << ");"
3040 << std::endl;
3041 out << indent << name << "->SetPosteriorMode(" << TestBit(kPosteriorMode) << ");" << std::endl;
3042 out << indent << name << "->SetShortestInterval(" << TestBit(kShortestInterval) << ");" << std::endl;
3043 if(TestBit(kUseWeights))
3044 out << indent << name << "->SetUseWeightedEvents();" << std::endl;
3045
3046 // save bin-by-bin prior parameters
3047 for(unsigned int i = 0; i < fBeta_bin_params.size(); ++i)
3048 {
3049 out << indent << name << "->SetBetaBinParameters(" << i << "," << fBeta_bin_params.at(i).first
3050 << "," << fBeta_bin_params.at(i).second << ");" << std::endl;
3051 }
3052
3053 //set bin contents
3054 Int_t nbins = fTotalHistogram->GetNbinsX() + 2;
3055 if(GetDimension() > 1)
3056 nbins *= fTotalHistogram->GetNbinsY() + 2;
3057 if(GetDimension() > 2)
3058 nbins *= fTotalHistogram->GetNbinsZ() + 2;
3059
3060 //important: set first total number than passed number
3061 for(Int_t i = 0; i < nbins; ++i) {
3062 out << indent << name <<"->SetTotalEvents(" << i << "," <<
3063 fTotalHistogram->GetBinContent(i) << ");" << std::endl;
3064 out << indent << name <<"->SetPassedEvents(" << i << "," <<
3065 fPassedHistogram->GetBinContent(i) << ");" << std::endl;
3066 }
3067
3068 //save list of functions
3069 TIter next(fFunctions);
3070 TObject* obj = 0;
3071 while((obj = next())) {
3072 obj->SavePrimitive(out,"nodraw");
3073 if(obj->InheritsFrom(TF1::Class())) {
3074 out << indent << name << "->GetListOfFunctions()->Add("
3075 << obj->GetName() << ");" << std::endl;
3076 }
3077 }
3078
3079 //set style
3083
3084 //draw TEfficiency object
3085 TString option = opt;
3086 option.ToLower();
3087 if (!option.Contains("nodraw"))
3088 out<< indent << name<< "->Draw(" << quote << opt << quote << ");"
3089 << std::endl;
3090}
3091
3092////////////////////////////////////////////////////////////////////////////////
3093/// Sets the shape parameter &alpha;
3094///
3095/// The prior probability of the efficiency is given by the beta distribution:
3096/// \f[
3097/// f(\varepsilon;\alpha;\beta) = \frac{1}{B(\alpha,\beta)} \varepsilon^{\alpha-1} (1 - \varepsilon)^{\beta-1}
3098/// \f]
3099///
3100/// Note: - both shape parameters have to be positive (i.e. > 0)
3101
3103{
3104 if(alpha > 0)
3105 fBeta_alpha = alpha;
3106 else
3107 Warning("SetBetaAlpha(Double_t)","invalid shape parameter %.2lf",alpha);
3108}
3109
3110////////////////////////////////////////////////////////////////////////////////
3111/// Sets the shape parameter &beta;
3112///
3113/// The prior probability of the efficiency is given by the beta distribution:
3114/// \f[
3115/// f(\varepsilon;\alpha,\beta) = \frac{1}{B(\alpha,\beta)} \varepsilon^{\alpha-1} (1 - \varepsilon)^{\beta-1}
3116/// \f]
3117///
3118/// Note: - both shape parameters have to be positive (i.e. > 0)
3119
3121{
3122 if(beta > 0)
3123 fBeta_beta = beta;
3124 else
3125 Warning("SetBetaBeta(Double_t)","invalid shape parameter %.2lf",beta);
3126}
3127
3128////////////////////////////////////////////////////////////////////////////////
3129/// Sets different shape parameter &alpha; and &beta;
3130/// for the prior distribution for each bin. By default the global parameter are used if they are not set
3131/// for the specific bin
3132/// The prior probability of the efficiency is given by the beta distribution:
3133/// \f[
3134/// f(\varepsilon;\alpha;\beta) = \frac{1}{B(\alpha,\beta)} \varepsilon^{\alpha-1} (1 - \varepsilon)^{\beta-1}
3135/// \f]
3136///
3137/// Note:
3138/// - both shape parameters have to be positive (i.e. > 0)
3139/// - bin gives the global bin number (cf. GetGlobalBin)
3140
3142{
3143 if (!fPassedHistogram || !fTotalHistogram) return;
3145 // doing this I get h1->fN which is available only for a TH1D
3146 UInt_t n = h1->GetBin(h1->GetNbinsX()+1, h1->GetNbinsY()+1, h1->GetNbinsZ()+1 ) + 1;
3147
3148 // in case vector is not created do with default alpha, beta params
3149 if (fBeta_bin_params.size() != n )
3150 fBeta_bin_params = std::vector<std::pair<Double_t, Double_t> >(n, std::make_pair(fBeta_alpha, fBeta_beta) );
3151
3152 // vector contains also values for under/overflows
3153 fBeta_bin_params[bin] = std::make_pair(alpha,beta);
3154 SetBit(kUseBinPrior,true);
3155
3156}
3157
3158////////////////////////////////////////////////////////////////////////////////
3159/// Set the bins for the underlined passed and total histograms
3160/// If the class have been already filled the previous contents will be lost
3161
3163{
3164 if (GetDimension() != 1) {
3165 Error("SetBins","Using wrong SetBins function for a %d-d histogram",GetDimension());
3166 return kFALSE;
3167 }
3168 if (fTotalHistogram->GetEntries() != 0 ) {
3169 Warning("SetBins","Histogram entries will be lost after SetBins");
3172 }
3175 return kTRUE;
3176}
3177
3178////////////////////////////////////////////////////////////////////////////////
3179/// Set the bins for the underlined passed and total histograms
3180/// If the class have been already filled the previous contents will be lost
3181
3183{
3184 if (GetDimension() != 1) {
3185 Error("SetBins","Using wrong SetBins function for a %d-d histogram",GetDimension());
3186 return kFALSE;
3187 }
3188 if (fTotalHistogram->GetEntries() != 0 ) {
3189 Warning("SetBins","Histogram entries will be lost after SetBins");
3192 }
3193 fPassedHistogram->SetBins(nx,xBins);
3194 fTotalHistogram->SetBins(nx,xBins);
3195 return kTRUE;
3196}
3197
3198////////////////////////////////////////////////////////////////////////////////
3199/// Set the bins for the underlined passed and total histograms
3200/// If the class have been already filled the previous contents will be lost
3201
3203{
3204 if (GetDimension() != 2) {
3205 Error("SetBins","Using wrong SetBins function for a %d-d histogram",GetDimension());
3206 return kFALSE;
3207 }
3208 if (fTotalHistogram->GetEntries() != 0 ) {
3209 Warning("SetBins","Histogram entries will be lost after SetBins");
3212 }
3215 return kTRUE;
3216}
3217
3218////////////////////////////////////////////////////////////////////////////////
3219/// Set the bins for the underlined passed and total histograms
3220/// If the class have been already filled the previous contents will be lost
3221
3222Bool_t TEfficiency::SetBins(Int_t nx, const Double_t *xBins, Int_t ny, const Double_t *yBins)
3223{
3224 if (GetDimension() != 2) {
3225 Error("SetBins","Using wrong SetBins function for a %d-d histogram",GetDimension());
3226 return kFALSE;
3227 }
3228 if (fTotalHistogram->GetEntries() != 0 ) {
3229 Warning("SetBins","Histogram entries will be lost after SetBins");
3232 }
3233 fPassedHistogram->SetBins(nx,xBins,ny,yBins);
3234 fTotalHistogram->SetBins(nx,xBins,ny,yBins);
3235 return kTRUE;
3236}
3237
3238////////////////////////////////////////////////////////////////////////////////
3239/// Set the bins for the underlined passed and total histograms
3240/// If the class have been already filled the previous contents will be lost
3241
3243 Int_t nz, Double_t zmin, Double_t zmax)
3244{
3245 if (GetDimension() != 3) {
3246 Error("SetBins","Using wrong SetBins function for a %d-d histogram",GetDimension());
3247 return kFALSE;
3248 }
3249 if (fTotalHistogram->GetEntries() != 0 ) {
3250 Warning("SetBins","Histogram entries will be lost after SetBins");
3253 }
3254 fPassedHistogram->SetBins(nx,xmin,xmax,ny,ymin,ymax,nz,zmin,zmax);
3255 fTotalHistogram->SetBins (nx,xmin,xmax,ny,ymin,ymax,nz,zmin,zmax);
3256 return kTRUE;
3257}
3258
3259////////////////////////////////////////////////////////////////////////////////
3260/// Set the bins for the underlined passed and total histograms
3261/// If the class have been already filled the previous contents will be lost
3262
3263Bool_t TEfficiency::SetBins(Int_t nx, const Double_t *xBins, Int_t ny, const Double_t *yBins, Int_t nz,
3264 const Double_t *zBins )
3265{
3266 if (GetDimension() != 3) {
3267 Error("SetBins","Using wrong SetBins function for a %d-d histogram",GetDimension());
3268 return kFALSE;
3269 }
3270 if (fTotalHistogram->GetEntries() != 0 ) {
3271 Warning("SetBins","Histogram entries will be lost after SetBins");
3274 }
3275 fPassedHistogram->SetBins(nx,xBins,ny,yBins,nz,zBins);
3276 fTotalHistogram->SetBins(nx,xBins,ny,yBins,nz,zBins);
3277 return kTRUE;
3278}
3279
3280////////////////////////////////////////////////////////////////////////////////
3281/// Sets the confidence level (0 < level < 1)
3282/// The default value is 1-sigma :~ 0.683
3283
3285{
3286 if((level > 0) && (level < 1))
3287 fConfLevel = level;
3288 else
3289 Warning("SetConfidenceLevel(Double_t)","invalid confidence level %.2lf",level);
3290}
3291
3292////////////////////////////////////////////////////////////////////////////////
3293/// Sets the directory holding this TEfficiency object
3294///
3295/// A reference to this TEfficiency object is removed from the current
3296/// directory (if it exists) and a new reference to this TEfficiency object is
3297/// added to the given directory.
3298///
3299/// Notes: - If the given directory is 0, the TEfficiency object does not
3300/// belong to any directory and will not be written to file during the
3301/// next TFile::Write() command.
3302
3304{
3305 if(fDirectory == dir)
3306 return;
3307 if(fDirectory)
3308 fDirectory->Remove(this);
3309 fDirectory = dir;
3310 if(fDirectory)
3311 fDirectory->Append(this);
3312}
3313
3314////////////////////////////////////////////////////////////////////////////////
3315/// Sets the name
3316///
3317/// Note: The names of the internal histograms are set to "name + _total" and
3318/// "name + _passed" respectively.
3319
3321{
3323
3324 //setting the names (appending the correct ending)
3325 TString name_total = name + TString("_total");
3326 TString name_passed = name + TString("_passed");
3327 fTotalHistogram->SetName(name_total);
3328 fPassedHistogram->SetName(name_passed);
3329}
3330
3331////////////////////////////////////////////////////////////////////////////////
3332/// Sets the number of passed events in the given global bin
3333///
3334/// returns "true" if the number of passed events has been updated
3335/// otherwise "false" ist returned
3336///
3337/// Note: - requires: 0 <= events <= fTotalHistogram->GetBinContent(bin)
3338
3340{
3341 if(events <= fTotalHistogram->GetBinContent(bin)) {
3342 fPassedHistogram->SetBinContent(bin,events);
3343 return true;
3344 }
3345 else {
3346 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);
3347 return false;
3348 }
3349}
3350
3351////////////////////////////////////////////////////////////////////////////////
3352/// Sets the histogram containing the passed events
3353///
3354/// The given histogram is cloned and stored internally as histogram containing
3355/// the passed events. The given histogram has to be consistent with the current
3356/// fTotalHistogram (see CheckConsistency(const TH1&,const TH1&)).
3357/// The method returns whether the fPassedHistogram has been replaced (true) or
3358/// not (false).
3359///
3360/// Note: The list of associated functions fFunctions is cleared.
3361///
3362/// Option:
3363/// - "f": force the replacement without checking the consistency
3364/// This can lead to inconsistent histograms and useless results
3365/// or unexpected behaviour. But sometimes it might be the only
3366/// way to change the histograms. If you use this option, you
3367/// should ensure that the fTotalHistogram is replaced by a
3368/// consistent one (with respect to rPassed) as well.
3369
3371{
3372 TString option = opt;
3373 option.ToLower();
3374
3375 Bool_t bReplace = option.Contains("f");
3376
3377 if(!bReplace)
3378 bReplace = CheckConsistency(rPassed,*fTotalHistogram);
3379
3380 if(bReplace) {
3381 delete fPassedHistogram;
3382 // do not add cloned histogram to gDirectory
3383 {
3384 TDirectory::TContext ctx(nullptr);
3385 fPassedHistogram = (TH1*)(rPassed.Clone());
3387 }
3388
3389 if(fFunctions)
3390 fFunctions->Delete();
3391
3392 //check whether both histograms are filled with weights
3393 bool useWeights = CheckWeights(rPassed,*fTotalHistogram);
3394
3395 SetUseWeightedEvents(useWeights);
3396
3397 return true;
3398 }
3399 else
3400 return false;
3401}
3402
3403////////////////////////////////////////////////////////////////////////////////
3404/// Sets the statistic option which affects the calculation of the confidence interval
3405///
3406/// Options:
3407/// - kFCP (=0)(default): using the Clopper-Pearson interval (recommended by PDG)
3408/// sets kIsBayesian = false
3409/// see also ClopperPearson
3410/// - kFNormal (=1) : using the normal approximation
3411/// sets kIsBayesian = false
3412/// see also Normal
3413/// - kFWilson (=2) : using the Wilson interval
3414/// sets kIsBayesian = false
3415/// see also Wilson
3416/// - kFAC (=3) : using the Agresti-Coull interval
3417/// sets kIsBayesian = false
3418/// see also AgrestiCoull
3419/// - kFFC (=4) : using the Feldman-Cousins frequentist method
3420/// sets kIsBayesian = false
3421/// see also FeldmanCousins
3422/// - kBJeffrey (=5) : using the Jeffrey interval
3423/// sets kIsBayesian = true, fBeta_alpha = 0.5 and fBeta_beta = 0.5
3424/// see also Bayesian
3425/// - kBUniform (=6) : using a uniform prior
3426/// sets kIsBayesian = true, fBeta_alpha = 1 and fBeta_beta = 1
3427/// see also Bayesian
3428/// - kBBayesian (=7) : using a custom prior defined by fBeta_alpha and fBeta_beta
3429/// sets kIsBayesian = true
3430/// see also Bayesian
3431/// - kMidP (=8) : using the Lancaster Mid-P method
3432/// sets kIsBayesian = false
3433
3434
3436{
3437 fStatisticOption = option;
3438
3439 switch(option)
3440 {
3441 case kFCP:
3443 SetBit(kIsBayesian,false);
3444 break;
3445 case kFNormal:
3446 fBoundary = &Normal;
3447 SetBit(kIsBayesian,false);
3448 break;
3449 case kFWilson:
3450 fBoundary = &Wilson;
3451 SetBit(kIsBayesian,false);
3452 break;
3453 case kFAC:
3455 SetBit(kIsBayesian,false);
3456 break;
3457 case kFFC:
3459 SetBit(kIsBayesian,false);
3460 break;
3461 case kMidP:
3463 SetBit(kIsBayesian,false);
3464 break;
3465 case kBJeffrey:
3466 fBeta_alpha = 0.5;
3467 fBeta_beta = 0.5;
3468 SetBit(kIsBayesian,true);
3469 SetBit(kUseBinPrior,false);
3470 break;
3471 case kBUniform:
3472 fBeta_alpha = 1;
3473 fBeta_beta = 1;
3474 SetBit(kIsBayesian,true);
3475 SetBit(kUseBinPrior,false);
3476 break;
3477 case kBBayesian:
3478 SetBit(kIsBayesian,true);
3479 break;
3480 default:
3483 SetBit(kIsBayesian,false);
3484 }
3485}
3486
3487////////////////////////////////////////////////////////////////////////////////
3488/// Sets the title
3489///
3490/// Notes:
3491/// - The titles of the internal histograms are set to "title + (total)"
3492/// or "title + (passed)" respectively.
3493/// - It is possible to label the axis of the histograms as usual (see
3494/// TH1::SetTitle).
3495///
3496/// Example: Setting the title to "My Efficiency" and label the axis
3497/// pEff->SetTitle("My Efficiency;x label;eff");
3498
3499void TEfficiency::SetTitle(const char* title)
3500{
3501
3502 //setting the titles (looking for the first semicolon and insert the tokens there)
3503 TString title_passed = title;
3504 TString title_total = title;
3505 Ssiz_t pos = title_passed.First(";");
3506 if (pos != kNPOS) {
3507 title_passed.Insert(pos," (passed)");
3508 title_total.Insert(pos," (total)");
3509 }
3510 else {
3511 title_passed.Append(" (passed)");
3512 title_total.Append(" (total)");
3513 }
3514 fPassedHistogram->SetTitle(title_passed);
3515 fTotalHistogram->SetTitle(title_total);
3516
3517 // strip (total) for the TEfficiency title
3518 // HIstogram SetTitle has already stripped the axis
3519 TString teffTitle = fTotalHistogram->GetTitle();
3520 teffTitle.ReplaceAll(" (total)","");
3521 TNamed::SetTitle(teffTitle);
3522
3523}
3524
3525////////////////////////////////////////////////////////////////////////////////
3526/// Sets the number of total events in the given global bin
3527///
3528/// returns "true" if the number of total events has been updated
3529/// otherwise "false" ist returned
3530///
3531/// Note: - requires: fPassedHistogram->GetBinContent(bin) <= events
3532
3534{
3535 if(events >= fPassedHistogram->GetBinContent(bin)) {
3536 fTotalHistogram->SetBinContent(bin,events);
3537 return true;
3538 }
3539 else {
3540 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);
3541 return false;
3542 }
3543}
3544
3545////////////////////////////////////////////////////////////////////////////////
3546/// Sets the histogram containing all events
3547///
3548/// The given histogram is cloned and stored internally as histogram containing
3549/// all events. The given histogram has to be consistent with the current
3550/// fPassedHistogram (see CheckConsistency(const TH1&,const TH1&)).
3551/// The method returns whether the fTotalHistogram has been replaced (true) or
3552/// not (false).
3553///
3554/// Note: The list of associated functions fFunctions is cleared.
3555///
3556/// Option:
3557/// - "f": force the replacement without checking the consistency
3558/// This can lead to inconsistent histograms and useless results
3559/// or unexpected behaviour. But sometimes it might be the only
3560/// way to change the histograms. If you use this option, you
3561/// should ensure that the fPassedHistogram is replaced by a
3562/// consistent one (with respect to rTotal) as well.
3563
3565{
3566 TString option = opt;
3567 option.ToLower();
3568
3569 Bool_t bReplace = option.Contains("f");
3570
3571 if(!bReplace)
3572 bReplace = CheckConsistency(*fPassedHistogram,rTotal);
3573
3574 if(bReplace) {
3575 delete fTotalHistogram;
3576 // do not add cloned histogram to gDirectory
3577 {
3578 TDirectory::TContext ctx(nullptr);
3579 fTotalHistogram = (TH1*)(rTotal.Clone());
3580 }
3582
3583 if(fFunctions)
3584 fFunctions->Delete();
3585
3586 //check whether both histograms are filled with weights
3587 bool useWeights = CheckWeights(*fPassedHistogram,rTotal);
3588 SetUseWeightedEvents(useWeights);
3589
3590 return true;
3591 }
3592 else
3593 return false;
3594}
3595
3596////////////////////////////////////////////////////////////////////////////////
3597
3599{
3600 if (on && !TestBit(kUseWeights) )
3601 gROOT->Info("TEfficiency::SetUseWeightedEvents","Handle weighted events for computing efficiency");
3602
3603 SetBit(kUseWeights,on);
3604
3609}
3610
3611////////////////////////////////////////////////////////////////////////////////
3612/// Sets the global weight for this TEfficiency object
3613///
3614/// Note: - weight has to be positive ( > 0)
3615
3617{
3618 if(weight > 0)
3619 fWeight = weight;
3620 else
3621 Warning("SetWeight","invalid weight %.2lf",weight);
3622}
3623
3624////////////////////////////////////////////////////////////////////////////////
3625/**
3626Calculates the boundaries for the frequentist Wilson interval
3627
3628\param[in] total number of total events
3629\param[in] passed 0 <= number of passed events <= total
3630\param[in] level confidence level
3631\param[in] bUpper
3632 - true - upper boundary is returned
3633 - false - lower boundary is returned
3634
3635Calculation:
3636\f{eqnarray*}{
3637 \alpha &=& 1 - \frac{level}{2}\\
3638 \kappa &=& \Phi^{-1}(1 - \alpha,1) ...\ normal\ quantile\ function\\
3639 mode &=& \frac{passed + \frac{\kappa^{2}}{2}}{total + \kappa^{2}}\\
3640 \Delta &=& \frac{\kappa}{total + \kappa^{2}} * \sqrt{passed (1 - \frac{passed}{total}) + \frac{\kappa^{2}}{4}}\\
3641 return &=& max(0,mode - \Delta)\ or\ min(1,mode + \Delta)
3642\f}
3643
3644*/
3645
3647{
3648 Double_t alpha = (1.0 - level)/2;
3649 if (total == 0) return (bUpper) ? 1 : 0;
3650 Double_t average = ((Double_t)passed) / total;
3651 Double_t kappa = ROOT::Math::normal_quantile(1 - alpha,1);
3652
3653 Double_t mode = (passed + 0.5 * kappa * kappa) / (total + kappa * kappa);
3654 Double_t delta = kappa / (total + kappa*kappa) * std::sqrt(total * average
3655 * (1 - average) + kappa * kappa / 4);
3656 if(bUpper)
3657 return ((mode + delta) > 1) ? 1.0 : (mode + delta);
3658 else
3659 return ((mode - delta) < 0) ? 0.0 : (mode - delta);
3660}
3661
3662////////////////////////////////////////////////////////////////////////////////
3663/// Addition operator
3664///
3665/// adds the corresponding histograms:
3666/// ~~~ {.cpp}
3667/// lhs.GetTotalHistogram() + rhs.GetTotalHistogram()
3668/// lhs.GetPassedHistogram() + rhs.GetPassedHistogram()
3669/// ~~~
3670/// the statistic option and the confidence level are taken from lhs
3671
3672const TEfficiency operator+(const TEfficiency& lhs,const TEfficiency& rhs)
3673{
3674 TEfficiency tmp(lhs);
3675 tmp += rhs;
3676 return tmp;
3677}
3678
3679#endif
double
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
const Ssiz_t kNPOS
Definition RtypesCore.h:115
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:92
double Double_t
Definition RtypesCore.h:59
long long Long64_t
Definition RtypesCore.h:73
const Bool_t kTRUE
Definition RtypesCore.h:91
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
static void indent(ostringstream &buf, int indent_level)
#define gDirectory
Definition TDirectory.h:290
const TEfficiency operator+(const TEfficiency &lhs, const TEfficiency &rhs)
Addition operator.
const Double_t kDefBetaAlpha
const Double_t kDefWeight
const Double_t kDefBetaBeta
const TEfficiency::EStatOption kDefStatOpt
const Double_t kDefConfLevel
static unsigned int total
char name[80]
Definition TGX11.cxx:110
float xmin
float ymin
float xmax
float ymax
double sqrt(double)
#define gROOT
Definition TROOT.h:406
#define gPad
static struct mg_connection * fc(struct mg_context *ctx)
Definition civetweb.c:3728
void Init(double alpha)
User class for performing function minimization.
virtual bool Minimize(int maxIter, double absTol=1.E-8, double relTol=1.E-10)
Find minimum position iterating until convergence specified by the absolute and relative tolerance or...
virtual double XMinimum() const
Return current estimate of the position of the minimum.
void SetFunction(const ROOT::Math::IGenFunction &f, double xlow, double xup)
Sets function to be minimized.
void SetNpx(int npx)
Set the number of point used to bracket root using a grid.
virtual double FValMinimum() const
Return function value at current estimate of the minimum.
Template class to wrap any C++ callable object which takes one argument i.e.
Double_t At(Int_t i) const
Definition TArrayD.h:79
Double_t * fArray
Definition TArrayD.h:30
const Double_t * GetArray() const
Definition TArrayD.h:43
Int_t fN
Definition TArray.h:38
Fill Area Attributes class.
Definition TAttFill.h:19
void Copy(TAttFill &attfill) const
Copy this fill attributes to a new TAttFill.
Definition TAttFill.cxx:202
virtual void SaveFillAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1001)
Save fill attributes as C++ statement(s) on output stream out.
Definition TAttFill.cxx:234
Line Attributes class.
Definition TAttLine.h:18
void Copy(TAttLine &attline) const
Copy this line attributes to a new TAttLine.
Definition TAttLine.cxx:172
virtual void SaveLineAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t widdef=1)
Save line attributes as C++ statement(s) on output stream out.
Definition TAttLine.cxx:270
Marker Attributes class.
Definition TAttMarker.h:19
virtual void SaveMarkerAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t sizdef=1)
Save line attributes as C++ statement(s) on output stream out.
void Copy(TAttMarker &attmarker) const
Copy this marker attributes to a new TAttMarker.
Class to manage histogram axis.
Definition TAxis.h:30
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition TAxis.cxx:823
Bool_t IsVariableBinSize() const
Definition TAxis.h:136
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:478
const TArrayD * GetXbins() const
Definition TAxis.h:130
Double_t GetXmax() const
Definition TAxis.h:134
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:440
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:518
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:419
Double_t GetXmin() const
Definition TAxis.h:133
Int_t GetNbins() const
Definition TAxis.h:121
const char * GetTitle() const
Returns title of object.
Definition TAxis.h:129
THashList * GetLabels() const
Definition TAxis.h:117
Binomial fitter for the division of two histograms.
TFitResultPtr Fit(TF1 *f1, Option_t *option="")
Carry out the fit of the given function to the given histograms.
Collection abstract base class.
Definition TCollection.h:63
virtual Bool_t IsEmpty() const
Small helper to keep current directory context.
Definition TDirectory.h:52
Describe directory structure in memory.
Definition TDirectory.h:45
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Class to handle efficiency histograms.
Definition TEfficiency.h:28
static Bool_t FeldmanCousinsInterval(Double_t total, Double_t passed, Double_t level, Double_t &lower, Double_t &upper)
Calculates the interval boundaries using the frequentist methods of Feldman-Cousins.
static Double_t BetaMode(Double_t alpha, Double_t beta)
Compute the mode of the beta distribution.
Bool_t SetPassedEvents(Int_t bin, Int_t events)
Sets the number of passed events in the given global bin.
TH2 * CreateHistogram(Option_t *opt="") const
Create the histogram used to be painted (for dim=2 TEfficiency) The return object is managed by the c...
static Bool_t BetaShortestInterval(Double_t level, Double_t alpha, Double_t beta, Double_t &lower, Double_t &upper)
Calculates the boundaries for a shortest confidence interval for a Beta distribution.
static Bool_t CheckWeights(const TH1 &pass, const TH1 &total)
Check if both histogram are weighted.
static Double_t BetaMean(Double_t alpha, Double_t beta)
Compute the mean (average) of the beta distribution.
TEfficiency()
default constructor
Double_t GetBetaAlpha(Int_t bin=-1) const
void FillWeighted(Bool_t bPassed, Double_t weight, Double_t x, Double_t y=0, Double_t z=0)
This function is used for filling the two histograms with a weight.
~TEfficiency()
default destructor
TList * GetListOfFunctions()
static Double_t Bayesian(Double_t total, Double_t passed, Double_t level, Double_t alpha, Double_t beta, Bool_t bUpper, Bool_t bShortest=false)
Calculates the boundaries for a Bayesian confidence interval (shortest or central interval depending ...
static Double_t AgrestiCoull(Double_t total, Double_t passed, Double_t level, Bool_t bUpper)
Calculates the boundaries for the frequentist Agresti-Coull interval.
Long64_t Merge(TCollection *list)
Merges the TEfficiency objects in the given list to the given TEfficiency object using the operator+=...
std::vector< std::pair< Double_t, Double_t > > fBeta_bin_params
Definition TEfficiency.h:48
static Double_t FeldmanCousins(Double_t total, Double_t passed, Double_t level, Bool_t bUpper)
Calculates the boundaries for the frequentist Feldman-Cousins interval.
EStatOption fStatisticOption
Definition TEfficiency.h:57
void SetStatisticOption(EStatOption option)
Sets the statistic option which affects the calculation of the confidence interval.
void SetWeight(Double_t weight)
Sets the global weight for this TEfficiency object.
TH1 * fTotalHistogram
Definition TEfficiency.h:58
Int_t GetDimension() const
returns the dimension of the current TEfficiency object
TEfficiency & operator+=(const TEfficiency &rhs)
Adds the histograms of another TEfficiency object to current histograms.
Bool_t SetBins(Int_t nx, Double_t xmin, Double_t xmax)
Set the bins for the underlined passed and total histograms If the class have been already filled the...
void Build(const char *name, const char *title)
Building standard data structure of a TEfficiency object.
TH1 * GetCopyPassedHisto() const
Returns a cloned version of fPassedHistogram.
Double_t GetEfficiencyErrorUp(Int_t bin) const
Returns the upper error on the efficiency in the given global bin.
void Draw(Option_t *opt="")
Draws the current TEfficiency object.
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute distance from point px,py to a graph.
Double_t fBeta_alpha
Definition TEfficiency.h:46
Bool_t UsesBayesianStat() const
void SetBetaBeta(Double_t beta)
Sets the shape parameter β.
Double_t GetConfidenceLevel() const
static Bool_t CheckBinning(const TH1 &pass, const TH1 &total)
Checks binning for each axis.
static Double_t BetaCentralInterval(Double_t level, Double_t alpha, Double_t beta, Bool_t bUpper)
Calculates the boundaries for a central confidence interval for a Beta distribution.
Int_t GetGlobalBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Returns the global bin number which can be used as argument for the following functions:
TH1 * fPassedHistogram
temporary histogram for painting
Definition TEfficiency.h:56
static Double_t MidPInterval(Double_t total, Double_t passed, Double_t level, Bool_t bUpper)
Calculates the boundaries using the mid-P binomial interval (Lancaster method) from B.
void SetBetaAlpha(Double_t alpha)
Sets the shape parameter α.
static Bool_t CheckEntries(const TH1 &pass, const TH1 &total, Option_t *opt="")
Checks whether bin contents are compatible with binomial statistics.
static Double_t Normal(Double_t total, Double_t passed, Double_t level, Bool_t bUpper)
Returns the confidence limits for the efficiency supposing that the efficiency follows a normal distr...
Double_t fWeight
Definition TEfficiency.h:59
Bool_t SetPassedHistogram(const TH1 &rPassed, Option_t *opt)
Sets the histogram containing the passed events.
Bool_t SetTotalEvents(Int_t bin, Int_t events)
Sets the number of total events in the given global bin.
Double_t GetBetaBeta(Int_t bin=-1) const
Double_t(* fBoundary)(Double_t, Double_t, Double_t, Bool_t)
Definition TEfficiency.h:50
void FillGraph(TGraphAsymmErrors *graph, Option_t *opt) const
Fill the graph to be painted with information from TEfficiency Internal method called by TEfficiency:...
void SetName(const char *name)
Sets the name.
void FillHistogram(TH2 *h2) const
Fill the 2d histogram to be painted with information from TEfficiency 2D Internal method called by TE...
Int_t FindFixBin(Double_t x, Double_t y=0, Double_t z=0) const
Returns the global bin number containing the given values.
TDirectory * fDirectory
Definition TEfficiency.h:52
static Double_t Combine(Double_t &up, Double_t &low, Int_t n, const Int_t *pass, const Int_t *total, Double_t alpha, Double_t beta, Double_t level=0.683, const Double_t *w=0, Option_t *opt="")
void SetUseWeightedEvents(Bool_t on=kTRUE)
static Double_t Wilson(Double_t total, Double_t passed, Double_t level, Bool_t bUpper)
Calculates the boundaries for the frequentist Wilson interval.
TEfficiency & operator=(const TEfficiency &rhs)
Assignment operator.
Double_t fConfLevel
pointer to a method calculating the boundaries of confidence intervals
Definition TEfficiency.h:51
Double_t fBeta_beta
Definition TEfficiency.h:47
void SavePrimitive(std::ostream &out, Option_t *opt="")
Have histograms fixed bins along each axis?
Double_t GetEfficiency(Int_t bin) const
Returns the efficiency in the given global bin.
Bool_t SetTotalHistogram(const TH1 &rTotal, Option_t *opt)
Sets the histogram containing all events.
void Fill(Bool_t bPassed, Double_t x, Double_t y=0, Double_t z=0)
This function is used for filling the two histograms.
void SetDirectory(TDirectory *dir)
Sets the directory holding this TEfficiency object.
TGraphAsymmErrors * fPaintGraph
Definition TEfficiency.h:54
TGraphAsymmErrors * CreateGraph(Option_t *opt="") const
Create the graph used be painted (for dim=1 TEfficiency) The return object is managed by the caller.
EStatOption GetStatisticOption() const
TList * fFunctions
pointer to directory holding this TEfficiency object
Definition TEfficiency.h:53
void Paint(Option_t *opt)
Paints this TEfficiency object.
void SetBetaBinParameters(Int_t bin, Double_t alpha, Double_t beta)
Sets different shape parameter α and β for the prior distribution for each bin.
static Bool_t CheckConsistency(const TH1 &pass, const TH1 &total, Option_t *opt="")
Checks the consistence of the given histograms.
Double_t GetWeight() const
TH1 * GetCopyTotalHisto() const
Returns a cloned version of fTotalHistogram.
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute action corresponding to one event.
static Double_t ClopperPearson(Double_t total, Double_t passed, Double_t level, Bool_t bUpper)
Calculates the boundaries for the frequentist Clopper-Pearson interval.
void SetConfidenceLevel(Double_t level)
Sets the confidence level (0 < level < 1) The default value is 1-sigma :~ 0.683.
Double_t GetEfficiencyErrorLow(Int_t bin) const
Returns the lower error on the efficiency in the given global bin.
void SetTitle(const char *title)
Sets the title.
TFitResultPtr Fit(TF1 *f1, Option_t *opt="")
Fits the efficiency using the TBinomialEfficiencyFitter class.
TH2 * fPaintHisto
temporary graph for painting
Definition TEfficiency.h:55
1-Dim function class
Definition TF1.h:213
Provides an indirection to the TFitResult class and with a semantics identical to a TFitResult pointe...
TGraph with asymmetric error bars.
virtual void Paint(Option_t *chopt="")
Draw this graph with its current attributes.
Definition TGraph.cxx:2044
virtual void PaintStats(TF1 *fit)
Draw the stats.
Definition TGraph.cxx:2071
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute distance from point px,py to a graph.
Definition TGraph.cxx:813
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute action corresponding to one event.
Definition TGraph.cxx:990
1-D histogram with a double per channel (see TH1 documentation)}
Definition TH1.h:618
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:575
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:8777
virtual void SetTitle(const char *title)
See GetStatOverflows for more information.
Definition TH1.cxx:6678
virtual void SetNormFactor(Double_t factor=1)
Definition TH1.h:404
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition TH1.cxx:8981
TAxis * GetZaxis()
Definition TH1.h:322
virtual void GetStats(Double_t *stats) const
fill the array stats from the contents of this histogram The array stats must be correctly dimensione...
Definition TH1.cxx:7726
virtual Int_t GetNbinsY() const
Definition TH1.h:297
virtual Int_t GetNbinsZ() const
Definition TH1.h:298
virtual Int_t GetDimension() const
Definition TH1.h:282
@ kIsAverage
Bin contents are average (used by Add)
Definition TH1.h:170
virtual void Reset(Option_t *option="")
Reset this histogram: contents, errors, etc.
Definition TH1.cxx:7069
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition TH1.h:320
virtual Int_t GetNcells() const
Definition TH1.h:299
TObject * Clone(const char *newname=0) const
Make a complete copy of the underlying object.
Definition TH1.cxx:2740
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:4893
virtual Int_t GetNbinsX() const
Definition TH1.h:296
virtual Bool_t Add(TF1 *h1, Double_t c1=1, Option_t *option="")
Performs the operation: this = this + c1*f1 if errors are defined (see TH1::Sumw2),...
Definition TH1.cxx:822
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition TH1.cxx:3350
TAxis * GetYaxis()
Definition TH1.h:321
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9062
@ kNstat
Definition TH1.h:183
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:8992
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4386
virtual void SetName(const char *name)
Change the name of this histogram.
Definition TH1.cxx:8800
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:4993
virtual TArrayD * GetSumw2()
Definition TH1.h:312
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute action corresponding to one event.
Definition TH1.cxx:3246
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9003
virtual void Paint(Option_t *option="")
Control routine to paint any kind of histograms.
Definition TH1.cxx:6155
virtual Int_t GetSumw2N() const
Definition TH1.h:314
virtual void SetBins(Int_t nx, Double_t xmin, Double_t xmax)
Redefine x axis parameters.
Definition TH1.cxx:8607
virtual void Sumw2(Bool_t flag=kTRUE)
Create structure to store sum of squares of weights.
Definition TH1.cxx:8860
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute distance from point px,py to a line.
Definition TH1.cxx:2811
virtual void SetStats(Bool_t stats=kTRUE)
Set statistics option on/off.
Definition TH1.cxx:8830
2-D histogram with a double per channel (see TH1 documentation)}
Definition TH2.h:292
2-D histogram with a float per channel (see TH1 documentation)}
Definition TH2.h:251
Service class for 2-Dim histogram classes.
Definition TH2.h:30
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content.
Definition TH2.cxx:2507
3-D histogram with a double per channel (see TH1 documentation)}
Definition TH3.h:305
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:31
A doubly linked list.
Definition TList.h:44
virtual void Add(TObject *obj)
Definition TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition TList.cxx:822
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:659
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:359
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:187
@ kNotDeleted
object has not been deleted
Definition TObject.h:78
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:130
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:879
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition TObject.cxx:107
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition TObject.cxx:666
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:696
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:445
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:893
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:921
void ResetBit(UInt_t f)
Definition TObject.h:186
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:68
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:867
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
void ToLower()
Change string to lower-case.
Definition TString.cxx:1145
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:649
void Clear()
Clear string without changing its capacity.
Definition TString.cxx:1196
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:519
const char * Data() const
Definition TString.h:369
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:692
Bool_t IsNull() const
Definition TString.h:407
TString & Append(const char *cs)
Definition TString.h:564
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
double beta_pdf(double x, double a, double b)
Probability density function of the beta distribution.
double beta_cdf(double x, double a, double b)
Cumulative distribution function of the beta distribution Upper tail of the integral of the beta_pdf.
double beta_cdf_c(double x, double a, double b)
Complement of the cumulative distribution function of the beta distribution.
double normal_quantile(double z, double sigma)
Inverse ( ) of the cumulative distribution function of the lower tail of the normal (Gaussian) distri...
double normal_quantile_c(double z, double sigma)
Inverse ( ) of the cumulative distribution function of the upper tail of the normal (Gaussian) distri...
double beta_quantile_c(double x, double a, double b)
Inverse ( ) of the cumulative distribution function of the lower tail of the beta distribution (beta_...
double beta_quantile(double x, double a, double b)
Inverse ( ) of the cumulative distribution function of the upper tail of the beta distribution (beta_...
const Double_t sigma
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGraphErrors * gr
Definition legend1.C:25
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Definition TMath.h:430
Definition graph.py:1