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