CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/DQMOffline/JetMET/interface/SusyDQM/Quantile.h

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 //dk    if( bin==begin ) return pair(sqrt(-1),0);
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