Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
DistSampler.cxx
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Author: L. Moneta Fri Sep 22 15:06:47 2006
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // implementation file for class DistSampler
12 
13 #include "Math/DistSampler.h"
15 #include "Math/Error.h"
16 
17 #include "Math/IFunction.h"
18 #include "Math/IFunctionfwd.h"
19 #include "Fit/BinData.h"
20 #include "Fit/UnBinData.h"
21 #include "Fit/DataRange.h"
22 
23 
24 namespace ROOT {
25 
26 
27 namespace Math {
28 
29 DistSampler::~DistSampler() {
30  // destructor
31  if (fOwnFunc && fFunc != 0) delete fFunc;
32  if (fRange) delete fRange;
33 }
34 
35 bool DistSampler::Init(const DistSamplerOptions & opt ) {
36  // default initialization with algorithm name
37  return Init(opt.Algorithm().c_str() );
38 }
39 
40 void DistSampler::SetRange(double xmin, double xmax, int icoord) {
41  if (!fRange) {
42  MATH_ERROR_MSG("DistSampler::SetRange","Need to set function before setting the range");
43  return;
44  }
45  fRange->SetRange(icoord,xmin,xmax);
46 }
47 
48 void DistSampler::SetRange(const double * xmin, const double * xmax) {
49  // set range specifying a vector for all coordinates
50  if (!fRange) {
51  MATH_ERROR_MSG("DistSampler::SetRange","Need to set function before setting the range");
52  return;
53  }
54  for (unsigned int icoord = 0; icoord < NDim(); ++icoord)
55  fRange->SetRange(icoord,xmin[icoord],xmax[icoord]);
56 }
57 
58 void DistSampler::SetRange(const ROOT::Fit::DataRange & range) {
59  // copy the given range
60  *fRange = range;
61 }
62 
63 void DistSampler::DoSetFunction(const ROOT::Math::IMultiGenFunction & func, bool copy) {
64  // set the internal function
65  // if a range exists and it is compatible it will be re-used
66  if (fOwnFunc && fFunc != 0) delete fFunc;
67  if (copy) {
68  fOwnFunc = true;
69  fFunc = func.Clone();
70  }
71  else {
72  fOwnFunc = false;
73  fFunc = &func;
74  }
75  fData = std::vector<double>(func.NDim());
76  // delete a range if exists and it is not compatible
77  if (fRange && fRange->NDim() != fData.size() ) {
78  delete fRange;
79  fRange = 0;
80  }
81  if (!fRange) fRange = new ROOT::Fit::DataRange(func.NDim() );
82 }
83 
84 bool DistSampler::IsInitialized() {
85  // test if sampler is initialized
86  // tryying to generate one event (for this cannot be const)
87  if (NDim() == 0) return false;
88  if (fFunc == 0) return false;
89  if (fFunc->NDim() != NDim() ) return false;
90  // test one event
91  if (!Sample(&fData[0]) ) return false;
92  return true;
93 }
94 
95 bool DistSampler::Generate(unsigned int nevt, ROOT::Fit::UnBinData & data) {
96  // generate a un-binned data sets (fill the given data set)
97  // if dataset has already data append to it
98  if (!IsInitialized()) {
99  MATH_WARN_MSG("DistSampler::Generate","sampler has not been initialized correctly");
100  return false;
101  }
102 
103  data.Append( nevt, NDim() );
104  for (unsigned int i = 0; i < nevt; ++i) {
105  const double * x = Sample();
106  data.Add( x );
107  }
108  return true;
109 }
110 
111 
112  bool DistSampler::Generate(unsigned int nevt, const int * nbins, ROOT::Fit::BinData & data, bool extend) {
113  // generate a bin data set from given bin center values
114  // bin center values must be present in given data set
115  //if (!IsInitialized()) {
116  if (NDim() == 0 || fFunc == 0 ) {
117  MATH_WARN_MSG("DistSampler::Generate","sampler has not been initialized correctly");
118  return false;
119  }
120 
121 
122  int ntotbins = 1;
123  for (unsigned int j = 0; j < NDim(); ++j) {
124  ntotbins *= nbins[j];
125  }
126 
127  data.Append(ntotbins, NDim(), ROOT::Fit::BinData::kValueError); // store always the error
128  // use for the moment bin center (should use bin integral)
129  std::vector<double> dx(NDim() );
130  std::vector<double> x(NDim() );
131  double binVolume = 1;
132  for (unsigned int j = 0; j < dx.size(); ++j) {
133  double x1 = 0,x2 = 0;
134  if (!fRange || !fRange->Size(j)) {
135  MATH_WARN_MSG("DistSampler::Generate","sampler has not a range defined for all coordinates");
136  return false;
137  }
138  fRange->GetRange(j,x1,x2);
139  dx[j] = (x2-x1)/double(nbins[j]);
140  assert(dx[j] > 0 && 1./dx[j] > 0 ); // avoid dx <= 0 and not inf
141  x[j] = x1 + dx[j]/2; // use bin centers
142  binVolume *= dx[j];
143  }
144  double nnorm = nevt * binVolume;
145 
146  if (extend) {
147 
148  bool ret = true;
149  for (int j = NDim()-1; j >=0; --j) {
150  for (int i = 0; i < nbins[j]; ++i) {
151  //const double * v = Sample();
152  double val = 0;
153  double eval = 0;
154  double yval = (ParentPdf())(&x.front());
155  double nexp = yval * nnorm;
156  ret &= SampleBin(nexp,val,&eval);
157  data.Add(&x.front(), val, eval);
158  x[j] += dx[j]; // increment x bin the bin
159  }
160  if (!ret) {
161  MATH_WARN_MSG("DistSampler::Generate","error returned from SampleBin");
162  return false;
163  }
164  }
165  }
166  else {
167  MATH_WARN_MSG("DistSampler::Generate","generation with fixed events not yet impelmented");
168  return false;
169  }
170  return true;
171 }
172 
173 } // end namespace Math
174 } // end namespace ROOT