Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGraphMultiErrors.cxx
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: Simon Spies 18/02/19
3 
4 /*************************************************************************
5  * Copyright (C) 2018-2019, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TROOT.h"
13 #include "TClass.h"
14 #include "TStyle.h"
15 #include "TVirtualPad.h"
16 #include "TEfficiency.h"
17 #include "Riostream.h"
18 
19 #include "TObject.h"
20 #include "TNamed.h"
21 #include "TAttLine.h"
22 #include "TAttFill.h"
23 #include "TAttMarker.h"
24 
25 #include "TArrayD.h"
26 #include "TVector.h"
27 #include "TH1.h"
28 #include "TF1.h"
29 #include "TMath.h"
30 #include "TGaxis.h"
31 #include "TVirtualGraphPainter.h"
32 #include "TGraphPainter.h"
33 #include "TBox.h"
34 #include "TArrow.h"
35 #include "Math/QuantFuncMathCore.h"
36 
37 #include "TGraphMultiErrors.h"
38 
39 ClassImp(TGraphMultiErrors)
40 
41 /** \class TGraphMultiErrors
42  \ingroup Hist
43 TGraph with asymmetric error bars and multiple y error dimensions.
44 
45 The TGraphMultiErrors painting is performed thanks to the TGraphPainter
46 class. All details about the various painting options are given in this class.
47 
48 The picture below gives an example:
49 
50 Begin_Macro(source)
51 {
52  auto c1 = new TCanvas("c1", "A Simple Graph with multiple y-errors", 200, 10, 700, 500);
53  c1->SetGrid();
54  c1->GetFrame()->SetBorderSize(12);
55  const Int_t np = 5;
56  Double_t x[np] = {0, 1, 2, 3, 4};
57  Double_t y[np] = {0, 2, 4, 1, 3};
58  Double_t exl[np] = {0.3, 0.3, 0.3, 0.3, 0.3};
59  Double_t exh[np] = {0.3, 0.3, 0.3, 0.3, 0.3};
60  Double_t eylstat[np] = {1, 0.5, 1, 0.5, 1};
61  Double_t eyhstat[np] = {0.5, 1, 0.5, 1, 2};
62  Double_t eylsys[np] = {0.5, 0.4, 0.8, 0.3, 1.2};
63  Double_t eyhsys[np] = {0.6, 0.7, 0.6, 0.4, 0.8};
64  auto gme = new TGraphMultiErrors("gme", "TGraphMultiErrors Example", np, x, y, exl, exh, eylstat, eyhstat);
65  gme->AddYError(np, eylsys, eyhsys);
66  gme->SetMarkerStyle(20);
67  gme->SetLineColor(kRed);
68  gme->GetAttLine(0)->SetLineColor(kRed);
69  gme->GetAttLine(1)->SetLineColor(kBlue);
70  gme->GetAttFill(1)->SetFillStyle(0);
71  gme->Draw("APS ; Z ; 5 s=0.5");
72 }
73 End_Macro
74 */
75 ////////////////////////////////////////////////////////////////////////////////
76 /// TGraphMultiErrors default constructor.
77 
78 TGraphMultiErrors::TGraphMultiErrors()
79  : TGraph(), fNYErrors(0), fSumErrorsMode(TGraphMultiErrors::kOnlyFirst), fExL(nullptr), fExH(nullptr)
80 {
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 /// TGraphMultiErrors default constructor with name and title.
85 
86 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title) : TGraphMultiErrors()
87 {
88  SetNameTitle(name, title);
89 }
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 /// TGraphMultiErrors normal constructor with np points and ne y-errors.
93 ///
94 /// All values are initialized to 0.
95 
96 TGraphMultiErrors::TGraphMultiErrors(Int_t np, Int_t ne)
97  : TGraph(np), fNYErrors(ne), fSumErrorsMode(TGraphMultiErrors::kOnlyFirst)
98 {
99  CtorAllocate();
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 /// TGraphMultiErrors normal constructor with name, title, np points and ne y-errors.
104 ///
105 /// All values are initialized to 0.
106 
107 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title, Int_t np, Int_t ne)
108  : TGraphMultiErrors(np, ne)
109 {
110  SetNameTitle(name, title);
111 }
112 
113 ////////////////////////////////////////////////////////////////////////////////
114 /// TGraphMultiErrors normal constructor with np points and a single y-error.
115 ///
116 /// The signature of this constructor is equal to the corresponding constructor of TGraphAsymmErrors.
117 /// If exL,H or eyL,H are NULL, the corresponding values are preset to zero.
118 
119 TGraphMultiErrors::TGraphMultiErrors(Int_t np, const Float_t *x, const Float_t *y, const Float_t *exL,
120  const Float_t *exH, const Float_t *eyL, const Float_t *eyH, Int_t m)
121  : TGraph(np, x, y), fNYErrors(1), fSumErrorsMode(m)
122 {
123  if (!CtorAllocate())
124  return;
125 
126  for (Int_t i = 0; i < fNpoints; i++) {
127  if (exL)
128  fExL[i] = exL[i];
129  else
130  fExL[i] = 0.;
131  if (exH)
132  fExH[i] = exH[i];
133  else
134  fExH[i] = 0.;
135  if (eyL)
136  fEyL[0][i] = eyL[i];
137  else
138  fEyL[0][i] = 0.;
139  if (eyH)
140  fEyH[0][i] = eyH[i];
141  else
142  fEyH[0][i] = 0.;
143  }
144 
145  CalcYErrorsSum();
146 }
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// TGraphMultiErrors normal constructor with name, title, np points and a single y-error.
150 ///
151 /// If exL,H or eyL,H are NULL, the corresponding values are preset to zero.
152 
153 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title, Int_t np, const Float_t *x,
154  const Float_t *y, const Float_t *exL, const Float_t *exH, const Float_t *eyL,
155  const Float_t *eyH, Int_t m)
156  : TGraphMultiErrors(np, x, y, exL, exH, eyL, eyH, m)
157 {
158  SetNameTitle(name, title);
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// TGraphMultiErrors normal constructor with np points and a single y-error.
163 ///
164 /// The signature of this constructor is equal to the corresponding constructor of TGraphAsymmErrors.
165 /// If exL,H or eyL,H are NULL, the corresponding values are preset to zero.
166 
167 TGraphMultiErrors::TGraphMultiErrors(Int_t np, const Double_t *x, const Double_t *y, const Double_t *exL,
168  const Double_t *exH, const Double_t *eyL, const Double_t *eyH, Int_t m)
169  : TGraph(np, x, y), fNYErrors(1), fSumErrorsMode(m)
170 {
171  if (!CtorAllocate())
172  return;
173 
174  Int_t n = fNpoints * sizeof(Double_t);
175 
176  if (exL)
177  memcpy(fExL, exL, n);
178  else
179  memset(fExL, 0, n);
180  if (exH)
181  memcpy(fExH, exH, n);
182  else
183  memset(fExH, 0, n);
184 
185  if (eyL)
186  fEyL[0].Set(fNpoints, eyL);
187  else
188  fEyL[0].Reset(0.);
189 
190  if (eyH)
191  fEyH[0].Set(fNpoints, eyH);
192  else
193  fEyH[0].Reset(0.);
194 
195  CalcYErrorsSum();
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// TGraphMultiErrors normal constructor with name, title, np points and a single y-error.
200 ///
201 /// If exL,H or eyL,H are NULL, the corresponding values are preset to zero.
202 
203 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title, Int_t np, const Double_t *x,
204  const Double_t *y, const Double_t *exL, const Double_t *exH, const Double_t *eyL,
205  const Double_t *eyH, Int_t m)
206  : TGraphMultiErrors(np, x, y, exL, exH, eyL, eyH, m)
207 {
208  SetNameTitle(name, title);
209 }
210 
211 ////////////////////////////////////////////////////////////////////////////////
212 /// TGraphMultiErrors normal constructor with np points and ne y-errors.
213 ///
214 /// If exL,H are NULL, the corresponding values are preset to zero.
215 /// The multiple y-errors are passed as std::vectors of std::vectors.
216 
217 TGraphMultiErrors::TGraphMultiErrors(Int_t np, Int_t ne, const Float_t *x, const Float_t *y, const Float_t *exL,
218  const Float_t *exH, std::vector<std::vector<Float_t>> eyL,
219  std::vector<std::vector<Float_t>> eyH, Int_t m)
220  : TGraph(np, x, y), fNYErrors(ne), fSumErrorsMode(m)
221 {
222  if (!CtorAllocate())
223  return;
224 
225  for (Int_t i = 0; i < fNpoints; i++) {
226  if (exL)
227  fExL[i] = exL[i];
228  else
229  fExL[i] = 0.;
230  if (exH)
231  fExH[i] = exH[i];
232  else
233  fExH[i] = 0.;
234 
235  for (Int_t j = 0; j < fNYErrors; j++) {
236  if (Int_t(eyL.size()) > j && Int_t(eyL[j].size()) > i)
237  fEyL[j][i] = eyL[j][i];
238  else
239  fEyL[j][i] = 0.;
240  if (Int_t(eyH.size()) > j && Int_t(eyH[j].size()) > i)
241  fEyH[j][i] = eyH[j][i];
242  else
243  fEyH[j][i] = 0.;
244  }
245  }
246 
247  CalcYErrorsSum();
248 }
249 
250 ////////////////////////////////////////////////////////////////////////////////
251 /// TGraphMultiErrors normal constructor with name, title, np points and ne y-errors.
252 ///
253 /// If exL,H are NULL, the corresponding values are preset to zero.
254 /// The multiple y-errors are passed as std::vectors of std::vectors.
255 
256 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title, Int_t np, Int_t ne, const Float_t *x,
257  const Float_t *y, const Float_t *exL, const Float_t *exH,
258  std::vector<std::vector<Float_t>> eyL, std::vector<std::vector<Float_t>> eyH,
259  Int_t m)
260  : TGraphMultiErrors(np, ne, x, y, exL, exH, eyL, eyH, m)
261 {
262  SetNameTitle(name, title);
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// TGraphMultiErrors normal constructor with np points and ne y-errors.
267 ///
268 /// If exL,H are NULL, the corresponding values are preset to zero.
269 /// The multiple y-errors are passed as std::vectors of std::vectors.
270 
271 TGraphMultiErrors::TGraphMultiErrors(Int_t np, Int_t ne, const Double_t *x, const Double_t *y, const Double_t *exL,
272  const Double_t *exH, std::vector<std::vector<Double_t>> eyL,
273  std::vector<std::vector<Double_t>> eyH, Int_t m)
274  : TGraph(np, x, y), fNYErrors(ne), fSumErrorsMode(m)
275 {
276  if (!CtorAllocate())
277  return;
278 
279  Int_t n = fNpoints * sizeof(Double_t);
280 
281  if (exL)
282  memcpy(fExL, exL, n);
283  else
284  memset(fExL, 0, n);
285  if (exH)
286  memcpy(fExH, exH, n);
287  else
288  memset(fExH, 0, n);
289 
290  for (Int_t i = 0; i < fNpoints; i++) {
291  for (Int_t j = 0; j < fNYErrors; j++) {
292  if (Int_t(eyL.size()) > j && Int_t(eyL[j].size()) > i)
293  fEyL[j][i] = eyL[j][i];
294  else
295  fEyL[j][i] = 0.;
296  if (Int_t(eyH.size()) > j && Int_t(eyH[j].size()) > i)
297  fEyH[j][i] = eyH[j][i];
298  else
299  fEyH[j][i] = 0.;
300  }
301  }
302 
303  CalcYErrorsSum();
304 }
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 /// TGraphMultiErrors normal constructor with name, title, np points and ne y-errors.
308 ///
309 /// If exL,H are NULL, the corresponding values are preset to zero.
310 /// The multiple y-errors are passed as std::vectors of std::vectors.
311 
312 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title, Int_t np, Int_t ne, const Double_t *x,
313  const Double_t *y, const Double_t *exL, const Double_t *exH,
314  std::vector<std::vector<Double_t>> eyL, std::vector<std::vector<Double_t>> eyH,
315  Int_t m)
316  : TGraphMultiErrors(np, ne, x, y, exL, exH, eyL, eyH, m)
317 {
318  SetNameTitle(name, title);
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// TGraphMultiErrors normal constructor with np points and ne y-errors.
323 ///
324 /// If exL,H are NULL, the corresponding values are preset to zero.
325 /// The multiple y-errors are passed as std::vectors of TArrayF objects.
326 
327 TGraphMultiErrors::TGraphMultiErrors(Int_t np, Int_t ne, const Float_t *x, const Float_t *y, const Float_t *exL,
328  const Float_t *exH, std::vector<TArrayF> eyL, std::vector<TArrayF> eyH, Int_t m)
329  : TGraph(np, x, y), fNYErrors(ne), fSumErrorsMode(m)
330 {
331  if (!CtorAllocate())
332  return;
333 
334  for (Int_t i = 0; i < fNpoints; i++) {
335  if (exL)
336  fExL[i] = exL[i];
337  else
338  fExL[i] = 0.;
339  if (exH)
340  fExH[i] = exH[i];
341  else
342  fExH[i] = 0.;
343 
344  for (Int_t j = 0; j < fNYErrors; j++) {
345  if (Int_t(eyL.size()) > j && eyL[j].GetSize() > i)
346  fEyL[j][i] = eyL[j][i];
347  else
348  fEyL[j][i] = 0.;
349  if (Int_t(eyH.size()) > j && eyH[j].GetSize() > i)
350  fEyH[j][i] = eyH[j][i];
351  else
352  fEyH[j][i] = 0.;
353  }
354  }
355 
356  CalcYErrorsSum();
357 }
358 
359 ////////////////////////////////////////////////////////////////////////////////
360 /// TGraphMultiErrors normal constructor with name, title, np points and ne y-errors.
361 ///
362 /// If exL,H are NULL, the corresponding values are preset to zero.
363 /// The multiple y-errors are passed as std::vectors of TArrayF objects.
364 
365 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title, Int_t np, Int_t ne, const Float_t *x,
366  const Float_t *y, const Float_t *exL, const Float_t *exH, std::vector<TArrayF> eyL,
367  std::vector<TArrayF> eyH, Int_t m)
368  : TGraphMultiErrors(np, ne, x, y, exL, exH, eyL, eyH, m)
369 {
370  SetNameTitle(name, title);
371 }
372 
373 ////////////////////////////////////////////////////////////////////////////////
374 /// TGraphMultiErrors normal constructor with np points and ne y-errors.
375 ///
376 /// If exL,H are NULL, the corresponding values are preset to zero.
377 /// The multiple y-errors are passed as std::vectors of TArrayD objects.
378 
379 TGraphMultiErrors::TGraphMultiErrors(Int_t np, Int_t ne, const Double_t *x, const Double_t *y, const Double_t *exL,
380  const Double_t *exH, std::vector<TArrayD> eyL, std::vector<TArrayD> eyH, Int_t m)
381  : TGraph(np, x, y), fNYErrors(ne), fSumErrorsMode(m)
382 {
383  if (!CtorAllocate())
384  return;
385 
386  Int_t n = fNpoints * sizeof(Double_t);
387 
388  if (exL)
389  memcpy(fExL, exL, n);
390  else
391  memset(fExL, 0, n);
392  if (exH)
393  memcpy(fExH, exH, n);
394  else
395  memset(fExH, 0, n);
396 
397  for (Int_t i = 0; i < fNpoints; i++) {
398  for (Int_t j = 0; j < fNYErrors; j++) {
399  if (Int_t(eyL.size()) > j && eyL[j].GetSize() > i)
400  fEyL[j][i] = eyL[j][i];
401  else
402  fEyL[j][i] = 0.;
403  if (Int_t(eyH.size()) > j && eyH[j].GetSize() > i)
404  fEyH[j][i] = eyH[j][i];
405  else
406  fEyH[j][i] = 0.;
407  }
408  }
409 
410  CalcYErrorsSum();
411 }
412 
413 ////////////////////////////////////////////////////////////////////////////////
414 /// TGraphMultiErrors normal constructor with name, title, np points and ne y-errors.
415 ///
416 /// If exL,H are NULL, the corresponding values are preset to zero.
417 /// The multiple y-errors are passed as std::vectors of TArrayD objects.
418 
419 TGraphMultiErrors::TGraphMultiErrors(const Char_t *name, const Char_t *title, Int_t np, Int_t ne, const Double_t *x,
420  const Double_t *y, const Double_t *exL, const Double_t *exH,
421  std::vector<TArrayD> eyL, std::vector<TArrayD> eyH, Int_t m)
422  : TGraphMultiErrors(np, ne, x, y, exL, exH, eyL, eyH, m)
423 {
424  SetNameTitle(name, title);
425 }
426 
427 ////////////////////////////////////////////////////////////////////////////////
428 /// Constructor with six vectors of floats in input and a single y error dimension
429 /// The signature of this constructor is equal to the corresponding constructor of TGraphAsymmErrors.
430 /// A grapherrors is built with the X coordinates taken from tvX and Y coord from tvY
431 /// and the errors from vectors tvExL/H and tvEyL/H.
432 /// The number of points in the graph is the minimum of number of points
433 /// in tvX and tvY.
434 
435 TGraphMultiErrors::TGraphMultiErrors(const TVectorF &tvX, const TVectorF &tvY, const TVectorF &tvExL,
436  const TVectorF &tvExH, const TVectorF &tvEyL, const TVectorF &tvEyH, Int_t m)
437  : TGraph(), fNYErrors(1), fSumErrorsMode(m)
438 {
439  fNpoints = TMath::Min(tvX.GetNrows(), tvY.GetNrows());
440 
441  if (!TGraph::CtorAllocate())
442  return;
443 
444  if (!CtorAllocate())
445  return;
446 
447  Int_t itvXL = tvX.GetLwb();
448  Int_t itvYL = tvY.GetLwb();
449  Int_t itvExLL = tvExL.GetLwb();
450  Int_t itvExHL = tvExH.GetLwb();
451  Int_t itvEyLL = tvEyL.GetLwb();
452  Int_t itvEyHL = tvEyH.GetLwb();
453 
454  for (Int_t i = 0; i < fNpoints; i++) {
455  fX[i] = tvX(itvXL + i);
456  fY[i] = tvY(itvYL + i);
457  fExL[i] = tvExL(itvExLL + i);
458  fExH[i] = tvExH(itvExHL + i);
459  fEyL[0][i] = tvEyL(itvEyLL + i);
460  fEyH[0][i] = tvEyH(itvEyHL + i);
461  }
462 
463  CalcYErrorsSum();
464 }
465 
466 ////////////////////////////////////////////////////////////////////////////////
467 /// Constructor with six vectors of doubles in input and a single y error dimension
468 /// The signature of this constructor is equal to the corresponding constructor of TGraphAsymmErrors.
469 /// A grapherrors is built with the X coordinates taken from tvX and Y coord from tvY
470 /// and the errors from vectors tvExL/H and tvEyL/H.
471 /// The number of points in the graph is the minimum of number of points
472 /// in tvX and tvY.
473 
474 TGraphMultiErrors::TGraphMultiErrors(const TVectorD &tvX, const TVectorD &tvY, const TVectorD &tvExL,
475  const TVectorD &tvExH, const TVectorD &tvEyL, const TVectorD &tvEyH, Int_t m)
476  : TGraph(), fNYErrors(1), fSumErrorsMode(m)
477 {
478  fNpoints = TMath::Min(tvX.GetNrows(), tvY.GetNrows());
479 
480  if (!TGraph::CtorAllocate())
481  return;
482 
483  if (!CtorAllocate())
484  return;
485 
486  Int_t itvXL = tvX.GetLwb();
487  Int_t itvYL = tvY.GetLwb();
488  Int_t itvExLL = tvExL.GetLwb();
489  Int_t itvExHL = tvExH.GetLwb();
490  Int_t itvEyLL = tvEyL.GetLwb();
491  Int_t itvEyHL = tvEyH.GetLwb();
492 
493  for (Int_t i = 0; i < fNpoints; i++) {
494  fX[i] = tvX(i + itvXL);
495  fY[i] = tvY(i + itvYL);
496  fExL[i] = tvExL(i + itvExLL);
497  fExH[i] = tvExH(i + itvExHL);
498  fEyL[0][i] = tvEyL(i + itvEyLL);
499  fEyH[0][i] = tvEyH(i + itvEyHL);
500  }
501 
502  CalcYErrorsSum();
503 }
504 
505 ////////////////////////////////////////////////////////////////////////////////
506 /// Constructor with multiple vectors of floats in input and multiple y error dimensions
507 /// A grapherrors is built with the X coordinates taken from tvX and Y coord from tvY
508 /// and the errors from vectors tvExL/H and tvEyL/H[yErrorDimension].
509 /// The number of points in the graph is the minimum of number of points
510 /// in tvX and tvY.
511 
512 TGraphMultiErrors::TGraphMultiErrors(Int_t ne, const TVectorF &tvX, const TVectorF &tvY, const TVectorF &tvExL,
513  const TVectorF &tvExH, const TVectorF *tvEyL, const TVectorF *tvEyH, Int_t m)
514  : TGraph(), fNYErrors(ne), fSumErrorsMode(m)
515 {
516  fNpoints = TMath::Min(tvX.GetNrows(), tvY.GetNrows());
517 
518  if (!TGraph::CtorAllocate())
519  return;
520 
521  if (!CtorAllocate())
522  return;
523 
524  Int_t itvXL = tvX.GetLwb();
525  Int_t itvYL = tvY.GetLwb();
526  Int_t itvExLL = tvExL.GetLwb();
527  Int_t itvExHL = tvExH.GetLwb();
528 
529  for (Int_t i = 0; i < fNpoints; i++) {
530  fX[i] = tvX(i + itvXL);
531  fY[i] = tvY(i + itvYL);
532  fExL[i] = tvExL(i + itvExLL);
533  fExH[i] = tvExH(i + itvExHL);
534 
535  for (Int_t j = 0; j < ne; j++) {
536  fEyL[j][i] = tvEyL[j](i + tvEyL[j].GetLwb());
537  fEyH[j][i] = tvEyH[j](i + tvEyH[j].GetLwb());
538  }
539  }
540 
541  CalcYErrorsSum();
542 }
543 
544 ////////////////////////////////////////////////////////////////////////////////
545 /// Constructor with multiple vectors of doubles in input and multiple y error dimensions
546 /// A grapherrors is built with the X coordinates taken from tvX and Y coord from tvY
547 /// and the errors from vectors tvExL/H and tvEyL/H[yErrorDimension].
548 /// The number of points in the graph is the minimum of number of points
549 /// in tvX and tvY.
550 
551 TGraphMultiErrors::TGraphMultiErrors(Int_t ne, const TVectorD &tvX, const TVectorD &tvY, const TVectorD &tvExL,
552  const TVectorD &tvExH, const TVectorD *tvEyL, const TVectorD *tvEyH, Int_t m)
553  : TGraph(), fNYErrors(ne), fSumErrorsMode(m)
554 {
555  fNpoints = TMath::Min(tvX.GetNrows(), tvY.GetNrows());
556 
557  if (!TGraph::CtorAllocate())
558  return;
559 
560  if (!CtorAllocate())
561  return;
562 
563  Int_t itvXL = tvX.GetLwb();
564  Int_t itvYL = tvY.GetLwb();
565  Int_t itvExLL = tvExL.GetLwb();
566  Int_t itvExHL = tvExH.GetLwb();
567 
568  for (Int_t i = 0; i < fNpoints; i++) {
569  fX[i] = tvX(i + itvXL);
570  fY[i] = tvY(i + itvYL);
571  fExL[i] = tvExL(i + itvExLL);
572  fExH[i] = tvExH(i + itvExHL);
573 
574  for (Int_t j = 0; j < ne; j++) {
575  fEyL[j][i] = tvEyL[j](i + tvEyL[j].GetLwb());
576  fEyH[j][i] = tvEyH[j](i + tvEyH[j].GetLwb());
577  }
578  }
579 
580  CalcYErrorsSum();
581 }
582 
583 ////////////////////////////////////////////////////////////////////////////////
584 /// TGraphMultiErrors copy constructor
585 
586 TGraphMultiErrors::TGraphMultiErrors(const TGraphMultiErrors &tgme) : TGraph(tgme)
587 {
588  fNYErrors = tgme.fNYErrors;
589  fSumErrorsMode = tgme.fSumErrorsMode;
590 
591  if (!CtorAllocate())
592  return;
593 
594  Int_t n = fNpoints * sizeof(Double_t);
595  memcpy(fExL, tgme.fExL, n);
596  memcpy(fExH, tgme.fExH, n);
597 
598  for (Int_t j = 0; j < fNYErrors; j++) {
599  fEyL[j] = tgme.fEyL[j];
600  fEyH[j] = tgme.fEyH[j];
601  tgme.fAttFill[j].Copy(fAttFill[j]);
602  tgme.fAttLine[j].Copy(fAttLine[j]);
603  }
604 
605  CalcYErrorsSum();
606 }
607 
608 ////////////////////////////////////////////////////////////////////////////////
609 /// TGraphMultiErrors assignment operator
610 
611 TGraphMultiErrors &TGraphMultiErrors::operator=(const TGraphMultiErrors &tgme)
612 {
613  if (this != &tgme) {
614  TGraph::operator=(tgme);
615  // delete arrays
616  if (fExL)
617  delete[] fExL;
618  if (fExH)
619  delete[] fExH;
620  if (fEyLSum)
621  delete[] fEyLSum;
622  if (fEyHSum)
623  delete[] fEyHSum;
624 
625  fNYErrors = tgme.fNYErrors;
626  fSumErrorsMode = tgme.fSumErrorsMode;
627 
628  if (!CtorAllocate())
629  return *this;
630 
631  Int_t n = fNpoints * sizeof(Double_t);
632  memcpy(fExL, tgme.fExL, n);
633  memcpy(fExH, tgme.fExH, n);
634  memcpy(fEyLSum, tgme.fEyLSum, n);
635  memcpy(fEyHSum, tgme.fEyHSum, n);
636 
637  for (Int_t j = 0; j < fNYErrors; j++) {
638  fEyL[j] = tgme.fEyL[j];
639  fEyH[j] = tgme.fEyH[j];
640  tgme.fAttFill[j].Copy(fAttFill[j]);
641  tgme.fAttLine[j].Copy(fAttLine[j]);
642  }
643  }
644  return *this;
645 }
646 
647 ////////////////////////////////////////////////////////////////////////////////
648 /// TGraphMultiErrors constructor importing its parameters from the TH1 object passed as argument
649 /// the low and high errors are set to the bin error of the histogram.
650 
651 TGraphMultiErrors::TGraphMultiErrors(const TH1 *h, Int_t ne)
652  : TGraph(h), fNYErrors(ne), fSumErrorsMode(TGraphMultiErrors::kOnlyFirst)
653 {
654  if (!CtorAllocate())
655  return;
656 
657  for (Int_t i = 0; i < fNpoints; i++) {
658  fExL[i] = h->GetBinWidth(i + 1) * gStyle->GetErrorX();
659  fExH[i] = h->GetBinWidth(i + 1) * gStyle->GetErrorX();
660  fEyL[0][i] = h->GetBinError(i + 1);
661  fEyH[0][i] = h->GetBinError(i + 1);
662 
663  for (Int_t j = 1; j < fNYErrors; j++) {
664  fEyL[j][i] = 0.;
665  fEyH[j][i] = 0.;
666  }
667  }
668 
669  CalcYErrorsSum();
670 
671  TAttFill::Copy(fAttFill[0]);
672  TAttLine::Copy(fAttLine[0]);
673 }
674 
675 ////////////////////////////////////////////////////////////////////////////////
676 /// Creates a TGraphMultiErrors by dividing two input TH1 histograms:
677 /// pass/total. (see TGraphMultiErrors::Divide)
678 
679 TGraphMultiErrors::TGraphMultiErrors(const TH1 *pass, const TH1 *total, Int_t ne, Option_t *option)
680  : TGraph(pass ? pass->GetNbinsX() : 0), fNYErrors(ne), fSumErrorsMode(TGraphMultiErrors::kOnlyFirst)
681 {
682  if (!pass || !total) {
683  Error("TGraphMultiErrors", "Invalid histogram pointers");
684  return;
685  }
686 
687  if (!CtorAllocate())
688  return;
689 
690  std::string sname = "divide_" + std::string(pass->GetName()) + "_by_" + std::string(total->GetName());
691  SetName(sname.c_str());
692  SetTitle(pass->GetTitle());
693 
694  // copy style from pass
695  pass->TAttLine::Copy(*this);
696  pass->TAttFill::Copy(*this);
697  pass->TAttMarker::Copy(*this);
698 
699  Divide(pass, total, option);
700  CalcYErrorsSum();
701 
702  TAttFill::Copy(fAttFill[0]);
703  TAttLine::Copy(fAttLine[0]);
704 }
705 
706 ////////////////////////////////////////////////////////////////////////////////
707 /// TGraphMultiErrors default destructor.
708 
709 TGraphMultiErrors::~TGraphMultiErrors()
710 {
711  if (fExL)
712  delete[] fExL;
713  if (fExH)
714  delete[] fExH;
715  fEyL.resize(0);
716  fEyH.resize(0);
717  if (fEyLSum)
718  delete[] fEyLSum;
719  if (fEyHSum)
720  delete[] fEyHSum;
721  fAttFill.resize(0);
722  fAttLine.resize(0);
723 }
724 
725 ////////////////////////////////////////////////////////////////////////////////
726 /// Should be called from ctors after fNpoints has been set
727 /// Note: This function should be called only from the constructor
728 /// since it does not delete previously existing arrays
729 
730 Bool_t TGraphMultiErrors::CtorAllocate()
731 {
732  if (!fNpoints || !fNYErrors) {
733  fExL = fExH = nullptr;
734  fEyL.resize(0);
735  fEyH.resize(0);
736  return kFALSE;
737  }
738 
739  fExL = new Double_t[fMaxSize];
740  fExH = new Double_t[fMaxSize];
741  fEyL.resize(fNYErrors, TArrayD(fMaxSize));
742  fEyH.resize(fNYErrors, TArrayD(fMaxSize));
743  fEyLSum = new Double_t[fMaxSize];
744  fEyHSum = new Double_t[fMaxSize];
745  fAttFill.resize(fNYErrors);
746  fAttLine.resize(fNYErrors);
747 
748  Int_t n = fMaxSize * sizeof(Double_t);
749  memset(fExL, 0, n);
750  memset(fExH, 0, n);
751  memset(fEyLSum, 0, n);
752  memset(fEyHSum, 0, n);
753 
754  return kTRUE;
755 }
756 
757 ////////////////////////////////////////////////////////////////////////////////
758 /// Copy and release.
759 
760 void TGraphMultiErrors::CopyAndRelease(Double_t **newarrays, Int_t ibegin, Int_t iend, Int_t obegin)
761 {
762  CopyPoints(newarrays, ibegin, iend, obegin);
763  if (newarrays) {
764  delete[] fX;
765  fX = newarrays[0];
766  delete[] fY;
767  fY = newarrays[1];
768 
769  delete[] fExL;
770  fExL = newarrays[2];
771  delete[] fExH;
772  fExH = newarrays[3];
773 
774  if (fEyLSum)
775  delete[] fEyLSum;
776  fEyLSum = newarrays[4];
777  if (fEyHSum)
778  delete[] fEyHSum;
779  fEyHSum = newarrays[5];
780 
781  delete[] newarrays;
782  }
783 }
784 
785 ////////////////////////////////////////////////////////////////////////////////
786 /// Copy errors from fE*** to arrays[***]
787 /// or to f*** Copy points.
788 
789 Bool_t TGraphMultiErrors::CopyPoints(Double_t **arrays, Int_t ibegin, Int_t iend, Int_t obegin)
790 {
791  if (TGraph::CopyPoints(arrays, ibegin, iend, obegin)) {
792  Int_t n = (iend - ibegin) * sizeof(Double_t);
793 
794  if (arrays) {
795  memmove(&arrays[2][obegin], &fExL[ibegin], n);
796  memmove(&arrays[3][obegin], &fExH[ibegin], n);
797  memmove(&arrays[4][obegin], &fEyLSum[ibegin], n);
798  memmove(&arrays[5][obegin], &fEyHSum[ibegin], n);
799  } else {
800  memmove(&fExL[obegin], &fExL[ibegin], n);
801  memmove(&fExH[obegin], &fExH[ibegin], n);
802  memmove(&fEyLSum[obegin], &fEyLSum[ibegin], n);
803  memmove(&fEyHSum[obegin], &fEyHSum[ibegin], n);
804  }
805 
806  return kTRUE;
807  } else
808  return kFALSE;
809 }
810 
811 ////////////////////////////////////////////////////////////////////////////////
812 /// Set zero values for point arrays in the range [begin, end)
813 
814 void TGraphMultiErrors::FillZero(Int_t begin, Int_t end, Bool_t from_ctor)
815 {
816  if (!from_ctor)
817  TGraph::FillZero(begin, end, from_ctor);
818 
819  Int_t n = (end - begin) * sizeof(Double_t);
820  memset(fExL + begin, 0, n);
821  memset(fExH + begin, 0, n);
822  memset(fEyLSum + begin, 0, n);
823  memset(fEyHSum + begin, 0, n);
824 
825  for (Int_t j = 0; j < fNYErrors; j++) {
826  memset(fEyL[j].GetArray() + begin, 0, n);
827  memset(fEyH[j].GetArray() + begin, 0, n);
828  }
829 }
830 
831 ////////////////////////////////////////////////////////////////////////////////
832 /// Recalculates the summed y error arrays
833 
834 void TGraphMultiErrors::CalcYErrorsSum() const
835 {
836  if (!fEyLSum)
837  fEyLSum = new Double_t[fNpoints];
838  if (!fEyHSum)
839  fEyHSum = new Double_t[fNpoints];
840 
841  for (Int_t i = 0; i < fNpoints; i++) {
842  fEyLSum[i] = GetErrorYlow(i);
843  fEyHSum[i] = GetErrorYhigh(i);
844  }
845 }
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// protected function to perform the merge operation of a graph with multiple asymmetric errors
849 
850 Bool_t TGraphMultiErrors::DoMerge(const TGraph *tg)
851 {
852  if (tg->GetN() == 0)
853  return kFALSE;
854 
855  if (tg->IsA() == TGraphMultiErrors::Class()) {
856  auto tgme = (TGraphMultiErrors *)tg;
857 
858  for (Int_t i = 0; i < tgme->GetN(); i++) {
859  Int_t ipoint = GetN();
860  Double_t x, y;
861  tgme->GetPoint(i, x, y);
862  SetPoint(ipoint, x, y);
863  SetPointEX(ipoint, tgme->GetErrorXlow(i), tgme->GetErrorXhigh(i));
864  for (Int_t j = 0; j < tgme->GetNYErrors(); j++)
865  SetPointEY(ipoint, j, tgme->GetErrorYlow(i, j), tgme->GetErrorYhigh(i, j));
866  }
867 
868  return kTRUE;
869  } else {
870  Warning("DoMerge", "Merging a %s is not compatible with a TGraphMultiErrors - Errors will be ignored",
871  tg->IsA()->GetName());
872  return TGraph::DoMerge(tg);
873  }
874 
875  return kFALSE;
876 }
877 
878 ////////////////////////////////////////////////////////////////////////////////
879 /// Swap points.
880 
881 void TGraphMultiErrors::SwapPoints(Int_t pos1, Int_t pos2)
882 {
883  SwapValues(fExL, pos1, pos2);
884  SwapValues(fExH, pos1, pos2);
885 
886  for (Int_t j = 0; j <= fNYErrors; j++) {
887  SwapValues(fEyL[j].GetArray(), pos1, pos2);
888  SwapValues(fEyH[j].GetArray(), pos1, pos2);
889  }
890 
891  TGraph::SwapPoints(pos1, pos2);
892 }
893 
894 ////////////////////////////////////////////////////////////////////////////////
895 /// Add a new y error to the graph and fill it with the values from eyL and eyH
896 
897 void TGraphMultiErrors::AddYError(Int_t np, const Double_t *eyL, const Double_t *eyH)
898 {
899  fEyL.emplace_back(np, eyL);
900  fEyH.emplace_back(np, eyH);
901  fEyL.back().Set(fNpoints);
902  fEyH.back().Set(fNpoints);
903  fAttFill.emplace_back();
904  fAttLine.emplace_back();
905 
906  fNYErrors += 1;
907 
908  CalcYErrorsSum();
909 }
910 
911 ////////////////////////////////////////////////////////////////////////////////
912 /// Allocate internal data structures for `size` points.
913 Double_t **TGraphMultiErrors::Allocate(Int_t size)
914 {
915  return AllocateArrays(6, size);
916 }
917 
918 ////////////////////////////////////////////////////////////////////////////////
919 /// Apply a function to all data points `y = f(x,y)`
920 ///
921 /// Errors are calculated as `eyh = f(x,y+eyh)-f(x,y)` and
922 /// `eyl = f(x,y)-f(x,y-eyl)`
923 /// Only the first error dimension is affected!!!
924 ///
925 /// Special treatment has to be applied for the functions where the
926 /// role of "up" and "down" is reversed.
927 /// function suggested/implemented by Miroslav Helbich <helbich@mail.desy.de>
928 
929 void TGraphMultiErrors::Apply(TF1 *f)
930 {
931  Double_t x, y, eyL, eyH, eyLNew, eyHNew, fxy;
932 
933  if (fHistogram) {
934  delete fHistogram;
935  fHistogram = nullptr;
936  }
937 
938  for (Int_t i = 0; i < fNpoints; i++) {
939  GetPoint(i, x, y);
940  eyL = GetErrorYlow(i, 0);
941  eyH = GetErrorYhigh(i, 0);
942 
943  fxy = f->Eval(x, y);
944  SetPoint(i, x, fxy);
945 
946  if (f->Eval(x, y - eyL) < f->Eval(x, y + eyH)) {
947  eyLNew = TMath::Abs(fxy - f->Eval(x, y - eyL));
948  eyHNew = TMath::Abs(f->Eval(x, y + eyH) - fxy);
949  } else {
950  eyHNew = TMath::Abs(fxy - f->Eval(x, y - eyL));
951  eyLNew = TMath::Abs(f->Eval(x, y + eyH) - fxy);
952  }
953 
954  // systematic errors and error on x doesn't change
955  SetPointEY(i, 0, eyLNew, eyHNew);
956  }
957 
958  if (gPad)
959  gPad->Modified();
960 }
961 
962 ////////////////////////////////////////////////////////////////////////////////
963 /// This function is only kept for backward compatibility.
964 /// You should rather use the Divide method.
965 /// It calls `Divide(pass,total,"cl=0.683 b(1,1) mode")` which is equivalent to the
966 /// former BayesDivide method.
967 
968 void TGraphMultiErrors::BayesDivide(const TH1 *pass, const TH1 *total, Option_t *)
969 {
970  Divide(pass, total, "cl=0.683 b(1,1) mode");
971 }
972 
973 ////////////////////////////////////////////////////////////////////////////////
974 /// This function was adapted from the TGraphAsymmErrors class.
975 /// See TGraphAsymmErrors::Divide for the documentation
976 ///
977 /// Only the first error dimension is affected!!!
978 
979 void TGraphMultiErrors::Divide(const TH1 *pass, const TH1 *total, Option_t *opt)
980 {
981  // check pointers
982  if (!pass || !total) {
983  Error("Divide", "one of the passed pointers is zero");
984  return;
985  }
986 
987  // check dimension of histograms; only 1-dimensional ones are accepted
988  if ((pass->GetDimension() > 1) || (total->GetDimension() > 1)) {
989  Error("Divide", "passed histograms are not one-dimensional");
990  return;
991  }
992 
993  // check whether histograms are filled with weights -> use number of effective
994  // entries
995  Bool_t bEffective = false;
996  // compare sum of weights with sum of squares of weights
997  // re-compute here to be sure to get the right values
998  Double_t psumw = 0;
999  Double_t psumw2 = 0;
1000  if (pass->GetSumw2()->fN > 0) {
1001  for (int i = 0; i < pass->GetNbinsX(); ++i) {
1002  psumw += pass->GetBinContent(i);
1003  psumw2 += pass->GetSumw2()->At(i);
1004  }
1005  } else {
1006  psumw = pass->GetSumOfWeights();
1007  psumw2 = psumw;
1008  }
1009  if (TMath::Abs(psumw - psumw2) > 1e-6)
1010  bEffective = true;
1011 
1012  Double_t tsumw = 0;
1013  Double_t tsumw2 = 0;
1014  if (total->GetSumw2()->fN > 0) {
1015  for (int i = 0; i < total->GetNbinsX(); ++i) {
1016  tsumw += total->GetBinContent(i);
1017  tsumw2 += total->GetSumw2()->At(i);
1018  }
1019  } else {
1020  tsumw = total->GetSumOfWeights();
1021  tsumw2 = tsumw;
1022  }
1023  if (TMath::Abs(tsumw - tsumw2) > 1e-6)
1024  bEffective = true;
1025 
1026  // we do not want to ignore the weights
1027  // if (bEffective && (pass->GetSumw2()->fN == 0 || total->GetSumw2()->fN == 0) ) {
1028  // Warning("Divide","histogram have been computed with weights but the sum of weight squares are not stored in the
1029  // histogram. Error calculation is performed ignoring the weights"); bEffective = false;
1030  // }
1031 
1032  // parse option
1033  TString option = opt;
1034  option.ToLower();
1035 
1036  Bool_t bVerbose = false;
1037  // pointer to function returning the boundaries of the confidence interval
1038  //(is only used in the frequentist cases.)
1039  // Double_t (*pBound)(Int_t,Int_t,Double_t,Bool_t) = &TEfficiency::ClopperPearson; // default method
1040  Double_t (*pBound)(Double_t, Double_t, Double_t, Bool_t) = &TEfficiency::ClopperPearson; // default method
1041  // confidence level
1042  Double_t conf = 0.682689492137;
1043  // values for bayesian statistics
1044  Bool_t bIsBayesian = false;
1045  Double_t alpha = 1;
1046  Double_t beta = 1;
1047 
1048  // verbose mode
1049  if (option.Contains("v")) {
1050  option.ReplaceAll("v", "");
1051  bVerbose = true;
1052  if (bEffective)
1053  Info("Divide", "weight will be considered in the Histogram Ratio");
1054  }
1055 
1056  // confidence level
1057  if (option.Contains("cl=")) {
1058  Double_t level = -1;
1059  // coverity [secure_coding : FALSE]
1060  sscanf(strstr(option.Data(), "cl="), "cl=%lf", &level);
1061  if ((level > 0) && (level < 1))
1062  conf = level;
1063  else
1064  Warning("Divide", "given confidence level %.3lf is invalid", level);
1065  option.ReplaceAll("cl=", "");
1066  }
1067 
1068  // normal approximation
1069  if (option.Contains("n")) {
1070  option.ReplaceAll("n", "");
1071  pBound = &TEfficiency::Normal;
1072  }
1073 
1074  // clopper pearson interval
1075  if (option.Contains("cp")) {
1076  option.ReplaceAll("cp", "");
1077  pBound = &TEfficiency::ClopperPearson;
1078  }
1079 
1080  // wilson interval
1081  if (option.Contains("w")) {
1082  option.ReplaceAll("w", "");
1083  pBound = &TEfficiency::Wilson;
1084  }
1085 
1086  // agresti coull interval
1087  if (option.Contains("ac")) {
1088  option.ReplaceAll("ac", "");
1089  pBound = &TEfficiency::AgrestiCoull;
1090  }
1091  // Feldman-Cousins interval
1092  if (option.Contains("fc")) {
1093  option.ReplaceAll("fc", "");
1094  pBound = &TEfficiency::FeldmanCousins;
1095  }
1096  // mid-P Lancaster interval (In a later ROOT Version!)
1097  if (option.Contains("midp")) {
1098  option.ReplaceAll("midp", "");
1099  // pBound = &TEfficiency::MidPInterval;
1100  }
1101 
1102  // bayesian with prior
1103  if (option.Contains("b(")) {
1104  Double_t a = 0;
1105  Double_t b = 0;
1106  sscanf(strstr(option.Data(), "b("), "b(%lf,%lf)", &a, &b);
1107  if (a > 0)
1108  alpha = a;
1109  else
1110  Warning("Divide", "given shape parameter for alpha %.2lf is invalid", a);
1111  if (b > 0)
1112  beta = b;
1113  else
1114  Warning("Divide", "given shape parameter for beta %.2lf is invalid", b);
1115  option.ReplaceAll("b(", "");
1116  bIsBayesian = true;
1117  }
1118 
1119  // use posterior mode
1120  Bool_t usePosteriorMode = false;
1121  if (bIsBayesian && option.Contains("mode")) {
1122  usePosteriorMode = true;
1123  option.ReplaceAll("mode", "");
1124  }
1125 
1126  Bool_t plot0Bins = false;
1127  if (option.Contains("e0")) {
1128  plot0Bins = true;
1129  option.ReplaceAll("e0", "");
1130  }
1131 
1132  Bool_t useShortestInterval = false;
1133  if (bIsBayesian && (option.Contains("sh") || (usePosteriorMode && !option.Contains("cen")))) {
1134  useShortestInterval = true;
1135  }
1136 
1137  // interpret as Poisson ratio
1138  Bool_t bPoissonRatio = false;
1139  if (option.Contains("pois")) {
1140  bPoissonRatio = true;
1141  option.ReplaceAll("pois", "");
1142  }
1143 
1144  // weights works only in case of Normal approximation or Bayesian for binomial interval
1145  // in case of Poisson ratio we can use weights by rescaling the obtained results using the effective entries
1146  if ((bEffective && !bPoissonRatio) && !bIsBayesian && pBound != &TEfficiency::Normal) {
1147  Warning("Divide", "Histograms have weights: only Normal or Bayesian error calculation is supported");
1148  Info("Divide", "Using now the Normal approximation for weighted histograms");
1149  }
1150 
1151  if (bPoissonRatio) {
1152  if (pass->GetDimension() != total->GetDimension()) {
1153  Error("Divide", "passed histograms are not of the same dimension");
1154  return;
1155  }
1156 
1157  if (!TEfficiency::CheckBinning(*pass, *total)) {
1158  Error("Divide", "passed histograms are not consistent");
1159  return;
1160  }
1161  } else {
1162  // check consistency of histograms, allowing weights
1163  if (!TEfficiency::CheckConsistency(*pass, *total, "w")) {
1164  Error("Divide", "passed histograms are not consistent");
1165  return;
1166  }
1167  }
1168 
1169  // Set the graph to have a number of points equal to the number of histogram
1170  // bins
1171  Int_t nbins = pass->GetNbinsX();
1172  Set(nbins);
1173 
1174  // Ok, now set the points for each bin
1175  // (Note: the TH1 bin content is shifted to the right by one:
1176  // bin=0 is underflow, bin=nbins+1 is overflow.)
1177 
1178  // this keeps track of the number of points added to the graph
1179  Int_t npoint = 0;
1180  // number of total and passed events
1181  Double_t t = 0, p = 0;
1182  Double_t tw = 0, tw2 = 0, pw = 0, pw2 = 0, wratio = 1; // for the case of weights
1183  // loop over all bins and fill the graph
1184  for (Int_t b = 1; b <= nbins; ++b) {
1185  // efficiency with lower and upper boundary of confidence interval default value when total =0;
1186  Double_t eff = 0., low = 0., upper = 0.;
1187 
1188  // special case in case of weights we have to consider the sum of weights and the sum of weight squares
1189  if (bEffective) {
1190  tw = total->GetBinContent(b);
1191  tw2 = (total->GetSumw2()->fN > 0) ? total->GetSumw2()->At(b) : tw;
1192  pw = pass->GetBinContent(b);
1193  pw2 = (pass->GetSumw2()->fN > 0) ? pass->GetSumw2()->At(b) : pw;
1194 
1195  if (bPoissonRatio) {
1196  // tw += pw;
1197  // tw2 += pw2;
1198  // compute ratio on the effective entries ( p and t)
1199  // special case is when (pw=0, pw2=0) in this case we cannot get the bin weight.
1200  // we use then the overall weight of the full histogram
1201  if (pw == 0 && pw2 == 0)
1202  p = 0;
1203  else
1204  p = (pw * pw) / pw2;
1205 
1206  if (tw == 0 && tw2 == 0)
1207  t = 0;
1208  else
1209  t = (tw * tw) / tw2;
1210 
1211  if (pw > 0 && tw > 0)
1212  // this is the ratio of the two bin weights ( pw/p / t/tw )
1213  wratio = (pw * t) / (p * tw);
1214  else if (pw == 0 && tw > 0)
1215  // case p histogram has zero compute the weights from all the histogram
1216  // weight of histogram - sumw2/sumw
1217  wratio = (psumw2 * t) / (psumw * tw);
1218  else if (tw == 0 && pw > 0)
1219  // case t histogram has zero compute the weights from all the histogram
1220  // weight of histogram - sumw2/sumw
1221  wratio = (pw * tsumw) / (p * tsumw2);
1222  else if (p > 0)
1223  wratio = pw / p; // not sure if needed
1224  else {
1225  // case both pw and tw are zero - we skip these bins
1226  if (!plot0Bins)
1227  continue; // skip bins with total <= 0
1228  }
1229 
1230  t += p;
1231  // std::cout << p << " " << t << " " << wratio << std::endl;
1232  } else if (tw <= 0 && !plot0Bins)
1233  continue; // skip bins with total <= 0
1234 
1235  // in the case of weights have the formula only for
1236  // the normal and bayesian statistics (see below)
1237 
1238  }
1239 
1240  // use bin contents
1241  else {
1242  t = TMath::Nint(total->GetBinContent(b));
1243  p = TMath::Nint(pass->GetBinContent(b));
1244 
1245  if (bPoissonRatio)
1246  t += p;
1247 
1248  if (t == 0. && !plot0Bins)
1249  continue; // skip bins with total = 0
1250  }
1251 
1252  // using bayesian statistics
1253  if (bIsBayesian) {
1254  if ((bEffective && !bPoissonRatio) && tw2 <= 0) {
1255  // case of bins with zero errors
1256  eff = pw / tw;
1257  low = eff;
1258  upper = eff;
1259  } else {
1260  Double_t aa, bb;
1261 
1262  if (bEffective && !bPoissonRatio) {
1263  // tw/tw2 re-normalize the weights
1264  double norm = tw / tw2; // case of tw2 = 0 is treated above
1265  aa = pw * norm + alpha;
1266  bb = (tw - pw) * norm + beta;
1267  } else {
1268  aa = double(p) + alpha;
1269  bb = double(t - p) + beta;
1270  }
1271  if (usePosteriorMode)
1272  eff = TEfficiency::BetaMode(aa, bb);
1273  else
1274  eff = TEfficiency::BetaMean(aa, bb);
1275 
1276  if (useShortestInterval) {
1277  TEfficiency::BetaShortestInterval(conf, aa, bb, low, upper);
1278  } else {
1279  low = TEfficiency::BetaCentralInterval(conf, aa, bb, false);
1280  upper = TEfficiency::BetaCentralInterval(conf, aa, bb, true);
1281  }
1282  }
1283  }
1284  // case of non-bayesian statistics
1285  else {
1286  if (bEffective && !bPoissonRatio) {
1287 
1288  if (tw > 0) {
1289 
1290  eff = pw / tw;
1291 
1292  // use normal error calculation using variance of MLE with weights (F.James 8.5.2)
1293  // this is the same formula used in ROOT for TH1::Divide("B")
1294 
1295  double variance = (pw2 * (1. - 2 * eff) + tw2 * eff * eff) / (tw * tw);
1296  double sigma = sqrt(variance);
1297 
1298  double prob = 0.5 * (1. - conf);
1299  double delta = ROOT::Math::normal_quantile_c(prob, sigma);
1300  low = eff - delta;
1301  upper = eff + delta;
1302  if (low < 0)
1303  low = 0;
1304  if (upper > 1)
1305  upper = 1.;
1306  }
1307  } else {
1308  // when not using weights (all cases) or in case of Poisson ratio with weights
1309  if (t != 0.)
1310  eff = ((Double_t)p) / t;
1311 
1312  low = pBound(t, p, conf, false);
1313  upper = pBound(t, p, conf, true);
1314  }
1315  }
1316  // treat as Poisson ratio
1317  if (bPoissonRatio) {
1318  Double_t ratio = eff / (1 - eff);
1319  // take the intervals in eff as intervals in the Poisson ratio
1320  low = low / (1. - low);
1321  upper = upper / (1. - upper);
1322  eff = ratio;
1323  if (bEffective) {
1324  // scale result by the ratio of the weight
1325  eff *= wratio;
1326  low *= wratio;
1327  upper *= wratio;
1328  }
1329  }
1330  // Set the point center and its errors
1331  if (TMath::Finite(eff)) {
1332  SetPoint(npoint, pass->GetBinCenter(b), eff);
1333  SetPointEX(npoint, pass->GetBinCenter(b) - pass->GetBinLowEdge(b),
1334  pass->GetBinLowEdge(b) - pass->GetBinCenter(b) + pass->GetBinWidth(b));
1335  SetPointEY(npoint, 0, eff - low, upper - eff);
1336  npoint++; // we have added a point to the graph
1337  }
1338  }
1339 
1340  Set(npoint); // tell the graph how many points we've really added
1341  if (npoint < nbins)
1342  Warning("Divide", "Number of graph points is different than histogram bins - %d points have been skipped",
1343  nbins - npoint);
1344 
1345  if (bVerbose) {
1346  Info("Divide", "made a graph with %d points from %d bins", npoint, nbins);
1347  Info("Divide", "used confidence level: %.2lf\n", conf);
1348  if (bIsBayesian)
1349  Info("Divide", "used prior probability ~ beta(%.2lf,%.2lf)", alpha, beta);
1350  Print();
1351  }
1352 }
1353 
1354 ////////////////////////////////////////////////////////////////////////////////
1355 /// Compute Range
1356 
1357 void TGraphMultiErrors::ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
1358 {
1359  TGraph::ComputeRange(xmin, ymin, xmax, ymax);
1360 
1361  for (Int_t i = 0; i < fNpoints; i++) {
1362  if (fX[i] - fExL[i] < xmin) {
1363  if (gPad && gPad->GetLogx()) {
1364  if (fExL[i] < fX[i])
1365  xmin = fX[i] - fExL[i];
1366  else
1367  xmin = TMath::Min(xmin, fX[i] / 3.);
1368  } else
1369  xmin = fX[i] - fExL[i];
1370  }
1371 
1372  if (fX[i] + fExH[i] > xmax)
1373  xmax = fX[i] + fExH[i];
1374 
1375  Double_t eyLMax = 0., eyHMax = 0.;
1376  for (Int_t j = 0; j < fNYErrors; j++) {
1377  eyLMax = TMath::Max(eyLMax, fEyL[j][i]);
1378  eyHMax = TMath::Max(eyHMax, fEyH[j][i]);
1379  }
1380 
1381  if (fY[i] - eyLMax < ymin) {
1382  if (gPad && gPad->GetLogy()) {
1383  if (eyLMax < fY[i])
1384  ymin = fY[i] - eyLMax;
1385  else
1386  ymin = TMath::Min(ymin, fY[i] / 3.);
1387  } else
1388  ymin = fY[i] - eyLMax;
1389  }
1390 
1391  if (fY[i] + eyHMax > ymax)
1392  ymax = fY[i] + eyHMax;
1393  }
1394 }
1395 
1396 ////////////////////////////////////////////////////////////////////////////////
1397 /// Deletes the y error with the index e
1398 /// Note that you must keep at least 1 error
1399 
1400 void TGraphMultiErrors::DeleteYError(Int_t e)
1401 {
1402  if (fNYErrors == 1 || e >= fNYErrors)
1403  return;
1404 
1405  fEyL.erase(fEyL.begin() + e);
1406  fEyH.erase(fEyH.begin() + e);
1407  fAttFill.erase(fAttFill.begin() + e);
1408  fAttLine.erase(fAttLine.begin() + e);
1409 
1410  fNYErrors -= 1;
1411 }
1412 
1413 ////////////////////////////////////////////////////////////////////////////////
1414 /// Get error on x coordinate for point i
1415 /// In case of asymmetric errors the mean of the square sum is returned
1416 
1417 Double_t TGraphMultiErrors::GetErrorX(Int_t i) const
1418 {
1419  if (i < 0 || i >= fNpoints || (!fExL && !fExH))
1420  return -1.;
1421 
1422  Double_t exL = fExL ? fExL[i] : 0.;
1423  Double_t exH = fExH ? fExH[i] : 0.;
1424  return TMath::Sqrt((exL * exL + exH * exH) / 2.);
1425 }
1426 
1427 ////////////////////////////////////////////////////////////////////////////////
1428 /// Get error on y coordinate for point i
1429 /// The multiple errors of the dimensions are summed according to fSumErrorsMode
1430 /// In case of asymmetric errors the mean of the square sum is returned
1431 
1432 Double_t TGraphMultiErrors::GetErrorY(Int_t i) const
1433 {
1434  if (i < 0 || i >= fNpoints || (fEyL.empty() && fEyH.empty()))
1435  return -1.;
1436 
1437  Double_t eyL = GetErrorYlow(i);
1438  Double_t eyH = GetErrorYhigh(i);
1439  return TMath::Sqrt((eyL * eyL + eyH * eyH) / 2.);
1440 }
1441 
1442 ////////////////////////////////////////////////////////////////////////////////
1443 /// Get error e on y coordinate for point i
1444 /// In case of asymmetric errors the mean of the square sum is returned
1445 
1446 Double_t TGraphMultiErrors::GetErrorY(Int_t i, Int_t e) const
1447 {
1448  if (i < 0 || i >= fNpoints || e >= fNYErrors || (fEyL.empty() && fEyH.empty()))
1449  return -1.;
1450 
1451  Double_t eyL = fEyL.empty() ? 0. : fEyL[e][i];
1452  Double_t eyH = fEyH.empty() ? 0. : fEyH[e][i];
1453  return TMath::Sqrt((eyL * eyL + eyH * eyH) / 2.);
1454 }
1455 
1456 ////////////////////////////////////////////////////////////////////////////////
1457 /// Get low error on x coordinate for point i
1458 
1459 Double_t TGraphMultiErrors::GetErrorXlow(Int_t i) const
1460 {
1461  if (i < 0 || i >= fNpoints || !fExL)
1462  return -1.;
1463  else
1464  return fExL[i];
1465 }
1466 
1467 ////////////////////////////////////////////////////////////////////////////////
1468 /// Get high error on x coordinate for point i
1469 
1470 Double_t TGraphMultiErrors::GetErrorXhigh(Int_t i) const
1471 {
1472  if (i < 0 || i >= fNpoints || !fExH)
1473  return -1.;
1474  else
1475  return fExH[i];
1476 }
1477 
1478 ////////////////////////////////////////////////////////////////////////////////
1479 /// Get low error on y coordinate for point i
1480 /// The multiple errors of the dimensions are summed according to fSumErrorsMode
1481 
1482 Double_t TGraphMultiErrors::GetErrorYlow(Int_t i) const
1483 {
1484  if (i < 0 || i >= fNpoints || fEyL.empty())
1485  return -1.;
1486 
1487  if (fSumErrorsMode == TGraphMultiErrors::kOnlyFirst)
1488  return fEyL[0][i];
1489  else if (fSumErrorsMode == TGraphMultiErrors::kSquareSum) {
1490  Double_t sum = 0.;
1491  for (Int_t j = 0; j < fNYErrors; j++)
1492  sum += fEyL[j][i] * fEyL[j][i];
1493  return TMath::Sqrt(sum);
1494  } else if (fSumErrorsMode == TGraphMultiErrors::kAbsSum) {
1495  Double_t sum = 0.;
1496  for (Int_t j = 0; j < fNYErrors; j++)
1497  sum += fEyL[j][i];
1498  return sum;
1499  }
1500 
1501  return -1.;
1502 }
1503 
1504 ////////////////////////////////////////////////////////////////////////////////
1505 /// Get high error on y coordinate for point i
1506 /// The multiple errors of the dimensions are summed according to fSumErrorsMode
1507 
1508 Double_t TGraphMultiErrors::GetErrorYhigh(Int_t i) const
1509 {
1510  if (i < 0 || i >= fNpoints || fEyH.empty())
1511  return -1.;
1512 
1513  if (fSumErrorsMode == TGraphMultiErrors::kOnlyFirst)
1514  return fEyH[0][i];
1515  else if (fSumErrorsMode == TGraphMultiErrors::kSquareSum) {
1516  Double_t sum = 0.;
1517  for (Int_t j = 0; j < fNYErrors; j++)
1518  sum += fEyH[j][i] * fEyH[j][i];
1519  return TMath::Sqrt(sum);
1520  } else if (fSumErrorsMode == TGraphMultiErrors::kAbsSum) {
1521  Double_t sum = 0.;
1522  for (Int_t j = 0; j < fNYErrors; j++)
1523  sum += fEyH[j][i];
1524  return sum;
1525  }
1526 
1527  return -1.;
1528 }
1529 
1530 ////////////////////////////////////////////////////////////////////////////////
1531 /// Get low error e on y coordinate for point i
1532 
1533 Double_t TGraphMultiErrors::GetErrorYlow(Int_t i, Int_t e) const
1534 {
1535  if (i < 0 || i >= fNpoints || e >= fNYErrors || fEyL.empty())
1536  return -1.;
1537 
1538  return fEyL[e][i];
1539 }
1540 
1541 ////////////////////////////////////////////////////////////////////////////////
1542 /// Get high error e on y coordinate for point i
1543 
1544 Double_t TGraphMultiErrors::GetErrorYhigh(Int_t i, Int_t e) const
1545 {
1546  if (i < 0 || i >= fNpoints || e >= fNYErrors || fEyH.empty())
1547  return -1.;
1548 
1549  return fEyH[e][i];
1550 }
1551 
1552 ////////////////////////////////////////////////////////////////////////////////
1553 /// Get all low errors on y coordinates as an array summed according to fSumErrorsMode
1554 
1555 Double_t *TGraphMultiErrors::GetEYlow() const
1556 {
1557  if (!fEyLSum)
1558  CalcYErrorsSum();
1559 
1560  return fEyLSum;
1561 }
1562 
1563 ////////////////////////////////////////////////////////////////////////////////
1564 /// Get all high errors on y coordinates as an array summed according to fSumErrorsMode
1565 
1566 Double_t *TGraphMultiErrors::GetEYhigh() const
1567 {
1568  if (!fEyHSum)
1569  CalcYErrorsSum();
1570 
1571  return fEyHSum;
1572 }
1573 
1574 ////////////////////////////////////////////////////////////////////////////////
1575 /// Get all low errors e on y coordinates as an array
1576 
1577 Double_t *TGraphMultiErrors::GetEYlow(Int_t e)
1578 {
1579  if (e >= fNYErrors || fEyL.empty())
1580  return nullptr;
1581  else
1582  return fEyL[e].GetArray();
1583 }
1584 
1585 ////////////////////////////////////////////////////////////////////////////////
1586 /// Get all high errors e on y coordinates as an array
1587 
1588 Double_t *TGraphMultiErrors::GetEYhigh(Int_t e)
1589 {
1590  if (e >= fNYErrors || fEyH.empty())
1591  return nullptr;
1592  else
1593  return fEyH[e].GetArray();
1594 }
1595 
1596 ////////////////////////////////////////////////////////////////////////////////
1597 /// Get AttFill pointer for specified error dimension
1598 
1599 TAttFill *TGraphMultiErrors::GetAttFill(Int_t e)
1600 {
1601  if (e >= 0 && e < fNYErrors)
1602  return &fAttFill.at(e);
1603  else
1604  return nullptr;
1605 }
1606 
1607 ////////////////////////////////////////////////////////////////////////////////
1608 /// Get AttLine pointer for specified error dimension
1609 
1610 TAttLine *TGraphMultiErrors::GetAttLine(Int_t e)
1611 {
1612  if (e >= 0 && e < fNYErrors)
1613  return &fAttLine.at(e);
1614  else
1615  return nullptr;
1616 }
1617 
1618 ////////////////////////////////////////////////////////////////////////////////
1619 /// Get Fill Color for specified error e (-1 = Global and x errors)
1620 
1621 Color_t TGraphMultiErrors::GetFillColor(Int_t e) const
1622 {
1623  if (e == -1)
1624  return GetFillColor();
1625  else if (e >= 0 && e < fNYErrors)
1626  return fAttFill[e].GetFillColor();
1627  else
1628  return 0;
1629 }
1630 
1631 ////////////////////////////////////////////////////////////////////////////////
1632 /// Get Fill Style for specified error e (-1 = Global and x errors)
1633 
1634 Style_t TGraphMultiErrors::GetFillStyle(Int_t e) const
1635 {
1636  if (e == -1)
1637  return GetFillStyle();
1638  else if (e >= 0 && e < fNYErrors)
1639  return fAttFill[e].GetFillStyle();
1640  else
1641  return 0;
1642 }
1643 
1644 ////////////////////////////////////////////////////////////////////////////////
1645 /// Get Line Color for specified error e (-1 = Global and x errors)
1646 
1647 Color_t TGraphMultiErrors::GetLineColor(Int_t e) const
1648 {
1649  if (e == -1)
1650  return GetLineColor();
1651  else if (e >= 0 && e < fNYErrors)
1652  return fAttLine[e].GetLineColor();
1653  else
1654  return 0;
1655 }
1656 
1657 ////////////////////////////////////////////////////////////////////////////////
1658 /// Get Line Style for specified error e (-1 = Global and x errors)
1659 
1660 Style_t TGraphMultiErrors::GetLineStyle(Int_t e) const
1661 {
1662  if (e == -1)
1663  return GetLineStyle();
1664  else if (e >= 0 && e < fNYErrors)
1665  return fAttLine[e].GetLineStyle();
1666  else
1667  return 0;
1668 }
1669 
1670 ////////////////////////////////////////////////////////////////////////////////
1671 /// Get Line Width for specified error e (-1 = Global and x errors)
1672 
1673 Width_t TGraphMultiErrors::GetLineWidth(Int_t e) const
1674 {
1675  if (e == -1)
1676  return GetLineWidth();
1677  else if (e >= 0 && e < fNYErrors)
1678  return fAttLine[e].GetLineWidth();
1679  else
1680  return 0;
1681 }
1682 
1683 ////////////////////////////////////////////////////////////////////////////////
1684 /// Print graph and errors values.
1685 
1686 void TGraphMultiErrors::Print(Option_t *) const
1687 {
1688  for (Int_t i = 0; i < fNpoints; i++) {
1689  printf("x[%d]=%g, y[%d]=%g", i, fX[i], i, fY[i]);
1690  if (fExL)
1691  printf(", exl[%d]=%g", i, fExL[i]);
1692  if (fExH)
1693  printf(", exh[%d]=%g", i, fExH[i]);
1694  if (!fEyL.empty())
1695  for (Int_t j = 0; j < fNYErrors; j++)
1696  printf(", eyl[%d][%d]=%g", j, i, fEyL[j][i]);
1697  if (!fEyH.empty())
1698  for (Int_t j = 0; j < fNYErrors; j++)
1699  printf(", eyh[%d][%d]=%g", j, i, fEyH[j][i]);
1700  printf("\n");
1701  }
1702 }
1703 
1704 ////////////////////////////////////////////////////////////////////////////////
1705 /// Save primitive as a C++ statement(s) on output stream out
1706 
1707 void TGraphMultiErrors::SavePrimitive(std::ostream &out, Option_t *option)
1708 {
1709  char quote = '"';
1710  out << " " << std::endl;
1711 
1712  if (gROOT->ClassSaved(TGraphMultiErrors::Class()))
1713  out << " ";
1714  else
1715  out << " TGraphMultiErrors* ";
1716 
1717  out << "tgme = new TGraphMultiErrors(" << fNpoints << ", " << fNYErrors << ");" << std::endl;
1718  out << " tgme->SetName(" << quote << GetName() << quote << ");" << std::endl;
1719  out << " tgme->SetTitle(" << quote << GetTitle() << quote << ");" << std::endl;
1720 
1721  SaveFillAttributes(out, "tgme", 0, 1001);
1722  SaveLineAttributes(out, "tgme", 1, 1, 1);
1723  SaveMarkerAttributes(out, "tgme", 1, 1, 1);
1724 
1725  for (Int_t j = 0; j < fNYErrors; j++) {
1726  fAttFill[j].SaveFillAttributes(out, Form("tgme->GetAttFill(%d)", j), 0, 1001);
1727  fAttLine[j].SaveLineAttributes(out, Form("tgme->GetAttLine(%d)", j), 1, 1, 1);
1728  }
1729 
1730  for (Int_t i = 0; i < fNpoints; i++) {
1731  out << " tgme->SetPoint(" << i << ", " << fX[i] << ", " << fY[i] << ");" << std::endl;
1732  out << " tgme->SetPointEX(" << i << ", " << fExL[i] << ", " << fExH[i] << ");" << std::endl;
1733 
1734  for (Int_t j = 0; j < fNYErrors; j++)
1735  out << " tgme->SetPointEY(" << i << ", " << j << ", " << fEyL[j][i] << ", " << fEyH[j][i] << ");"
1736  << std::endl;
1737  }
1738 
1739  static Int_t frameNumber = 0;
1740  if (fHistogram) {
1741  frameNumber++;
1742  TString hname = fHistogram->GetName();
1743  hname += frameNumber;
1744  fHistogram->SetName(Form("Graph_%s", hname.Data()));
1745  fHistogram->SavePrimitive(out, "nodraw");
1746  out << " tgme->SetHistogram(" << fHistogram->GetName() << ");" << std::endl;
1747  out << " " << std::endl;
1748  }
1749 
1750  // save list of functions
1751  TIter next(fFunctions);
1752  TObject *obj;
1753  while ((obj = next())) {
1754  obj->SavePrimitive(out, "nodraw");
1755  if (obj->InheritsFrom("TPaveStats")) {
1756  out << " tgme->GetListOfFunctions()->Add(ptstats);" << std::endl;
1757  out << " ptstats->SetParent(tgme->GetListOfFunctions());" << std::endl;
1758  } else
1759  out << " tgme->GetListOfFunctions()->Add(" << obj->GetName() << ");" << std::endl;
1760  }
1761 
1762  const char *l = strstr(option, "multigraph");
1763  if (l)
1764  out << " multigraph->Add(tgme, " << quote << l + 10 << quote << ");" << std::endl;
1765  else
1766  out << " tgme->Draw(" << quote << option << quote << ");" << std::endl;
1767 }
1768 
1769 ////////////////////////////////////////////////////////////////////////////////
1770 /// Set ex and ey values for point pointed by the mouse.
1771 ///
1772 /// Up to 3 y error dimensions possible.
1773 
1774 void TGraphMultiErrors::SetPointError(Double_t exL, Double_t exH, Double_t eyL1, Double_t eyH1, Double_t eyL2,
1775  Double_t eyH2, Double_t eyL3, Double_t eyH3)
1776 {
1777  Int_t px = gPad->GetEventX();
1778  Int_t py = gPad->GetEventY();
1779 
1780  // localize point to be deleted
1781  Int_t ipoint = -2;
1782  Int_t i;
1783  // start with a small window (in case the mouse is very close to one point)
1784  for (i = 0; i < fNpoints; i++) {
1785  Int_t dpx = px - gPad->XtoAbsPixel(gPad->XtoPad(fX[i]));
1786  Int_t dpy = py - gPad->YtoAbsPixel(gPad->YtoPad(fY[i]));
1787 
1788  if (dpx * dpx + dpy * dpy < 25) {
1789  ipoint = i;
1790  break;
1791  }
1792  }
1793 
1794  if (ipoint == -2)
1795  return;
1796 
1797  SetPointEX(ipoint, exL, exH);
1798 
1799  if (fNYErrors > 0)
1800  SetPointEY(ipoint, 0, eyL1, eyH1);
1801  if (fNYErrors > 1)
1802  SetPointEY(ipoint, 1, eyL2, eyH2);
1803  if (fNYErrors > 2)
1804  SetPointEY(ipoint, 2, eyL3, eyH3);
1805  gPad->Modified();
1806 }
1807 
1808 ////////////////////////////////////////////////////////////////////////////////
1809 /// Set ex and ey values for point i.
1810 
1811 void TGraphMultiErrors::SetPointError(Int_t i, Int_t ne, Double_t exL, Double_t exH, const Double_t *eyL,
1812  const Double_t *eyH)
1813 {
1814  SetPointEX(i, exL, exH);
1815  SetPointEY(i, ne, eyL, eyH);
1816 }
1817 
1818 ////////////////////////////////////////////////////////////////////////////////
1819 /// Set ex values for point i.
1820 
1821 void TGraphMultiErrors::SetPointEX(Int_t i, Double_t exL, Double_t exH)
1822 {
1823  SetPointEXlow(i, exL);
1824  SetPointEXhigh(i, exH);
1825 }
1826 
1827 ////////////////////////////////////////////////////////////////////////////////
1828 /// Set exL value for point i.
1829 
1830 void TGraphMultiErrors::SetPointEXlow(Int_t i, Double_t exL)
1831 {
1832  if (i < 0)
1833  return;
1834 
1835  if (i >= fNpoints) {
1836  // re-allocate the object
1837  TGraphMultiErrors::SetPoint(i, 0., 0.);
1838  }
1839 
1840  fExL[i] = exL;
1841 }
1842 
1843 ////////////////////////////////////////////////////////////////////////////////
1844 /// Set exH value for point i.
1845 
1846 void TGraphMultiErrors::SetPointEXhigh(Int_t i, Double_t exH)
1847 {
1848  if (i < 0)
1849  return;
1850 
1851  if (i >= fNpoints) {
1852  // re-allocate the object
1853  TGraphMultiErrors::SetPoint(i, 0., 0.);
1854  }
1855 
1856  fExH[i] = exH;
1857 }
1858 
1859 ////////////////////////////////////////////////////////////////////////////////
1860 /// Set ey values for point i.
1861 
1862 void TGraphMultiErrors::SetPointEY(Int_t i, Int_t ne, const Double_t *eyL, const Double_t *eyH)
1863 {
1864  SetPointEYlow(i, ne, eyL);
1865  SetPointEYhigh(i, ne, eyH);
1866 }
1867 
1868 ////////////////////////////////////////////////////////////////////////////////
1869 /// Set eyL values for point i.
1870 
1871 void TGraphMultiErrors::SetPointEYlow(Int_t i, Int_t ne, const Double_t *eyL)
1872 {
1873  for (Int_t j = 0; j < fNYErrors; j++) {
1874  if (j < ne)
1875  SetPointEYlow(i, j, eyL[j]);
1876  else
1877  SetPointEYlow(i, j, 0.);
1878  }
1879 }
1880 
1881 ////////////////////////////////////////////////////////////////////////////////
1882 /// Set eyH values for point i.
1883 
1884 void TGraphMultiErrors::SetPointEYhigh(Int_t i, Int_t ne, const Double_t *eyH)
1885 {
1886  for (Int_t j = 0; j < fNYErrors; j++) {
1887  if (j < ne)
1888  SetPointEYhigh(i, j, eyH[j]);
1889  else
1890  SetPointEYhigh(i, j, 0.);
1891  }
1892 }
1893 
1894 ////////////////////////////////////////////////////////////////////////////////
1895 /// Set error e ey values for point i.
1896 
1897 void TGraphMultiErrors::SetPointEY(Int_t i, Int_t e, Double_t eyL, Double_t eyH)
1898 {
1899  SetPointEYlow(i, e, eyL);
1900  SetPointEYhigh(i, e, eyH);
1901 }
1902 
1903 ////////////////////////////////////////////////////////////////////////////////
1904 /// Set error e eyL value for point i.
1905 
1906 void TGraphMultiErrors::SetPointEYlow(Int_t i, Int_t e, Double_t eyL)
1907 {
1908  if (i < 0 || e < 0)
1909  return;
1910 
1911  if (i >= fNpoints)
1912  // re-allocate the object
1913  TGraphMultiErrors::SetPoint(i, 0., 0.);
1914 
1915  while (e >= fNYErrors)
1916  AddYError(fNpoints);
1917 
1918  fEyL[e][i] = eyL;
1919  if (fEyLSum)
1920  fEyLSum[i] = GetErrorYlow(i);
1921  else
1922  CalcYErrorsSum();
1923 }
1924 
1925 ////////////////////////////////////////////////////////////////////////////////
1926 /// Set error e eyH value for point i.
1927 
1928 void TGraphMultiErrors::SetPointEYhigh(Int_t i, Int_t e, Double_t eyH)
1929 {
1930  if (i < 0 || e < 0)
1931  return;
1932 
1933  if (i >= fNpoints)
1934  // re-allocate the object
1935  TGraphMultiErrors::SetPoint(i, 0., 0.);
1936 
1937  while (e >= fNYErrors)
1938  AddYError(fNpoints);
1939 
1940  fEyH[e][i] = eyH;
1941  if (fEyHSum)
1942  fEyHSum[i] = GetErrorYhigh(i);
1943  else
1944  CalcYErrorsSum();
1945 }
1946 
1947 ////////////////////////////////////////////////////////////////////////////////
1948 /// Set error e ey values
1949 
1950 void TGraphMultiErrors::SetEY(Int_t e, Int_t np, const Double_t *eyL, const Double_t *eyH)
1951 {
1952  SetEYlow(e, np, eyL);
1953  SetEYhigh(e, np, eyH);
1954 }
1955 
1956 ////////////////////////////////////////////////////////////////////////////////
1957 /// Set error e eyL values
1958 
1959 void TGraphMultiErrors::SetEYlow(Int_t e, Int_t np, const Double_t *eyL)
1960 {
1961  for (Int_t i = 0; i < fNpoints; i++) {
1962  if (i < np)
1963  SetPointEYlow(i, e, eyL[i]);
1964  else
1965  SetPointEYlow(i, e, 0.);
1966  }
1967 }
1968 
1969 ////////////////////////////////////////////////////////////////////////////////
1970 /// Set error e eyH values
1971 
1972 void TGraphMultiErrors::SetEYhigh(Int_t e, Int_t np, const Double_t *eyH)
1973 {
1974  for (Int_t i = 0; i < fNpoints; i++) {
1975  if (i < np)
1976  SetPointEYhigh(i, e, eyH[i]);
1977  else
1978  SetPointEYhigh(i, e, 0.);
1979  }
1980 }
1981 
1982 ////////////////////////////////////////////////////////////////////////////////
1983 /// Set the sum errors mode and recalculate summed errors
1984 void TGraphMultiErrors::SetSumErrorsMode(Int_t m)
1985 {
1986  if (fSumErrorsMode == m)
1987  return;
1988  fSumErrorsMode = m;
1989  CalcYErrorsSum();
1990 }
1991 
1992 ////////////////////////////////////////////////////////////////////////////////
1993 /// Set TAttFill parameters of error e by copying from another TAttFill (-1 = Global and x errors)
1994 
1995 void TGraphMultiErrors::SetAttFill(Int_t e, TAttFill *taf)
1996 {
1997  if (e == -1)
1998  taf->TAttFill::Copy(*this);
1999  else if (e >= 0 && e < fNYErrors)
2000  taf->TAttFill::Copy(fAttFill[e]);
2001 }
2002 
2003 ////////////////////////////////////////////////////////////////////////////////
2004 /// Set TAttLine parameters of error e by copying from another TAttLine (-1 = Global and x errors)
2005 
2006 void TGraphMultiErrors::SetAttLine(Int_t e, TAttLine *taf)
2007 {
2008  if (e == -1)
2009  taf->TAttLine::Copy(*this);
2010  else if (e >= 0 && e < fNYErrors)
2011  taf->TAttLine::Copy(fAttLine[e]);
2012 }
2013 
2014 ////////////////////////////////////////////////////////////////////////////////
2015 /// Set Fill Color of error e (-1 = Global and x errors)
2016 
2017 void TGraphMultiErrors::SetFillColor(Int_t e, Color_t fcolor)
2018 {
2019  if (e == -1)
2020  SetFillColor(fcolor);
2021  else if (e >= 0 && e < fNYErrors)
2022  fAttFill[e].SetFillColor(fcolor);
2023 }
2024 
2025 ////////////////////////////////////////////////////////////////////////////////
2026 /// Set Fill Color and Alpha of error e (-1 = Global and x errors)
2027 
2028 void TGraphMultiErrors::SetFillColorAlpha(Int_t e, Color_t fcolor, Float_t falpha)
2029 {
2030  if (e == -1)
2031  SetFillColorAlpha(fcolor, falpha);
2032  else if (e >= 0 && e < fNYErrors)
2033  fAttFill[e].SetFillColorAlpha(fcolor, falpha);
2034 }
2035 
2036 ////////////////////////////////////////////////////////////////////////////////
2037 /// Set Fill Style of error e (-1 = Global and x errors)
2038 
2039 void TGraphMultiErrors::SetFillStyle(Int_t e, Style_t fstyle)
2040 {
2041  if (e == -1)
2042  SetFillStyle(fstyle);
2043  else if (e >= 0 && e < fNYErrors)
2044  fAttFill[e].SetFillStyle(fstyle);
2045 }
2046 
2047 ////////////////////////////////////////////////////////////////////////////////
2048 /// Set Line Color of error e (-1 = Global and x errors)
2049 
2050 void TGraphMultiErrors::SetLineColor(Int_t e, Color_t lcolor)
2051 {
2052  if (e == -1)
2053  SetLineColor(lcolor);
2054  else if (e >= 0 && e < fNYErrors)
2055  fAttLine[e].SetLineColor(lcolor);
2056 }
2057 
2058 ////////////////////////////////////////////////////////////////////////////////
2059 /// Set Line Color and Alpha of error e (-1 = Global and x errors)
2060 
2061 void TGraphMultiErrors::SetLineColorAlpha(Int_t e, Color_t lcolor, Float_t lalpha)
2062 {
2063  if (e == -1)
2064  SetLineColorAlpha(lcolor, lalpha);
2065  else if (e >= 0 && e < fNYErrors)
2066  fAttLine[e].SetLineColorAlpha(lcolor, lalpha);
2067 }
2068 
2069 ////////////////////////////////////////////////////////////////////////////////
2070 /// Set Line Style of error e (-1 = Global and x errors)
2071 
2072 void TGraphMultiErrors::SetLineStyle(Int_t e, Style_t lstyle)
2073 {
2074  if (e == -1)
2075  SetLineStyle(lstyle);
2076  else if (e >= 0 && e < fNYErrors)
2077  fAttLine[e].SetLineStyle(lstyle);
2078 }
2079 
2080 ////////////////////////////////////////////////////////////////////////////////
2081 /// Set Line Width of error e (-1 = Global and x errors)
2082 
2083 void TGraphMultiErrors::SetLineWidth(Int_t e, Width_t lwidth)
2084 {
2085  if (e == -1)
2086  SetLineWidth(lwidth);
2087  else if (e >= 0 && e < fNYErrors)
2088  fAttLine[e].SetLineWidth(lwidth);
2089 }