RooGrid.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooGrid.cxx 36209 2010-10-08 21:37:36Z 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 // RooGrid is a utility class for RooMCIntegrator which
00021 // implements an adaptive multi-dimensional Monte Carlo numerical
00022 // integration, following the VEGAS algorithm.  
00023 // END_HTML
00024 //
00025 
00026 #include "RooFit.h"
00027 
00028 #include "RooGrid.h"
00029 #include "RooGrid.h"
00030 #include "RooAbsFunc.h"
00031 #include "RooNumber.h"
00032 #include "RooRandom.h"
00033 #include "TMath.h"
00034 #include "RooMsgService.h"
00035 #include "TClass.h"
00036 
00037 #include <math.h>
00038 #include "Riostream.h"
00039 #include <iomanip>
00040 
00041 ClassImp(RooGrid)
00042 ;
00043 
00044 
00045 //_____________________________________________________________________________
00046 RooGrid::RooGrid() :
00047   _valid(kFALSE), _dim(0), _bins(0), _boxes(0), _vol(0), _xl(0),  _xu(0),  _delx(0),  _d(0),  _xi(0),  _xin(0),  _weight(0)
00048 {
00049   // Default constructor
00050 }
00051 
00052 
00053 //_____________________________________________________________________________
00054 RooGrid::RooGrid(const RooAbsFunc &function)
00055   : _valid(kTRUE), _xl(0),_xu(0),_delx(0),_xi(0)
00056 {
00057   // Constructor with given function binding
00058 
00059   // check that the input function is valid
00060   if(!(_valid= function.isValid())) {
00061     oocoutE((TObject*)0,InputArguments) << ClassName() << ": cannot initialize using an invalid function" << endl;
00062     return;
00063   }
00064 
00065   // allocate workspace memory
00066   _dim= function.getDimension();
00067   _xl= new Double_t[_dim];
00068   _xu= new Double_t[_dim];
00069   _delx= new Double_t[_dim];
00070   _d= new Double_t[_dim*maxBins];
00071   _xi= new Double_t[_dim*(maxBins+1)];
00072   _xin= new Double_t[maxBins+1];
00073   _weight= new Double_t[maxBins];
00074   if(!_xl || !_xu || !_delx || !_d || !_xi || !_xin || !_weight) {
00075     oocoutE((TObject*)0,Integration) << ClassName() << ": memory allocation failed" << endl;
00076     _valid= kFALSE;
00077     return;
00078   }
00079 
00080   // initialize the grid
00081   _valid= initialize(function);
00082 }
00083 
00084 
00085 //_____________________________________________________________________________
00086 RooGrid::~RooGrid() 
00087 {
00088   // Destructor
00089   if(_xl)     delete[] _xl;
00090   if(_xu)     delete[] _xu;
00091   if(_delx)   delete[] _delx;
00092   if(_d)      delete[] _d;
00093   if(_xi)     delete[] _xi;
00094   if(_xin)    delete[] _xin;
00095   if(_weight) delete[] _weight;
00096 }
00097 
00098 
00099 //_____________________________________________________________________________
00100 Bool_t RooGrid::initialize(const RooAbsFunc &function) 
00101 {
00102   // Calculate and store the grid dimensions and volume using the
00103   // specified function, and initialize the grid using a single bin.
00104   // Return kTRUE, or else kFALSE if the range is not valid.
00105 
00106   _vol= 1;
00107   _bins= 1;
00108   for(UInt_t index= 0; index < _dim; index++) {
00109     _xl[index]= function.getMinLimit(index);
00110     if(RooNumber::isInfinite(_xl[index])) {
00111       oocoutE((TObject*)0,Integration) << ClassName() << ": lower limit of dimension " << index << " is infinite" << endl;
00112       return kFALSE;
00113     }
00114     _xu[index]= function.getMaxLimit(index);
00115     if(RooNumber::isInfinite(_xl[index])) {
00116       oocoutE((TObject*)0,Integration) << ClassName() << ": upper limit of dimension " << index << " is infinite" << endl;
00117       return kFALSE;
00118     }
00119     Double_t dx= _xu[index] - _xl[index];
00120     if(dx <= 0) {
00121       oocoutE((TObject*)0,Integration) << ClassName() << ": bad range for dimension " << index << ": [" << _xl[index]
00122                                        << "," << _xu[index] << "]" << endl;
00123       return kFALSE;
00124     }
00125     _delx[index]= dx;
00126     _vol*= dx;
00127     coord(0,index) = 0;
00128     coord(1,index) = 1;
00129   }
00130   return kTRUE;
00131 }
00132 
00133 
00134 //_____________________________________________________________________________
00135 void RooGrid::resize(UInt_t bins) 
00136 {
00137   // Adjust the subdivision of each axis to give the specified
00138   // number of bins, using an algorithm that preserves relative
00139   // bin density. The new binning can be finer or coarser than
00140   // the original binning.
00141 
00142   // is there anything to do?
00143   if(bins == _bins) return;
00144   
00145   // weight is ratio of bin sizes
00146   Double_t pts_per_bin = (Double_t) _bins / (Double_t) bins;
00147 
00148   // loop over grid dimensions
00149   for (UInt_t j = 0; j < _dim; j++) {
00150     Double_t xold,xnew(0),dw(0);
00151     Int_t i = 1;
00152     // loop over bins in this dimension and load _xin[] with new bin edges
00153 
00154     UInt_t k;
00155     for(k = 1; k <= _bins; k++) {
00156       dw += 1.0;
00157       xold = xnew;
00158       xnew = coord(k,j);      
00159       while(dw > pts_per_bin) {
00160         dw -= pts_per_bin;
00161         newCoord(i++)= xnew - (xnew - xold) * dw;
00162       }
00163     }
00164     // copy the new edges into _xi[j]
00165     for(k = 1 ; k < bins; k++) {
00166       coord(k, j) = newCoord(k);
00167     }
00168     coord(bins, j) = 1;
00169   }  
00170   _bins = bins;
00171 }
00172 
00173 
00174 //_____________________________________________________________________________
00175 void RooGrid::resetValues() 
00176 {
00177   // Reset the values associated with each grid cell.
00178   
00179   for(UInt_t i = 0; i < _bins; i++) {
00180     for (UInt_t j = 0; j < _dim; j++) {
00181       value(i,j)= 0.0;
00182     }
00183   }
00184 }
00185 
00186 
00187 //_____________________________________________________________________________
00188 void RooGrid::generatePoint(const UInt_t box[], Double_t x[], UInt_t bin[], Double_t &vol,
00189                             Bool_t useQuasiRandom) const 
00190 {
00191   // Generate a random vector in the specified box and and store its
00192   // coordinates in the x[] array provided, the corresponding bin
00193   // indices in the bin[] array, and the volume of this bin in vol.
00194   // The box is specified by the array box[] of box integer indices
00195   // that each range from 0 to getNBoxes()-1.
00196 
00197   vol= 1;
00198 
00199   // generate a vector of quasi-random numbers to use
00200   if(useQuasiRandom) {
00201     RooRandom::quasi(_dim,x);
00202   }
00203   else {
00204     RooRandom::uniform(_dim,x);
00205   }
00206 
00207   // loop over coordinate axes
00208   for(UInt_t j= 0; j < _dim; ++j) {
00209 
00210     // generate a random point uniformly distributed (in box space)
00211     // within the box[j]-th box of coordinate axis j.
00212     Double_t z= ((box[j] + x[j])/_boxes)*_bins;
00213 
00214     // store the bin in which this point lies along the j-th
00215     // coordinate axis and calculate its width and position y
00216     // in normalized bin coordinates.
00217     Int_t k= (Int_t)z;
00218     bin[j] = k;
00219     Double_t y, bin_width;
00220     if(k == 0) {
00221       bin_width= coord(1,j);
00222       y= z * bin_width;
00223     }
00224     else {
00225       bin_width= coord(k+1,j) - coord(k,j);
00226       y= coord(k,j) + (z-k)*bin_width;
00227     }
00228     // transform from normalized bin coordinates to x space.
00229     x[j] = _xl[j] + y*_delx[j];
00230 
00231     // update this bin's calculated volume
00232     vol *= bin_width;
00233   }
00234 }
00235 
00236 
00237 
00238 //_____________________________________________________________________________
00239 void RooGrid::firstBox(UInt_t box[]) const 
00240 {
00241   // Reset the specified array of box indices to refer to the first box
00242   // in the standard traversal order.
00243 
00244   for(UInt_t i= 0; i < _dim; i++) box[i]= 0;
00245 }
00246 
00247 
00248 
00249 //_____________________________________________________________________________
00250 Bool_t RooGrid::nextBox(UInt_t box[]) const 
00251 {
00252   // Update the specified array of box indices to refer to the next box
00253   // in the standard traversal order and return kTRUE, or else return
00254   // kFALSE if we the indices already refer to the last box.
00255 
00256   // try incrementing each index until we find one that does not roll
00257   // over, starting from the last index.
00258   Int_t j(_dim-1);
00259   while (j >= 0) {
00260     box[j]= (box[j] + 1) % _boxes;
00261     if (0 != box[j]) return kTRUE;
00262     j--;
00263   }
00264   // if we get here, then there are no more boxes
00265   return kFALSE;
00266 }
00267 
00268 
00269 
00270 //_____________________________________________________________________________
00271 void RooGrid::printMultiline(ostream& os, Int_t /*contents*/, Bool_t verbose, TString indent) const 
00272 {
00273   // Print info about this object to the specified stream.
00274 
00275   os << ClassName() << ": volume = " << getVolume() << endl;
00276   os << indent << "  Has " << getDimension() << " dimension(s) each subdivided into "
00277      << getNBins() << " bin(s) and sampled with " << _boxes << " box(es)" << endl;
00278   for(UInt_t index= 0; index < getDimension(); index++) {
00279     os << indent << "  (" << index << ") ["
00280        << setw(10) << _xl[index] << "," << setw(10) << _xu[index] << "]" << endl;
00281     if(!verbose) continue;
00282     for(UInt_t bin= 0; bin < _bins; bin++) {
00283       os << indent << "    bin-" << bin << " : x = " << coord(bin,index) << " , y = "
00284          << value(bin,index) << endl;
00285     }
00286   }
00287 }
00288 
00289 
00290 //_____________________________________________________________________________
00291 void RooGrid::printName(ostream& os) const 
00292 {
00293   // Print name of grid object
00294   os << GetName() ;
00295 }
00296 
00297 
00298 //_____________________________________________________________________________
00299 void RooGrid::printTitle(ostream& os) const 
00300 {
00301   // Print title of grid object
00302   os << GetTitle() ;
00303 }
00304 
00305 
00306 //_____________________________________________________________________________
00307 void RooGrid::printClassName(ostream& os) const 
00308 {
00309   // Print class name of grid object
00310   os << IsA()->GetName() ;
00311 }
00312 
00313 
00314 
00315 //_____________________________________________________________________________
00316 void RooGrid::accumulate(const UInt_t bin[], Double_t amount) 
00317 {
00318   // Add the specified amount to bin[j] of the 1D histograms associated
00319   // with each axis j.
00320 
00321   for(UInt_t j = 0; j < _dim; j++) value(bin[j],j) += amount;
00322 }
00323 
00324 
00325 //_____________________________________________________________________________
00326 void RooGrid::refine(Double_t alpha) 
00327 {
00328   // Refine the grid using the values that have been accumulated so far.
00329   // The parameter alpha controls the stiffness of the rebinning and should
00330   // usually be between 1 (stiffer) and 2 (more flexible). A value of zero
00331   // prevents any rebinning.
00332   
00333   for (UInt_t j = 0; j < _dim; j++) {
00334 
00335     // smooth this dimension's histogram of grid values and calculate the
00336     // new sum of the histogram contents as grid_tot_j
00337     Double_t oldg = value(0,j);
00338     Double_t newg = value(1,j);
00339     value(0,j)= (oldg + newg)/2;
00340     Double_t grid_tot_j = value(0,j);    
00341     // this loop implements value(i,j) = ( value(i-1,j)+value(i,j)+value(i+1,j) ) / 3
00342 
00343     UInt_t i;
00344     for (i = 1; i < _bins - 1; i++) {
00345       Double_t rc = oldg + newg;
00346       oldg = newg;
00347       newg = value(i+1,j);
00348       value(i,j)= (rc + newg)/3;
00349       grid_tot_j+= value(i,j);
00350     }
00351     value(_bins-1,j)= (newg + oldg)/2;
00352     grid_tot_j+= value(_bins-1,j);
00353 
00354     // calculate the weights for each bin of this dimension's histogram of values
00355     // and their sum
00356     Double_t tot_weight(0);
00357     for (i = 0; i < _bins; i++) {
00358       _weight[i] = 0;
00359       if (value(i,j) > 0) {
00360         oldg = grid_tot_j/value(i,j);
00361         /* damped change */
00362         _weight[i] = TMath::Power(((oldg-1.0)/oldg/log(oldg)), alpha);
00363       }
00364       tot_weight += _weight[i];
00365     }
00366 
00367     Double_t pts_per_bin = tot_weight / _bins;
00368     
00369     Double_t xold;
00370     Double_t xnew = 0;
00371     Double_t dw = 0;    
00372 
00373     UInt_t k;
00374     i = 1;
00375     for (k = 0; k < _bins; k++) {
00376       dw += _weight[k];
00377       xold = xnew;
00378       xnew = coord(k+1,j);
00379       
00380       while(dw > pts_per_bin) {
00381         dw -= pts_per_bin;
00382         newCoord(i++) = xnew - (xnew - xold) * dw / _weight[k];
00383       }
00384     }
00385     
00386     for (k = 1 ; k < _bins ; k++) {
00387       coord( k, j) = newCoord(k);
00388     }
00389     
00390     coord(_bins, j) = 1;
00391   }
00392 }

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