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

Hist1d.h

Go to the documentation of this file.
00001 #ifndef ANP_HIST1D_H
00002 #define ANP_HIST1D_H
00003 
00004 // $Id: Hist1d.h,v 1.15 2009/10/15 18:30:13 jyuko Exp $
00005 //
00006 // Bin<> and Hist<> templates that implement histogram template
00007 //
00008 // Bin numbering conventions is as in TH1: 
00009 //    bin = 0 is overflow bin
00010 //    bin = nbin + 1 is overflow bin
00011 //
00012 
00013 // C++
00014 #include <algorithm>
00015 #include <cassert>
00016 #include <cmath>
00017 #include <iomanip>
00018 #include <iostream>
00019 #include <string>
00020 #include <vector>
00021 
00022 // ROOT
00023 #include "TH1.h"
00024 
00025 // Local
00026 #include "PhysicsNtuple/Default.h"
00027 
00028 namespace Anp
00029 {
00030    template<typename T>
00031       class Bin
00032    {
00033    public:
00034       
00035       Bin();
00036       Bin(unsigned int bin, const T edge);
00037       Bin(const Bin &lhs, const Bin &rhs);
00038       ~Bin();
00039       
00040       void add();
00041       void add(const T &weight);
00042       
00043       void set_bin(unsigned int bin);
00044       void set_sum(const T &sum, const T &sum2);
00045       void set_ent(unsigned int entries);
00046       void reset();
00047 
00048       unsigned int bin() const;
00049       unsigned int entries() const;
00050 
00051       T edge() const;
00052       T sum()  const;
00053       T sum2() const;
00054 
00055       void print(std::ostream& o = std::cout, short width = 0, short precision = 0) const;
00056 
00057    private:
00058       
00059       unsigned int fBin;
00060       unsigned int fNEntry;
00061 
00062       T fEdge;
00063       T fSum;
00064       T fSum2;
00065    };
00066 
00067    // 
00068    // Bin global operators and functions
00069    // 
00070    template <typename T> bool operator<(const Bin<T> &lhs, const Bin<T> &rhs);
00071 
00072    template <typename T> bool operator<(const Bin<T> &lhs, const T &rhs);
00073    template <typename T> bool operator<(const T &lhs, const Bin<T> &rhs);
00074 
00075    template <typename T> bool operator<(const Bin<T> &lhs, unsigned int bin);
00076    template <typename T> bool operator<(unsigned int bin, const Bin<T> &rhs);
00077 
00078    template <typename T> bool operator==(const Bin<T> &lhs, unsigned int bin);
00079    template <typename T> bool operator==(unsigned int bin, const Bin<T> &rhs);   
00080 
00081    template <typename T> Bin<T> Merge(const Bin<T> &lhs, const Bin<T> &rhs);
00082 
00083 
00084    template <typename T>
00085       class Hist1d
00086    {      
00087    public:
00088       
00089 #ifndef __CINT__
00090       typedef typename std::vector<Anp::Bin<T> >::const_iterator BinIter;
00091       typedef typename std::vector<Anp::Bin<T> >::iterator BinIterator;
00092 
00093       typedef typename std::vector<T>::const_iterator Iter;
00094       typedef typename std::vector<T>::iterator Iterator;
00095 #endif
00096 
00097    public:
00098 
00099       Hist1d();
00100       Hist1d(unsigned int nbin, const T low, const T high);
00101       explicit Hist1d(const std::vector<T> &vec);
00102       explicit Hist1d(const TH1 &h);
00103       ~Hist1d();
00104       
00105       unsigned int Fill(const T value);
00106       unsigned int Fill(const T value, const T weight);
00107       unsigned int Fill(const T value, const T weight, const T width);
00108       unsigned int Fill(const TH1 &h);
00109 
00110       unsigned int Merge(const T minvalue);
00111       unsigned int Rebin(unsigned int ngroup);
00112 
00113       Bin<T>& operator[](unsigned int bin);
00114       Bin<T>& GetBin(const T value);
00115 
00116       const Bin<T>& operator[](unsigned int bin) const;
00117       const Bin<T>& GetBin(const T value) const;
00118 
00119       T GetIntegral(const std::string &option = "") const;
00120       unsigned int GetEntries(const std::string &option = "") const;
00121       unsigned int GetNbins() const;
00122 
00123       const std::vector<Anp::Bin<T> >& GetBins() const;
00124 
00125       void Reset();
00126 
00127       void Print(std::ostream& o = std::cout) const;
00128       
00129    private:
00130 
00131       const Bin<T>& get_bin_const(const T value) const;
00132       Bin<T>& get_bin(const T value);
00133 
00134       void init_bins();
00135       void init_bins(std::vector<T> vec);
00136       void init_trivial();
00137 
00138    private:
00139 
00140       std::vector<Anp::Bin<T> > fData;
00141 
00142       unsigned int fNBin;
00143 
00144       T fLowEdge;
00145       T fHighEdge;
00146 
00147       bool fSearchBin;
00148    };
00149 
00150    template<typename T>    
00151       TH1* CreateTH1(const Hist1d<T> &h, const std::string &name = "h");
00152 
00153    //--------------------------------------------------------------------------------------
00154    // inlined member functions for Bin<T>
00155    //--------------------------------------------------------------------------------------
00156 
00157    template<typename T> 
00158       Bin<T>::Bin()
00159          : fBin(), fNEntry(0), fEdge(), fSum(0), fSum2(0) {}
00160 
00161 
00162    template<typename T> 
00163       Bin<T>::Bin(const unsigned int bin, const T edge)
00164          : fBin(bin), fNEntry(0), fEdge(edge), fSum(0), fSum2(0) {}
00165 
00166    template <typename T> 
00167       Bin<T>::Bin(const Bin &lhs, const Bin &rhs) :
00168       fBin(lhs.bin()),
00169       fNEntry(lhs.entries() + rhs.entries()),
00170       fEdge(lhs.edge()),
00171       fSum(lhs.sum() + rhs.sum()),
00172       fSum2(lhs.sum2() + rhs.sum2())
00173    {
00174       if(rhs.bin() < lhs.bin())
00175       {
00176          fBin = rhs.bin();
00177       }
00178       if(rhs.edge() < lhs.edge())
00179       {
00180          fEdge = rhs.edge();
00181       }      
00182    }
00183 
00184    template<typename T> 
00185       Bin<T>::~Bin() {}
00186 
00187    template<typename T> 
00188       inline unsigned int Bin<T>::bin() const { return fBin; }
00189 
00190    template<typename T> 
00191       inline unsigned int Bin<T>::entries() const { return fNEntry; }
00192 
00193    template<typename T>    
00194       inline T Bin<T>::edge() const { return fEdge; }
00195 
00196    template<typename T> 
00197       inline T Bin<T>::sum()  const { return fSum; }
00198 
00199    template<typename T> 
00200       inline T Bin<T>::sum2() const { return fSum2; }
00201 
00202    template<typename T> 
00203       inline void Bin<T>::add()
00204    {
00205       ++fNEntry;
00206       ++fSum;
00207       ++fSum2;
00208    }
00209 
00210    template<typename T> 
00211       inline void Bin<T>::add(const T &weight)
00212    {
00213       ++fNEntry;
00214       fSum  += weight;
00215       fSum2 += weight*weight;
00216    }
00217 
00218    template<typename T> 
00219       inline void Bin<T>::set_bin(const unsigned int bin)
00220    {
00221       fBin = bin;
00222    }
00223 
00224    template<typename T> 
00225       inline void Bin<T>::set_sum(const T &sum, const T &sum2)
00226    {
00227       fSum  = sum;
00228       fSum2 = sum2;
00229    }
00230 
00231    template<typename T> 
00232       inline void Bin<T>::set_ent(const unsigned int entries)
00233    {
00234       fNEntry = entries;
00235    }
00236 
00237    template<typename T> 
00238       inline void Bin<T>::reset()
00239    {
00240       fNEntry = 0;
00241       fSum    = 0;
00242       fSum2   = 0;
00243    }
00244 
00245    template<typename T> 
00246       inline void Bin<T>::print(std::ostream& o, const short width, const short precision) const
00247    {
00248       if(width == 0 || precision == 0)
00249       {
00250          o << "Bin: (bin, edge, sum) = (" 
00251            << bin() << ", " << edge()  << ", "<< sum() << ")" << std::endl;
00252       }
00253       else
00254       {
00255          o << "Bin: (bin, edge, sum) = " 
00256            << std::setw(width) << std::setprecision(precision) << bin()
00257            << ", " 
00258            << std::setw(width) << std::setprecision(precision) << edge() 
00259            << ", " 
00260            << std::setw(width) << std::setprecision(precision) << sum() 
00261            << ")" <<std::endl;
00262       }
00263    }
00264 
00265    //--------------------------------------------------------------------------------------
00266    // non member Bin<T> functions
00267    //--------------------------------------------------------------------------------------
00268    template<typename T>
00269       inline bool operator<(const Bin<T> &lhs, const Bin<T> &rhs) { return lhs.bin() < rhs.bin(); }
00270    
00271    template<typename T>
00272       inline bool operator<(const Bin<T> &lhs, const T &rhs) { return lhs.edge() < rhs; }
00273    
00274    template<typename T> 
00275       inline bool operator<(const T &lhs, const Bin<T> &rhs) { return lhs < rhs.edge(); }  
00276 
00277    template<typename T>
00278       inline bool operator<(const Bin<T> &lhs, const unsigned int rhs) { return lhs.bin() < rhs; }
00279    
00280    template<typename T> 
00281       inline bool operator<(const unsigned int lhs, const Bin<T> &rhs) { return lhs < rhs.bin(); } 
00282 
00283    template<typename T>
00284       inline bool operator==(const Bin<T> &lhs, const unsigned int rhs) { return lhs.bin() == rhs; }
00285    
00286    template<typename T> 
00287       inline bool operator==(const unsigned int lhs, const Bin<T> &rhs) { return lhs == rhs.bin(); } 
00288    
00289    template <typename T>
00290       inline std::ostream& operator<<(std::ostream& o, const Bin<T> &self)
00291    {
00292       self.print(o);
00293       return o;
00294    }
00295 
00296    template <typename T>
00297       inline T GetKernelOverlap(const T lpos, const T rpos, const T cpos, const T width)
00298    {
00299       // Compute fraction of kernel intergral for kernel centered at x0 = cpos 
00300       // and between lpos and rpos boundaries. Kernel function is (1-((x-x0)/w)^2)^2
00301       // for x < 1.0 and 0 otherwise. Kerner integral I(x) = (x - 2*x^3/3 + x^5/5)/C,
00302       // where C = 16/15.
00303       
00304       if(!(lpos < rpos) || !(width > 0.0))
00305       {
00306          std::cerr << "GetKernelOverlap - invalid input parameters (" 
00307                    << lpos << ", " << rpos << ", " << cpos << ", " << width << ")" << std::endl;
00308          return 0;
00309       }
00310 
00311       T ledge = cpos - width;
00312       T redge = cpos + width;
00313 
00314       if(ledge < lpos) ledge = lpos;
00315       if(redge > rpos) redge = rpos;
00316       
00317       const T x1 = (ledge - cpos)/width;
00318       const T x2 = (redge - cpos)/width;
00319 
00320       const T I1 = x1 - 2.0*x1*x1*x1/3.0 + x1*x1*x1*x1*x1/5.0;
00321       const T I2 = x2 - 2.0*x2*x2*x2/3.0 + x2*x2*x2*x2*x2/5.0;
00322 
00323       const T overlap = 15.0*(I2 - I1)/16.0;
00324 
00325       //std::cout << "(lpos, rpos, cpos) = (" 
00326       //<< lpos << ", " << rpos << ", " << cpos << ")" << std::endl
00327       //<< "(ledg, redg, width, overlap) = (" 
00328       //<< ledge << ", " << redge << ", " << width << ", " << overlap << ")" << std::endl;
00329 
00330       return overlap;
00331    }
00332 
00333    template <typename T> 
00334       inline Bin<T> Merge(const Bin<T> &lhs, const Bin<T> &rhs)
00335    {
00336       Bin<T> bin(std::min<unsigned int>(lhs.bin(), rhs.bin()),
00337                  std::min<T>(lhs.edge(), rhs.edge()));
00338 
00339       bin.set_sum(lhs.sum() + rhs.sum(), lhs.sum2() + rhs.sum2());
00340       bin.set_ent(lhs.entries() + rhs.entries());
00341 
00342       return bin;
00343    }
00344 
00345    //--------------------------------------------------------------------------------------
00346    // Hist1d<T> member functions
00347    //--------------------------------------------------------------------------------------
00348    template <typename T>
00349       Hist1d<T>::Hist1d()
00350       : fData(), fNBin(0), fLowEdge(), fHighEdge(), fSearchBin(false)
00351    {    
00352       init_trivial();
00353    }
00354 
00355    //-----------------------------------------------------------------------------------------------
00356    template <typename T>
00357       Hist1d<T>::Hist1d(const unsigned int nbin, const T low, const T high)
00358       : fData(), fNBin(nbin), fLowEdge(low), fHighEdge(high), fSearchBin(false)
00359    {
00360       if(fNBin > 0)
00361       {
00362          init_bins();
00363       }
00364       else
00365       {
00366          init_trivial();
00367       }
00368    }
00369 
00370    //-----------------------------------------------------------------------------------------------
00371    template <typename T>
00372       Hist1d<T>::Hist1d(const std::vector<T> &vec)
00373       : fData(), fNBin(0), fLowEdge(), fHighEdge(), fSearchBin(true)
00374    {
00375       if(vec.size() > 1)
00376       {
00377          init_bins(vec);
00378       }
00379       else
00380       {
00381          init_trivial();
00382       }
00383    }
00384 
00385    //-----------------------------------------------------------------------------------------------
00386    template <typename T>
00387       Hist1d<T>::Hist1d(const TH1 &h)
00388      :fData(),
00389       fNBin(h.GetNbinsX()),
00390       fLowEdge(h.GetXaxis() -> GetXmin()),
00391       fHighEdge(h.GetXaxis() -> GetXmax()),
00392       fSearchBin(true)
00393    {
00394       const int nbin = h.GetNbinsX();
00395       
00396       if(nbin < 2)
00397       { 
00398          std::cerr << "Hist1d<T>::Hist1d encountered TH1 without bins" << std::endl;
00399          return;
00400       }
00401 
00402       for(int ibin = 1; ibin <= nbin + 1; ++ibin)
00403       {
00404          const double value = h.GetBinContent(ibin);
00405          const double edge  = h.GetBinLowEdge(ibin);
00406          
00407          if(ibin == 1)
00408          {
00409             fData.push_back(Bin<T>(0, edge));
00410          }
00411 
00412          Bin<T> bin(ibin, edge);
00413          bin.add(value);
00414 
00415          fData.push_back(bin);
00416       }      
00417 
00418       std::sort(fData.begin(), fData.end());
00419    }
00420 
00421    //-----------------------------------------------------------------------------------------------
00422    template <typename T>
00423       Hist1d<T>::~Hist1d() {}
00424 
00425    //-----------------------------------------------------------------------------------------------
00426    template <typename T>
00427       unsigned int Hist1d<T>::Fill(const T value)
00428    {
00429       Bin<T> &bin = get_bin(value);
00430       bin.add();
00431       return bin.bin();
00432    }
00433 
00434    //-----------------------------------------------------------------------------------------------
00435    template <typename T>
00436       unsigned int Hist1d<T>::Fill(const T value, const T weight)
00437    {
00438       Bin<T> &bin = get_bin(value);
00439       bin.add(weight);
00440       return bin.bin();
00441    }
00442 
00443    //-----------------------------------------------------------------------------------------------
00444    template <typename T>
00445       unsigned int Hist1d<T>::Fill(const T value, const T weight, const T width)
00446    {
00447       if(!(width > 0.0) || fNBin < 1 || fData.empty())
00448       {
00449          return Fill(value, weight);
00450       }
00451 
00452       // compute boundaries for non zero kernel coontributions
00453       const T lpos = value - width;
00454       const T rpos = value + width;
00455 
00456       // Only overlap with underflow or overflow bins
00457       if(rpos < fData.front())
00458       {
00459          // rpos < underflow bin edge - no contribution to other bins
00460          Bin<T> &bin = fData.front();
00461          bin.add(weight);
00462          return bin.bin();
00463       }
00464       else if(!(lpos < fData.back()))
00465       {
00466          // lpos >= last overflow edge - no contribution to other bins
00467          Bin<T> &bin = fData.back();
00468          bin.add(weight);
00469          return bin.bin();
00470       }
00471 
00472       BinIterator lit = std::lower_bound(fData.begin(), fData.end(), lpos);
00473       if(lit == fData.end())
00474       {
00475          std::cerr << "Hist1d<T>::Fill - lower_bound has failed to find correct bin" << std::endl;
00476          return 0;
00477       }       
00478 
00479       // make copy of beg and end iterators
00480       BinIterator ibeg = fData.begin();
00481       BinIterator iend = fData.end();
00482 
00483       //
00484       // special case: compute overlap with underflow bin
00485       //
00486       if(lit == ibeg)
00487       {
00488          if(lpos < ibeg -> edge())
00489          {
00490             ibeg -> add(weight*GetKernelOverlap<T>(lpos, ibeg -> edge(), value, width));
00491          }
00492 
00493          lit++;
00494       }
00495       else
00496       {
00497          lit--;
00498          assert(lit != ibeg && "logic error finding underflow bin");
00499       }
00500 
00501       for(; lit != iend; ++lit)
00502       {  
00503          //
00504          // No more non overlapping bins
00505          //
00506          if(!(lit -> edge() < rpos))
00507          {
00508             break;
00509          }
00510 
00511          //
00512          // Overlap with this bin
00513          //
00514          T overlap = 0;
00515          
00516          const BinIterator nit = lit + 1;
00517          if(nit == iend)
00518          {
00519             overlap = Anp::GetKernelOverlap<T>(lit -> edge(), rpos, value, width);
00520          }
00521          else
00522          {
00523             //
00524             // kernel is entirely contain in a single bin
00525             //
00526             if(lit -> edge() < lpos && rpos < nit -> edge())
00527             {
00528                lit -> add(weight);
00529                break;
00530             }
00531             
00532             overlap = Anp::GetKernelOverlap<T>(std::max<T>(lit -> edge(), lpos),
00533                                                std::min<T>(nit -> edge(), rpos),
00534                                                value, width);
00535          }
00536 
00537          lit -> add(weight*overlap); // compute overlap fraction with this bin
00538       }
00539       
00540       return 0;
00541    }
00542 
00543    //-----------------------------------------------------------------------------------------------
00544    template <typename T>
00545       unsigned int Hist1d<T>::Fill(const TH1 &h)
00546    {      
00547       const int nbin = h.GetNbinsX();
00548       
00549       assert(nbin > 1 && "Hist1d<T>::Fill encountered TH1 without bins");
00550 
00551       for(int ibin = 0; ibin <= nbin + 1; ++ibin)
00552       {
00553          const double value  = h.GetBinContent(ibin);
00554          const double center = h.GetBinCenter(ibin);
00555          
00556          if(ibin == 0)
00557          {
00558             fData.front().add(value);
00559          }
00560          else if(ibin == nbin + 1)
00561          {
00562             fData.back().add(value);
00563          }
00564          else
00565          {
00566             Fill(center, value);
00567          }
00568       }
00569 
00570       return 0;
00571    }
00572 
00573    //-----------------------------------------------------------------------------------------------
00574    template <typename T>
00575       unsigned int Hist1d<T>::Merge(const T minvalue)
00576    {
00577       unsigned int nmerge = 0;
00578     
00579       typename std::vector<Bin<T> >::iterator bit = fData.begin();
00580       while(bit != fData.end())
00581       {
00582          if(bit -> sum() > minvalue)
00583          {
00584             ++bit;
00585             continue;
00586          }
00587 
00588          if(bit == fData.begin() || bit - 1 == fData.begin())
00589          {
00590             ++bit;
00591             continue;
00592          }
00593 
00594          if(bit + 1 == fData.end() || bit + 2 == fData.end())
00595          {
00596             ++bit;
00597             continue;
00598          }
00599          
00600          typename std::vector<Bin<T> >::iterator lit = bit - 1;
00601          typename std::vector<Bin<T> >::iterator hit = bit + 1;
00602         
00603          if(lit -> sum() < hit -> sum())
00604          {
00605             const Bin<T> newbin(*lit, *bit);
00606 
00607             typename std::vector<Bin<T> >::iterator pit = fData.erase(lit, bit + 1);
00608 
00609             fData.insert(pit, newbin);
00610          }
00611          else
00612          {
00613             const Bin<T> newbin(*bit, *hit);
00614 
00615             typename std::vector<Bin<T> >::iterator pit = fData.erase(bit, hit + 1);
00616 
00617             fData.insert(pit, newbin);
00618          }
00619          
00620          bit = fData.begin();
00621 
00622          ++nmerge;
00623       }
00624 
00625       BinIterator pit = fData.begin();
00626       for(BinIterator cit = fData.begin(); cit != fData.end(); ++cit)
00627       {  
00628          if(cit == fData.begin() || cit - 1 == fData.begin())
00629          {
00630             pit = cit;
00631             continue;
00632          }
00633 
00634          if(!(pit -> edge() < cit -> edge()) || !(pit -> bin() < cit -> bin()))
00635          {
00636             std::cerr << "Hist1d<T>::Merge - logic error for bin " << cit -> bin() << std::endl;
00637          }
00638 
00639          pit = cit;
00640 
00641          cit -> set_bin(std::distance(fData.begin(), cit));
00642          
00643       }
00644 
00645       fNBin = fData.size() - 2;
00646 
00647       return nmerge;
00648    }
00649 
00650    //-----------------------------------------------------------------------------------------------
00651    template <typename T>
00652       unsigned int Hist1d<T>::Rebin(const unsigned int ngroup)
00653    {
00654       //
00655       // rebin histogram by adding ngroup bins together
00656       //
00657 
00658       if(ngroup < 1 || ngroup >= fNBin || fData.size() < 3)
00659       {
00660          return 0;
00661       }
00662 
00663       std::vector<Anp::Bin<T> > data;
00664       bool newbin = true;
00665       Bin<T> bin;
00666 
00667       assert(int(fNBin) == int(fData.size()) - 2 && "logic error counting bins");
00668 
00669       for(unsigned int ibin = 1; ibin <= fNBin; ++ibin)
00670       {
00671          assert(ibin < fData.size() && "out of bounds access");
00672 
00673          if(newbin)
00674          {
00675             bin = fData[ibin];
00676             newbin = false;
00677             continue;
00678          }
00679 
00680          bin = Anp::Merge<T>(bin, fData[ibin]);
00681 
00682          if(ibin % ngroup == 0)
00683          {
00684             data.push_back(bin);
00685             newbin = true;
00686          }
00687       }
00688 
00689       //
00690       // Add last bin
00691       //
00692       if(!newbin) data.push_back(bin);
00693 
00694       //
00695       // sort bins
00696       //
00697       std::sort(data.begin(), data.end());
00698       
00699       //
00700       // Add overflow and underflow bins
00701       //
00702       data.insert(data.begin(), fData.front());
00703       data.insert(data.end(),   fData.back());
00704       
00705       for(unsigned int ibin = 0; ibin < data.size(); ibin++)
00706       {
00707          data[ibin].set_bin(ibin);
00708       }
00709       
00710       fData = data;
00711       fNBin = data.size() - 2;
00712       fSearchBin = true;
00713 
00714       return fNBin;
00715    }
00716 
00717    //-----------------------------------------------------------------------------------------------
00718    template <typename T>      
00719       Bin<T>& Hist1d<T>::operator[](const unsigned int bin)
00720    {
00721       assert(!fData.empty() && "empty bin vector in Hist1d<T>::operator[]");
00722 
00723       if(bin >= fData.size())
00724       {
00725          std::cerr << "Hist1d<T>::operator[" << bin << "] is out of range" << std::endl;
00726          return fData.back();
00727       }
00728       
00729       return fData[bin];
00730    }
00731 
00732    //-----------------------------------------------------------------------------------------------
00733    template <typename T>
00734       Bin<T>& Hist1d<T>::GetBin(const T value)
00735    {
00736       return get_bin(value);
00737    }
00738 
00739    //-----------------------------------------------------------------------------------------------
00740    template <typename T>      
00741       const Bin<T>& Hist1d<T>::operator[](const unsigned int bin) const
00742    {
00743       assert(!fData.empty() && "empty bin vector in Hist1d<T>::operator[]");
00744 
00745       if(bin >= fData.size())
00746       {
00747          std::cerr << "Hist1d<T>::operator[" << bin << "] is out of range" << std::endl;
00748          return fData.back();
00749       }
00750       
00751       return fData[bin];
00752    }
00753 
00754    //-----------------------------------------------------------------------------------------------
00755    template <typename T>
00756       const Bin<T>& Hist1d<T>::GetBin(const T value) const
00757    {
00758       return get_bin_const(value);
00759    }
00760 
00761    //-----------------------------------------------------------------------------------------------
00762    template <typename T>
00763       inline unsigned int Hist1d<T>::GetEntries(const std::string &option) const
00764    {
00765       if(fData.size() < 2)
00766       {
00767          return 0;
00768       }
00769 
00770       unsigned int entries = 0;
00771       
00772       BinIter beg = fData.begin();
00773       BinIter end = fData.end();
00774       
00775       if(option.find("U") == std::string::npos)
00776       {
00777          beg++;
00778       }
00779       if(option.find("O") == std::string::npos)
00780       {
00781          end--;
00782       }
00783       
00784       for(BinIter cit = beg; cit != end; ++cit)
00785       {  
00786          entries += cit -> entries();
00787       }
00788       
00789       return entries;
00790    }
00791    
00792    //-----------------------------------------------------------------------------------------------
00793    template <typename T>
00794       inline T Hist1d<T>::GetIntegral(const std::string &option) const
00795    {
00796       if(fData.size() < 2)
00797       {
00798          return 0;
00799       }
00800 
00801       T integral = 0;
00802 
00803       BinIter beg = fData.begin();
00804       BinIter end = fData.end();
00805       
00806       if(option.find("U") == std::string::npos)
00807       {
00808          beg++;
00809       }
00810       if(option.find("O") == std::string::npos)
00811       {
00812          end--;
00813       }
00814 
00815       for(BinIter cit = beg; cit != end; ++cit)
00816       {  
00817          integral += cit -> sum();
00818       }
00819       
00820       return integral;
00821    }
00822 
00823    //-----------------------------------------------------------------------------------------------
00824    template <typename T>
00825       inline unsigned int Hist1d<T>::GetNbins() const { return fNBin; }
00826       
00827    //-----------------------------------------------------------------------------------------------
00828    template <typename T>
00829       inline const std::vector<Anp::Bin<T> >& Hist1d<T>::GetBins() const { return fData; }
00830 
00831    //-----------------------------------------------------------------------------------------------
00832    template <typename T>
00833       inline void Hist1d<T>::Reset()
00834    {
00835       for(BinIterator cit = fData.begin(); cit != fData.end(); ++cit)
00836       {  
00837          cit -> reset();
00838       }
00839    }
00840 
00841    //-----------------------------------------------------------------------------------------------
00842    template <typename T>
00843       const Bin<T>& Hist1d<T>::get_bin_const(const T value) const
00844    {
00845       assert(!fData.empty() && "Hist1d<T>::get_bin_const() - vector is empty");
00846          
00847       if(fData.size() == 1)
00848       {
00849          return fData.front();
00850       }
00851       else if(value < fData.front())
00852       {
00853          // value < underflow bin edge so return underflow bin
00854          return fData.front();
00855       }
00856       else if(!(value < fData.back()))
00857       {
00858          // value >= last overflow edge so return overflow bin
00859          return fData.back();
00860       }
00861 
00862       // this point is reached if value >= low edge AND value < high edge
00863       // use stl binary_search to find proper bin, exclude underflow bin
00864       
00865       if(fSearchBin)
00866       {
00867          BinIter bit = std::lower_bound(fData.begin() + 1, fData.end(), value);
00868          if(bit == fData.end())
00869          {
00870             std::cerr << "Hist1d<T>::get_bin_const() - lower_bound has failed to find bin" << std::endl;
00871             return fData.back();
00872          }
00873          else if(!(value < *bit) && !(*bit < value))
00874          {
00875             return *bit;
00876          }
00877          
00878          return *(bit - 1);
00879       }
00880       else
00881       {
00882          const unsigned int bin = 
00883             1 + static_cast<unsigned int>((fNBin*(value - fLowEdge))/(fHighEdge - fLowEdge));
00884 
00885          if(bin > fNBin)
00886          {
00887             std::cerr << "Hist1d<T>::get_bin_const() - logic error #1" << std::endl;
00888             return fData.back();
00889          }
00890 
00891          return fData[bin];
00892       }      
00893       
00894       std::cerr << "Hist1d<T>::get_bin_const() - logic error #2" << std::endl;
00895       return fData.front();
00896    }
00897 
00898    //-----------------------------------------------------------------------------------------------
00899    template <typename T>
00900       Bin<T>& Hist1d<T>::get_bin(const T value)
00901    {
00902       return const_cast<Bin<T> &>(get_bin_const(value));
00903    }
00904 
00905    //-----------------------------------------------------------------------------------------------
00906    template <typename T>
00907       void Hist1d<T>::init_trivial()
00908    {
00909       fNBin = 0;
00910       fData.push_back(Bin<T>(0, T()));
00911    }
00912 
00913    //-----------------------------------------------------------------------------------------------
00914    template <typename T>
00915       void Hist1d<T>::init_bins()
00916    {
00917       if(!(fLowEdge < fHighEdge))
00918       {
00919          std::cerr << "Hist1d<T>::init_bins() - minimum is not larger than maximum" << std::endl;
00920          init_trivial();
00921          return;
00922       }
00923 
00924       fData.push_back(Bin<T>(0, fLowEdge));
00925 
00926       for(unsigned int ibin = 0; ibin < fNBin + 1; ++ibin)
00927       {
00928          const T edge = fLowEdge + static_cast<T>(((fHighEdge - fLowEdge)*ibin)/fNBin);
00929          fData.push_back(Bin<T>(ibin + 1, edge));
00930       }
00931 
00932       // sort all but first overflow bin
00933       std::sort(fData.begin() + 1, fData.end());
00934    }
00935 
00936    //-----------------------------------------------------------------------------------------------
00937    template <typename T>
00938       void Hist1d<T>::init_bins(std::vector<T> vec)
00939    {
00940       assert(vec.size() > 1 && "Hist1d<T>::init_bins() encountered small vector");
00941 
00942       // sort bin edges
00943       std::sort(vec.begin(), vec.end());
00944       
00945       fNBin = vec.size() - 1;
00946       fData.push_back(Bin<T>(0, vec.front()));
00947 
00948       for(unsigned int ibin = 0; ibin < vec.size(); ++ibin)
00949       {
00950          fData.push_back(Bin<T>(ibin + 1, vec[ibin]));
00951       }
00952 
00953       // sort all but first overflow bin
00954       std::sort(fData.begin() + 1, fData.end());
00955    }
00956 
00957    //-----------------------------------------------------------------------------------------------
00958    template <typename T>
00959       void Hist1d<T>::Print(std::ostream& o) const
00960    {
00961       o << "Printing 1d histogram containing " << fNBin << " bins" << std::endl;
00962 
00963       short width = 1;      
00964       for(short i = 1; i < 10; ++i)
00965       {
00966          if(fNBin < 10^(i))
00967          {
00968             width = i;
00969             break;
00970          }
00971       }
00972       if(width < 4)
00973       {
00974          width = 4;
00975       }
00976 
00977       for(BinIter it = fData.begin(); it != fData.end(); ++it)
00978       {
00979          it -> print(o, width, width);
00980       }
00981    }
00982 
00983    //--------------------------------------------------------------------------------------
00984    // non member Hist1d<T> functions below this line
00985    //--------------------------------------------------------------------------------------
00986    template<typename T>    
00987       TH1* CreateTH1(const Hist1d<T> &h, const std::string &name)
00988    {
00989       const std::vector<Bin<T> > &bvec = h.GetBins();
00990 
00991       if(bvec.empty())
00992       {
00993          return 0;
00994       }
00995 
00996       double *array = new double[bvec.size() - 1];
00997 
00998       for(int ibin = 1; ibin < int(bvec.size()); ++ibin)
00999       {
01000          array[ibin - 1] = bvec[ibin].edge();
01001       }
01002 
01003       TH1 *th1 = new TH1D(name.c_str(), name.c_str(), bvec.size() - 2, array);
01004 
01005       delete [] array;
01006 
01007       for(int ibin = 0; ibin < int(bvec.size()); ++ibin)
01008       {
01009          th1 -> SetBinContent(ibin, bvec[ibin].sum());
01010       }
01011 
01012       Anp::SetDir(th1, 0);
01013       th1 -> SetEntries(h.GetIntegral("UO"));
01014 
01015       return th1;
01016    }
01017 
01018 #ifndef __CINT__
01019 
01020    template <typename T>
01021       std::ostream& operator<<(std::ostream& o, const Hist1d<T> &self)
01022    {
01023       self.Print(o);
01024       return o;
01025    }
01026 
01027 #endif
01028 
01029 }
01030 #endif

Generated on Mon Feb 15 11:06:47 2010 for loon by  doxygen 1.3.9.1