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