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