00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <string.h>
00013
00014 #include "Riostream.h"
00015 #include "TEfficiency.h"
00016 #include "TROOT.h"
00017 #include "TGraphAsymmErrors.h"
00018 #include "TStyle.h"
00019 #include "TMath.h"
00020 #include "TArrow.h"
00021 #include "TBox.h"
00022 #include "TVirtualPad.h"
00023 #include "TF1.h"
00024 #include "TH1.h"
00025 #include "TVector.h"
00026 #include "TVectorD.h"
00027 #include "TClass.h"
00028 #include "Math/QuantFuncMathCore.h"
00029
00030 ClassImp(TGraphAsymmErrors)
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 TGraphAsymmErrors::TGraphAsymmErrors(): TGraph()
00070 {
00071
00072
00073 fEXlow = 0;
00074 fEYlow = 0;
00075 fEXhigh = 0;
00076 fEYhigh = 0;
00077 }
00078
00079
00080
00081 TGraphAsymmErrors::TGraphAsymmErrors(const TGraphAsymmErrors &gr)
00082 : TGraph(gr)
00083 {
00084
00085
00086 if (!CtorAllocate()) return;
00087 Int_t n = fNpoints*sizeof(Double_t);
00088 memcpy(fEXlow, gr.fEXlow, n);
00089 memcpy(fEYlow, gr.fEYlow, n);
00090 memcpy(fEXhigh, gr.fEXhigh, n);
00091 memcpy(fEYhigh, gr.fEYhigh, n);
00092 }
00093
00094
00095
00096 TGraphAsymmErrors& TGraphAsymmErrors::operator=(const TGraphAsymmErrors &gr)
00097 {
00098
00099
00100 if(this!=&gr) {
00101 TGraph::operator=(gr);
00102 if (!CtorAllocate()) return *this;
00103 Int_t n = fNpoints*sizeof(Double_t);
00104 memcpy(fEXlow, gr.fEXlow, n);
00105 memcpy(fEYlow, gr.fEYlow, n);
00106 memcpy(fEXhigh, gr.fEXhigh, n);
00107 memcpy(fEYhigh, gr.fEYhigh, n);
00108 }
00109 return *this;
00110 }
00111
00112
00113
00114 TGraphAsymmErrors::TGraphAsymmErrors(Int_t n)
00115 : TGraph(n)
00116 {
00117
00118
00119
00120
00121 if (!CtorAllocate()) return;
00122 FillZero(0, fNpoints);
00123 }
00124
00125
00126
00127 TGraphAsymmErrors::TGraphAsymmErrors(Int_t n, const Float_t *x, const Float_t *y, const Float_t *exl, const Float_t *exh, const Float_t *eyl, const Float_t *eyh)
00128 : TGraph(n,x,y)
00129 {
00130
00131
00132
00133
00134 if (!CtorAllocate()) return;
00135
00136 for (Int_t i=0;i<n;i++) {
00137 if (exl) fEXlow[i] = exl[i];
00138 else fEXlow[i] = 0;
00139 if (exh) fEXhigh[i] = exh[i];
00140 else fEXhigh[i] = 0;
00141 if (eyl) fEYlow[i] = eyl[i];
00142 else fEYlow[i] = 0;
00143 if (eyh) fEYhigh[i] = eyh[i];
00144 else fEYhigh[i] = 0;
00145 }
00146 }
00147
00148
00149
00150 TGraphAsymmErrors::TGraphAsymmErrors(Int_t n, const Double_t *x, const Double_t *y, const Double_t *exl, const Double_t *exh, const Double_t *eyl, const Double_t *eyh)
00151 : TGraph(n,x,y)
00152 {
00153
00154
00155
00156
00157 if (!CtorAllocate()) return;
00158
00159 n = fNpoints*sizeof(Double_t);
00160 if(exl) { memcpy(fEXlow, exl, n);
00161 } else { memset(fEXlow, 0, n); }
00162 if(exh) { memcpy(fEXhigh, exh, n);
00163 } else { memset(fEXhigh, 0, n); }
00164 if(eyl) { memcpy(fEYlow, eyl, n);
00165 } else { memset(fEYlow, 0, n); }
00166 if(eyh) { memcpy(fEYhigh, eyh, n);
00167 } else { memset(fEYhigh, 0, n); }
00168 }
00169
00170
00171
00172 TGraphAsymmErrors::TGraphAsymmErrors(const TVectorF &vx, const TVectorF &vy, const TVectorF &vexl, const TVectorF &vexh, const TVectorF &veyl, const TVectorF &veyh)
00173 :TGraph()
00174 {
00175
00176
00177
00178
00179
00180
00181 fNpoints = TMath::Min(vx.GetNrows(), vy.GetNrows());
00182 if (!TGraph::CtorAllocate()) return;
00183 if (!CtorAllocate()) return;
00184 Int_t ivxlow = vx.GetLwb();
00185 Int_t ivylow = vy.GetLwb();
00186 Int_t ivexllow = vexl.GetLwb();
00187 Int_t ivexhlow = vexh.GetLwb();
00188 Int_t iveyllow = veyl.GetLwb();
00189 Int_t iveyhlow = veyh.GetLwb();
00190 for (Int_t i=0;i<fNpoints;i++) {
00191 fX[i] = vx(i+ivxlow);
00192 fY[i] = vy(i+ivylow);
00193 fEXlow[i] = vexl(i+ivexllow);
00194 fEYlow[i] = veyl(i+iveyllow);
00195 fEXhigh[i] = vexh(i+ivexhlow);
00196 fEYhigh[i] = veyh(i+iveyhlow);
00197 }
00198 }
00199
00200
00201
00202 TGraphAsymmErrors::TGraphAsymmErrors(const TVectorD &vx, const TVectorD &vy, const TVectorD &vexl, const TVectorD &vexh, const TVectorD &veyl, const TVectorD &veyh)
00203 :TGraph()
00204 {
00205
00206
00207
00208
00209
00210
00211 fNpoints = TMath::Min(vx.GetNrows(), vy.GetNrows());
00212 if (!TGraph::CtorAllocate()) return;
00213 if (!CtorAllocate()) return;
00214 Int_t ivxlow = vx.GetLwb();
00215 Int_t ivylow = vy.GetLwb();
00216 Int_t ivexllow = vexl.GetLwb();
00217 Int_t ivexhlow = vexh.GetLwb();
00218 Int_t iveyllow = veyl.GetLwb();
00219 Int_t iveyhlow = veyh.GetLwb();
00220 for (Int_t i=0;i<fNpoints;i++) {
00221 fX[i] = vx(i+ivxlow);
00222 fY[i] = vy(i+ivylow);
00223 fEXlow[i] = vexl(i+ivexllow);
00224 fEYlow[i] = veyl(i+iveyllow);
00225 fEXhigh[i] = vexh(i+ivexhlow);
00226 fEYhigh[i] = veyh(i+iveyhlow);
00227 }
00228 }
00229
00230
00231
00232 TGraphAsymmErrors::TGraphAsymmErrors(const TH1 *h)
00233 : TGraph(h)
00234 {
00235
00236
00237
00238 if (!CtorAllocate()) return;
00239
00240 for (Int_t i=0;i<fNpoints;i++) {
00241 fEXlow[i] = h->GetBinWidth(i+1)*gStyle->GetErrorX();
00242 fEXhigh[i] = fEXlow[i];
00243 fEYlow[i] = h->GetBinError(i+1);
00244 fEYhigh[i] = fEYlow[i];
00245 }
00246 }
00247
00248
00249
00250 TGraphAsymmErrors::TGraphAsymmErrors(const TH1* pass, const TH1* total, Option_t *option)
00251 : TGraph((pass)?pass->GetNbinsX():0)
00252 {
00253
00254
00255
00256 if (!pass || !total) {
00257 Error("TGraphAsymmErrors","Invalid histogram pointers");
00258 return;
00259 }
00260 if (!CtorAllocate()) return;
00261
00262 std::string sname = "divide_" + std::string(pass->GetName()) + "_by_" +
00263 std::string(total->GetName());
00264 SetName(sname.c_str());
00265 SetTitle(pass->GetTitle());
00266
00267
00268 pass->TAttLine::Copy(*this);
00269 pass->TAttFill::Copy(*this);
00270 pass->TAttMarker::Copy(*this);
00271
00272 Divide(pass, total, option);
00273 }
00274
00275
00276
00277 TGraphAsymmErrors::~TGraphAsymmErrors()
00278 {
00279
00280
00281 if(fEXlow) delete [] fEXlow;
00282 if(fEXhigh) delete [] fEXhigh;
00283 if(fEYlow) delete [] fEYlow;
00284 if(fEYhigh) delete [] fEYhigh;
00285 }
00286
00287
00288
00289 void TGraphAsymmErrors::Apply(TF1 *f)
00290 {
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 Double_t x,y,exl,exh,eyl,eyh,eyl_new,eyh_new,fxy;
00302
00303 for (Int_t i=0;i<GetN();i++) {
00304 GetPoint(i,x,y);
00305 exl=GetErrorXlow(i);
00306 exh=GetErrorXhigh(i);
00307 eyl=GetErrorYlow(i);
00308 eyh=GetErrorYhigh(i);
00309
00310 fxy = f->Eval(x,y);
00311 SetPoint(i,x,fxy);
00312
00313
00314
00315 if (f->Eval(x,y-eyl)<f->Eval(x,y+eyh)) {
00316 eyl_new = TMath::Abs(fxy - f->Eval(x,y-eyl));
00317 eyh_new = TMath::Abs(f->Eval(x,y+eyh) - fxy);
00318 }
00319 else {
00320 eyh_new = TMath::Abs(fxy - f->Eval(x,y-eyl));
00321 eyl_new = TMath::Abs(f->Eval(x,y+eyh) - fxy);
00322 }
00323
00324
00325 SetPointError(i,exl,exh,eyl_new,eyh_new);
00326 }
00327 }
00328
00329
00330 void TGraphAsymmErrors::BayesDivide(const TH1* pass, const TH1* total, Option_t *)
00331 {
00332
00333
00334
00335
00336
00337 Divide(pass,total,"cl=0.683 b(1,1) mode");
00338 }
00339
00340
00341 void TGraphAsymmErrors::Divide(const TH1* pass, const TH1* total, Option_t *opt)
00342 {
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 if(!pass || !total) {
00396 Error("Divide","one of the passed pointers is zero");
00397 return;
00398 }
00399
00400
00401 if((pass->GetDimension() > 1) || (total->GetDimension() > 1)) {
00402 Error("Divide","passed histograms are not one-dimensional");
00403 return;
00404 }
00405
00406
00407 if(!TEfficiency::CheckConsistency(*pass,*total,"w")) {
00408 Error("Divide","passed histograms are not consistent");
00409 return;
00410 }
00411
00412
00413
00414 Bool_t bEffective = false;
00415
00416 Double_t stats[10];
00417 pass->GetStats(stats);
00418 if (TMath::Abs(stats[0] -stats[1]) > 1e-6)
00419 bEffective = true;
00420 total->GetStats(stats);
00421 if (TMath::Abs(stats[0] -stats[1]) > 1e-6)
00422 bEffective = true;
00423
00424 if (bEffective && (pass->GetSumw2()->fN == 0 || total->GetSumw2()->fN == 0) ) {
00425 Warning("Divide","histogram have been computed with weights but the sum of weight squares are not stored in the histogram. Error calculation is performed ignoring the weights");
00426 bEffective = false;
00427 }
00428
00429
00430 TString option = opt;
00431 option.ToLower();
00432
00433 Bool_t bVerbose = false;
00434
00435
00436 Double_t (*pBound)(Int_t,Int_t,Double_t,Bool_t) = &TEfficiency::ClopperPearson;
00437
00438 Double_t conf = 0.683;
00439
00440 Bool_t bIsBayesian = false;
00441 Double_t alpha = 1;
00442 Double_t beta = 1;
00443
00444
00445 if(option.Contains("v")) {
00446 option.ReplaceAll("v","");
00447 bVerbose = true;
00448 }
00449
00450
00451 if(option.Contains("cl=")) {
00452 Double_t level = -1;
00453
00454 sscanf(strstr(option.Data(),"cl="),"cl=%lf",&level);
00455 if((level > 0) && (level < 1))
00456 conf = level;
00457 else
00458 Warning("Divide","given confidence level %.3lf is invalid",level);
00459 option.ReplaceAll("cl=","");
00460 }
00461
00462
00463 if(option.Contains("n")) {
00464 option.ReplaceAll("n","");
00465 pBound = &TEfficiency::Normal;
00466 }
00467
00468
00469 if(option.Contains("cp")) {
00470 option.ReplaceAll("cp","");
00471 pBound = &TEfficiency::ClopperPearson;
00472 }
00473
00474
00475 if(option.Contains("w")) {
00476 option.ReplaceAll("w","");
00477 pBound = &TEfficiency::Wilson;
00478 }
00479
00480
00481 if(option.Contains("ac")) {
00482 option.ReplaceAll("ac","");
00483 pBound = &TEfficiency::AgrestiCoull;
00484 }
00485
00486 if(option.Contains("fc")) {
00487 option.ReplaceAll("fc","");
00488 pBound = &TEfficiency::FeldmanCousins;
00489 }
00490
00491
00492 if(option.Contains("b(")) {
00493 Double_t a = 0;
00494 Double_t b = 0;
00495 sscanf(strstr(option.Data(),"b("),"b(%lf,%lf)",&a,&b);
00496 if(a > 0)
00497 alpha = a;
00498 else
00499 Warning("Divide","given shape parameter for alpha %.2lf is invalid",a);
00500 if(b > 0)
00501 beta = b;
00502 else
00503 Warning("Divide","given shape parameter for beta %.2lf is invalid",b);
00504 option.ReplaceAll("b(","");
00505 bIsBayesian = true;
00506 }
00507
00508
00509 Bool_t usePosteriorMode = false;
00510 if(bIsBayesian && option.Contains("mode") ) {
00511 usePosteriorMode = true;
00512 option.ReplaceAll("mode","");
00513 }
00514
00515 Bool_t plot0Bins = false;
00516 if(option.Contains("e0") ) {
00517 plot0Bins = true;
00518 option.ReplaceAll("e0","");
00519 }
00520
00521 Bool_t useShortestInterval = false;
00522 if (bIsBayesian && ( option.Contains("sh") || (usePosteriorMode && !option.Contains("cen") ) ) ) {
00523 useShortestInterval = true;
00524 }
00525
00526
00527 if (!bIsBayesian && pBound != &TEfficiency::Normal )
00528 Warning("Divide","Histogram have weights - only normal error calculation is supported and it will be used");
00529
00530
00531
00532
00533 Int_t nbins = pass->GetNbinsX();
00534 Set(nbins);
00535
00536
00537
00538
00539
00540
00541 double eff, low, upper;
00542
00543 int npoint=0;
00544
00545 Int_t t = 0 , p = 0;
00546 Double_t tw = 0, tw2 = 0, pw = 0, pw2 = 0;
00547
00548 for (Int_t b=1; b<=nbins; ++b) {
00549
00550
00551 eff = 0;
00552 low = 0;
00553 upper = 0;
00554
00555
00556 if(bEffective) {
00557 tw = total->GetBinContent(b);
00558 tw2 = total->GetSumw2()->At(b);
00559 pw = pass->GetBinContent(b);
00560 pw2 = pass->GetSumw2()->At(b);
00561
00562 if (tw <= 0 && !plot0Bins) continue;
00563
00564
00565
00566
00567 }
00568
00569
00570 else {
00571 t = int( total->GetBinContent(b) + 0.5);
00572 p = int(pass->GetBinContent(b) + 0.5);
00573
00574 if (!t && !plot0Bins) continue;
00575 }
00576
00577
00578
00579 if(bIsBayesian) {
00580 double aa,bb;
00581 if (bEffective) {
00582
00583 double norm = (tw2 > 0) ? tw/tw2 : 0.;
00584 aa = pw * norm + alpha;
00585 bb = (tw - pw) * norm + beta;
00586 }
00587 else {
00588 aa = double(p) + alpha;
00589 bb = double(t-p) + beta;
00590 }
00591 if (usePosteriorMode)
00592 eff = TEfficiency::BetaMode(aa,bb);
00593 else
00594 eff = TEfficiency::BetaMean(aa,bb);
00595
00596 if (useShortestInterval) {
00597 TEfficiency::BetaShortestInterval(conf,aa,bb,low,upper);
00598 }
00599 else {
00600 low = TEfficiency::BetaCentralInterval(conf,aa,bb,false);
00601 upper = TEfficiency::BetaCentralInterval(conf,aa,bb,true);
00602 }
00603 }
00604
00605 else {
00606 if (bEffective) {
00607
00608 if (tw > 0) {
00609
00610 eff = pw/tw;
00611
00612
00613
00614
00615 double variance = ( pw2 * (1. - 2 * eff) + tw2 * eff *eff ) / ( tw * tw) ;
00616 double sigma = sqrt(variance);
00617
00618 double prob = 0.5 * (1.-conf);
00619 double delta = ROOT::Math::normal_quantile_c(prob, sigma);
00620 low = eff - delta;
00621 upper = eff + delta;
00622 if (low < 0) low = 0;
00623 if (upper > 1) upper = 1.;
00624 }
00625 }
00626
00627 else {
00628
00629 if(t)
00630 eff = ((Double_t)p)/t;
00631
00632 low = pBound(t,p,conf,false);
00633 upper = pBound(t,p,conf,true);
00634 }
00635 }
00636
00637 SetPoint(npoint,pass->GetBinCenter(b),eff);
00638 SetPointError(npoint,
00639 pass->GetBinCenter(b)-pass->GetBinLowEdge(b),
00640 pass->GetBinLowEdge(b)-pass->GetBinCenter(b)+pass->GetBinWidth(b),
00641 eff-low,upper-eff);
00642 npoint++;
00643 }
00644
00645 Set(npoint);
00646
00647 if (bVerbose) {
00648 Info("Divide","made a graph with %d points from %d bins",npoint,nbins);
00649 Info("Divide","used confidence level: %.2lf\n",conf);
00650 if(bIsBayesian)
00651 Info("Divide","used prior probability ~ beta(%.2lf,%.2lf)",alpha,beta);
00652 Print();
00653 }
00654 }
00655
00656
00657 void TGraphAsymmErrors::ComputeRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const
00658 {
00659
00660
00661 TGraph::ComputeRange(xmin,ymin,xmax,ymax);
00662
00663 for (Int_t i=0;i<fNpoints;i++) {
00664 if (fX[i] -fEXlow[i] < xmin) {
00665 if (gPad && gPad->GetLogx()) {
00666 if (fEXlow[i] < fX[i]) xmin = fX[i]-fEXlow[i];
00667 else xmin = TMath::Min(xmin,fX[i]/3);
00668 } else {
00669 xmin = fX[i]-fEXlow[i];
00670 }
00671 }
00672 if (fX[i] +fEXhigh[i] > xmax) xmax = fX[i]+fEXhigh[i];
00673 if (fY[i] -fEYlow[i] < ymin) {
00674 if (gPad && gPad->GetLogy()) {
00675 if (fEYlow[i] < fY[i]) ymin = fY[i]-fEYlow[i];
00676 else ymin = TMath::Min(ymin,fY[i]/3);
00677 } else {
00678 ymin = fY[i]-fEYlow[i];
00679 }
00680 }
00681 if (fY[i] +fEYhigh[i] > ymax) ymax = fY[i]+fEYhigh[i];
00682 }
00683 }
00684
00685
00686
00687 void TGraphAsymmErrors::CopyAndRelease(Double_t **newarrays,
00688 Int_t ibegin, Int_t iend, Int_t obegin)
00689 {
00690
00691
00692 CopyPoints(newarrays, ibegin, iend, obegin);
00693 if (newarrays) {
00694 delete[] fEXlow;
00695 fEXlow = newarrays[0];
00696 delete[] fEXhigh;
00697 fEXhigh = newarrays[1];
00698 delete[] fEYlow;
00699 fEYlow = newarrays[2];
00700 delete[] fEYhigh;
00701 fEYhigh = newarrays[3];
00702 delete[] fX;
00703 fX = newarrays[4];
00704 delete[] fY;
00705 fY = newarrays[5];
00706 delete[] newarrays;
00707 }
00708 }
00709
00710
00711
00712 Bool_t TGraphAsymmErrors::CopyPoints(Double_t **arrays,
00713 Int_t ibegin, Int_t iend, Int_t obegin)
00714 {
00715
00716
00717
00718 if (TGraph::CopyPoints(arrays ? arrays+4 : 0, ibegin, iend, obegin)) {
00719 Int_t n = (iend - ibegin)*sizeof(Double_t);
00720 if (arrays) {
00721 memmove(&arrays[0][obegin], &fEXlow[ibegin], n);
00722 memmove(&arrays[1][obegin], &fEXhigh[ibegin], n);
00723 memmove(&arrays[2][obegin], &fEYlow[ibegin], n);
00724 memmove(&arrays[3][obegin], &fEYhigh[ibegin], n);
00725 } else {
00726 memmove(&fEXlow[obegin], &fEXlow[ibegin], n);
00727 memmove(&fEXhigh[obegin], &fEXhigh[ibegin], n);
00728 memmove(&fEYlow[obegin], &fEYlow[ibegin], n);
00729 memmove(&fEYhigh[obegin], &fEYhigh[ibegin], n);
00730 }
00731 return kTRUE;
00732 } else {
00733 return kFALSE;
00734 }
00735 }
00736
00737
00738
00739 Bool_t TGraphAsymmErrors::CtorAllocate(void)
00740 {
00741
00742
00743 if (!fNpoints) {
00744 fEXlow = fEYlow = fEXhigh = fEYhigh = 0;
00745 return kFALSE;
00746 }
00747 fEXlow = new Double_t[fMaxSize];
00748 fEYlow = new Double_t[fMaxSize];
00749 fEXhigh = new Double_t[fMaxSize];
00750 fEYhigh = new Double_t[fMaxSize];
00751 return kTRUE;
00752 }
00753
00754
00755 void TGraphAsymmErrors::FillZero(Int_t begin, Int_t end,
00756 Bool_t from_ctor)
00757 {
00758
00759
00760 if (!from_ctor) {
00761 TGraph::FillZero(begin, end, from_ctor);
00762 }
00763 Int_t n = (end - begin)*sizeof(Double_t);
00764 memset(fEXlow + begin, 0, n);
00765 memset(fEXhigh + begin, 0, n);
00766 memset(fEYlow + begin, 0, n);
00767 memset(fEYhigh + begin, 0, n);
00768 }
00769
00770
00771
00772 Double_t TGraphAsymmErrors::GetErrorX(Int_t i) const
00773 {
00774
00775
00776
00777 if (i < 0 || i >= fNpoints) return -1;
00778 if (!fEXlow && !fEXhigh) return -1;
00779 Double_t elow=0, ehigh=0;
00780 if (fEXlow) elow = fEXlow[i];
00781 if (fEXhigh) ehigh = fEXhigh[i];
00782 return TMath::Sqrt(0.5*(elow*elow + ehigh*ehigh));
00783 }
00784
00785
00786
00787 Double_t TGraphAsymmErrors::GetErrorY(Int_t i) const
00788 {
00789
00790
00791
00792 if (i < 0 || i >= fNpoints) return -1;
00793 if (!fEYlow && !fEYhigh) return -1;
00794 Double_t elow=0, ehigh=0;
00795 if (fEYlow) elow = fEYlow[i];
00796 if (fEYhigh) ehigh = fEYhigh[i];
00797 return TMath::Sqrt(0.5*(elow*elow + ehigh*ehigh));
00798 }
00799
00800
00801
00802 Double_t TGraphAsymmErrors::GetErrorXhigh(Int_t i) const
00803 {
00804
00805
00806 if (i<0 || i>fNpoints) return -1;
00807 if (fEXhigh) return fEXhigh[i];
00808 return -1;
00809 }
00810
00811
00812
00813 Double_t TGraphAsymmErrors::GetErrorXlow(Int_t i) const
00814 {
00815
00816
00817 if (i<0 || i>fNpoints) return -1;
00818 if (fEXlow) return fEXlow[i];
00819 return -1;
00820 }
00821
00822
00823
00824 Double_t TGraphAsymmErrors::GetErrorYhigh(Int_t i) const
00825 {
00826
00827
00828 if (i<0 || i>fNpoints) return -1;
00829 if (fEYhigh) return fEYhigh[i];
00830 return -1;
00831 }
00832
00833
00834
00835 Double_t TGraphAsymmErrors::GetErrorYlow(Int_t i) const
00836 {
00837
00838
00839 if (i<0 || i>fNpoints) return -1;
00840 if (fEYlow) return fEYlow[i];
00841 return -1;
00842 }
00843
00844
00845
00846 void TGraphAsymmErrors::Print(Option_t *) const
00847 {
00848
00849
00850 for (Int_t i=0;i<fNpoints;i++) {
00851 printf("x[%d]=%g, y[%d]=%g, exl[%d]=%g, exh[%d]=%g, eyl[%d]=%g, eyh[%d]=%g\n"
00852 ,i,fX[i],i,fY[i],i,fEXlow[i],i,fEXhigh[i],i,fEYlow[i],i,fEYhigh[i]);
00853 }
00854 }
00855
00856
00857
00858 void TGraphAsymmErrors::SavePrimitive(ostream &out, Option_t *option )
00859 {
00860
00861
00862 char quote = '"';
00863 out<<" "<<endl;
00864 if (gROOT->ClassSaved(TGraphAsymmErrors::Class())) {
00865 out<<" ";
00866 } else {
00867 out<<" TGraphAsymmErrors *";
00868 }
00869 out<<"grae = new TGraphAsymmErrors("<<fNpoints<<");"<<endl;
00870 out<<" grae->SetName("<<quote<<GetName()<<quote<<");"<<endl;
00871 out<<" grae->SetTitle("<<quote<<GetTitle()<<quote<<");"<<endl;
00872
00873 SaveFillAttributes(out,"grae",0,1001);
00874 SaveLineAttributes(out,"grae",1,1,1);
00875 SaveMarkerAttributes(out,"grae",1,1,1);
00876
00877 for (Int_t i=0;i<fNpoints;i++) {
00878 out<<" grae->SetPoint("<<i<<","<<fX[i]<<","<<fY[i]<<");"<<endl;
00879 out<<" grae->SetPointError("<<i<<","<<fEXlow[i]<<","<<fEXhigh[i]<<","<<fEYlow[i]<<","<<fEYhigh[i]<<");"<<endl;
00880 }
00881
00882 static Int_t frameNumber = 0;
00883 if (fHistogram) {
00884 frameNumber++;
00885 TString hname = fHistogram->GetName();
00886 hname += frameNumber;
00887 fHistogram->SetName(hname.Data());
00888 fHistogram->SavePrimitive(out,"nodraw");
00889 out<<" grae->SetHistogram("<<fHistogram->GetName()<<");"<<endl;
00890 out<<" "<<endl;
00891 }
00892
00893
00894 TIter next(fFunctions);
00895 TObject *obj;
00896 while ((obj=next())) {
00897 obj->SavePrimitive(out,"nodraw");
00898 if (obj->InheritsFrom("TPaveStats")) {
00899 out<<" grae->GetListOfFunctions()->Add(ptstats);"<<endl;
00900 out<<" ptstats->SetParent(grae->GetListOfFunctions());"<<endl;
00901 } else {
00902 out<<" grae->GetListOfFunctions()->Add("<<obj->GetName()<<");"<<endl;
00903 }
00904 }
00905
00906 const char *l = strstr(option,"multigraph");
00907 if (l) {
00908 out<<" multigraph->Add(grae,"<<quote<<l+10<<quote<<");"<<endl;
00909 } else {
00910 out<<" grae->Draw("<<quote<<option<<quote<<");"<<endl;
00911 }
00912 }
00913
00914
00915 void TGraphAsymmErrors::SetPointError(Double_t exl, Double_t exh, Double_t eyl, Double_t eyh)
00916 {
00917
00918
00919 Int_t px = gPad->GetEventX();
00920 Int_t py = gPad->GetEventY();
00921
00922
00923 Int_t ipoint = -2;
00924 Int_t i;
00925
00926 for (i=0;i<fNpoints;i++) {
00927 Int_t dpx = px - gPad->XtoAbsPixel(gPad->XtoPad(fX[i]));
00928 Int_t dpy = py - gPad->YtoAbsPixel(gPad->YtoPad(fY[i]));
00929 if (dpx*dpx+dpy*dpy < 25) {ipoint = i; break;}
00930 }
00931 if (ipoint == -2) return;
00932
00933 fEXlow[ipoint] = exl;
00934 fEYlow[ipoint] = eyl;
00935 fEXhigh[ipoint] = exh;
00936 fEYhigh[ipoint] = eyh;
00937 gPad->Modified();
00938 }
00939
00940
00941
00942 void TGraphAsymmErrors::SetPointError(Int_t i, Double_t exl, Double_t exh, Double_t eyl, Double_t eyh)
00943 {
00944
00945
00946 if (i < 0) return;
00947 if (i >= fNpoints) {
00948
00949 TGraphAsymmErrors::SetPoint(i,0,0);
00950 }
00951 fEXlow[i] = exl;
00952 fEYlow[i] = eyl;
00953 fEXhigh[i] = exh;
00954 fEYhigh[i] = eyh;
00955 }
00956
00957
00958
00959 void TGraphAsymmErrors::SetPointEXlow(Int_t i, Double_t exl)
00960 {
00961
00962
00963 if (i < 0) return;
00964 if (i >= fNpoints) {
00965
00966 TGraphAsymmErrors::SetPoint(i,0,0);
00967 }
00968 fEXlow[i] = exl;
00969 }
00970
00971
00972
00973 void TGraphAsymmErrors::SetPointEXhigh(Int_t i, Double_t exh)
00974 {
00975
00976
00977 if (i < 0) return;
00978 if (i >= fNpoints) {
00979
00980 TGraphAsymmErrors::SetPoint(i,0,0);
00981 }
00982 fEXhigh[i] = exh;
00983 }
00984
00985
00986
00987 void TGraphAsymmErrors::SetPointEYlow(Int_t i, Double_t eyl)
00988 {
00989
00990
00991 if (i < 0) return;
00992 if (i >= fNpoints) {
00993
00994 TGraphAsymmErrors::SetPoint(i,0,0);
00995 }
00996 fEYlow[i] = eyl;
00997 }
00998
00999
01000
01001 void TGraphAsymmErrors::SetPointEYhigh(Int_t i, Double_t eyh)
01002 {
01003
01004
01005 if (i < 0) return;
01006 if (i >= fNpoints) {
01007
01008 TGraphAsymmErrors::SetPoint(i,0,0);
01009 }
01010 fEYhigh[i] = eyh;
01011 }
01012
01013
01014
01015 void TGraphAsymmErrors::Streamer(TBuffer &b)
01016 {
01017
01018
01019 if (b.IsReading()) {
01020 UInt_t R__s, R__c;
01021 Version_t R__v = b.ReadVersion(&R__s, &R__c);
01022 if (R__v > 2) {
01023 b.ReadClassBuffer(TGraphAsymmErrors::Class(), this, R__v, R__s, R__c);
01024 return;
01025 }
01026
01027 TGraph::Streamer(b);
01028 fEXlow = new Double_t[fNpoints];
01029 fEYlow = new Double_t[fNpoints];
01030 fEXhigh = new Double_t[fNpoints];
01031 fEYhigh = new Double_t[fNpoints];
01032 if (R__v < 2) {
01033 Float_t *exlow = new Float_t[fNpoints];
01034 Float_t *eylow = new Float_t[fNpoints];
01035 Float_t *exhigh = new Float_t[fNpoints];
01036 Float_t *eyhigh = new Float_t[fNpoints];
01037 b.ReadFastArray(exlow,fNpoints);
01038 b.ReadFastArray(eylow,fNpoints);
01039 b.ReadFastArray(exhigh,fNpoints);
01040 b.ReadFastArray(eyhigh,fNpoints);
01041 for (Int_t i=0;i<fNpoints;i++) {
01042 fEXlow[i] = exlow[i];
01043 fEYlow[i] = eylow[i];
01044 fEXhigh[i] = exhigh[i];
01045 fEYhigh[i] = eyhigh[i];
01046 }
01047 delete [] eylow;
01048 delete [] exlow;
01049 delete [] eyhigh;
01050 delete [] exhigh;
01051 } else {
01052 b.ReadFastArray(fEXlow,fNpoints);
01053 b.ReadFastArray(fEYlow,fNpoints);
01054 b.ReadFastArray(fEXhigh,fNpoints);
01055 b.ReadFastArray(fEYhigh,fNpoints);
01056 }
01057 b.CheckByteCount(R__s, R__c, TGraphAsymmErrors::IsA());
01058
01059
01060 } else {
01061 b.WriteClassBuffer(TGraphAsymmErrors::Class(),this);
01062 }
01063 }
01064
01065
01066
01067 void TGraphAsymmErrors::SwapPoints(Int_t pos1, Int_t pos2)
01068 {
01069
01070
01071 SwapValues(fEXlow, pos1, pos2);
01072 SwapValues(fEXhigh, pos1, pos2);
01073 SwapValues(fEYlow, pos1, pos2);
01074 SwapValues(fEYhigh, pos1, pos2);
01075 TGraph::SwapPoints(pos1, pos2);
01076 }