Go to the documentation of this file.00001 #ifndef QUANTILE_H
00002 #define QUANTILE_H
00003
00004 #include "TH1.h"
00005 #include <vector>
00006 #include <iostream>
00007
00008 struct Quantile {
00009 typedef std::pair<double,double> pair;
00010 typedef std::vector<pair> array;
00011
00012 pair operator()(const double frac) const {return fromHead(frac);}
00013 pair operator[](const double frac) const {return fromTail(frac);}
00014
00015 Quantile(const TH1* h) :
00016 N( 1 + h->GetNbinsX()),
00017 Total(h->Integral(0,N))
00018 { for(int i=0;i<N; i++) {
00019 const double H = h->GetBinContent(i) + (head.size()?head.back().second:0);
00020 const double T = h->GetBinContent(N-i) + (tail.size()?tail.back().second:0);
00021 if(H) head.push_back( pair( h->GetBinWidth(i) + h->GetBinLowEdge(i) , H));
00022 if(T) tail.push_back( pair( h->GetBinLowEdge(N-i),T));
00023 }
00024 }
00025
00026 pair fromHead(const double frac) const {return calculateQ(frac,true);}
00027 pair fromTail(const double frac) const {return calculateQ(frac,false);}
00028
00029 private:
00030
00031 pair calculateQ(const double frac, const bool fromHead) const {
00032 const double f = frac<0.5 ? frac : 1-frac ;
00033 array::const_iterator
00034 begin( ( (frac<0.5) == fromHead ) ? head.begin() : tail.begin()),
00035 end( ( (frac<0.5) == fromHead ) ? head.end() : tail.end()),
00036 bin(begin);
00037
00038 while( bin->second < f*Total ) bin++;
00039
00040 if( bin==begin ) return pair(-1,0);
00041
00042 array::const_iterator
00043 binNext( next(bin,end)),
00044 binPrev( prev(bin,begin)),
00045 binPPrev( prev(binPrev,begin));
00046
00047 const double
00048 DX( binNext->first - binPPrev->first ),
00049 DY( (binNext->second - binPPrev->second)/Total ),
00050
00051 dX( bin->first - binPrev->first ),
00052 dY( (bin->second - binPrev->second)/Total ),
00053
00054 avgX( ( bin->first + binPrev->first) /2 ),
00055 avgY( ( bin->second + binPrev->second) /(2*Total) ),
00056
00057 x_q( avgX + dX/dY * ( f - avgY ) ),
00058 xerr_q( std::max(fabs(DX/DY),fabs(dX/dY)) * sqrt(f*(1-f)/Total) );
00059
00060 return pair(x_q,xerr_q);
00061 }
00062
00063
00064 template<class T> T prev(T bin, T begin) const {
00065 T binPrev = bin;
00066 while( binPrev > begin &&
00067 (binPrev-1)->second == (bin-1)->second )
00068 binPrev--;
00069 return binPrev;
00070 }
00071
00072 template<class T> T next(T bin, T end) const {
00073 T binNext = bin;
00074 while( binNext<end-1 &&
00075 (++binNext)->second == bin->second)
00076 ;
00077 return binNext;
00078 }
00079
00080 const int N;
00081 const double Total;
00082 array head,tail;
00083 };
00084 #endif