TUnuranSampler.cxx

Go to the documentation of this file.
00001 // @(#)root/unuran:$Id: TUnuranSampler.cxx 37419 2010-12-08 21:19:45Z moneta $
00002 // Authors: L. Moneta, J. Leydold Wed Feb 28 2007
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2010  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Implementation file for class TUnuranSampler
00012 #include "TUnuranSampler.h"
00013 
00014 #include "TUnuranContDist.h"
00015 #include "TUnuranDiscrDist.h"
00016 #include "TUnuranMultiContDist.h"
00017 #include "TUnuran.h"
00018 #include "Math/OneDimFunctionAdapter.h"
00019 #include "Math/DistSamplerOptions.h"
00020 #include "Fit/DataRange.h"
00021 //#include "Math/WrappedTF1.h"
00022 
00023 #include "TRandom.h"
00024 #include "TError.h"
00025 
00026 #include "TF1.h"
00027 #include <cassert>
00028 #include <cmath>
00029 
00030 ClassImp(TUnuranSampler)
00031 
00032 TUnuranSampler::TUnuranSampler() : ROOT::Math::DistSampler(), 
00033    fOneDim(false), 
00034    fDiscrete(false),
00035    fHasMode(false), fHasArea(false),
00036    fMode(0), fArea(0),
00037    fFunc1D(0),
00038    fUnuran(new TUnuran()  )
00039 {
00040    fLevel = ROOT::Math::DistSamplerOptions::DefaultPrintLevel();
00041 }
00042 
00043 TUnuranSampler::~TUnuranSampler() {
00044    assert(fUnuran != 0);
00045    delete fUnuran; 
00046 }
00047 
00048 bool TUnuranSampler::Init(const char * algo) { 
00049    // initialize unuran classes using the given algorithm
00050    assert (fUnuran != 0 );
00051    if (NDim() == 0)  {
00052       Error("TUnuranSampler::Init","Distribution function has not been set ! Need to call SetFunction first.");
00053       return false;
00054    }
00055 
00056    if (fLevel < 0) fLevel =  ROOT::Math::DistSamplerOptions::DefaultPrintLevel();
00057 
00058    TString method(algo); 
00059    if (method.IsNull() ) { 
00060       if (NDim() == 1) method = ROOT::Math::DistSamplerOptions::DefaultAlgorithm1D();
00061       else  method = ROOT::Math::DistSamplerOptions::DefaultAlgorithmND();
00062    }
00063    method.ToUpper();
00064 
00065    bool ret = false; 
00066    if (NDim() == 1) { 
00067        // check if distribution is discrete by 
00068       // using first string in the method name is "D"
00069       if (method.First("D") == 0) { 
00070          if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim discrete distribution with method %s",method.Data());
00071          ret =  DoInitDiscrete1D(method);
00072       }
00073       else {
00074          if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim continous distribution with method %s",method.Data());
00075          ret =  DoInit1D(method); 
00076       }
00077    }
00078    else { 
00079       if (fLevel>1) Info("TUnuranSampler::Init","Initialize multi-dim continous distribution with method %s",method.Data());
00080       ret = DoInitND(method); 
00081    }
00082    // set print level in UNURAN (must be done after having initialized) -
00083    if (fLevel>0) { 
00084       //fUnuran->SetLogLevel(fLevel); ( seems not to work  disable for the time being) 
00085       if (ret) Info("TUnuranSampler::Init","Successfully initailized Unuran with method %s",method.Data() );
00086       else Error("TUnuranSampler::Init","Failed to  initailize Unuran with method %s",method.Data() );
00087       // seems not to work in UNURAN (cll only when level > 0 )
00088    }
00089    return ret; 
00090 }
00091 
00092 
00093 bool TUnuranSampler::Init(const ROOT::Math::DistSamplerOptions & opt ) { 
00094    // default initialization with algorithm name
00095    SetPrintLevel(opt.PrintLevel() );
00096    return Init(opt.Algorithm().c_str() );
00097 }
00098 
00099 
00100 bool TUnuranSampler::DoInit1D(const char * method) { 
00101    // initilize for 1D sampling
00102    // need to create 1D interface from Multidim one 
00103    // (to do: use directly 1D functions ??)
00104    fOneDim = true; 
00105    TUnuranContDist * dist = 0;
00106    if (fFunc1D == 0) { 
00107       ROOT::Math::OneDimMultiFunctionAdapter<> function(ParentPdf() ); 
00108       dist = new TUnuranContDist(function,0,false,true); 
00109    }
00110    else { 
00111       dist = new TUnuranContDist(*fFunc1D); // no need to copy the function
00112    }
00113    // set range in distribution (support only one range)
00114    const ROOT::Fit::DataRange & range = PdfRange(); 
00115    if (range.Size(0) > 0) { 
00116       double xmin, xmax; 
00117       range.GetRange(0,xmin,xmax); 
00118       dist->SetDomain(xmin,xmax); 
00119    }
00120    if (fHasMode) dist->SetMode(fMode);
00121    if (fHasArea) dist->SetPdfArea(fArea);
00122 
00123    bool ret = false; 
00124    if (method) ret =  fUnuran->Init(*dist, method);       
00125    else ret =  fUnuran->Init(*dist);
00126    delete dist; 
00127    return ret; 
00128 }
00129 
00130 bool TUnuranSampler::DoInitDiscrete1D(const char * method) { 
00131    // initilize for 1D sampling of discrete distributions
00132    fOneDim = true; 
00133    fDiscrete = true;
00134    TUnuranDiscrDist * dist = 0;
00135    if (fFunc1D == 0) { 
00136       // need to copy the passed function pointer in this case
00137       ROOT::Math::OneDimMultiFunctionAdapter<> function(ParentPdf() ); 
00138       dist = new TUnuranDiscrDist(function,true); 
00139    }
00140    else { 
00141       // no need to copy the function since fFunc1D is managed outside
00142       dist = new TUnuranDiscrDist(*fFunc1D, false); 
00143    }
00144    // set range in distribution (support only one range)
00145    // otherwise 0, inf is assumed
00146    const ROOT::Fit::DataRange & range = PdfRange(); 
00147    if (range.Size(0) > 0) { 
00148       double xmin, xmax; 
00149       range.GetRange(0,xmin,xmax);
00150       if (xmin < 0) { 
00151          Warning("DoInitDiscrete1D","range starts from negative values - set minimum to zero"); 
00152          xmin = 0; 
00153       }
00154       dist->SetDomain(int(xmin+0.1),int(xmax+0.1)); 
00155    }
00156    if (fHasMode) dist->SetMode(int(fMode+0.1));
00157    if (fHasArea) dist->SetProbSum(fArea);
00158 
00159    bool ret =  fUnuran->Init(*dist, method);       
00160    delete dist;
00161    return ret;
00162 }
00163 
00164 
00165 bool TUnuranSampler::DoInitND(const char * method) { 
00166    // initilize for 1D sampling
00167    TUnuranMultiContDist dist(ParentPdf()); 
00168    // set range in distribution (support only one range)
00169    const ROOT::Fit::DataRange & range = PdfRange(); 
00170    if (range.IsSet()) { 
00171       std::vector<double> xmin(range.NDim() ); 
00172       std::vector<double> xmax(range.NDim() ); 
00173       range.GetRange(&xmin[0],&xmax[0]); 
00174       dist.SetDomain(&xmin.front(),&xmax.front());
00175 //       std::cout << " range is min = "; 
00176 //       for (int j = 0; j < NDim(); ++j) std::cout << xmin[j] << "   "; 
00177 //       std::cout << " max = "; 
00178 //       for (int j = 0; j < NDim(); ++j) std::cout << xmax[j] << "   "; 
00179 //       std::cout << std::endl;
00180    }
00181    fOneDim = false; 
00182    if (method) return fUnuran->Init(dist, method); 
00183    return fUnuran->Init(dist);
00184 }
00185 
00186 void TUnuranSampler::SetFunction(TF1 * pdf) { 
00187    // set function from a TF1 pointer 
00188    SetFunction<TF1>(*pdf, pdf->GetNdim());
00189 } 
00190 
00191 void TUnuranSampler::SetRandom(TRandom * r) { 
00192    // set random generator (must be called before Init to have effect)
00193    fUnuran->SetRandom(r); 
00194 } 
00195 
00196 void TUnuranSampler::SetSeed(unsigned int seed) { 
00197    // set random generator seed (must be called before Init to have effect)
00198    fUnuran->SetSeed(seed); 
00199 } 
00200 
00201 TRandom * TUnuranSampler::GetRandom() { 
00202    // get random generator used 
00203    return  fUnuran->GetRandom(); 
00204 } 
00205 
00206 double TUnuranSampler::Sample1D() { 
00207    // sample 1D distributions
00208    return (fDiscrete) ? (double) fUnuran->SampleDiscr() : fUnuran->Sample(); 
00209 }
00210 
00211 bool TUnuranSampler::Sample(double * x) { 
00212    // sample multi-dim distributions
00213    if (!fOneDim) return fUnuran->SampleMulti(x); 
00214    x[0] = Sample1D(); 
00215    return true; 
00216 } 
00217 
00218 
00219 bool TUnuranSampler::SampleBin(double prob, double & value, double *error) {
00220    // sample a bin according to Poisson statistics
00221 
00222    TRandom * r = fUnuran->GetRandom(); 
00223    if (!r) return false; 
00224    value = r->Poisson(prob); 
00225    if (error) *error = std::sqrt(value);
00226    return true; 
00227 }

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