Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TFoamSampler.cxx
Go to the documentation of this file.
1 // @(#)root/unuran:$Id$
2 // Authors: L. Moneta, Dec 2010
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2010 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Implementation file for class TFoamSampler
12 
13 #include "TFoamSampler.h"
15 
16 #include "TFoam.h"
17 #include "TFoamIntegrand.h"
19 #include "Math/IOptions.h"
20 #include "Fit/DataRange.h"
21 
22 #include "TRandom.h"
23 #include "TError.h"
24 
25 #include "TF1.h"
26 #include <cassert>
27 #include <cmath>
28 
29 class FoamDistribution : public TFoamIntegrand {
30 
31 public:
32 
33  FoamDistribution(const ROOT::Math::IMultiGenFunction & f, const ROOT::Fit::DataRange & range) :
34  fFunc(f),
35  fX(std::vector<double>(f.NDim() ) ),
36  fMinX(std::vector<double>(f.NDim() ) ),
37  fDeltaX(std::vector<double>(f.NDim() ) )
38  {
39  assert(f.NDim() == range.NDim() );
40  std::vector<double> xmax(f.NDim() );
41  for (unsigned int i = 0; i < range.NDim(); ++i) {
42  if (range.Size(i) == 0)
43  Error("FoamDistribution","Range is not set for coordinate dim %d",i);
44  else if (range.Size(i)>1)
45  Warning("FoamDistribution","Using only first range in coordinate dim %d",i);
46 
47  std::pair<double,double> r = range(i);
48  fMinX[i] = r.first;
49  fDeltaX[i] = r.second - r.first;
50  }
51  }
52  // in principle function does not need to be cloned
53 
54  virtual double Density(int ndim, double * x) {
55  assert(ndim == (int) fFunc.NDim() );
56  for (int i = 0; i < ndim; ++i)
57  fX[i] = fMinX[i] + x[i] * fDeltaX[i];
58 
59  return (fFunc)(&fX[0]);
60  }
61 
62  double MinX(unsigned int i) { return fMinX[i]; }
63  double DeltaX(unsigned int i) { return fDeltaX[i]; }
64 
65 private:
66 
67  const ROOT::Math::IMultiGenFunction & fFunc;
68  std::vector<double> fX;
69  std::vector<double> fMinX;
70  std::vector<double> fDeltaX;
71 
72 };
73 
74 /** \class TFoamSampler
75  class implementing the ROOT::Math::DistSampler interface using FOAM
76  for sampling arbitrary distributions.
77 */
78 
79 ClassImp(TFoamSampler);
80 
81 
82 TFoamSampler::TFoamSampler() : ROOT::Math::DistSampler(),
83 // fOneDim(false)
84 // fDiscrete(false),
85 // fHasMode(false), fHasArea(false),
86 // fMode(0), fArea(0),
87  fFunc1D(0),
88  fFoam(new TFoam("FOAM") ),
89  fFoamDist(0)
90 {}
91 
92 TFoamSampler::~TFoamSampler() {
93  assert(fFoam != 0);
94  delete fFoam;
95  if (fFoamDist) delete fFoamDist;
96 }
97 
98 bool TFoamSampler::Init(const char *) {
99 
100  // initialize using default options
101  ROOT::Math::DistSamplerOptions opt(0);
102  ROOT::Math::IOptions * foamOpt = ROOT::Math::DistSamplerOptions::FindDefault("Foam");
103  if (foamOpt) opt.SetExtraOptions(*foamOpt);
104  return Init(opt);
105 }
106 
107 bool TFoamSampler::Init(const ROOT::Math::DistSamplerOptions & opt) {
108  // initialize foam classes using the given algorithm
109  assert (fFoam != 0 );
110  if (NDim() == 0) {
111  Error("TFoamSampler::Init","Distribution function has not been set ! Need to call SetFunction first.");
112  return false;
113  }
114 
115  // initialize the foam
116  fFoam->SetkDim(NDim() );
117 
118  // initialize random number
119  if (!GetRandom()) SetRandom(gRandom);
120 
121  // create TFoamIntegrand class
122  if (fFoamDist) delete fFoamDist;
123  fFoamDist = new FoamDistribution(ParentPdf(),PdfRange());
124 
125  fFoam->SetRho(fFoamDist);
126  // set print level
127  fFoam->SetChat(opt.PrintLevel());
128 
129  // get extra options
130  ROOT::Math::IOptions * fopt = opt.ExtraOptions();
131  if (fopt) {
132  int nval = 0;
133  double fval = 0;
134  if (fopt->GetIntValue("nCells", nval) ) fFoam->SetnCells(nval);
135  if (fopt->GetIntValue("nCell1D", nval) && NDim() ==1) fFoam->SetnCells(nval);
136  if (fopt->GetIntValue("nCellND", nval) && NDim() >1) fFoam->SetnCells(nval);
137  if (fopt->GetIntValue("nCell2D", nval) && NDim() ==2) fFoam->SetnCells(nval);
138  if (fopt->GetIntValue("nCell3D", nval) && NDim() ==3) fFoam->SetnCells(nval);
139 
140  if (fopt->GetIntValue("nSample", nval) ) fFoam->SetnSampl(nval);
141  if (fopt->GetIntValue("nBin", nval) ) fFoam->SetnBin(nval);
142  if (fopt->GetIntValue("OptDrive",nval) ) fFoam->SetOptDrive(nval);
143  if (fopt->GetIntValue("OptRej",nval) ) fFoam->SetOptRej(nval);
144  if (fopt->GetRealValue("MaxWtRej",fval) ) fFoam->SetMaxWtRej(fval);
145 
146 
147  if (fopt->GetIntValue("chatLevel", nval) ) fFoam->SetChat(nval);
148  }
149  fFoam->Initialize();
150 
151  return true;
152 
153 }
154 
155 
156 void TFoamSampler::SetFunction(TF1 * pdf) {
157  // set function from a TF1 pointer
158  SetFunction<TF1>(*pdf, pdf->GetNdim());
159 }
160 
161 void TFoamSampler::SetRandom(TRandom * r) {
162  // set random generator (must be called before Init to have effect)
163  fFoam->SetPseRan(r);
164 }
165 
166 void TFoamSampler::SetSeed(unsigned int seed) {
167  // set random generator seed (must be called before Init to have effect)
168  TRandom * r = fFoam->GetPseRan();
169  if (r) r->SetSeed(seed);
170 }
171 
172 TRandom * TFoamSampler::GetRandom() {
173  // get random generator used
174  return fFoam->GetPseRan();
175 }
176 
177 // double TFoamSampler::Sample1D() {
178 // // sample 1D distributions
179 // return (fDiscrete) ? (double) fFoam->SampleDiscr() : fFoam->Sample();
180 // }
181 
182 bool TFoamSampler::Sample(double * x) {
183  // sample multi-dim distributions
184 
185  fFoam->MakeEvent();
186  fFoam->GetMCvect(x);
187  // adjust for the range
188  for (unsigned int i = 0; i < NDim(); ++i)
189  x[i] = ( (FoamDistribution*)fFoamDist)->MinX(i) + ( ( (FoamDistribution*) fFoamDist)->DeltaX(i))*x[i];
190 
191  return true;
192 }
193 
194 
195 bool TFoamSampler::SampleBin(double prob, double & value, double *error) {
196  // sample a bin according to Poisson statistics
197 
198  TRandom * r = GetRandom();
199  if (!r) return false;
200  value = r->Poisson(prob);
201  if (error) *error = std::sqrt(value);
202  return true;
203 }