00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TUnuranSampler.h"
00013
00014 #include "TUnuranContDist.h"
00015 #include "TUnuranDiscrDist.h"
00016 #include "TUnuranMultiContDist.h"
00017 #include "TUnuran.h"
00018 #include "Math/OneDimFunctionAdapter.h"
00019 #include "Math/DistSamplerOptions.h"
00020 #include "Fit/DataRange.h"
00021
00022
00023 #include "TRandom.h"
00024 #include "TError.h"
00025
00026 #include "TF1.h"
00027 #include <cassert>
00028 #include <cmath>
00029
00030 ClassImp(TUnuranSampler)
00031
00032 TUnuranSampler::TUnuranSampler() : ROOT::Math::DistSampler(),
00033 fOneDim(false),
00034 fDiscrete(false),
00035 fHasMode(false), fHasArea(false),
00036 fMode(0), fArea(0),
00037 fFunc1D(0),
00038 fUnuran(new TUnuran() )
00039 {
00040 fLevel = ROOT::Math::DistSamplerOptions::DefaultPrintLevel();
00041 }
00042
00043 TUnuranSampler::~TUnuranSampler() {
00044 assert(fUnuran != 0);
00045 delete fUnuran;
00046 }
00047
00048 bool TUnuranSampler::Init(const char * algo) {
00049
00050 assert (fUnuran != 0 );
00051 if (NDim() == 0) {
00052 Error("TUnuranSampler::Init","Distribution function has not been set ! Need to call SetFunction first.");
00053 return false;
00054 }
00055
00056 if (fLevel < 0) fLevel = ROOT::Math::DistSamplerOptions::DefaultPrintLevel();
00057
00058 TString method(algo);
00059 if (method.IsNull() ) {
00060 if (NDim() == 1) method = ROOT::Math::DistSamplerOptions::DefaultAlgorithm1D();
00061 else method = ROOT::Math::DistSamplerOptions::DefaultAlgorithmND();
00062 }
00063 method.ToUpper();
00064
00065 bool ret = false;
00066 if (NDim() == 1) {
00067
00068
00069 if (method.First("D") == 0) {
00070 if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim discrete distribution with method %s",method.Data());
00071 ret = DoInitDiscrete1D(method);
00072 }
00073 else {
00074 if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim continous distribution with method %s",method.Data());
00075 ret = DoInit1D(method);
00076 }
00077 }
00078 else {
00079 if (fLevel>1) Info("TUnuranSampler::Init","Initialize multi-dim continous distribution with method %s",method.Data());
00080 ret = DoInitND(method);
00081 }
00082
00083 if (fLevel>0) {
00084
00085 if (ret) Info("TUnuranSampler::Init","Successfully initailized Unuran with method %s",method.Data() );
00086 else Error("TUnuranSampler::Init","Failed to initailize Unuran with method %s",method.Data() );
00087
00088 }
00089 return ret;
00090 }
00091
00092
00093 bool TUnuranSampler::Init(const ROOT::Math::DistSamplerOptions & opt ) {
00094
00095 SetPrintLevel(opt.PrintLevel() );
00096 return Init(opt.Algorithm().c_str() );
00097 }
00098
00099
00100 bool TUnuranSampler::DoInit1D(const char * method) {
00101
00102
00103
00104 fOneDim = true;
00105 TUnuranContDist * dist = 0;
00106 if (fFunc1D == 0) {
00107 ROOT::Math::OneDimMultiFunctionAdapter<> function(ParentPdf() );
00108 dist = new TUnuranContDist(function,0,false,true);
00109 }
00110 else {
00111 dist = new TUnuranContDist(*fFunc1D);
00112 }
00113
00114 const ROOT::Fit::DataRange & range = PdfRange();
00115 if (range.Size(0) > 0) {
00116 double xmin, xmax;
00117 range.GetRange(0,xmin,xmax);
00118 dist->SetDomain(xmin,xmax);
00119 }
00120 if (fHasMode) dist->SetMode(fMode);
00121 if (fHasArea) dist->SetPdfArea(fArea);
00122
00123 bool ret = false;
00124 if (method) ret = fUnuran->Init(*dist, method);
00125 else ret = fUnuran->Init(*dist);
00126 delete dist;
00127 return ret;
00128 }
00129
00130 bool TUnuranSampler::DoInitDiscrete1D(const char * method) {
00131
00132 fOneDim = true;
00133 fDiscrete = true;
00134 TUnuranDiscrDist * dist = 0;
00135 if (fFunc1D == 0) {
00136
00137 ROOT::Math::OneDimMultiFunctionAdapter<> function(ParentPdf() );
00138 dist = new TUnuranDiscrDist(function,true);
00139 }
00140 else {
00141
00142 dist = new TUnuranDiscrDist(*fFunc1D, false);
00143 }
00144
00145
00146 const ROOT::Fit::DataRange & range = PdfRange();
00147 if (range.Size(0) > 0) {
00148 double xmin, xmax;
00149 range.GetRange(0,xmin,xmax);
00150 if (xmin < 0) {
00151 Warning("DoInitDiscrete1D","range starts from negative values - set minimum to zero");
00152 xmin = 0;
00153 }
00154 dist->SetDomain(int(xmin+0.1),int(xmax+0.1));
00155 }
00156 if (fHasMode) dist->SetMode(int(fMode+0.1));
00157 if (fHasArea) dist->SetProbSum(fArea);
00158
00159 bool ret = fUnuran->Init(*dist, method);
00160 delete dist;
00161 return ret;
00162 }
00163
00164
00165 bool TUnuranSampler::DoInitND(const char * method) {
00166
00167 TUnuranMultiContDist dist(ParentPdf());
00168
00169 const ROOT::Fit::DataRange & range = PdfRange();
00170 if (range.IsSet()) {
00171 std::vector<double> xmin(range.NDim() );
00172 std::vector<double> xmax(range.NDim() );
00173 range.GetRange(&xmin[0],&xmax[0]);
00174 dist.SetDomain(&xmin.front(),&xmax.front());
00175
00176
00177
00178
00179
00180 }
00181 fOneDim = false;
00182 if (method) return fUnuran->Init(dist, method);
00183 return fUnuran->Init(dist);
00184 }
00185
00186 void TUnuranSampler::SetFunction(TF1 * pdf) {
00187
00188 SetFunction<TF1>(*pdf, pdf->GetNdim());
00189 }
00190
00191 void TUnuranSampler::SetRandom(TRandom * r) {
00192
00193 fUnuran->SetRandom(r);
00194 }
00195
00196 void TUnuranSampler::SetSeed(unsigned int seed) {
00197
00198 fUnuran->SetSeed(seed);
00199 }
00200
00201 TRandom * TUnuranSampler::GetRandom() {
00202
00203 return fUnuran->GetRandom();
00204 }
00205
00206 double TUnuranSampler::Sample1D() {
00207
00208 return (fDiscrete) ? (double) fUnuran->SampleDiscr() : fUnuran->Sample();
00209 }
00210
00211 bool TUnuranSampler::Sample(double * x) {
00212
00213 if (!fOneDim) return fUnuran->SampleMulti(x);
00214 x[0] = Sample1D();
00215 return true;
00216 }
00217
00218
00219 bool TUnuranSampler::SampleBin(double prob, double & value, double *error) {
00220
00221
00222 TRandom * r = fUnuran->GetRandom();
00223 if (!r) return false;
00224 value = r->Poisson(prob);
00225 if (error) *error = std::sqrt(value);
00226 return true;
00227 }