TGraphAsymmErrors.cxx

Go to the documentation of this file.
00001 // @(#)root/hist:$Id: TGraphAsymmErrors.cxx 38124 2011-02-17 17:19:13Z moneta $
00002 // Author: Rene Brun   03/03/99
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
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 /* Begin_Html
00034 <center><h2>TGraphAsymmErrors class</h2></center>
00035 A TGraphAsymmErrors is a TGraph with assymetric error bars.
00036 <p>
00037 The TGraphAsymmErrors painting is permofed thanks to the
00038 <a href="http://root.cern.ch/root/html/TGraphPainter.html">TGraphPainter</a>
00039 class. All details about the various painting options are given in
00040 <a href="http://root.cern.ch/root/html/TGraphPainter.html">this class</a>.
00041 <p>
00042 The picture below gives an example:
00043 End_Html
00044 Begin_Macro(source)
00045 {
00046    c1 = new TCanvas("c1","A Simple Graph with assymetric error bars",200,10,700,500);
00047    c1->SetFillColor(42);
00048    c1->SetGrid();
00049    c1->GetFrame()->SetFillColor(21);
00050    c1->GetFrame()->SetBorderSize(12);
00051    Int_t n = 10;
00052    Double_t x[n]   = {-0.22, 0.05, 0.25, 0.35, 0.5, 0.61,0.7,0.85,0.89,0.95};
00053    Double_t y[n]   = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};
00054    Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
00055    Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};
00056    Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03};
00057    Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6};
00058    gr = new TGraphAsymmErrors(n,x,y,exl,exh,eyl,eyh);
00059    gr->SetTitle("TGraphAsymmErrors Example");
00060    gr->SetMarkerColor(4);
00061    gr->SetMarkerStyle(21);
00062    gr->Draw("ALP");
00063    return c1;
00064 }
00065 End_Macro */
00066 
00067 
00068 //______________________________________________________________________________
00069 TGraphAsymmErrors::TGraphAsymmErrors(): TGraph()
00070 {
00071    // TGraphAsymmErrors default constructor.
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    // TGraphAsymmErrors copy constructor
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    // TGraphAsymmErrors assignment operator
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    // TGraphAsymmErrors normal constructor.
00118    //
00119    // the arrays are preset to zero
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    // TGraphAsymmErrors normal constructor.
00131    //
00132    // if exl,h or eyl,h are null, the corresponding arrays are preset to zero
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    // TGraphAsymmErrors normal constructor.
00154    //
00155    // if exl,h or eyl,h are null, the corresponding arrays are preset to zero
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    // Constructor with six vectors of floats in input
00176    // A grapherrors is built with the X coordinates taken from vx and Y coord from vy
00177    // and the errors from vectors vexl/h and veyl/h.
00178    // The number of points in the graph is the minimum of number of points
00179    // in vx and vy.
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    // Constructor with six vectors of doubles in input
00206    // A grapherrors is built with the X coordinates taken from vx and Y coord from vy
00207    // and the errors from vectors vexl/h and veyl/h.
00208    // The number of points in the graph is the minimum of number of points
00209    // in vx and vy.
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    // TGraphAsymmErrors constructor importing its parameters from the TH1 object passed as argument
00236    // the low and high errors are set to the bin error of the histogram.
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    // Creates a TGraphAsymmErrors by dividing two input TH1 histograms:
00254    // pass/total. (see TGraphAsymmErrors::Divide)
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    //copy style from pass
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    // TGraphAsymmErrors default destructor.
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    // apply a function to all data points
00292    // y = f(x,y)
00293    //
00294    // Errors are calculated as eyh = f(x,y+eyh)-f(x,y) and
00295    // eyl = f(x,y)-f(x,y-eyl)
00296    //
00297    // Special treatment has to be applied for the functions where the
00298    // role of "up" and "down" is reversed.
00299    // function suggested/implemented by Miroslav Helbich <helbich@mail.desy.de>
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       // in the case of the functions like y-> -1*y the roles of the
00314       // upper and lower error bars is reversed
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       //error on x doesn't change
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    //This function is only kept for backward compatibility.
00333    //You should rather use the Divide method.
00334    //It calls Divide(pass,total,"cl=0.683 b(1,1) mode") which is equivalent to the
00335    //former BayesDivide method.
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    // Fill this TGraphAsymmErrors by dividing two 1-dimensional histograms pass/total
00344    //
00345    // The assumption is that the entries in "pass" are a subset of those in
00346    // "total". That is, we create an "efficiency" graph, where each entry is
00347    // between 0 and 1, inclusive.
00348    //
00349    // If the histograms are not filled with unit weights, the number of effective
00350    // entries is used which might lead to wrong results.
00351    // Begin_Latex effective entries = #frac{(#sum w_{i})^{2}}{#sum w_{i}^{2}}End_Latex
00352    //
00353    // The points are assigned a x value at the center of each histogram bin.
00354    // The y values are Begin_Latex eff = #frac{pass}{total} End_Latex for all options except for the 
00355    // bayesian one where the estimated efficiency is given by
00356    // Begin_Latex eff = #frac{pass + a}{total + a + b} End_Latex.
00357    //
00358    // If the denominator becomes 0 or pass >  total, the corresponding bin is
00359    // skipped.
00360    //
00361    // The x errors span each histogram bin (lowedge ... lowedge+width)
00362    // The y errors depend on the chosen statistic methode which can be determined
00363    // by the options given below. For a detailed description of the used statistic
00364    // calculations please have a look at the corresponding functions! 
00365    //
00366    // Options:
00367    // - v     : verbose mode: prints information about the number of used bins
00368    //           and calculated efficiencies with their errors
00369    // - cl=x  : determine the used confidence level (0<x<1) (default is 0.683)
00370    // - cp    : Clopper-Pearson interval (see TEfficiency::ClopperPearson)
00371    // - w     : Wilson interval (see TEfficiency::Wilson)
00372    // - n     : normal approximation propagation (see TEfficiency::Normal)
00373    // - ac    : Agresti-Coull interval (see TEfficiency::AgrestiCoull)
00374    // - fc    : Feldman-Cousins interval (see TEfficiency::FeldmanCousinsInterval)
00375    // - b(a,b): bayesian interval using a prior probability ~Beta(a,b); a,b > 0
00376    //           (see TEfficiency::Bayesian)
00377    // - mode  : use mode of posterior for Bayesian interval (default is mean)
00378    // - shortest: use shortest interval (done by default if mode is set) 
00379    // - central: use central interval (done by default if mode is NOT set)
00380    // - e0    : plot (in Bayesian case) efficiency and interval for bins where total=0 
00381    //           (default is to skip them)
00382    //
00383    // Note:
00384    // Unfortunately there is no straightforward approach for determining a confidence
00385    // interval for a given confidence level. The actual coverage probability of the
00386    // confidence interval oscillates significantly according to the total number of
00387    // events and the true efficiency. In order to decrease the impact of this
00388    // oscillation on the actual coverage probability a couple of approximations and
00389    // methodes has been developped. For a detailed discussion, please have a look at
00390    // this statistical paper:
00391    // Begin_Html <a href="http://www-stat.wharton.upenn.edu/~tcai/paper/Binomial-StatSci.pdf"
00392    // > http://www-stat.wharton.upenn.edu/~tcai/paper/Binomial-StatSci.pdf</a> End_Html
00393 
00394    //check pointers
00395    if(!pass || !total) {
00396       Error("Divide","one of the passed pointers is zero");
00397       return;
00398    }
00399    
00400    //check dimension of histograms; only 1-dimensional ones are accepted
00401    if((pass->GetDimension() > 1) || (total->GetDimension() > 1)) {
00402       Error("Divide","passed histograms are not one-dimensional");
00403       return;
00404    }
00405    
00406    //check consistency of histograms, allowing weights
00407    if(!TEfficiency::CheckConsistency(*pass,*total,"w")) {
00408       Error("Divide","passed histograms are not consistent");
00409       return;
00410    }
00411 
00412    //check whether histograms are filled with weights -> use number of effective
00413    //entries
00414    Bool_t bEffective = false;
00415    //compare sum of weights with sum of squares of weights
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    //parse option
00430    TString option = opt;
00431    option.ToLower();
00432 
00433    Bool_t bVerbose = false;
00434    //pointer to function returning the boundaries of the confidence interval
00435    //(is only used in the frequentist cases.)
00436    Double_t (*pBound)(Int_t,Int_t,Double_t,Bool_t) = &TEfficiency::ClopperPearson; // default method
00437    //confidence level
00438    Double_t conf = 0.683;
00439    //values for bayesian statistics
00440    Bool_t bIsBayesian = false;
00441    Double_t alpha = 1;
00442    Double_t beta = 1;
00443 
00444    //verbose mode
00445    if(option.Contains("v")) {
00446       option.ReplaceAll("v","");
00447       bVerbose = true;
00448    }
00449 
00450    //confidence level
00451    if(option.Contains("cl=")) {
00452       Double_t level = -1;
00453       // coverity [secure_coding : FALSE]
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    //normal approximation
00463    if(option.Contains("n")) {
00464       option.ReplaceAll("n","");
00465       pBound = &TEfficiency::Normal;
00466    }
00467 
00468    //clopper pearson interval
00469    if(option.Contains("cp")) {
00470       option.ReplaceAll("cp","");
00471       pBound = &TEfficiency::ClopperPearson;
00472    }
00473 
00474    //wilson interval
00475    if(option.Contains("w")) {
00476       option.ReplaceAll("w","");
00477       pBound = &TEfficiency::Wilson;
00478    }
00479 
00480    //agresti coull interval
00481    if(option.Contains("ac")) {
00482       option.ReplaceAll("ac","");
00483       pBound = &TEfficiency::AgrestiCoull;
00484    }
00485    // Feldman-Cousins interval
00486    if(option.Contains("fc")) {
00487       option.ReplaceAll("fc","");
00488       pBound = &TEfficiency::FeldmanCousins;
00489    }
00490 
00491    //bayesian with prior
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    // use posterior mode
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    // weights works only in case of Normal approximation or Bayesian 
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    //Set the graph to have a number of points equal to the number of histogram
00532    //bins
00533    Int_t nbins = pass->GetNbinsX();
00534    Set(nbins);
00535 
00536    // Ok, now set the points for each bin
00537    // (Note: the TH1 bin content is shifted to the right by one:
00538    //  bin=0 is underflow, bin=nbins+1 is overflow.)
00539 
00540    //efficiency with lower and upper boundary of confidence interval
00541    double eff, low, upper;
00542    //this keeps track of the number of points added to the graph
00543    int npoint=0;
00544    //number of total and passed events
00545    Int_t t = 0 , p = 0;
00546    Double_t tw = 0, tw2 = 0, pw = 0, pw2 = 0; // for the case of weights
00547    //loop over all bins and fill the graph
00548    for (Int_t b=1; b<=nbins; ++b) {
00549 
00550       // default value when total =0;
00551       eff = 0;
00552       low = 0; 
00553       upper = 0; 
00554 
00555       // special case in case of weights we have to consider the sum of weights and the sum of weight squares
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; // skip bins with total <= 0
00563 
00564           // in the case of weights have the formula only for 
00565           // the normal and  bayesian statistics (see below)
00566 
00567        }
00568        
00569        //use bin contents
00570        else {
00571           t = int( total->GetBinContent(b) + 0.5);
00572           p = int(pass->GetBinContent(b) + 0.5);
00573           
00574           if (!t && !plot0Bins) continue; // skip bins with total = 0
00575        }
00576 
00577 
00578       //using bayesian statistics
00579       if(bIsBayesian) {
00580          double aa,bb;
00581          if (bEffective) { 
00582             // tw/tw2 renormalize the weights
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       // case of non-bayesian statistics
00605       else {
00606          if (bEffective) { 
00607                      
00608             if (tw > 0) { 
00609 
00610                eff = pw/tw;
00611 
00612                // use normal error calculation using variance of MLE with weights (F.James 8.5.2) 
00613                // this is the same formula used in ROOT for TH1::Divide("B")
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             // when not using weights
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       //Set the point center and its errors
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++;//we have added a point to the graph
00643    }
00644 
00645    Set(npoint);//tell the graph how many points we've really added
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    // Compute Range
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    // Copy and release.
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    // Copy errors from fE*** to arrays[***]
00716    // or to f*** Copy points.
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    // Should be called from ctors after fNpoints has been set
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    // Set zero values for point arrays in the range [begin, end)
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    // This function is called by GraphFitChisquare.
00775    // It returns the error along X at point i.
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    // This function is called by GraphFitChisquare.
00790    // It returns the error along Y at point i.
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    // Get high error on X.
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    // Get low error on X.
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    // Get high error on Y.
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    // Get low error on Y.
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    // Print graph and errors values.
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     // Save primitive as a C++ statement(s) on output stream out
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    // save list of functions
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    // Set ex and ey values for point pointed by the mouse.
00918 
00919    Int_t px = gPad->GetEventX();
00920    Int_t py = gPad->GetEventY();
00921 
00922    //localize point to be deleted
00923    Int_t ipoint = -2;
00924    Int_t i;
00925    // start with a small window (in case the mouse is very close to one point)
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    // Set ex and ey values for point number i.
00945 
00946    if (i < 0) return;
00947    if (i >= fNpoints) {
00948    // re-allocate the object
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    // Set EXlow for point i
00962 
00963    if (i < 0) return;
00964    if (i >= fNpoints) {
00965    // re-allocate the object
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    // Set EXhigh for point i
00976 
00977    if (i < 0) return;
00978    if (i >= fNpoints) {
00979    // re-allocate the object
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    // Set EYlow for point i
00990 
00991    if (i < 0) return;
00992    if (i >= fNpoints) {
00993    // re-allocate the object
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    // Set EYhigh for point i
01004 
01005    if (i < 0) return;
01006    if (i >= fNpoints) {
01007    // re-allocate the object
01008       TGraphAsymmErrors::SetPoint(i,0,0);
01009    }
01010    fEYhigh[i]  = eyh;
01011 }
01012 
01013 
01014 //______________________________________________________________________________
01015 void TGraphAsymmErrors::Streamer(TBuffer &b)
01016 {
01017    // Stream an object of class TGraphAsymmErrors.
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       //====process old versions before automatic schema evolution
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       //====end of old versions
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    // Swap points.
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 }

Generated on Tue Jul 5 14:24:18 2011 for ROOT_528-00b_version by  doxygen 1.5.1