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