00001 #ifndef ANP_HIST1D_H
00002 #define ANP_HIST1D_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <algorithm>
00015 #include <cassert>
00016 #include <cmath>
00017 #include <iomanip>
00018 #include <iostream>
00019 #include <string>
00020 #include <vector>
00021
00022
00023 #include "TH1.h"
00024
00025
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
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
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
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
00300
00301
00302
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
00326
00327
00328
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
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
00453 const T lpos = value - width;
00454 const T rpos = value + width;
00455
00456
00457 if(rpos < fData.front())
00458 {
00459
00460 Bin<T> &bin = fData.front();
00461 bin.add(weight);
00462 return bin.bin();
00463 }
00464 else if(!(lpos < fData.back()))
00465 {
00466
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
00480 BinIterator ibeg = fData.begin();
00481 BinIterator iend = fData.end();
00482
00483
00484
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
00505
00506 if(!(lit -> edge() < rpos))
00507 {
00508 break;
00509 }
00510
00511
00512
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
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);
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
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
00691
00692 if(!newbin) data.push_back(bin);
00693
00694
00695
00696
00697 std::sort(data.begin(), data.end());
00698
00699
00700
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
00854 return fData.front();
00855 }
00856 else if(!(value < fData.back()))
00857 {
00858
00859 return fData.back();
00860 }
00861
00862
00863
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
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
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
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
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