DistSampler.cxx

Go to the documentation of this file.
00001 // @(#)root/mathcore:$Id: DistSampler.cxx 37232 2010-12-03 18:09:43Z moneta $
00002 // Author: L. Moneta Fri Sep 22 15:06:47 2006
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // implementation file for class DistSampler
00012 
00013 #include "Math/DistSampler.h"
00014 #include "Math/DistSamplerOptions.h"
00015 #include "Math/Error.h"
00016 
00017 #include "Math/IFunction.h"
00018 #include "Fit/BinData.h"
00019 #include "Fit/UnBinData.h"
00020 #include "Fit/DataRange.h"
00021 
00022 
00023 namespace ROOT { 
00024    
00025 
00026 namespace Math { 
00027 
00028 DistSampler::~DistSampler() { 
00029    // destructor 
00030    if (fOwnFunc && fFunc != 0) delete fFunc; 
00031    if (fRange) delete fRange;
00032 }
00033 
00034 bool DistSampler::Init(const DistSamplerOptions & opt ) { 
00035    // default initialization with algorithm name
00036    return Init(opt.Algorithm().c_str() );
00037 }
00038 
00039 void DistSampler::SetRange(double xmin, double xmax, int icoord) {
00040    if (!fRange) { 
00041       MATH_ERROR_MSG("DistSampler::SetRange","Need to set function before setting the range");
00042       return;
00043    }
00044    fRange->SetRange(icoord,xmin,xmax);
00045 }
00046 
00047 void DistSampler::SetRange(const double * xmin, const double * xmax) {
00048    // set range specifying a vector for all coordinates 
00049    if (!fRange) {
00050       MATH_ERROR_MSG("DistSampler::SetRange","Need to set function before setting the range");
00051       return;
00052    }
00053    for (unsigned int icoord = 0; icoord < NDim(); ++icoord) 
00054       fRange->SetRange(icoord,xmin[icoord],xmax[icoord]);
00055 }
00056 
00057 void DistSampler::SetRange(const ROOT::Fit::DataRange & range) {
00058    // copy the given range
00059    *fRange = range;  
00060 }
00061 
00062 void DistSampler::DoSetFunction(const ROOT::Math::IMultiGenFunction & func, bool copy) { 
00063    // set the internal function
00064    // if a range exists and it is compatible it will be re-used
00065    if (fOwnFunc && fFunc != 0) delete fFunc; 
00066    if (copy) {
00067       fOwnFunc = true; 
00068       fFunc = func.Clone(); 
00069    }
00070    else {
00071       fOwnFunc = false; 
00072       fFunc = &func; 
00073    }
00074    fData = std::vector<double>(func.NDim());
00075    // delete a range if exists and it is not compatible
00076    if (fRange && fRange->NDim() != fData.size() ) {
00077       delete fRange; 
00078       fRange = 0; 
00079    }
00080    if (!fRange) fRange = new ROOT::Fit::DataRange(func.NDim() );
00081 }
00082 
00083 bool DistSampler::IsInitialized()  { 
00084    // test if sampler is initialized
00085    // tryying to generate one event (for this cannot be const) 
00086    if (NDim() == 0) return false; 
00087    if (fFunc == 0) return false; 
00088    if (fFunc->NDim() != NDim() ) return false; 
00089    // test one event 
00090    if (!Sample(&fData[0]) ) return false; 
00091    return true;
00092 }
00093 
00094 bool DistSampler::Generate(unsigned int nevt, ROOT::Fit::UnBinData & data) { 
00095    // generate a un-binned data sets (fill the given data set)
00096    // if dataset has already data append to it 
00097    int n0 = data.DataSize(); 
00098    if (n0 > 0 ) { 
00099       if (data.PointSize() != NDim() ) {
00100          MATH_ERROR_MSG("DistSampler::Generate","unbin data not consistent with distribution");
00101          return false; 
00102       }
00103    }
00104    if (!IsInitialized()) { 
00105          MATH_WARN_MSG("DistSampler::Generate","sampler has not been initialized correctly");
00106          return false; 
00107    }
00108 
00109    data.Initialize( n0 + nevt, NDim() );
00110    for (unsigned int i = 0; i < nevt; ++i) { 
00111       const double * x = Sample(); 
00112       data.Add( x ); 
00113    }
00114    return true;
00115 }
00116 
00117 
00118    bool DistSampler::Generate(unsigned int nevt, const  int * nbins, ROOT::Fit::BinData & data, bool extend) { 
00119    // generate a bin data set from given bin center values 
00120    // bin center values must be present in given data set 
00121    //if (!IsInitialized()) { 
00122    if (NDim() == 0 || fFunc == 0 ) {
00123       MATH_WARN_MSG("DistSampler::Generate","sampler has not been initialized correctly");
00124       return false; 
00125    }
00126    
00127 
00128    int ntotbins = 1;
00129    for (unsigned int j = 0; j < NDim(); ++j) { 
00130       ntotbins *= nbins[j];
00131    }
00132 
00133    data.Initialize(ntotbins, NDim(), ROOT::Fit::BinData::kValueError);    // store always the error
00134    // use for the moment bin center (should use bin integral) 
00135    std::vector<double> dx(NDim() );
00136    std::vector<double> x(NDim() );
00137    double binVolume = 1;
00138    for (unsigned int j = 0; j < dx.size(); ++j) { 
00139       double x1 = 0,x2 = 0; 
00140       if (!fRange || !fRange->Size(j)) { 
00141          MATH_WARN_MSG("DistSampler::Generate","sampler has not a range defined for all coordinates");
00142          return false; 
00143       }
00144       fRange->GetRange(j,x1,x2); 
00145       dx[j] =  (x2-x1)/double(nbins[j]); 
00146       assert(dx[j] > 0 && 1./dx[j] > 0 ); // avoid dx <= 0 and  not inf
00147       x[j] = x1 + dx[j]/2;  // use bin centers
00148       binVolume *= dx[j];
00149    }
00150    double nnorm = nevt * binVolume; 
00151 
00152    if (extend) { 
00153 
00154       bool ret = true;
00155       for (int j = NDim()-1; j >=0; --j) { 
00156          for (int i = 0; i < nbins[j]; ++i) { 
00157             //const double * v = Sample(); 
00158             double val = 0; 
00159             double eval = 0;
00160             double yval = (ParentPdf())(&x.front());
00161             double nexp = yval * nnorm;
00162             ret &= SampleBin(nexp,val,&eval);
00163             data.Add(&x.front(), val, eval); 
00164             x[j] += dx[j]; // increment x bin the bin
00165          }
00166          if (!ret) { 
00167             MATH_WARN_MSG("DistSampler::Generate","error returned from SampleBin");
00168             return false; 
00169          } 
00170       }
00171    }
00172    else { 
00173       MATH_WARN_MSG("DistSampler::Generate","generation with fixed events not yet impelmented");
00174       return false; 
00175    }
00176    return true;
00177 }
00178    
00179 } // end namespace Math
00180 } // end namespace ROOT

Generated on Tue Jul 5 14:33:22 2011 for ROOT_528-00b_version by  doxygen 1.5.1