00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
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
00082
00083
00084
00085
00086
00087 TFoamSampler::TFoamSampler() : ROOT::Math::DistSampler(),
00088 fOneDim(false),
00089
00090
00091
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
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
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
00121 fFoam->SetkDim(NDim() );
00122
00123
00124 if (!GetRandom()) SetRandom(gRandom);
00125
00126
00127 if (fFoamDist) delete fFoamDist;
00128 fFoamDist = new FoamDistribution(ParentPdf(),PdfRange());
00129
00130 fFoam->SetRho(fFoamDist);
00131
00132 fFoam->SetChat(opt.PrintLevel());
00133
00134
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
00163 SetFunction<TF1>(*pdf, pdf->GetNdim());
00164 }
00165
00166 void TFoamSampler::SetRandom(TRandom * r) {
00167
00168 fFoam->SetPseRan(r);
00169 }
00170
00171 void TFoamSampler::SetSeed(unsigned int seed) {
00172
00173 TRandom * r = fFoam->GetPseRan();
00174 if (r) r->SetSeed(seed);
00175 }
00176
00177 TRandom * TFoamSampler::GetRandom() {
00178
00179 return fFoam->GetPseRan();
00180 }
00181
00182
00183
00184
00185
00186
00187 bool TFoamSampler::Sample(double * x) {
00188
00189
00190 fFoam->MakeEvent();
00191 fFoam->GetMCvect(x);
00192
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
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 }