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 }