TFoamSampler.cxx

Go to the documentation of this file.
00001 // @(#)root/unuran:$Id: TFoamSampler.cxx 37419 2010-12-08 21:19:45Z moneta $
00002 // Authors: L. Moneta,  Dec 2010
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2010  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Implementation file for class TFoamSampler
00012 
00013 #include "TFoamSampler.h"
00014 #include "Math/DistSamplerOptions.h"
00015 
00016 #include "TFoam.h"
00017 #include "TFoamIntegrand.h"
00018 #include "Math/OneDimFunctionAdapter.h"
00019 #include "Math/IOptions.h"
00020 #include "Fit/DataRange.h"
00021 
00022 #include "TRandom.h"
00023 #include "TError.h"
00024 
00025 #include "TF1.h"
00026 #include <cassert>
00027 #include <cmath>
00028 
00029 class FoamDistribution : public TFoamIntegrand { 
00030 
00031 public:
00032 
00033    FoamDistribution(const ROOT::Math::IMultiGenFunction & f, const ROOT::Fit::DataRange & range) : 
00034       fFunc(f), 
00035       fX(std::vector<double>(f.NDim() ) ), 
00036       fMinX(std::vector<double>(f.NDim() ) ),
00037       fDeltaX(std::vector<double>(f.NDim() ) )
00038    {
00039       assert(f.NDim() == range.NDim() );
00040       std::vector<double> xmax(f.NDim() );
00041       for (unsigned int i = 0; i < range.NDim(); ++i) {
00042          if (range.Size(i) == 0)
00043             Error("FoamDistribution","Range is not set for coordinate dim %d",i);
00044          else if (range.Size(i)>1) 
00045             Warning("FoamDistribution","Using only first range in coordinate dim %d",i);
00046 
00047          std::pair<double,double> r = range(i); 
00048          fMinX[i] = r.first;
00049          fDeltaX[i] = r.second - r.first; 
00050       }
00051    } 
00052    // in principle function does not need to be cloned
00053 
00054    virtual double Density(int ndim, double * x) {
00055       assert(ndim == (int) fFunc.NDim() );
00056       for (int i = 0; i < ndim; ++i)
00057          fX[i] = fMinX[i] + x[i] * fDeltaX[i]; 
00058 
00059       return (fFunc)(&fX[0]);
00060    }
00061 
00062    double  MinX(unsigned int i) { return fMinX[i]; }
00063    double  DeltaX(unsigned int i) { return fDeltaX[i]; }
00064               
00065 private:
00066 
00067    const ROOT::Math::IMultiGenFunction & fFunc;
00068    std::vector<double> fX; 
00069    std::vector<double> fMinX; 
00070    std::vector<double> fDeltaX; 
00071 
00072 };
00073 
00074 
00075 
00076 ClassImp(TFoamSampler)
00077 
00078 
00079 //_______________________________________________________________________________
00080 /**
00081    TFoamSampler class
00082    class implementing  the ROOT::Math::DistSampler interface using FOAM
00083    for sampling arbitrary distributions. 
00084 
00085 
00086 */
00087 TFoamSampler::TFoamSampler() : ROOT::Math::DistSampler(), 
00088    fOneDim(false), 
00089 //    fDiscrete(false),
00090 //    fHasMode(false), fHasArea(false),
00091 //    fMode(0), fArea(0),
00092    fFunc1D(0),
00093    fFoam(new TFoam("FOAM")  ),
00094    fFoamDist(0)
00095 {}
00096 
00097 TFoamSampler::~TFoamSampler() {
00098    assert(fFoam != 0);
00099    delete fFoam; 
00100    if (fFoamDist) delete fFoamDist; 
00101 }
00102 
00103 bool TFoamSampler::Init(const char *) { 
00104 
00105    // initialize using default options
00106    ROOT::Math::DistSamplerOptions opt(0);
00107    ROOT::Math::IOptions * foamOpt  = ROOT::Math::DistSamplerOptions::FindDefault("Foam"); 
00108    if (foamOpt) opt.SetExtraOptions(*foamOpt); 
00109    return Init(opt);
00110 }
00111 
00112 bool TFoamSampler::Init(const ROOT::Math::DistSamplerOptions & opt) { 
00113    // initialize foam classes using the given algorithm
00114    assert (fFoam != 0 );
00115    if (NDim() == 0)  {
00116       Error("TFoamSampler::Init","Distribution function has not been set ! Need to call SetFunction first.");
00117       return false;
00118    }
00119 
00120    // initialize the foam 
00121    fFoam->SetkDim(NDim() );
00122 
00123    // initialize random number 
00124    if (!GetRandom()) SetRandom(gRandom);
00125 
00126    // create TFoamIntegrand class 
00127    if (fFoamDist) delete fFoamDist; 
00128    fFoamDist = new FoamDistribution(ParentPdf(),PdfRange());
00129 
00130    fFoam->SetRho(fFoamDist);
00131    // set print level
00132    fFoam->SetChat(opt.PrintLevel());
00133 
00134    // get extra options 
00135    ROOT::Math::IOptions * fopt = opt.ExtraOptions(); 
00136    if (fopt) { 
00137       int nval = 0; 
00138       double fval = 0;
00139       if (fopt->GetIntValue("nCells", nval) ) fFoam->SetnCells(nval);
00140       if (fopt->GetIntValue("nCell1D", nval) && NDim() ==1) fFoam->SetnCells(nval);
00141       if (fopt->GetIntValue("nCellND", nval) && NDim()  >1) fFoam->SetnCells(nval);
00142       if (fopt->GetIntValue("nCell2D", nval) && NDim() ==2) fFoam->SetnCells(nval);
00143       if (fopt->GetIntValue("nCell3D", nval) && NDim() ==3) fFoam->SetnCells(nval);
00144 
00145       if (fopt->GetIntValue("nSample", nval) ) fFoam->SetnSampl(nval);
00146       if (fopt->GetIntValue("nBin", nval) ) fFoam->SetnBin(nval);
00147       if (fopt->GetIntValue("OptDrive",nval) ) fFoam->SetOptDrive(nval);
00148       if (fopt->GetIntValue("OptRej",nval) ) fFoam->SetOptRej(nval);
00149       if (fopt->GetRealValue("MaxWtRej",fval) ) fFoam->SetMaxWtRej(fval);
00150 
00151 
00152       if (fopt->GetIntValue("chatLevel", nval) ) fFoam->SetChat(nval);
00153    }
00154    fFoam->Initialize();
00155 
00156    return true;
00157       
00158 }
00159 
00160 
00161 void TFoamSampler::SetFunction(TF1 * pdf) { 
00162    // set function from a TF1 pointer 
00163    SetFunction<TF1>(*pdf, pdf->GetNdim());
00164 } 
00165 
00166 void TFoamSampler::SetRandom(TRandom * r) { 
00167    // set random generator (must be called before Init to have effect)
00168    fFoam->SetPseRan(r); 
00169 } 
00170 
00171 void TFoamSampler::SetSeed(unsigned int seed) { 
00172    // set random generator seed (must be called before Init to have effect)
00173    TRandom * r = fFoam->GetPseRan();
00174    if (r) r->SetSeed(seed);
00175 } 
00176 
00177 TRandom * TFoamSampler::GetRandom() { 
00178    // get random generator used 
00179    return  fFoam->GetPseRan(); 
00180 } 
00181 
00182 // double TFoamSampler::Sample1D() { 
00183 //    // sample 1D distributions
00184 //    return (fDiscrete) ? (double) fFoam->SampleDiscr() : fFoam->Sample(); 
00185 // }
00186 
00187 bool TFoamSampler::Sample(double * x) { 
00188    // sample multi-dim distributions
00189 
00190    fFoam->MakeEvent();
00191    fFoam->GetMCvect(x);
00192    // adjust for the range   
00193    for (unsigned int i = 0; i < NDim(); ++i) 
00194       x[i] = ( (FoamDistribution*)fFoamDist)->MinX(i) + ( ( (FoamDistribution*) fFoamDist)->DeltaX(i))*x[i];
00195 
00196    return true; 
00197 } 
00198 
00199 
00200 bool TFoamSampler::SampleBin(double prob, double & value, double *error) {
00201    // sample a bin according to Poisson statistics
00202 
00203    TRandom * r = GetRandom(); 
00204    if (!r) return false; 
00205    value = r->Poisson(prob); 
00206    if (error) *error = std::sqrt(value);
00207    return true; 
00208 }

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