GraphSysErr  0.10-2
A class to hold results with statistical and systematic errors A class to hold results with statistical and systematic errors
GraphSysErr.C
Go to the documentation of this file.
1 
12 # include <TNamed.h>
13 # include <TAttMarker.h>
14 # include <TAttLine.h>
15 # include <TAttFill.h>
16 #ifndef GraphSysErr_C
17 # define GraphSysErr_C
18 # include <TList.h>
19 # ifndef __CINT__
20 # include <TStyle.h>
21 # include <TGraph.h>
22 # include <TGraphErrors.h>
23 # include <TGraphAsymmErrors.h>
24 # include <TMultiGraph.h>
25 # include <TH1.h>
26 # include <TMath.h>
27 # include <TFitResultPtr.h>
28 # include <TF1.h>
29 # include <TROOT.h>
30 # include <TSystem.h>
31 # include <TDatime.h>
32 # include <TList.h>
33 # include <TBrowser.h>
34 # include <TPRegexp.h>
35 # include <TClonesArray.h>
36 # include <TArrayL64.h>
37 # include <TLine.h>
38 # include <TClass.h>
39 # include <TObjString.h>
40 # include <iostream>
41 # include <iomanip>
42 # include <fstream>
43 # include <sstream>
44 // # define TOKEN(C,I) static_cast<TObjString*>(C->At(I))->String()
45 # define INCOMPAT_CMN_AS_QUAL 1
46 # else
47 # include <iosfwd>
48 class TGraph;
49 class TGraphErrors;
50 class TGraphAsymmErrors;
51 class TMultiGraph;
52 class TFitResultPtr;
53 class TF1;
54 class TList;
55 class TBrowser;
56 class TArrayD;
57 class TClonesArray;
58 class TLine;
59 # endif
60 
61 
174 class GraphSysErr : public TNamed, public TAttMarker,
175  public TAttLine, public TAttFill
176 {
177 public:
178  enum {
179  kDraw = 0x1,
180  kImport = 0x2,
181  kExport = 0x4,
182  kRatio = 0x8,
183  kVerbose = 0 // Set to OR of above to enable verbose/debug output
184  };
186  typedef TGraphAsymmErrors Graph;
191  kNormal = 0, // - Line with ticks
192  kNoTick = 1, // Z0 - Line with no ticks
193  kArrow = 2, // >0 - Linw with arrows
194  kRect = 3, // 20 - Rectangle w/fill
195  kBox = 4, // 50 - Rectangle w/fill & line
196  kFill = 5, // 30 - Filled area
197  kCurve = 6, // 40 - Filled smoothed area
198  kHat = 7, // []0 - Hats
199  kBar = 8, // ||0 - A bar
200  kNone = 9, // XP - No errors
201  kLine = 10, // XC
202  kConnect = 11 // XL
203  };
209  enum EChi2Type {
210  kExperimentExperiment, // Ignore errors on both
211  kExperimentModel, // Ignore errors on second
212  kModelModel, // Use errors on both
213  kExperimentTruth // Use errors on first, take second to be exact.
214  };
224  kMax = 0x00001, // Error is largest relative error
225  kMin = 0x00002, // Error is largest relative error
226  kCancel = 0x00004,
227  kDenomRel = 0x00008,
229  };
230  enum {
231  kUsedBit = (1 << 18),
232  kOnlyWeightBit = (1 << 19)
233  };
242  : TNamed(),
243  TAttMarker(1,20,1),
244  TAttLine(1,1,1),
245  TAttFill(0,0),
246  fPoint2Point(),
247  fCommon(),
248  fData(0),
249  fDrawn(0),
250  fCounter(0),
251  fSumFill(0,0),
252  fSumLine(1,1,1),
253  fSumTitle(),
254  fSumOption(0),
255  fCommonSumFill(0,0),
256  fCommonSumLine(1,1,1),
257  fCommonSumTitle(),
258  fCommonSumOption(0),
259  fDataOption(0),
260  fXTitle(""),
261  fYTitle(""),
262  fMap(0),
263  fQualifiers(0),
264  fStatRelative(false)
265  {
266 
267  }
273  GraphSysErr(Int_t n)
274  : TNamed("sysErrGraph","Data"),
275  TAttMarker(1,20,1),
276  TAttLine(1,1,1),
277  TAttFill(0,0),
278  fPoint2Point(),
279  fCommon(),
280  fData(0),
281  fDrawn(0),
282  fCounter(0),
283  fSumFill(0,0),
284  fSumLine(1,1,1),
285  fSumTitle("Uncorr.Errors"),
286  fSumOption(0),
287  fCommonSumFill(0,0),
288  fCommonSumLine(1,1,1),
289  fCommonSumTitle("Corr.Errors."),
290  fCommonSumOption(0),
291  fDataOption(0),
292  fXTitle(""),
293  fYTitle(""),
294  fMap(0),
295  fQualifiers(0),
296  fStatRelative(false)
297  {
298  fPoint2Point.SetName("point2point");
299  fPoint2Point.SetOwner();
300  fCommon.SetName("common");
301  fCommon.SetOwner();
302  MakeDataGraph(n);
303  }
311  GraphSysErr(const char* name, const char* title, Int_t n=0)
312  : TNamed(name,title),
313  TAttMarker(1,20,1),
314  TAttLine(1,1,1),
315  TAttFill(0,0),
316  fPoint2Point(),
317  fCommon(),
318  fData(0),
319  fDrawn(0),
320  fCounter(0),
321  fSumFill(0,0),
322  fSumLine(1,1,1),
323  fSumTitle("Errors"),
324  fSumOption(0),
325  fCommonSumFill(0,0),
326  fCommonSumLine(1,1,1),
327  fCommonSumTitle("Corr.Errors."),
328  fCommonSumOption(0),
329  fDataOption(0),
330  fXTitle(""),
331  fYTitle(""),
332  fMap(0),
333  fQualifiers(0),
334  fStatRelative(false)
335  {
336  fPoint2Point.SetOwner();
337  fCommon.SetOwner();
338  fCommon.SetName("common");
339  fPoint2Point("point2point");
340  MakeDataGraph(n);
341  }
347  GraphSysErr(const GraphSysErr& other)
348  : TNamed(other),
349  TAttMarker(other),
350  TAttLine(other),
351  TAttFill(other),
352  fPoint2Point(),
353  fCommon(),
354  fData(0),
355  fDrawn(0),
356  fCounter(0),
357  fSumFill(other.fSumFill),
358  fSumLine(other.fSumLine),
359  fSumTitle(other.fSumTitle),
360  fSumOption(other.fSumOption),
365  fDataOption(other.fDataOption),
366  fXTitle(other.fXTitle),
367  fYTitle(other.fYTitle),
368  fMap(0),
369  fQualifiers(0),
370  fStatRelative(false)
371  {
372  if (other.fData)
373  fData = static_cast<Graph*>(other.fData->Clone());
374 
375  fPoint2Point.SetOwner();
376  fCommon.SetOwner();
377  fCommon.SetName(other.GetName());
378  fPoint2Point(other.GetName());
379 
380  TIter nextC(&other.fCommon);
381  HolderCommon* common = 0;
382  while ((common = static_cast<HolderCommon*>(nextC()))) {
383  fCommon.Add(new HolderCommon(*common));
384  fCounter++;
385  }
386 
387  TIter nextP(&other.fPoint2Point);
388  HolderP2P* p2p = 0;
389  while ((p2p = static_cast<HolderP2P*>(nextP()))) {
390  fPoint2Point.Add(new HolderP2P(*p2p));
391  fCounter++;
392  }
393 
394  CopyKeys(&other, "ar");
395  // Print("all");
396  }
400  virtual ~GraphSysErr()
401  {
402  fPoint2Point.Delete();
403  fCommon.Delete();
404  if (fData) delete fData;
405  if (fDrawn) delete fDrawn;
406  if (fMap) delete fMap;
407  if (fQualifiers) delete fQualifiers;
408  }
417  {
418  if (&other == this) return *this;
419 
420  other.TNamed::Copy(*this);
421  other.TAttMarker::Copy(*this);
422  other.TAttLine::Copy(*this);
423  other.TAttFill::Copy(*this);
424  fPoint2Point.Clear();
425  fCommon.Clear();
426 
427  if (fData) delete fData;
428  fData = 0;
429  if (other.fData)
430  fData = static_cast<Graph*>(other.fData->Clone());
431 
432  if (fDrawn) { delete fDrawn; fDrawn = 0; }
433 
434  fCounter = other.fCounter;
435 
436  other.fSumFill.Copy(fSumFill);
437  other.fSumLine.Copy(fSumLine);
438  fSumTitle = other.fSumTitle;
439  fSumOption = other.fSumOption;
440 
441  other.fCommonSumFill.Copy(fCommonSumFill);
442  other.fCommonSumLine.Copy(fCommonSumLine);
445 
446  fXTitle = other.fXTitle;
447  fYTitle = other.fYTitle;
449 
450  TIter nextC(&other.fCommon);
451  HolderCommon* common = 0;
452  while ((common = static_cast<HolderCommon*>(nextC())))
453  fCommon.Add(new HolderCommon(*common));
454 
455  TIter nextP(&other.fPoint2Point);
456  HolderP2P* p2p = 0;
457  while ((p2p = static_cast<HolderP2P*>(nextP())))
458  fPoint2Point.Add(new HolderP2P(*p2p));
459 
460  if (fMap) delete fMap;
461  fMap = 0;
462  if (other.fMap)
463  fMap = static_cast<TList*>(other.fMap->Clone());
464 
465  if (fQualifiers) delete fQualifiers;
466  fQualifiers = 0;
467  if (other.fQualifiers)
468  fQualifiers = static_cast<TList*>(other.fQualifiers->Clone());
469 
470  return *this;
471  }
472  /* @} */
473 
483  virtual void ls(Option_t* option="") const
484  {
485  Print(option);
486  }
492  virtual void Print(Option_t* option="R") const
493  {
494  gROOT->IndentLevel();
495  std::cout << GetName() << ": " << GetTitle() << std::endl;
496 
497  TString opt(option);
498  opt.ToUpper();
499  if (opt.IsNull()) return;
500 
501  Bool_t all = opt.Contains("ALL");
502  Bool_t keys = all || opt.Contains("KEY");
503  Bool_t qual = all || opt.Contains("QUAL");
504  Bool_t sys = all || opt.Contains("SYS");
505  Bool_t cmn = sys || opt.Contains("COMMON");
506  Bool_t p2p = sys || opt.Contains("P2P");
507  Bool_t poi = all || opt.Contains("XY");
508  Bool_t attr = all || opt.Contains("ATTR");
509  Bool_t sum = opt.Contains("SUM");
510 
511  gROOT->IncreaseDirLevel();
512  if (fMap && keys) {
513  gROOT->IndentLevel();
514  std::cout << "Key/value pairs: " << std::endl;
515  gROOT->IncreaseDirLevel();
516  TIter nextKV(fMap);
517  TObject* kv = 0;
518  while ((kv = nextKV())) {
519  gROOT->IndentLevel();
520  std::cout << '"' << kv->GetName() << '"' << "\t"
521  << '"' << kv->GetTitle() << '"' << "\n";
522  }
523  gROOT->IndentLevel();
524  std::cout << "\"XTitle\"\t\"" << fXTitle << "\"\n";
525  gROOT->IndentLevel();
526  std::cout << "\"YTitle\"\t\"" << fYTitle << "\"\n";
527  // fMap->Print(option);
528  gROOT->DecreaseDirLevel();
529  }
530  if (fQualifiers && qual) {
531  gROOT->IndentLevel();
532  std::cout << "Qualifier pairs: " << std::endl;
533  gROOT->IncreaseDirLevel();
534  TIter nextQ(fQualifiers);
535  TObject* q = 0;
536  while ((q = nextQ())) {
537  gROOT->IndentLevel();
538  std::cout << '"' << q->GetName() << '"' << "\t"
539  << '"' << q->GetTitle() << '"' << "\n";
540  }
541  // fQualifiers->ls(option);
542  gROOT->DecreaseDirLevel();
543  }
544  if (attr) {
545  gROOT->IndentLevel();
546  Printf(" [option: %3d line (c/s/w):%3d/%1d/%2d fill (c/s):%3d/%4d marker (c/s/s):%3d/%2d/%f]",
547  fDataOption, GetLineColor(), GetLineStyle(), GetLineWidth(),
548  GetFillColor(), GetFillStyle(),
549  GetMarkerColor(), GetMarkerStyle(), GetMarkerSize());
550  gROOT->IndentLevel();
551  Printf(" [sum title: %s "
552  "option: %3d line (c/s/w):%3d/%1d/%2d fill (c/s):%3d/%4d",
553  fSumTitle.Data(), fSumOption,
554  fSumLine.GetLineColor(),
555  fSumLine.GetLineStyle(),
556  fSumLine.GetLineWidth(),
557  fSumFill.GetFillColor(),
558  fSumFill.GetFillStyle());
559  gROOT->IndentLevel();
560  Printf(" [common sum title: %s "
561  "option: %3d line (c/s/w):%3d/%1d/%2d fill (c/s):%3d/%4d",
562  fCommonSumTitle.Data(),
564  fCommonSumLine.GetLineColor(),
565  fCommonSumLine.GetLineStyle(),
566  fCommonSumLine.GetLineWidth(),
567  fCommonSumFill.GetFillColor(),
568  fCommonSumFill.GetFillStyle());
569  }
570 
571  if (cmn) {
572  gROOT->IndentLevel();
573  std::cout << "Commons: " << std::endl;
574  gROOT->IncreaseDirLevel();
575  TIter nextC(&fCommon);
576  TObject* c = 0;
577  while ((c = nextC())) {
578  gROOT->IndentLevel();
579  c->Print(option);
580  }
581  // fCommon.Print(option);
582  gROOT->DecreaseDirLevel();
583  }
584 
585  if (p2p) {
586  gROOT->IndentLevel();
587  std::cout << "Point-to-point: " << std::endl;
588  gROOT->IncreaseDirLevel();
589  TIter nextP(&fPoint2Point);
590  TObject* p = 0;
591  while ((p = nextP())) {
592  gROOT->IndentLevel();
593  p->Print(option);
594  }
595  // fPoint2Point.Print(option);
596  gROOT->DecreaseDirLevel();
597  }
598  if (poi) {
599  // gROOT->IndentLevel();
600  gROOT->IndentLevel();
601  std::cout << "Points: " << std::endl;
602  gROOT->IncreaseDirLevel();
603  TString hs;
604  hs.Form(" %3s: %9s %9s %9s -> %9s %9s %9s",
605  "#", "X", "-dX", "+dX", "Y", "-stat", "+stat");
606  gROOT->IndentLevel();
607  std::cout << hs;
608  if (sum) {
609  hs.Form(" %9s %9s", "-sys", "+sys");
610  std::cout << hs;
611  }
612  else {
613  TIter nextP(&fPoint2Point);
614  HolderP2P* p = 0;
615  while ((p = static_cast<HolderP2P*>(nextP()))) {
616  Bool_t rel = p->IsRelative();
617  const char* post = (rel ? "%" : " ");
618  TString nm(p->GetTitle());
619  if (nm.Length() > 7) {
620  nm.Remove(4,nm.Length()-4);
621  nm.Append("...");
622  }
623  hs.Form(" -%8s%s +%8s%s", nm.Data(), post, nm.Data(), post);
624  std::cout << hs;
625  }
626  }
627  std::cout << std::endl;
628  for (Int_t i = 0; i < GetN(); i++) {
629  gROOT->IndentLevel();
630  Double_t eyl, eyh, wyl, wyh;
631  // point,stat,common,quad,nosqrt,eyl,eyh
632  Double_t y = GetYandError(i,false,false,true,false,eyl,eyh,wyl,wyh);
633  // Double_t y = GetY(i);
634  TString s;
635  s.Form(" %3d: %+8f -%7f +%7f -> %+8f -%7f +%7f",
636  i, GetX(i), GetErrorXLeft(i), GetErrorXRight(i),
637  y, GetStatErrorDown(i), GetStatErrorUp(i));
638  std::cout << s;
639  if (sum) {
640  TString sSum;
641  sSum.Form(" -%7f +%7f", eyl, eyh);
642  std::cout << sSum;
643  }
644  // if (sum && p2p) std::cout << " [";
645  else if (p2p) {
646  TIter nextP(&fPoint2Point);
647  HolderP2P* p = 0;
648  while ((p = static_cast<HolderP2P*>(nextP()))) {
649  Bool_t rel = p->IsRelative();
650  Double_t fac = (rel ? (TMath::Abs(y) > 1e-9 ? 100/y : 0) : 1);
651  const char* post = (rel ? "%" : " ");
652  s.Form(" -%7f%s +%7f%s",
653  fac * p->GetYDown(i), post,
654  fac * p->GetYUp(i) , post);
655  std::cout << s;
656  }
657  }
658  // if (sum && p2p) std::cout << " ]";
659  std::cout << std::endl;
660  } // for i
661  gROOT->DecreaseDirLevel();
662  } // if poi
663  gROOT->DecreaseDirLevel();
664  } //*MENU*
670  virtual Bool_t IsFolder() const { return true; }
676  virtual void Browse(TBrowser* b)
677  {
678  if (fMap) b->Add(fMap);
679  if (fQualifiers) b->Add(fQualifiers);
680  b->Add(&fCommon);
681  b->Add(&fPoint2Point);
682  if (fData) b->Add(fData);
683  if (fDrawn) b->Add(fDrawn);
684  }
685  /* @} */
781  void Draw(Option_t* option="")
782  {
783  TString opt(option);
784  opt.ToUpper();
785  Bool_t clear = opt.Contains("CLEAR");
786  Bool_t axis = opt.Contains("AXIS");
787  // --- Optionally clear old stack --------------------------------
788  if (clear && fDrawn) {
789  delete fDrawn;
790  fDrawn = 0;
791  }
792 
793  fDrawn = MakeMulti(option);
794  if (!fDrawn) return;
795 
796  fDrawn->Draw(axis ? "A" : "");
797  if (axis) {
798  fDrawn->GetHistogram()->SetXTitle(fXTitle);
799  fDrawn->GetHistogram()->SetYTitle(fYTitle);
800  }
801  } //*MENU*
823  TFitResultPtr Fit(TF1* f1, Option_t* fitOption, Option_t* drawOption,
824  Axis_t min=0, Axis_t max=0)
825  {
826  TString dOpt(drawOption);
827  dOpt.ToUpper();
828  Bool_t clear = dOpt.Contains("CLEAR");
829  Bool_t axis = dOpt.Contains("AXIS");
830 
831  if (clear && fDrawn) {
832  delete fDrawn;
833  fDrawn = 0;
834  }
835 
836  fDrawn = MakeMulti(drawOption);
837  if (!fDrawn ||
838  !fDrawn->GetListOfGraphs() ||
839  !fDrawn->GetListOfGraphs()->First())
840  return TFitResultPtr(-1);
841  // fDrawn->GetListOfGraphs()->ls();
842  Graph* g = static_cast<Graph*>(fDrawn->GetListOfGraphs()->First());
843 
844  TString fOpt(fitOption);
845  fOpt.ToUpper();
846  Bool_t noStore = fOpt.Contains("N");
847  Bool_t noDraw = fOpt.Contains("0");
848  Bool_t range = fOpt.Contains("R");
849  fOpt.Append("N0");
850  TFitResultPtr r = g->Fit(f1, fOpt.Data(), "", min, max);
851 
852  if (!noStore) {
853  Int_t status = r;
854  if (status == 0) {
855  if (min < max && !range) f1->SetRange(min, max);
856  fDrawn->GetListOfFunctions()->Add(f1);
857  }
858  }
859 
860  if (!noStore && !noDraw) {
861  fDrawn->Draw(axis ? "A" : "");
862  if (axis) {
863  fDrawn->GetHistogram()->SetXTitle(fXTitle);
864  fDrawn->GetHistogram()->SetYTitle(fYTitle);
865  }
866  }
867 
868  return r;
869  }
891  TFitResultPtr Fit(const char* formula,
892  Option_t* fitOption, Option_t* drawOption,
893  Axis_t min=0, Axis_t max=0)
894  {
895  TString fname(formula);
896  Bool_t linear = fname.Contains("++");
897  TF1* f1 = 0;
898  if (linear) f1 = new TF1(formula,formula,min,max);
899  else {
900  f1 = static_cast<TF1*>(gROOT->GetFunction(formula));
901  if (!f1) Warning("Fit", "Unknown function %s", formula);
902  }
903  if (!f1) return -1;
904 
905  return Fit(f1, fitOption, drawOption, min, max);
906  }
914  TMultiGraph* GetMulti(Option_t* option="")
915  {
916  if (!fDrawn) fDrawn = MakeMulti(option);
917  return fDrawn;
918  }
919  /* @} */
930  void Scale(TF1* f, Double_t s=1)
931  {
932  HolderCommon* cmn = 0;
933  TIter cNext(&fCommon);
934  while ((cmn = static_cast<HolderCommon*>(cNext()))) {
935  if (cmn->IsRelative())
936  // Do not scale relative errors - they scale by themselves
937  continue;
938  cmn->Set(cmn->GetYDown()/s, cmn->GetYUp()/s);
939  }
940  for (Int_t i = 0; i < GetN(); i++) {
941  Double_t x = GetX(i);
942  Double_t y = GetY(i);
943  Double_t g = f->Eval(x);
944  SetPoint(i, GetX(i), y/g);
946 
947  HolderP2P* p2p = 0;
948  TIter pNext(&fPoint2Point);
949  while ((p2p = static_cast<HolderP2P*>(pNext()))) {
950  Double_t fac = (p2p->IsRelative() ?
951  (TMath::Abs(y) < 1e-9) ? 0 : 1/y : 1/g);
952  SetSysError(p2p->GetUniqueID(), i,
953  p2p->GetXLeft(i), p2p->GetXRight(i),
954  fac*p2p->GetYDown(i), fac*p2p->GetYUp(i));
955  }
956  }
957  }
963  void Scale(Double_t s)
964  {
965  HolderCommon* cmn = 0;
966  TIter cNext(&fCommon);
967  while ((cmn = static_cast<HolderCommon*>(cNext()))) {
968  if (cmn->IsRelative())
969  // Do not scale relative errors - they scale by themselves
970  continue;
971  cmn->Set(s * cmn->GetYDown(), s * cmn->GetYUp());
972  }
973  for (Int_t i = 0; i < GetN(); i++) {
974  Double_t y = GetY(i);
975  SetPoint(i, GetX(i), s*y);
977 
978  HolderP2P* p2p = 0;
979  TIter pNext(&fPoint2Point);
980  while ((p2p = static_cast<HolderP2P*>(pNext()))) {
981  Double_t fac = (p2p->IsRelative() ?
982  (TMath::Abs(y) < 1e-9) ? 0 : 1/y :
983  s);
984  SetSysError(p2p->GetUniqueID(), i,
985  p2p->GetXLeft(i), p2p->GetXRight(i),
986  fac*p2p->GetYDown(i), fac*p2p->GetYUp(i));
987  }
988  }
989  }
1003  Int_t Average(const TCollection* others, Bool_t sep=true)
1004  {
1005  const Double_t tol = 1e-9;
1006  TList sharedC; sharedC.SetOwner();
1007  TList sharedP;
1008  TIter oNext(others);
1009  GraphSysErr* other = 0;
1010  Double_t xMin = +1e9;
1011  Double_t xMax = -1e9;
1012  Int_t nX = 0;
1013  Bool_t first = true;
1014  Bool_t nonSh = false;
1015  Int_t npS = 0;
1016  // Here, we do some initial investigations into the the passed
1017  // graphs. We should find all common errors that are shared amoung
1018  // the input graphs, and we need to check for the consistency of
1019  // those.
1020  while ((other = static_cast<GraphSysErr*>(oNext()))) {
1021  Int_t n = other->GetN();
1022  nX = TMath::Max(nX,n);
1023  xMin = TMath::Min(xMin,other->GetX(0) -2*other->GetErrorXLeft(0));
1024  xMax = TMath::Max(xMax,other->GetX(n-1)+2*other->GetErrorXRight(n-1));
1025 
1026  if (first) {
1027  // For the first graph, we simply add the title of all the
1028  // common systematics.
1029  HolderCommon* cmn = 0;
1030  TIter cNext(&other->fCommon);
1031  while ((cmn = static_cast<HolderCommon*>(cNext()))) {
1032  HolderCommon* o = static_cast<HolderCommon*>(cmn->Clone());
1033  sharedC.Add(o);
1034  }
1035  if (sep) {
1036  // and then the same for the point to point
1037  HolderP2P* p2p = 0;
1038  TIter pNext(&other->fPoint2Point);
1039  while ((p2p = static_cast<HolderP2P*>(pNext()))) {
1040  sharedP.Add(p2p->Clone());
1041  }
1042  }
1043 
1044  // We also copy the keys
1045  CopyKeys(other, "ar");
1046  }
1047  else {
1048  // Otherwise, we check that this graph has all the common
1049  // errors in our temporary list, and if not, we remove that
1050  // error from the list
1051  TObjLink* cur = sharedC.FirstLink();
1052  while (cur) {
1053  HolderCommon* o = static_cast<HolderCommon*>(cur->GetObject());
1054  HolderCommon* c = other->FindCompat(o, tol, true);
1055  if (!c) {
1056  // This error not found in the graph we're looking at.
1057  // Remove it from the list
1058  Info("Average", "Common systematic %s not found in %s",
1059  o->GetTitle(), other->GetName());
1060  other->Print("sys");
1061  TObjLink* keep = cur->Next();
1062  TObject* obj = sharedC.Remove(cur);
1063  cur = keep;
1064  nonSh = true;
1065  if (obj) delete obj;
1066  continue;
1067  }
1068  cur = cur->Next();
1069  } // while cur
1070 
1071  // Now check the point-to-point errors
1072  cur = sharedP.FirstLink();
1073  while (cur) {
1074  HolderP2P* o = static_cast<HolderP2P*>(cur->GetObject());
1075  HolderP2P* p = other->FindCompat(o);
1076  if (!p) {
1077  // This error not found in the graph we're looking at.
1078  // Remove it from the list
1079  Info("Average", "P2P systematic %s not found in %s",
1080  o->GetTitle(), other->GetName());
1081  TObjLink* keep = cur->Next();
1082  TObject* obj = sharedP.Remove(cur);
1083  cur = keep;
1084  npS++;
1085  if (obj) delete obj;
1086  continue;
1087  }
1088  cur = cur->Next();
1089  } // while cur
1090  } // else
1091  first = false;
1092  } // while cmn
1093  // Now we have the list of common errors that are shared amoung
1094  // all the input graphs. So we define those new common errors on
1095  // this graph, and disable them on the inputs.
1096  TIter nextC(&sharedC);
1097  HolderCommon* com = 0;
1098  while ((com = static_cast<HolderCommon*>(nextC()))) {
1099  Int_t cId = DefineCommon(com->GetTitle(), com->IsRelative(),
1100  com->GetYDown(1), com->GetYUp(1), kBox);
1101  HolderCommon* c = FindCommon(cId);
1102  c->CopyAttr(com);
1103  // Info("Average", "Shared common error %s +%7f%s -%7f%s",
1104  // c->GetTitle(),
1105  // c->GetYDown(1), (c->IsRelative() ? "%" : ""),
1106  // c->GetYUp(1), (c->IsRelative() ? "%" : ""));
1107 
1108  // Now loop over all input graphs, find the shared commons, and
1109  // mark them as used.
1110  oNext.Reset();
1111  while ((other = static_cast<GraphSysErr*>(oNext()))) {
1112  HolderCommon* oc = other->FindCompat(c, tol, true);
1113  if (!oc) {
1114  Error("Average", "This should NOT happen");
1115  other->Print("sys");
1116  continue;
1117  }
1118  oc->SetBit(kUsedBit);
1119  } // while other
1120  } // while com
1121  sharedC.Clear();
1122  // If we found some common errors that are not shared, we need to
1123  // make a point-to-point error for absorbing the remaining common
1124  // errors.
1125  Int_t bId = 0;
1126  if (nonSh || !sep) {
1127  bId = DeclarePoint2Point("Blob", false, kBox);
1128  SetSysFillColor(bId, kRed+2);
1129  SetSysLineColor(bId, kRed+2);
1130  SetSysFillStyle(bId, 3004);
1131  }
1132 
1133  // At this point, we have found all the common shared errors and
1134  // added those to ourselves. Those that are not shared go into the
1135  // blob point-to-point error.
1136  //
1137  // Next step, is to deal with the shared point-to-point errors.
1138  // If we have shared point-to-point errors, we need to deal with
1139  // them separately. To do that, we make a list of identifiers
1140  // that we should inspect at each X value. The identifiers point
1141  // to the p2p errors of each input graph.
1142  //
1143  TArrayL64 mp2p;
1144  Int_t dOf = 6;
1145  if (sep) {
1146  TIter nextP(&sharedP);
1147  HolderP2P* p2p = 0;
1148  Int_t j = 0;
1149  mp2p.Set(100);
1150  while ((p2p = static_cast<HolderP2P*>(nextP()))) {
1151  // Info("Average", "Loop %d shared P2P %s", j, p2p->GetTitle());
1152  Int_t pId = DeclarePoint2Point(p2p->GetTitle(),
1153  p2p->IsRelative(), kBox);
1154  HolderP2P* p = FindP2P(pId);
1155  p->CopyAttr(p2p);
1156  Info("Average", "Shared point-to-point error %s", p->GetTitle());
1157 
1158  // Now loop over all input graphs, find the shared commons, and
1159  // mark them as used.
1160  oNext.Reset();
1161  Long64_t mask = 0;
1162  Int_t off = 0;
1163  while ((other = static_cast<GraphSysErr*>(oNext())) && off < 64) {
1164  HolderP2P* op = other->FindCompat(p, true);
1165  if (!op) {
1166  Error("Average", "This should NOT happen");
1167  continue;
1168  }
1169  mask |= ((op->GetUniqueID() & 0x3F) << off);
1170  off += dOf;
1171  // Info("Average", "Mark %s as used", op->GetTitle());
1172  op->SetBit(kUsedBit);
1173  } // while other
1174  if (off >= 64) {
1175  Warning("Average",
1176  "Some shared point-to-point errors could not be encoded "
1177  "becasue we have too many (%d>%d) input graphs",
1178  others->GetEntries(), 64/dOf);
1179  }
1180  mp2p[pId] = mask;
1181  j++;
1182  } // while p2p
1183  // Info("Average", "Declared new shared P2P - mapping:");
1184  // for (Int_t j = 1; j < mp2p.GetSize(); j++) {
1185  // if (mp2p[j] == 0) continue;
1186  // rintf("%3d/%3d", j, mp2p.GetSize());
1187  // for (Int_t k = 0; k < 64; k += dOf)
1188  // printf(" %3d", (mp2p[j] >> k) & 0x3f);
1189  // printf("\n");
1190  // }
1191 
1192  // sharedP.Clear();
1193  // Now we have all shared point-to-point errors defined, and we
1194  // have the ids for each graph in the shar array (6bits each).
1195  //
1196  // Next, we will declare _all_ other our point-to-point errors
1197  // separately on this graph. That means that the point-to-point
1198  // errors can be 0 in some ranges.
1199  oNext.Reset();
1200  Int_t off = 0;
1201  while ((other = static_cast<GraphSysErr*>(oNext()))) {
1202  Long64_t* mask = 0;
1203  TIter oNextP(&(other->fPoint2Point));
1204  HolderP2P* p2p = 0;
1205  while ((p2p = static_cast<HolderP2P*>(oNextP())) && off < 64) {
1206  if (p2p->TestBit(kUsedBit)) {
1207  // Info("Average", "%s marked as used", p2p->GetTitle());
1208  continue; // Already in the shared part
1209  }
1210 
1211  // The point-to-point error should go into the weight, but not
1212  // in the result.
1213  p2p->SetBit(kOnlyWeightBit);
1214  Int_t pId = 0;
1215  HolderP2P* p = FindCompat(p2p);
1216  if (!p) {
1217  pId = DeclarePoint2Point(p2p->GetTitle(), p2p->IsRelative(), kBox);
1218  p = FindP2P(pId);
1219  p->CopyAttr(p2p);
1220  mask = &(mp2p[pId]);
1221 
1222  }
1223  *mask |= ((p2p->GetUniqueID() & 0x3F) << off);
1224  }
1225  off += dOf;
1226  } // while other
1227  if (off >= 64) {
1228  Warning("Average",
1229  "Some shared point-to-point errors could not be encoded "
1230  "becasue we have too many (%d>%d) input graphs",
1231  others->GetEntries(), 64/dOf);
1232  }
1233  // Info("Average", "Declared new shared P2P - mapping:");
1234  // for (Int_t j = 0; j < mp2p.GetSize(); j++) {
1235  // if (mp2p[j] == 0) continue;
1236  // printf("%3d/%3d", j, mp2p.GetSize());
1237  // for (Int_t k = 0; k < 64; k += dOf)
1238  // printf(" %3d", (mp2p[j] >> k) & 0x3f);
1239  // printf("\n");
1240  // }
1241  }
1242 
1243  // Now search for the X values to evaluate at
1244  Double_t x = xMin;
1245  Double_t oldX = xMin;
1246  Int_t cnt = 0;
1247  TArrayD xa(2*nX); // Assume no more than 100 points
1248  TArrayD exla(2*nX);
1249  TArrayD exha(2*nX);
1250  do {
1251  // Find the next X to evaluate at
1252  oNext.Reset();
1253  Double_t nextX = xMax;
1254  Double_t texl = 0;
1255  Double_t texh = 0;
1256  // Info("Average", "nextX=%f xMax=%f", nextX, xMax);
1257  while ((other = static_cast<GraphSysErr*>(oNext()))) {
1258  for (Int_t i = other->GetUniqueID(); i < other->GetN(); i++) {
1259  if (other->GetX(i) <= x) {
1260  // Info("Average", "- x_i=%f < x=%f", g->GetX(i), x);
1261  continue;
1262  }
1263  if (other->GetX(i) < nextX) {
1264  // Info("Average", "Set x to %f (was %f)", g->GetX(i), nextX);
1265  nextX = other->GetX(i);
1266  texl = TMath::Max(texl, other->GetErrorXLeft(i));
1267  texh = TMath::Max(texh, other->GetErrorXRight(i));
1268  }
1269  else {
1270  // g->SetUniqueID(i);
1271  // Info("Average", "No more (%s) here at x=%f (next=%f)",
1272  // g->GetName(), g->GetX(i), nextX);
1273  break;
1274  }
1275  }
1276  }
1277  if (nextX >= xMax) {
1278  // Info("Average", "Next x is too large %f>%f", nextX, xMax);
1279  break;
1280  }
1281 
1282  if (cnt >= xa.GetSize()) {
1283  Warning("Average", "increasing size of X cache");
1284  xa.Set(1.5*cnt);
1285  exla.Set(1.5*cnt);
1286  exha.Set(1.5*cnt);
1287  }
1288  // Info("Average", "Set next x to %f +/- (%f,%f)", nextX, texl, texh);
1289  xa[cnt] = nextX;
1290  exla[cnt] = texl;
1291  exha[cnt] = texh;
1292  Double_t dx = texh*2;//(nextX-oldX);
1293  oldX = x;
1294  x = nextX+dx/4;
1295  cnt++;
1296  } while (cnt < 1000); // Do not go for more than 1000 points
1297  // At this point we have
1298  //
1299  // - All common errors defined, and we have set the shared ones
1300  // - All point-to-point errors defined, and we know which input
1301  // graph contributes to each.
1302  // - A list of X values to evaluate each graph at.
1303 
1304  // Print("sys");
1305  // Now we loop over the list of X values and evaluate each graph
1306  // at that X value.
1307  for (Int_t i = 0; i < cnt; i++) {
1308  Double_t xi = xa[i];
1309  Double_t texl = exla[i];
1310  Double_t texh = exha[i];
1311  Double_t nexl = TMath::Abs(xi - (i == 0 ? xa[i+1] : xa[i-1]))/2;
1312  Double_t nexh = TMath::Abs(xi - (i + 1 == cnt ? xa[i-1] : xa[i+1]))/2;
1313  Double_t exl = TMath::Min(texl, nexl);
1314  Double_t exh = TMath::Min(texh, nexh);
1315  // Info("Average", "@ %3d x=%f, exl=min(%f,%f)=%f exh=min(%f,%f)=%f",
1316  // i, xi, texl, nexl, exl, texh, nexh, exh);
1317 
1318 
1319  // Now loop again - this time calculating our data point
1320  Double_t sum = 0;
1321  Double_t sumW = 0;
1322  // Double_t sumWS = 0;
1323  Double_t sumE = 0;
1324  Double_t sumES = 0;
1325  oNext.Reset();
1326 
1327  // Use our combiner framework for calculating the averaged
1328  // result and errors. Note, we define two combiners. One that
1329  // include all non-shared common and point-to-point errors
1330  // (centroid), and one that doesn't have the non-shared common
1331  // and point-to-point errors as well as the split point-to-point
1332  // errors (error). The first one is used to set the centroid of
1333  // the data, while the second is used to set the combined error
1334  LinearSigmaCombiner centroid;
1335  LinearSigmaCombiner error;
1336  LinearSigmaCombiner stats;
1337  Int_t j = 0;
1338  TArrayI ai1(others->GetEntries());
1339  TArrayI ai2(others->GetEntries());
1340  TArrayD ax(others->GetEntries());
1341  while ((other = static_cast<GraphSysErr*>(oNext()))) {
1342  Bool_t cmn = true; // Include the common errors
1343  Bool_t stat = false; // Include the statistical errors
1344  Bool_t quad = true; // Add in quadrature
1345  Bool_t nosqrt = false; // Do not return squared error
1346 
1347  Double_t y, eyl, eyh, wyl, wyh, syl, syh;
1348 
1349  Int_t fret = other->FindPoint(xi, ai1[j], ai2[j]);
1350  if (fret < -1) { j++; continue; } // Nothing here
1351  if (fret >= 0) {
1352  y = other->GetYandError(fret,cmn,stat,quad,nosqrt,eyl, eyh, wyl, wyh);
1353  syl = other->GetStatErrorDown(fret);
1354  syh = other->GetStatErrorUp(fret);
1355  }
1356  else {
1357  Double_t eyl1, eyh1, wyl1, wyh1;
1358  Double_t eyl2, eyh2, wyl2, wyh2;
1359  Double_t x1 = other->GetX(ai1[j]);
1360  Double_t x2 = other->GetX(ai2[j]);
1361  Double_t y1 = other->GetYandError(ai1[j],cmn,stat,quad,nosqrt,
1362  eyl1,eyh1,wyl1,wyh1);
1363  Double_t y2 = other->GetYandError(ai2[j],cmn,stat,quad,nosqrt,
1364  eyl2,eyh2,wyl2,wyh2);
1365  Double_t syl1 = other->GetStatErrorDown(ai1[j]);
1366  Double_t syh1 = other->GetStatErrorUp(ai1[j]);
1367  Double_t syl2 = other->GetStatErrorDown(ai2[j]);
1368  Double_t syh2 = other->GetStatErrorUp(ai2[j]);
1369  Double_t dx = (x2-x1);
1370  ax[j] = (xi-x1)/dx;
1371  y = y1 + ax[j] * (y2-y1);
1372  eyl = eyl1 + ax[j] * (eyh1-eyl1);
1373  eyh = eyh2 + ax[j] * (eyh2-eyl2);
1374  wyl = wyl1 + ax[j] * (wyh1-wyl1);
1375  wyh = wyh2 + ax[j] * (wyh2-wyl2);
1376  syl = syl1 + ax[j] * (syh1-syl1);
1377  syh = syh2 + ax[j] * (syh2-syl2);
1378  }
1379 
1380  centroid.Add(y, wyl, wyh);
1381  error.Add(y, eyl, eyh);
1382  stats.Add(y, syl, syh);
1383  j++;
1384  } // while (other)
1385  centroid.Calculate();
1386  // Info("Average", "Centroid");
1387  // centroid.Print();
1388  // centroid.fResult->Print();
1389  Double_t newY = centroid.fResult->fX;
1390  SetPoint(i, xi, newY);
1391  SetPointError(i, exl, exh);
1392 
1393  stats.Calculate();
1394  // Info("Average", "Stats");
1395  // stats.Print();
1396  // stats.fResult->Print();
1397  stats.Calculate();
1398  Double_t fac = IsStatRelative() ? 1/newY : 1;
1399  SetStatError(i, fac*stats.fResult->fEl,fac*stats.fResult->fEh);
1400 
1401  if (bId > 0) {
1402  // Calculations for error
1403  error.Calculate();
1404  // Info("Average", "Error");
1405  // error.Print();
1406  // error.fResult->Print();
1407 
1408  fac = IsRelative(bId) ? 1/newY : 1;
1409  SetSysError(bId,i,0,0,fac*error.fResult->fEl,fac*error.fResult->fEh);
1410  }
1411 
1412  // Now, we have set the blob point-to-point error. Next, we
1413  // need to do the point-to-point erros that should be transfered
1414  // to the output. We have stored masks of IDs in mp2p, so we
1415  // loop over that array first. The lower 6 bits is the output
1416  // Id, while the remaining bits (counting from the low side) are
1417  // ids for each input graph.
1418  for (Int_t j = 1; j < mp2p.GetSize(); j++) {
1419  Long64_t mask = mp2p[j];
1420  if (mask == 0) continue;
1421  Int_t tid = j; // (mask & 0x3f);
1422  HolderP2P* tp2p = FindP2P(tid);
1423  if (!tp2p) {
1424  Warning("Average", "No target point-to-point error at %d for id=%d",
1425  j, tid);
1426  continue;
1427  }
1428  // Zero by default
1429  SetSysError(tid, i, 0, 0);
1430  Long64_t rem = mask;
1431  if (rem == 0)
1432  // There's no IDs for this, explicitly set the value to 0
1433  continue;
1434 
1435  // Now we should loop over all the input graphs and get the
1436  // error and finally combine them into one. Again, we use a
1437  // linear sigma approximation from our combiner framework to
1438  // do the calculations.
1440  Int_t k = 0; // Index into index array and for off set in mask
1441  oNext.Reset();
1442  while ((other = static_cast<GraphSysErr*>(oNext()))) {
1443  if (ai1[k] == -1 && ai2[k] == -1) {
1444  // This graph does not contribute at this point
1445  // Info("Average", "No contribution at %f (%d:%d,%d) for %s to %s",
1446  // xi, k, ai1[k], ai2[k], other->GetName(), tp2p->GetTitle());
1447  k++;
1448  continue;
1449  }
1450  Int_t sid = ((rem >> dOf*k) & 0x3f);
1451  if (sid <= 0) {
1452  // This graph does not contribute to this error
1453  // Info("Average",
1454  // "No contribution for %s to %s, not found [%d:%d,%d]",
1455  // other->GetName(), tp2p->GetTitle(), k, ai1[k], ai2[k]);
1456  k++;
1457  continue;
1458  }
1459  HolderP2P* sp2p = other->FindP2P(sid);
1460  if (!sp2p) {
1461  Warning("Average", "Couldn't find point-to-point error %d (%s)"
1462  "in graph %d (%s) - should not happen",
1463  sid, tp2p->GetTitle(), k, other->GetName());
1464  k++;
1465  }
1466  Double_t sy = 0;
1467  Double_t seyl = 0;
1468  Double_t seyh = 0;
1469  if (ai1[k] == ai2[k]) {
1470  // Exact point
1471  sy = other->GetY(ai1[k]);
1472  seyl = other->GetSysErrorYDown(sid, ai1[k]);
1473  seyh = other->GetSysErrorYUp(sid, ai1[k]);
1474  }
1475  else {
1476  // Interpolate
1477  Double_t sy1 = other->GetY(ai1[k]);
1478  Double_t sy2 = other->GetY(ai2[k]);
1479  sy = sy1 + ax[k] * (sy2-sy1);
1480  seyl = sp2p->GetYDown(ai1[k],ai2[k],ax[k]);
1481  seyh = sp2p->GetYUp(ai1[k],ai2[k],ax[k]);
1482  }
1483  //Info("Average", "Contribution (%d:%d-%d:%f,%f) to %s from %s",
1484  // k,ai1[k],ai2[k],seyl,seyh,tp2p->GetTitle(),other->GetName());
1485  sc.Add(sy, seyl, seyh);
1486  k++;
1487  } // while other
1488  sc.Calculate();
1489  // Info("Average", "%s", tp2p->GetTitle());
1490  // sc.Print();
1491  // sc.fResult->Print();
1492  fac = IsRelative(tid) ? 1/newY : 1;
1493  SetSysError(tid, i, 0, 0, fac*sc.fResult->fEl, fac*sc.fResult->fEh);
1494  } // for j (# of p2p)
1495  } // for i (points)
1496 
1497  oNext.Reset();
1498  while ((other = static_cast<GraphSysErr*>(oNext())))
1499  other->ClearUsed();
1500  ClearUsed();
1501 
1502  return bId;
1503  }
1514  Double_t Integral(Double_t& error,
1515  Option_t* option="quad sum stat",
1516  UShort_t first=0,
1517  Short_t last=-1)
1518  {
1519  if (last < 0) last = GetN()-1;
1520  Double_t sum = 0;
1521  Double_t err2 = 0;
1522  TString opts(option); opts.ToLower();
1523  Bool_t cmn = opts.Contains("comm");
1524  Bool_t stat = opts.Contains("stat");
1525  Bool_t quad = opts.Contains("quad");
1526 
1527  for (Short_t i = first; i <= last; i++) {
1528  Double_t eyl, eyh;
1529  Double_t y = GetYandError(i, cmn, stat, quad, false, eyl, eyh);
1530  Double_t eym = (eyh+eyl)/2;
1531  Double_t x = GetX(i);
1532  Double_t exl = GetErrorXLeft(i);
1533  Double_t exr = GetErrorXRight(i);
1534  Double_t x1 = x - exl;
1535  Double_t x2 = x + exr;
1536  Double_t prv = x1;
1537  Double_t nxt = x2;
1538  if (i-1 >= 0) prv = GetX(i-1)+GetErrorXRight(i-1);
1539  if (i+1 < GetN()) nxt = GetX(i+1)-GetErrorXLeft(i+1);
1540  if (prv > x1) x1 -= (prv-x1)/2; // Adjust to half-ways
1541  if (nxt < x2) x2 -= (x2-nxt)/2; // Adjust to half-ways
1542  Double_t wdt = (x2-x1);
1543  if (wdt < 0) continue; // Do not take this point
1544  sum += wdt * y;
1545  err2 += TMath::Power(eym*wdt,2);
1546  }
1547  error = TMath::Sqrt(err2);
1548  return sum;
1549  }
1566  static Bool_t NextPoint(Int_t i,
1567  const GraphSysErr* num,
1568  const GraphSysErr* denom,
1569  Double_t& x,
1570  Double_t& dY,
1571  Double_t& dEyl,
1572  Double_t& dEyh,
1573  Double_t& nY,
1574  Double_t& nEyl,
1575  Double_t& nEyh)
1576  {
1577  x = num->GetX(i);
1578  if (!denom->FindYandError(x, false, true, true, false, dY, dEyl, dEyh))
1579  return false;
1580  if (TMath::Abs(dY) < 1e-9)
1581  return false;
1582 
1583  nY = num->GetYandError(i,false,true,true,false,nEyl, nEyh);
1584  return true;
1585  }
1586 
1598  static GraphSysErr* Ratio(const GraphSysErr* num,
1599  const GraphSysErr* den,
1600  UInt_t flags=kRatioDefault,
1601  Double_t fac=1)
1602  {
1603  // num->Print("sys");
1604  // den->Print("sys");
1605  num->ClearUsed();
1606  den->ClearUsed();
1607  GraphSysErr* ret = new GraphSysErr(1);
1608  ret->CopyAttr(num);
1609  ret->CopyKeys(num, "ar");
1610  Bool_t emax = (flags & kMax);
1611  Bool_t cmin = (flags & kMin);
1612  Bool_t cmax = (flags & kMax);
1613  Bool_t denrel = (flags & kDenomRel);
1614  Bool_t cancc = (flags & kCancel);
1615  Int_t id = 0;
1616  Int_t notUsed = 0;
1617  // Loop over all common errors in the numerator, and see if we
1618  // have the same common error in the denominator. If we do, we
1619  // can (partially) cancel this common error.
1620  //
1621  // Technically, we mark each used common error as used, and create
1622  // a new common error in the output graph.
1623  //
1624  // Common errors that are not shared by both the numerator and the
1625  // denominator will not be cancelled. Instead, if they are
1626  // relative, they will be added to the output graph directly.
1627  // Finally, common systematic errors that are not cancelled or are
1628  // not relative, will go into the blob of point-to-point errors
1629  TIter nextNC(&num->fCommon);
1630  HolderCommon* comN = 0;
1631  while ((comN = static_cast<HolderCommon*>(nextNC()))) {
1632  Bool_t rel = comN->IsRelative();
1633  Double_t eyl = comN->GetYDown(1);
1634  Double_t eyh = comN->GetYUp(1);
1635  Int_t idD = den->FindId(comN->GetTitle());
1636  HolderCommon* comD = 0;
1637  if (idD != 0 && // Check it exists
1638  (comD = den->FindCommon(idD)) && // Check it is a common
1639  (rel == comD->IsRelative())) { // Same as this
1640  // We found the same error in the denominator, so we need to
1641  // cancel errors here.
1642  Double_t dEyl = comD->GetYDown(1);
1643  Double_t dEyh = comD->GetYUp(1);
1644  Double_t nEyl = comN->GetYDown(1);
1645  Double_t nEyh = comN->GetYUp(1);
1646  if (cmin) {
1647  eyl = TMath::Min(nEyl, dEyl);
1648  eyh = TMath::Min(nEyh, dEyh);
1649  }
1650  else if (cmax) {
1651  eyl = TMath::Max(nEyl, dEyl);
1652  eyh = TMath::Max(nEyh, dEyh);
1653  }
1654  else if (cancc) {
1655  eyl = TMath::Sqrt(TMath::Abs(dEyl*dEyl-nEyl*nEyl));
1656  eyh = TMath::Sqrt(TMath::Abs(dEyh*dEyh-nEyh*nEyh));
1657  }
1658  const char* post = (rel ? "%" : "");
1659  Double_t pfc = (rel ? 100 : 1);
1660 
1661  if (kVerbose & kRatio)
1662  ::Info("Ratio", "Cancelling the common systematic error %s "
1663  "between numerator (-%f%s +%f%s) "
1664  "and denominator (-%f%s +%f%s): -%f%s + %f%s",
1665  comD->GetTitle(),
1666  pfc*nEyl, post, pfc*nEyh, post,
1667  pfc*dEyl, post, pfc*dEyh, post,
1668  pfc*eyl, post, pfc*eyh, post);
1669 
1670  // Flag the denominator error as used
1671  comD->SetBit(kUsedBit);
1672  }
1673  else if (!rel) {
1674  // We cannot cancel, and it is not relative, add to blob
1675  if (kVerbose & kRatio)
1676  ::Info("Ratio",
1677  "Common numerator systematic %s will be added to blob",
1678  comN->GetTitle());
1679  notUsed++; // Count how many we're not setting directly
1680  continue;
1681  }
1682  // Now we can define our common error. Which value we set depend
1683  // on whether the error was cancelled with the denominator
1684  Int_t cId = ret->DefineCommon(comN->GetTitle(),rel,
1685  eyl, eyh, kBox);
1686  HolderCommon* c = ret->FindCommon(cId);
1687  c->CopyAttr(comN);
1688  // Flag the numerator error as used
1689  comN->SetBit(kUsedBit);
1690  }
1691  // Loop over all denominator common systematic errors. If it is
1692  // not cancelled with the numerator and is relative, we define a
1693  // new error on the output ratio. Otherwise it will be absorbed in a blob
1694  TIter nextDC(&den->fCommon);
1695  HolderCommon* comD = 0;
1696  while ((comD = static_cast<HolderCommon*>(nextDC()))) {
1697  if (comD->TestBit(kUsedBit)) continue;
1698  if (!comD->IsRelative()) {
1699  if (kVerbose & kRatio)
1700  ::Info("Ratio",
1701  "Common denominator systematic %s will be added to blob",
1702  comD->GetTitle());
1703  notUsed++; // Count how many we're not setting directly
1704  continue;
1705  }
1706  if (kVerbose & kRatio)
1707  ::Info("Ratio", "Propagating common sysmatic %s to ratio",
1708  comD->GetTitle());
1709  // ret->Print("sys");
1710  // Now we can define our common error. Which value we set depend
1711  // on whether the error was cancelled with the denominator
1712  Int_t cId = ret->DefineCommon(comD->GetTitle(),true,
1713  comD->GetYDown(1),
1714  comD->GetYUp(1),
1715  kBox);
1716  HolderCommon* c = ret->FindCommon(cId);
1717  c->CopyAttr(comD);
1718  // Flag the denominator error as used
1719  comD->SetBit(kUsedBit);
1720  // ret->Print("sys");
1721  }
1722 
1723  // Loop over all point-to-point errors in the numerator, and see
1724  // if we have the same point-to-point error in the denominator.
1725  // If we do, we can (partially) cancel this point-to-point error.
1726  //
1727  // Technically, we mark each used point-to-point error as used.
1728  //
1729  // Point-to-point errors that are not shared by both the numerator
1730  // and the denominator will not be cancelled. Instead, they will
1731  // be added in on the residual point-to-point sum (in quadrature)
1732  // error.
1733  //
1734  // We encode the IDs of the
1735  // errors in a single mask.
1736  //
1737  // 24 -------- 16 -------- 8 -------- 0
1738  // | Denom ID | Num ID | Ratio ID |
1739  // +-----------+----------+----------+
1740  //
1741  Int_t sCnt = 0;
1742  TArrayI shared(num->fPoint2Point.GetEntries() +
1743  den->fPoint2Point.GetEntries());
1744  TIter nextNP(&num->fPoint2Point);
1745  HolderP2P* p2pN = 0;
1746  while ((p2pN = static_cast<HolderP2P*>(nextNP()))) {
1747  Bool_t rel = p2pN->IsRelative();
1748  Int_t idD = den->FindId(p2pN->GetTitle());
1749  HolderP2P* p2pD = idD == 0 ? 0 : den->FindP2P(idD);
1750  Bool_t same = !p2pD ? false : rel == p2pD->IsRelative();
1751  Int_t mask = 0;
1752  // Printf("Id of denom %s -> %d (%p, %s, %s)", p2pN->GetTitle(), idD,
1753  // p2pD, same ? "same" : "diff",
1754  // p2pD ? (p2pD->TestBit(kUsedBit) ? "used" : "ready") : "?");
1755  if (cancc &&
1756  p2pD && // Check it is a p2p
1757  same) { // Same as this
1758  // We found the same error in the denominator, so we need to
1759  // cancel errors when looping.
1760  mask = ((p2pD->GetUniqueID() & 0xFF) << 16);
1761  // Printf("Found %s in both denom (%s,%d) and num (%s,%d)",
1762  // p2pN->GetTitle(),
1763  // p2pD->GetTitle(), p2pD->GetUniqueID(),
1764  // p2pN->GetTitle(), p2pD->GetUniqueID());
1765  if (kVerbose & kRatio)
1766  ::Info("Ratio", "Cancelling the p2p systamtic error %s "
1767  "between numerator and denominator",
1768  p2pN->GetTitle());
1769  // Flag the denominator error as used
1770  p2pD->SetBit(kUsedBit);
1771  }
1772  Int_t pId = ret->DeclarePoint2Point(p2pN->GetTitle(),rel,
1773  kBox);
1774  HolderP2P* p = ret->FindP2P(pId);
1775  p->CopyAttr(p2pN);
1776  // Flag the numerator error as used
1777  p2pN->SetBit(kUsedBit);
1778  mask |= (((p2pN->GetUniqueID() & 0xFF) << 8) |
1779  (pId & 0xFF));
1780  // Printf("Found shared P2P: %s -> %d", p2pN->GetTitle(), pId);
1781  // num->Print("sys");
1782  // den->Print("sys");
1783  shared[sCnt] = mask;
1784  sCnt++;
1785  }
1786  // Loop over all denominator point-to-point systematic errors. If
1787  // it is not cancelled with the numerator, we define a new error
1788  // on the output ratio
1789  TIter nextDP(&den->fPoint2Point);
1790  HolderP2P* p2pD = 0;
1791  while ((p2pD = static_cast<HolderP2P*>(nextDP()))) {
1792  if (p2pD->TestBit(kUsedBit)) {
1793  // Printf("P2P of denom %s already used", p2pD->GetTitle());
1794  continue;
1795  }
1796  Int_t pId = ret->DeclarePoint2Point(p2pD->GetTitle(),true,
1797  kBox);
1798  HolderP2P* p = ret->FindP2P(pId);
1799  p->CopyAttr(p2pD);
1800  // Flag the numerator error as used
1801  p2pD->SetBit(kUsedBit);
1802  Int_t mask = (((p2pD->GetUniqueID() & 0xFF) << 16) |
1803  (pId & 0xFF));
1804  // Printf("P2P of %s (%d) denom propagated", p2pD->GetTitle(),
1805  // p2pD->GetUniqueID());
1806  shared[sCnt] = mask;
1807  sCnt++;
1808  }
1809  Int_t bId = 0;
1810  if (notUsed > 0) {
1811  // If we have some error that are not used - i.e., non-relative
1812  // common errors in the numerator or denominator, we need to
1813  // make a new point-to-point systematic error for those.
1814  bId = ret->DeclarePoint2Point("Blob", false, kBox);
1815  }
1816 
1817  // Now loop over all the points we have in the numerator and
1818  // figure out what to do for each point.
1819  Int_t cnt = 0; // Counter of output points
1820  for (Int_t i = 0; i < num->GetN(); i++) {
1821  Double_t x = num->GetX(i);
1822  Double_t nY = num->GetY(i);
1823  Double_t nEyl = 0;
1824  Double_t nEyh = 0;
1825  Double_t dY = 0;
1826  Double_t dEyl = 0;
1827  Double_t dEyh = 0;
1828  Int_t di1, di2;
1829  Int_t di = den->FindPoint(x, di1, di2, fac);
1830  Double_t daX = 0; // Relative distance between interpolated points
1831  if (di < -1) {
1832  if (kVerbose & kRatio)
1833  ::Warning("Ratio", "Next point %d (%f) not found in denominator",
1834  i, x);
1835  continue;
1836  }
1837  Bool_t cmn = true; // Include the common errors
1838  Bool_t stat = false; // Include the statistical errors
1839  Bool_t quad = true; // Add in quadrature
1840  Bool_t nosqrt = false; // Do not return squared error
1841  if (di >= 0) {
1842  // Exact point
1843  // point,common,stat,quadratic,nosqrt,
1844  dY = den->GetYandError(di,cmn,stat,quad,nosqrt,dEyl,dEyh);
1845  di1 = di;
1846  }
1847  else {
1848  Double_t eyl1, eyl2, eyh1, eyh2;
1849  Double_t x1 = den->GetX(di1);
1850  Double_t x2 = den->GetX(di2);
1851  Double_t y1 = den->GetYandError(di1,cmn,stat,quad,nosqrt,eyl1,eyh1);
1852  Double_t y2 = den->GetYandError(di2,cmn,stat,quad,nosqrt,eyl2,eyh2);
1853  // Linear interpolation
1854  Double_t dx = (x2-x1);
1855  daX = (x-x1)/dx;
1856  dY = y1 + daX * (y2 - y1);
1857  dEyl = eyl1 + daX * (eyl2 - eyl1);
1858  dEyh = eyh1 + daX * (eyh2 - eyh1);
1859  }
1860  // At this point, we have the X and Y values, and the non-p2p
1861  // and non-cancelled and non-relative-common errors calculated
1862  // for numerator and denominator individually.
1863  //
1864  // We start by setting the point value. Perhaps here, we should
1865  // also set the statistics.
1866  Double_t rY = (dY != 0 ? nY/dY : 0);
1867  ret->SetPoint(cnt, x, rY);
1868  ret->SetPointError(cnt, num->GetErrorXLeft(i), num->GetErrorXRight(i));
1869 
1870  // We have not dealt with the statistical errors yet. We do
1871  // that here.
1872  Double_t sEyl = 0;
1873  Double_t sEyh = 0;
1874  if (TMath::Abs(rY) > 1.e-9) {
1875  Double_t snEyl = num->GetStatErrorDown(cnt);
1876  Double_t snEyh = num->GetStatErrorUp (cnt);
1877  Double_t sdEyl = den->GetStatErrorDown(cnt);
1878  Double_t sdEyh = den->GetStatErrorUp (cnt);
1879  // Statistical errors never cancel, and must be propagted. Note,
1880  // despite it technically being wrong, we treat the lower and
1881  // higher errors independently.
1882  sEyl = TMath::Sqrt(rY*rY*(snEyl*snEyl/nY/nY+sdEyl*sdEyl/dY/dY));
1883  sEyh = TMath::Sqrt(rY*rY*(snEyh*snEyh/nY/nY+sdEyh*sdEyh/dY/dY));
1884  }
1885  ret->SetStatError(cnt, sEyl, sEyh);
1886 
1887  // Next, we should update our blob systematic p2p error if it
1888  // exists.
1889  if (bId > 0) {
1890  Double_t eyl = 0, eyh = 0;
1891  // Printf("Calculate blob syst.uncer. d=(%f,%f) n=(%f,%f)",
1892  // dEyl, dEyh, nEyl, nEyh);
1893  if (denrel) {
1894  Double_t rdEyl = (dY != 0 ? dEyl/dY : 0);
1895  Double_t rdEyh = (dY != 0 ? dEyh/dY : 0);
1896  eyl = rdEyl*rY;
1897  eyh = rdEyh*rY;
1898  }
1899  else if (emax) {
1900  // Take the largest of the two errors, and divide by the
1901  // denominator.
1902  eyl = TMath::Max(nEyl, dEyl);
1903  eyh = TMath::Max(nEyh, dEyh);
1904  eyl /= dY;
1905  eyh /= dY;
1906  }
1907  else if (cmin) {
1908  // Take the largest of the two errors, and divide by the
1909  // denominator.
1910  eyl = TMath::Min(nEyl, dEyl);
1911  eyh = TMath::Min(nEyh, dEyh);
1912  eyl /= dY;
1913  eyh /= dY;
1914  }
1915  else {
1916  // Find the relative errors and add in quadrature
1917  Double_t rnEyl = (nY != 0 ? nEyl/nY : 0);
1918  Double_t rnEyh = (nY != 0 ? nEyh/nY : 0);
1919  Double_t rdEyl = (dY != 0 ? dEyl/dY : 0);
1920  Double_t rdEyh = (dY != 0 ? dEyh/dY : 0);
1921  Double_t reyl = TMath::Sqrt(rnEyl*rnEyl+rdEyl*rdEyl);
1922  Double_t reyh = TMath::Sqrt(rnEyh*rnEyh+rdEyh*rdEyh);
1923  eyl = reyl*rY;
1924  eyh = reyh*rY;
1925  }
1926  // Printf("den err (%f%%,%f%%) - blob (%f%%,%f%%)", dEyl*100, dEyh*100,
1927  // eyl*100,eyh*100);
1928  ret->SetSysError(bId, cnt, eyl, eyh);
1929  }
1930 
1931  // Now we need to update our various point-to-point
1932  // errors. We've stored a mask for each declared point-to-point
1933  // error. Each mask consist of three fields, corresponding to
1934  // point-to-point errors in the denominator, numerator, and the
1935  // ratio. If all three fields are set, we shold cancel between
1936  // numerator and denominator. If only the ratio and either of
1937  // the denominator or numerator fields are set, we simply need
1938  // to copy that to the ratio point-to-point error - as a
1939  // relative error of course.
1940  for (Int_t im = 0; im < shared.GetSize(); im++) {
1941  Int_t mask = shared[im];
1942  if (mask <= 0) break;
1943  Int_t rId = ((mask >> 0) & 0xFF);
1944  Int_t nId = ((mask >> 8) & 0xFF);
1945  Int_t dId = ((mask >> 16) & 0xFF);
1946  if (nId == 0 && dId == 0) {
1947  ::Warning("Ratio", "Both numerator and denominator IDs are 0");
1948  break;
1949  }
1950  Bool_t rel = ret->IsRelative(rId);
1951  Bool_t crel = true; // rel
1952  Double_t pdEyl = 0;
1953  Double_t pdEyh = 0;
1954  Double_t pnEyl = 0;
1955  Double_t pnEyh = 0;
1956  if (dId != 0) {
1957  HolderP2P* pD = den->FindP2P(dId);
1958  Double_t lfc = (crel ? (TMath::Abs(dY) > 1e-9 ? 1/dY : 0) : 1);
1959  pdEyl = pD->GetYDown(di1, di2, daX) * lfc;
1960  pdEyh = pD->GetYUp (di1, di2, daX) * lfc;
1961  }
1962  if (nId != 0) {
1963  HolderP2P* pN = num->FindP2P(nId);
1964  Double_t lfc = (crel ? (TMath::Abs(nY) > 1e-9 ? 1/nY : 0) : 1);
1965  pnEyl = pN->GetYDown(i) * lfc;
1966  pnEyh = pN->GetYUp (i) * lfc;
1967  }
1968  // Printf("Doing error %d from n=%d (%f +%f -%f) d=%d (%f +%f -%f)",
1969  // rId, nId, nY, pnEyl, pnEyh, dId, dY, pdEyh, pdEyl);
1970  Double_t peyl = 0;
1971  Double_t peyh = 0;
1972  Double_t lfc = (!crel ? (TMath::Abs(dY) > 1e-9 ? 1/dY : 0) : 1);
1973  if (nId == 0) {
1974  // No numerator value - set directly
1975  peyl = pdEyl * lfc;
1976  peyh = pdEyh * lfc;
1977  } // else if
1978  else if (dId == 0) {
1979  // No denomenator value - set directly
1980  peyl = pnEyl * lfc;
1981  peyh = pnEyh * lfc;
1982  } // else if
1983  else {
1984  // Cancel errors
1985  if (denrel) {
1986  peyl = pdEyl*lfc;
1987  peyh = pdEyh*lfc;
1988  // Printf("den err (%f%%,%f%%)", peyl*100,peyh*100);
1989  }
1990  else if (cmin) {
1991  peyl = TMath::Min(nEyl, dEyl) * lfc;
1992  peyh = TMath::Min(nEyh, dEyh) * lfc;
1993  }
1994  else if (cmax) {
1995  peyl = TMath::Min(nEyl, dEyl) * lfc;
1996  peyh = TMath::Min(nEyh, dEyh) * lfc;
1997  }
1998  else {
1999  peyl = TMath::Sqrt(TMath::Abs(pnEyl*pnEyl-pdEyl*pdEyl)) * lfc;
2000  peyh = TMath::Sqrt(TMath::Abs(pnEyh*pnEyh-pdEyh*pdEyh)) * lfc;
2001  // ::Info("Ratio", "sqrt(|%8f^2 - %8f^2|)=%8f", pnEyl,pdEyl,peyl);
2002  }
2003  } // Else
2004  // Printf("%f, den err (%f%%,%f%%) - %d (%f%%,%f%%)",
2005  // rY, pdEyl*100, pdEyh*100, rId, peyl*100,peyh*100);
2006  lfc = (rel ? 1 : rY);
2007  ret->SetSysError(rId, cnt, 0, 0, lfc*peyl, lfc*peyh);
2008  }
2009 
2010  // Finally, increment counter
2011  cnt++;
2012  }
2013 
2014  // Reset the used case bits
2015  num->ClearUsed();
2016  den->ClearUsed();
2017 
2018  if (cnt <= 0) {
2019  ::Warning("", "No common points found");
2020  delete ret;
2021  ret = 0;
2022  return 0;
2023  }
2024  return ret;
2025  }
2030  void ClearUsed() const
2031  {
2032  // Reset the used case bits
2033  TObject* oe = 0;
2034  TIter nextC(&fCommon);
2035  while ((oe = nextC())) {
2036  oe->ResetBit(kUsedBit);
2037  oe->ResetBit(kOnlyWeightBit);
2038  }
2039  TIter nextP(&fPoint2Point);
2040  while ((oe = nextP())) {
2041  oe->ResetBit(kUsedBit);
2042  oe->ResetBit(kOnlyWeightBit);
2043  }
2044  }
2055  static Double_t KolomogorovTest(const GraphSysErr* g1,
2056  const GraphSysErr* g2)
2057  {
2058  Double_t z;
2059  return KolomogorovTest(g1, g2, z);
2060  }
2072  static Double_t KolomogorovTest(const GraphSysErr* g1,
2073  const GraphSysErr* g2,
2074  Double_t& z)
2075  {
2076  TArrayD a1y;
2077  TArrayD a2y;
2078  TArrayD a1e2;
2079  TArrayD a2e2;
2080  Int_t cnt = CacheGraphs(g1, g2, a1y, a2y, a1e2, a2e2);
2081  if (cnt <= 0) return -1;
2082 
2083  Double_t s1 = a1y.GetSum(); // Summed content
2084  Double_t s2 = a2y.GetSum(); // Summed content
2085  Double_t sw1 = a1e2.GetSum(); // Summed weights
2086  Double_t sw2 = a2e2.GetSum(); // Summed weights
2087  if (a1e2.GetSum() <= 0 && a2e2.GetSum()) {
2088  ::Warning("ChisquareTest", "No errors");
2089  return -1;
2090  }
2091 
2092  Double_t sr1 = 0;
2093  Double_t sr2 = 0;
2094  Double_t dfMax = 0;
2095  for (Int_t i = 0; i < cnt; i++) {
2096  // KolmogorowvTest
2097  sr1 += a1y[i] / s1;
2098  sr2 += a2y[i] / s2;
2099  dfMax = TMath::Max(dfMax, TMath::Abs(sr1-sr2));
2100  }
2101  // K-S test
2102  Double_t se1 = s1 * s1 / sw1;
2103  Double_t se2 = s2 * s2 / sw2;
2104  z = dfMax * TMath::Sqrt(se1 * se2 / (se1 + se2));
2105  return TMath::KolmogorovProb(z);
2106  }
2121  static Int_t CacheGraphs(const GraphSysErr* g1,
2122  const GraphSysErr* g2,
2123  TArrayD& a1y,
2124  TArrayD& a2y,
2125  TArrayD& a1e2,
2126  TArrayD& a2e2)
2127  {
2128  Int_t cnt = 0;
2129  Int_t n = g1->GetN();
2130  a1y.Set(n);
2131  a2y.Set(n);
2132  a1e2.Set(n);
2133  a2e2.Set(n);
2134  for (Int_t i = 0; i < g1->GetN(); i++) {
2135  Double_t x = 0;
2136  Double_t y1 = 0;
2137  Double_t e1yl = 0;
2138  Double_t e1yh = 0;
2139  Double_t e2yl = 0;
2140  Double_t e2yh = 0;
2141  Double_t y2 = 0;
2142  if (!NextPoint(i, g1, g2, x, y1, e1yl, e1yh, y2, e2yl, e2yh)) {
2143  ::Warning("ChisquareTest", "Next point - %d %f not found", i, x);
2144  continue;
2145  }
2146 
2147  Double_t e1y2 = TMath::Power(TMath::Max(e1yl,e1yh), 2);
2148  Double_t e2y2 = TMath::Power(TMath::Max(e2yl,e2yh), 2);
2149 
2150  // Cache the numbers
2151  a1y[cnt] = y1; // Store value
2152  a2y[cnt] = y2; // Store value
2153  a1e2[cnt] = e1y2; // Store square error
2154  a2e2[cnt] = e2y2; // Store square error
2155  cnt++;
2156  }
2157  if (cnt <= 0)
2158  ::Warning("CacheGraphs", "No common points found");
2159 
2160  return cnt;
2161  }
2174  static Double_t ChisquareTest(const GraphSysErr* g1,
2175  const GraphSysErr* g2,
2177  {
2178  Int_t ndf = 0;
2179  return ChisquareTest(g1, g2, ndf, type);
2180  }
2194  static Double_t ChisquareTest(const GraphSysErr* g1,
2195  const GraphSysErr* g2,
2196  Int_t& ndf,
2197  EChi2Type type)
2198  {
2199  Double_t chi2 = 0;
2200  ndf = -1;
2201  TArrayD a1y;
2202  TArrayD a2y;
2203  TArrayD a1e2;
2204  TArrayD a2e2;
2205  Int_t cnt = CacheGraphs(g1, g2, a1y, a2y, a1e2, a2e2);
2206  if (cnt <= 0) return -1;
2207 
2208  Double_t s1 = a1y.GetSum(); // Summed content
2209  Double_t s2 = a2y.GetSum(); // Summed content
2210  if (type == kModelModel && (a1e2.GetSum() <= 0 && a2e2.GetSum())) {
2211  ::Warning("ChisquareTest", "No errors");
2212  return -1;
2213  }
2214 
2215  ndf = cnt;
2216 
2217  // Now loop over cached points
2218  Double_t s = s1 + s2;
2219  for (Int_t i = 0; i < ndf; i++) {
2220  switch (type) {
2221  case kExperimentExperiment: {
2222  Double_t sum = a1y[i]+a2y[i];
2223  Double_t delta = s2 * a1y[i] - s1 * a2y[i];
2224  chi2 += delta * delta / sum;
2225  }
2226  break;
2227  case kExperimentModel: {
2228  Double_t v1 = s2 * a1y[i] - s1 * a2e2[i];
2229  Double_t v2 = v1 * v1 + 4 * s2 * s2 * a1y[i] * a2e2[i];
2230  Double_t pp = (v1 + v2) / (2 * s2 * s2);
2231  Double_t p1 = pp * s1;
2232  Double_t p2 = pp * s2;
2233  Double_t d1 = a1y[i] - p1;
2234  Double_t d2 = a1y[i] - p2;
2235  chi2 += d1 * d1 / p1;
2236  if (a2e2[i] > 0) chi2 += d2 * d2 / a2e2[i];
2237  }
2238  break;
2239  case kModelModel: {
2240  Double_t sigma = s1 * s1 * a2e2[i] + s2 * s2 * a1e2[i];
2241  Double_t delta = s2 * a1y[i] - s1 * a2y[i];
2242  chi2 += delta * delta / sigma;
2243  }
2244  break;
2245  case kExperimentTruth: {
2246  Double_t delta = a2y[i] - a1y[i];
2247  chi2 += delta * delta / a1e2[i];
2248  }
2249  break;
2250  default:
2251  ::Warning("ChisquareTest", "Should not happen");
2252  return -1;
2253  }
2254 
2255  }
2256  if (type == kExperimentExperiment) chi2 /= s1 * s2;
2257  else if (type == kExperimentTruth) chi2 /= ndf;
2258 
2259  return chi2;
2260  }
2261 
2267  void RemovePoint(Int_t i)
2268  {
2269  if (i < 0 || i >= GetN()) return;
2270  fData->RemovePoint(i);
2271  TIter next(&fPoint2Point);
2272  HolderP2P* p2p = 0;
2273  while ((p2p = static_cast<HolderP2P*>(next()))) {
2274  p2p->fGraph->RemovePoint(i);
2275  }
2276  }
2284  void SwapPoints(Int_t i, Int_t j, Bool_t reflect=false)
2285  {
2286  if (i == j && !reflect) return;
2287  SwapPoints(fData, i, j, reflect);
2288  TIter next(&fPoint2Point);
2289  HolderP2P* p2p = 0;
2290  while ((p2p = static_cast<HolderP2P*>(next()))) {
2291  SwapPoints(p2p->fGraph, i, j, reflect);
2292  }
2293  }
2301  GraphSysErr* Reflect(Double_t x0=0) const
2302  {
2303  GraphSysErr* cpy = new GraphSysErr(*this);
2304  for (Int_t i = 0; i < GetN()/2; i++) {
2305  cpy->SwapPoints(i, GetN()-i-1, true);
2306  }
2307  return cpy;
2308  }
2316  Bool_t Symmetrize(GraphSysErr* other)
2317  {
2318  GraphSysErr* cpy = new GraphSysErr(*other);
2319 
2320  // Declare "blob" systematic point-to-point error
2321  Int_t id = DeclarePoint2Point("Syst.unc..", false, kBox);
2322 
2323  // Loop over common errors
2324  HolderCommon* cmn = 0;
2325  TIter cNext(&fCommon);
2326  while ((cmn = static_cast<HolderCommon*>(cNext()))) {
2327  Int_t oId = cpy->FindId(cmn->GetTitle());
2328  if (oId <= 0) {
2329  // If the common error ins't found in copy - it should,
2330  // because we did a straight copy - then give up.
2331  Error("Symmetrice", "Common error %s not found in %s",
2332  cmn->GetTitle(), cpy->GetName());
2333  cpy->Print("all");
2334  delete cpy;
2335  cpy = 0;
2336  break;
2337  // }
2338  // }
2339  } // oId <= 0
2340 
2341  // Zero this error here - we should add it later
2342  HolderCommon* oCmn = cpy->FindCommon(oId);
2343  if (cmn->fEyl <= 0 && cmn->fEyh <= 0) {
2344  // Copy the error over
2345  cmn->fEyl = oCmn->fEyl;
2346  cmn->fEyh = oCmn->fEyh;
2347  }
2348  oCmn->Set(0,0);
2349  } // while cmn
2350  if (!cpy) return false;
2351 
2352  // Loop over all points
2353  Int_t cnt = 0;
2354  Int_t n = other->GetN();
2355  TArrayI used(n); // book-keeping
2356  Int_t nonZero = 0; // how many non-zero sys.uncerr.
2357  used.Reset(-1);
2358  for (Int_t i = 0; i < n; i++) {
2359  if (used[i] >= 0 && used[i] != i) {
2360  Int_t j = used[i];
2361  // Info("Symmetrice", "Copy %d to %d instead of %d", j, cnt, i);
2362  SetPoint(cnt, -GetX(j), GetY(j));
2365  SetSysError(id, cnt, 0, GetSysErrorY(id, j));
2366  // Info("Symmetrice", "%f -> %f +/- %f",
2367  // -GetX(j), GetY(j), GetSysErrorY(id,j));
2368  cnt++;
2369  continue;
2370  }
2371  used[i] = i;
2372  Double_t eyl1, eyh1;
2373  Double_t exl1 = cpy->GetErrorXLeft(i);
2374  Double_t exh1 = cpy->GetErrorXRight(i);
2375  Double_t seyl1 = cpy->GetStatErrorDown(i);
2376  Double_t seyh1 = cpy->GetStatErrorUp(i);
2377  Double_t y1 = cpy->GetYandError(i,true,false,true,false,eyl1,eyh1);
2378  Double_t x1 = cpy->GetX(i);
2379  Double_t y2 = 0;
2380  Double_t eyl2 = 0;
2381  Double_t eyh2 = 0;
2382  Double_t seyl2 = 0;
2383  Double_t seyh2 = 0;
2384  Int_t i1, i2;
2385  Int_t j = cpy->FindPoint(-x1, i1, i2); // Find mirror
2386  if (j < -1) {
2387  // IF there's no mirror point, the just set to current
2388  // Info("Symmetrice", "No mirror of %f using %d for %d", x1, i, cnt);
2389  SetPoint(cnt, x1, y1);
2390  SetPointError(cnt, exl1, exh1);
2391  SetStatError(cnt, seyl1, seyh1);
2392  SetSysError(id, cnt, 0, 0, eyl1, eyh1);
2393  cnt++;
2394  continue;
2395  }
2396  if (j >= 0) {
2397  // If we have exact mirror, then use that point and mark as
2398  // used
2399  // Info("Symmetrice", "Got exact mirror of %f(%d) at %d", x1, i, j);
2400  y2 = cpy->GetYandError(j,true,false,true,false,eyl2,eyh2);
2401  seyl2 = cpy->GetStatErrorDown(j);
2402  seyh2 = cpy->GetStatErrorUp(j);
2403  // We should copy values when we get to j
2404  used[j] = cnt;
2405  }
2406  else {
2407  // Otherwise we use interpolation between two points
2408  // Info("Symmetrice", "Interpolate mirror of %f(%d) between %d-%d",
2409  // x1, i, i1, i2);
2410  cpy->FindYandError(-x1,true,true,true,false,y2,eyl2,eyh2,seyl2,seyh2);
2411  }
2412  // Now calculate weighted mean and variance
2413  Double_t newY = (y1+y2) / 2;
2414  Double_t newV = 0;
2415  if ((eyh1+eyl1) > 1e-9 && (eyh2+eyl2) > 1e-9) {
2416  Double_t s1 = 2 * eyl1 * eyh1 / (eyh1 + eyl1);
2417  Double_t sp1 = (eyh1 - eyl1) / (eyh1 + eyl1);
2418  Double_t w1 = .5 * TMath::Power(s1+y1*sp1, 3) / s1;
2419  Double_t s2 = 2 * eyl2 * eyh2 / (eyh2 + eyl2);
2420  Double_t sp2 = (eyh2 - eyl2) / (eyh2 + eyl2);
2421  Double_t w2 = .5 * TMath::Power(s2+y2*sp2, 3) / s2;
2422  // Printf("s1=%f sp1=%f w1=%f s2=%f sp2=%f w2=%f",
2424  Double_t sumW = (w1+w2);
2425  newY = (y1*w1+y2*w2) / sumW;
2426  newV = TMath::Sqrt((w1*w1*s1*s1+w2*w2*s2*s2) / sumW / sumW);
2427  nonZero++;
2428  }
2429  Double_t seyl = TMath::Sqrt(seyl1*seyl1+seyl2*seyl2);
2430  Double_t seyh = TMath::Sqrt(seyh1*seyh1+seyh2*seyh2);
2431 
2432  // Info("Symmmetrice", "%f (%f +/- %f) + (%f +/- %f) -> %f +/- %f",
2433  // x1, y1, w1, y2, w2, newY, newV);
2434  SetPoint(cnt, x1, newY);
2435  SetPointError(cnt, exl1, exh1);
2436  SetStatError(cnt, seyl, seyh);
2437  SetSysError(id, cnt, 0, newV);
2438  cnt++;
2439  }
2440  if (nonZero <= 0) RemoveSysError(id);
2441  // Info("", "After symmetrization:");
2442  // Print("all");
2443  return true;
2444  }
2445  /* @} */
2450  void SavePrimitive(std::ostream& out, Option_t* option="")
2451  {
2452  TString opt(option);
2453  opt.ToLower();
2454  Bool_t load = opt.Contains("load"); opt.ReplaceAll("load", "");
2455  TString funcName;
2456  TPRegexp regex("func=([a-zA-z][a-zA-Z0-9_]*)");
2457  TObjArray* toks = regex.MatchS(opt);
2458  if (toks) {
2459  if (toks->GetEntriesFast() > 1)
2460  funcName = toks->At(1)->GetName();
2461  if (toks->GetEntriesFast() > 0)
2462  opt.ReplaceAll(toks->At(0)->GetName(), "");
2463  delete toks;
2464  }
2465 
2466 
2467  // Save initialization
2468  if (!funcName.IsNull())
2469  out << "TObject* " << funcName << "(Option_t* o=\"\")\n";
2470  out << "{\n";
2471  if (load)
2472  out << " // Load class\n"
2473  << " if (!gROOT->GetClass(\"GraphSysErr\"))\n"
2474  << " gROOT->LoadMacro(\"GraphSysErr.C+\");\n";
2475  out << " GraphSysErr* g = new GraphSysErr(\""
2476  << GetName() << "\",\"" << GetTitle() << "\","
2477  << GetN() << ");\n";
2478  // Save attributes
2479  out << " // Point options\n"
2480  << " g->SetMarkerStyle(" << GetMarkerStyle() << ");\n"
2481  << " g->SetMarkerColor(" << GetMarkerColor() << ");\n"
2482  << " g->SetMarkerSize(" << GetMarkerSize() << ");\n"
2483  << " g->SetLineStyle(" << GetLineStyle() << ");\n"
2484  << " g->SetLineColor(" << GetLineColor() << ");\n"
2485  << " g->SetLineWidth(" << GetLineWidth() << ");\n"
2486  << " g->SetFillStyle(" << GetFillStyle() << ");\n"
2487  << " g->SetFillColor(" << GetFillColor() << ");\n"
2488  << " g->SetXTitle(\"" << fXTitle << "\");\n"
2489  << " g->SetYTitle(\"" << fYTitle << "\");\n"
2490  << " g->SetDataOption(" << fDataOption << ");\n"
2491  << " // Sum options\n"
2492  << " g->SetSumOption(" << fSumOption << ");\n"
2493  << " g->SetSumTitle(\"" << fSumTitle << "\");\n"
2494  << " g->SetSumLineStyle(" << fSumLine.GetLineStyle() << ");\n"
2495  << " g->SetSumLineColor(" << fSumLine.GetLineColor() << ");\n"
2496  << " g->SetSumLineWidth(" << fSumLine.GetLineWidth() << ");\n"
2497  << " g->SetSumFillStyle(" << fSumFill.GetFillStyle() << ");\n"
2498  << " g->SetSumFillColor(" << fSumFill.GetFillColor() << ");\n"
2499  << " g->SetCommonSumOption(" << fCommonSumOption << ");\n"
2500  << " g->SetCommonSumTitle(\"" << fCommonSumTitle << "\");\n"
2501  << " g->SetCommonSumLineStyle(" <<fCommonSumLine.GetLineStyle()<<");\n"
2502  << " g->SetCommonSumLineColor(" <<fCommonSumLine.GetLineColor()<<");\n"
2503  << " g->SetCommonSumLineWidth(" <<fCommonSumLine.GetLineWidth()<<");\n"
2504  << " g->SetCommonSumFillStyle(" <<fCommonSumFill.GetFillStyle()<<");\n"
2505  << " g->SetCommonSumFillColor(" <<fCommonSumFill.GetFillColor()<<");\n"
2506  << " // Stat options\n"
2507  << " g->SetStatRelative(" << fStatRelative << ");\n";
2508  TIter nextC(&fCommon);
2509  HolderCommon* cmn = 0;
2510  while ((cmn = static_cast<HolderCommon*>(nextC())))
2511  cmn->SavePrimitive(out, "d");
2512  TIter nextP(&fPoint2Point);
2513  HolderP2P* p2p = 0;
2514  while ((p2p = static_cast<HolderP2P*>(nextP())))
2515  p2p->SavePrimitive(out, "d");
2516  Int_t n = GetN();
2517  out << " // " << n << " points\n";
2518  Bool_t statRel = IsStatRelative();
2519  for (Int_t i = 0; i < n; i++) {
2520  Double_t y = GetY(i);
2521  out << " g->SetPoint(" << i << ',' << GetX(i) << ',' << y << ");\n"
2522  << " g->SetPointError(" << i << ',' << GetErrorXLeft(i) << ','
2523  << GetErrorXRight(i) << ");\n"
2524  << " g->SetStatError(" << i << ','
2525  << (statRel ? 1/y : 1)*GetStatErrorDown(i) << ','
2526  << (statRel ? 1/y : 1)*GetStatErrorUp(i) << ");\n";
2527  nextP.Reset();
2528  while ((p2p = static_cast<HolderP2P*>(nextP()))) {
2529  Int_t id = p2p->GetUniqueID();
2530  Bool_t rel = p2p->IsRelative();
2531  out << " g->SetSysError(" << id << ',' << i << ','
2532  << GetSysErrorXLeft(id, i) << ','
2533  << GetSysErrorXRight(id, i) << ','
2534  << (rel ? 1/y : 1) * GetSysErrorYDown(id, i) << ','
2535  << (rel ? 1/y : 1) * GetSysErrorYUp(id, i) << ");\n";
2536  } // while(p2p)
2537  } // for (i)
2538  out << " if (o && o[0] != '\\0') {\n"
2539  << " g->Draw(o);\n";
2540  if (fDrawn && fDrawn->GetHistogram())
2541  out << " if (g->GetMulti() && g->GetMulti()->GetHistogram()) {\n"
2542  << " g->GetMulti()->GetHistogram()->SetMinimum("
2543  << fDrawn->GetHistogram()->GetMinimum() << ");\n"
2544  << " g->GetMulti()->GetHistogram()->SetMaximum("
2545  << fDrawn->GetHistogram()->GetMaximum() << ");"
2546  << " }\n";
2547 
2548  out << " }\n";
2549  if (!funcName.IsNull()) out << " return g;\n";
2550  out << "};\n";
2551  }
2557  void Save(const char* fileName)
2558  {
2559  std::ofstream out(fileName);
2560  TString funcName(fileName);
2561  funcName.ReplaceAll(".C","");
2562  out << "// \n"
2563  << "// Generated by GraphSysErr.C\n"
2564  << "// \n"
2565  // << "class GraphSysErr;\n\n";
2566  << "\n";
2567  SavePrimitive(out, Form("load func=%s", funcName.Data()));
2568  out.close();
2569  }
2602  void Export(std::ostream& out=std::cout,
2603  Option_t* option="",
2604  Int_t nsign=2)
2605  {
2606  // Info("Export", "Using %d significant digits on errors", nsign);
2607  TString opt(option);
2608  opt.ToLower();
2609  Bool_t header = opt.Contains("h");
2610  Bool_t sysNames = opt.Contains("s");
2611  Bool_t comment = opt.Contains("c");
2612  Bool_t title = opt.Contains("t");
2613 
2614  ExportHeader(out, header, comment, nsign);
2615 
2616  // --- Export qualifiers -----------------------------------------
2617  Bool_t hasTitle = false;
2618  if (fQualifiers) {
2619  TIter nextQ(fQualifiers);
2620  TObject* q = 0;
2621  while ((q = nextQ())) {
2622  TString k(q->GetName());
2623  if (k.EqualTo("RE") || k.EqualTo("title", TString::kIgnoreCase))
2624  hasTitle = true;
2625  out << FormatKey("qual") << q->GetName() << " : "
2626  << q->GetTitle() << std::endl;
2627  }
2628  }
2629  if (!hasTitle && title)
2630  out << FormatKey("qual") << "RE : " << GetTitle() << std::endl;
2631 
2632  // --- Export X/Y titles ----------------------------------------
2633  const char* fill = "<please fill in>";
2634  TString xTit = fXTitle; EscapeLtx(xTit, "fill");
2635  TString yTit = fYTitle; EscapeLtx(yTit, "fill");
2636 
2637  out << FormatKey("xheader") << xTit << "\n"
2638  << FormatKey("yheader") << yTit << std::endl;
2639 
2640  // --- Export common errors --------------------------------------
2641  TIter nextC(&fCommon);
2642  HolderCommon* holderCommon = 0;
2643  while ((holderCommon = static_cast<HolderCommon*>(nextC()))) {
2644  Bool_t rel = holderCommon->IsRelative();
2645  Double_t up = holderCommon->GetYUp(rel ? 100 : 1);
2646  Double_t down = holderCommon->GetYDown(rel ? 100 : 1);
2647  out << FormatKey("dserror");
2648  ExportError(out, down, up, true, rel, nsign);
2649  out << ":" << holderCommon->GetTitle() << std::endl;
2650  }
2651 
2652  // --- Export data points ----------------------------------------
2653  out << FormatKey("data") << " x : y" << std::endl;
2654  Int_t n = GetN();
2655  for (Int_t i = 0; i < n; i++) {
2656  ExportPoint(out, i, true, sysNames, nsign);
2657  out << std::endl;
2658  }
2659  out << "*dataend:\n"
2660  << "# End of dataset\n" << std::endl;
2661  } //*MENU*
2668  static void EscapeLtx(TString& val, const TString& fill="")
2669  {
2670  if (val.IsNull()) {val = fill; return; }
2671  if (!val.Contains("#") && !val.Contains("\\")) return;
2672 
2673  if (val[0] !='$') val.Prepend("$");
2674  if (val[val.Length()-1]!='$') val.Append("$");
2675  val.ReplaceAll("#", "\\");
2676  }
2691  static void Export(const TSeqCollection* col,
2692  std::ostream& out,
2693  Option_t* option="H",
2694  Int_t nsign=0)
2695  {
2696  if (col->GetEntries() < 1) return;
2697 
2698  // --- Deduce options --------------------------------------------
2699  TString opt(option);
2700  opt.ToLower();
2701  Bool_t alsoTop = opt.Contains("h");
2702  Bool_t alsoCmt = opt.Contains("c");
2703  Bool_t alsoNme = opt.Contains("s");
2704  Bool_t alsoTit = opt.Contains("t");
2705 
2706  // --- some variables to use -------------------------------------
2707  const Double_t tol = 1e-10;
2708  GraphSysErr* first = 0;
2709  GraphSysErr* gse = 0;
2710  TList toExport;
2711  TList commons;
2712  TList quals;
2713  TString data("x ");
2714  Int_t nPoints = -1;
2715  Int_t idx = 0;
2716 
2717  // --- Check the passed graphs for compatiblity ------------------
2718  TIter nextCheck(col);
2719  TObject* o = 0;
2720  while ((o = nextCheck())) {
2721  if (!o->IsA()->InheritsFrom(GraphSysErr::Class())) continue;
2722  gse = static_cast<GraphSysErr*>(o);
2723  if (!first) {
2724  first = gse;
2725  nPoints = first->GetN();
2726  }
2727  else {
2728  // --- Check number of points --------------------------------
2729  if (gse->GetN() != nPoints) {
2730  Int_t nTmp = TMath::Min(gse->GetN(), nPoints);
2731  ::Warning("Export", "Incompatible number of points %d in %s"
2732  "using only %d of them",
2733  gse->GetN(), gse->GetName(), nTmp);
2734  nPoints = nTmp;
2735  }
2736  // --- check X values ----------------------------------------
2737  Bool_t ok = true;
2738  for (Int_t i = 0; i < nPoints; i++) {
2739  Double_t x1 = first->GetX(i);
2740  Double_t exl1 = first->fData->GetErrorXlow(i);
2741  Double_t exh1 = first->fData->GetErrorXhigh(i);
2742  Double_t xT = gse->GetX(i);
2743  Double_t exlT = gse->fData->GetErrorXlow(i);
2744  Double_t exhT = gse->fData->GetErrorXhigh(i);
2745  if (TMath::Abs(x1-xT) > tol ||
2746  (exl1 > tol && TMath::Abs(exl1-exlT) > tol) ||
2747  (exh1 > tol && TMath::Abs(exh1-exhT) > tol)) {
2748  ::Warning("Export", "X--coordinate of %s @ point %d: %f (+%f,-%f) "
2749  "incompatible [%f (+%f,-%f)]",
2750  gse->GetTitle(), i, xT, exhT, exlT, x1, exh1, exl1);
2751  ok = false;
2752  break;
2753  }
2754  } // for i
2755  if (!ok) continue;
2756  } // !first
2757 
2758  // --- Get all possible qualifiers -----------------------------
2759  toExport.Add(gse);
2760  TIter nextQ(gse->fQualifiers);
2761  TObject* q = 0;
2762  while ((q = nextQ())) {
2763  // ::Info("", "qualifier %s=%s", q->GetName(), q->GetTitle());
2764  StoreQual(quals, idx, q);
2765  }
2766 
2767  // --- Get all common systematics ------------------------------
2768  TIter nextCmn(&(gse->fCommon));
2769  TObject* oCmn = 0;
2770  while ((oCmn = nextCmn())) {
2771  if (commons.FindObject(oCmn->GetTitle())) continue;
2772  TObjString* cmn = new TObjString(oCmn->GetTitle());
2773  if (gse == first) cmn->SetUniqueID(gse->FindId(oCmn->GetTitle()));
2774  commons.Add(cmn);
2775  }
2776 
2777  idx++;
2778  data += ": y ";
2779  }
2780  // --- Now deduce the common common errors -----------------------
2781  TIter nextCmn(&(commons));
2782  TObject* oCmn = 0;
2783  while ((oCmn = nextCmn())) {
2784  TString oNme(oCmn->GetName());
2785  Bool_t found = true;
2786  Double_t ecl1 = -1;
2787  Double_t ech1 = -1;
2788 
2789  // --- Loop over data ------------------------------------------
2790  TIter nextG(&toExport);
2791  while ((gse = static_cast<GraphSysErr*>(nextG()))) {
2793  Int_t gseId = first->FindId(oNme);
2794 
2795  if (gseId > 0) {
2796  // If we do, check compatibility
2797  if (ecl1 < 0) {
2798  // First time we get this error
2799  ecl1 = gse->GetCommonErrorYDown(gseId);
2800  ech1 = gse->GetCommonErrorYUp(gseId);
2801  continue;
2802  }
2803  else {
2804  // Now check values within tolerance
2805  Double_t eclT = gse->GetCommonErrorYDown(gseId);
2806  Double_t echT = gse->GetCommonErrorYUp(gseId);
2807  if ((ecl1 > tol && TMath::Abs(ecl1-eclT) > tol) ||
2808  (ech1 > tol && TMath::Abs(ech1-echT) > tol)) {
2809  found = false;
2810  } // incompatible
2811  } // ecl1 >= 0
2812  } // gseId > 0
2813  else
2814  // This graph does not have this common, flag it
2815  found = false;
2816  } // while(gse)
2817 #if INCOMPAT_CMN_AS_QUAL
2818 #else
2819  found = true;
2820 #endif
2821  oCmn->SetBit(BIT(14), found);
2822 
2823  // If we found the error in all graphs and they are all
2824  // compatible, then all is good,
2825  if (found) continue;
2826 
2827  // If not, we represent the common systematic as a qualifier
2828  idx = 0;
2829  nextG.Reset();
2830  while ((gse = static_cast<GraphSysErr*>(nextG()))) {
2831  Int_t gseId = first->FindId(oNme);
2832  TString val;
2833  if (gseId > 0) {
2834  // This graph has the value, store as qual
2835  Bool_t rel = gse->IsRelative(gseId);
2836  Double_t ecl = gse->GetCommonErrorYDown(gseId);
2837  Double_t ech = gse->GetCommonErrorYUp(gseId);
2838  std::stringstream s;
2839  ExportError(s, ecl, ech, false, rel, nsign);
2840  val = s.str().c_str();
2841  }
2842  else {
2843  // This does not have the error, store empty string
2844  val = "";
2845  }
2846  // Now store this in our qualifier table
2847  StoreQual(quals, idx, oNme, val);
2848  idx++;
2849  } // while(gse)
2850  } // while common
2851 
2852  // --- Sanity checks ---------------------------------------------
2853  if (nPoints <= 0) {
2854  ::Error("Export", "No points to write");
2855  return;
2856  }
2857  if (toExport.GetEntries() <= 0) {
2858  ::Error("Export", "No graphs to export");
2859  return;
2860  }
2861  if (!first) {
2862  ::Error("Export", "Didn't get the first graph");
2863  return;
2864  }
2865 
2866  // --- Export header --------------------------------------------
2867  first->ExportHeader(out, alsoTop, alsoCmt, nsign);
2868 
2869  // --- Export qualifiers -----------------------------------------
2870  // quals.ls();
2871  Bool_t hasTitle = false;
2872  TIter nextQ(&quals);
2873  TList* ql = 0;
2874  while ((ql = static_cast<TList*>(nextQ()))) {
2875  TString k(ql->GetName());
2876  if (k.EqualTo("RE") || k.EqualTo("title", TString::kIgnoreCase))
2877  hasTitle = true;
2878  out << FormatKey("qual") << ql->GetName();
2879  for (Int_t i = 0; i < toExport.GetEntries(); i++) {
2880  TObject* qv = ql->At(i);
2881  TString v = "";
2882  if (qv) v = qv->GetName();
2883  out << " : " << v;
2884  }
2885  out << std::endl;
2886  }
2887  if (!hasTitle && alsoTit) {
2888  out << FormatKey("qual") << "RE ";
2889  for (Int_t i = 0; i < toExport.GetEntries(); i++)
2890  out << ": " << toExport.At(i)->GetTitle();
2891  out << std::endl;
2892  }
2893 
2894 
2895  // --- Export axis titles ----------------------------------------
2896  const char* fill = "<please fill in>";
2897  const char* fields[] = { "xheader", "yheader", 0 };
2898  const char** pfld = fields;
2899  while (*pfld) {
2900  out << FormatKey(*pfld);
2901  TIter nextSpec(&toExport);
2902  Bool_t one = true;
2903  while ((gse = static_cast<GraphSysErr*>(nextSpec()))) {
2904  TString val;
2905  if ((*pfld)[0] == 'x') val = gse->fXTitle;
2906  else if ((*pfld)[0] == 'y') val = gse->fYTitle;
2907  EscapeLtx(val, fill);
2908  out << (one ? "" : ":") << val;
2909  if ((*pfld)[0] == 'x') break;
2910  one = false;
2911  }
2912  pfld++;
2913  out << std::endl;
2914  }
2915 
2916  // --- Export common systematics ---------------------------------
2917  TIter nextC(&commons);
2918  while ((oCmn = nextC())) {
2919  TString tit(oCmn->GetName());
2920  EscapeLtx(tit);
2921  out << FormatKey("dserror");
2922 #if INCOMPAT_CMN_AS_QUAL
2923  if (!oCmn->TestBit(BIT(14))) {
2924  ::Warning("Export",
2925  "Common systematic error \"%s\" represented by qual",
2926  oCmn->GetName());
2927  out << "- : " << tit << std::endl;
2928  continue;
2929  }
2930  UInt_t id = first->FindId(oCmn->GetName());
2931  Bool_t rel = first->IsRelative(id);
2932  Double_t ecl = first->GetCommonErrorYDown(id);
2933  Double_t ech = first->GetCommonErrorYUp(id);
2934  ExportError(out, ecl, ech, true, rel, nsign);
2935  out << " : "<< tit << std::endl;
2936 #else
2937  out << tit << std::flush;
2938  TIter next(&toExport);
2939  while ((gse = static_cast<GraphSysErr*>(next()))) {
2940  UInt_t id = gse->FindId(oCmn->GetName());
2941  Bool_t rel = gse->IsRelative(id);
2942  Double_t ecl = gse->GetCommonErrorYDown(id);
2943  Double_t ech = gse->GetCommonErrorYUp(id);
2944  out << " : ";
2945  ExportError(out, ecl, ech, true, rel, nsign);
2946  }
2947  out << ":" << tit << std::endl;
2948 #endif
2949  }
2950 
2951  // --- Export points ---------------------------------------------
2952  out << FormatKey("data") << data << std::endl;
2953  for (Int_t i = 0; i < nPoints; i++) {
2954  TIter next(&toExport);
2955  Bool_t one = true;
2956  while ((gse = static_cast<GraphSysErr*>(next()))) {
2957  gse->ExportPoint(out, i, one, alsoNme, nsign);
2958  one = false;
2959  }
2960  out << std::endl;
2961  }
2962  out << "*dataend:\n"
2963  << "# End of dataset\n" << std::endl;
2964  // return out;
2965  }
2983  static TSeqCollection* Import(const TString& fileName)
2984  {
2985  std::ifstream in(fileName.Data());
2986  if (!in) {
2987  ::Warning("Import", "Failed to open \"%s\"", fileName.Data());
2988  return 0;
2989  }
2990  TList* ret = new TList;
2991  ret->SetOwner();
2992  GraphSysErr* g = 0;
2993  GraphSysErr* first = 0;
2994  Int_t id = 0;
2995  do {
2996  Int_t sub = 1;
2997  UShort_t nIdx = 256;
2998  int cur = in.tellg();
2999  do {
3000  in.seekg(cur, in.beg);
3001  if (!(g = Import(in, sub, &nIdx))) break;
3002  if (kVerbose & kImport)
3003  ::Info("Import", "Imported %d of %d", sub, nIdx);
3004  g->SetName(Form("ds_%d_%d", id, sub-1));
3005  if (!first) first = g;
3006  else g->CopyKeys(first);
3007  ret->Add(g);
3008  sub++;
3009  } while(sub < nIdx);
3010  id++;
3011  } while (!in.eof());
3012  return ret;
3013  }
3033  static GraphSysErr* Import(std::istream& in, UShort_t idx=0,
3034  UShort_t* nIdx=0)
3035  {
3036  GraphSysErr* ret = 0;
3037  Int_t n = 0;
3038  Bool_t inSet = false;
3039  Bool_t inData = false;
3040  TString xtit = "";
3041  TString ytit = "";
3042  TString tmp = "";
3043  TString last = "";
3044  TList quals;
3045  TList keys;
3046  Int_t isty = 0;
3047  do {
3048  TString line;
3049  line.ReadLine(in);
3050  tmp = line.Strip(TString::kBoth, ' '); line = tmp;
3051  if (line.IsNull()) continue;
3052  if (line[0] == '#') continue;
3053  if (line[0] == '*') { // We have some sort of header stuff
3054  Int_t colon = line.Index(":");
3055  if (colon == kNPOS) continue;
3056  Int_t len = line.Length()-colon-1;
3057  TString value = line(colon+1,len);
3058  tmp = value.Strip(TString::kBoth, ' '); value = tmp;
3059  last = line(1,colon-1);
3060  if (kVerbose & kImport)
3061  ::Info("Import", "Got a key '%s' -> '%s'", last.Data(), value.Data());
3062 
3063  if (last.BeginsWith("dataset", TString::kIgnoreCase)) {
3064  inSet = true;
3065  inData = false;
3066  isty = 0;
3067  }
3068  else if (last.BeginsWith("dataend", TString::kIgnoreCase)) {
3069  inSet = false;
3070  inData = false;
3071  // Always terminate on the end of a data set
3072  break;
3073  }
3074  // else if (last.BeginsWith("dscomment",TString::kIgnoreCase)) {
3075  // tit = value;
3076  // }
3077  else if (last.BeginsWith("qual", TString::kIgnoreCase)) {
3078  // ::Info("", "Got qual: %s", value.Data());
3079  // if (!qual.IsNull()) {
3080  // ::Info("", "Adding seen qual: %s", qual.Data());
3081  quals.Add(new TObjString(value));
3082  }
3083  else if (last.BeginsWith("xheader", TString::kIgnoreCase))
3084  xtit = value;
3085  else if (last.BeginsWith("yheader", TString::kIgnoreCase))
3086  ytit = value;
3087  else if (last.BeginsWith("dserror", TString::kIgnoreCase)) {
3088  // Common systematic error
3089  if (kVerbose & kImport)
3090  ::Info("Import", "Got common error line: '%s'", line.Data());
3091  TObjArray* tokens = value.Tokenize(":");
3092  Double_t el = 0, eh = 0;
3093  Bool_t rel = false;
3094  if (ImportError(Token(tokens, 0), el, eh, rel)) {
3095  if (rel) { el /= 100.; eh /= 100.; }
3096  TString& tnam = Token(tokens, 1);
3097  TString nam = tnam.Strip(TString::kBoth, ' ');
3098  if (!ret) ret = new GraphSysErr("imported", "");
3099  Int_t id = ret->DefineCommon(nam, rel, el, eh, kRect);
3100  ret->SetSysLineColor(id, (isty % 6) + 2);
3101  ret->SetSysFillColor(id, (isty % 6) + 2);
3102  ret->SetSysFillStyle(id, 3001 + (isty % 10));
3103  isty++;
3104  }
3105  }
3106  else if (last.BeginsWith("data", TString::kIgnoreCase)) {
3107  if (kVerbose & kImport)
3108  ::Info("Import", "Got start of data line: '%s'", line.Data());
3109  // These are the field we can deal with
3110  // Let's get the header field value
3111  TObjArray* tokens = value.Tokenize(":");
3112  if (nIdx) {
3113  *nIdx = tokens->GetEntriesFast();
3114  // ::Info("Import", "Max index is %d", *nIdx);
3115  }
3116  if (tokens->GetEntriesFast() > 2 && idx < 1) {
3117  idx = 1;
3118  ::Warning("Import", "Can only import one data set at a time, "
3119  "selecting the %d column", idx);
3120  }
3121  else if (idx >= 1 && idx >= tokens->GetEntriesFast()) {
3122  ::Warning("Import", "column %d not available for this data set",
3123  idx);
3124  inSet = false;
3125  }
3126  // We do nothing to the tokens here.
3127  tokens->Delete();
3128  inData = true;
3129  }
3130  else {
3131  // some other key.
3132  if (kVerbose & kImport)
3133  ::Info("Import", "Got pair line '%s' (%s -> %s)", line.Data(),
3134  last.Data(), value.Data());
3135  keys.Add(new TNamed(last, value));
3136  }
3137  continue;
3138  }
3139  if (!inData) {
3140  if (kVerbose & kImport)
3141  ::Info("Import", "Got a possible contiuation line '%s'", line.Data());
3142  // Probably a continuation line.
3143  if (last.IsNull())
3144  // No last key or no map
3145  continue;
3146 
3147  if (kVerbose & kImport)
3148  ::Info("Import", "Got some other line: '%s'", line.Data());
3149 
3150  TNamed* ptr = static_cast<TNamed*>(keys.FindObject(last));
3151  if (!ptr)
3152  // Key is not added, do nothing to this line
3153  continue;
3154 
3155  TString tt(ptr->GetTitle());
3156  if (!tt.EndsWith(" ") && !tt.EndsWith("\t") && !tt.EndsWith("\n"))
3157  // If value does not end in a white-space, add it.
3158  tt.Append("\n");
3159 
3160  // Append our line, and set the title
3161  tt.Append(line);
3162  ptr->SetTitle(tt);
3163 
3164  continue;
3165  }
3166  if (!inSet) {
3167  // We're outside a data-set so do nothing
3168  continue;
3169  }
3170  if (idx < 1) idx = 1;
3171 
3172  if (kVerbose & kImport)
3173  ::Info("Import", "Got a data line: '%s'", line.Data());
3174  TObjArray* tokens = line.Tokenize(";");
3175  if (tokens->GetEntriesFast() < idx+1) {
3176  ::Warning("Import", "Too few columns %d<%0d in line: %s",
3177  tokens->GetEntriesFast(), idx+1, line.Data());
3178  tokens->Delete();
3179  continue;
3180  }
3181  TString& xCol = static_cast<TObjString*>(tokens->At(0))->String();
3182  TString& yCol = static_cast<TObjString*>(tokens->At(idx))->String();
3183  if (kVerbose & kImport)
3184  ::Info("Import", "xColumn: '%s', yColumn: '%s'",
3185  xCol.Data(), yCol.Data());
3186 
3187  tmp = xCol.Strip(TString::kBoth, ' '); xCol = tmp;
3188  tmp = yCol.Strip(TString::kBoth, ' '); yCol = tmp;
3189  TString yFull = yCol;
3190 
3191  Int_t chop = yCol.Last('(');
3192  if (chop != kNPOS) {
3193  yCol.Remove(chop, yCol.Length()-chop);
3194  yCol.Remove(TString::kBoth, ' ');
3195  }
3196  if (kVerbose & kImport)
3197  ::Info("Import", "xColumn: '%s', yColumn: '%s'",
3198  xCol.Data(), yCol.Data());
3199 
3200  if (xCol.IsNull()) {
3201  ::Warning("Import", "Empty X column in line: %s", line.Data());
3202  tokens->Delete();
3203  continue;
3204  }
3205  if (yCol.IsNull()) {
3206  ::Warning("Import", "Empty Y column in line: %s", line.Data());
3207  tokens->Delete();
3208  continue;
3209  }
3210  Bool_t rel = false;
3211  Double_t x = 0, exl = 0, exh = 0;
3212  if (!ImportPoint(xCol, x, exl, exh, rel)) {
3213  ::Warning("Import", "Failed to import X value in line: %s",line.Data());
3214  tokens->Delete();
3215  continue;
3216  }
3217  Double_t y = 0, eyl = 0, eyh = 0;
3218  if (!ImportPoint(yCol, y, eyl, eyh, rel)) {
3219  ::Warning("Import", "Failed to import X value in line: %s",line.Data());
3220  tokens->Delete();
3221  continue;
3222  }
3223  if (!ret) ret = new GraphSysErr("imported", "");
3224  if (rel) ret->SetStatRelative(true);
3225  ret->SetPoint(n, x, y);
3226  ret->SetPointError(n, exl, exh);
3227 
3228  if (ret->IsStatRelative()) { eyl /= 100; eyh /= 100; }
3229  ret->SetStatError(n, eyl, eyh);
3230 
3231  Int_t lparen = yFull.Index("(");
3232  Int_t rparen = yFull.Index(")");
3233  if (lparen == rparen) {
3234  n++;
3235  continue;
3236  }
3237  TString rem = yFull(lparen+1, rparen-lparen-1);
3238  if (kVerbose & kImport)
3239  ::Info("Import", "Got systematic errors: '%s'", rem.Data());
3240 
3241  TObjArray* stok = rem.Tokenize("D");
3242  Int_t isys = 0;
3243  for (Int_t i = 0; i < stok->GetEntriesFast(); i++) {
3244  TString t = Token(stok,i);
3245  if (!t.BeginsWith("SYS=",TString::kIgnoreCase)) {
3246  ::Warning("Import", "Ignoring unknown spec %s (@ %d) in %s",
3247  t.Data(), i, rem.Data());
3248  continue;
3249  }
3250  t.Remove(0,4);
3251  if (t[t.Length()-1] == ',') t.Remove(t.Length()-1,1);
3252  tmp = t.Strip(TString::kBoth, ' '); t = tmp;
3253 
3254  Double_t el = 0, eh = 0;
3255  rel = false;
3256  if (!ImportError(t, el, eh, rel)) continue;
3257 
3258  Int_t colon = t.Index(":");
3259  TString nam(Form("sys%d", isys));
3260  if (colon != kNPOS) nam = t(colon+1, t.Length()-colon-1);
3261 
3262  UInt_t id = ret->FindId(nam);
3263  if (id == 0) {
3264  id = ret->DeclarePoint2Point(nam, rel, kRect);
3265  ret->SetSysLineColor(id, (isty % 6) + 2);
3266  ret->SetSysFillColor(id, (isty % 6) + 2);
3267  ret->SetSysFillStyle(id, 3001 + (isty % 10));
3268  isty++;
3269  }
3270  HolderP2P* p = ret->FindP2P(id);
3271  if (p->IsRelative()) { el /= 100.; eh /= 100.; }
3272  ret->SetSysError(id, n, exl, exh, el, eh);
3273  isys++;
3274  }
3275  stok->Delete();
3276 
3277  n++;
3278  } while (!in.eof());
3279  if (ret) {
3280  TString rxtit = ExtractField(xtit, idx-1);
3281  TString rytit = ExtractField(ytit, idx-1);
3282  if (!rxtit.IsNull()) ret->SetXTitle(rxtit);
3283  if (!rytit.IsNull()) ret->SetYTitle(rytit);
3284 
3285  Bool_t hasTitle = false;
3286  TIter nextQ(&quals);
3287  TObject* qual = 0;
3288  while ((qual = nextQ())) {
3289  TString k = ExtractField(qual->GetName(), 0);
3290  TString q = ExtractField(qual->GetName(), idx);
3291  /*
3292  ::Info("LoopQ", "Qualifier string: %s -> %s,%s",
3293  qual->GetName(), k.Data(), q.Data());
3294  */
3295  ret->AddQualifier(k, q);
3296  if (!hasTitle &&
3297  (k.EqualTo("RE") ||
3298  k.EqualTo("title", TString::kIgnoreCase))) {
3299  hasTitle = true;
3300  ret->SetTitle(q);
3301  }
3302  }
3303  TIter nextK(&keys);
3304  TObject* pair = 0;
3305  while ((pair = nextK())) {
3306  ret->SetKey(pair->GetName(),pair->GetTitle());
3307  TString k = pair->GetName();
3308  if (!hasTitle && (k.EqualTo("location"))) {
3309  ret->SetTitle(pair->GetTitle());
3310  hasTitle = true;
3311  }
3312  }
3313  if (!hasTitle) ret->SetTitle("Title");
3314  }
3315  keys.SetOwner();
3316  keys.Delete();
3317  return ret;
3318  }
3319  /* @} */
3320  //__________________________________________________________________
3340  UInt_t DefineCommon(const char* title, Bool_t relative,
3341  Double_t ey, EDrawOption_t option=kFill)
3342  {
3343  return DefineCommon(title, relative, ey, ey, option);
3344  }
3356  UInt_t DefineCommon(const char* title, Bool_t relative,
3357  Double_t eyl, Double_t eyh,
3358  EDrawOption_t option=kRect)
3359  {
3360  UInt_t id = ++fCounter;
3361  TString name(Form("common_%08x", id));
3362 
3363  HolderCommon* h = new HolderCommon(name, title, relative, option, id);
3364  h->Set(eyl, eyh);
3365 
3366  fCommon.AddLast(h);
3367  return id;
3368  }
3383  UInt_t DeclarePoint2Point(const char* title, Bool_t relative,
3384  EDrawOption_t option=kBar)
3385  {
3386  UInt_t id = ++fCounter;
3387  TString name(Form("p2p_%08x", id));
3388 
3389  Holder* h = new HolderP2P(name, title, relative, option, id);
3390 
3391  fPoint2Point.AddLast(h);
3392  return id;
3393  }
3394  void RemoveSysError(Int_t id)
3395  {
3396  HolderCommon* h = FindCommon(id);
3397  if (h) {
3398  fCommon.Remove(h);
3399  return;
3400  }
3401  HolderP2P* p = FindP2P(id);
3402  if (p) {
3403  fPoint2Point.Remove(p);
3404  return;
3405  }
3406  }
3414  UInt_t FindId(const char* title) const
3415  {
3416  TString tit(title);
3417 
3418  TIter nextC(&fCommon);
3419  Holder* holder = 0;
3420  while ((holder = static_cast<Holder*>(nextC()))) {
3421  if (tit.EqualTo(holder->GetTitle())) return holder->GetUniqueID();
3422  }
3423 
3424  TIter nextP(&fPoint2Point);
3425  while ((holder = static_cast<Holder*>(nextP()))) {
3426  if (tit.EqualTo(holder->GetTitle())) return holder->GetUniqueID();
3427  }
3428  // fCommon.ls();
3429  // fPoint2Point.ls();
3430  return 0;
3431  }
3432  Int_t GetNSys() const { return fCounter; }
3433  /* @} */
3434 
3435  //__________________________________________________________________
3447  void SetPoint(Int_t i, Double_t x, Double_t y)
3448  {
3449  if (!fData) return;
3450  fData->SetPoint(i, x, y);
3451  }
3458  void SetPointError(Int_t i, Double_t ex)
3459  {
3460  SetPointError(i, ex, ex);
3461  }
3469  void SetPointError(Int_t i, Double_t exl, Double_t exh)
3470  {
3471  if (!fData) return;
3472  fData->SetPointError(i, exl, exh,
3473  fData->GetErrorYlow(i),
3474  fData->GetErrorYhigh(i));
3475  }
3482  void SetStatRelative(Bool_t rel) { fStatRelative = rel; }
3488  Bool_t IsStatRelative() const { return fStatRelative; }
3495  void SetStatError(Int_t i, Double_t ey)
3496  {
3497  SetStatError(i, ey, ey);
3498  }
3499  /*
3500  * Set the statistical error on the ith data point
3501  *
3502  * @param i Point number
3503  * @param eyl Lower error on Y
3504  * @param eyh Higher error on Y
3505  */
3506  void SetStatError(Int_t i, Double_t eyl, Double_t eyh)
3507  {
3508  if (!fData) return;
3509  if (fStatRelative) {
3510  eyl *= fData->GetY()[i];
3511  eyh *= fData->GetY()[i];
3512  }
3513  fData->SetPointError(i,
3514  fData->GetErrorXlow(i),
3515  fData->GetErrorXhigh(i),
3516  eyl, eyh);
3517  }
3518  void SetSysError(Int_t id, Double_t eyl, Double_t eyh)
3519  {
3520  HolderCommon* h = FindCommon(id);
3521  if (!h) return;
3522  h->Set(eyl, eyh);
3523  }
3532  void SetSysError(Int_t id, Int_t i, Double_t ex, Double_t ey)
3533  {
3534  HolderP2P* h = FindP2P(id);
3535  if (!h) return;
3536  h->Set(i, fData, ex, ey);
3537  }
3548  void SetSysError(Int_t id, Int_t i, Double_t exl, Double_t exh,
3549  Double_t eyl, Double_t eyh)
3550  {
3551  HolderP2P* h = FindP2P(id);
3552  if (!h) return;
3553  h->Set(i, fData, exl, exh, eyl, eyh);
3554  }
3555  /* @} */
3556  //__________________________________________________________________
3566  void SetTitle(const char* name)
3567  {
3568  TNamed::SetTitle(name);
3569  if (fData) fData->SetTitle(name);
3570  }
3576  void SetDataOption(EDrawOption_t opt) { fDataOption = opt; } //*MENU*
3582  void SetXTitle(const char* title) { fXTitle = title; } //*MENU*
3588  void SetYTitle(const char* title) { fYTitle = title; } //*MENU*
3589  /* @} */
3590 
3591  //__________________________________________________________________
3599  Int_t GetN() const { return fData ? fData->GetN() : 0; }
3605  Double_t GetX(Int_t p) const { return fData->GetX()[p]; }
3611  Double_t GetErrorXLeft(Int_t p) const { return fData->GetErrorXlow(p); }
3617  Double_t GetErrorXRight(Int_t p) const { return fData->GetErrorXhigh(p); }
3623  Double_t GetY(Int_t point) const { return fData->GetY()[point]; }
3629  Double_t GetStatError(Int_t point) const { return fData->GetErrorY(point); }
3635  Double_t GetStatErrorUp(Int_t point) const
3636  {
3637  return fData->GetErrorYhigh(point);
3638  }
3644  Double_t GetStatErrorDown(Int_t point) const
3645  {
3646  return fData->GetErrorYlow(point);
3647  }
3648  Bool_t IsCommon(Int_t id) const
3649  {
3650  HolderCommon* c = FindCommon(id);
3651  return c != 0;
3652  }
3660  Bool_t IsRelative(Int_t id) const
3661  {
3662  HolderP2P* h = FindP2P(id);
3663  if (h) return h->IsRelative();
3664  HolderCommon* c = FindCommon(id);
3665  if (c) return c->IsRelative();
3666  return false;
3667  }
3674  Double_t GetSysErrorX(Int_t id, Int_t point) const
3675  {
3676  HolderP2P* h = FindP2P(id);
3677  if (!h) return 0;
3678  return h->GetX(point);
3679  }
3686  Double_t GetSysErrorY(Int_t id, Int_t point) const
3687  {
3688  HolderP2P* h = FindP2P(id);
3689  if (!h) return 0;
3690  return h->GetY(point);
3691  }
3698  Double_t GetSysErrorXLeft(Int_t id, Int_t point) const
3699  {
3700  HolderP2P* h = FindP2P(id);
3701  if (!h) return 0;
3702  return h->GetXLeft(point);
3703  }
3710  Double_t GetSysErrorXRight(Int_t id, Int_t point) const
3711  {
3712  HolderP2P* h = FindP2P(id);
3713  if (!h) return 0;
3714  return h->GetXRight(point);
3715  }
3722  Double_t GetSysErrorYUp(Int_t id, Int_t point) const
3723  {
3724  HolderP2P* h = FindP2P(id);
3725  if (h) return h->GetYUp(point);
3726  HolderCommon* c = FindCommon(id);
3727  if (c) return c->GetYUp(GetY(point));
3728  return 0;
3729  }
3736  Double_t GetSysErrorYDown(Int_t id, Int_t point) const
3737  {
3738  HolderP2P* h = FindP2P(id);
3739  if (h) return h->GetYDown(point);
3740  HolderCommon* c = FindCommon(id);
3741  if (c) return c->GetYDown(GetY(point));
3742  return 0;
3743  }
3751  const char* GetSysTitle(Int_t id) const
3752  {
3753  Holder* h = Find(id);
3754  if (!h) return "";
3755  return h->GetTitle();
3756  }
3764  Style_t GetSysFillStyle(Int_t id) const
3765  {
3766  Holder* h = Find(id);
3767  if (!h) return 0;
3768  return h->GetFillStyle();
3769  }
3777  Style_t GetSysLineStyle(Int_t id) const
3778  {
3779  Holder* h = Find(id);
3780  if (!h) return 0;
3781  return h->GetLineStyle();
3782  }
3790  Color_t GetSysFillColor(Int_t id) const
3791  {
3792  Holder* h = Find(id);
3793  if (!h) return 0;
3794  return h->GetFillColor();
3795  }
3803  Color_t GetSysLineColor(Int_t id) const
3804  {
3805  Holder* h = Find(id);
3806  if (!h) return 0;
3807  return h->GetLineColor();
3808  }
3816  Width_t GetSysLineWidth(Int_t id) const
3817  {
3818  Holder* h = Find(id);
3819  if (!h) return 0;
3820  return h->GetLineWidth();
3821  }
3827  const char* GetSumTitle() const
3828  {
3829  return fSumTitle.Data();
3830  }
3831  UInt_t GetSumOption() const { return fSumOption; }
3837  Style_t GetSumFillStyle() const
3838  {
3839  return fSumFill.GetFillStyle();
3840  }
3846  Style_t GetSumLineStyle() const
3847  {
3848  return fSumLine.GetLineStyle();
3849  }
3855  Color_t GetSumFillColor() const
3856  {
3857  return fSumFill.GetFillColor();
3858  }
3864  Color_t GetSumLineColor() const
3865  {
3866  return fSumLine.GetLineColor();
3867  }
3873  Width_t GetSumLineWidth() const
3874  {
3875  return fSumLine.GetLineWidth();
3876  }
3882  const char* GetCommonSumTitle() const
3883  {
3884  return fCommonSumTitle.Data();
3885  }
3886  UInt_t GetCommonSumOption() const { return fCommonSumOption; }
3892  Style_t GetCommonSumFillStyle() const
3893  {
3894  return fCommonSumFill.GetFillStyle();
3895  }
3901  Style_t GetCommonSumLineStyle() const
3902  {
3903  return fCommonSumLine.GetLineStyle();
3904  }
3910  Color_t GetCommonSumFillColor() const
3911  {
3912  return fCommonSumFill.GetFillColor();
3913  }
3919  Color_t GetCommonSumLineColor() const
3920  {
3921  return fCommonSumLine.GetLineColor();
3922  }
3928  Width_t GetCommonSumLineWidth() const
3929  {
3930  return fCommonSumLine.GetLineWidth();
3931  }
3937  Double_t GetCommonErrorYUp(Int_t id) const
3938  {
3939  HolderCommon* c = FindCommon(id);
3940  if (!c) return 0;
3941  Bool_t rel = c->IsRelative();
3942  return c->GetYUp(rel ? 100 : 1);
3943  }
3949  Double_t GetCommonErrorYDown(Int_t id) const
3950  {
3951  HolderCommon* c = FindCommon(id);
3952  if (!c) return 0;
3953  Bool_t rel = c->IsRelative();
3954  return c->GetYDown(rel ? 100 : 1);
3955  }
3961  const char* GetXTitle() const { return fXTitle.Data(); }
3967  const char* GetYTitle() const { return fYTitle.Data(); }
3975  void GetMinMax(Option_t* option,
3976  Double_t& ymin, Double_t& ymax) const
3977  {
3978  Double_t xmin, xmax;
3979  Int_t imin, imax;
3980  GetMinMax(option, ymin, ymax, xmin, xmax, imin, imax);
3981  }
3993  void GetMinMax(Option_t* option,
3994  Double_t& ymin, Double_t& ymax,
3995  Double_t& xmin, Double_t& xmax,
3996  Int_t& imin, Int_t& imax) const
3997  {
3998  TString opt(option); opt.ToUpper();
3999  Bool_t cmn = opt.Contains("COMMON");
4000  Bool_t stat = opt.Contains("STAT");
4001  Bool_t quad = opt.Contains("QUAD");
4002  Bool_t noerr = opt.Contains("Y");
4003  quad = !opt.Contains("DIRECT");
4004 
4005  ymin = +1e9;
4006  ymax = -1e9;
4007  xmin = -1e9;
4008  xmax = +1e9;
4009  imin = -1;
4010  imax = -1;
4011  for (Int_t i = 0; i < GetN(); i++) {
4012  Double_t eyl = 0;
4013  Double_t eyh = 0;
4014  Double_t y = noerr ? GetY(i) : GetYandError(i, cmn, stat, quad, false, eyl, eyh);
4015  Double_t yl = y - eyl;
4016  Double_t yh = y + eyh;
4017  if (yl < ymin) {
4018  ymin = yl;
4019  xmin = GetX(i);
4020  imin = i;
4021  }
4022  if (yh > ymax) {
4023  ymax = yh;
4024  xmax = GetX(i);
4025  imax = i;
4026  }
4027  // Printf("%3d: %f -> %f +%f -%f -> %f %f -> %f %f",
4028  // i, GetX(i), y, eyl, eyh, yl, yh, ymin, ymax);
4029  }
4030  // Printf("min=(%d,%f,%f) max=(%d,%f,%f)", imin, xmin, ymin, imax, xmax, ymax);
4031  }
4044  void FindFwhm(Int_t start, Int_t dir, Double_t ymax,
4045  Bool_t cmn, Bool_t stat, Bool_t quad,
4046  Int_t& i1, Int_t& i2) const
4047  {
4048  Int_t lim = (dir < 0) ? -1 : GetN();
4049  i1 = i2 = -1;
4050  for (Int_t i = start+dir; i != lim; i += dir) {
4051  Double_t eyl, eyh;
4052  Double_t y = GetYandError(i, cmn, stat, quad, false, eyl, eyh);
4053  // Printf("%3d: %2d %f -> %f -%f +%f (%f, %f, %f) -> %2d %2d",
4054  // i, dir, GetX(i), y, eyl, eyh, y-eyl, y+eyh, ymax/2,
4055  // i1, i2);
4056  if (y-eyl > ymax/2) continue; // Still above
4057  if (y+eyh < ymax/2) break; // Found lower limit
4058  if (i1 < 0) i1 = i2 = i;
4059  else i2 = i;
4060  }
4061  // Printf("Found %d,%d", i1, i2);
4062  }
4071  Double_t FWHM(Double_t& el, Double_t& eh) const
4072  {
4073  Double_t xl, xh;
4074  return FWHM(el, eh, xl, xh);
4075  }
4086  Double_t FWHM(Double_t& el, Double_t& eh, Double_t& xl, Double_t& xh) const
4087  {
4088  Double_t ymin, ymax, xmin, xmax;
4089  Int_t imin, imax;
4090  GetMinMax("quad stat", ymin, ymax, xmin, xmax, imin, imax);
4091  if (ymin > ymax/2) {
4092  Warning("FWHM", "Half of ymax=%f is out of reach [%f,%f]",
4093  ymax/2, ymin, ymax);
4094  return -1;
4095  }
4096 
4097  // Point bounds of found half-max
4098  Int_t li1, li2, ri1, ri2;
4099  // Search left
4100  FindFwhm(imax, -1, ymax, false, true, true, li1, li2);
4101  // Search right
4102  FindFwhm(imax, +1, ymax, false, true, true, ri1, ri2);
4103 
4104  Double_t lsign = 1;
4105  // Check if we've found no left point
4106  if (li1 < 0 && li2 < 0) {
4107  // Check if we've found no right point
4108  if (ri1 < 0 && ri2 < 0) {
4109  Warning("FWHM", "No left and right point found");
4110  return -1;
4111  }
4112  // Set sign, and copy right point to left point
4113  lsign = -1;
4114  li2 = ri1;
4115  li1 = ri2;
4116  }
4117  Double_t rsign = 1;
4118  // Check if we've found no right point
4119  if (ri1 < 0 && ri2 < 0) {
4120  // Check if we've found no left point
4121  if (li1 < 0 && li2 < 0) {
4122  Warning("FWHM", "No right and left point found");
4123  return -1;
4124  }
4125  // Set sign, and copy left point to right point
4126  rsign = -1;
4127  ri2 = li1;
4128  ri1 = li2;
4129  }
4130  // Printf("Points low=(%d,%d) high=(%d,%d)", li1, li2, ri1, ri2);
4131 
4132  // Now find best estimate of left X
4133  LinearSigmaCombiner scl;
4134  scl.Add(lsign*GetX(li1), GetErrorXLeft(li1), GetErrorXRight(li1));
4135  scl.Add(lsign*GetX(li2), GetErrorXLeft(li2), GetErrorXRight(li2));
4136  Combiner::Result* lr = scl.Calculate();
4137  scl.Print();
4138  lr->Print();
4139 
4140  // Now find best estimate of right X
4141  LinearSigmaCombiner scr;
4142  scr.Add(GetX(ri1), GetErrorXLeft(ri1), GetErrorXRight(ri1));
4143  scr.Add(GetX(ri2), GetErrorXLeft(ri2), GetErrorXRight(ri2));
4144  Combiner::Result* rr = scr.Calculate();
4145  scr.Print();
4146  rr->Print();
4147 
4148  // Get error on left/right hand sides
4149  el = lr->fEh+rr->fEl;
4150  eh = lr->fEl+rr->fEh;
4151  if (el < 1e-9 && eh < 1e-9) {
4152  // If the errors are very small, we take the average
4153  xl = (GetX(li2)+GetX(li1))/2;
4154  xh = (GetX(ri2)+GetX(ri1))/2;
4155  el = (GetX(li2)-GetX(li1))/2;
4156  eh = (GetX(ri2)-GetX(ri1))/2;
4157  }
4158  else {
4159  // Otherwise we set left/right hand values to best-fit values
4160  xl = lr->fX;
4161  xh = rr->fX;
4162  }
4163  // Evaluate the full-width half-maximum
4164  Double_t fwhm = (xh - xl);
4165  return fwhm;
4166  }
4167 
4184  Double_t MeanX(Double_t& error,
4185  Bool_t cmn=false,
4186  Bool_t stat=true,
4187  Bool_t quad=true) const
4188  {
4189  Double_t meanX=TMath::Infinity(), stdDev, n;
4190  StatisticsX(meanX, stdDev, n, cmn, stat, quad);
4191  error = stdDev/n;
4192  return meanX;
4193  }
4209  Double_t MeanX(Bool_t cmn=false,
4210  Bool_t stat=true,
4211  Bool_t quad=true) const
4212  {
4213  Double_t error;
4214  return MeanX(error, cmn, stat, quad);
4215  }
4232  Double_t StandardDeviationX(Double_t& error,
4233  Bool_t cmn=false,
4234  Bool_t stat=true,
4235  Bool_t quad=true) const
4236  {
4237  Double_t meanX=TMath::Infinity(), stdDev, eStdDev, n;
4238  StatisticsX(meanX, stdDev, n, cmn, stat, quad);
4239  error = stdDev/TMath::Sqrt(2)/n;
4240  return stdDev;
4241  }
4257  Double_t StandardDeviationX(Bool_t cmn=false,
4258  Bool_t stat=true,
4259  Bool_t quad=true) const
4260  {
4261  Double_t error;
4262  return StandardDeviationX(error, cmn, stat, quad);
4263  }
4264  Double_t StandardDeviationXMean(Double_t mean,
4265  Double_t& error,
4266  Bool_t cmn=false,
4267  Bool_t stat=true,
4268  Bool_t quad=true) const
4269  {
4270  Double_t meanX, stdDev, eStdDev, n;
4271  StatisticsX(meanX, stdDev, n, cmn, stat, quad);
4272  Double_t sd2 = stdDev*stdDev - meanX*meanX;
4273  stdDev = TMath::Sqrt(sd2 - mean*mean);
4274  error = stdDev/TMath::Sqrt(2)/n;
4275  return stdDev;
4276  }
4277 
4308  void StatisticsX(Double_t& meanX,
4309  Double_t& stdDevX,
4310  Double_t& n,
4311  Bool_t cmn=false,
4312  Bool_t stat=true,
4313  Bool_t quad=true) const
4314  {
4315  Double_t sumY = 0;
4316  Double_t sumXY = 0;
4317  Double_t sumXXY = 0;
4318  Double_t sumE2 = 0;
4319  for (Int_t i = 0; i < GetN(); i++) {
4320  Double_t e2yl, e2yh;
4321  Double_t x = GetX(i);
4322  Double_t y = GetYandError(i,cmn,stat,quad,true,e2yl,e2yh);
4323 
4324  sumY += y;
4325  sumXY += x*y;
4326  sumXXY += x*x*y;
4327  sumE2 += TMath::Max(e2yl,e2yh);
4328  }
4329  if (meanX == TMath::Infinity())
4330  meanX = sumXY/sumY;
4331  Double_t sd2 = TMath::Abs(sumXXY/sumY-meanX*meanX);
4332  stdDevX = TMath::Sqrt(sd2);
4333  Double_t eff = sumE2 > 0 ? sumY*sumY/sumE2 : sumY;
4334  n = TMath::Sqrt(eff);
4335  }
4336  /* @} */
4337 
4338  //__________________________________________________________________
4349  void SetSysLineColor(Int_t id, Color_t color) //*MENU*
4350  {
4351  Holder* h = Find(id);
4352  if (!h) return;
4353  h->SetLineColor(color);
4354  }
4361  void SetSysLineStyle(Int_t id, Style_t style) //*MENU*
4362  {
4363  Holder* h = Find(id);
4364  if (!h) return;
4365  h->SetLineStyle(style);
4366  }
4373  void SetSysLineWidth(Int_t id, Width_t width) //*MENU*
4374  {
4375  Holder* h = Find(id);
4376  if (!h) return;
4377  h->SetLineWidth(width);
4378  }
4385  void SetSysFillColor(Int_t id, Color_t color) //*MENU*
4386  {
4387  Holder* h = Find(id);
4388  if (!h) return;
4389  h->SetFillColor(color);
4390  }
4397  void SetSysFillStyle(Int_t id, Style_t style) //*MENU*
4398  {
4399  Holder* h = Find(id);
4400  if (!h) return;
4401  h->SetFillStyle(style);
4402  }
4409  void SetSysTitle(Int_t id, const char* name) //*MENU*
4410  {
4411  Holder* h = Find(id);
4412  if (!h) return;
4413  h->SetTitle(name);
4414  }
4421  void SetSysOption(Int_t id, EDrawOption_t opt) //*MENU*
4422  {
4423  Holder* h = Find(id);
4424  if (!h) return;
4425  h->SetDOption(opt);
4426  }
4427  /* @} */
4428 
4429  //__________________________________________________________________
4439  void SetSumOption(EDrawOption_t opt) { fSumOption = opt; } //*MENU*
4445  void SetSumTitle(const char* title) { fSumTitle = title; } //*MENU*
4451  void SetSumLineColor(Color_t color) { fSumLine.SetLineColor(color); } //*MENU*
4457  void SetSumLineStyle(Style_t style){ fSumLine.SetLineStyle(style); } //*MENU*
4463  void SetSumLineWidth(Width_t width){ fSumLine.SetLineWidth(width); }//*MENU*
4469  void SetSumFillColor(Color_t color){ fSumFill.SetFillColor(color); }//*MENU*
4475  void SetSumFillStyle(Style_t style){ fSumFill.SetFillStyle(style); }//*MENU*
4481  void SetCommonSumOption(EDrawOption_t opt) { fCommonSumOption = opt; } //*MENU*
4487  void SetCommonSumTitle(const char* title) { fCommonSumTitle = title; } //*MENU*
4493  void SetCommonSumLineColor(Color_t color) { fCommonSumLine.SetLineColor(color); } //*MENU*
4499  void SetCommonSumLineStyle(Style_t style){ fCommonSumLine.SetLineStyle(style); } //*MENU*
4505  void SetCommonSumLineWidth(Width_t width){ fCommonSumLine.SetLineWidth(width); }//*MENU*
4511  void SetCommonSumFillColor(Color_t color){ fCommonSumFill.SetFillColor(color); }//*MENU*
4517  void SetCommonSumFillStyle(Style_t style){ fCommonSumFill.SetFillStyle(style); }//*MENU*
4518  /* @} */
4577  void SetKey(const char* key, const char* value, Bool_t replace=false) //*MENU*
4578  {
4579  if (!fMap) {
4580  fMap = new TList();
4581  fMap->SetOwner();
4582  fMap->SetName("keys");
4583  // fMap->SetTitle("key/value pairs");
4584  }
4585  TString k(key);
4586  TString v(value);
4587  TString t = v.Strip(TString::kBoth);
4588  v = t;
4589  if (k.EqualTo("experiment",TString::kIgnoreCase)) {
4590  TObjArray* l = v.Tokenize("-");
4591  t = Token(l, 0); TString lab = t.Strip(TString::kBoth);
4592  t = Token(l, 1); TString acc = t.Strip(TString::kBoth);
4593  t = Token(l, 2); TString exp = t.Strip(TString::kBoth);
4594  SetKey("laboratory", lab.Data(), replace);
4595  SetKey("accelerator", acc.Data(), replace);
4596  SetKey("detector", exp.Data(), replace);
4597  l->Delete();
4598  }
4599  if (k.EqualTo("comment", TString::kIgnoreCase)) {
4600  TString l(GetKey("laboratory"));
4601  TString a(GetKey("accelerator"));
4602  if (!l.IsNull() && !a.IsNull())
4603  v.Remove(0, l.Length()+1+a.Length()+1);
4604  t = v.Strip(TString::kBoth);
4605  fMap->Add(new TNamed("abstract", t.Data()));
4606  }
4607  else {
4608  if (replace) {
4609  TObjLink* cur = fMap->FirstLink();
4610  TObjLink* last = fMap->LastLink();
4611  while (cur) { // != last) {
4612  if (!k.EqualTo(cur->GetObject()->GetName())) {
4613  cur = cur->Next();
4614  continue;
4615  }
4616  TObjLink* tmp = cur->Next();
4617  fMap->Remove(cur);
4618  cur = tmp;
4619  }
4620  }
4621  fMap->Add(new TNamed(k, v));
4622  }
4623  }
4631  const char* GetKey(const char* key) const
4632  {
4633  if (!fMap) return 0;
4634  TObject* o = fMap->FindObject(key);
4635  if (!o) return 0;
4636  return o->GetTitle();
4637  }
4651  void CopyKeys(const GraphSysErr* g, Option_t* option="fr")
4652  {
4653  if (!g) return;
4654 
4655  TString opt(option);
4656  opt.ToLower();
4657 
4658  Bool_t all = opt.Contains("a");
4659  Bool_t file = opt.Contains("f");
4660  Bool_t header = opt.Contains("h");
4661  Bool_t qual = opt.Contains("q");
4662  Bool_t repl = opt.Contains("r");
4663 
4664  // With the "all" option we just do a plain copy
4665  TList* map = g->fMap;
4666  TIter nextKV(map);
4667  TObject* kv = 0;
4668  while ((kv = nextKV())) {
4669  if (!all) {
4670  TString key = kv->GetName();
4671  if (file && !(key.EqualTo("reference") ||
4672  key.EqualTo("laboratory") ||
4673  key.EqualTo("accelerator")||
4674  key.EqualTo("detector") ||
4675  key.EqualTo("abstract") ||
4676  key.EqualTo("author") ||
4677  key.EqualTo("doi") ||
4678  key.EqualTo("inspireId") ||
4679  key.EqualTo("cdsId") ||
4680  key.EqualTo("durhamId") ||
4681  key.EqualTo("title") ||
4682  key.EqualTo("status"))) continue;
4683  if (header && !(key.EqualTo("location") ||
4684  key.EqualTo("reackey") ||
4685  key.EqualTo("obskey") ||
4686  key.EqualTo("dscomment"))) continue;
4687  }
4688  SetKey(kv->GetName(), kv->GetTitle(), repl);
4689  }
4690 
4691  if (!all && !qual) return;
4692  TList* quals = g->fQualifiers;
4693  TIter nextQ(quals);
4694  TObject* qv = 0;
4695  while ((qv = nextQ())) {
4696  const char* test = GetQualifier(qv->GetName());
4697  if (!test || test[0] == '\0')
4698  AddQualifier(qv->GetName(), qv->GetTitle());
4699  }
4700  }
4701  void CopyAttr(const GraphSysErr* f)
4702  {
4703  fDataOption = f->fDataOption;
4704  SetMarkerColor(f->GetMarkerColor());
4705  SetMarkerStyle(f->GetMarkerStyle());
4706  SetMarkerSize(f->GetMarkerSize());
4707  SetLineColor(f->GetLineColor());
4708  SetLineStyle(f->GetLineStyle());
4709  SetLineWidth(f->GetLineWidth());
4710  SetFillColor(f->GetFillColor());
4711  SetFillStyle(f->GetFillStyle());
4712 
4713  fSumOption = f->fSumOption;
4714  SetSumTitle(f->GetSumTitle());
4720 
4728 
4729  SetXTitle(f->GetXTitle());
4730  SetYTitle(f->GetYTitle());
4731  }
4732 
4733 
4734 
4735 
4736  /* @} */
4737  //__________________________________________________________________
4749  void AddQualifier(const TString& key, const TString& value,
4750  Bool_t replace=false)
4751  {
4752  if (!fQualifiers) {
4753  fQualifiers = new TList();
4754  fQualifiers->SetOwner();
4755  fQualifiers->SetName("qualifiers");
4756  }
4757  TString val(value);
4758  if (key.EqualTo(value)) val = "";
4759 
4760  TString k = key.Strip(TString::kBoth, ' ');
4761  TObject* o = fQualifiers->FindObject(k);
4762  if (o) {
4763  Warning("AddQualifier", "Dataset already has qualifier \"%s\"",
4764  k.Data());
4765  if (replace) static_cast<TNamed*>(o)->SetTitle(value);
4766  return;
4767  }
4768 
4769  fQualifiers->Add(new TNamed(k, value));
4770  }
4776  void RemoveQualifier(const TString& key)
4777  {
4778  if (!fQualifiers) return;
4779  TObject* o = fQualifiers->FindObject(key);
4780  if (!o) return;
4781  fQualifiers->Remove(o);
4782  delete o;
4783  }
4791  const char* GetQualifier(const char* name) const
4792  {
4793  if (!fQualifiers) return "";
4794  TObject* o = fQualifiers->FindObject(name);
4795  if (!o) return "";
4796  return o->GetTitle();
4797  }
4798  /* @} */
4815  Bool_t FindYandError(Double_t x,
4816  Bool_t cmn,
4817  Bool_t stat,
4818  Bool_t quad,
4819  Bool_t nosqrt,
4820  Double_t& y,
4821  Double_t& eyl,
4822  Double_t& eyh,
4823  Double_t& seyl,
4824  Double_t& seyh) const
4825  {
4826  Int_t i1, i2;
4827  Int_t ret = FindPoint(x, i1, i2);
4828  seyl = seyh = 0;
4829  if (ret < -1)
4830  // No valid point found
4831  return false;
4832  if (ret >= 0) {
4833  // Got exact point
4834  // Info("", "Get point %d (%f)", ret, x);
4835  y = GetYandError(ret, cmn, stat, quad, nosqrt, eyl, eyh);
4836  if (!stat) {
4837  // If stat error not include, get them here
4838  seyl = GetStatErrorDown(ret);
4839  seyh = GetStatErrorUp(ret);
4840  }
4841  return true;
4842  }
4843  // Interpolate between points
4844  Double_t eyl1, eyl2, eyh1, eyh2;
4845  Double_t x1 = fData->GetX()[i1];
4846  Double_t x2 = fData->GetX()[i2];
4847  Double_t y1 = GetYandError(i1, cmn, stat, quad, nosqrt, eyl1, eyh1);
4848  Double_t y2 = GetYandError(i2, cmn, stat, quad, nosqrt, eyl2, eyh2);
4849  Double_t seyl1 = GetStatErrorDown(i1);
4850  Double_t seyh1 = GetStatErrorUp(i1);
4851  Double_t seyl2 = GetStatErrorDown(i2);
4852  Double_t seyh2 = GetStatErrorUp(i2);
4853 
4854  // Linear interpolation
4855  Double_t dx = (x2-x1);
4856  Double_t ax = (x-x1)/dx;
4857  y = y1 + ax * (y2 - y1);
4858  eyl = eyl1 + ax * (eyl2 - eyl1);
4859  eyh = eyh1 + ax * (eyh2 - eyh1);
4860  if (!stat) {
4861  // if stat errors not included, calculate here
4862  seyl = seyl1 + ax * (seyl2 - seyl1);
4863  seyh = seyh1 + ax * (seyh2 - seyh1);
4864  }
4865  return true;
4866  }
4881  Bool_t FindYandError(Double_t x,
4882  Bool_t cmn,
4883  Bool_t stat,
4884  Bool_t quad,
4885  Bool_t nosqrt,
4886  Double_t& y,
4887  Double_t& eyl,
4888  Double_t& eyh) const
4889  {
4890  Double_t seyl;
4891  Double_t seyh;
4892  return FindYandError(x, cmn, stat, quad, nosqrt, y, eyl, eyh, seyl, seyh);
4893  }
4894 
4895  //__________________________________________________________________
4901  struct Combiner : public TObject
4902  {
4903  typedef Double_t (*Wrapper_t)(Double_t*,Double_t*);
4907  struct Observation : public TObject
4908  {
4910  Double_t fX;
4912  Double_t fEl;
4914  Double_t fEh;
4922  Observation(Double_t x=0, Double_t el=0, Double_t eh=0)
4923  : fX(x), fEl(el), fEh(eh)
4924  {
4925  }
4929  virtual ~Observation() {}
4940  Double_t S() const
4941  {
4942  if (fEl * fEh == 0) return 0;
4943  return 2 * fEl * fEh / (fEl + fEh);
4944  }
4955  Double_t Sprime() const
4956  {
4957  if (TMath::Abs(fEh + fEl) < 1e-9) return 1;
4958  return (fEh - fEl) / (fEh + fEl);
4959  }
4960  Double_t Svar(Double_t guess=0) const
4961  {
4962  return S() + Sprime() * (guess - fX);
4963  }
4974  Double_t V() const { return fEl * fEh; }
4985  Double_t Vprime() const { return fEh - fEl; }
4991  virtual Double_t Low() const { return fX - 3 * fEl; }
4997  virtual Double_t High() const { return fX + 3 * fEh; }
5003  virtual void Print(Option_t* option="") const
5004  {
5005  Printf("%10.8f -%10.8f +%10.8f", fX, fEl, fEh);
5006  }
5007  ClassDef(Observation,1); // An experimental observation
5008  };
5009 
5013  struct Result : public Observation
5014  {
5016  Double_t fChi2;
5018  Double_t fLower;
5020  Double_t fUpper;
5031  Result(Double_t x=0, Double_t el=0, Double_t eh=0,
5032  Double_t chi2=0, Double_t low=0, Double_t high=0)
5033  : Observation(x, el, eh),
5034  fChi2(chi2),
5035  fLower(low),
5036  fUpper(high)
5037  {}
5043  Double_t Low() const { return fLower; }
5049  Double_t High() const { return fUpper; }
5055  virtual void Print(Option_t* option="") const
5056  {
5057  Printf("%10.8f -%10.8f +%10.8f %5.2f", fX, fEl, fEh, fChi2);
5058  }
5059  ClassDef(Result,1); // Final result
5060  };
5061  TClonesArray fData; // Container of observations
5062  Result* fResult; // Result of combining
5063 
5068  : fData("GraphSysErr::Combiner::Observation"), fResult(0)
5069  {
5070  fData.SetOwner();
5071  }
5075  virtual ~Combiner() { fData.Clear(); if (fResult) delete fResult; }
5085  void Clear(Option_t* option="")
5086  {
5087  fData.Clear();
5088  if (fResult) delete fResult;
5089  fResult = 0;
5090  }
5096  void Add(const Observation& r)
5097  {
5098  Add(r.fX,r.fEl,r.fEh);
5099  }
5107  void Add(Double_t x, Double_t el, Double_t eh)
5108  {
5109  // if (TMath::Abs(x) < 1e-10 &&
5110  // TMath::Abs(el) < 1e-10 &&
5111  // TMath::Abs(eh) < 1e-10) return;
5112  new (fData[fData.GetEntries()]) Observation(x,el,eh);
5113  }
5119  void Print(Option_t* option="") const
5120  {
5121  TIter next(&fData);
5122  Observation* r = 0;
5123  while ((r = static_cast<Observation*>(next())))
5124  r->Print(option);
5125  }
5126  /* @} */
5127 
5135  virtual Double_t W(const Observation& r) const = 0;
5144  virtual Double_t StepW(Double_t guess, const Observation& r) const = 0;
5150  virtual Double_t StepOffset(Double_t guess, const Observation& r) const = 0;
5157  virtual Double_t VarTerm(Double_t guess, const Observation& r) const = 0;
5173  Double_t ChiTerm(Double_t guess, const Observation& r) const
5174  {
5175  Double_t var = VarTerm(guess, r);
5176  if (var <= 0) return -1000;
5177 
5178  return TMath::Power(guess - r.fX, 2) / var;
5179  }
5189  Double_t F(Double_t guess,
5190  Double_t chi2) const
5191  {
5192  if (fData.GetEntries() == 1) return 1;
5193  Double_t s = -chi2;
5194 
5195  TIter next(&fData);
5196  Observation* r = 0;
5197  while ((r = static_cast<Observation*>(next())))
5198  s += ChiTerm(guess, *r);
5199  return s;
5200  }
5212  Double_t E(UShort_t nIter,
5213  Int_t sign,
5214  Double_t best,
5215  Double_t chi2,
5216  Double_t s)
5217  {
5218  if (fData.GetEntries() == 1) {
5219  Observation* o = static_cast<Observation*>(fData[0]);
5220  return (sign < 0 ? o->fEl : o->fEh);
5221  }
5222 
5223  // Step size
5224  Double_t delta = 0.1 * sign * s;
5225 
5226  // Iterations
5227  for (UShort_t i = 0; i < nIter; i++) {
5228  // Calculate chi^2 with current guess
5229  Double_t got = F(best + sign * s, chi2);
5230 
5231  if (TMath::Abs(got-1) < 1e-7)
5232  // We're close to 1 so get out
5233  break;
5234 
5235  // The next guess' chi^2 value e
5236  Double_t guess = F(best + sign * s + delta, chi2);
5237 
5238  // Where to search next
5239  if ((got - 1) * (guess - 1) > 0) {
5240  if ((got - 1) / (guess - 1) < 1)
5241  delta = -delta;
5242  else
5243  s += sign * delta;
5244  continue;
5245  }
5246 
5247  // Update error value and decrease step size
5248  s += sign * delta * (1 - got) / (guess - got);
5249  delta /= 2;
5250  }
5251  return s;
5252  }
5262  Double_t X(UShort_t nIter,
5263  Double_t lowest,
5264  Double_t highest)
5265  {
5266  // Starting values
5267  if (fData.GetEntries() == 1)
5268  return static_cast<Observation*>(fData[0])->fX;
5269  Double_t x = (highest+lowest)/2;
5270  Double_t oldX = -1e33;
5271  // Do the iterations
5272  for (UShort_t i = 0; i < nIter; i++) {
5273  Double_t sum = 0;
5274  Double_t sumw = 0;
5275  Double_t offset = 0;
5276 
5277  // Loop over observations
5278  TIter next(&fData);
5279  Observation* r = 0;
5280  while ((r = static_cast<Observation*>(next()))) {
5281  Double_t w = StepW(x, *r);
5282  offset += StepOffset(x, *r);
5283  sum += r->fX * w;
5284  sumw += w;
5285  }
5286  x = (TMath::Abs(sumw) > 1e-9) ? (sum - offset) / sumw : 0;
5287 
5288  if (TMath::Abs(x - oldX) < (highest-lowest) * 1e-9) break;
5289  oldX = x;
5290  }
5291  return x;
5292  }
5300  Result* Calculate(UShort_t nIter=50)
5301  {
5302  Double_t lowest = +1e33;
5303  Double_t highest = -1e33;
5304  Double_t sumLow = 0;
5305  Double_t sumHigh = 0;
5306 
5307  // Find boundaries and sum weights
5308  TIter next(&fData);
5309  Observation* r = 0;
5310  while ((r = static_cast<Observation*>(next()))) {
5311  lowest = TMath::Min(r->Low(), lowest);
5312  highest = TMath::Max(r->High(), highest);
5313  if (r->fEl > 1e-10) sumLow += 1./TMath::Power(r->fEl, 2);
5314  if (r->fEh > 1e-10) sumHigh += 1./TMath::Power(r->fEh, 2);
5315  }
5316  // Summed weights
5317  Double_t sLow = sumLow > 1e-10 ? 1. / TMath::Sqrt(sumLow) : 0;
5318  Double_t sHigh = sumHigh > 1e-10 ? 1. / TMath::Sqrt(sumHigh) : 0;
5319 
5320  // Now do the calculations
5321  Double_t bestX = X(nIter, lowest, highest);
5322  Double_t bestChi2 = F(bestX, 0);
5323  Double_t bestLow = TMath::Abs(E(nIter,-1,bestX,bestChi2,sLow));
5324  Double_t bestHigh = TMath::Abs(E(nIter,+1,bestX,bestChi2,sHigh));
5325 
5326  fResult = new Result(bestX, bestLow, bestHigh, bestChi2, lowest, highest);
5327  return fResult;
5328  }
5334  virtual Wrapper_t Wrapper() const = 0;
5335 
5345  TF1* MakeF(const Observation& r, Int_t j) const
5346  {
5347  TF1* f = new TF1(Form("f%02d", j), Wrapper(), r.Low(), r.High(), 3);
5348  f->SetParNames("x", "#sigma^{-}", "#sigma^{+}");
5349  f->SetParameters(r.fX, r.fEl, r.fEh);
5350  f->SetLineStyle((j%3)+2);
5351  f->SetLineColor(kBlack);
5352  f->SetLineWidth(2);
5353  return f;
5354  }
5362  TLine* MakeL(TF1* f) const
5363  {
5364  Double_t m = f->GetParameter(0);
5365  TLine* l = new TLine(m-f->GetParameter(1), 1,
5366  m+f->GetParameter(2), 1);
5367  l->SetLineColor(f->GetLineColor());
5368  l->SetLineStyle(f->GetLineStyle());
5369  l->SetLineWidth(f->GetLineWidth());
5370  return l;
5371  }
5372  void Draw(Option_t* option="")
5373  {
5374  if (!fResult) return;
5375 
5376  TList fs; fs.SetOwner(false);
5377  Int_t j = 0;
5378  TIter next(&fData);
5379  Observation* r = 0;
5380  while ((r = static_cast<Observation*>(next()))) {
5381  TF1* f = MakeF(*r, j);
5382  f->SetRange(fResult->Low(), fResult->High());
5383  fs.Add(f, j == 0 ? "" : "same");
5384  fs.Add(MakeL(f));
5385  j++;
5386  }
5387  TF1* fr = MakeF(*fResult, j);
5388  fr->SetLineColor(kRed+2);
5389  fr->SetLineStyle(1);
5390  fs.Add(fr);
5391  fs.Add(MakeL(fr));
5392  TIter nextD(&fs);
5393  TObject* o = 0;
5394  j = 0;
5395  while((o = nextD())) { o->Draw(j == 0 ? "" : "same"); j++; }
5396  // fs.Draw();
5397  static_cast<TF1*>(fs.First())->GetHistogram()
5398  ->GetYaxis()->SetRangeUser(-.1, 5.1);
5399  }
5400  ClassDef(Combiner,1); // Combine systematics
5401  };
5402 
5403 
5408  {
5420  Double_t W(const Observation& r) const
5421  {
5422  // Double_t s = r.S();
5423  // if (s < 1e-10) return 0;
5424  // return .5 * TMath::Power(r.Svar(), 3) / s;
5425  Double_t w = StepW(0,r);
5426  return 1/w;
5427  }
5440  Double_t StepW(Double_t guess, const Observation& r) const
5441  {
5442  Double_t s = r.S();
5443  Double_t t = r.Svar(guess);
5444  Double_t ret = s / TMath::Power(t,3);
5445  return ret;
5446  }
5452  Double_t StepOffset(Double_t, const Observation&) const
5453  {
5454  return 0;
5455  }
5469  Double_t VarTerm(Double_t guess, const Observation& r) const
5470  {
5471  return TMath::Power(r.Svar(guess),2);
5472  }
5495  static Double_t L(Double_t guess, Double_t x, Double_t el, Double_t eh)
5496  {
5497  Observation tmp(x,el,eh);
5498  Double_t d = (guess-x);
5499  Double_t t = tmp.Svar(guess); // (s+sp*d);
5500  if (TMath::Abs(d) < 1e-10) return 0;
5501  // if (TMath::Abs(t) < 1e-10) return DBL_MAX;
5502  Double_t ret = TMath::Power(d/t, 2);
5503  return ret;
5504  }
5513  static Double_t WrapL(Double_t* xp, Double_t* pp)
5514  {
5515  return L(xp[0], pp[0], pp[1], pp[2]);
5516  }
5522  Wrapper_t Wrapper() const { return WrapL; }
5523  ClassDef(LinearSigmaCombiner,1); // Sigma combiner
5524  };
5529  {
5541  Double_t W(const Observation& r) const
5542  {
5543  Double_t v = r.V();
5544  Double_t vp = r.Vprime();
5545  return TMath::Power(v + r.fX * vp, 2) / (2 * v + r.fX * vp);
5546  }
5559  Double_t StepW(Double_t guess, const Observation& r) const
5560  {
5561  Double_t v = r.V();
5562  return v / TMath::Power(v+r.Vprime()*(guess - r.fX), 2);
5563  }
5576  Double_t StepOffset(Double_t guess, const Observation& r) const
5577  {
5578  Double_t vp = r.Vprime();
5579  return 0.5 * vp * TMath::Power((guess-r.fX)/(r.V()+vp*(guess-r.fX)),2);
5580  }
5594  Double_t VarTerm(Double_t guess, const Observation& r) const
5595  {
5596  return r.V() + r.Vprime() * (guess - r.fX);
5597  }
5617  static Double_t L(Double_t guess, Double_t x, Double_t el, Double_t eh)
5618  {
5619  Double_t d = (guess-x);
5620  Double_t v = eh * el;
5621  Double_t vp = eh - el;
5622  return TMath::Power(d,2) / (v+vp*d);
5623  }
5632  static Double_t WrapL(Double_t* xp, Double_t* pp)
5633  {
5634  return L(xp[0], pp[0], pp[1], pp[2]);
5635  }
5641  Wrapper_t Wrapper() const { return WrapL; }
5642  ClassDef(LinearVarianceCombiner,1); // Variance combiner
5643  };
5644 
5645  //__________________________________________________________________
5649  struct Holder : public TNamed, TAttLine, TAttFill
5650  {
5652  friend struct GraphSysErr;
5657  : TNamed(),
5658  TAttLine(),
5659  TAttFill(),
5660  fRelative(true),
5661  fOption(kRect)
5662  {}
5666  virtual ~Holder() {}
5667  void CopyAttr(Holder* h)
5668  {
5669  SetLineColor(h->GetLineColor());
5670  SetLineStyle(h->GetLineStyle());
5671  SetLineWidth(h->GetLineWidth());
5672  SetFillColor(h->GetFillColor());
5673  SetFillStyle(h->GetFillStyle());
5674  fOption = h->fOption;
5675  }
5676  protected:
5686  Holder(const char* name, const char* title, Bool_t rel,
5687  UInt_t option, UInt_t id)
5688  : TNamed(name, title),
5689  TAttLine(0,0,0),
5690  TAttFill(0,0),
5691  fRelative(rel),
5692  fOption(option)
5693  {
5694  SetUniqueID(id);
5695  }
5701  Holder(const Holder& other)
5702  : TNamed(other),
5703  TAttLine(other),
5704  TAttFill(other),
5705  fRelative(other.fRelative),
5706  fOption(other.fOption)
5707  {
5708  SetUniqueID(other.GetUniqueID());
5709  }
5717  Holder& operator=(const Holder& other)
5718  {
5719  if (&other == this) return *this;
5720 
5721  other.TNamed::Copy(*this);
5722  other.TAttLine::Copy(*this);
5723  other.TAttFill::Copy(*this);
5724 
5725  fRelative = other.fRelative;
5726  fOption = other.fOption;
5727 
5728  SetUniqueID(other.GetUniqueID());
5729 
5730  return *this;
5731  }
5732 
5742  virtual Graph* StackError(Graph* g, Bool_t ignoreErr, Bool_t quad) const = 0;
5752  virtual void SumError(Graph* g, Int_t i, Bool_t ignoreErr,
5753  Bool_t quad, UInt_t opt) const = 0;
5757  virtual UInt_t GetDOption() const { return fOption; }
5763  virtual void SetDOption(EDrawOption_t opt) { fOption = opt; }
5769  virtual Bool_t IsRelative() const { return fRelative; }
5770 
5771  virtual void Print(Option_t* option="") const
5772  {
5773  gROOT->IndentLevel();
5774  Printf("%s/%s %s(ID # %d%s)", GetName(), GetTitle(),
5775  IsRelative() ? "PCT " : "", GetUniqueID(),
5776  TestBit(kUsedBit) ? " used" : "");
5777  TString opt(option);
5778  if (!opt.Contains("ATTR", TString::kIgnoreCase)) return;
5779  gROOT->IndentLevel();
5780  Printf(" [option: %3d line (c/s/w):%3d/%1d/%2d fill (c/s):%3d/%4d]",
5781  fOption, GetLineColor(), GetLineStyle(), GetLineWidth(),
5782  GetFillColor(), GetFillStyle());
5783 
5784  }
5785  virtual void ls(Option_t* option) const
5786  {
5787  Print(option);
5788  }
5789  protected:
5790  UShort_t XMode(Int_t opt=-1) const
5791  {
5792  UShort_t xMode = 0;
5793  if (opt < 0) opt = fOption;
5794  switch (opt) {
5795  case kNormal: case kNoTick: case kFill: case kCurve: xMode = 0; break;
5796  case kArrow: case kHat: case kBar: xMode = 1; break;
5797  case kNone: xMode = 0; break;
5798  case kRect: case kBox: xMode = 3; break;
5799  }
5800  return xMode;
5801  }
5818  void DoAdd(UShort_t xMode,
5819  Double_t curExl,
5820  Double_t curExh,
5821  Double_t curEyl,
5822  Double_t curEyh,
5823  Bool_t ignoreErr,
5824  Bool_t quad,
5825  Bool_t sqOld,
5826  Double_t& exl,
5827  Double_t& exh,
5828  Double_t& eyl,
5829  Double_t& eyh) const
5830  {
5831  // Double_t oexl = exl;
5832  // Double_t oexh = exh;
5833  if (quad) {
5834  eyl *= eyl;
5835  eyh *= eyh;
5836  if (sqOld) {
5837  curEyl *= curEyl;
5838  curEyh *= curEyh;
5839  }
5840  }
5841 
5842  if (!ignoreErr) {
5843  if (kVerbose & kDraw)
5844  Info("", "old: +%f/-%f this: +%f/-%f -> +%f/-%f",
5845  curEyl, curEyh, eyl, eyh, eyl + curEyl, eyh + curEyh);
5846  exl = TMath::Max(exl, curExl);
5847  exh = TMath::Max(exh, curExh);
5848  eyl += curEyl;
5849  eyh += curEyh;
5850  }
5851 
5852  switch (xMode) {
5853  case 0: break; // kNormal, kNoTick, kFill, kCurve, kNone
5854  case 1: exl = exh = 0; break; // kArrow, kHat, kBar
5855  case 2: // kRect, kBox
5856  if (exl <= 0) exl = gStyle->GetErrorX()/2;
5857  if (exh <= 0) exh = gStyle->GetErrorX()/2;
5858  break;
5859  }
5860  }
5861 
5867  void SetAttributes(Graph* g) const
5868  {
5869  if (!g) return;
5870  this->TAttLine::Copy(*g);
5871  this->TAttFill::Copy(*g);
5872  g->SetMarkerColor(0);
5873  g->SetMarkerStyle(0);
5874  g->SetMarkerSize(0);
5875  }
5877  Bool_t fRelative;
5879  UInt_t fOption;
5880  ClassDef(Holder,3);
5881  };
5882  //__________________________________________________________________
5886  struct HolderP2P : public Holder
5887  {
5889  friend struct GraphSysErr;
5894  : Holder(),
5895  fGraph(0)
5896  {}
5897  protected:
5907  HolderP2P(const char* name, const char* title, Bool_t rel,
5908  UInt_t opt, UInt_t id)
5909  : Holder(name, title, rel, opt, id),
5910  fGraph(0)
5911  {
5912  fGraph = new Graph();
5913  fGraph->SetName(name);
5914  fGraph->SetTitle(title);
5915  SetAttributes(fGraph);
5916  }
5922  HolderP2P(const HolderP2P& other)
5923  : Holder(other),
5924  fGraph(0)
5925  {
5926  if (other.fGraph)
5927  fGraph = static_cast<Graph*>(other.fGraph->Clone());
5928 
5929  if (fGraph) SetAttributes(fGraph);
5930  }
5939  {
5940  if (&other == this) return *this;
5941 
5942  this->Holder::operator=(other);
5943  if (fGraph) delete fGraph;
5944  fGraph = 0;
5945  if (other.fGraph)
5946  fGraph = static_cast<Graph*>(other.fGraph->Clone());
5947  if (fGraph) SetAttributes(fGraph);
5948 
5949  return *this;
5950  }
5951 
5964  void Set(Int_t point, Graph* g, Double_t ex, Double_t ey)
5965  {
5966  Set(point, g, ex, ex, ey, ey);
5967  }
5978  void Set(Int_t point, Graph* g, Double_t ex1, Double_t ex2,
5979  Double_t ey1, Double_t ey2)
5980  {
5981  if (!fGraph) return;
5982  if (!g) return;
5983  if (point >= g->GetN()) return;
5984  Double_t x = g->GetX()[point];
5985  Double_t y = g->GetY()[point];
5986  fGraph->SetPoint(point, x, y);
5987  if (fRelative) { ey1 *= y; ey2 *= y; }
5988  fGraph->SetPointError(point, ex1, ex2, ey1, ey2);
5989  }
5990  /* @} */
5991 
6003  Double_t GetX(Int_t point) const
6004  {
6005  if (!fGraph) return 0;
6006  return fGraph->GetErrorX(point);
6007  }
6015  Double_t GetXLeft(Int_t point) const
6016  {
6017  if (!fGraph) return 0;
6018  return fGraph->GetErrorXlow(point);
6019  }
6027  Double_t GetXRight(Int_t point) const
6028  {
6029  if (!fGraph) return 0;
6030  return fGraph->GetErrorXhigh(point);
6031  }
6039  Double_t GetY(Int_t point) const
6040  {
6041  if (!fGraph) return 0;
6042  return fGraph->GetErrorY(point);
6043  }
6053  Double_t GetYDown(Int_t i1, Int_t i2, Double_t ax) const
6054  {
6055  if (!fGraph) return 0;
6056  if (i1 == i2) return GetYDown(i1);
6057  Double_t e1 = GetYDown(i1);
6058  Double_t e2 = GetYDown(i2);
6059  return e1 + ax * (e2-e1); // Linear interpolation
6060  }
6068  Double_t GetYDown(Int_t point) const
6069  {
6070  if (!fGraph) return 0;
6071  return fGraph->GetErrorYlow(point);
6072  }
6082  Double_t GetYUp(Int_t i1, Int_t i2, Double_t ax) const
6083  {
6084  if (!fGraph) return 0;
6085  if (i1 == i2) return GetYUp(i1);
6086  Double_t e1 = GetYUp(i1);
6087  Double_t e2 = GetYUp(i2);
6088  return e1 + ax * (e2-e1); // Linear interpolation
6089  }
6097  Double_t GetYUp(Int_t point) const
6098  {
6099  if (!fGraph) return 0;
6100  return fGraph->GetErrorYhigh(point);
6101  }
6102  /* @} */
6103 
6121  void AddError(Int_t i,
6122  UShort_t xMode,
6123  Bool_t ignoreErr,
6124  Bool_t quad,
6125  Bool_t sqOld,
6126  Double_t& exl,
6127  Double_t& exh,
6128  Double_t& eyl,
6129  Double_t& eyh) const
6130  {
6131  Double_t exlO = fGraph->GetErrorXlow(i);
6132  Double_t exhO = fGraph->GetErrorXhigh(i);
6133  Double_t eylO = fGraph->GetErrorYlow(i);
6134  Double_t eyhO = fGraph->GetErrorYhigh(i);
6135  Double_t oyl = eylO;
6136  Double_t oyh = eyhO;
6137  if (exl <= 0) exlO = exl;
6138  if (exh <= 0) exhO = exh;
6139 
6140  DoAdd(xMode,
6141  exl, exh, eyl, eyh,
6142  ignoreErr, quad, sqOld,
6143  exlO, exhO, eylO, eyhO);
6144  if (kVerbose & kDraw)
6145  Info(GetTitle(), "quad: %s this: +%f/-%f, old: +%f/-%f -> +%f/-%f",
6146  (quad ? "true" : "false"), oyl, oyh, eyl, eyh, eylO, eyhO);
6147 
6148  exl = exlO;
6149  exh = exhO;
6150  eyl = eylO;
6151  eyh = eyhO;
6152  }
6165  void StackPointError(Int_t i,
6166  UShort_t xMode,
6167  Bool_t ignoreErr,
6168  Bool_t quad,
6169  Double_t& exl,
6170  Double_t& exh,
6171  Double_t& eyl,
6172  Double_t& eyh) const
6173  {
6174  Double_t oldEyl = eyl;
6175  Double_t oldEyh = eyh;
6176  AddError(i, xMode, ignoreErr, quad, true, exl, exh, eyl, eyh);
6177  if (kVerbose & kDraw)
6178  Info(GetTitle(), "old= +%f/-%f -> +%f/-%f", oldEyl, oldEyh, eyl, eyh);
6179  }
6189  Graph* StackError(Graph* g, Bool_t ignoreErr, Bool_t quad) const
6190  {
6191  Graph* ga = new Graph(g->GetN());
6192  for (Int_t i = 0; i < g->GetN(); i++) {
6193  Double_t x = g->GetX()[i];
6194  Double_t y = g->GetY()[i];
6195  Double_t exl = g->GetErrorXlow(i);
6196  Double_t exh = g->GetErrorXhigh(i);
6197  Double_t eyl = g->GetErrorYlow(i);
6198  Double_t eyh = g->GetErrorYhigh(i);
6199  StackPointError(i, XMode(), ignoreErr, quad, exl, exh, eyl, eyh);
6200  // AddError(i, g, quad, ignoreErr, true, exl, exh, eyl, eyh);
6201  ga->SetPoint(i, x, y);
6202  ga->SetPointError(i, exl,exh,eyl,eyh);
6203  }
6204  SetAttributes(ga);
6205  ga->SetTitle(GetTitle());
6206  ga->SetName(Form("stack_%08x", GetUniqueID()));
6207  return ga;
6208  }
6221  void SumPointError(Int_t i, UShort_t xMode, Bool_t ignoreErr, Bool_t quad,
6222  Double_t& exl,
6223  Double_t& exh,
6224  Double_t& eyl,
6225  Double_t& eyh) const
6226  {
6227  AddError(i, xMode, ignoreErr, quad, false, exl, exh, eyl, eyh);
6228  }
6238  void SumError(Graph* g, Int_t i, Bool_t ignoreErr,
6239  Bool_t quad, UInt_t opt) const
6240  {
6241  Double_t exl = (g ? g->GetErrorXlow(i) : 0);
6242  Double_t exh = (g ? g->GetErrorXhigh(i) : 0);
6243  Double_t eyl = (g ? g->GetErrorYlow(i) : 0);
6244  Double_t eyh = (g ? g->GetErrorYhigh(i) : 0);
6245  SumPointError(i, XMode(opt), ignoreErr, quad, exl, exh, eyl, eyh);
6246  g->SetPointError(i, exl,exh,eyl,eyh);
6247  }
6248  /* @} */
6249  void SavePrimitive(std::ostream& out, Option_t* option="")
6250  {
6251  if (option[0] == 'd' || option[0] == 'D')
6252  out << " // Point-2-Point systematic " << GetTitle() << "\n"
6253  << " {\n"
6254  << " Int_t id = g->DeclarePoint2Point(\"" << GetTitle() << "\","
6255  << IsRelative() << ',' << fOption << ");\n"
6256  << " g->SetSysLineColor(id," << GetLineColor() << ");\n"
6257  << " g->SetSysLineStyle(id," << GetLineStyle() << ");\n"
6258  << " g->SetSysLineWidth(id," << GetLineWidth() << ");\n"
6259  << " g->SetSysFillColor(id," << GetFillColor() << ");\n"
6260  << " g->SetSysFillStyle(id," << GetFillStyle() << ");\n"
6261  << " }\n";
6262  }
6263  virtual void Print(Option_t* option="") const
6264  {
6265  gROOT->IndentLevel();
6266  Printf("%s/%s (ID # %d, %d points)", GetName(), GetTitle(), GetUniqueID(),
6267  (fGraph ? fGraph->GetN() : -1));
6268  TString opt(option);
6269  if (!opt.Contains("ATTR", TString::kIgnoreCase)) return;
6270  gROOT->IndentLevel();
6271  Printf(" [option: %3d line (c/s/w):%3d/%1d/%2d fill (c/s):%3d/%4d]",
6272  fOption, GetLineColor(), GetLineStyle(), GetLineWidth(),
6273  GetFillColor(), GetFillStyle());
6274 
6275  }
6277  // Graph* fGraph;
6278  TGraphAsymmErrors* fGraph;
6279 
6280  ClassDef(HolderP2P,3);
6281  };
6282  //__________________________________________________________________
6287  struct HolderCommon : public Holder
6288  {
6290  friend struct GraphSysErr;
6295  : Holder(), fEyl(0), fEyh(0)
6296  {}
6297  protected:
6307  HolderCommon(const char* name, const char* title, Bool_t rel,
6308  UInt_t opt, UInt_t id)
6309  : Holder(name, title, rel, opt, id), fEyl(0), fEyh(0)
6310  {
6311  }
6318  : Holder(other),
6319  fEyl(other.fEyl),
6320  fEyh(other.fEyh)
6321  {
6322  }
6331  {
6332  if (&other == this) return *this;
6333  this->Holder::operator=(other);
6334  fEyl = other.fEyl;
6335  fEyh = other.fEyh;
6336  return *this;
6337  }
6338 
6348  void Set(Double_t ey) { Set(ey, ey); }
6355  void Set(Double_t eyl, Double_t eyh)
6356  {
6357  fEyl = eyl;
6358  fEyh = eyh;
6359  }
6367  Double_t GetYDown(Double_t y=0) const
6368  {
6369  return (fRelative ? y : 1) * fEyl;
6370  }
6378  Double_t GetYUp(Double_t y=0) const
6379  {
6380  return (fRelative ? y : 1) * fEyh;
6381  }
6382  /* @} */
6383 
6402  void AddError(Double_t y,
6403  UShort_t xMode,
6404  Bool_t ignoreErr,
6405  Bool_t quad,
6406  Bool_t sqOld,
6407  Double_t& exl,
6408  Double_t& exh,
6409  Double_t& eyl,
6410  Double_t& eyh) const
6411  {
6412  //exl = (i == 0 ? 0 :(g->GetX()[i] -g->GetX()[i-1])/2);
6413  //exh = (i+1 >= g->GetN()? 0 :(g->GetX()[i+1]-g->GetX()[i])/2);
6414  Double_t exlO = exl;
6415  Double_t exhO = exh;
6416  Double_t eylO = GetYDown(y);
6417  Double_t eyhO = GetYUp(y);
6418  if (exlO <= 0) exlO = gStyle->GetErrorX()/2;
6419  if (exhO <= 0) exhO = gStyle->GetErrorX()/2;
6420 
6421  DoAdd(xMode, exl, exh, eyl, eyh,
6422  ignoreErr, quad, sqOld,
6423  exlO, exhO, eylO, eyhO);
6424  exl = exlO;
6425  exh = exhO;
6426  eyl = eylO;
6427  eyh = eyhO;
6428  }
6439  Graph* BarError(Graph* g, Bool_t quad, Double_t x, Double_t y) const
6440  {
6441  Double_t exl = (g ? g->GetErrorXlow(0) : 0);
6442  Double_t exh = (g ? g->GetErrorXhigh(0) : 0);
6443  Double_t eyl = (g ? g->GetErrorYlow(0) : 0);
6444  Double_t eyh = (g ? g->GetErrorYhigh(0) : 0);
6445  AddError(y, XMode(), false, quad, quad, exl, exh, eyl, eyh);
6446 
6447  Graph* r = new Graph(1);
6448  r->SetPoint(0, x, y);
6449  r->SetPointError(0, exl, exh, eyl, eyh);
6450 
6451  SetAttributes(r);
6452  r->SetTitle(GetTitle());
6453  r->SetName(Form("bar_%08x", GetUniqueID()));
6454 
6455  return r;
6456  }
6469  void StackPointError(Double_t y,
6470  UShort_t xMode,
6471  Bool_t ignoreErr,
6472  Bool_t quad,
6473  Double_t& exl,
6474  Double_t& exh,
6475  Double_t& eyl,
6476  Double_t& eyh) const
6477  {
6478  AddError(y, xMode, ignoreErr, quad, true, exl, exh, eyl, eyh);
6479  }
6480 
6490  Graph* StackError(Graph* g, Bool_t ignoreErr, Bool_t quad) const
6491  {
6492  Graph* ga = new Graph(g->GetN());
6493  for (Int_t i = 0; i < g->GetN(); i++) {
6494  Double_t x = g->GetX()[i];
6495  Double_t y = g->GetY()[i];
6496  Double_t exl = g->GetErrorXlow(i);
6497  Double_t exh = g->GetErrorXhigh(i);
6498  Double_t eyl = g->GetErrorYlow(i);
6499  Double_t eyh = g->GetErrorYhigh(i);
6500  StackPointError(y, XMode(), ignoreErr, quad, exl, exh, eyl, eyh);
6501  ga->SetPoint(i, x, y);
6502  ga->SetPointError(i, exl,exh,eyl,eyh);
6503  }
6504  SetAttributes(ga);
6505  ga->SetTitle(GetTitle());
6506  ga->SetName(Form("stack_%08x", GetUniqueID()));
6507  return ga;
6508  }
6521  void SumPointError(Double_t y, UShort_t xMode, Bool_t ignoreErr,Bool_t quad,
6522  Double_t& exl,
6523  Double_t& exh,
6524  Double_t& eyl,
6525  Double_t& eyh) const
6526  {
6527  AddError(y, xMode, ignoreErr, quad, false, exl, exh, eyl, eyh);
6528  }
6538  void SumError(Graph* g, Int_t i, Bool_t ignoreErr, Bool_t quad,
6539  UInt_t opt) const
6540  {
6541  Double_t y = (g ? g->GetY()[i] : 0);
6542  Double_t exl = (g ? g->GetErrorXlow(i) : 0);
6543  Double_t exh = (g ? g->GetErrorXhigh(i) : 0);
6544  Double_t eyl = (g ? g->GetErrorYlow(i) : 0);
6545  Double_t eyh = (g ? g->GetErrorYhigh(i) : 0);
6546  SumPointError(y, XMode(opt), ignoreErr, quad, exl, exl, eyl, eyh);
6547  g->SetPointError(i, exl,exh,eyl,eyh);
6548  }
6549  /* @} */
6550  void SavePrimitive(std::ostream& out, Option_t* option="")
6551  {
6552  if (option[0] == 'd' || option[0] == 'D')
6553  out << " // Common systematic " << GetTitle() << "\n"
6554  << " {\n"
6555  << " Int_t id = g->DefineCommon(\"" << GetTitle() << "\","
6556  << fRelative << ',' << fEyl << ',' << fEyh << ','
6557  << fOption << ");\n"
6558  << " g->SetSysLineColor(id," << GetLineColor() << ")\n;"
6559  << " g->SetSysLineStyle(id," << GetLineStyle() << ")\n;"
6560  << " g->SetSysLineWidth(id," << GetLineWidth() << ")\n;"
6561  << " g->SetSysFillColor(id," << GetFillColor() << ")\n;"
6562  << " g->SetSysFillStyle(id," << GetFillStyle() << ")\n;"
6563  << " }\n";
6564  }
6565  virtual void Print(Option_t* option="") const
6566  {
6567  Bool_t rel = IsRelative();
6568  Double_t fac = (rel ? 100 : 1);
6569  const char* pst = (rel ? "%" : "");
6570  gROOT->IndentLevel();
6571  Printf("%s/%s (ID # %d) -%f%s +%f%s",
6572  GetName(), GetTitle(), GetUniqueID(),
6573  fac*fEyl, pst, fac*fEyh, pst);
6574  TString opt(option);
6575  if (!opt.Contains("ATTR", TString::kIgnoreCase)) return;
6576  gROOT->IndentLevel();
6577  Printf(" [option: %3d line (c/s/w):%3d/%1d/%2d fill (c/s):%3d/%4d]",
6578  fOption, GetLineColor(), GetLineStyle(), GetLineWidth(),
6579  GetFillColor(), GetFillStyle());
6580 
6581  }
6583  Double_t fEyl;
6585  Double_t fEyh;
6586 
6588  };
6602  Double_t GetYandError(Int_t i,
6603  Bool_t cmn,
6604  Bool_t stat,
6605  Bool_t quad,
6606  Bool_t nosqrt,
6607  Double_t& eyl,
6608  Double_t& eyh) const
6609  {
6610  Double_t wyl = 0;
6611  Double_t wyh = 0;
6612  return GetYandError(i, cmn, stat, quad, nosqrt, eyl, eyh, wyl, wyh);
6613  }
6633  Double_t GetYandError(Int_t i,
6634  Bool_t cmn,
6635  Bool_t stat,
6636  Bool_t quad,
6637  Bool_t nosqrt,
6638  Double_t& eyl,
6639  Double_t& eyh,
6640  Double_t& wyl,
6641  Double_t& wyh) const
6642  {
6643  // --- Find location for common errors ---------------------------
6644  Int_t n = fData->GetN();
6645  if (i >= n) {
6646  eyl = -1;
6647  eyh = -1;
6648  return 0;
6649  }
6650  Double_t y = fData->GetY()[i];
6651  wyl = GetStatErrorDown(i);
6652  wyh = GetStatErrorUp(i);
6653  eyl = (stat ? wyl : 0);
6654  eyh = (stat ? wyh : 0);
6655  if (quad) {
6656  wyl *= wyl;
6657  wyh *= wyh;
6658  eyl *= eyl;
6659  eyh *= eyh;
6660  }
6661  Double_t exl = GetErrorXLeft(i);
6662  Double_t exh = GetErrorXRight(i);
6663 
6664  // Otherwise, we are adding all selected errors togethter
6665  // Graph* g = static_cast<Graph*>(fData->Clone("error"));
6666  // g->SetTitle(fSumTitle);
6667  Int_t xMode = -1;
6668  if (cmn) {
6669  TIter nextC(&fCommon);
6670  HolderCommon* hc = 0;
6671  while ((hc = static_cast<HolderCommon*>(nextC()))) {
6672  if (hc->TestBit(kUsedBit)) continue;
6673  if (xMode < 0) xMode = hc->XMode(fSumOption);
6674  hc->SumPointError(y, xMode, false, quad, exl, exh, wyl, wyh);
6675  if (hc->TestBit(kOnlyWeightBit)) continue;
6676  hc->SumPointError(y, xMode, false, quad, exl, exh, eyl, eyh);
6677  }
6678  }
6679  TIter nextP(&fPoint2Point);
6680  HolderP2P* hp = 0;
6681  while ((hp = static_cast<HolderP2P*>(nextP()))) {
6682  if (hp->TestBit(kUsedBit)) continue;
6683  if (xMode < 0) xMode = hp->XMode(fSumOption);
6684  hp->SumPointError(i, xMode, false, quad, exl, exh, wyl, wyh);
6685  if (hp->TestBit(kOnlyWeightBit)) continue;
6686  hp->SumPointError(i, xMode, false, quad, exl, exh, eyl, eyh);
6687  }
6688  if (quad && !nosqrt) {
6689  eyl = TMath::Sqrt(eyl);
6690  eyh = TMath::Sqrt(eyh);
6691  wyl = TMath::Sqrt(wyl);
6692  wyh = TMath::Sqrt(wyh);
6693  }
6694  return y;
6695  }
6739  static Double_t Round(Double_t v, Int_t p, Int_t& rexpo)
6740  {
6741  if (v == 0) {
6742  // ret.Form("%.*f", p-1, 0);
6743  rexpo = 0;
6744  return 0; // ret.Data();
6745  }
6746 
6747  // Get the sign, take absolute value, get exponent, get scalar, scale
6748  Bool_t neg = (v < 0);
6749  Double_t tmp = TMath::Abs(v);
6750  Int_t expo = Int_t(TMath::Log10(tmp));
6751  Double_t tens = TMath::Power(10, expo - p + 1);
6752  Double_t n = RoundN(tens, tmp); // TMath::Ceil(tmp/tens);
6753 
6754  if (n < TMath::Power(10, p-1)) {
6755  // If scaled is less than 10 to our precision, take off one digit
6756  expo--;
6757  tens = TMath::Power(10, expo - p + 1);
6758  n = RoundN(tens,tmp); // TMath::Ceil(tmp/tens);
6759  }
6760 
6761  if (TMath::Abs((n+1) * tens) <= TMath::Abs(n * tens))
6762  // If the value is not near original, add one
6763  n++;
6764 
6765  if (n >= TMath::Power(10,p)) {
6766  // If value is larger than 10 to our precision, scale down one
6767  n /= 10;
6768  expo++;
6769  }
6770 
6771  rexpo = expo-p+1;
6772  return (neg ? -1 : 1)*n;
6773  }
6774 protected:
6775  static void SwapPoints(Graph* g, Int_t i, Int_t j, Bool_t reflect)
6776  {
6777  Double_t s = (reflect ? -1 : 1);
6778  Double_t tmpX = g->GetX()[i];
6779  Double_t tmpY = g->GetY()[i];
6780  Double_t tmpExl = g->GetErrorXlow(i);
6781  Double_t tmpExh = g->GetErrorXhigh(i);
6782  Double_t tmpEyl = g->GetErrorYlow(i);
6783  Double_t tmpEyh = g->GetErrorYhigh(i);
6784  if (reflect) {
6785  // Swap low and high X error when reflecting
6786  Double_t tmp = tmpExl;
6787  tmpExl = tmpExh;
6788  tmpExh = tmp;
6789  }
6790  g->SetPoint(i, s*g->GetX()[j], g->GetY()[j]);
6791  g->SetPointError(i,
6792  g->GetErrorXlow(j), g->GetErrorXhigh(j),
6793  g->GetErrorYlow(j), g->GetErrorYhigh(j));
6794  g->SetPoint(j, s*tmpX, tmpY);
6795  g->SetPointError(j, tmpExl, tmpExh, tmpEyl, tmpEyh);
6796  }
6801  static const char* FormatKey(const char* key)
6802  {
6803  TString tmp(Form("*%s:", key));
6804  return Form("%-12s", tmp.Data());
6805  }
6814  static const char* ExtractField(const TString& value, Int_t idx)
6815  {
6816  static TString val;
6817  val = "";
6818  TObjArray* tokens = value.Tokenize(":");
6819  Int_t iVal = TMath::Min(Int_t(idx),tokens->GetEntriesFast()-1);
6820  if (iVal < 0) return val;
6821  TString tmp = tokens->At(iVal)->GetName();
6822  val = tmp.Strip(TString::kBoth, ' ');
6823  // tokens->ls();
6824  // ::Info("", "Selecting %d: %s", iVal, val.Data());
6825  delete tokens;
6826  return val.Data();
6827  }
6836  static void StoreQual(TList& quals, Int_t idx,
6837  const char* name, const char* val)
6838  {
6839  TObject* oqv = quals.FindObject(name);
6840  TList* qv = 0;
6841  if (!oqv) {
6842  // ::Info("StoreQual", "Creating list for qualifier %s", name);
6843  qv = new TList;
6844  qv->SetOwner();
6845  qv->SetName(name);
6846  quals.Add(qv);
6847  }
6848  else qv = static_cast<TList*>(oqv);
6849  // ::Info("StoreQual", "Storing %d value %s=%s", idx, name, val);
6850  qv->AddAt(new TObjString(val), idx);
6851  }
6859  static void StoreQual(TList& quals, Int_t idx, TObject* q)
6860  {
6861  StoreQual(quals, idx, q->GetName(), q->GetTitle());
6862  }
6873  std::ostream& ExportKey(std::ostream& out,
6874  const char* which,
6875  Bool_t alsoKey = true,
6876  const char* fill = "<please fill in>") const
6877  {
6878  Bool_t gotit = false;
6879  if (fMap) {
6880  TIter nextK(fMap);
6881  TObject* obj = 0;
6882  while ((obj = nextK())) {
6883  TString k(obj->GetName());
6884  if (!k.EqualTo(which)) continue;
6885  gotit = true;
6886  if (alsoKey) out << FormatKey(obj->GetName());
6887  out << obj->GetTitle() << std::endl;
6888  }
6889  }
6890  if (!gotit) {
6891  if (alsoKey)
6892  out << FormatKey(which);
6893  out << fill << std::endl;
6894  }
6895  return out;
6896  }
6907  std::ostream& ExportHeader(std::ostream& out,
6908  Bool_t alsoTop=false,
6909  Bool_t alsoComment=false,
6910  Int_t nsign=-1) const
6911  {
6912  if (alsoComment) {
6913  out << "# Generated by GraphSysErr\n"
6914  << "# See also\n"
6915  << "# \n"
6916  << "# http://hepdata.cedar.ac.uk/resource/sample.input\n"
6917  << "# http://hepdata.cedar.ac.uk/submittingdata\n"
6918  << "# \n"
6919  << "# Please fill in missing fields\n";
6920  }
6921  if (alsoTop) {
6922  TDatime now;
6923  UserGroup_t* u = gSystem->GetUserInfo();
6924  TString ref = GetKey("reference");
6925  const char* lab = GetKey("laboratory");
6926  const char* accel = GetKey("accelerator");
6927  const char* exper = GetKey("detector");
6928  const char* abs = GetKey("abstract");
6929  const char* months[] = {"JAN","FEB","MAR","APR",
6930  "MAY","JUN","JUL","AUG",
6931  "SEP","OCT","NOV","DEC"};
6932  if (ref.IsNull())
6933  out << "*reference: <journal/archive ref> : <year>" << std::endl;
6934  else {
6935  ExportKey(out, "reference", true, "<reference>");
6936  }
6937  ExportKey(out, "author", true, "<Last name of first author in CAPS>");
6938  ExportKey(out, "doi", true, "<DOI number>");
6939  ExportKey(out, "inspireId", true, "<inSpire ID>");
6940  ExportKey(out, "cdsId", true, "<CDS ID>");
6941  ExportKey(out, "durhamId", true, "<fill in on submission>");
6942  ExportKey(out, "title", true, "<Title of paper>");
6943 
6944  out << FormatKey("status") << "Encoded "
6945  << std::setw(2) << now.GetDay() <<' '<< months[now.GetMonth()-1]<<' '
6946  << std::setw(4) << now.GetYear() << " by "<< u->fRealName.Data()<<"\n"
6947  << FormatKey("experiment") << (lab ? lab : "<lab>") << '-'
6948  << (accel ? accel : "<accelerator>") << '-'
6949  << (exper ? exper : "<experiment>") << '\n'
6950  << FormatKey("detector") << (exper ? exper : "<experiment>") << '\n'
6951  << FormatKey("comment") << (lab ? lab : "<lab>") << '-'
6952  << (accel ? accel : "<accelerator>") << ". "
6953  << (abs ? abs : "<abstract>") << "\n"
6954  << std::endl;
6955  }
6956  out << "# Start of dataset\n";
6957  if (nsign >= 0) out << "# Using " << nsign << " significant digits\n";
6958  out << FormatKey("dataset") << std::endl;
6959  // out << FormatKey("dscomment") << GetTitle() << std::endl;
6960  const char* fields[] = { "location",
6961  "reackey",
6962  "obskey",
6963  "dscomment",
6964  // "qual",
6965  0 };
6966  const char** pfld = fields;
6967  while (*pfld) {
6968  ExportKey(out, *pfld, true);
6969  pfld++;
6970  }
6971  return out;
6972  }
6985  static Int_t ExportError(std::ostream& o,
6986  Double_t low,
6987  Double_t high,
6988  Bool_t nopm,
6989  Bool_t rel,
6990  Int_t nsign)
6991  {
6992  Double_t l = low;
6993  Double_t h = high;
6994  Int_t p = o.precision();
6995  Int_t e = 0;
6996  if (nsign >= 0) {
6997  Int_t pp = nsign;
6998  Int_t le, he;
6999  Double_t lm = Round(l, nsign, le);
7000  Double_t hm = Round(h, nsign, he);
7001  e = TMath::Min(le,he);
7002  l = lm*TMath::Power(10,le);
7003  h = hm*TMath::Power(10,he);
7004  o.precision(pp);
7005  }
7006  // ::Info("ExportError","Before (%2d) -%8f.+%8f After -%8f,+%8f",
7007  // nsign, low,high,l,h);
7008  if (TMath::Abs(h-l) < 1e-12)
7009  o << (nopm ? "" : "+- ") << TMath::Abs(l) << (rel ? " PCT" : "");
7010  else
7011  o << "+" << h << ",-" << l << (rel ? " PCT" : "");
7012  o.precision(p);
7013  return e;
7014  }
7026  std::ostream& ExportPoint(std::ostream& out,
7027  Int_t i,
7028  Bool_t alsoX=true,
7029  Bool_t sysName=true,
7030  Int_t nsign=0) const
7031  {
7032  Int_t p = out.precision();
7033  // out.setf(std::ios::fixed);
7034  if (alsoX) {
7035  Double_t x = GetX(i);
7036  Double_t exl = fData->GetErrorXlow(i);
7037  Double_t exh = fData->GetErrorXhigh(i);
7038  Int_t pp = p;
7039  Int_t ppp = p;
7040  if (nsign > 0) {
7041  Int_t pxl, pxh;
7042  Double_t mxl = Round(exl,nsign,pxl);
7043  Double_t mxh = Round(exh,nsign,pxh);
7044  exl = mxl*TMath::Power(10, pxl);
7045  exh = mxh*TMath::Power(10, pxh);
7046  Int_t mp = TMath::Min(pxl,pxh);
7047  pp = nsign;
7048  ppp = TMath::Ceil(TMath::Log10(TMath::Abs(x)))-mp;
7049  // Info("","pxl=%d pxh=%d mp=%d ppp=%d", pxl, pxh, mp, ppp);
7050  }
7051 
7052  if (TMath::Abs(exl) < 1e-10 && TMath::Abs(exh) < 1e-10) {
7053  if (nsign <= 0) out << ' ' << x;
7054  else {
7055  Int_t px;
7056  Double_t mx = Round(x, nsign, px);
7057  Double_t xx = mx*TMath::Power(10,px);
7058  // Printf("round %f -> %f (%d) -> %.*g", x, mx, px, nsign, xx);
7059  out.precision(nsign);
7060  out << ' ' << xx;
7061  }
7062  }
7063  else {
7064  if (TMath::Abs(exh-exl) < 1e-10) {
7065  out.precision(ppp);
7066  out << ' ' << x-exl << " TO " << x+exh;
7067  }
7068  else {
7069  out.precision(ppp);
7070  out << ' ' << x << ' ';
7071  out.precision(pp);
7072  out << '+' << exh << ",-" << exl;
7073  }
7074  }
7075  out.precision(p);
7076  out << "; ";
7077  }
7078  // out.unsetf(std::ios::fixed);
7079 
7080  Bool_t statRel = fStatRelative;
7081  Double_t y = GetY(i);
7082  Double_t fy = (statRel ? (y == 0 ? 0 : 100./y) : 1);
7083  Double_t eyl = GetStatErrorDown(i) * fy;
7084  Double_t eyh = GetStatErrorUp(i) * fy;
7085  // out << y << ' ';
7086  std::stringstream tmp;
7087  // tmp.setf(std::ios::fixed);
7088  Int_t le = ExportError(tmp, eyl, eyh, false, statRel, nsign);
7089 
7090  if (fPoint2Point.GetEntries() > 0) {
7091  tmp << " (" << std::flush;
7092  TIter nextP(&fPoint2Point);
7093  HolderP2P* holderP2P = 0;
7094  Bool_t first = true;
7095  while ((holderP2P = static_cast<HolderP2P*>(nextP()))) {
7096  Bool_t rel = holderP2P->IsRelative();
7097  fy = (rel ? (y == 0 ? 0 : 100./y) : 1);
7098  if (!first) tmp << ',';
7099  Double_t esh = holderP2P->GetYUp(i)*fy;
7100  Double_t esl = holderP2P->GetYDown(i)*fy;
7101  tmp << "DSYS=";
7102  le = TMath::Min(le,ExportError(tmp, esl, esh, true, rel, nsign));
7103  if (sysName)
7104  tmp << ':' << holderP2P->GetTitle() << std::flush;
7105  first = false;
7106  }
7107  tmp << ')';
7108  }
7109  if (nsign) {
7110  Int_t nY = TMath::Ceil(TMath::Log10(TMath::Abs(y)))-le;
7111  out.precision(nY);
7112  out << y << ' ';
7113  out.precision(p);
7114  }
7115  else
7116  out << y << ' ';
7117  out << tmp.str() << ';';
7118  return out;
7119  }
7138  static Double_t RoundN(Double_t tens, Double_t tmp)
7139  {
7140  // Add small number to not loose least digit if a 1
7141  Double_t n = TMath::Floor(100*tmp/tens+.00001);
7142  Int_t next = int(n/10) % 10;
7143  if (next > 5)
7144  // Round up
7145  return TMath::Ceil(n/100);
7146  if (next < 5)
7147  // Round down
7148  return TMath::Floor(n/100);
7149  Int_t nnext = int(n) % 10;
7150  if (nnext != 0)
7151  // Round up
7152  return TMath::Ceil(n/100);
7153  Int_t last = int(n/100) % 10;
7154  if (last % 2 == 0)
7155  // Round down
7156  return TMath::Floor(n/100);
7157  // Round to nearest even
7158  return TMath::Ceil(n/100);
7159  }
7169  static TString& Token(TObjArray* c, UShort_t idx, Bool_t verbose=true)
7170  {
7171  static TString empty("");
7172  if (idx >= c->GetEntriesFast()) {
7173  if (verbose) {
7174  ::Error("Token", "Token %d does not exist in array", idx);
7175  c->ls();
7176  }
7177  return empty;
7178  }
7179  return static_cast<TObjString*>(c->At(idx))->String();
7180  }
7191  static Bool_t ImportError(const TString& s,
7192  Double_t& el, Double_t& eh, Bool_t& rel)
7193  {
7194  TString tmp(s);
7195  // ::Info("ImportError", "Parsing '%s' for errors", s.Data());
7196  // Allow for PCT (any case) and % as relative markers
7197  if (tmp.Contains("PCT", TString::kIgnoreCase) || tmp.Contains("%"))
7198  rel = true;
7199  if (tmp.BeginsWith("+-") || tmp.BeginsWith("-+")) {
7200  el = eh = tmp.Atof();
7201  // ::Info("ImportError", "Got symmetric %f,%f", el, eh);
7202  return true;
7203  }
7204  TObjArray* tokens = tmp.Tokenize(",");
7205  for (Int_t i = 0; i < tokens->GetEntriesFast(); i++) {
7206  TString& t = Token(tokens, i);
7207  if (t.IsNull()) continue;
7208  t.Remove(TString::kBoth, ' ');
7209  Double_t v = t.Atof();
7210  // ::Info("ImportError", "Got token '%s' -> %f", t.Data(), v);
7211  if (t[0] != '-' && t[0] != '+') {
7212  // ::Info("ImportError", "First char not + or -: %c", t.Data()[0]);
7213  el = eh = TMath::Abs(v);
7214  }
7215  else if (v < 0) {
7216  // ::Info("ImportError", "Value %f < 0 -> setting el=%f", v, -v);
7217  if (el > 0) {
7218  Double_t max = TMath::Max(el, -v);
7219  ::Warning("ImportError",
7220  "Lower error already set to %f, chosing the maximum of "
7221  "(%f,%f) -> %f", el, el, -v, max);
7222  v = -max;
7223  }
7224  el = -v;
7225  }
7226  else {
7227  // ::Info("ImportError", "Value %f >= 0 -> setting eh=%f", v, v);
7228  if (eh > 0) {
7229  Double_t max = TMath::Max(eh, v);
7230  ::Warning("ImportError",
7231  "Lower error already set to %f, chosing the maximum of "
7232  "(%f,%f) -> %f", eh, eh, v, max);
7233  v = max;
7234  }
7235  eh = v;
7236  }
7237  }
7238  // ::Info("ImportError", "Got a-symmetric %f,%f", el, eh);
7239  tokens->Delete();
7240  delete tokens;
7241  return true;
7242  }
7243 
7255  static Bool_t ImportPoint(const TString& s,
7256  Double_t& v,
7257  Double_t& el,
7258  Double_t& eh,
7259  Bool_t& rel)
7260  {
7261  // ::Info("ImportPoint", "s=%s", s.Data());
7262  rel = s.Contains("PCT");
7263  TObjArray* tok = s.Tokenize(" ,");
7264  if (tok->GetEntriesFast() >= 4 &&
7265  Token(tok,2).EqualTo("TO", TString::kIgnoreCase) &&
7266  Token(tok,1).Contains("BIN", TString::kIgnoreCase)) {
7267  v = Token(tok,0).Atof();
7268  TString tmp = Token(tok,1);
7269  TString s1 = tmp.Strip(TString::kBoth, '(');
7270  s1.ReplaceAll("BIN=","");
7271  Double_t v1 = s1.Atof();
7272  tmp = Token(tok,3);
7273  s1 = tmp.Strip(TString::kBoth, ')');
7274  Double_t v2 = s1.Atof();
7275  el = (v-v1);
7276  eh = (v2-v);
7277  }
7278  else if (tok->GetEntriesFast() >= 3 &&
7279  Token(tok,1).EqualTo("TO", TString::kIgnoreCase)) {
7280  Double_t v1 = Token(tok,0).Atof();
7281  Double_t v2 = Token(tok,2).Atof();
7282  v = (v1+v2)/2;
7283  el = (v-v1);
7284  eh = (v2-v);
7285  }
7286  else {
7287  v = Token(tok,0).Atof();
7288  if (tok->GetEntriesFast() >= 2 &&
7289  (Token(tok,1).BeginsWith("+-") ||
7290  Token(tok,1).BeginsWith("-+"))) {
7291  TString t = Token(tok,1);
7292  if (t.Length() > 2) {
7293  t.Remove(0,2);
7294  // ::Info("ImportPoint", "Extract from %s", t.Data());
7295  el = eh = t.Atof();
7296  }
7297  else {
7298  // ::Info("ImportPoint","Extract from next %s",Token(tok, 2).Data());
7299  el = eh = Token(tok,2).Atof();
7300  }
7301  }
7302  else {
7303  for (Int_t i = 1; i < tok->GetEntriesFast(); i++) {
7304  TString t = Token(tok, i);
7305  Char_t m = t[0];
7306  // ::Info("ImportPoint", "%s -> %c", t.Data(), m);
7307  if (m != '+' && m != '-') continue;
7308  if (t.Length() == 1) t = Token(tok, ++i); // Take next
7309  else t.Remove(0,1); // Remove sign
7310  // ::Info("ImportPoint", "%s -> %f", t.Data(), t.Atof());
7311  if (m == '-') el = t.Atof();
7312  else eh = t.Atof();
7313  }
7314  }
7315  }
7316  tok->Delete();
7317  delete tok;
7318  return true;
7319  }
7320  /* @} */
7331  void SqrtPoint(Graph* g, Int_t i)
7332  {
7333  if (kVerbose & kDraw)
7334  printf("%20s Point %3d %f,%f -> ","",
7335  i,g->GetEYlow()[i],g->GetEYhigh()[i]);
7336 
7337  g->GetEYlow()[i] = TMath::Sqrt(g->GetEYlow()[i]);
7338  g->GetEYhigh()[i] = TMath::Sqrt(g->GetEYhigh()[i]);
7339 
7340  if (kVerbose & kDraw)
7341  Printf("%f,%f", g->GetEYlow()[i], g->GetEYhigh()[i]);
7342  }
7348  void SqrtGraph(Graph* g)
7349  {
7350  for (Int_t i = 0; i < g->GetN(); i++)
7351  SqrtPoint(g, i);
7352  }
7353  /* @} */
7363  const char* FormatOption(UInt_t opt)
7364  {
7365  static TString ret;
7366  ret = "";
7367  switch (opt) {
7368  case kNormal: ret = ""; break; // Line with ticks
7369  case kNoTick: ret = "Z0"; break; // Line with no ticks
7370  case kArrow: ret = ">0"; break; // Linw with arrows
7371  case kRect: ret = "20"; break; // Rectangle w/fill
7372  case kBox: ret = "50"; break; // Rectangle w/fill & line
7373  case kFill: ret = "30"; break; // Filled area
7374  case kCurve: ret = "40"; break; // Filled smoothed area
7375  case kHat: ret = "[]0"; break; // Hats
7376  case kBar: ret = "||0"; break; // A bar
7377  case kNone: ret = "XP"; break; // No errors
7378  case kLine: ret = "CX"; break;
7379  case kConnect: ret = "LX"; break;
7380  }
7381  return ret.Data();
7382  }
7388  void MakeDataGraph(Int_t n)
7389  {
7390  fData = new Graph(n);
7391  fData->SetName(Form("%s_data", fName.Data()));
7392  fData->SetTitle(GetTitle());
7393  }
7404  Int_t FindPoint(Double_t x, Int_t& i1, Int_t& i2, Double_t fac=1) const
7405  {
7406  i1 = -1;
7407  i2 = -1;
7408  Int_t n = GetN();
7409  if (x < GetX(0)-fac*GetErrorXLeft(0) ||
7410  x > GetX(n-1)+fac*GetErrorXRight(n-1)) {
7411  // If we're out side the coverage, set return to -1
7412  // Info("FindPoint", "X=%f Out of range [%f,%f]",
7413  // x,GetX(0),GetX(GetN()-1));
7414  i1 = i2 = -1;
7415  return -2;
7416  }
7417  const Double_t tol = 1e-9;
7418  for (Int_t i=0; i < n; i++) {
7419  // if (TMath::Abs(GetX(i)-x) < tol) {
7420  if (x <= GetX(i)+fac*GetErrorXRight(i) &&
7421  x >= GetX(i)-fac*GetErrorXLeft(i)) {
7422  // if ((GetX(i)+GetErrorXRight(i)-x)<tol &&
7423  // (x - GetX(i) - GetErrorXLeft(i) <tol)) {
7424  // Found matching point
7425  i2 = i1 = i;
7426  break;
7427  }
7428  // Info("FindPoint", "Not @ %d (%f not in %f -%f +%f)",
7429  // i, x, GetX(i), GetErrorXLeft(i), GetErrorXRight(i));
7430  if (x > GetX(i)) {
7431  // X still larger
7432  i1 = i;
7433  }
7434  else {
7435  // X is lower
7436  i2 = i;
7437  break;
7438  }
7439  }
7440  if (i1 == i2)
7441  // If equal, return the point
7442  return i1;
7443  if (TMath::Abs((GetX(i1)+fac*GetErrorXRight(i1)) -
7444  (GetX(i2)-fac*GetErrorXLeft(i2))) > 10*tol) {
7445  // If the two found points are not adjecent, we are in a hole
7446  // and we indicate that.
7447  // Info("FindPoint","Found hole at i1=%d(%f+%f) i2=%d(%f-%f) (%f)",
7448  // i1, GetX(i1), GetErrorXRight(i1),
7449  // i2, GetX(i2), GetErrorXLeft(i2), x);
7450  // Print("xy");
7451  i1 = i2 = -1;
7452  return -2;
7453  }
7454  if (i2 > 0) {
7455  // Otherwise return negative value to indicate we should look at
7456  // two points.
7457  // Info("FindPoint","Found i1=%d i2=%d %f in [%f,%f]", i1, i2,
7458  // x, GetX(i1)-GetErrorXLeft(i1), GetX(i2)+GetErrorXRight(i2));
7459  return -1;
7460  }
7461  // Return negative two to indicate nothing was found
7462  return -2;
7463 
7464  }
7472  TMultiGraph* MakeMulti(Option_t* option)
7473  {
7474  if (!fData) {
7475  Warning("MakeMulti", "No data defined");
7476  return 0;
7477  }
7478 
7479  // --- Process options -------------------------------------------
7480  TString opt(option);
7481  opt.ToUpper();
7482 
7483  Bool_t cmn = opt.Contains("COMMON");
7484  Bool_t combine = opt.Contains("COMBINED");
7485  Bool_t stat = opt.Contains("STAT");
7486  Bool_t quad = opt.Contains("QUAD");
7487  combine = !opt.Contains("STACK");
7488  quad = !opt.Contains("DIRECT");
7489  Bool_t split = opt.Contains("SPLIT");
7490  Int_t xpos = (opt.Contains("WEST") ? -1 : 1);
7491  Int_t ypos = (opt.Contains("MIN") ? -1 :
7492  opt.Contains("MAX") ? 1 : 0);
7493 
7494  // --- Some general information ----------------------------------
7495  Int_t n = fData->GetN();
7496  Double_t dx = TMath::Max(gStyle->GetErrorX(),0.0001F);
7497  if (n <= 0) {
7498  Warning("MakeMulti", "Nothing to do (n=%d)", n);
7499  return 0;
7500  }
7501 
7502  // --- Find location for common errors ---------------------------
7503  Double_t xBase = 0;
7504  if (opt.Contains("XBASE=")) {
7505  Int_t idx = opt.Index("XBASE=")+6;
7506  TString tmp = opt(idx,opt.Length()-idx);
7507  xBase = tmp.Atof();
7508  }
7509  else {
7510  xBase = ((xpos < 0 ?
7511  fData->GetX()[0] - fData->GetEXlow()[0]:
7512  fData->GetX()[n-1] + fData->GetEXhigh()[n-1])
7513  + xpos * 1.2 * dx);
7514  }
7515  Double_t yBase = fData->GetY()[0];
7516  for (Int_t i = 0; i < n; i++) {
7517  Double_t y = fData->GetY()[i];
7518  yBase = (ypos < 0 ? TMath::Min(yBase, y) :
7519  ypos > 0 ? TMath::Max(yBase, y) : yBase + y);
7520  }
7521  if (ypos == 0) yBase /= n;
7522 
7523  // --- Create stack and temp collection --------------------------
7524  TList drawn;
7525  drawn.SetOwner(false);
7526 
7527  Graph* prev = 0;
7528  if (!combine) {
7529  // If we're not combining, we basically copy the graphs to the
7530  // draw list, but modify the errors to show progresive larger
7531  // errors.
7532  prev = fData;
7533  if (cmn) {
7534  // If we should add common errors, do that first
7535  TIter next(&fCommon);
7536  Holder* h = 0;
7537  while ((h = static_cast<Holder*>(next()))) {
7538  Graph* g = h->StackError(prev, (!stat ? prev == fData : false), quad);
7539  if (!g) continue;
7540 
7541  if (quad) SqrtGraph(g);
7542  prev = g;
7543  drawn.AddFirst(g, FormatOption(h->GetDOption()));
7544  }
7545  }
7546  TIter next(&fPoint2Point);
7547  Holder* h = 0;
7548  while ((h = static_cast<Holder*>(next()))) {
7549  Graph* g = h->StackError(prev, (!stat ? prev == fData : false), quad);
7550  if (!g) continue;
7551 
7552  if (quad) SqrtGraph(g);
7553  prev = g;
7554  drawn.AddFirst(g, FormatOption(h->GetDOption()));
7555  }
7556  }
7557  else {
7558  // Otherwise, we are adding all selected errors togethter
7559  Graph* g = static_cast<Graph*>(fData->Clone("error"));
7560  g->SetTitle(fSumTitle);
7561  Holder* h = 0;
7562  for (Int_t i = 0; i < n; i++) {
7563  if (!stat) {
7564  g->SetPointError(i, g->GetEXlow()[i],
7565  g->GetEXhigh()[i],0,0);
7566  }
7567  else if (quad) {
7568  // g->GetEXlow()[i] *= g->GetEXlow()[i];
7569  g->GetEYlow()[i] *= g->GetEYlow()[i];
7570  // g->GetEXhigh()[i] *= g->GetEXhigh()[i];
7571  g->GetEYhigh()[i] *= g->GetEYhigh()[i];
7572  }
7573 
7574 
7575  if (cmn) {
7576  TIter nextC(&fCommon);
7577  while ((h = static_cast<Holder*>(nextC()))) {
7578  h->SumError(g, i, false, quad, fSumOption);
7579 
7580  }
7581  }
7582  TIter nextP(&fPoint2Point);
7583  while ((h = static_cast<Holder*>(nextP())))
7584  h->SumError(g, i, false, quad, fSumOption);
7585 
7586  // Printf("Point # %d", i);
7587  if (quad) SqrtPoint(g, i);
7588  }
7589  fSumLine.Copy(*g);
7590  fSumFill.Copy(*g);
7591  g->SetMarkerStyle(0);
7592  g->SetMarkerSize(0);
7593  g->SetMarkerColor(0);
7594 
7595  drawn.AddFirst(g, FormatOption(fSumOption));
7596  }
7597  // --- Show common errors on the side, if requested --------------
7598  if (!cmn) {
7599  TIter nextC(&fCommon);
7600  HolderCommon* hc = 0;
7601  if (!combine) {
7602  prev = 0;
7603  while ((hc = static_cast<HolderCommon*>(nextC()))) {
7604  Graph* g = hc->BarError(prev, quad && !split, xBase, yBase);
7605  if (!g) {
7606  Warning("MakeMulti", "Got no graph for common error %s",
7607  hc->GetTitle());
7608  continue;
7609  }
7610 
7611  if (quad && !split) SqrtGraph(g);
7612 
7613  if (split) xBase += xpos * 1.2 * dx;
7614  if (!prev)
7615  drawn.AddLast(g, FormatOption(hc->GetDOption()));
7616  else {
7617  // Here, we use the underling linked list of the list so
7618  // that we can add an object before another including the
7619  // possible options
7620  TObjLink* f = drawn.FirstLink();
7621  TObjLink* p = 0;
7622  while (f && f->GetObject()) {
7623  if (f->GetObject() == prev) {
7624  if (p) new TObjOptLink(g, p, FormatOption(hc->GetDOption()));
7625  else new TObjOptLink(g, FormatOption(hc->GetDOption()));
7626  break;
7627  }
7628  p = f;
7629  f = f->Next();
7630  }
7631  }
7632  prev = (split ? 0 : g);
7633  } // while (hc)
7634  } // !combine
7635  else {
7636  // Combine systematics
7637  if (fCommon.GetEntries() > 0) {
7638  Graph* g = new Graph(1);
7639  g->SetPoint(0, xBase, yBase);
7640  Double_t exl = 0;
7641  Double_t exh = 0;
7642  Double_t eyl = 0;
7643  Double_t eyh = 0;
7644  while ((hc = static_cast<HolderCommon*>(nextC()))) {
7645  hc->SumPointError(yBase, hc->XMode(fCommonSumOption),
7646  false, quad, exl, exh, eyl, eyh);
7647  }
7648  g->SetPointError(0, exl, exh, eyl, eyh);
7649  fCommonSumLine.Copy(*g);
7650  fCommonSumFill.Copy(*g);
7651  g->SetMarkerStyle(0);
7652  g->SetMarkerSize(0);
7653  g->SetMarkerColor(0);
7654 
7655  if (quad) SqrtGraph(g);
7656  drawn.AddLast(g, FormatOption(fCommonSumOption));
7657  } // while hc
7658  }
7659  }
7660  // --- Copy attributes to data copy ------------------------------
7661  this->TAttLine::Copy(*fData);
7662  this->TAttFill::Copy(*fData);
7663  this->TAttMarker::Copy(*fData);
7664 
7665  // --- Get the options for drawing the data ----------------------
7666  TString dopt = FormatOption(fDataOption);
7667  dopt.Append(" p same");
7668  // if (stat && combine) dopt.Append(" X");
7669 
7670  // --- Add copy of data to stack ---------------------------------
7671  if (!stat) {
7672  // If stat are not combined into point-to-point, add straight copy
7673  drawn.AddLast(fData->Clone("data"), dopt.Data());
7674  }
7675  else {
7676  // Otherwise, we just add the markers (i.e., all errors zero'd)
7677  TGraph* g = new TGraph(fData->GetN());
7678  g->SetName("data");
7679  g->SetTitle(fData->GetTitle());
7680  this->TAttLine::Copy(*g);
7681  this->TAttFill::Copy(*g);
7682  this->TAttMarker::Copy(*g);
7683  for (Int_t i = 0; i < fData->GetN(); i++)
7684  g->SetPoint(i, fData->GetX()[i], fData->GetY()[i]);
7685  drawn.AddLast(g, dopt.Data());
7686  }
7687 
7688  // --- Now copy objects from temp collection to stack ------------
7689  TMultiGraph* ret = new TMultiGraph("drawn", GetTitle());
7690  TIter nextG(&drawn);
7691  TGraph* gg = 0;
7692  while ((gg = static_cast<TGraph*>(nextG()))) {
7693  if (kVerbose & kDraw)
7694  Printf("%-20s:%-20s %20s "
7695  "(line:%3d/%d/%d, marker:%3d/%2d/%4f, fill:%3d/%4d)",
7696  gg->GetName(), gg->GetTitle(), nextG.GetOption(),
7697  gg->GetLineColor(), gg->GetLineStyle(), gg->GetLineWidth(),
7698  gg->GetMarkerColor(), gg->GetMarkerStyle(), gg->GetMarkerSize(),
7699  gg->GetFillColor(), gg->GetFillStyle());
7700  ret->Add(gg, nextG.GetOption());
7701  }
7702  return ret;
7703  }
7704  /* @} */
7709  //__________________________________________________________________
7717  HolderP2P* FindP2P(UInt_t id) const
7718  {
7719  TIter next(&fPoint2Point);
7720  TObject* o = 0;
7721  while ((o = next())) {
7722  if (o->GetUniqueID() != id) continue;
7723  return static_cast<HolderP2P*>(o);
7724  }
7725  return 0;
7726  }
7734  HolderCommon* FindCommon(UInt_t id) const
7735  {
7736  TIter next(&fCommon);
7737  TObject* o = 0;
7738  while ((o = next())) {
7739  if (o->GetUniqueID() != id) continue;
7740  return static_cast<HolderCommon*>(o);
7741  }
7742  return 0;
7743  }
7754  Double_t tol=1e-6,
7755  bool verb=false) const
7756  {
7757  if (!o) return 0;
7758  Int_t id = FindId(o->GetTitle());
7759  if (id <= 0) {
7760  if (verb)
7761  Warning("FindCompat[C]", "Syst.unc. '%s' not found in %s",
7762  o->GetTitle(), GetName());
7763  return 0;
7764  }
7765  HolderCommon* c = FindCommon(id);
7766  if (!c) {
7767  if (verb)
7768  Warning("FindCompat[C]", "Syst.unc. '%s' (%d) is not a common",
7769  o->GetTitle(), id);
7770  return 0;
7771  }
7772  if (o->IsRelative() != c->IsRelative()) {
7773  if (verb)
7774  Warning("FindCompat[C]", "Inconsistent value type (%s) of '%s' (%d)",
7775  c->IsRelative() ? "relative" : "fixed",
7776  c->GetTitle(), id);
7777  return 0;
7778  }
7779  Double_t ltol = 0.01;
7780  Double_t x1, x2, test;
7781  x1 = o->GetYDown(1);
7782  x2 = c->GetYDown(1);
7783  test = TMath::Abs(x2-x1) / (1+TMath::Min(TMath::Abs(x1), TMath::Abs(x2)));
7784  if (test > ltol) {
7785  if (verb) {
7786  Warning("FindCompat[C]","Lower value %10f of '%s' (%d) "
7787  "incompatible with %10f (|%f|>%f [%g])",
7788  c->GetYDown(1), c->GetTitle(), id, o->GetYDown(1),
7789  test, ltol, tol);
7790  c->Print("common");
7791  o->Print("common");
7792  }
7793  return 0;
7794  }
7795  x1 = o->GetYDown(1);
7796  x2 = c->GetYDown(1);
7797  test = TMath::Abs(x2-x1) / (1+TMath::Min(TMath::Abs(x1), TMath::Abs(x2)));
7798  if (TMath::Abs(o->GetYUp(1)-c->GetYUp(1)) > ltol) {
7799  if (verb) {
7800  Warning("FindCompat[C]","Upper value %10f of '%s' (%d) "
7801  "incompatible with %10f (|%f|>%f [%g])",
7802  c->GetYUp(1), c->GetTitle(), id, o->GetYUp(1),
7803  test, ltol, tol);
7804  c->Print("common");
7805  o->Print("common");
7806  }
7807  return 0;
7808  }
7809  // All is good
7810  return c;
7811  }
7820  HolderP2P* FindCompat(const HolderP2P* o, Bool_t verb=false) const
7821  {
7822  if (!o) return 0;
7823  Int_t id = FindId(o->GetTitle());
7824  if (id <= 0) {
7825  if (verb)
7826  Warning("FindCompat[P]", "Syst.unc. '%s' not found in %s",
7827  o->GetTitle(), GetName());
7828  return 0;
7829  }
7830  HolderP2P* p = FindP2P(id);
7831  if (!p) {
7832  if (verb)
7833  Warning("FindCompat[P]", "Syst.unc. '%s' (%d) is not point-to-point",
7834  o->GetTitle(), id);
7835  return 0;
7836  }
7837  if (o->IsRelative() != p->IsRelative()) {
7838  if (verb)
7839  Warning("FindCompat[P]", "Inconsistent value type (%s) of '%s' (%d)",
7840  p->IsRelative() ? "relative" : "fixed",
7841  p->GetTitle(), id);
7842  return 0;
7843  }
7844  return p;
7845  }
7853  Holder* Find(UInt_t id) const
7854  {
7855  Holder* h = FindP2P(id);
7856  if (h) return h;
7857  TIter nextC(&fCommon);
7858  TObject* o = 0;
7859  while ((o = nextC())) {
7860  if (o->GetUniqueID() != id) continue;
7861  return static_cast<Holder*>(o);
7862  }
7863  return 0;
7864  }
7865  /* @} */
7869  TList fCommon;
7871  // Graph* fData;
7872  TGraphAsymmErrors* fData;
7874  TMultiGraph* fDrawn;
7876  UInt_t fCounter;
7878  TAttFill fSumFill;
7880  TAttLine fSumLine;
7882  TString fSumTitle;
7883  // Drawin option for sums
7884  UInt_t fSumOption;
7886  TAttFill fCommonSumFill;
7888  TAttLine fCommonSumLine;
7891  // Drawin option for sums
7893  // Drawing options for data
7894  UInt_t fDataOption;
7896  TString fXTitle;
7898  TString fYTitle;
7900  TList* fMap;
7902  TList* fQualifiers;
7905  ClassDef(GraphSysErr,4);
7906 };
7929 #endif
7930 //
7931 // EOF
7932 //
7933 
static Double_t L(Double_t guess, Double_t x, Double_t el, Double_t eh)
Return the likely-hood function value at :
Definition: GraphSysErr.C:5617
static Double_t WrapL(Double_t *xp, Double_t *pp)
Wrap likely-hood function for ROOT.
Definition: GraphSysErr.C:5632
virtual ~Observation()
Virtual destructor.
Definition: GraphSysErr.C:4929
virtual void SumError(Graph *g, Int_t i, Bool_t ignoreErr, Bool_t quad, UInt_t opt) const =0
Sum errors at point.
static void StoreQual(TList &quals, Int_t idx, TObject *q)
Store a qualifier in a table.
Definition: GraphSysErr.C:6859
Result(Double_t x=0, Double_t el=0, Double_t eh=0, Double_t chi2=0, Double_t low=0, Double_t high=0)
The final result.
Definition: GraphSysErr.C:5031
TAttLine fCommonSumLine
Attributes of summed errors.
Definition: GraphSysErr.C:7888
void SavePrimitive(std::ostream &out, Option_t *option="")
Definition: GraphSysErr.C:6249
void Set(Int_t point, Graph *g, Double_t ex1, Double_t ex2, Double_t ey1, Double_t ey2)
Set errors at point.
Definition: GraphSysErr.C:5978
void SumPointError(Int_t i, UShort_t xMode, Bool_t ignoreErr, Bool_t quad, Double_t &exl, Double_t &exh, Double_t &eyl, Double_t &eyh) const
Sum up point errors.
Definition: GraphSysErr.C:6221
void Export(std::ostream &out=std::cout, Option_t *option="", Int_t nsign=2)
Dump on stream a table suitable (After some editing) for uploading to the Durham database.
Definition: GraphSysErr.C:2602
TAttFill fSumFill
Attributes of summed errors.
Definition: GraphSysErr.C:7878
Width_t GetCommonSumLineWidth() const
Get line width of sum systematic uncertainty.
Definition: GraphSysErr.C:3928
Result * Calculate(UShort_t nIter=50)
Do the calculation.
Definition: GraphSysErr.C:5300
Double_t VarTerm(Double_t guess, const Observation &r) const
Calculate the contribution variance to the with the guess .
Definition: GraphSysErr.C:5594
void AddError(Double_t y, UShort_t xMode, Bool_t ignoreErr, Bool_t quad, Bool_t sqOld, Double_t &exl, Double_t &exh, Double_t &eyl, Double_t &eyh) const
Add errors together at point.
Definition: GraphSysErr.C:6402
UInt_t GetCommonSumOption() const
Definition: GraphSysErr.C:3886
Width_t GetSumLineWidth() const
Get line width of sum systematic uncertainty.
Definition: GraphSysErr.C:3873
void Print(Option_t *option="") const
Print content of the list.
Definition: GraphSysErr.C:5119
void SetSysLineColor(Int_t id, Color_t color)
Set the line color of the systematice error identified by ID.
Definition: GraphSysErr.C:4349
void SetYTitle(const char *title)
Set title on y axis.
Definition: GraphSysErr.C:3588
static void StoreQual(TList &quals, Int_t idx, const char *name, const char *val)
Store a qualifier in a table.
Definition: GraphSysErr.C:6836
UInt_t fDataOption
Definition: GraphSysErr.C:7894
std::ostream & ExportKey(std::ostream &out, const char *which, Bool_t alsoKey=true, const char *fill="<please fill in>") const
Export all values of a key.
Definition: GraphSysErr.C:6873
Double_t GetSysErrorXLeft(Int_t id, Int_t point) const
Definition: GraphSysErr.C:3698
Double_t GetSysErrorY(Int_t id, Int_t point) const
Definition: GraphSysErr.C:3686
static Double_t ChisquareTest(const GraphSysErr *g1, const GraphSysErr *g2, Int_t &ndf, EChi2Type type)
Calculate the test of equivilance between two graphs.
Definition: GraphSysErr.C:2194
Double_t(* Wrapper_t)(Double_t *, Double_t *)
Definition: GraphSysErr.C:4903
void Draw(Option_t *option="")
Draw this data.
Definition: GraphSysErr.C:781
void SetSysLineStyle(Int_t id, Style_t style)
Set the line style of the systematice error identified by ID.
Definition: GraphSysErr.C:4361
void Draw(Option_t *option="")
Definition: GraphSysErr.C:5372
TMultiGraph * fDrawn
The drawn graphs.
Definition: GraphSysErr.C:7874
UInt_t fCommonSumOption
Definition: GraphSysErr.C:7892
Double_t GetStatErrorUp(Int_t point) const
Definition: GraphSysErr.C:3635
Double_t GetYandError(Int_t i, Bool_t cmn, Bool_t stat, Bool_t quad, Bool_t nosqrt, Double_t &eyl, Double_t &eyh) const
Get the point value and low and high errors.
Definition: GraphSysErr.C:6602
void SetStatError(Int_t i, Double_t eyl, Double_t eyh)
Definition: GraphSysErr.C:3506
void SavePrimitive(std::ostream &out, Option_t *option="")
Definition: GraphSysErr.C:6550
UInt_t fOption
Options.
Definition: GraphSysErr.C:5879
const char * GetXTitle() const
Get name of X axis.
Definition: GraphSysErr.C:3961
TList * fQualifiers
List of qualifiers.
Definition: GraphSysErr.C:7902
Double_t GetYDown(Double_t y=0) const
Get the down error.
Definition: GraphSysErr.C:6367
void SetSysOption(Int_t id, EDrawOption_t opt)
Set the draw option for a specific systematic error.
Definition: GraphSysErr.C:4421
void GetMinMax(Option_t *option, Double_t &ymin, Double_t &ymax, Double_t &xmin, Double_t &xmax, Int_t &imin, Int_t &imax) const
Get minimum and maximum.
Definition: GraphSysErr.C:3993
void SetKey(const char *key, const char *value, Bool_t replace=false)
Set a key/value pair.
Definition: GraphSysErr.C:4577
Double_t GetSysErrorYUp(Int_t id, Int_t point) const
Definition: GraphSysErr.C:3722
Color_t GetSysLineColor(Int_t id) const
Get line color of systematic uncertainty.
Definition: GraphSysErr.C:3803
void SetPointError(Int_t i, Double_t ex)
Set the X error (bin width) of the ith point.
Definition: GraphSysErr.C:3458
Double_t GetYUp(Int_t i1, Int_t i2, Double_t ax) const
Get the errors upwards along Y between points i1 and i2.
Definition: GraphSysErr.C:6082
const char * GetYTitle() const
Get name of Y axis.
Definition: GraphSysErr.C:3967
Graph * BarError(Graph *g, Bool_t quad, Double_t x, Double_t y) const
Make a graph for showing next to data.
Definition: GraphSysErr.C:6439
Double_t StandardDeviationX(Bool_t cmn=false, Bool_t stat=true, Bool_t quad=true) const
Calculate the standard deviatin along X.
Definition: GraphSysErr.C:4257
virtual Bool_t IsRelative() const
Check if this is a relative error.
Definition: GraphSysErr.C:5769
void SetSysFillStyle(Int_t id, Style_t style)
Set the fill style of the systematice error identified by ID.
Definition: GraphSysErr.C:4397
static Int_t CacheGraphs(const GraphSysErr *g1, const GraphSysErr *g2, TArrayD &a1y, TArrayD &a2y, TArrayD &a1e2, TArrayD &a2e2)
Get the Y and error values for the two passed graphs.
Definition: GraphSysErr.C:2121
virtual Double_t Low() const
Lower bound.
Definition: GraphSysErr.C:4991
UInt_t FindId(const char *title) const
Find the ID of an error with the given title.
Definition: GraphSysErr.C:3414
Double_t StepOffset(Double_t, const Observation &) const
Calculate the bias.
Definition: GraphSysErr.C:5452
void SetSysLineWidth(Int_t id, Width_t width)
Set the line width of the systematice error identified by ID.
Definition: GraphSysErr.C:4373
virtual Double_t StepOffset(Double_t guess, const Observation &r) const =0
Calculate the bias.
virtual void Print(Option_t *option="") const
Definition: GraphSysErr.C:6263
void SetSysError(Int_t id, Double_t eyl, Double_t eyh)
Definition: GraphSysErr.C:3518
Double_t GetErrorXRight(Int_t p) const
Definition: GraphSysErr.C:3617
TString fXTitle
X title.
Definition: GraphSysErr.C:7896
void Add(const Observation &r)
Add an obervation.
Definition: GraphSysErr.C:5096
HolderCommon * FindCompat(const HolderCommon *o, Double_t tol=1e-6, bool verb=false) const
Find an error in this graph that is compatible with the passed error.
Definition: GraphSysErr.C:7753
const char * GetQualifier(const char *name) const
Get qualifier.
Definition: GraphSysErr.C:4791
void SetCommonSumLineColor(Color_t color)
Set the line color of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4493
TAttLine fSumLine
Attributes of summed errors.
Definition: GraphSysErr.C:7880
std::ostream & ExportPoint(std::ostream &out, Int_t i, Bool_t alsoX=true, Bool_t sysName=true, Int_t nsign=0) const
Export a single point.
Definition: GraphSysErr.C:7026
Observation(Double_t x=0, Double_t el=0, Double_t eh=0)
Create a single obersvation.
Definition: GraphSysErr.C:4922
Wrapper_t Wrapper() const
Return function pointer to wrapper.
Definition: GraphSysErr.C:5522
Width_t GetSysLineWidth(Int_t id) const
Get line width of systematic uncertainty.
Definition: GraphSysErr.C:3816
TList fCommon
List of common errors.
Definition: GraphSysErr.C:7869
void AddQualifier(const TString &key, const TString &value, Bool_t replace=false)
Adds a qualifier.
Definition: GraphSysErr.C:4749
void SwapPoints(Int_t i, Int_t j, Bool_t reflect=false)
Swap two points.
Definition: GraphSysErr.C:2284
void RemoveQualifier(const TString &key)
Remove a qualifier.
Definition: GraphSysErr.C:4776
void SumPointError(Double_t y, UShort_t xMode, Bool_t ignoreErr, Bool_t quad, Double_t &exl, Double_t &exh, Double_t &eyl, Double_t &eyh) const
Sum up point errors.
Definition: GraphSysErr.C:6521
Double_t StandardDeviationX(Double_t &error, Bool_t cmn=false, Bool_t stat=true, Bool_t quad=true) const
Calculate the standard deviatin along X.
Definition: GraphSysErr.C:4232
const char * GetSysTitle(Int_t id) const
Get title of systematic error.
Definition: GraphSysErr.C:3751
Double_t StepOffset(Double_t guess, const Observation &r) const
Calculate the bias.
Definition: GraphSysErr.C:5576
Double_t MeanX(Double_t &error, Bool_t cmn=false, Bool_t stat=true, Bool_t quad=true) const
Calculate the mean along X.
Definition: GraphSysErr.C:4184
void SetSumLineStyle(Style_t style)
Set the line style of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4457
virtual Double_t High() const
Upper bound.
Definition: GraphSysErr.C:4997
UInt_t GetSumOption() const
Definition: GraphSysErr.C:3831
Double_t GetYandError(Int_t i, Bool_t cmn, Bool_t stat, Bool_t quad, Bool_t nosqrt, Double_t &eyl, Double_t &eyh, Double_t &wyl, Double_t &wyh) const
Get the point value and low and high errors.
Definition: GraphSysErr.C:6633
void SetCommonSumOption(EDrawOption_t opt)
Set the draw option for summed errors.
Definition: GraphSysErr.C:4481
Double_t S() const
Calculate.
Definition: GraphSysErr.C:4940
Double_t GetY(Int_t point) const
Definition: GraphSysErr.C:3623
Double_t GetStatErrorDown(Int_t point) const
Definition: GraphSysErr.C:3644
TString fYTitle
Y title.
Definition: GraphSysErr.C:7898
HolderCommon(const HolderCommon &other)
Copy CTOR.
Definition: GraphSysErr.C:6317
static TString & Token(TObjArray *c, UShort_t idx, Bool_t verbose=true)
Get the ith token from the array of tokens c.
Definition: GraphSysErr.C:7169
void RemoveSysError(Int_t id)
Definition: GraphSysErr.C:3394
Int_t Average(const TCollection *others, Bool_t sep=true)
Average one or more graphs.
Definition: GraphSysErr.C:1003
An experimental observation.
Definition: GraphSysErr.C:4907
GraphSysErr(const GraphSysErr &other)
Copy CTOR.
Definition: GraphSysErr.C:347
Double_t E(UShort_t nIter, Int_t sign, Double_t best, Double_t chi2, Double_t s)
Try to find best error.
Definition: GraphSysErr.C:5212
Double_t GetSysErrorXRight(Int_t id, Int_t point) const
Definition: GraphSysErr.C:3710
void CopyAttr(const GraphSysErr *f)
Definition: GraphSysErr.C:4701
Double_t VarTerm(Double_t guess, const Observation &r) const
Calculate the contribution variance to the with the guess .
Definition: GraphSysErr.C:5469
virtual void Print(Option_t *option="") const
Definition: GraphSysErr.C:5771
void StackPointError(Int_t i, UShort_t xMode, Bool_t ignoreErr, Bool_t quad, Double_t &exl, Double_t &exh, Double_t &eyl, Double_t &eyh) const
Stack up point errors.
Definition: GraphSysErr.C:6165
static TSeqCollection * Import(const TString &fileName)
Import all data sets from a Durham input formatted file.
Definition: GraphSysErr.C:2983
void SqrtPoint(Graph *g, Int_t i)
Take the square root of the errors at point.
Definition: GraphSysErr.C:7331
Base class to hold systematic errors.
Definition: GraphSysErr.C:5649
Style_t GetCommonSumFillStyle() const
Get fill style of sum systematic uncertainty.
Definition: GraphSysErr.C:3892
void SetStatError(Int_t i, Double_t ey)
Set the statistical error on the ith data point.
Definition: GraphSysErr.C:3495
void SetCommonSumTitle(const char *title)
Set the title uses for summed errors.
Definition: GraphSysErr.C:4487
Graph * StackError(Graph *g, Bool_t ignoreErr, Bool_t quad) const
Create new graph with stacked errors.
Definition: GraphSysErr.C:6490
Double_t V() const
Calculate.
Definition: GraphSysErr.C:4974
TGraphAsymmErrors Graph
A short-hand type definition.
Definition: GraphSysErr.C:186
void CopyAttr(Holder *h)
Definition: GraphSysErr.C:5667
void MakeDataGraph(Int_t n)
Make our data graph.
Definition: GraphSysErr.C:7388
virtual ~Holder()
DTOR.
Definition: GraphSysErr.C:5666
static Bool_t ImportPoint(const TString &s, Double_t &v, Double_t &el, Double_t &eh, Bool_t &rel)
Service function to import a point value (X or Y) with errors.
Definition: GraphSysErr.C:7255
TGraphAsymmErrors * fGraph
Our data.
Definition: GraphSysErr.C:6278
Double_t GetErrorXLeft(Int_t p) const
Definition: GraphSysErr.C:3611
TGraphAsymmErrors * fData
Our data points.
Definition: GraphSysErr.C:7872
void SetPoint(Int_t i, Double_t x, Double_t y)
Set the ith data point.
Definition: GraphSysErr.C:3447
void StatisticsX(Double_t &meanX, Double_t &stdDevX, Double_t &n, Bool_t cmn=false, Bool_t stat=true, Bool_t quad=true) const
Calculates the statistics of X.
Definition: GraphSysErr.C:4308
static void SwapPoints(Graph *g, Int_t i, Int_t j, Bool_t reflect)
Definition: GraphSysErr.C:6775
Color_t GetSumFillColor() const
Get fill color of sum systematic uncertainty.
Definition: GraphSysErr.C:3855
GraphSysErr(Int_t n)
CTOR with number of points.
Definition: GraphSysErr.C:273
static Bool_t NextPoint(Int_t i, const GraphSysErr *num, const GraphSysErr *denom, Double_t &x, Double_t &dY, Double_t &dEyl, Double_t &dEyh, Double_t &nY, Double_t &nEyl, Double_t &nEyh)
Find the next point and for ratio.
Definition: GraphSysErr.C:1566
Style_t GetSumLineStyle() const
Get line style of sum systematic uncertainty.
Definition: GraphSysErr.C:3846
void SetTitle(const char *name)
Set the title of the data.
Definition: GraphSysErr.C:3566
ERatioOption
Options for ratios.
Definition: GraphSysErr.C:223
UInt_t DefineCommon(const char *title, Bool_t relative, Double_t ey, EDrawOption_t option=kFill)
Define a common systematic error.
Definition: GraphSysErr.C:3340
Double_t GetYUp(Int_t point) const
Get errors upward along Y at point.
Definition: GraphSysErr.C:6097
std::ostream & ExportHeader(std::ostream &out, Bool_t alsoTop=false, Bool_t alsoComment=false, Int_t nsign=-1) const
Export data set header, and possibly file header too.
Definition: GraphSysErr.C:6907
EChi2Type
Types of comparisons.
Definition: GraphSysErr.C:209
void SumError(Graph *g, Int_t i, Bool_t ignoreErr, Bool_t quad, UInt_t opt) const
Sum errors at point.
Definition: GraphSysErr.C:6238
void Save(const char *fileName)
Save to a ROOT script.
Definition: GraphSysErr.C:2557
virtual void Print(Option_t *option="") const
Print to standard output.
Definition: GraphSysErr.C:5003
TFitResultPtr Fit(const char *formula, Option_t *fitOption, Option_t *drawOption, Axis_t min=0, Axis_t max=0)
Fit a function to the data.
Definition: GraphSysErr.C:891
static Double_t KolomogorovTest(const GraphSysErr *g1, const GraphSysErr *g2, Double_t &z)
Perform a Kolomogorov-Smironov test.
Definition: GraphSysErr.C:2072
static Bool_t ImportError(const TString &s, Double_t &el, Double_t &eh, Bool_t &rel)
Import errors from a string.
Definition: GraphSysErr.C:7191
Double_t StandardDeviationXMean(Double_t mean, Double_t &error, Bool_t cmn=false, Bool_t stat=true, Bool_t quad=true) const
Definition: GraphSysErr.C:4264
This class defines an (X,Y) with any number of error sources.
Definition: GraphSysErr.C:174
UInt_t DeclarePoint2Point(const char *title, Bool_t relative, EDrawOption_t option=kBar)
Delcare a point-to-point systematic error.
Definition: GraphSysErr.C:3383
void AddError(Int_t i, UShort_t xMode, Bool_t ignoreErr, Bool_t quad, Bool_t sqOld, Double_t &exl, Double_t &exh, Double_t &eyl, Double_t &eyh) const
Add errors together at point.
Definition: GraphSysErr.C:6121
static Double_t KolomogorovTest(const GraphSysErr *g1, const GraphSysErr *g2)
Perform a Kolomogorov-Smironov test.
Definition: GraphSysErr.C:2055
void Set(Double_t eyl, Double_t eyh)
Set error.
Definition: GraphSysErr.C:6355
virtual Double_t StepW(Double_t guess, const Observation &r) const =0
Calculate the weight based on a guess of best .
void SetStatRelative(Bool_t rel)
Set whether statistical errors should be considered relative.
Definition: GraphSysErr.C:3482
Int_t FindPoint(Double_t x, Int_t &i1, Int_t &i2, Double_t fac=1) const
Find point (or possibly two points) that match X.
Definition: GraphSysErr.C:7404
HolderP2P * FindCompat(const HolderP2P *o, Bool_t verb=false) const
Find an error in this graph that is compatible with the passed error.
Definition: GraphSysErr.C:7820
Double_t fEyl
Down errors.
Definition: GraphSysErr.C:6583
void GetMinMax(Option_t *option, Double_t &ymin, Double_t &ymax) const
Get minimum and maximum.
Definition: GraphSysErr.C:3975
HolderP2P & operator=(const HolderP2P &other)
Assignement operator.
Definition: GraphSysErr.C:5938
void SumError(Graph *g, Int_t i, Bool_t ignoreErr, Bool_t quad, UInt_t opt) const
Sum errors at point.
Definition: GraphSysErr.C:6538
static Double_t Round(Double_t v, Int_t p, Int_t &rexpo)
Round number v to n significant digits.
Definition: GraphSysErr.C:6739
void SetDataOption(EDrawOption_t opt)
Set the draw option for the data and statistical errors.
Definition: GraphSysErr.C:3576
GraphSysErr & operator=(const GraphSysErr &other)
Assignment operator.
Definition: GraphSysErr.C:416
virtual UInt_t GetDOption() const
Definition: GraphSysErr.C:5757
Style_t GetSumFillStyle() const
Get fill style of sum systematic uncertainty.
Definition: GraphSysErr.C:3837
UShort_t XMode(Int_t opt=-1) const
Definition: GraphSysErr.C:5790
GraphSysErr(const char *name, const char *title, Int_t n=0)
Constructor with name, title, and optional pre-allocated size.
Definition: GraphSysErr.C:311
Style_t GetSysLineStyle(Int_t id) const
Get line style of systematic uncertainty.
Definition: GraphSysErr.C:3777
virtual Double_t W(const Observation &r) const =0
Calculate the weight.
Holder of common errors.
Definition: GraphSysErr.C:6287
Double_t fLower
Lower bound to use.
Definition: GraphSysErr.C:5018
virtual void Print(Option_t *option="R") const
Print this.
Definition: GraphSysErr.C:492
TString fSumTitle
Title on summed errors.
Definition: GraphSysErr.C:7882
Double_t MeanX(Bool_t cmn=false, Bool_t stat=true, Bool_t quad=true) const
Calculate the mean along X.
Definition: GraphSysErr.C:4209
Double_t GetCommonErrorYUp(Int_t id) const
Get the common systematic error.
Definition: GraphSysErr.C:3937
void SavePrimitive(std::ostream &out, Option_t *option="")
Definition: GraphSysErr.C:2450
HolderCommon * FindCommon(UInt_t id) const
Find a common error graph.
Definition: GraphSysErr.C:7734
void SetSysFillColor(Int_t id, Color_t color)
Set the fill color of the systematice error identified by ID.
Definition: GraphSysErr.C:4385
TLine * MakeL(TF1 *f) const
Make a line that represents the best found errors.
Definition: GraphSysErr.C:5362
virtual ~GraphSysErr()
DTOR.
Definition: GraphSysErr.C:400
Graph * StackError(Graph *g, Bool_t ignoreErr, Bool_t quad) const
Create new graph with stacked errors.
Definition: GraphSysErr.C:6189
static void EscapeLtx(TString &val, const TString &fill="")
Utility to escape out TLatex stuff, and put &#39;$...$&#39; around LaTeX.
Definition: GraphSysErr.C:2668
static Double_t ChisquareTest(const GraphSysErr *g1, const GraphSysErr *g2, EChi2Type type=kExperimentTruth)
Calculate the test of equivilance between two graphs.
Definition: GraphSysErr.C:2174
Double_t FWHM(Double_t &el, Double_t &eh) const
Calculate the full-width at half-maximum.
Definition: GraphSysErr.C:4071
virtual void Print(Option_t *option="") const
Definition: GraphSysErr.C:6565
Double_t W(const Observation &r) const
Calculate the weight.
Definition: GraphSysErr.C:5541
Double_t Low() const
Lower bound.
Definition: GraphSysErr.C:5043
TAttFill fCommonSumFill
Attributes of summed errors.
Definition: GraphSysErr.C:7886
static Int_t ExportError(std::ostream &o, Double_t low, Double_t high, Bool_t nopm, Bool_t rel, Int_t nsign)
Export an error.
Definition: GraphSysErr.C:6985
TF1 * MakeF(const Observation &r, Int_t j) const
Make a function that represents to Log-likehood for a given observation.
Definition: GraphSysErr.C:5345
static Double_t RoundN(Double_t tens, Double_t tmp)
Round number.
Definition: GraphSysErr.C:7138
virtual ~Combiner()
Virtual destructor.
Definition: GraphSysErr.C:5075
Double_t fEyh
Up errors.
Definition: GraphSysErr.C:6585
void SqrtGraph(Graph *g)
Take the square root of the errors.
Definition: GraphSysErr.C:7348
Double_t GetXLeft(Int_t point) const
Get errors to the left along X at point.
Definition: GraphSysErr.C:6015
void SetSumFillStyle(Style_t style)
Set the fill style of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4475
virtual Wrapper_t Wrapper() const =0
Return function pointer to wrapper.
Double_t Svar(Double_t guess=0) const
Definition: GraphSysErr.C:4960
void Scale(TF1 *f, Double_t s=1)
Scale graph by a constant.
Definition: GraphSysErr.C:930
Combiner()
Constructor.
Definition: GraphSysErr.C:5067
TMultiGraph * GetMulti(Option_t *option="")
Get last drawn multigraph or create a new one.
Definition: GraphSysErr.C:914
Int_t GetN() const
Definition: GraphSysErr.C:3599
A combiner that uses a linear approximation.
Definition: GraphSysErr.C:5407
virtual Graph * StackError(Graph *g, Bool_t ignoreErr, Bool_t quad) const =0
Create new graph with stacked errors.
const char * GetKey(const char *key) const
Get (first) value of a key.
Definition: GraphSysErr.C:4631
void SetSumOption(EDrawOption_t opt)
Set the draw option for summed errors.
Definition: GraphSysErr.C:4439
HolderP2P(const char *name, const char *title, Bool_t rel, UInt_t opt, UInt_t id)
CTOR with name and title.
Definition: GraphSysErr.C:5907
Double_t ChiTerm(Double_t guess, const Observation &r) const
Calculate the contribution variance to the with the guess .
Definition: GraphSysErr.C:5173
HolderCommon(const char *name, const char *title, Bool_t rel, UInt_t opt, UInt_t id)
CTOR with name and title.
Definition: GraphSysErr.C:6307
void SetSumLineWidth(Width_t width)
Set the line width of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4463
Double_t Integral(Double_t &error, Option_t *option="quad sum stat", UShort_t first=0, Short_t last=-1)
Calculate the intergral and error on integral of the graph.
Definition: GraphSysErr.C:1514
Bool_t FindYandError(Double_t x, Bool_t cmn, Bool_t stat, Bool_t quad, Bool_t nosqrt, Double_t &y, Double_t &eyl, Double_t &eyh) const
Find Y value and errors corresponding X.
Definition: GraphSysErr.C:4881
Double_t High() const
Upper bound.
Definition: GraphSysErr.C:5049
void SetAttributes(Graph *g) const
Set attributes.
Definition: GraphSysErr.C:5867
Bool_t fRelative
Relative error flag.
Definition: GraphSysErr.C:5877
virtual void SetDOption(EDrawOption_t opt)
Set the draw option.
Definition: GraphSysErr.C:5763
Double_t X(UShort_t nIter, Double_t lowest, Double_t highest)
Find best estimate of .
Definition: GraphSysErr.C:5262
Bool_t IsCommon(Int_t id) const
Definition: GraphSysErr.C:3648
virtual Double_t VarTerm(Double_t guess, const Observation &r) const =0
Calculate the contribution variance to the with the guess .
static void Export(const TSeqCollection *col, std::ostream &out, Option_t *option="H", Int_t nsign=0)
Export a set of data sets to a single table.
Definition: GraphSysErr.C:2691
UInt_t DefineCommon(const char *title, Bool_t relative, Double_t eyl, Double_t eyh, EDrawOption_t option=kRect)
Define a common systematic error.
Definition: GraphSysErr.C:3356
Bool_t fStatRelative
Whether statistical errors are relative.
Definition: GraphSysErr.C:7904
void SetSumTitle(const char *title)
Set the title uses for summed errors.
Definition: GraphSysErr.C:4445
HolderCommon & operator=(const HolderCommon &other)
Assignment operator.
Definition: GraphSysErr.C:6330
virtual void Browse(TBrowser *b)
Browse this object.
Definition: GraphSysErr.C:676
Double_t StepW(Double_t guess, const Observation &r) const
Calculate the weight based on a guess of best .
Definition: GraphSysErr.C:5559
Int_t GetNSys() const
Definition: GraphSysErr.C:3432
Bool_t Symmetrize(GraphSysErr *other)
Symmetrice the other graph and store result here.
Definition: GraphSysErr.C:2316
void SetSysError(Int_t id, Int_t i, Double_t ex, Double_t ey)
Set the systematic error identified by id on the ith data point.
Definition: GraphSysErr.C:3532
void ClearUsed() const
Clear bit we set during the processing.
Definition: GraphSysErr.C:2030
void SetPointError(Int_t i, Double_t exl, Double_t exh)
Set the X error (bin width) of the ith point.
Definition: GraphSysErr.C:3469
Double_t GetCommonErrorYDown(Int_t id) const
Get the common systematic error.
Definition: GraphSysErr.C:3949
Style_t GetCommonSumLineStyle() const
Get line style of sum systematic uncertainty.
Definition: GraphSysErr.C:3901
TFitResultPtr Fit(TF1 *f1, Option_t *fitOption, Option_t *drawOption, Axis_t min=0, Axis_t max=0)
Fit a function to the data.
Definition: GraphSysErr.C:823
void SetSysError(Int_t id, Int_t i, Double_t exl, Double_t exh, Double_t eyl, Double_t eyh)
Set the systematic error identified by id on the ith data point.
Definition: GraphSysErr.C:3548
Style_t GetSysFillStyle(Int_t id) const
Get fill style of systematic uncertainty.
Definition: GraphSysErr.C:3764
Holder * Find(UInt_t id) const
Find any error.
Definition: GraphSysErr.C:7853
Double_t W(const Observation &r) const
Calculate the weight.
Definition: GraphSysErr.C:5420
void SetSysTitle(Int_t id, const char *name)
Set the systematic error title.
Definition: GraphSysErr.C:4409
HolderP2P(const HolderP2P &other)
Copy CTOR.
Definition: GraphSysErr.C:5922
Double_t GetX(Int_t point) const
Get symmetric errors along X at point.
Definition: GraphSysErr.C:6003
void SetCommonSumLineStyle(Style_t style)
Set the line style of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4499
Double_t fUpper
Upper bound to use.
Definition: GraphSysErr.C:5020
Color_t GetCommonSumLineColor() const
Get line color of sum systematic uncertainty.
Definition: GraphSysErr.C:3919
Double_t F(Double_t guess, Double_t chi2) const
Calculate the where is current guess at the observation.
Definition: GraphSysErr.C:5189
Double_t FWHM(Double_t &el, Double_t &eh, Double_t &xl, Double_t &xh) const
Calculate the full-width at half-maximum.
Definition: GraphSysErr.C:4086
Double_t GetXRight(Int_t point) const
Get errors to the right along X at point.
Definition: GraphSysErr.C:6027
Holder(const char *name, const char *title, Bool_t rel, UInt_t option, UInt_t id)
CTOR with name and title.
Definition: GraphSysErr.C:5686
void Add(Double_t x, Double_t el, Double_t eh)
Add an observation.
Definition: GraphSysErr.C:5107
Double_t GetYDown(Int_t i1, Int_t i2, Double_t ax) const
Get the errors downwards along Y between points i1 and i2.
Definition: GraphSysErr.C:6053
static const char * FormatKey(const char *key)
Definition: GraphSysErr.C:6801
Color_t GetCommonSumFillColor() const
Get fill color of sum systematic uncertainty.
Definition: GraphSysErr.C:3910
Double_t GetYUp(Double_t y=0) const
Get the up error.
Definition: GraphSysErr.C:6378
void StackPointError(Double_t y, UShort_t xMode, Bool_t ignoreErr, Bool_t quad, Double_t &exl, Double_t &exh, Double_t &eyl, Double_t &eyh) const
Stack up point errors.
Definition: GraphSysErr.C:6469
Double_t GetSysErrorX(Int_t id, Int_t point) const
Definition: GraphSysErr.C:3674
static const char * ExtractField(const TString &value, Int_t idx)
Extract a field from a string.
Definition: GraphSysErr.C:6814
void Scale(Double_t s)
Scale graph by a constant.
Definition: GraphSysErr.C:963
const char * GetSumTitle() const
Get title of summed systematic error.
Definition: GraphSysErr.C:3827
void Set(Double_t ey)
Set symmetric error.
Definition: GraphSysErr.C:6348
Color_t GetSumLineColor() const
Get line color of sum systematic uncertainty.
Definition: GraphSysErr.C:3864
Holder(const Holder &other)
Copy constructorr.
Definition: GraphSysErr.C:5701
const char * FormatOption(UInt_t opt)
Parse options.
Definition: GraphSysErr.C:7363
Bool_t IsStatRelative() const
Check if statistical errors are relative.
Definition: GraphSysErr.C:3488
TList * fMap
Map of keys.
Definition: GraphSysErr.C:7900
Combining measurements.
Definition: GraphSysErr.C:4901
Double_t Vprime() const
Calculate.
Definition: GraphSysErr.C:4985
GraphSysErr()
Default CTOR - use only for I/O.
Definition: GraphSysErr.C:241
void SetSumFillColor(Color_t color)
Set the fill color of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4469
EDrawOption_t
Drawing options.
Definition: GraphSysErr.C:190
UInt_t fCounter
Counter.
Definition: GraphSysErr.C:7876
void RemovePoint(Int_t i)
Remove a point from the graph.
Definition: GraphSysErr.C:2267
Double_t fChi2
The final .
Definition: GraphSysErr.C:5016
void SetCommonSumFillStyle(Style_t style)
Set the fill style of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4517
static GraphSysErr * Ratio(const GraphSysErr *num, const GraphSysErr *den, UInt_t flags=kRatioDefault, Double_t fac=1)
Take the ratio of 2 graphs.
Definition: GraphSysErr.C:1598
UInt_t fSumOption
Definition: GraphSysErr.C:7884
TMultiGraph * MakeMulti(Option_t *option)
Make our stack.
Definition: GraphSysErr.C:7472
void DoAdd(UShort_t xMode, Double_t curExl, Double_t curExh, Double_t curEyl, Double_t curEyh, Bool_t ignoreErr, Bool_t quad, Bool_t sqOld, Double_t &exl, Double_t &exh, Double_t &eyl, Double_t &eyh) const
Do add errors.
Definition: GraphSysErr.C:5818
Double_t GetYDown(Int_t point) const
Get errors downward along Y at point.
Definition: GraphSysErr.C:6068
void Set(Int_t point, Graph *g, Double_t ex, Double_t ey)
Set errors at point.
Definition: GraphSysErr.C:5964
Double_t GetSysErrorYDown(Int_t id, Int_t point) const
Definition: GraphSysErr.C:3736
Double_t GetX(Int_t p) const
Definition: GraphSysErr.C:3605
HolderP2P * FindP2P(UInt_t id) const
Find a point-2-point error graph.
Definition: GraphSysErr.C:7717
void FindFwhm(Int_t start, Int_t dir, Double_t ymax, Bool_t cmn, Bool_t stat, Bool_t quad, Int_t &i1, Int_t &i2) const
Find the full-width at half-maximum.
Definition: GraphSysErr.C:4044
TList fPoint2Point
List of graphs.
Definition: GraphSysErr.C:7867
const char * GetCommonSumTitle() const
Get title of summed systematic error.
Definition: GraphSysErr.C:3882
Holder & operator=(const Holder &other)
Assignment operator.
Definition: GraphSysErr.C:5717
void SetCommonSumLineWidth(Width_t width)
Set the line width of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4505
Bool_t FindYandError(Double_t x, Bool_t cmn, Bool_t stat, Bool_t quad, Bool_t nosqrt, Double_t &y, Double_t &eyl, Double_t &eyh, Double_t &seyl, Double_t &seyh) const
Find Y value and errors corresponding X.
Definition: GraphSysErr.C:4815
Double_t GetY(Int_t point) const
Get symmetric errors along Y at point.
Definition: GraphSysErr.C:6039
Bool_t IsRelative(Int_t id) const
Check if an error is relative.
Definition: GraphSysErr.C:3660
static GraphSysErr * Import(std::istream &in, UShort_t idx=0, UShort_t *nIdx=0)
Import data from input formatted Durham database file.
Definition: GraphSysErr.C:3033
Wrapper_t Wrapper() const
Return function pointer to wrapper.
Definition: GraphSysErr.C:5641
void Clear(Option_t *option="")
Clear the internal data.
Definition: GraphSysErr.C:5085
A combiner that uses a linear variance approximation.
Definition: GraphSysErr.C:5528
Color_t GetSysFillColor(Int_t id) const
Get fill color of systematic uncertainty.
Definition: GraphSysErr.C:3790
void SetSumLineColor(Color_t color)
Set the line color of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4451
void CopyKeys(const GraphSysErr *g, Option_t *option="fr")
Copy key/value and qualifiers from one graph to this graph.
Definition: GraphSysErr.C:4651
Double_t GetStatError(Int_t point) const
Definition: GraphSysErr.C:3629
virtual void Print(Option_t *option="") const
Print to standard output.
Definition: GraphSysErr.C:5055
void SetXTitle(const char *title)
Set title on X axis.
Definition: GraphSysErr.C:3582
Double_t Sprime() const
Calculate.
Definition: GraphSysErr.C:4955
Double_t StepW(Double_t guess, const Observation &r) const
Calculate the weight based on a guess of best .
Definition: GraphSysErr.C:5440
void SetCommonSumFillColor(Color_t color)
Set the fill color of the sumtematice error identified by ID.
Definition: GraphSysErr.C:4511
A holder for Point-to-Point systematic errors.
Definition: GraphSysErr.C:5886
virtual Bool_t IsFolder() const
Say that this should be shown as a folder.
Definition: GraphSysErr.C:670
virtual void ls(Option_t *option) const
Definition: GraphSysErr.C:5785
static Double_t L(Double_t guess, Double_t x, Double_t el, Double_t eh)
Return the likely-hood function value at :
Definition: GraphSysErr.C:5495
GraphSysErr * Reflect(Double_t x0=0) const
Make a copy of the graph, and reflect around x0.
Definition: GraphSysErr.C:2301
static Double_t WrapL(Double_t *xp, Double_t *pp)
Wrap likely-hood function for ROOT.
Definition: GraphSysErr.C:5513
TString fCommonSumTitle
Title on summed errors.
Definition: GraphSysErr.C:7890
virtual void ls(Option_t *option="") const
List the content.
Definition: GraphSysErr.C:483