RooBinning.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooBinning.cxx 36207 2010-10-08 19:00:29Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 // 
00019 // BEGIN_HTML 
00020 // Class RooBinning is an implements RooAbsBinning in terms
00021 // of an array of boundary values, posing no constraints on the choice
00022 // of binning, thus allowing variable bin sizes. Various methods allow
00023 // the user to add single bin boundaries, mirrored pairs, or sets of
00024 // uniformly spaced boundaries.  
00025 // END_HTML
00026 //
00027 
00028 #include "RooFit.h"
00029 
00030 #include "Riostream.h"
00031 #include "Riostream.h"
00032 #include "RooBinning.h"
00033 #include "RooDouble.h"
00034 #include "RooAbsPdf.h"
00035 #include "RooRealVar.h"
00036 #include "RooNumber.h"
00037 #include "RooMsgService.h"
00038 #include "TList.h"
00039 
00040 ClassImp(RooBinning)
00041 ;
00042 
00043 
00044 //_____________________________________________________________________________
00045 RooBinning::RooBinning(Double_t xlo, Double_t xhi, const char* name) : 
00046   RooAbsBinning(name), 
00047   _xlo(0),
00048   _xhi(0),
00049   _ownBoundLo(kTRUE), 
00050   _ownBoundHi(kTRUE), 
00051   _array(0)
00052 {
00053   // Constructor for an initially empty binning defining the range [xlo,xhi]
00054 
00055   setRange(xlo,xhi) ;
00056 }
00057 
00058 
00059 
00060 //_____________________________________________________________________________
00061 RooBinning::RooBinning(Int_t nbins, Double_t xlo, Double_t xhi, const char* name) : 
00062   RooAbsBinning(name), 
00063   _xlo(0),
00064   _xhi(0),
00065   _ownBoundLo(kTRUE), 
00066   _ownBoundHi(kTRUE), 
00067   _array(0)
00068 {
00069   // Constructor for a uniform binning in 'nbins' bins in the range [xlo,xhi]
00070 
00071   // Uniform bin size constructor
00072   setRange(xlo,xhi) ;
00073   addUniform(nbins,xlo,xhi) ;
00074 }
00075 
00076 
00077 
00078 
00079 //_____________________________________________________________________________
00080 RooBinning::RooBinning(Int_t nbins, const Double_t* boundaries, const char* name) : 
00081   RooAbsBinning(name),
00082   _xlo(0),
00083   _xhi(0),
00084   _ownBoundLo(kTRUE), 
00085   _ownBoundHi(kTRUE), 
00086   _array(0)
00087 {
00088   // Constructor for a binning in the range[xlo,xhi] with 'nbins' bin boundaries listed
00089   // array 'boundaries'
00090 
00091   // Variable bin size constructor
00092   setRange(boundaries[0],boundaries[nbins]) ;
00093   while(nbins--) addBoundary(boundaries[nbins]) ;
00094 }
00095 
00096 
00097 
00098 //_____________________________________________________________________________
00099 RooBinning::RooBinning(const RooBinning& other, const char* name) : 
00100   RooAbsBinning(name),
00101   _boundaries(other._boundaries),
00102   _array(0)
00103 { 
00104   // Copy constructor
00105   _xlo = other._xlo ;
00106   _xhi = other._xhi ;
00107   _ownBoundLo = other._ownBoundLo ;
00108   _ownBoundHi = other._ownBoundHi ;
00109   _nbins = other._nbins ;
00110 }
00111 
00112 
00113 
00114 //_____________________________________________________________________________
00115 RooBinning::~RooBinning() 
00116 {
00117   // Destructor
00118 
00119   if (_array) delete[] _array ;
00120 
00121 }
00122 
00123 
00124 //_____________________________________________________________________________
00125 Bool_t RooBinning::addBoundary(Double_t boundary) 
00126 {  
00127   // Add bin boundary at given value
00128 
00129   if (_boundaries.find(boundary)!=_boundaries.end()) {
00130     // If boundary previously existed as range delimiter, 
00131     //                    convert to regular boundary now
00132     if (boundary==_xlo) _ownBoundLo = kFALSE ;
00133     if (boundary==_xhi) _ownBoundHi = kFALSE ;
00134     return kFALSE ;    
00135   }
00136 
00137   // Add a new boundary
00138   _boundaries.insert(boundary) ;
00139   updateBinCount() ;
00140   return kTRUE ;
00141 }
00142 
00143 
00144 
00145 //_____________________________________________________________________________
00146 void RooBinning::addBoundaryPair(Double_t boundary, Double_t mirrorPoint) 
00147 {
00148   // Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary
00149 
00150   addBoundary(boundary) ;
00151   addBoundary(2*mirrorPoint-boundary) ;
00152 }
00153 
00154 
00155 
00156 //_____________________________________________________________________________
00157 Bool_t RooBinning::removeBoundary(Double_t boundary)
00158 {
00159   // Remove boundary at given value
00160 
00161   if (_boundaries.find(boundary)!=_boundaries.end()) {
00162     _boundaries.erase(boundary) ;
00163     return kFALSE ;
00164   }
00165 
00166   // Return error status - no boundary found
00167   return kTRUE ;
00168 }
00169 
00170 
00171 
00172 //_____________________________________________________________________________
00173 Bool_t RooBinning::hasBoundary(Double_t boundary)
00174 {
00175   // Check if boundary exists at given value
00176 
00177   return (_boundaries.find(boundary)!=_boundaries.end()) ;
00178 }
00179 
00180 
00181 
00182 //_____________________________________________________________________________
00183 void RooBinning::addUniform(Int_t nbins, Double_t xlo, Double_t xhi)
00184 {
00185   // Add array of nbins uniformly sized bins in range [xlo,xhi]
00186 
00187   Int_t i ;
00188   Double_t binw = (xhi-xlo)/nbins ;
00189   for (i=0 ; i<=nbins ; i++) 
00190     addBoundary(xlo+i*binw) ;  
00191 }
00192 
00193 
00194 
00195 //_____________________________________________________________________________
00196 Int_t RooBinning::binNumber(Double_t x) const
00197 {
00198   // Return sequential bin number that contains value x where bin
00199   // zero is the first bin with an upper boundary above the lower bound
00200   // of the range
00201 
00202   Int_t n(0) ;
00203   for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {
00204     if (x<*iter) {
00205       return n ;
00206     }
00207 
00208     // Only increment counter in valid range
00209     if (*iter> _xlo && n<_nbins-1) n++ ;    
00210   }  
00211   return n;
00212 }
00213 
00214 
00215 
00216 //_____________________________________________________________________________
00217 Int_t RooBinning::rawBinNumber(Double_t x) const 
00218 {
00219   // Return sequential bin number that contains value x where bin
00220   // zero is the first bin that is defined, regardless if that bin
00221   // is outside the current defined range
00222   
00223  
00224   // Determine 'raw' bin number (i.e counting all defined boundaries) for given value
00225   Int_t n(0) ;
00226 
00227   for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {    
00228     if (x<*iter) return n>0?n-1:0 ;
00229     n++ ;
00230   }
00231   return n-1;
00232 }
00233 
00234 
00235 
00236 //_____________________________________________________________________________
00237 Double_t RooBinning::nearestBoundary(Double_t x) const 
00238 {
00239   // Return the value of the nearest boundary to x
00240 
00241   Int_t bn = binNumber(x) ;
00242   if (fabs(binLow(bn)-x)<fabs(binHigh(bn)-x)) {
00243     return binLow(bn) ;
00244   } else {
00245     return binHigh(bn) ;
00246   }
00247 }
00248 
00249 
00250 
00251 //_____________________________________________________________________________
00252 Double_t* RooBinning::array() const
00253 {
00254   // Return array of boundary values
00255 
00256   if (_array) delete[] _array ;
00257   _array = new Double_t[numBoundaries()] ;
00258 
00259   Int_t i(0) ;
00260   for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {
00261     if (*iter>=_xlo && *iter <=_xhi) {
00262       _array[i++] = *iter ;
00263     }
00264   }
00265   return _array ;
00266 }
00267 
00268 
00269 
00270 //_____________________________________________________________________________
00271 void RooBinning::setRange(Double_t xlo, Double_t xhi) 
00272 {
00273   // Change the defined range associated with this binning.
00274   // Bins that lie outside the new range [xlo,xhi] will not be
00275   // removed, but will be 'inactive', i.e. the new 0 bin will
00276   // be the first bin with an upper boundarie > xlo
00277 
00278   if (xlo>xhi) {
00279     coutE(InputArguments) << "RooUniformBinning::setRange: ERROR low bound > high bound" << endl ;
00280     return ;
00281   }
00282   
00283   // Remove previous boundaries 
00284   
00285   for (set<Double_t>::iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ;) {    
00286     if ((*iter == _xlo && _ownBoundLo) || (*iter == _xhi && _ownBoundHi)) {
00287       _boundaries.erase(iter++) ;
00288     } else {
00289       ++iter ;
00290     }
00291   }
00292 
00293   // Insert boundaries at range delimiter, if necessary 
00294   _ownBoundLo = kFALSE ;
00295   _ownBoundHi = kFALSE ;
00296   if (!hasBoundary(xlo)) {
00297     addBoundary(xlo) ;
00298     _ownBoundLo = kTRUE ;
00299   }
00300   if (!hasBoundary(xhi)) {
00301     addBoundary(xhi) ;
00302     _ownBoundHi = kTRUE ;
00303   }
00304 
00305   _xlo = xlo ;
00306   _xhi = xhi ;
00307   
00308   // Count number of bins with new range 
00309   updateBinCount() ;
00310 }
00311 
00312 
00313 
00314 
00315 //_____________________________________________________________________________
00316 void RooBinning::updateBinCount()
00317 {
00318   // Update the internal bin counter
00319 
00320   Int_t i(-1) ;
00321   for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {    
00322     if (*iter>=_xlo && *iter <=_xhi) {
00323       i++ ;
00324     }
00325   }
00326   _nbins = i ;
00327 }
00328 
00329 
00330 
00331 //_____________________________________________________________________________
00332 Bool_t RooBinning::binEdges(Int_t bin, Double_t& xlo, Double_t& xhi) const 
00333 {
00334   // Return upper and lower bound of bin 'bin'. If the return value
00335   // is true an error occurred
00336 
00337   if (bin<0 || bin>= _nbins) {
00338     coutE(InputArguments) << "RooBinning::binEdges ERROR: bin number must be in range (0," << _nbins << ")" << endl ; 
00339     return kTRUE ;
00340   }
00341   
00342   // Determine sequential bin number for given value
00343   Int_t n(0) ;
00344   for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {    
00345 
00346     if (n==bin && *iter>=_xlo) {
00347       xlo = *iter ;
00348       iter++ ;
00349       xhi = *iter ;
00350       return kFALSE ;
00351     }
00352 
00353     // Only increment counter in valid range
00354     if (*iter>= _xlo && n<_nbins-1) n++ ;
00355   }
00356 
00357   return kTRUE ;
00358 }
00359 
00360 
00361 
00362 //_____________________________________________________________________________
00363 Double_t RooBinning::binCenter(Int_t bin) const 
00364 {
00365   // Return the position of the center of bin 'bin'
00366 
00367   Double_t xlo,xhi ;
00368   if (binEdges(bin,xlo,xhi)) return 0 ;
00369   return (xlo+xhi)/2 ;
00370 }
00371 
00372 
00373 
00374 //_____________________________________________________________________________
00375 Double_t RooBinning::binWidth(Int_t bin) const 
00376 {
00377   // Return the width of the requested bin
00378 
00379   Double_t xlo,xhi ;
00380   if (binEdges(bin,xlo,xhi)) return 0 ;
00381   return (xhi-xlo);
00382 }
00383 
00384 
00385 
00386 //_____________________________________________________________________________
00387 Double_t RooBinning::binLow(Int_t bin) const 
00388 {
00389   // Return the lower bound of the requested bin
00390 
00391   Double_t xlo,xhi ;
00392   if (binEdges(bin,xlo,xhi)) return 0 ;
00393   return xlo ;
00394 }
00395 
00396 
00397 
00398 //_____________________________________________________________________________
00399 Double_t RooBinning::binHigh(Int_t bin) const  
00400 {
00401   // Return the upper bound of the requested bin
00402 
00403   Double_t xlo,xhi ;
00404   if (binEdges(bin,xlo,xhi)) return  0 ;
00405   return xhi ;
00406 }
00407 
00408 
00409 
00410 //______________________________________________________________________________
00411 void RooBinning::Streamer(TBuffer &R__b)
00412 {
00413    // Custom streamer that provides backward compatibility to read v1 data
00414 
00415    if (R__b.IsReading()) {
00416 
00417      UInt_t R__s, R__c;
00418      Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
00419      if (R__v>1) {
00420        R__b.ReadClassBuffer(RooBinning::Class(),this,R__v,R__s,R__c);
00421      } else {
00422        RooAbsBinning::Streamer(R__b);
00423        R__b >> _xlo;
00424        R__b >> _xhi;
00425        R__b >> _ownBoundLo;
00426        R__b >> _ownBoundHi;
00427        R__b >> _nbins;
00428        
00429        // Convert TList to set<double>
00430        TList boundaries ;
00431        boundaries.Streamer(R__b);
00432        TIterator* iter = boundaries.MakeIterator() ;
00433        RooDouble* elem ;
00434        while((elem=(RooDouble*)iter->Next())) {
00435          _boundaries.insert(*elem) ;
00436        }
00437        delete iter ;
00438        
00439        R__b.CheckByteCount(R__s, R__c, RooBinning::IsA());
00440      }
00441    } else {
00442      R__b.WriteClassBuffer(RooBinning::Class(),this);
00443    }
00444 }
00445 
00446 

Generated on Tue Jul 5 15:06:05 2011 for ROOT_528-00b_version by  doxygen 1.5.1