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