Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Plot.cxx

Go to the documentation of this file.
00001 // $Id: Plot.cxx,v 1.6 2007/09/13 21:23:56 rustem Exp $
00002 
00003 // C++
00004 #include <algorithm>
00005 #include <cassert>
00006 #include <cmath>
00007 #include <fstream>
00008 #include <iostream>
00009 #include <iomanip>
00010 #include <sstream>
00011 
00012 // ROOT
00013 #include "TArrow.h"
00014 #include "TBox.h"
00015 #include "TCanvas.h"
00016 #include "TFile.h"
00017 #include "TGraphAsymmErrors.h"
00018 #include "TH1.h"
00019 #include "TF1.h"
00020 #include "TLine.h"
00021 #include "TPaveStats.h"
00022 #include "TStyle.h"
00023 
00024 // Local
00025 #include "PhysicsNtuple/DataBlock.h"
00026 #include "PhysicsNtuple/Hist1d.h"
00027 #include "Plot.h"
00028 
00029 using namespace std;
00030 
00031 //-----------------------------------------------------------------------------------------
00032 double Plot::GetChi2(const Hist &lhs, const Hist &rhs, const string &option, ostream &o)
00033 {
00034    TH1 *hL = lhs.GetHist();
00035    TH1 *hR = rhs.GetHist();
00036 
00037    if(!hL || !hR)
00038    {
00039       cerr << "GetChi2() - null histogram pointers" << endl;
00040       return 0.0;
00041    }
00042    if(hL -> GetNbinsX() != hR -> GetNbinsX())
00043    {
00044       cerr << "GetChi2() - histograms have unequal number of bins" << endl;
00045       return 0.0;
00046    }
00047 
00048    unsigned int ndof = 0;
00049    double chi2 = 0.0;
00050 
00051    int lbin = 1, hbin = hL -> GetNbinsX();
00052 
00053    if(option.find("U") != string::npos || option.find("u") != string::npos)
00054    {
00055       --lbin;
00056    }
00057    if(option.find("O") != string::npos || option.find("o") != string::npos)
00058    {
00059       ++hbin;
00060    }
00061    if(!(lbin < hbin))
00062    {
00063       cerr << "GetChi2() - invalid range of histogram bins" << endl;
00064       return 0.0;
00065    }
00066 
00067    const map<int, pair<Band, Band> >& bandL = lhs.GetErrorBand();
00068    const map<int, pair<Band, Band> >& bandR = rhs.GetErrorBand();
00069 
00070    for(int ibin = lbin; ibin <= hbin; ++ibin)
00071    {
00072       const double valueL = hL -> GetBinContent(ibin);
00073       const double valueR = hR -> GetBinContent(ibin);
00074     
00075       if(!(valueL > 0.0) && !(valueR > 0.0))
00076       {
00077          continue;
00078       }
00079     
00080       const double nom = (valueL - valueR)*(valueL - valueR);
00081       double den = 0.0;
00082 
00083       const map<int, pair<Band, Band> >::const_iterator lit = bandL.find(ibin);
00084       if(lit != bandL.end())
00085       {
00086          const Band &band = (lit -> second).second;
00087          assert(band.Bin() == ibin && "Mismatched bin number");
00088 
00089          if(band.Low() > band.High())
00090          {
00091             den += band.Low();
00092          }
00093          else
00094          {
00095             den += band.High();
00096          }
00097       }
00098       else
00099       {
00100          den += valueL;
00101       }
00102       
00103       const map<int, pair<Band, Band> >::const_iterator rit = bandR.find(ibin);
00104       if(rit != bandR.end())
00105       {
00106          const Band &band = (rit -> second).second;
00107          assert(band.Bin() == ibin && "Mismatched bin number");
00108 
00109          if(band.Low() > band.High())
00110          {
00111             den += band.Low();
00112          }
00113          else
00114          {
00115             den += band.High();
00116          }
00117       }
00118       else
00119       {
00120          den += valueR;
00121       }
00122 
00123       if(!(den > 0.0))
00124       {
00125          cerr << "Plot::GetChi2 - bin error is zero" << endl;
00126          continue;
00127       }
00128 
00129       chi2 += nom/den;
00130       ++ndof;
00131    }
00132 
00133    if(!(ndof > 0))
00134    {
00135       return 0.0;
00136    }
00137 
00138    if(option.find("P") != string::npos || option.find("V") != string::npos)
00139    {
00140       o << "chi2/ndof = " << chi2 << "/" << ndof << " = " << chi2/ndof << endl;
00141    }
00142 
00143    if(option.find("chi2") != string::npos)
00144    {
00145       return chi2;
00146    }
00147    else if(option.find("ndof") != string::npos)
00148    {
00149       return ndof;
00150    }
00151 
00152    return chi2/ndof;
00153 }
00154 
00155 //-----------------------------------------------------------------------------------------
00156 Plot::Style::Style()
00157    :lwidth(2),
00158     lstyle(1),
00159     lcolor(1),
00160     mstyle(-1),
00161     msize(0),
00162     mcolor(0),
00163     stat(1),
00164     rebin(0),
00165     xmin(+1.0),
00166     xmax(-1.0),
00167     statx(0.75),
00168     staty(0.5),
00169     statw(0.25),
00170     stath(0.23),
00171     option(),
00172     xtitle(),
00173     ytitle()
00174 {
00175 }
00176 
00177 //-----------------------------------------------------------------------------------------
00178 Plot::Style::~Style()
00179 {
00180 }
00181 
00182 //-----------------------------------------------------------------------------------------
00183 void Plot::Style::Print(ostream &o) const
00184 {
00185    o << "lwidth = " << lwidth << endl;
00186    o << "lstyle = " << lstyle << endl;
00187    o << "lcolor = " << lcolor << endl;
00188    o << "mstyle = " << mstyle << endl;
00189    o << "msize = " << msize  << endl;
00190    o << "mcolor = " << mcolor << endl;
00191    o << "stat = " << stat   << endl;
00192    o << "rebin = " << rebin  << endl;
00193    o << "xmin = " << xmin << endl;
00194    o << "xmax = " << xmax << endl;
00195    o << "statx = " << statx << endl;
00196    o << "staty = " << staty << endl;
00197    o << "statw = " <<  statw << endl;
00198    o << "stath = " << stath << endl;
00199    o << "option = " << option << endl;
00200    o << "xtitle = " << xtitle << endl;
00201    o << "ytitle = " << ytitle << endl;
00202 }
00203 
00204 //-----------------------------------------------------------------------------------------
00205 bool Plot::Style::Read(string path)
00206 {
00207    std::ifstream infile(path.c_str());
00208    if(!infile || !infile.is_open())
00209    {
00210       cerr << "Style::Read - failed to open file " << path << endl;
00211       return false;
00212    }
00213 
00214    
00215    while(!infile.eof())
00216    {
00217       std::string line;
00218       std::getline(infile, line);
00219 
00220       const string::size_type epos = line.find("=");
00221       
00222       if(line.empty() || line.find("#") != string::npos || epos == string::npos)
00223       {
00224          continue;
00225       }
00226 
00227       Set(line.substr(0, epos), line.substr(epos + 1));
00228    }
00229 
00230    return true;
00231 }
00232 
00233 //-----------------------------------------------------------------------------------------
00234 bool Plot::Style::Set(string name, string value)
00235 {
00236    //cout << "(name, value) = (" << name << ", " << value << ")" << endl;
00237 
00238    if(name.find("lwidth") != string::npos) lwidth = atoi(value.c_str());
00239    if(name.find("lstyle") != string::npos) lstyle = atoi(value.c_str());
00240    if(name.find("lcolor") != string::npos) lcolor = atoi(value.c_str());
00241    if(name.find("mstyle") != string::npos) mstyle = atoi(value.c_str());
00242    if(name.find("msize" ) != string::npos) msize  = atoi(value.c_str());
00243    if(name.find("mcolor") != string::npos) mcolor = atoi(value.c_str());
00244    if(name.find("stat"  ) != string::npos) stat   = atoi(value.c_str());
00245    if(name.find("rebin" ) != string::npos) rebin  = atoi(value.c_str());
00246    if(name.find("xmin"  ) != string::npos) xmin   = atof(value.c_str());
00247    if(name.find("xmax"  ) != string::npos) xmax   = atof(value.c_str());
00248    if(name.find("statx" ) != string::npos) statx  = atof(value.c_str());
00249    if(name.find("staty" ) != string::npos) staty  = atof(value.c_str());
00250    if(name.find("statw" ) != string::npos) statw  = atof(value.c_str());
00251    if(name.find("stath" ) != string::npos) stath  = atof(value.c_str());
00252    if(name.find("option") != string::npos) option = value;
00253    if(name.find("xtitle") != string::npos) xtitle = value;
00254    if(name.find("ytitle") != string::npos) ytitle = value;
00255 
00256    return true;
00257 }
00258 
00259 //-----------------------------------------------------------------------------------------
00260 double Plot::GetChi2(TH1 *h1, TH1 *h2, const string &option, const string &tag)
00261 {
00262    if(!h1 || !h2)
00263    {
00264       cerr << "GetChi2() - invalid histogram pointers" << endl;
00265       return 0.0;
00266    }
00267    if(h1 -> GetNbinsX() != h2 -> GetNbinsX())
00268    {
00269       cerr << "GetChi2() - histograms have unequal number of bins" << endl;
00270       return 0.0;
00271    }
00272 
00273    double ndof = 0.0;
00274    double chi2 = 0.0;
00275 
00276    int lbin = 1, hbin = h1 -> GetNbinsX();
00277 
00278    if(option.find("U") != string::npos || option.find("u") != string::npos)
00279    {
00280       --lbin;
00281    }
00282    if(option.find("O") != string::npos || option.find("o") != string::npos)
00283    {
00284       ++hbin;
00285    }
00286    if(!(lbin < hbin))
00287    {
00288       cerr << "GetChi2() - invalid range of histogram bins" << endl;
00289       return 0.0;
00290    }
00291 
00292    for(int ibin = lbin; ibin <= hbin; ++ibin)
00293    {
00294       const double value1 = h1 -> GetBinContent(ibin);
00295       const double value2 = h2 -> GetBinContent(ibin);
00296     
00297       if(value1 > 0.0 && value2 > 0.0)
00298       {
00299          chi2 += (value1 - value2) * (value1 - value2)/value1;
00300          ndof += 1.0;
00301       }
00302    }
00303 
00304    if(!(ndof > 0.0))
00305    {
00306       return 0.0;
00307    }
00308 
00309    if(option.find("P") != string::npos || option.find("V") != string::npos || !tag.empty())
00310    {
00311       if(tag.empty())
00312       {
00313          cout << "chi2/ndof = " << chi2 << "/" << ndof << " = " << chi2/ndof << endl;
00314       }
00315       else
00316       {
00317          cout << tag << ": chi2/ndof = " << chi2 << "/" << ndof << " = " << chi2/ndof << endl;
00318       }
00319    }
00320 
00321    return chi2/ndof;
00322 }
00323 
00324 //-----------------------------------------------------------------------------------------
00325 const string Plot::Format(const double v, const int w, const int p)
00326 {
00327    stringstream ss;
00328    ss << std::fixed << std::setw(w) << std::setprecision(p) << v;
00329    return ss.str();
00330 }
00331 
00332 //-----------------------------------------------------------------------------------------
00333 Plot::Hist::Hist(string fpath)
00334    :fFilePath(),
00335     fHistPath(),
00336     fHistPathL(),
00337     fHistPathH(),
00338     fHist(0),
00339     fHistL(0),
00340     fHistH(0),
00341     fProtons(0.0),
00342     fErrorColor(-1),
00343     fErrorStyle(1001),
00344     fAGraph(0),
00345     fError(),
00346     fArray()
00347 {
00348    Set(fpath);
00349 }
00350 
00351 //-----------------------------------------------------------------------------------------
00352 Plot::Hist::~Hist()
00353 {
00354    if(fHist)  delete fHist;
00355    if(fHistL) delete fHistL;
00356    if(fHistH) delete fHistH;   
00357 
00358    ClearError();
00359 }
00360 
00361 //-----------------------------------------------------------------------------------------
00362 bool Plot::Hist::Set(const string fpath)
00363 {
00364    if(fpath.size() < 6)
00365    {
00366       return false;
00367    }
00368 
00369    TFile *file = new TFile(fpath.c_str(), "READ");
00370    if(!file -> IsOpen())
00371    {
00372       cerr << "Failed to open ROOT file " << fpath << endl;
00373       return false;
00374    }
00375 
00376    fFilePath = fpath;
00377    
00378    return true;
00379 }
00380 
00381 //-----------------------------------------------------------------------------------------
00382 void Plot::Hist::SetProtons(const double protons)
00383 {
00384    if(protons > 0.0)
00385    {
00386       fProtons = protons;
00387    }
00388 }
00389 
00390 //---------------------------------------------------------------------------------------
00391 TH1* Plot::Hist::Get(const string hpath)
00392 {   
00393    pair<TH1 *, double> result = Read(hpath);
00394 
00395    if(!result.first)
00396    {
00397       return 0;
00398    }
00399    
00400    fHistPath = hpath;
00401 
00402    fHist = result.first;
00403 
00404    if(result.second > 0.0)
00405    {
00406       fProtons = result.second;
00407    }
00408 
00409    return fHist;
00410 }
00411 
00412 //---------------------------------------------------------------------------------------
00413 TGraphAsymmErrors* Plot::Hist::SetLH(const string lpath, const string hpath)
00414 {   
00415    pair<TH1 *, double> lresult = Read(lpath);
00416    pair<TH1 *, double> hresult = Read(hpath);
00417 
00418    if(!lresult.first || !hresult.first)
00419    {
00420       return 0;
00421    }
00422 
00423    if(fHistL) delete fHistL;
00424    if(fHistH) delete fHistH;
00425 
00426    fHistPathL = lpath;
00427    fHistPathH = hpath;
00428 
00429    fHistL = lresult.first;
00430    fHistH = hresult.first;
00431 
00432    return ComputeError();
00433 }
00434 
00435 //---------------------------------------------------------------------------------------
00436 TGraphAsymmErrors* Plot::Hist::ComputeError()
00437 {   
00438    TH1 *hC = fHist;
00439    TH1 *hL = fHistL;
00440    TH1 *hH = fHistH;
00441 
00442    if(!hC || !hL || !hH)
00443    {
00444       return 0;
00445    }
00446 
00447    ClearError();
00448 
00449    const int nbin = hC -> GetNbinsX();
00450 
00451    if(hL -> GetNbinsX() != nbin || hH -> GetNbinsX() != nbin)
00452    {
00453       cerr << "Error::Compute - mismatched number of bins" << endl;
00454       return 0;
00455    }
00456 
00457    int npoint = 0;
00458    for(int ibin = 1; ibin <= nbin; ++ibin)
00459    {
00460       if(hC -> GetBinContent(ibin) > 0)
00461       {
00462          ++npoint;
00463       }
00464    }
00465 
00466    double* x   = Create(npoint);
00467    double* y   = Create(npoint);
00468    double* exl = Create(npoint);
00469    double* exh = Create(npoint);
00470    double* eyl = Create(npoint); 
00471    double* eyh = Create(npoint);
00472 
00473    npoint = 0;
00474    for(int ibin = 1; ibin <= nbin; ++ibin)
00475    {      
00476       if(!(hC -> GetBinContent(ibin) > 0))
00477       {
00478          continue;
00479       }
00480 
00481       const double xc = hC -> GetXaxis() -> GetBinCenter(ibin);
00482       const double xl = hC -> GetXaxis() -> GetBinLowEdge(ibin);
00483       const double xh = hC -> GetXaxis() -> GetBinUpEdge(ibin);
00484 
00485       const double yc = hC -> GetBinContent(ibin);
00486       const double yl = hL -> GetBinContent(ibin);
00487       const double yh = hH -> GetBinContent(ibin);
00488 
00489       if(yl > yh)
00490       {
00491          cerr << "Error::Compute -  low value " << yl << " larger than high value " << yh<< endl;
00492          continue;
00493       }
00494 
00495       if(yc < yl || yh < yc)
00496       {
00497          cerr << "Error::Compute -  low and/or high error have wrong limit" << yh << endl;
00498          continue;
00499       }
00500 
00501       const double error_stat = std::sqrt(yc);
00502       const double error_low  = error_stat + yc - yl;
00503       const double error_high = error_stat + yh - yc;
00504 
00505       //cout << "yc - yl = " << yc << " - " << yl << " = " << yc - yl << endl;
00506       //cout << "yh - yc = " << yh << " - " << yc << " = " << yh - yc << endl;
00507 
00508       x[npoint] = xc;
00509       y[npoint] = yc;
00510 
00511       exl[npoint] = xc - xl;
00512       exh[npoint] = xh - xc;
00513 
00514       eyl[npoint] = error_low;
00515       eyh[npoint] = error_high;
00516 
00517       ++npoint;
00518 
00519       const Band xb(ibin, xc, xl, xh);
00520       const Band yb(ibin, yc, yl - error_stat, yh + error_stat);
00521       
00522       const pair<Band, Band> np(xb, yb);
00523 
00524       if(!fError.insert(map<int, pair<Band, Band> >::value_type(ibin, np)).second)
00525       {
00526          cerr << "Error::Compute - bin " << ibin << " already exists" << endl;
00527       }
00528 
00529       TBox *box = new TBox(xb.Low(), yb.Low(), xb.High(), yb.High());
00530 
00531       if(!fBox.insert(map<int, TBox *>::value_type(ibin, box)).second)
00532       {
00533          cerr << "Error::Compute - bin " << ibin << " already exists" << endl;
00534       }
00535       
00536       
00537       if(error_low > error_high)
00538       {
00539          hC -> SetBinError(ibin, error_low);
00540       }
00541       else
00542       {
00543          hC -> SetBinError(ibin, error_high);
00544       }
00545    }
00546 
00547    fAGraph = new TGraphAsymmErrors(npoint, x, y, exl, exh, eyl, eyh);
00548 
00549    return fAGraph;
00550 }
00551 
00552 //---------------------------------------------------------------------------------------
00553 TH1* Plot::Hist::operator->() const
00554 {
00555    return fHist;
00556 }
00557 
00558 //---------------------------------------------------------------------------------------
00559 double Plot::Hist::GetEntries(string option) const
00560 {
00561    TH1 *h = fHist;
00562 
00563    if(option.find("l") != string::npos)
00564    {
00565       h = fHistL;
00566    }
00567    else if(option.find("h") != string::npos)
00568    {
00569       h = fHistH;
00570    }
00571 
00572    if(!h)
00573    {
00574       return 0.0;
00575    }
00576 
00577    long double area = 0.0;
00578 
00579    int lbin = 1, hbin = h -> GetNbinsX();
00580 
00581    if(option.find("u") != string::npos)
00582    {
00583       --lbin;
00584    }
00585    if(option.find("o") != string::npos)
00586    {
00587       ++hbin;
00588    }
00589 
00590    for(int ibin = lbin; ibin <= hbin; ++ibin)
00591    {
00592       const long double value = h -> GetBinContent(ibin);
00593 
00594       if(value > 0.0)
00595       {
00596          area += value;
00597       }
00598    }
00599 
00600    return static_cast<double>(area);
00601 }
00602 
00603 //---------------------------------------------------------------------------------------
00604 double Plot::Hist::GetProtons() const
00605 {
00606    return fProtons;
00607 }
00608 
00609 //---------------------------------------------------------------------------------------
00610 const map<int, pair<Plot::Band, Plot::Band> >& Plot::Hist::GetErrorBand() const
00611 {
00612    return fError;
00613 }
00614 
00615 //---------------------------------------------------------------------------------------
00616 void Plot::Hist::Rebin(const int rebin)
00617 {
00618    if(!fHist || rebin < 1)
00619    {
00620       return;
00621    }
00622 
00623    fHist -> Rebin(rebin);
00624    
00625    if(fHistL && fHistH)
00626    {
00627       fHistL -> Rebin(rebin);
00628       fHistH -> Rebin(rebin);
00629       
00630       ComputeError();
00631    }   
00632 }
00633 
00634 //---------------------------------------------------------------------------------------
00635 TH1* Plot::Hist::Scale(const Hist &other, string option)
00636 {
00637    if(!fHist)
00638    {
00639       return 0;
00640    }
00641 
00642    const double area = GetEntries("uo");
00643 
00644    double scale = 1.0;
00645 
00646    if(option.find("area") != string::npos)
00647    {
00648       if(area > 0.0)
00649       {
00650          scale = 1.0/area;
00651       }
00652    }
00653    else if(option.find("ent") != string::npos)
00654    {
00655       const double area_other = other.GetEntries("");
00656       if(area > 0.0 && area_other > 0.0)
00657       {
00658          scale = area_other/area;
00659       }
00660    }
00661    else if(option.find("pot") != string::npos)
00662    {
00663       if(fProtons > 0.0 && other.GetProtons() > 0.0)
00664       {
00665          scale = other.GetProtons()/fProtons;
00666       }
00667    }
00668 
00669    const double entries  = GetEntries("uo");
00670    const double entriesl = GetEntries("l uo");
00671    const double entriesh = GetEntries("h uo");
00672 
00673    fHist -> Scale(scale);
00674    
00675    if(fHistL) fHistL -> Scale(scale);
00676    if(fHistH) fHistH -> Scale(scale);
00677 
00678    if(option.find("area") == string::npos)
00679    {
00680       fHist -> SetEntries(entries * scale);
00681       
00682       if(fHistL) fHistL -> SetEntries(entriesl * scale);
00683       if(fHistH) fHistH -> SetEntries(entriesh * scale);
00684    }
00685 
00686    ComputeError();
00687 
00688    return fHist;
00689 }
00690 
00691 //---------------------------------------------------------------------------------------
00692 TCanvas* Plot::Hist::Draw(string option, string cname)
00693 {
00694    if(!fHist)
00695    {
00696       return 0;
00697    }
00698    
00699    TH1 *h = fHist;
00700 
00701    TCanvas *canvas = 0;
00702 
00703    if(!cname.empty())
00704    {
00705       canvas = new TCanvas(cname.c_str(), cname.c_str(), 0, 0, 650, 400);
00706       canvas -> cd();
00707 
00708       if(option.find("grid") != string::npos)
00709       {
00710          canvas -> SetGrid();
00711       }
00712       if(cname.find("log") != string::npos)
00713       {
00714          canvas -> SetLogy();
00715       }
00716       canvas -> Draw();
00717    }
00718 
00719    h -> Draw(option.c_str());
00720 
00721    if(option.find("E") != string::npos)
00722    {
00723       TH1 *hc = dynamic_cast<TH1 *> (fHist -> Clone("hc"));
00724       hc -> SetDirectory(0);
00725       hc -> Draw("same HIST");
00726    }
00727 
00728    if(fErrorColor > 0 && fErrorStyle > 0)
00729    {
00730       const int bmin = fHist -> GetXaxis() -> GetFirst();
00731       const int bmax = fHist -> GetXaxis() -> GetLast();
00732 
00733       for(map<int, TBox *>::const_iterator it = fBox.begin(); it != fBox.end(); ++it)
00734       {
00735          const int ibin = it -> first;
00736          
00737          if(ibin < bmin || ibin > bmax)
00738          {
00739             continue;
00740          }
00741 
00742          TBox *box = it -> second;
00743          if(!box)
00744          {
00745             continue;
00746          }
00747          
00748          box -> SetFillColor(fErrorColor);
00749          box -> SetFillStyle(fErrorStyle);       
00750          box -> Draw();
00751       }
00752    }
00753 
00754    gPad -> Modified();
00755    gPad -> Update();
00756 
00757    return canvas;
00758 }
00759 
00760 //---------------------------------------------------------------------------------------
00761 void Plot::Hist::SetErrorStyle(const int color, const int style)
00762 {
00763    fErrorColor = color;
00764    fErrorStyle = style;
00765 }
00766 
00767 //-----------------------------------------------------------------------------------------
00768 void Plot::Hist::Move(float x, float y, float w, float h, string option)
00769 {
00770    if(!fHist || !gPad)
00771    {
00772       return;
00773    }
00774 
00775    gPad -> Modified();
00776    gPad -> Update();
00777 
00778    TPaveStats* stat = dynamic_cast<TPaveStats *> (fHist -> FindObject("stats"));
00779    if(!stat)
00780    {
00781       if(option.find("V") != string::npos)
00782       {
00783          cerr << "Hist::Move - no statistics box is present" << endl;
00784       }
00785       return;
00786    }
00787 
00788    int color = fHist -> GetLineColor();
00789    if(option.find("M") != string::npos)
00790    {
00791       color = fHist -> GetMarkerColor();
00792    }
00793 
00794    stat -> SetStatFormat("6.3f");
00795    stat -> SetTextColor(color);
00796    stat -> SetLineColor(color);
00797    //stat -> SetOptStat(1111110);
00798 
00799    if(option.find("V") != string::npos)
00800    {
00801       cout << "Hist::Move - left lower corner = (" << x << ", " << y << ") and " 
00802            << "right upper corner = (" << x + w << ", " << y + h << ")" << endl;      
00803    }
00804 
00805    stat -> SetX1NDC(x);
00806    stat -> SetY1NDC(y);
00807    stat -> SetX2NDC(x + w);
00808    stat -> SetY2NDC(y + h);
00809 
00810    gPad -> Modified();
00811    gPad -> Update();
00812 }
00813 
00814 
00815 //-----------------------------------------------------------------------------------------
00816 TH1* Plot::Hist::GetHist(string option) const
00817 {
00818    TH1 *h = fHist;
00819 
00820    if(option.find("l") != string::npos)
00821    {
00822       h = fHistL;
00823    }
00824    else if(option.find("h") != string::npos)
00825    {
00826       h = fHistH;
00827    }
00828 
00829    return h;   
00830 }
00831 
00832 //-----------------------------------------------------------------------------------------
00833 TH1* Plot::Hist::GetRatio(const Hist &other, string option,
00834                           const double min_, const double max_, const double factor) const
00835 {
00836    if(!fHist || !other.GetHist())
00837    {
00838       cerr << "Error::GetRatio - invalid histogram pointer(s)" << endl;
00839       return 0;
00840    }
00841 
00842    TH1 *hC = fHist;
00843    TH1 *hL = fHistL;
00844    TH1 *hH = fHistH;
00845    TH1 *hO = other.GetHist();
00846    
00847    const int nbin = hC -> GetNbinsX();
00848    const double nmin = 1000;      
00849       
00850    if(hC -> GetNbinsX() != nbin)
00851    {
00852       cerr << "Error::GetRatio - mismatched number of bins" << endl;
00853       return 0;
00854    }
00855    
00856    TH1 *hR = CreateRatio(hC, hO, option, nmin);
00857    if(!hR)
00858    {
00859       cerr << "Error::GetRatio - failed to create ratio histogram" << endl;
00860       return 0;      
00861    }
00862    else if(option.find("merge") != string::npos)
00863    {
00864       if(hL && hH)
00865       {
00866          Anp::Hist1d<double> histL(*hR);
00867          Anp::Hist1d<double> histH(*hR);         
00868 
00869          histL.Reset();
00870          histH.Reset();
00871          
00872          histL.Fill(*hL);
00873          histH.Fill(*hH);
00874 
00875          hL = Anp::CreateTH1<double>(histL, "hL");
00876          hH = Anp::CreateTH1<double>(histH, "hH");
00877       }
00878 
00879       Anp::Hist1d<double> histC(*hR);
00880       Anp::Hist1d<double> histO(*hR);
00881       
00882       histC.Reset();
00883       histO.Reset();
00884 
00885       histC.Fill(*hC);
00886       histO.Fill(*hO);
00887 
00888       hC = Anp::CreateTH1<double>(histC, "hC");
00889       hO = Anp::CreateTH1<double>(histO, "hO");
00890    }
00891 
00892    double miny = -1.0, maxy = -1.0;
00893 
00894    const int rbin = hR -> GetNbinsX();
00895    
00896    for(int ibin = 1; ibin <= rbin; ++ibin)
00897    {      
00898       const double valueC = hC -> GetBinContent(ibin);
00899       const double valueO = hO -> GetBinContent(ibin);
00900 
00901       if(!(valueC > 0) || !(valueO > 0))
00902       {
00903          continue;
00904       }
00905 
00906       if(std::fabs(hC ->GetBinLowEdge(ibin)-hO->GetBinLowEdge(ibin)) > 0.00001*hC->GetBinWidth(ibin))
00907       {
00908          cerr << "Hist::GetRatio - invalid lower bin edge for hC and hO" << endl;
00909          continue;
00910       }
00911 
00912       double errorC = hC -> GetBinError(ibin);
00913 
00914       if(hH && hL)
00915       {
00916          if(std::fabs(hC ->GetBinLowEdge(ibin)-hH->GetBinLowEdge(ibin)) > 0.00001*hC->GetBinWidth(ibin) ||
00917             std::fabs(hC ->GetBinLowEdge(ibin)-hL->GetBinLowEdge(ibin)) > 0.00001*hC->GetBinWidth(ibin))
00918          {
00919             cerr << "Hist::GetRatio - invalid lower bin edge for hC and hL or hH" << endl;
00920             continue;
00921          }
00922 
00923          const double errorH = hH -> GetBinContent(ibin) - valueC;
00924          const double errorL = valueC - hL -> GetBinContent(ibin);
00925 
00926          //cout << "errorH = " << errorH << endl;
00927          //cout << "errorL = " << errorL << endl;
00928 
00929          assert(!(errorH < 0.0) && !(errorL < 0.0) && "Negative errors");
00930 
00931          errorC = std::sqrt(valueC);
00932          
00933          if(errorH > errorL)
00934          {
00935             errorC += errorH;
00936          }
00937          else
00938          {
00939             errorC += errorL;
00940          }
00941       }
00942 
00943       const double errorO = hO -> GetBinError(ibin);
00944 
00945       const double ratio = valueO/valueC;
00946       const double error = ratio*(errorO/valueO + errorC/valueC);
00947 
00948       hR -> SetBinContent(ibin, ratio);
00949       hR -> SetBinError(ibin, error);
00950    
00951       if(maxy < 0.0)
00952       {
00953          miny = ratio - error;
00954          maxy = ratio + error;
00955       }
00956       else
00957       {
00958          miny = std::min<double>(miny, ratio - error);
00959          maxy = std::max<double>(maxy, ratio + error);
00960       }
00961    }
00962 
00963    if(maxy > 0.0)
00964    {
00965       const double span = std::fabs(maxy) + std::fabs(miny);
00966       hR -> GetYaxis() -> SetRangeUser(miny - span*factor, maxy + span*factor);
00967    }
00968 
00969    if(min_ < max_)
00970    {
00971       hR -> GetYaxis() -> SetRangeUser(min_, max_);
00972    }
00973 
00974    if(option.find("l") != string::npos)
00975    {
00976       TLine *line = 0;
00977       
00978       if(min_ < max_)
00979       {
00980          line = new TLine(min_, 1.0, max_, 1.0);
00981       }
00982       else
00983       {
00984          line = new TLine(hR -> GetXaxis() -> GetXmin(), 1.0, hR -> GetXaxis() -> GetXmax(), 1.0);
00985       }
00986 
00987       line -> SetLineWidth(1);
00988       hR -> GetListOfFunctions() -> Add(line);
00989    }
00990 
00991    if(option.find("merge") != string::npos)
00992    {
00993       if(hO) delete hO;
00994       if(hC) delete hC;
00995       if(hL) delete hL;
00996       if(hH) delete hH;
00997    }
00998 
00999    return hR;
01000 }
01001 
01002 //---------------------------------------------------------------------------------------
01003 std::pair<TH1 *, double> Plot::Hist::Read(const string &hpath)
01004 {
01005    pair<TH1 *, double> result(0, 0.0);
01006 
01007    if(fFilePath.size() < 6)
01008    {
01009       return result;
01010    }
01011    
01012    TFile *file = new TFile(fFilePath.c_str(), "READ");
01013    if(!file -> IsOpen())
01014    {
01015       cerr << "Hist::Read - Failed to open ROOT file " << fFilePath << endl;
01016       return result;
01017    }
01018 
01019    TH1 *h = dynamic_cast<TH1 *>(file -> Get(hpath.c_str()));
01020    if(!h)
01021    {
01022       cerr << "Plot::Read - failed to find histogram " << hpath << endl;
01023       return result;
01024    }
01025 
01026    h = dynamic_cast<TH1 *>(h -> Clone());
01027    h -> SetDirectory(0);
01028 
01029    result.first = h;
01030 
01031    DataBlock *block = dynamic_cast<DataBlock *>(file -> Get("block"));   
01032    if(block)
01033    {
01034       result.second = block -> GetProtonsOut();
01035    }
01036    else
01037    {
01038       cout << "Plot::Get() - failed to find DataBlock in " << file -> GetName() << endl;
01039    }      
01040 
01041    
01042    file -> Close();   
01043    
01044    return result;
01045 }
01046 
01047 //-----------------------------------------------------------------------------------------
01048 TH1* Plot::Hist::CreateRatio(TH1 *hC, TH1 *hO, const string &option, double nmin) const
01049 {
01050    if(!hC || !hO)
01051    {
01052       return 0;
01053    }
01054 
01055    const int nbin = hC -> GetNbinsX();
01056 
01057    if(hC -> GetNbinsX() != nbin)
01058    {
01059       cerr << "Plot::CreateRatio - mismatched number of bins" << endl;
01060       return 0;
01061    }
01062 
01063    TH1 *hR = 0;
01064 
01065    if(option.find("merge") != string::npos)
01066    {
01067       Anp::Hist1d<double> hist(*hO);
01068 
01069       hist.Merge(nmin);
01070       hist.Reset();
01071       hist.Fill(*hC);
01072       hist.Merge(nmin);
01073 
01074       hR = Anp::CreateTH1<double>(hist, "hR");
01075    }
01076    else
01077    {
01078       hR = dynamic_cast<TH1 *>(hO -> Clone("hR"));
01079 
01080       if(!hR)
01081       {
01082          cerr << "Plot::CreateRatio - failed to clone histogram" << endl;
01083          return 0;
01084       }     
01085    }
01086 
01087    if(hR)
01088    {
01089       hR -> Reset();
01090       hR -> SetDirectory(0);
01091       hR -> SetStats(false);
01092       hR -> GetXaxis() -> SetTitle(hO -> GetXaxis() -> GetTitle());
01093       hR -> GetXaxis() -> CenterTitle();
01094    }
01095 
01096    return hR;
01097 }
01098 
01099 //-----------------------------------------------------------------------------------------
01100 double* Plot::Hist::Create(const int size)
01101 {
01102    if(size < 1)
01103    {
01104       cerr << "Error::Create - can not create zero size array" << endl;
01105       return 0;
01106    }
01107 
01108    double *a = new double[size];
01109 
01110    for(int i = 0; i < size; ++i)
01111    {
01112       a[i] = 0.0;
01113    }
01114 
01115    fArray.push_back(a);
01116    
01117    return a;
01118 }
01119 
01120 //-----------------------------------------------------------------------------------------
01121 void Plot::Hist::ClearError()
01122 {
01123    if(fAGraph)
01124    {
01125       delete fAGraph;
01126       fAGraph = 0;
01127    }
01128 
01129    for(vector<double *>::iterator it = fArray.begin(); it != fArray.end(); ++it)
01130    {
01131       double *a = *it;
01132       if(a)
01133       {
01134          delete [] a;
01135       }
01136    }  
01137 
01138    for(map<int, TBox *>::iterator it = fBox.begin(); it != fBox.end(); ++it)
01139    {
01140       TBox *box = it -> second;
01141       if(box) delete box;
01142    }
01143 
01144    fArray.clear();
01145    fError.clear();
01146    fBox.clear();
01147 }
01148 
01149 //-----------------------------------------------------------------------------------------
01150 Plot::Range::Range(const double factor, const double min, const double max)
01151    :fFactor(factor),
01152     fMin(min),
01153     fMax(max)
01154 {
01155    if(!(fFactor > 1.0))
01156    {
01157       fFactor = 1.0;
01158    }
01159 }
01160 
01161 //-----------------------------------------------------------------------------------------
01162 Plot::Range::~Range()
01163 {
01164 }
01165 
01166 //-----------------------------------------------------------------------------------------
01167 void Plot::Range::Set(const double factor, const double min, const double max)
01168 {
01169    fFactor = factor;
01170    if(min < max)
01171    {
01172       fMin = min;
01173       fMax = max;
01174    }
01175 }
01176 
01177 //-----------------------------------------------------------------------------------------
01178 void Plot::Range::Add(TH1 * h)
01179 {
01180    if(h)
01181    {
01182       fHist.push_back(h);
01183    }
01184 }
01185 
01186 //-----------------------------------------------------------------------------------------
01187 void Plot::Range::Resize(string option, const double min_, const double max_)
01188 {
01189    if(option.find("Y") != string::npos)
01190    {
01191       double min = 0.0, max = 0.0;
01192       for(HistVec::iterator hit = fHist.begin(); hit != fHist.end(); ++hit)
01193       {
01194          TH1 *h = *hit;
01195          const std::pair<double, double> pmm = GetMinMax(h, option);
01196          
01197          if(hit == fHist.begin())
01198          {
01199             min = pmm.first;
01200             max = pmm.second;
01201          }
01202          else
01203          {
01204             min = std::min(min, pmm.first);
01205             max = std::max(max, pmm.second);
01206          }
01207       }
01208 
01209       if(option.find("min") != string::npos)
01210       {
01211          min = min_;
01212       }
01213       if(option.find("max") != string::npos)
01214       {
01215          max = max_;
01216       }
01217 
01218       if(min < 0.0)
01219       {
01220          min *= fFactor;
01221       }
01222       else
01223       {
01224          min /= fFactor;
01225       }
01226       
01227       if(max < 0.0)
01228       {
01229          max /= fFactor;
01230       }
01231       else
01232       {
01233          max *= fFactor;
01234       }
01235     
01236       if(option.find("V") != string::npos)
01237       {
01238          cout << "Range::Resize - setting y axis range from " << min << " to " << max << endl;
01239       }
01240 
01241       for(HistVec::iterator hit = fHist.begin(); hit != fHist.end(); ++hit)
01242       {
01243          TH1 *h = *hit;
01244          
01245          h -> GetYaxis() -> SetRangeUser(min, max);
01246       }
01247    }
01248    else if(option.find("X") != string::npos && min_ < max_)
01249    {
01250       if(option.find("V") != string::npos)
01251       {
01252          cout << "Range::Resize - setting x axis range from " << min_ << " to " << max_ << endl;
01253       }
01254 
01255       for(HistVec::iterator hit = fHist.begin(); hit != fHist.end(); ++hit)
01256       {
01257          TH1 *h = *hit;
01258 
01259          h -> GetXaxis() -> SetRangeUser(min_, max_);
01260       }
01261    }
01262 }
01263 
01264 
01265 //-----------------------------------------------------------------------------------------
01266 const std::pair<double, double> Plot::Range::GetMinMax(TH1 *h, const string &option) const
01267 {
01268    if(!h || h -> GetNbinsX() < 1)
01269    {
01270       return pair<double, double> (0.0, 0.0);
01271    }
01272    
01273    bool init = false, use_error = false;
01274    double min = 0.0, max = 0.0;
01275 
01276    if(option.find("E") != string::npos)
01277    {
01278       use_error = true;
01279    }
01280 
01281    for(int ibin = 1; ibin <= h -> GetNbinsX(); ++ibin)
01282    {
01283       double value = h -> GetBinContent(ibin);
01284       double error = h -> GetBinError(ibin);
01285       
01286       if(!(value > 0.0))
01287       {
01288          continue;
01289       }
01290       
01291       if(use_error)
01292       {
01293          value += error;
01294       }
01295 
01296       if(!init)
01297       {
01298          min = value;
01299          max = value;
01300          init = true;
01301          continue;
01302       }
01303       
01304       
01305       min = std::min(min, value);
01306       max = std::max(max, value);            
01307    }
01308 
01309     return pair<double, double> (min, max);
01310 }
01311 
01312 
01313 //-----------------------------------------------------------------------------------------
01314 Plot::Band::Band()
01315    :bin(0),
01316     center(0.0),
01317     low(0.0),
01318     high(0.0)
01319 {
01320 }
01321 
01322 //-----------------------------------------------------------------------------------------
01323 Plot::Band::Band(int bin_, double center_, double low_, double high_)
01324    :bin(bin_),
01325     center(center_),
01326     low(low_),
01327     high(high_)
01328 {
01329 }
01330 
01331 //-----------------------------------------------------------------------------------------
01332 Plot::Band::~Band()
01333 {
01334 }
01335 
01336 //-----------------------------------------------------------------------------------------
01337 int Plot::Band::Bin() const
01338 {
01339    return bin;
01340 }
01341 
01342 //-----------------------------------------------------------------------------------------
01343 double Plot::Band::Center() const
01344 {
01345    return center;
01346 }
01347 
01348 //-----------------------------------------------------------------------------------------
01349 double Plot::Band::Low() const
01350 {
01351    return low;
01352 }
01353 
01354 //-----------------------------------------------------------------------------------------
01355 double Plot::Band::High() const
01356 {
01357    return high;
01358 }
01359 
01360 //-----------------------------------------------------------------------------------------
01361 bool Plot::operator==(const Band &lhs, const Band &rhs)
01362 {
01363    return (lhs.Bin() == rhs.Bin());
01364 }
01365 
01366 //-----------------------------------------------------------------------------------------
01367 void Plot::TestHist(TH1 *hO, TH1 *hC, string option)
01368 {
01369    const double nmin = 1000;
01370       
01371    vector<Anp::Bin<double> > bvec;
01372    
01373    map<int, double> bmap;
01374    
01375    Anp::Hist1d<double> histO(*hO);
01376    Anp::Hist1d<double> histC(*hC);
01377    
01378    cout << "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO" << endl;
01379    histO.Print();
01380    const unsigned int nmergeO = histO.Merge(1000.0);
01381    histO.Print();
01382    
01383    cout << "Merged " << nmergeO << " bins" << endl;
01384    
01385    cout << "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" << endl;
01386    histC.Print();
01387    const unsigned int nmergeC = histC.Merge(1000.0);
01388    histC.Print();
01389    
01390    cout << "Merged " << nmergeC << " bins" << endl;
01391    
01392    cout << "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN" << endl;
01393    histO.Reset();
01394    histO.Fill(*hC);
01395    histO.Print();
01396 
01397    cout << "Attempting draw test..." << endl;
01398 
01399    TH1 *h1 = Anp::CreateTH1<double>(histO, "h1");
01400    TH1 *h2 = Anp::CreateTH1<double>(histC, "h2");
01401    
01402    hC -> SetLineColor(1);
01403    hC -> SetLineWidth(2);
01404    hC -> SetFillColor(0);
01405    h1 -> SetLineColor(2);
01406    h2 -> SetLineColor(4);
01407 
01408    if(!h1)
01409    {
01410       cerr << "Failed to create h1" << endl;
01411       return;
01412    }
01413    if(!h2)
01414    {
01415       cerr << "Failed to create h2" << endl;
01416       return;
01417    }
01418 
01419    TCanvas *canvas = new TCanvas("ctest", "ctest", 0, 0, 650, 400);
01420    canvas -> SetGrid();
01421    canvas -> Draw();
01422    
01423    hC -> Draw("HIST");
01424    h1 -> Draw("sames");   
01425    h2 -> Draw("sames");
01426 
01427    cout << "Finished draw test" << endl;
01428 
01429    return;
01430 
01431    const int nbin = hC -> GetNbinsX();
01432 
01433    for(int ibin = 1; ibin <= nbin; ++ibin)
01434    {
01435       const double value = hO -> GetBinContent(ibin);
01436       const double edge  = hO -> GetBinLowEdge(ibin);
01437       
01438       Anp::Bin<double> bin(ibin, edge);
01439       bin.add(value);
01440       
01441       bvec.push_back(bin);
01442    }
01443    
01444    unsigned int osize = bvec.size();
01445    double osum = 0.0;
01446    
01447    if(option.find("V") != string::npos)
01448    {
01449       for(unsigned int ibin = 0; ibin < bvec.size(); ++ibin)
01450       {
01451          const Anp::Bin<double> &bin = bvec[ibin];
01452          cout << "ibin = " << ibin << ", edge = " << bin.edge() << ", sum = " << bin.sum() << endl; 
01453          osum += bin.sum();
01454       }
01455    }
01456 
01457    std::sort(bvec.begin(), bvec.end());
01458    
01459    vector<Anp::Bin<double> >::iterator bit = bvec.begin();
01460    while(bit != bvec.end())
01461    {
01462       if(bit -> sum() > nmin || bit == bvec.begin() || bit + 1 == bvec.end())
01463       {
01464          ++bit;
01465          continue;
01466       }
01467       
01468       vector<Anp::Bin<double> >::iterator lit = bit - 1;
01469       vector<Anp::Bin<double> >::iterator hit = bit + 1;
01470       
01471       if(lit -> sum() < hit -> sum())
01472       {
01473          Anp::Bin<double> bin(0, lit -> edge());
01474          
01475          bin.add(bit -> sum());
01476          bin.add(lit -> sum());
01477          
01478          bvec.erase(lit, hit + 1);
01479          
01480          bvec.push_back(bin);
01481       }
01482       else
01483       {
01484          Anp::Bin<double> bin(0, bit -> edge());
01485          
01486          bin.add(bit -> sum());
01487          bin.add(hit -> sum());
01488          
01489          bvec.erase(bit, hit + 1);
01490          
01491          bvec.push_back(bin);       
01492       }
01493       
01494       std::sort(bvec.begin(), bvec.end());
01495       
01496          bit = bvec.begin();
01497    }
01498    
01499    if(option.find("V") != string::npos)
01500    {
01501       double nsum = 0.0;
01502       for(unsigned int ibin = 0; ibin < bvec.size(); ++ibin)
01503       {
01504          const Anp::Bin<double> &bin = bvec[ibin];
01505          cout << "ibin = " << ibin << ", edge = " << bin.edge() << ", sum = " << bin.sum() << endl; 
01506          nsum += bin.sum();
01507       }
01508       
01509       cout << "old bvec size = " << osize << endl;
01510       cout << "new bvec size = " << bvec.size() << endl;
01511       cout << "osum - nsum = " << osum << " - " << nsum << " = " << osum - nsum << endl;
01512    }
01513 }
01514 
01515 //-----------------------------------------------------------------------------------------
01516 void Plot::TestError(TH1 *hI, string option)
01517 {
01518    cout << "Plot::TestError - option = " << option << endl;
01519 
01520    TH1 *hO = dynamic_cast<TH1 *>(hI -> Clone("hO"));
01521    TH1 *hN = dynamic_cast<TH1 *>(hI -> Clone("hN"));
01522 
01523    hO -> SetDirectory(0);
01524    hN -> SetDirectory(0);
01525 
01526    const int nbin = hN -> GetNbinsX();
01527 
01528    for(int ibin = 1; ibin <= nbin; ++ibin)
01529    {
01530       const double value = hN -> GetBinContent(ibin);
01531       
01532       if(option.find("half") != std::string::npos)
01533       {
01534          hN -> SetBinError(ibin, 0.5*std::sqrt(value));
01535       }
01536       else
01537       {
01538          hN -> SetBinError(ibin, std::sqrt(value));
01539       }
01540    }
01541 
01542    hO -> SetLineColor(2);
01543    hN -> SetLineColor(4);
01544 
01545    TCanvas *canvas = new TCanvas("ctest", "ctest", 0, 0, 720, 450);
01546    canvas -> SetGrid();
01547    canvas -> Draw();
01548    
01549    hO -> Draw("E1");
01550    hN -> Draw("E1 sames");  
01551 }

Generated on Thu Nov 1 11:52:27 2007 for loon by  doxygen 1.3.9.1