00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "Math/DistSampler.h"
00014 #include "Math/DistSamplerOptions.h"
00015 #include "Math/Error.h"
00016
00017 #include "Math/IFunction.h"
00018 #include "Fit/BinData.h"
00019 #include "Fit/UnBinData.h"
00020 #include "Fit/DataRange.h"
00021
00022
00023 namespace ROOT {
00024
00025
00026 namespace Math {
00027
00028 DistSampler::~DistSampler() {
00029
00030 if (fOwnFunc && fFunc != 0) delete fFunc;
00031 if (fRange) delete fRange;
00032 }
00033
00034 bool DistSampler::Init(const DistSamplerOptions & opt ) {
00035
00036 return Init(opt.Algorithm().c_str() );
00037 }
00038
00039 void DistSampler::SetRange(double xmin, double xmax, int icoord) {
00040 if (!fRange) {
00041 MATH_ERROR_MSG("DistSampler::SetRange","Need to set function before setting the range");
00042 return;
00043 }
00044 fRange->SetRange(icoord,xmin,xmax);
00045 }
00046
00047 void DistSampler::SetRange(const double * xmin, const double * xmax) {
00048
00049 if (!fRange) {
00050 MATH_ERROR_MSG("DistSampler::SetRange","Need to set function before setting the range");
00051 return;
00052 }
00053 for (unsigned int icoord = 0; icoord < NDim(); ++icoord)
00054 fRange->SetRange(icoord,xmin[icoord],xmax[icoord]);
00055 }
00056
00057 void DistSampler::SetRange(const ROOT::Fit::DataRange & range) {
00058
00059 *fRange = range;
00060 }
00061
00062 void DistSampler::DoSetFunction(const ROOT::Math::IMultiGenFunction & func, bool copy) {
00063
00064
00065 if (fOwnFunc && fFunc != 0) delete fFunc;
00066 if (copy) {
00067 fOwnFunc = true;
00068 fFunc = func.Clone();
00069 }
00070 else {
00071 fOwnFunc = false;
00072 fFunc = &func;
00073 }
00074 fData = std::vector<double>(func.NDim());
00075
00076 if (fRange && fRange->NDim() != fData.size() ) {
00077 delete fRange;
00078 fRange = 0;
00079 }
00080 if (!fRange) fRange = new ROOT::Fit::DataRange(func.NDim() );
00081 }
00082
00083 bool DistSampler::IsInitialized() {
00084
00085
00086 if (NDim() == 0) return false;
00087 if (fFunc == 0) return false;
00088 if (fFunc->NDim() != NDim() ) return false;
00089
00090 if (!Sample(&fData[0]) ) return false;
00091 return true;
00092 }
00093
00094 bool DistSampler::Generate(unsigned int nevt, ROOT::Fit::UnBinData & data) {
00095
00096
00097 int n0 = data.DataSize();
00098 if (n0 > 0 ) {
00099 if (data.PointSize() != NDim() ) {
00100 MATH_ERROR_MSG("DistSampler::Generate","unbin data not consistent with distribution");
00101 return false;
00102 }
00103 }
00104 if (!IsInitialized()) {
00105 MATH_WARN_MSG("DistSampler::Generate","sampler has not been initialized correctly");
00106 return false;
00107 }
00108
00109 data.Initialize( n0 + nevt, NDim() );
00110 for (unsigned int i = 0; i < nevt; ++i) {
00111 const double * x = Sample();
00112 data.Add( x );
00113 }
00114 return true;
00115 }
00116
00117
00118 bool DistSampler::Generate(unsigned int nevt, const int * nbins, ROOT::Fit::BinData & data, bool extend) {
00119
00120
00121
00122 if (NDim() == 0 || fFunc == 0 ) {
00123 MATH_WARN_MSG("DistSampler::Generate","sampler has not been initialized correctly");
00124 return false;
00125 }
00126
00127
00128 int ntotbins = 1;
00129 for (unsigned int j = 0; j < NDim(); ++j) {
00130 ntotbins *= nbins[j];
00131 }
00132
00133 data.Initialize(ntotbins, NDim(), ROOT::Fit::BinData::kValueError);
00134
00135 std::vector<double> dx(NDim() );
00136 std::vector<double> x(NDim() );
00137 double binVolume = 1;
00138 for (unsigned int j = 0; j < dx.size(); ++j) {
00139 double x1 = 0,x2 = 0;
00140 if (!fRange || !fRange->Size(j)) {
00141 MATH_WARN_MSG("DistSampler::Generate","sampler has not a range defined for all coordinates");
00142 return false;
00143 }
00144 fRange->GetRange(j,x1,x2);
00145 dx[j] = (x2-x1)/double(nbins[j]);
00146 assert(dx[j] > 0 && 1./dx[j] > 0 );
00147 x[j] = x1 + dx[j]/2;
00148 binVolume *= dx[j];
00149 }
00150 double nnorm = nevt * binVolume;
00151
00152 if (extend) {
00153
00154 bool ret = true;
00155 for (int j = NDim()-1; j >=0; --j) {
00156 for (int i = 0; i < nbins[j]; ++i) {
00157
00158 double val = 0;
00159 double eval = 0;
00160 double yval = (ParentPdf())(&x.front());
00161 double nexp = yval * nnorm;
00162 ret &= SampleBin(nexp,val,&eval);
00163 data.Add(&x.front(), val, eval);
00164 x[j] += dx[j];
00165 }
00166 if (!ret) {
00167 MATH_WARN_MSG("DistSampler::Generate","error returned from SampleBin");
00168 return false;
00169 }
00170 }
00171 }
00172 else {
00173 MATH_WARN_MSG("DistSampler::Generate","generation with fixed events not yet impelmented");
00174 return false;
00175 }
00176 return true;
00177 }
00178
00179 }
00180 }