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