Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGraphAsymmErrors.cxx
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Author: Rene Brun 03/03/99
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12
13#include "TEfficiency.h"
14#include "TROOT.h"
15#include "TBuffer.h"
16#include "TGraphAsymmErrors.h"
17#include "TGraphErrors.h"
18#include "TStyle.h"
19#include "TMath.h"
20#include "TVirtualPad.h"
21#include "TF1.h"
22#include "TH1.h"
23#include "TVector.h"
24#include "TVectorD.h"
25#include "TSystem.h"
27#include "strtok.h"
28
29#include <cstring>
30#include <iostream>
31#include <fstream>
32
33
34
35/** \class TGraphAsymmErrors
36 \ingroup Graphs
37TGraph with asymmetric error bars.
38
39The TGraphAsymmErrors painting is performed thanks to the TGraphPainter
40class. All details about the various painting options are given in this class.
41
42The picture below gives an example:
43
44Begin_Macro(source)
45{
46 auto c1 = new TCanvas("c1","A Simple Graph with asymmetric error bars",200,10,700,500);
47 c1->SetFillColor(42);
48 c1->SetGrid();
49 c1->GetFrame()->SetFillColor(21);
50 c1->GetFrame()->SetBorderSize(12);
51 const Int_t n = 10;
52 Double_t x[n] = {-0.22, 0.05, 0.25, 0.35, 0.5, 0.61,0.7,0.85,0.89,0.95};
53 Double_t y[n] = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};
54 Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
55 Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};
56 Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03};
57 Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6};
58 auto gr = new TGraphAsymmErrors(n,x,y,exl,exh,eyl,eyh);
59 gr->SetTitle("TGraphAsymmErrors Example");
60 gr->SetMarkerColor(4);
61 gr->SetMarkerStyle(21);
62 gr->Draw("ALP");
63}
64End_Macro
65*/
66
67
68////////////////////////////////////////////////////////////////////////////////
69/// TGraphAsymmErrors default constructor.
70
72
73
74////////////////////////////////////////////////////////////////////////////////
75/// TGraphAsymmErrors copy constructor
76
78 : TGraph(gr)
79{
80 if (!CtorAllocate()) return;
81 Int_t n = fNpoints*sizeof(Double_t);
82 memcpy(fEXlow, gr.fEXlow, n);
83 memcpy(fEYlow, gr.fEYlow, n);
84 memcpy(fEXhigh, gr.fEXhigh, n);
85 memcpy(fEYhigh, gr.fEYhigh, n);
86}
87
88
89////////////////////////////////////////////////////////////////////////////////
90/// TGraphAsymmErrors assignment operator.
91
93{
94 if(this!=&gr) {
96 // delete arrays
97 if (fEXlow) delete [] fEXlow;
98 if (fEYlow) delete [] fEYlow;
99 if (fEXhigh) delete [] fEXhigh;
100 if (fEYhigh) delete [] fEYhigh;
101
102 if (!CtorAllocate()) return *this;
103 Int_t n = fNpoints*sizeof(Double_t);
104 memcpy(fEXlow, gr.fEXlow, n);
105 memcpy(fEYlow, gr.fEYlow, n);
106 memcpy(fEXhigh, gr.fEXhigh, n);
107 memcpy(fEYhigh, gr.fEYhigh, n);
108 }
109 return *this;
110}
111
112
113////////////////////////////////////////////////////////////////////////////////
114/// TGraphAsymmErrors normal constructor.
115///
116/// the arrays are preset to zero
117
119 : TGraph(n)
120{
121 if (!CtorAllocate()) return;
122 FillZero(0, fNpoints);
123}
124
125
126////////////////////////////////////////////////////////////////////////////////
127/// TGraphAsymmErrors normal constructor.
128///
129/// if exl,h or eyl,h are null, the corresponding arrays are preset to zero
130
132 : TGraph(n,x,y)
133{
134 if (!CtorAllocate()) return;
135
136 for (Int_t i=0;i<n;i++) {
137 if (exl) fEXlow[i] = exl[i];
138 else fEXlow[i] = 0;
139 if (exh) fEXhigh[i] = exh[i];
140 else fEXhigh[i] = 0;
141 if (eyl) fEYlow[i] = eyl[i];
142 else fEYlow[i] = 0;
143 if (eyh) fEYhigh[i] = eyh[i];
144 else fEYhigh[i] = 0;
145 }
146}
147
148
149////////////////////////////////////////////////////////////////////////////////
150/// TGraphAsymmErrors normal constructor.
151///
152/// if exl,h or eyl,h are null, the corresponding arrays are preset to zero
153
155 : TGraph(n,x,y)
156{
157 if (!CtorAllocate()) return;
158
159 n = fNpoints*sizeof(Double_t);
160 if (exl)
161 memcpy(fEXlow, exl, n);
162 else
163 memset(fEXlow, 0, n);
164 if (exh)
165 memcpy(fEXhigh, exh, n);
166 else
167 memset(fEXhigh, 0, n);
168 if (eyl)
169 memcpy(fEYlow, eyl, n);
170 else
171 memset(fEYlow, 0, n);
172 if (eyh)
173 memcpy(fEYhigh, eyh, n);
174 else
175 memset(fEYhigh, 0, n);
176}
177
178
179////////////////////////////////////////////////////////////////////////////////
180/// Constructor with six vectors of floats in input
181/// A grapherrors is built with the X coordinates taken from vx and Y coord from vy
182/// and the errors from vectors vexl/h and veyl/h.
183/// The number of points in the graph is the minimum of number of points
184/// in vx and vy.
185
187{
188 fNpoints = TMath::Min(vx.GetNrows(), vy.GetNrows());
189 if (!TGraph::CtorAllocate()) return;
190 if (!CtorAllocate()) return;
191 Int_t ivxlow = vx.GetLwb();
192 Int_t ivylow = vy.GetLwb();
193 Int_t ivexllow = vexl.GetLwb();
194 Int_t ivexhlow = vexh.GetLwb();
195 Int_t iveyllow = veyl.GetLwb();
196 Int_t iveyhlow = veyh.GetLwb();
197 for (Int_t i=0;i<fNpoints;i++) {
198 fX[i] = vx(i+ivxlow);
199 fY[i] = vy(i+ivylow);
200 fEXlow[i] = vexl(i+ivexllow);
201 fEYlow[i] = veyl(i+iveyllow);
202 fEXhigh[i] = vexh(i+ivexhlow);
203 fEYhigh[i] = veyh(i+iveyhlow);
204 }
205}
206
207
208////////////////////////////////////////////////////////////////////////////////
209/// Constructor with six vectors of doubles in input
210/// A grapherrors is built with the X coordinates taken from vx and Y coord from vy
211/// and the errors from vectors vexl/h and veyl/h.
212/// The number of points in the graph is the minimum of number of points
213/// in vx and vy.
214
216{
217 fNpoints = TMath::Min(vx.GetNrows(), vy.GetNrows());
218 if (!TGraph::CtorAllocate()) return;
219 if (!CtorAllocate()) return;
220 Int_t ivxlow = vx.GetLwb();
221 Int_t ivylow = vy.GetLwb();
222 Int_t ivexllow = vexl.GetLwb();
223 Int_t ivexhlow = vexh.GetLwb();
224 Int_t iveyllow = veyl.GetLwb();
225 Int_t iveyhlow = veyh.GetLwb();
226 for (Int_t i=0;i<fNpoints;i++) {
227 fX[i] = vx(i+ivxlow);
228 fY[i] = vy(i+ivylow);
229 fEXlow[i] = vexl(i+ivexllow);
230 fEYlow[i] = veyl(i+iveyllow);
231 fEXhigh[i] = vexh(i+ivexhlow);
232 fEYhigh[i] = veyh(i+iveyhlow);
233 }
234}
235
236
237////////////////////////////////////////////////////////////////////////////////
238/// TGraphAsymmErrors constructor importing its parameters from the TH1 object passed as argument
239/// the low and high errors are set to the bin error of the histogram.
240
242 : TGraph(h)
243{
244 if (!CtorAllocate()) return;
245
246 for (Int_t i = 0; i < fNpoints; i++) {
247 fEXlow[i] = h->GetBinWidth(i+1)*gStyle->GetErrorX();
248 fEXhigh[i] = fEXlow[i];
249 fEYlow[i] = h->GetBinErrorLow(i+1);
250 fEYhigh[i] = h->GetBinErrorUp(i+1);
251 }
252}
253
254
255////////////////////////////////////////////////////////////////////////////////
256/// Creates a TGraphAsymmErrors by dividing two input TH1 histograms:
257/// pass/total. (see TGraphAsymmErrors::Divide)
258
260 : TGraph((pass)?pass->GetNbinsX():0)
261{
262 if (!pass || !total) {
263 Error("TGraphAsymmErrors","Invalid histogram pointers");
264 return;
265 }
266 if (!CtorAllocate()) return;
267
268 std::string sname = "divide_" + std::string(pass->GetName()) + "_by_" +
269 std::string(total->GetName());
270 SetName(sname.c_str());
271 SetTitle(pass->GetTitle());
272
273 //copy style from pass
274 pass->TAttLine::Copy(*this);
275 pass->TAttFill::Copy(*this);
276 pass->TAttMarker::Copy(*this);
277
279}
280
281
282////////////////////////////////////////////////////////////////////////////////
283/// TGraphAsymmErrors constructor reading input from filename
284/// filename is assumed to contain at least 2 columns of numbers
285///
286/// Convention for format (default=`"%lg %lg %lg %lg %lg %lg"`)
287///
288/// - format = `"%lg %lg"` read only 2 first columns into X, Y
289/// - format = `"%lg %lg %lg %lg"` read only 4 first columns into X, Y, EYL, EYH
290/// - format = `"%lg %lg %lg %lg %lg %lg"` read only 6 first columns into X, Y, EXL, EXH, EYL, EYH
291///
292/// If format string is empty, suitable value will be provided based on file extension
293///
294/// For files separated by a specific delimiter different from ' ' and `\\t` (e.g. `;` in csv files)
295/// you can avoid using `%*s` to bypass this delimiter by explicitly specify the `option` argument,
296/// e.g. `option=" \\t,;"` for columns of figures separated by any of these characters (`' ', '\\t', ',', ';'`)
297/// used once (e.g. `"1;1"`) or in a combined way (`" 1;,;; 1"`).
298///
299/// Note in that case, the instantiation is about 2 times slower.
300/// In case a delimiter is specified, the format `"%lg %lg %lg"` will read X,Y,EXL.
301
303 : TGraph(100)
304{
305 if (!CtorAllocate()) return;
306 Double_t x, y, exl, exh, eyl, eyh;
309 std::ifstream infile(fname.Data());
310 if (!infile.good()) {
311 MakeZombie();
312 Error("TGraphAsymmErrors", "Cannot open file: %s, TGraphAsymmErrors is Zombie", filename);
313 fNpoints = 0;
314 return;
315 }
316 std::string line;
317 Int_t np = 0;
318
320
321 if (!option || !*option) { // No delimiters specified (standard constructor).
322
323 Int_t ncol = 6;
324 if (format_.IsNull()) {
325 if (fname.EndsWith(".txt", TString::kIgnoreCase))
326 format_ = "%lg %lg %lg %lg %lg %lg";
327 else if (fname.EndsWith(".tsv", TString::kIgnoreCase))
328 format_ = "%lg\t%lg\t%lg\t%lg\t%lg\t%lg";
329 else
330 format_ = "%lg,%lg,%lg,%lg,%lg,%lg";
331 } else
332 ncol = TGraphErrors::CalculateScanfFields(format); //count number of columns in format
333
334 Int_t res;
335 while (std::getline(infile, line, '\n')) {
336 exl = exh = eyl = eyh = 0.;
337 if (ncol < 3) {
338 res = sscanf(line.c_str(), format_.Data(), &x, &y);
339 } else if (ncol < 5) {
340 res = sscanf(line.c_str(), format_.Data(), &x, &y, &eyl, &eyh);
341 } else {
342 res = sscanf(line.c_str(), format_.Data(), &x, &y, &exl, &exh, &eyl, &eyh);
343 }
344 if (res < 2) {
345 continue; //skip empty and ill-formed lines
346 }
347 SetPoint(np, x, y);
349 np++;
350 }
351 Set(np);
352
353 } else { // A delimiter has been specified in "option"
354
355 // Checking format and creating its boolean equivalent
356 format_.ReplaceAll(" ", "") ;
357 format_.ReplaceAll("\t", "") ;
358 format_.ReplaceAll("lg", "") ;
359 format_.ReplaceAll("s", "") ;
360 format_.ReplaceAll("%*", "0") ;
361 format_.ReplaceAll("%", "1") ;
362 if (!format_.IsDigit()) {
363 Error("TGraphAsymmErrors", "Incorrect input format! Allowed format tags are {\"%%lg\",\"%%*lg\" or \"%%*s\"}");
364 return ;
365 }
366 Int_t ntokens = format_.Length() ;
367 if (ntokens < 2) {
368 Error("TGraphAsymmErrors", "Incorrect input format! Only %d tag(s) in format whereas at least 2 \"%%lg\" tags are expected!", ntokens);
369 return ;
370 }
373 for (Int_t idx = 0; idx < ntokens; idx++) {
374 isTokenToBeSaved[idx] = TString::Format("%c", format_[idx]).Atoi(); //atoi(&format_[idx]) does not work for some reason...
375 if (isTokenToBeSaved[idx] == 1) {
377 }
378 }
379 if (ntokens >= 2 && (ntokensToBeSaved < 2 || ntokensToBeSaved > 6)) { //first condition not to repeat the previous error message
380 Error("TGraphAsymmErrors", "Incorrect input format! There are %d \"%%lg\" tag(s) in format whereas 2, 3, 4, 5 or 6 are expected!", ntokensToBeSaved);
381 delete [] isTokenToBeSaved;
382 return ;
383 }
384
385 // Initializing loop variables
386 Bool_t isLineToBeSkipped = kFALSE; //empty and ill-formed lines
387 char *token = nullptr;
388 TString token_str = "";
389 Int_t token_idx = 0;
390 Double_t value[6]; //x,y,exl, exh, eyl, eyh buffers
391 for (Int_t k = 0; k < 6; k++)
392 value[k] = 0.;
393 Int_t value_idx = 0;
394
395 // Looping
396 char *rest;
397 while (std::getline(infile, line, '\n')) {
398 if (!line.empty()) {
399 if (line[line.size() - 1] == char(13)) { // removing DOS CR character
400 line.erase(line.end() - 1, line.end()) ;
401 }
402 token = R__STRTOK_R(const_cast<char*>(line.c_str()), option, &rest) ;
403 while (token != nullptr && value_idx < ntokensToBeSaved) {
405 token_str = TString(token) ;
406 token_str.ReplaceAll("\t", "") ;
407 if (!token_str.IsFloat()) {
409 break ;
410 } else {
411 value[value_idx] = token_str.Atof() ;
412 value_idx++ ;
413 }
414 }
415 token = R__STRTOK_R(nullptr, option, &rest); // next token
416 token_idx++ ;
417 }
418 if (!isLineToBeSkipped && value_idx > 1) { //i.e. 2, 3, 4, 5 or 6
419 x = value[0];
420 y = value[1];
421 exl = value[2];
422 exh = value[3];
423 eyl = value[4];
424 eyh = value[5];
425 SetPoint(np, x, y);
427 np++ ;
428 }
429 }
431 token = nullptr;
432 token_idx = 0;
433 value_idx = 0;
434 }
435 Set(np) ;
436
437 // Cleaning
438 delete [] isTokenToBeSaved;
439 delete token;
440 }
441 infile.close();
442}
443
444////////////////////////////////////////////////////////////////////////////////
445/// TGraphAsymmErrors default destructor.
446
448{
449 if(fEXlow) delete [] fEXlow;
450 if(fEXhigh) delete [] fEXhigh;
451 if(fEYlow) delete [] fEYlow;
452 if(fEYhigh) delete [] fEYhigh;
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Allocate internal data structures for `size` points.
457
461
462////////////////////////////////////////////////////////////////////////////////
463/// Add a point with asymmetric errorbars to the graph.
464
470
471////////////////////////////////////////////////////////////////////////////////
472/// Apply a function to all data points \f$ y = f(x,y) \f$
473///
474/// Errors are calculated as \f$ eyh = f(x,y+eyh)-f(x,y) \f$ and
475/// \f$ eyl = f(x,y)-f(x,y-eyl) \f$
476///
477/// Special treatment has to be applied for the functions where the
478/// role of "up" and "down" is reversed.
479///
480/// Function suggested/implemented by Miroslav Helbich <helbich@mail.desy.de>
481
483{
485
486 if (fHistogram) {
487 delete fHistogram;
488 fHistogram = nullptr;
489 }
490 for (Int_t i=0;i<GetN();i++) {
491 GetPoint(i,x,y);
492 exl = GetErrorXlow(i);
493 exh = GetErrorXhigh(i);
494 eyl = GetErrorYlow(i);
495 eyh = GetErrorYhigh(i);
496
497 fxy = f->Eval(x,y);
498 SetPoint(i,x,fxy);
499
500 // in the case of the functions like y-> -1*y the roles of the
501 // upper and lower error bars is reversed
502 if (f->Eval(x,y-eyl)<f->Eval(x,y+eyh)) {
503 eyl_new = TMath::Abs(fxy - f->Eval(x,y-eyl));
504 eyh_new = TMath::Abs(f->Eval(x,y+eyh) - fxy);
505 } else {
506 eyh_new = TMath::Abs(fxy - f->Eval(x,y-eyl));
507 eyl_new = TMath::Abs(f->Eval(x,y+eyh) - fxy);
508 }
509
510 //error on x doesn't change
512 }
513 if (gPad) gPad->Modified();
514}
515
516////////////////////////////////////////////////////////////////////////////////
517///This function is only kept for backward compatibility.
518///You should rather use the Divide method.
519///It calls `Divide(pass,total,"cl=0.683 b(1,1) mode")` which is equivalent to the
520///former BayesDivide method.
521
523{
524 Divide(pass,total,"cl=0.683 b(1,1) mode");
525}
526
527////////////////////////////////////////////////////////////////////////////////
528/// Fill this TGraphAsymmErrors by dividing two 1-dimensional histograms pass/total
529///
530/// This method serves two purposes:
531///
532/// ### 1) calculating efficiencies:
533///
534/// The assumption is that the entries in "pass" are a subset of those in
535/// "total". That is, we create an "efficiency" graph, where each entry is
536/// between 0 and 1, inclusive.
537///
538/// If the histograms are not filled with unit weights, the number of effective
539/// entries is used to normalise the bin contents which might lead to wrong results.
540/// \f[
541/// \text{effective entries} = \frac{(\sum w_{i})^{2}}{\sum w_{i}^{2}}
542/// \f]
543/// The points are assigned a x value at the center of each histogram bin.
544/// The y values are \f$\text{eff} = \frac{\text{pass}}{\text{total}}\f$
545/// for all options except for the
546/// bayesian methods where the result depends on the chosen option.
547///
548/// If the denominator becomes 0 or pass > total, the corresponding bin is
549/// skipped.
550///
551/// ### 2) calculating ratios of two Poisson means (option 'pois'):
552///
553/// The two histograms are interpreted as independent Poisson processes and the ratio
554/// \f[
555/// \tau = \frac{n_{1}}{n_{2}} = \frac{\varepsilon}{1 - \varepsilon}
556/// \f]
557/// with \f$\varepsilon = \frac{n_{1}}{n_{1} + n_{2}}\f$.
558/// The histogram 'pass' is interpreted as \f$n_{1}\f$ and the total histogram
559/// is used for \f$n_{2}\f$.
560///
561/// The (asymmetric) uncertainties of the Poisson ratio are linked to the uncertainties
562/// of efficiency by a parameter transformation:
563/// \f[
564/// \Delta \tau_{low/up} = \frac{1}{(1 - \varepsilon)^{2}} \Delta \varepsilon_{low/up}
565/// \f]
566///
567/// The x errors span each histogram bin (lowedge ... lowedge+width)
568/// The y errors depend on the chosen statistic methode which can be determined
569/// by the options given below. For a detailed description of the used statistic
570/// calculations please have a look at the corresponding functions!
571///
572/// Options:
573/// - v : verbose mode: prints information about the number of used bins
574/// and calculated efficiencies with their errors
575/// - cl=x : determine the used confidence level (0<x<1) (default is 0.683)
576/// - cp : Clopper-Pearson interval (see TEfficiency::ClopperPearson)
577/// - w : Wilson interval (see TEfficiency::Wilson)
578/// - n : normal approximation propagation (see TEfficiency::Normal)
579/// - ac : Agresti-Coull interval (see TEfficiency::AgrestiCoull)
580/// - fc : Feldman-Cousins interval (see TEfficiency::FeldmanCousinsInterval)
581/// - midp : Lancaster mid-P interval (see TEfficiency::MidPInterval)
582/// - b(a,b): bayesian interval using a prior probability ~Beta(a,b); a,b > 0
583/// (see TEfficiency::Bayesian)
584/// - mode : use mode of posterior for Bayesian interval (default is mean)
585/// - shortest: use shortest interval (done by default if mode is set)
586/// - central: use central interval (done by default if mode is NOT set)
587/// - pois: interpret histograms as poisson ratio instead of efficiency
588/// - e0 : plot efficiency and interval for bins where total=0
589/// (default is to skip them)
590///
591/// Note:
592/// Unfortunately there is no straightforward approach for determining a confidence
593/// interval for a given confidence level. The actual coverage probability of the
594/// confidence interval oscillates significantly according to the total number of
595/// events and the true efficiency. In order to decrease the impact of this
596/// oscillation on the actual coverage probability a couple of approximations and
597/// methodes has been developed. For a detailed discussion, please have a look at
598/// this statistical paper:
599/// http://www-stat.wharton.upenn.edu/~tcai/paper/Binomial-StatSci.pdf
600
601
603{
604 //check pointers
605 if(!pass || !total) {
606 Error("Divide","one of the passed pointers is zero");
607 return;
608 }
609
610 //check dimension of histograms; only 1-dimensional ones are accepted
611 if((pass->GetDimension() > 1) || (total->GetDimension() > 1)) {
612 Error("Divide","passed histograms are not one-dimensional");
613 return;
614 }
615
616 //check whether histograms are filled with weights -> use number of effective
617 //entries
618 Bool_t bEffective = false;
619 //compare sum of weights with sum of squares of weights
620 // re-compute here to be sure to get the right values
621 Double_t psumw = 0;
622 Double_t psumw2 = 0;
623 if (pass->GetSumw2()->fN > 0) {
624 for (int i = 0; i < pass->GetNcells(); ++i) {
625 psumw += pass->GetBinContent(i);
626 psumw2 += pass->GetSumw2()->At(i);
627 }
628 }
629 else {
630 psumw = pass->GetSumOfWeights();
631 psumw2 = psumw;
632 }
633 if (TMath::Abs(psumw - psumw2) > 1e-6)
634 bEffective = true;
635
636 Double_t tsumw = 0;
637 Double_t tsumw2 = 0;
638 if (total->GetSumw2()->fN > 0) {
639 for (int i = 0; i < total->GetNcells(); ++i) {
640 tsumw += total->GetBinContent(i);
641 tsumw2 += total->GetSumw2()->At(i);
642 }
643 }
644 else {
645 tsumw = total->GetSumOfWeights();
646 tsumw2 = tsumw;
647 }
648 if (TMath::Abs(tsumw - tsumw2) > 1e-6)
649 bEffective = true;
650
651
652
653 // we do not want to ignore the weights
654 // if (bEffective && (pass->GetSumw2()->fN == 0 || total->GetSumw2()->fN == 0) ) {
655 // Warning("Divide","histogram have been computed with weights but the sum of weight squares are not stored in the histogram. Error calculation is performed ignoring the weights");
656 // bEffective = false;
657 // }
658
659 //parse option
660 TString option = opt;
661 option.ToLower();
662
663 Bool_t bVerbose = false;
664 //pointer to function returning the boundaries of the confidence interval
665 //(is only used in the frequentist cases.)
667 //confidence level
668 Double_t conf = 0.682689492137;
669 //values for bayesian statistics
670 Bool_t bIsBayesian = false;
671 Double_t alpha = 1;
672 Double_t beta = 1;
673
674 //verbose mode
675 if(option.Contains("v")) {
676 option.ReplaceAll("v","");
677 bVerbose = true;
678 if (bEffective)
679 Info("Divide","weight will be considered in the Histogram Ratio");
680 }
681
682
683 //confidence level
684 if(option.Contains("cl=")) {
685 Double_t level = -1;
686 // coverity [secure_coding : FALSE]
687 sscanf(strstr(option.Data(),"cl="),"cl=%lf",&level);
688 if((level > 0) && (level < 1))
689 conf = level;
690 else
691 Warning("Divide","given confidence level %.3lf is invalid",level);
692 option.ReplaceAll("cl=","");
693 }
694
695 // look for statistic options
696 // check first Bayesian case
697 // bayesian with prior
698 Bool_t usePosteriorMode = false;
700 if (option.Contains("b(")) {
701 Double_t a = 0;
702 Double_t b = 0;
703 sscanf(strstr(option.Data(), "b("), "b(%lf,%lf)", &a, &b);
704 if (a > 0)
705 alpha = a;
706 else
707 Warning("Divide", "given shape parameter for alpha %.2lf is invalid", a);
708 if (b > 0)
709 beta = b;
710 else
711 Warning("Divide", "given shape parameter for beta %.2lf is invalid", b);
712 option.ReplaceAll("b(", "");
713 bIsBayesian = true;
714
715 // look for specific bayesian options
716
717 // use posterior mode
718
719 if (option.Contains("mode")) {
720 usePosteriorMode = true;
721 option.ReplaceAll("mode", "");
722 }
723 if (option.Contains("sh") || (usePosteriorMode && !option.Contains("cen"))) {
724 useShortestInterval = true;
725 }
726 }
727 // normal approximation
728 else if (option.Contains("n")) {
729 option.ReplaceAll("n", "");
731 }
732 // clopper pearson interval
733 else if (option.Contains("cp")) {
734 option.ReplaceAll("cp", "");
736 }
737 // wilson interval
738 else if (option.Contains("w")) {
739 option.ReplaceAll("w", "");
741 }
742 // agresti coull interval
743 else if (option.Contains("ac")) {
744 option.ReplaceAll("ac", "");
746 }
747 // Feldman-Cousins interval
748 else if (option.Contains("fc")) {
749 option.ReplaceAll("fc", "");
751 }
752 // mid-P Lancaster interval
753 else if (option.Contains("midp")) {
754 option.ReplaceAll("midp", "");
756 }
757
758 // interpret as Poisson ratio
759 Bool_t bPoissonRatio = false;
760 if (option.Contains("pois")) {
761 bPoissonRatio = true;
762 option.ReplaceAll("pois", "");
763 }
764 Bool_t plot0Bins = false;
765 if (option.Contains("e0")) {
766 plot0Bins = true;
767 option.ReplaceAll("e0", "");
768 }
769
770 // weights works only in case of Normal approximation or Bayesian for binomial interval
771 // in case of Poisson ratio we can use weights by rescaling the obtained results using the effective entries
773 Warning("Divide", "Histograms have weights: only Normal or Bayesian error calculation is supported");
774 Info("Divide", "Using now the Normal approximation for weighted histograms");
775 }
776
777 if (bPoissonRatio) {
778 if (pass->GetDimension() != total->GetDimension()) {
779 Error("Divide", "passed histograms are not of the same dimension");
780 return;
781 }
782
784 Error("Divide", "passed histograms are not consistent");
785 return;
786 }
787 } else {
788 // check consistency of histograms, allowing weights
790 Error("Divide", "passed histograms are not consistent");
791 return;
792 }
793 }
794
795 // Set the graph to have a number of points equal to the number of histogram
796 // bins
797 Int_t nbins = pass->GetNbinsX();
798 Set(nbins);
799
800 // Ok, now set the points for each bin
801 // (Note: the TH1 bin content is shifted to the right by one:
802 // bin=0 is underflow, bin=nbins+1 is overflow.)
803
804 //efficiency with lower and upper boundary of confidence interval
805 double eff, low, upper;
806 //this keeps track of the number of points added to the graph
807 int npoint=0;
808 //number of total and passed events
809 Double_t t = 0 , p = 0;
810 Double_t tw = 0, tw2 = 0, pw = 0, pw2 = 0, wratio = 1; // for the case of weights
811 //loop over all bins and fill the graph
812 for (Int_t b=1; b<=nbins; ++b) {
813
814 // default value when total =0;
815 eff = 0;
816 low = 0;
817 upper = 0;
818
819 // special case in case of weights we have to consider the sum of weights and the sum of weight squares
820 if (bEffective) {
821 tw = total->GetBinContent(b);
822 tw2 = (total->GetSumw2()->fN > 0) ? total->GetSumw2()->At(b) : tw;
823 pw = pass->GetBinContent(b);
824 pw2 = (pass->GetSumw2()->fN > 0) ? pass->GetSumw2()->At(b) : pw;
825
826 if (bPoissonRatio) {
827 // tw += pw;
828 // tw2 += pw2;
829 // compute ratio on the effective entries ( p and t)
830 // special case is when (pw=0, pw2=0) in this case we cannot get the bin weight.
831 // we use then the overall weight of the full histogram
832 if (pw == 0 && pw2 == 0)
833 p = 0;
834 else
835 p = (pw * pw) / pw2;
836
837 if (tw == 0 && tw2 == 0)
838 t = 0;
839 else
840 t = (tw * tw) / tw2;
841
842 if (pw > 0 && tw > 0)
843 // this is the ratio of the two bin weights ( pw/p / t/tw )
844 wratio = (pw * t) / (p * tw);
845 else if (pw == 0 && tw > 0)
846 // case p histogram has zero compute the weights from all the histogram
847 // weight of histogram - sumw2/sumw
848 wratio = (psumw2 * t) / (psumw * tw);
849 else if (tw == 0 && pw > 0)
850 // case t histogram has zero compute the weights from all the histogram
851 // weight of histogram - sumw2/sumw
852 wratio = (pw * tsumw) / (p * tsumw2);
853 else if (p > 0)
854 wratio = pw / p; // not sure if needed
855 else {
856 // case both pw and tw are zero - we skip these bins
857 if (!plot0Bins) continue; // skip bins with total <= 0
858 }
859
860 t += p;
861 // std::cout << p << " " << t << " " << wratio << std::endl;
862 } else if (tw <= 0 && !plot0Bins)
863 continue; // skip bins with total <= 0
864
865 // in the case of weights have the formula only for
866 // the normal and bayesian statistics (see below)
867
868 }
869
870 // use bin contents
871 else {
872 t = std::round(total->GetBinContent(b));
873 p = std::round(pass->GetBinContent(b));
874
875 if (bPoissonRatio)
876 t += p;
877
878 if (t == 0.0 && !plot0Bins)
879 continue; // skip bins with total = 0
880 }
881
882 //using bayesian statistics
883 if(bIsBayesian) {
884 double aa,bb;
885
886 if ((bEffective && !bPoissonRatio) && tw2 <= 0) {
887 // case of bins with zero errors
888 eff = pw/tw;
889 low = eff; upper = eff;
890 }
891 else {
892
893 if (bEffective && !bPoissonRatio) {
894 // tw/tw2 re-normalize the weights
895 double norm = tw/tw2; // case of tw2 = 0 is treated above
896 aa = pw * norm + alpha;
897 bb = (tw - pw) * norm + beta;
898 }
899 else {
900 aa = double(p) + alpha;
901 bb = double(t-p) + beta;
902 }
905 else
907
910 }
911 else {
914 }
915 }
916 }
917 // case of non-bayesian statistics
918 else {
919 if (bEffective && !bPoissonRatio) {
920
921 if (tw > 0) {
922
923 eff = pw/tw;
924
925 // use normal error calculation using variance of MLE with weights (F.James 8.5.2)
926 // this is the same formula used in ROOT for TH1::Divide("B")
927
928 double variance = ( pw2 * (1. - 2 * eff) + tw2 * eff *eff ) / ( tw * tw) ;
929 double sigma = sqrt(variance);
930
931 double prob = 0.5 * (1.-conf);
933 low = eff - delta;
934 upper = eff + delta;
935 if (low < 0) low = 0;
936 if (upper > 1) upper = 1.;
937 }
938 }
939 else {
940 // when not using weights (all cases) or in case of Poisson ratio with weights
941 if(t != 0.0)
942 eff = ((Double_t)p)/t;
943
944 low = pBound(t,p,conf,false);
945 upper = pBound(t,p,conf,true);
946 }
947 }
948 // treat as Poisson ratio
949 if(bPoissonRatio)
950 {
951 Double_t ratio = eff/(1 - eff);
952 // take the intervals in eff as intervals in the Poisson ratio
953 low = low/(1. - low);
954 upper = upper/(1.-upper);
955 eff = ratio;
956 if (bEffective) {
957 //scale result by the ratio of the weight
958 eff *= wratio;
959 low *= wratio;
960 upper *= wratio;
961 }
962 }
963 //Set the point center and its errors
964 if (TMath::Finite(eff)) {
965 SetPoint(npoint,pass->GetBinCenter(b),eff);
967 pass->GetBinCenter(b)-pass->GetBinLowEdge(b),
968 pass->GetBinLowEdge(b)-pass->GetBinCenter(b)+pass->GetBinWidth(b),
969 eff-low,upper-eff);
970 npoint++;//we have added a point to the graph
971 }
972 }
973
974 Set(npoint);//tell the graph how many points we've really added
975 if (npoint < nbins)
976 Warning("Divide","Number of graph points is different than histogram bins - %d points have been skipped",nbins-npoint);
977
978
979 if (bVerbose) {
980 Info("Divide","made a graph with %d points from %d bins",npoint,nbins);
981 Info("Divide","used confidence level: %.2lf\n",conf);
982 if(bIsBayesian)
983 Info("Divide","used prior probability ~ beta(%.2lf,%.2lf)",alpha,beta);
984 Print();
985 }
986}
987
988////////////////////////////////////////////////////////////////////////////////
989/// Compute Range.
990
992{
994
995 for (Int_t i=0;i<fNpoints;i++) {
996 if (fX[i] -fEXlow[i] < xmin) {
997 if (gPad && gPad->GetLogx()) {
998 if (fEXlow[i] < fX[i]) xmin = fX[i]-fEXlow[i];
999 else xmin = TMath::Min(xmin,fX[i]/3);
1000 } else {
1001 xmin = fX[i]-fEXlow[i];
1002 }
1003 }
1004 if (fX[i] +fEXhigh[i] > xmax) xmax = fX[i]+fEXhigh[i];
1005 if (fY[i] -fEYlow[i] < ymin) {
1006 if (gPad && gPad->GetLogy()) {
1007 if (fEYlow[i] < fY[i]) ymin = fY[i]-fEYlow[i];
1008 else ymin = TMath::Min(ymin,fY[i]/3);
1009 } else {
1010 ymin = fY[i]-fEYlow[i];
1011 }
1012 }
1013 if (fY[i] +fEYhigh[i] > ymax) ymax = fY[i]+fEYhigh[i];
1014 }
1015}
1016
1017
1018////////////////////////////////////////////////////////////////////////////////
1019/// Copy and release.
1020
1023{
1025 if (newarrays) {
1026 delete[] fEXlow;
1027 fEXlow = newarrays[0];
1028 delete[] fEXhigh;
1029 fEXhigh = newarrays[1];
1030 delete[] fEYlow;
1031 fEYlow = newarrays[2];
1032 delete[] fEYhigh;
1033 fEYhigh = newarrays[3];
1034 delete[] fX;
1035 fX = newarrays[4];
1036 delete[] fY;
1037 fY = newarrays[5];
1038 delete[] newarrays;
1039 }
1040}
1041
1042
1043////////////////////////////////////////////////////////////////////////////////
1044/// Copy errors from `fE***` to `arrays[***]`
1045/// or to `f***` Copy points.
1046
1049{
1050 if (TGraph::CopyPoints(arrays ? arrays+4 : nullptr, ibegin, iend, obegin)) {
1051 Int_t n = (iend - ibegin)*sizeof(Double_t);
1052 if (arrays) {
1053 memmove(&arrays[0][obegin], &fEXlow[ibegin], n);
1054 memmove(&arrays[1][obegin], &fEXhigh[ibegin], n);
1055 memmove(&arrays[2][obegin], &fEYlow[ibegin], n);
1056 memmove(&arrays[3][obegin], &fEYhigh[ibegin], n);
1057 } else {
1062 }
1063 return kTRUE;
1064 } else {
1065 return kFALSE;
1066 }
1067}
1068
1069
1070////////////////////////////////////////////////////////////////////////////////
1071/// Should be called from ctors after `fNpoints` has been set.
1072/// Note: This function should be called only from the constructor
1073/// since it does not delete previously existing arrays
1074
1076{
1077 if (!fNpoints) {
1078 fEXlow = fEYlow = fEXhigh = fEYhigh = nullptr;
1079 return kFALSE;
1080 }
1081 fEXlow = new Double_t[fMaxSize];
1082 fEYlow = new Double_t[fMaxSize];
1083 fEXhigh = new Double_t[fMaxSize];
1084 fEYhigh = new Double_t[fMaxSize];
1085 return kTRUE;
1086}
1087
1088////////////////////////////////////////////////////////////////////////////////
1089/// Protected function to perform the merge operation of a graph with asymmetric errors.
1090
1092{
1093 if (g->GetN() == 0) return kFALSE;
1094
1095 Double_t * exl = g->GetEXlow();
1096 Double_t * exh = g->GetEXhigh();
1097 Double_t * eyl = g->GetEYlow();
1098 Double_t * eyh = g->GetEYhigh();
1099 if (exl == nullptr || exh == nullptr || eyl == nullptr || eyh == nullptr) {
1100 if (g->IsA() != TGraph::Class() )
1101 Warning("DoMerge","Merging a %s is not compatible with a TGraphAsymmErrors - errors will be ignored",g->IsA()->GetName());
1102 return TGraph::DoMerge(g);
1103 }
1104 for (Int_t i = 0 ; i < g->GetN(); i++) {
1105 Int_t ipoint = GetN();
1106 Double_t x = g->GetX()[i];
1107 Double_t y = g->GetY()[i];
1108 SetPoint(ipoint, x, y);
1109 SetPointError(ipoint, exl[i], exh[i], eyl[i], eyh[i] );
1110 }
1111
1112 return kTRUE;
1113}
1114
1115////////////////////////////////////////////////////////////////////////////////
1116/// Set zero values for point arrays in the range `[begin, end]`
1117
1120{
1121 if (!from_ctor) {
1122 TGraph::FillZero(begin, end, from_ctor);
1123 }
1124 Int_t n = (end - begin)*sizeof(Double_t);
1125 memset(fEXlow + begin, 0, n);
1126 memset(fEXhigh + begin, 0, n);
1127 memset(fEYlow + begin, 0, n);
1128 memset(fEYhigh + begin, 0, n);
1129}
1130
1131
1132////////////////////////////////////////////////////////////////////////////////
1133/// Returns the combined error along X at point i by computing the average
1134/// of the lower and upper variance.
1135
1137{
1138 if (i < 0 || i >= fNpoints) return -1;
1139 if (!fEXlow && !fEXhigh) return -1;
1140 Double_t elow=0, ehigh=0;
1141 if (fEXlow) elow = fEXlow[i];
1142 if (fEXhigh) ehigh = fEXhigh[i];
1143 return TMath::Sqrt(0.5*(elow*elow + ehigh*ehigh));
1144}
1145
1146
1147////////////////////////////////////////////////////////////////////////////////
1148/// Returns the combined error along Y at point i by computing the average
1149/// of the lower and upper variance.
1150
1152{
1153 if (i < 0 || i >= fNpoints) return -1;
1154 if (!fEYlow && !fEYhigh) return -1;
1155 Double_t elow=0, ehigh=0;
1156 if (fEYlow) elow = fEYlow[i];
1157 if (fEYhigh) ehigh = fEYhigh[i];
1158 return TMath::Sqrt(0.5*(elow*elow + ehigh*ehigh));
1159}
1160
1161
1162////////////////////////////////////////////////////////////////////////////////
1163/// Get high error on X.
1164
1166{
1167 if (i<0 || i>fNpoints) return -1;
1168 if (fEXhigh) return fEXhigh[i];
1169 return -1;
1170}
1171
1172
1173////////////////////////////////////////////////////////////////////////////////
1174/// Get low error on X.
1175
1177{
1178 if (i<0 || i>fNpoints) return -1;
1179 if (fEXlow) return fEXlow[i];
1180 return -1;
1181}
1182
1183
1184////////////////////////////////////////////////////////////////////////////////
1185/// Get high error on Y.
1186
1188{
1189 if (i<0 || i>fNpoints) return -1;
1190 if (fEYhigh) return fEYhigh[i];
1191 return -1;
1192}
1193
1194
1195////////////////////////////////////////////////////////////////////////////////
1196/// Get low error on Y.
1197
1199{
1200 if (i<0 || i>fNpoints) return -1;
1201 if (fEYlow) return fEYlow[i];
1202 return -1;
1203}
1204
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Adds all graphs with asymmetric errors from the collection to this graph.
1208/// Returns the total number of points in the result or -1 in case of an error.
1209
1211{
1212 TIter next(li);
1213 while (TObject* o = next()) {
1214 TGraph *g = dynamic_cast<TGraph*>(o);
1215 if (!g) {
1216 Error("Merge",
1217 "Cannot merge - an object which doesn't inherit from TGraph found in the list");
1218 return -1;
1219 }
1220 int n0 = GetN();
1221 int n1 = n0+g->GetN();
1222 Set(n1);
1223 Double_t * x = g->GetX();
1224 Double_t * y = g->GetY();
1225 Double_t * exlow = g->GetEXlow();
1226 Double_t * exhigh = g->GetEXhigh();
1227 Double_t * eylow = g->GetEYlow();
1228 Double_t * eyhigh = g->GetEYhigh();
1229 for (Int_t i = 0 ; i < g->GetN(); i++) {
1230 SetPoint(n0+i, x[i], y[i]);
1231 if (exlow) fEXlow[n0+i] = exlow[i];
1232 if (exhigh) fEXhigh[n0+i] = exhigh[i];
1233 if (eylow) fEYlow[n0+i] = eylow[i];
1234 if (eyhigh) fEYhigh[n0+i] = eyhigh[i];
1235 }
1236 }
1237 return GetN();
1238}
1239
1240////////////////////////////////////////////////////////////////////////////////
1241/// Print graph and errors values.
1242
1244{
1245 for (Int_t i=0;i<fNpoints;i++) {
1246 printf("x[%d]=%g, y[%d]=%g, exl[%d]=%g, exh[%d]=%g, eyl[%d]=%g, eyh[%d]=%g\n"
1247 ,i,fX[i],i,fY[i],i,fEXlow[i],i,fEXhigh[i],i,fEYlow[i],i,fEYhigh[i]);
1248 }
1249}
1250
1251
1252////////////////////////////////////////////////////////////////////////////////
1253/// Save primitive as a C++ statement(s) on output stream out.
1254
1255void TGraphAsymmErrors::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1256{
1257 auto xname = SavePrimitiveVector(out, "grae_fx", fNpoints, fX, kTRUE);
1258 auto yname = SavePrimitiveVector(out, "grae_fy", fNpoints, fY);
1259 auto exlname = SavePrimitiveVector(out, "grae_fexl", fNpoints, fEXlow, 111);
1260 auto exhname = SavePrimitiveVector(out, "grae_fexh", fNpoints, fEXhigh, 111);
1261 auto eylname = SavePrimitiveVector(out, "grae_feyl", fNpoints, fEYlow, 111);
1262 auto eyhname = SavePrimitiveVector(out, "grae_feyh", fNpoints, fEYhigh, 111);
1263
1264 SavePrimitiveConstructor(out, Class(), "grae",
1265 TString::Format("%d, %s.data(), %s.data(), %s, %s, %s, %s",
1266 fNpoints, xname.Data(), yname.Data(), exlname.Data(), exhname.Data(),
1267 eylname.Data(), eyhname.Data()),
1268 kFALSE);
1269
1270 SaveHistogramAndFunctions(out, "grae", option);
1271}
1272
1273////////////////////////////////////////////////////////////////////////////////
1274/// Multiply the values and errors of a TGraphAsymmErrors by a constant c1.
1275///
1276/// If option contains "x" the x values and errors are scaled
1277/// If option contains "y" the y values and errors are scaled
1278/// If option contains "xy" both x and y values and errors are scaled
1279
1281{
1283 TString opt = option; opt.ToLower();
1284 if (opt.Contains("x") && GetEXlow()) {
1285 for (Int_t i=0; i<GetN(); i++)
1286 GetEXlow()[i] *= c1;
1287 }
1288 if (opt.Contains("x") && GetEXhigh()) {
1289 for (Int_t i=0; i<GetN(); i++)
1290 GetEXhigh()[i] *= c1;
1291 }
1292 if (opt.Contains("y") && GetEYlow()) {
1293 for (Int_t i=0; i<GetN(); i++)
1294 GetEYlow()[i] *= c1;
1295 }
1296 if (opt.Contains("y") && GetEYhigh()) {
1297 for (Int_t i=0; i<GetN(); i++)
1298 GetEYhigh()[i] *= c1;
1299 }
1300}
1301
1302////////////////////////////////////////////////////////////////////////////////
1303/// Set ex and ey values for point pointed by the mouse.
1304
1306{
1307 if (!gPad) {
1308 Error("SetPointError", "Cannot be used without gPad, requires last mouse position");
1309 return;
1310 }
1311
1312 Int_t px = gPad->GetEventX();
1313 Int_t py = gPad->GetEventY();
1314
1315 //localize point to be deleted
1316 Int_t ipoint = -2;
1317 Int_t i;
1318 // start with a small window (in case the mouse is very close to one point)
1319 for (i=0;i<fNpoints;i++) {
1320 Int_t dpx = px - gPad->XtoAbsPixel(gPad->XtoPad(fX[i]));
1321 Int_t dpy = py - gPad->YtoAbsPixel(gPad->YtoPad(fY[i]));
1322 if (dpx*dpx+dpy*dpy < 25) {ipoint = i; break;}
1323 }
1324 if (ipoint == -2) return;
1325
1326 fEXlow[ipoint] = exl;
1327 fEYlow[ipoint] = eyl;
1328 fEXhigh[ipoint] = exh;
1329 fEYhigh[ipoint] = eyh;
1330 gPad->Modified();
1331}
1332
1333
1334////////////////////////////////////////////////////////////////////////////////
1335/// Set ex and ey values for point number i.
1336
1338{
1339 if (i < 0) return;
1340 if (i >= fNpoints) {
1341 // re-allocate the object
1343 }
1344 fEXlow[i] = exl;
1345 fEYlow[i] = eyl;
1346 fEXhigh[i] = exh;
1347 fEYhigh[i] = eyh;
1348}
1349
1350
1351////////////////////////////////////////////////////////////////////////////////
1352/// Set EXlow for point `i`.
1353
1355{
1356 if (i < 0) return;
1357 if (i >= fNpoints) {
1358 // re-allocate the object
1360 }
1361 fEXlow[i] = exl;
1362}
1363
1364
1365////////////////////////////////////////////////////////////////////////////////
1366/// Set EXhigh for point `i`.
1367
1369{
1370 if (i < 0) return;
1371 if (i >= fNpoints) {
1372 // re-allocate the object
1374 }
1375 fEXhigh[i] = exh;
1376}
1377
1378
1379////////////////////////////////////////////////////////////////////////////////
1380/// Set EYlow for point `i`.
1381
1383{
1384 if (i < 0) return;
1385 if (i >= fNpoints) {
1386 // re-allocate the object
1388 }
1389 fEYlow[i] = eyl;
1390}
1391
1392
1393////////////////////////////////////////////////////////////////////////////////
1394/// Set EYhigh for point `i`.
1395
1397{
1398 if (i < 0) return;
1399 if (i >= fNpoints) {
1400 // re-allocate the object
1402 }
1403 fEYhigh[i] = eyh;
1404}
1405
1406
1407////////////////////////////////////////////////////////////////////////////////
1408/// Stream an object of class TGraphAsymmErrors.
1409
1411{
1412 if (b.IsReading()) {
1413 UInt_t R__s, R__c;
1414 Version_t R__v = b.ReadVersion(&R__s, &R__c);
1415 if (R__v > 2) {
1416 b.ReadClassBuffer(TGraphAsymmErrors::Class(), this, R__v, R__s, R__c);
1417 return;
1418 }
1419 //====process old versions before automatic schema evolution
1421 fEXlow = new Double_t[fNpoints];
1422 fEYlow = new Double_t[fNpoints];
1423 fEXhigh = new Double_t[fNpoints];
1424 fEYhigh = new Double_t[fNpoints];
1425 if (R__v < 2) {
1426 Float_t *exlow = new Float_t[fNpoints];
1427 Float_t *eylow = new Float_t[fNpoints];
1430 b.ReadFastArray(exlow,fNpoints);
1431 b.ReadFastArray(eylow,fNpoints);
1432 b.ReadFastArray(exhigh,fNpoints);
1433 b.ReadFastArray(eyhigh,fNpoints);
1434 for (Int_t i=0;i<fNpoints;i++) {
1435 fEXlow[i] = exlow[i];
1436 fEYlow[i] = eylow[i];
1437 fEXhigh[i] = exhigh[i];
1438 fEYhigh[i] = eyhigh[i];
1439 }
1440 delete [] eylow;
1441 delete [] exlow;
1442 delete [] eyhigh;
1443 delete [] exhigh;
1444 } else {
1445 b.ReadFastArray(fEXlow,fNpoints);
1446 b.ReadFastArray(fEYlow,fNpoints);
1447 b.ReadFastArray(fEXhigh,fNpoints);
1448 b.ReadFastArray(fEYhigh,fNpoints);
1449 }
1450 b.CheckByteCount(R__s, R__c, TGraphAsymmErrors::IsA());
1451 //====end of old versions
1452
1453 } else {
1454 b.WriteClassBuffer(TGraphAsymmErrors::Class(),this);
1455 }
1456}
1457
1458
1459////////////////////////////////////////////////////////////////////////////////
1460/// Swap points.
1461
1470
1471////////////////////////////////////////////////////////////////////////////////
1472/// Update the fX, fY, fEXlow, fEXhigh, fEYlow and fEYhigh arrays with the sorted values.
1473
1475{
1476 std::vector<Double_t> fEXlowSorted(numSortedPoints);
1477 std::vector<Double_t> fEXhighSorted(numSortedPoints);
1478 std::vector<Double_t> fEYlowSorted(numSortedPoints);
1479 std::vector<Double_t> fEYhighSorted(numSortedPoints);
1480
1481 // Fill the sorted X and Y error values based on the sorted indices
1482 std::generate(fEXlowSorted.begin(), fEXlowSorted.end(),
1483 [begin = low, &sorting_indices, this]() mutable { return fEXlow[sorting_indices[begin++]]; });
1484 std::generate(fEXhighSorted.begin(), fEXhighSorted.end(),
1485 [begin = low, &sorting_indices, this]() mutable { return fEXhigh[sorting_indices[begin++]]; });
1486 std::generate(fEYlowSorted.begin(), fEYlowSorted.end(),
1487 [begin = low, &sorting_indices, this]() mutable { return fEYlow[sorting_indices[begin++]]; });
1488 std::generate(fEYhighSorted.begin(), fEYhighSorted.end(),
1489 [begin = low, &sorting_indices, this]() mutable { return fEYhigh[sorting_indices[begin++]]; });
1490
1491 // Copy the sorted X and Y error values back to the original arrays
1492 std::copy(fEXlowSorted.begin(), fEXlowSorted.end(), fEXlow + low);
1493 std::copy(fEXhighSorted.begin(), fEXhighSorted.end(), fEXhigh + low);
1494 std::copy(fEYlowSorted.begin(), fEYlowSorted.end(), fEYlow + low);
1495 std::copy(fEYhighSorted.begin(), fEYhighSorted.end(), fEYhigh + low);
1496
1498}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
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.
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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 Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format
float xmin
float ymin
float xmax
float ymax
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
#define gPad
const_iterator begin() const
const_iterator end() const
Buffer base class used for serializing objects.
Definition TBuffer.h:43
Collection abstract base class.
Definition TCollection.h:65
static Double_t BetaMode(Double_t alpha, Double_t beta)
Compute the mode of the beta distribution.
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 Double_t BetaMean(Double_t alpha, Double_t beta)
Compute the mean (average) of the beta distribution.
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.
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.
static Bool_t CheckBinning(const TH1 &pass, const TH1 &total)
Checks binning for each axis.
static Double_t BetaCentralInterval(Double_t level, Double_t alpha, Double_t beta, Bool_t bUpper)
Calculates the boundaries for a central confidence interval for a Beta distribution.
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.
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...
static Double_t Wilson(Double_t total, Double_t passed, Double_t level, Bool_t bUpper)
Calculates the boundaries for the frequentist Wilson interval.
static Bool_t CheckConsistency(const TH1 &pass, const TH1 &total, Option_t *opt="")
Checks the consistence of the given histograms.
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.
1-Dim function class
Definition TF1.h:182
TGraph with asymmetric error bars.
Double_t * GetEXlow() const override
virtual void SetPointEYlow(Int_t i, Double_t eyl)
Set EYlow for point i.
Double_t * fEXhigh
[fNpoints] array of X high errors
Double_t GetErrorY(Int_t bin) const override
Returns the combined error along Y at point i by computing the average of the lower and upper varianc...
void FillZero(Int_t begin, Int_t end, Bool_t from_ctor=kTRUE) override
Set zero values for point arrays in the range [begin, end]
virtual void Divide(const TH1 *pass, const TH1 *total, Option_t *opt="cp")
Fill this TGraphAsymmErrors by dividing two 1-dimensional histograms pass/total.
Bool_t CtorAllocate()
Should be called from ctors after fNpoints has been set.
static TClass * Class()
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 GetErrorXhigh(Int_t i) const override
Get high error on X.
Double_t * fEYhigh
[fNpoints] array of Y high errors
Bool_t CopyPoints(Double_t **arrays, Int_t ibegin, Int_t iend, Int_t obegin) override
Copy errors from fE*** to arrays[***] or to f*** Copy points.
virtual void AddPointError(Double_t x, Double_t y, Double_t exl=0., Double_t exh=0., Double_t eyl=0., Double_t eyh=0.)
Add a point with asymmetric errorbars to the graph.
void ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const override
Compute Range.
virtual void SetPointEXlow(Int_t i, Double_t exl)
Set EXlow for point i.
void Streamer(TBuffer &) override
Stream an object of class TGraphAsymmErrors.
virtual void SetPointEYhigh(Int_t i, Double_t eyh)
Set EYhigh for point i.
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitive as a C++ statement(s) on output stream out.
virtual void BayesDivide(const TH1 *pass, const TH1 *total, Option_t *opt="")
This function is only kept for backward compatibility.
Double_t * GetEYhigh() const override
void Print(Option_t *chopt="") const override
Print graph and errors values.
Double_t GetErrorYhigh(Int_t i) const override
Get high error on Y.
Int_t Merge(TCollection *list) override
Adds all graphs with asymmetric errors from the collection to this graph.
Double_t GetErrorXlow(Int_t i) const override
Get low error on X.
Double_t * fEYlow
[fNpoints] array of Y low errors
void UpdateArrays(const std::vector< Int_t > &sorting_indices, Int_t numSortedPoints, Int_t low) override
Update the fX, fY, fEXlow, fEXhigh, fEYlow and fEYhigh arrays with the sorted values.
void SwapPoints(Int_t pos1, Int_t pos2) override
Swap points.
Double_t * GetEXhigh() const override
Double_t * fEXlow
[fNpoints] array of X low errors
void Apply(TF1 *f) override
Apply a function to all data points .
Double_t ** Allocate(Int_t size) override
Allocate internal data structures for size points.
Double_t * GetEYlow() const override
Bool_t DoMerge(const TGraph *g) override
Protected function to perform the merge operation of a graph with asymmetric errors.
void CopyAndRelease(Double_t **newarrays, Int_t ibegin, Int_t iend, Int_t obegin) override
Copy and release.
TClass * IsA() const override
virtual void SetPointEXhigh(Int_t i, Double_t exh)
Set EXhigh for point i.
Double_t GetErrorYlow(Int_t i) const override
Get low error on Y.
Double_t GetErrorX(Int_t bin) const override
Returns the combined error along X at point i by computing the average of the lower and upper varianc...
TGraphAsymmErrors()
TGraphAsymmErrors default constructor.
TGraphAsymmErrors & operator=(const TGraphAsymmErrors &gr)
TGraphAsymmErrors assignment operator.
~TGraphAsymmErrors() override
TGraphAsymmErrors default destructor.
void Scale(Double_t c1=1., Option_t *option="y") override
Multiply the values and errors of a TGraphAsymmErrors by a constant c1.
static Int_t CalculateScanfFields(const char *fmt)
Calculate scan fields.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
virtual void AddPoint(Double_t x, Double_t y)
Append a new point to the graph.
Definition TGraph.h:97
Int_t fNpoints
Number of points <= fMaxSize.
Definition TGraph.h:46
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Set x and y values for point number i.
Definition TGraph.cxx:2384
Int_t fMaxSize
!Current dimension of arrays fX and fY
Definition TGraph.h:45
TH1F * fHistogram
Pointer to histogram used for drawing axis.
Definition TGraph.h:50
virtual void UpdateArrays(const std::vector< Int_t > &sorting_indices, Int_t numSortedPoints, Int_t low)
Update the fX and fY arrays with the sorted values.
Definition TGraph.cxx:2634
Int_t GetN() const
Definition TGraph.h:131
Double_t * fY
[fNpoints] array of Y points
Definition TGraph.h:48
Bool_t CtorAllocate()
In constructors set fNpoints than call this method.
Definition TGraph.cxx:833
virtual void ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
Compute the x/y range of the points in this graph.
Definition TGraph.cxx:759
Double_t ** AllocateArrays(Int_t Narrays, Int_t arraySize)
Allocate arrays.
Definition TGraph.cxx:626
virtual void Scale(Double_t c1=1., Option_t *option="y")
Multiply the values of a TGraph by a constant c1.
Definition TGraph.cxx:2294
static void SwapValues(Double_t *arr, Int_t pos1, Int_t pos2)
Swap values.
Definition TGraph.cxx:2653
void Streamer(TBuffer &) override
Stream an object of class TGraph.
Definition TGraph.cxx:2558
virtual Bool_t DoMerge(const TGraph *g)
protected function to perform the merge operation of a graph
Definition TGraph.cxx:2718
void SetName(const char *name="") override
Set graph name.
Definition TGraph.cxx:2423
virtual void SwapPoints(Int_t pos1, Int_t pos2)
Swap points.
Definition TGraph.cxx:2625
virtual void FillZero(Int_t begin, Int_t end, Bool_t from_ctor=kTRUE)
Set zero values for point arrays in the range [begin, end) Should be redefined in descendant classes.
Definition TGraph.cxx:1130
void SaveHistogramAndFunctions(std::ostream &out, const char *varname, Option_t *option)
Save histogram and list of functions of TGraph as C++ statement Used in all TGraph-derived classes.
Definition TGraph.cxx:2248
Double_t * fX
[fNpoints] array of X points
Definition TGraph.h:47
void SetTitle(const char *title="") override
Change (i.e.
Definition TGraph.cxx:2439
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:2312
virtual Int_t GetPoint(Int_t i, Double_t &x, Double_t &y) const
Get x and y values for point number i.
Definition TGraph.cxx:1560
virtual Bool_t CopyPoints(Double_t **newarrays, Int_t ibegin, Int_t iend, Int_t obegin)
Copy points from fX and fY to arrays[0] and arrays[1] or to fX and fY if arrays == 0 and ibegin !...
Definition TGraph.cxx:807
TGraph & operator=(const TGraph &)
Equal operator for this graph.
Definition TGraph.cxx:249
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1074
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1088
void MakeZombie()
Definition TObject.h:53
static void SavePrimitiveConstructor(std::ostream &out, TClass *cl, const char *variable_name, const char *constructor_agrs="", Bool_t empty_line=kTRUE)
Save object constructor in the output stream "out".
Definition TObject.cxx:771
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:790
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1062
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
@ kIgnoreCase
Definition TString.h:285
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Float_t GetErrorX() const
Definition TStyle.h:188
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1285
TVectorT.
Definition TVectorT.h:29
TLine * line
double normal_quantile_c(double z, double sigma)
Inverse ( ) of the cumulative distribution function of the upper tail of the normal (Gaussian) distri...
const Double_t sigma
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGraphErrors * gr
Definition legend1.C:25
Int_t Finite(Double_t x)
Check if it is finite with a mask in order to be consistent in presence of fast math.
Definition TMath.h:781
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122