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