ROOT logo
// @(#)root/unuran:$Id$
// Authors: L. Moneta, J. Leydold Wed Feb 28 2007

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2010  LCG ROOT Math Team, CERN/PH-SFT                *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Implementation file for class TUnuranSampler
#include "TUnuranSampler.h"

#include "TUnuranContDist.h"
#include "TUnuranDiscrDist.h"
#include "TUnuranMultiContDist.h"
#include "TUnuran.h"
#include "Math/OneDimFunctionAdapter.h"
#include "Math/DistSamplerOptions.h"
#include "Fit/DataRange.h"
//#include "Math/WrappedTF1.h"

#include "TRandom.h"
#include "TError.h"

#include "TF1.h"
#include <cassert>
#include <cmath>

ClassImp(TUnuranSampler)

TUnuranSampler::TUnuranSampler() : ROOT::Math::DistSampler(), 
   fOneDim(false), 
   fDiscrete(false),
   fHasMode(false), fHasArea(false),
   fMode(0), fArea(0),
   fFunc1D(0),
   fUnuran(new TUnuran()  )
{
   fLevel = ROOT::Math::DistSamplerOptions::DefaultPrintLevel();
}

TUnuranSampler::~TUnuranSampler() {
   assert(fUnuran != 0);
   delete fUnuran; 
}

bool TUnuranSampler::Init(const char * algo) { 
   // initialize unuran classes using the given algorithm
   assert (fUnuran != 0 );
   if (NDim() == 0)  {
      Error("TUnuranSampler::Init","Distribution function has not been set ! Need to call SetFunction first.");
      return false;
   }

   if (fLevel < 0) fLevel =  ROOT::Math::DistSamplerOptions::DefaultPrintLevel();

   TString method(algo); 
   if (method.IsNull() ) { 
      if (NDim() == 1) method = ROOT::Math::DistSamplerOptions::DefaultAlgorithm1D();
      else  method = ROOT::Math::DistSamplerOptions::DefaultAlgorithmND();
   }
   method.ToUpper();

   bool ret = false; 
   if (NDim() == 1) { 
       // check if distribution is discrete by 
      // using first string in the method name is "D"
      if (method.First("D") == 0) { 
         if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim discrete distribution with method %s",method.Data());
         ret =  DoInitDiscrete1D(method);
      }
      else {
         if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim continuous distribution with method %s",method.Data());
         ret =  DoInit1D(method); 
      }
   }
   else { 
      if (fLevel>1) Info("TUnuranSampler::Init","Initialize multi-dim continuous distribution with method %s",method.Data());
      ret = DoInitND(method); 
   }
   // set print level in UNURAN (must be done after having initialized) -
   if (fLevel>0) { 
      //fUnuran->SetLogLevel(fLevel); ( seems not to work  disable for the time being) 
      if (ret) Info("TUnuranSampler::Init","Successfully initailized Unuran with method %s",method.Data() );
      else Error("TUnuranSampler::Init","Failed to  initailize Unuran with method %s",method.Data() );
      // seems not to work in UNURAN (cll only when level > 0 )
   }
   return ret; 
}


bool TUnuranSampler::Init(const ROOT::Math::DistSamplerOptions & opt ) { 
   // default initialization with algorithm name
   SetPrintLevel(opt.PrintLevel() );
   return Init(opt.Algorithm().c_str() );
}


bool TUnuranSampler::DoInit1D(const char * method) { 
   // initilize for 1D sampling
   // need to create 1D interface from Multidim one 
   // (to do: use directly 1D functions ??)
   fOneDim = true; 
   TUnuranContDist * dist = 0;
   if (fFunc1D == 0) { 
      ROOT::Math::OneDimMultiFunctionAdapter<> function(ParentPdf() ); 
      dist = new TUnuranContDist(function,0,false,true); 
   }
   else { 
      dist = new TUnuranContDist(*fFunc1D); // no need to copy the function
   }
   // set range in distribution (support only one range)
   const ROOT::Fit::DataRange & range = PdfRange(); 
   if (range.Size(0) > 0) { 
      double xmin, xmax; 
      range.GetRange(0,xmin,xmax); 
      dist->SetDomain(xmin,xmax); 
   }
   if (fHasMode) dist->SetMode(fMode);
   if (fHasArea) dist->SetPdfArea(fArea);

   bool ret = false; 
   if (method) ret =  fUnuran->Init(*dist, method);       
   else ret =  fUnuran->Init(*dist);
   delete dist; 
   return ret; 
}

bool TUnuranSampler::DoInitDiscrete1D(const char * method) { 
   // initilize for 1D sampling of discrete distributions
   fOneDim = true; 
   fDiscrete = true;
   TUnuranDiscrDist * dist = 0;
   if (fFunc1D == 0) { 
      // need to copy the passed function pointer in this case
      ROOT::Math::OneDimMultiFunctionAdapter<> function(ParentPdf() ); 
      dist = new TUnuranDiscrDist(function,true); 
   }
   else { 
      // no need to copy the function since fFunc1D is managed outside
      dist = new TUnuranDiscrDist(*fFunc1D, false); 
   }
   // set range in distribution (support only one range)
   // otherwise 0, inf is assumed
   const ROOT::Fit::DataRange & range = PdfRange(); 
   if (range.Size(0) > 0) { 
      double xmin, xmax; 
      range.GetRange(0,xmin,xmax);
      if (xmin < 0) { 
         Warning("DoInitDiscrete1D","range starts from negative values - set minimum to zero"); 
         xmin = 0; 
      }
      dist->SetDomain(int(xmin+0.1),int(xmax+0.1)); 
   }
   if (fHasMode) dist->SetMode(int(fMode+0.1));
   if (fHasArea) dist->SetProbSum(fArea);

   bool ret =  fUnuran->Init(*dist, method);       
   delete dist;
   return ret;
}


bool TUnuranSampler::DoInitND(const char * method) { 
   // initilize for 1D sampling
   TUnuranMultiContDist dist(ParentPdf()); 
   // set range in distribution (support only one range)
   const ROOT::Fit::DataRange & range = PdfRange(); 
   if (range.IsSet()) { 
      std::vector<double> xmin(range.NDim() ); 
      std::vector<double> xmax(range.NDim() ); 
      range.GetRange(&xmin[0],&xmax[0]); 
      dist.SetDomain(&xmin.front(),&xmax.front());
//       std::cout << " range is min = "; 
//       for (int j = 0; j < NDim(); ++j) std::cout << xmin[j] << "   "; 
//       std::cout << " max = "; 
//       for (int j = 0; j < NDim(); ++j) std::cout << xmax[j] << "   "; 
//       std::cout << std::endl;
   }
   fOneDim = false; 
   if (method) return fUnuran->Init(dist, method); 
   return fUnuran->Init(dist);
}

void TUnuranSampler::SetFunction(TF1 * pdf) { 
   // set function from a TF1 pointer 
   SetFunction<TF1>(*pdf, pdf->GetNdim());
} 

void TUnuranSampler::SetRandom(TRandom * r) { 
   // set random generator (must be called before Init to have effect)
   fUnuran->SetRandom(r); 
} 

void TUnuranSampler::SetSeed(unsigned int seed) { 
   // set random generator seed (must be called before Init to have effect)
   fUnuran->SetSeed(seed); 
} 

TRandom * TUnuranSampler::GetRandom() { 
   // get random generator used 
   return  fUnuran->GetRandom(); 
} 

double TUnuranSampler::Sample1D() { 
   // sample 1D distributions
   return (fDiscrete) ? (double) fUnuran->SampleDiscr() : fUnuran->Sample(); 
}

bool TUnuranSampler::Sample(double * x) { 
   // sample multi-dim distributions
   if (!fOneDim) return fUnuran->SampleMulti(x); 
   x[0] = Sample1D(); 
   return true; 
} 


bool TUnuranSampler::SampleBin(double prob, double & value, double *error) {
   // sample a bin according to Poisson statistics

   TRandom * r = fUnuran->GetRandom(); 
   if (!r) return false; 
   value = r->Poisson(prob); 
   if (error) *error = std::sqrt(value);
   return true; 
}
 TUnuranSampler.cxx:1
 TUnuranSampler.cxx:2
 TUnuranSampler.cxx:3
 TUnuranSampler.cxx:4
 TUnuranSampler.cxx:5
 TUnuranSampler.cxx:6
 TUnuranSampler.cxx:7
 TUnuranSampler.cxx:8
 TUnuranSampler.cxx:9
 TUnuranSampler.cxx:10
 TUnuranSampler.cxx:11
 TUnuranSampler.cxx:12
 TUnuranSampler.cxx:13
 TUnuranSampler.cxx:14
 TUnuranSampler.cxx:15
 TUnuranSampler.cxx:16
 TUnuranSampler.cxx:17
 TUnuranSampler.cxx:18
 TUnuranSampler.cxx:19
 TUnuranSampler.cxx:20
 TUnuranSampler.cxx:21
 TUnuranSampler.cxx:22
 TUnuranSampler.cxx:23
 TUnuranSampler.cxx:24
 TUnuranSampler.cxx:25
 TUnuranSampler.cxx:26
 TUnuranSampler.cxx:27
 TUnuranSampler.cxx:28
 TUnuranSampler.cxx:29
 TUnuranSampler.cxx:30
 TUnuranSampler.cxx:31
 TUnuranSampler.cxx:32
 TUnuranSampler.cxx:33
 TUnuranSampler.cxx:34
 TUnuranSampler.cxx:35
 TUnuranSampler.cxx:36
 TUnuranSampler.cxx:37
 TUnuranSampler.cxx:38
 TUnuranSampler.cxx:39
 TUnuranSampler.cxx:40
 TUnuranSampler.cxx:41
 TUnuranSampler.cxx:42
 TUnuranSampler.cxx:43
 TUnuranSampler.cxx:44
 TUnuranSampler.cxx:45
 TUnuranSampler.cxx:46
 TUnuranSampler.cxx:47
 TUnuranSampler.cxx:48
 TUnuranSampler.cxx:49
 TUnuranSampler.cxx:50
 TUnuranSampler.cxx:51
 TUnuranSampler.cxx:52
 TUnuranSampler.cxx:53
 TUnuranSampler.cxx:54
 TUnuranSampler.cxx:55
 TUnuranSampler.cxx:56
 TUnuranSampler.cxx:57
 TUnuranSampler.cxx:58
 TUnuranSampler.cxx:59
 TUnuranSampler.cxx:60
 TUnuranSampler.cxx:61
 TUnuranSampler.cxx:62
 TUnuranSampler.cxx:63
 TUnuranSampler.cxx:64
 TUnuranSampler.cxx:65
 TUnuranSampler.cxx:66
 TUnuranSampler.cxx:67
 TUnuranSampler.cxx:68
 TUnuranSampler.cxx:69
 TUnuranSampler.cxx:70
 TUnuranSampler.cxx:71
 TUnuranSampler.cxx:72
 TUnuranSampler.cxx:73
 TUnuranSampler.cxx:74
 TUnuranSampler.cxx:75
 TUnuranSampler.cxx:76
 TUnuranSampler.cxx:77
 TUnuranSampler.cxx:78
 TUnuranSampler.cxx:79
 TUnuranSampler.cxx:80
 TUnuranSampler.cxx:81
 TUnuranSampler.cxx:82
 TUnuranSampler.cxx:83
 TUnuranSampler.cxx:84
 TUnuranSampler.cxx:85
 TUnuranSampler.cxx:86
 TUnuranSampler.cxx:87
 TUnuranSampler.cxx:88
 TUnuranSampler.cxx:89
 TUnuranSampler.cxx:90
 TUnuranSampler.cxx:91
 TUnuranSampler.cxx:92
 TUnuranSampler.cxx:93
 TUnuranSampler.cxx:94
 TUnuranSampler.cxx:95
 TUnuranSampler.cxx:96
 TUnuranSampler.cxx:97
 TUnuranSampler.cxx:98
 TUnuranSampler.cxx:99
 TUnuranSampler.cxx:100
 TUnuranSampler.cxx:101
 TUnuranSampler.cxx:102
 TUnuranSampler.cxx:103
 TUnuranSampler.cxx:104
 TUnuranSampler.cxx:105
 TUnuranSampler.cxx:106
 TUnuranSampler.cxx:107
 TUnuranSampler.cxx:108
 TUnuranSampler.cxx:109
 TUnuranSampler.cxx:110
 TUnuranSampler.cxx:111
 TUnuranSampler.cxx:112
 TUnuranSampler.cxx:113
 TUnuranSampler.cxx:114
 TUnuranSampler.cxx:115
 TUnuranSampler.cxx:116
 TUnuranSampler.cxx:117
 TUnuranSampler.cxx:118
 TUnuranSampler.cxx:119
 TUnuranSampler.cxx:120
 TUnuranSampler.cxx:121
 TUnuranSampler.cxx:122
 TUnuranSampler.cxx:123
 TUnuranSampler.cxx:124
 TUnuranSampler.cxx:125
 TUnuranSampler.cxx:126
 TUnuranSampler.cxx:127
 TUnuranSampler.cxx:128
 TUnuranSampler.cxx:129
 TUnuranSampler.cxx:130
 TUnuranSampler.cxx:131
 TUnuranSampler.cxx:132
 TUnuranSampler.cxx:133
 TUnuranSampler.cxx:134
 TUnuranSampler.cxx:135
 TUnuranSampler.cxx:136
 TUnuranSampler.cxx:137
 TUnuranSampler.cxx:138
 TUnuranSampler.cxx:139
 TUnuranSampler.cxx:140
 TUnuranSampler.cxx:141
 TUnuranSampler.cxx:142
 TUnuranSampler.cxx:143
 TUnuranSampler.cxx:144
 TUnuranSampler.cxx:145
 TUnuranSampler.cxx:146
 TUnuranSampler.cxx:147
 TUnuranSampler.cxx:148
 TUnuranSampler.cxx:149
 TUnuranSampler.cxx:150
 TUnuranSampler.cxx:151
 TUnuranSampler.cxx:152
 TUnuranSampler.cxx:153
 TUnuranSampler.cxx:154
 TUnuranSampler.cxx:155
 TUnuranSampler.cxx:156
 TUnuranSampler.cxx:157
 TUnuranSampler.cxx:158
 TUnuranSampler.cxx:159
 TUnuranSampler.cxx:160
 TUnuranSampler.cxx:161
 TUnuranSampler.cxx:162
 TUnuranSampler.cxx:163
 TUnuranSampler.cxx:164
 TUnuranSampler.cxx:165
 TUnuranSampler.cxx:166
 TUnuranSampler.cxx:167
 TUnuranSampler.cxx:168
 TUnuranSampler.cxx:169
 TUnuranSampler.cxx:170
 TUnuranSampler.cxx:171
 TUnuranSampler.cxx:172
 TUnuranSampler.cxx:173
 TUnuranSampler.cxx:174
 TUnuranSampler.cxx:175
 TUnuranSampler.cxx:176
 TUnuranSampler.cxx:177
 TUnuranSampler.cxx:178
 TUnuranSampler.cxx:179
 TUnuranSampler.cxx:180
 TUnuranSampler.cxx:181
 TUnuranSampler.cxx:182
 TUnuranSampler.cxx:183
 TUnuranSampler.cxx:184
 TUnuranSampler.cxx:185
 TUnuranSampler.cxx:186
 TUnuranSampler.cxx:187
 TUnuranSampler.cxx:188
 TUnuranSampler.cxx:189
 TUnuranSampler.cxx:190
 TUnuranSampler.cxx:191
 TUnuranSampler.cxx:192
 TUnuranSampler.cxx:193
 TUnuranSampler.cxx:194
 TUnuranSampler.cxx:195
 TUnuranSampler.cxx:196
 TUnuranSampler.cxx:197
 TUnuranSampler.cxx:198
 TUnuranSampler.cxx:199
 TUnuranSampler.cxx:200
 TUnuranSampler.cxx:201
 TUnuranSampler.cxx:202
 TUnuranSampler.cxx:203
 TUnuranSampler.cxx:204
 TUnuranSampler.cxx:205
 TUnuranSampler.cxx:206
 TUnuranSampler.cxx:207
 TUnuranSampler.cxx:208
 TUnuranSampler.cxx:209
 TUnuranSampler.cxx:210
 TUnuranSampler.cxx:211
 TUnuranSampler.cxx:212
 TUnuranSampler.cxx:213
 TUnuranSampler.cxx:214
 TUnuranSampler.cxx:215
 TUnuranSampler.cxx:216
 TUnuranSampler.cxx:217
 TUnuranSampler.cxx:218
 TUnuranSampler.cxx:219
 TUnuranSampler.cxx:220
 TUnuranSampler.cxx:221
 TUnuranSampler.cxx:222
 TUnuranSampler.cxx:223
 TUnuranSampler.cxx:224
 TUnuranSampler.cxx:225
 TUnuranSampler.cxx:226
 TUnuranSampler.cxx:227