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