Logo ROOT  
Reference Guide
TUnuranSampler.cxx
Go to the documentation of this file.
1// @(#)root/unuran:$Id$
2// Authors: L. Moneta, J. Leydold Wed Feb 28 2007
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2010 LCG ROOT Math Team, CERN/PH-SFT *
7 * *
8 * *
9 **********************************************************************/
10
11// Implementation file for class TUnuranSampler
12#include "TUnuranSampler.h"
13
14#include "TUnuranContDist.h"
15#include "TUnuranDiscrDist.h"
17#include "TUnuran.h"
20#include "Math/GenAlgoOptions.h"
21#include "Fit/DataRange.h"
22//#include "Math/WrappedTF1.h"
23
24#include "TRandom.h"
25#include "TError.h"
26
27#include "TF1.h"
28#include <cassert>
29#include <cmath>
30
32
34 fOneDim(false),
35 fDiscrete(false),
36 fHasMode(false), fHasArea(false),
37 fMode(0), fArea(0),
38 fUnuran(new TUnuran() )
39{
41}
42
44 assert(fUnuran != 0);
45 delete fUnuran;
46}
47
48bool TUnuranSampler::Init(const char * algo) {
49 // initialize unuran classes using the given algorithm
50 assert (fUnuran != 0 );
51 bool ret = false;
52 //case distribution has not been set
53 // Maybe we are using the Unuran string API which contains also distribution string
54 // try to initialize Unuran
55 if (NDim() == 0) {
56 ret = fUnuran->Init(algo,"");
57 if (!ret) {
58 Error("TUnuranSampler::Init",
59 "Unuran initialization string is invalid or the Distribution function has not been set and one needs to call SetFunction first.");
60 return false;
61 }
62 int ndim = fUnuran->GetDimension();
63 assert(ndim > 0);
64 fOneDim = (ndim == 1);
66 DoSetDimension(ndim);
67 return true;
68 }
69
71
72 TString method(algo);
73 if (method.IsNull() ) {
76 }
77 method.ToUpper();
78
79 if (NDim() == 1) {
80 // check if distribution is discrete by
81 // using first string in the method name is "D"
82 if (method.First("D") == 0) {
83 if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim discrete distribution with method %s",method.Data());
84 ret = DoInitDiscrete1D(method);
85 }
86 else {
87 if (fLevel>1) Info("TUnuranSampler::Init","Initialize one-dim continuous distribution with method %s",method.Data());
88 ret = DoInit1D(method);
89 }
90 }
91 else {
92 if (fLevel>1) Info("TUnuranSampler::Init","Initialize multi-dim continuous distribution with method %s",method.Data());
93 ret = DoInitND(method);
94 }
95 // set print level in UNURAN (must be done after having initialized) -
96 if (fLevel>0) {
97 //fUnuran->SetLogLevel(fLevel); ( seems not to work disable for the time being)
98 if (ret) Info("TUnuranSampler::Init","Successfully initailized Unuran with method %s",method.Data() );
99 else Error("TUnuranSampler::Init","Failed to initailize Unuran with method %s",method.Data() );
100 // seems not to work in UNURAN (call only when level > 0 )
101 }
102 return ret;
103}
104
105
107 // default initialization with algorithm name
109 // check if there are extra options
110 std::string optionStr = opt.Algorithm();
111 auto extraOpts = opt.ExtraOptions();
112 if (extraOpts) {
113 ROOT::Math::GenAlgoOptions * opts = dynamic_cast<ROOT::Math::GenAlgoOptions*>(extraOpts);
114 auto appendOption = [&](const std::string & key, const std::string & val) {
115 optionStr += "; ";
116 optionStr += key;
117 if (!val.empty()) {
118 optionStr += "=";
119 optionStr += val;
120 }
121 };
122 auto names = opts->GetAllNamedKeys();
123 for ( auto & name : names) {
124 std::string value = opts->NamedValue(name.c_str());
125 appendOption(name,value);
126 }
127 names = opts->GetAllIntKeys();
128 for ( auto & name : names) {
129 std::string value = ROOT::Math::Util::ToString(opts->IValue(name.c_str()));
130 appendOption(name,value);
131 }
132 names = opts->GetAllRealKeys();
133 for ( auto & name : names) {
134 std::string value = ROOT::Math::Util::ToString(opts->RValue(name.c_str()));
135 appendOption(name,value);
136 }
137 }
138 Info("Init","Initialize UNU.RAN with Method option string: %s",optionStr.c_str());
139 return Init(optionStr.c_str() );
140}
141
142
143bool TUnuranSampler::DoInit1D(const char * method) {
144 // initialize for 1D sampling
145 // need to create 1D interface from Multidim one
146 // (to do: use directly 1D functions ??)
147 // to do : add possibility for String API of UNURAN
148 fOneDim = true;
149 TUnuranContDist * dist = 0;
150 if (fFunc1D == 0) {
151 if (HasParentPdf()) {
154 }
155 else {
156 if (!fDPDF && !fCDF) {
157 Error("DoInit1D", "No PDF, CDF or DPDF function has been set");
158 return false;
159 }
160 dist = new TUnuranContDist(nullptr, fDPDF, fCDF, fUseLogPdf, true);
161 }
162 }
163 else {
164 dist = new TUnuranContDist(fFunc1D, fDPDF, fCDF, fUseLogPdf, true); // no need to copy the function
165 }
166 // set range in distribution (support only one range)
167 const ROOT::Fit::DataRange & range = PdfRange();
168 if (range.Size(0) > 0) {
169 double xmin, xmax;
170 range.GetRange(0,xmin,xmax);
171 dist->SetDomain(xmin,xmax);
172 }
173 if (fHasMode) dist->SetMode(fMode);
174 if (fHasArea) dist->SetPdfArea(fArea);
175
176 bool ret = false;
177 if (method) ret = fUnuran->Init(*dist, method);
178 else ret = fUnuran->Init(*dist);
179 delete dist;
180 return ret;
181}
182
183bool TUnuranSampler::DoInitDiscrete1D(const char * method) {
184 // initialize for 1D sampling of discrete distributions
185 fOneDim = true;
186 fDiscrete = true;
188 if (fFunc1D == 0) {
189 if (!HasParentPdf()) {
190 Error("DoInitDiscrete1D", "No PMF has been defined");
191 return false;
192 }
193 // need to copy the passed function pointer in this case
195 dist = new TUnuranDiscrDist(function,true);
196 }
197 else {
198 // no need to copy the function since fFunc1D is managed outside
199 dist = new TUnuranDiscrDist(*fFunc1D, false);
200 }
201 // set CDF if available
202 if (fCDF) dist->SetCdf(*fCDF);
203 // set range in distribution (support only one range)
204 // otherwise 0, inf is assumed
205 const ROOT::Fit::DataRange & range = PdfRange();
206 if (range.Size(0) > 0) {
207 double xmin, xmax;
208 range.GetRange(0,xmin,xmax);
209 if (xmin < 0) {
210 Warning("DoInitDiscrete1D","range starts from negative values - set minimum to zero");
211 xmin = 0;
212 }
213 dist->SetDomain(int(xmin+0.1),int(xmax+0.1));
214 }
215 if (fHasMode) dist->SetMode(int(fMode+0.1));
216 if (fHasArea) dist->SetProbSum(fArea);
217
218 bool ret = fUnuran->Init(*dist, method);
219 delete dist;
220 return ret;
221}
222
223
224bool TUnuranSampler::DoInitND(const char * method) {
225 // initialize for ND sampling
226 if (!HasParentPdf()) {
227 Error("DoInitND", "No PDF has been defined");
228 return false;
229 }
231 // set range in distribution (support only one range)
232 const ROOT::Fit::DataRange & range = PdfRange();
233 if (range.IsSet()) {
234 std::vector<double> xmin(range.NDim() );
235 std::vector<double> xmax(range.NDim() );
236 range.GetRange(&xmin[0],&xmax[0]);
237 dist.SetDomain(&xmin.front(),&xmax.front());
238// std::cout << " range is min = ";
239// for (int j = 0; j < NDim(); ++j) std::cout << xmin[j] << " ";
240// std::cout << " max = ";
241// for (int j = 0; j < NDim(); ++j) std::cout << xmax[j] << " ";
242// std::cout << std::endl;
243 }
244 fOneDim = false;
245 if (fHasMode && fNDMode.size() == dist.NDim())
246 dist.SetMode(fNDMode.data());
247
248 if (method) return fUnuran->Init(dist, method);
249 return fUnuran->Init(dist);
250}
251
253 // set function from a TF1 pointer
254 SetFunction<TF1>(*pdf, pdf->GetNdim());
255}
256
258 // set random generator (must be called before Init to have effect)
260}
261
262void TUnuranSampler::SetSeed(unsigned int seed) {
263 // set random generator seed (must be called before Init to have effect)
264 fUnuran->SetSeed(seed);
265}
266
268 // get random generator used
269 return fUnuran->GetRandom();
270}
271
273 // sample 1D distributions
274 return (fDiscrete) ? (double) fUnuran->SampleDiscr() : fUnuran->Sample();
275}
276
277bool TUnuranSampler::Sample(double * x) {
278 // sample multi-dim distributions
279 if (!fOneDim) return fUnuran->SampleMulti(x);
280 x[0] = Sample1D();
281 return true;
282}
283
284
285bool TUnuranSampler::SampleBin(double prob, double & value, double *error) {
286 // sample a bin according to Poisson statistics
287 TRandom * r = fUnuran->GetRandom();
288 if (!r) return false;
289 value = r->Poisson(prob);
290 if (error) *error = std::sqrt(prob);
291 return true;
292}
293
294void TUnuranSampler::SetMode(const std::vector<double> &mode)
295{
296 // set modes for multidim distribution
297 if (mode.size() == ParentPdf().NDim()) {
298 if (mode.size() == 1)
299 fMode = mode[0];
300 else
301 fNDMode = mode;
302
303 fHasMode = true;
304 }
305 else {
306 Error("SetMode", "modes vector is not compatible with function dimension of %d", (int)ParentPdf().NDim());
307 fHasMode = false;
308 fNDMode.clear();
309 }
310}
311
313 fCDF = &cdf;
314 // in case dimension has not been defined ( a pdf is not provided)
315 if (NDim() == 0) DoSetDimension(1);
316}
317
319 fDPDF = &dpdf;
320 // in case dimension has not been defined ( a pdf is not provided)
321 if (NDim() == 0) DoSetDimension(1);
322}
#define ClassImp(name)
Definition: Rtypes.h:375
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition: TError.cxx:220
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition: TError.cxx:231
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char mode
char name[80]
Definition: TGX11.cxx:110
float xmin
Definition: THbookFile.cxx:95
float xmax
Definition: THbookFile.cxx:95
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition: DataRange.h:35
bool IsSet() const
return true if a range has been set in any of the coordinates i.e.
Definition: DataRange.h:80
unsigned int NDim() const
get range dimension
Definition: DataRange.h:65
unsigned int Size(unsigned int icoord=0) const
return range size for coordinate icoord (starts from zero) Size == 0 indicates no range is present [-...
Definition: DataRange.h:71
void GetRange(unsigned int irange, unsigned int icoord, double &xmin, double &xmax) const
get the i-th range for given coordinate.
Definition: DataRange.h:104
DistSampler options class.
int PrintLevel() const
non-static methods for retrieving options
const std::string & Algorithm() const
type of algorithm (method)
IOptions * ExtraOptions() const
return extra options (NULL pointer if they are not present)
static const std::string & DefaultAlgorithmND()
static const std::string & DefaultAlgorithm1D()
const double * Sample()
Sample one event and return an array x with sample coordinates values.
Definition: DistSampler.h:193
const ROOT::Math::IMultiGenFunction & ParentPdf() const
Get the parent distribution function (must be called after setting the function).
Definition: DistSampler.h:173
unsigned int NDim() const
return the dimension of the parent distribution (and the data)
Definition: DistSampler.h:91
const ROOT::Fit::DataRange & PdfRange() const
return the data range of the Pdf . Must be called after setting the function
Definition: DistSampler.h:276
virtual void DoSetDimension(unsigned int ndim)
Definition: DistSampler.cxx:78
bool HasParentPdf() const
Check if there is a parent distribution defined.
Definition: DistSampler.h:178
class implementing generic options for a numerical algorithm Just store the options in a map of strin...
std::vector< std::string > GetAllRealKeys()
std::vector< std::string > GetAllIntKeys()
std::vector< std::string > GetAllNamedKeys()
Interface (abstract class) for generic functions objects of one-dimension Provides a method to evalua...
Definition: IFunction.h:135
double RValue(const char *name) const
Definition: IOptions.h:50
std::string NamedValue(const char *name) const
Definition: IOptions.h:64
int IValue(const char *name) const
Definition: IOptions.h:57
OneDimMultiFunctionAdapter class to wrap a multidimensional function in one dimensional one.
1-Dim function class
Definition: TF1.h:213
virtual Int_t GetNdim() const
Definition: TF1.h:490
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:27
Basic string class.
Definition: TString.h:136
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:523
const char * Data() const
Definition: TString.h:369
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1163
Bool_t IsNull() const
Definition: TString.h:407
TUnuranContDist class describing one dimensional continuous distribution.
TUnuranDiscrDist class for one dimensional discrete distribution.
TUnuranMultiContDist class describing multi dimensional continuous distributions.
TUnuranSampler class class implementing the ROOT::Math::DistSampler interface using the UNU....
const ROOT::Math::IGenFunction * fDPDF
1D Derivative function pointer
double fArea
area of dist
bool Init(const char *algo="") override
initialize the generators with the given algorithm If no algorithm is passed used the default one for...
const ROOT::Math::IGenFunction * fCDF
CDF function pointer.
void SetRandom(TRandom *r) override
Set the random engine to be used Needs to be called before Init to have effect.
void SetFunction(const ROOT::Math::IGenFunction &func) override
Set the parent function distribution to use for random sampling (one dim case).
TRandom * GetRandom() override
Get the random engine used by the sampler.
bool fHasMode
flag to indicate if a mode is set
bool fHasArea
flag to indicate if a area is set
void SetSeed(unsigned int seed) override
Set the random seed for the TRandom instances used by the sampler classes Needs to be called before I...
void SetPrintLevel(int level)
Set the print level (if level=-1 use default)
bool DoInitND(const char *algo)
Initialization for multi-dim distributions.
TUnuran * fUnuran
unuran engine class
const ROOT::Math::IGenFunction * fFunc1D
1D function pointer (pdf)
bool DoInit1D(const char *algo)
Initialization for 1D distributions.
void SetMode(double mode) override
Set the mode of the distribution (1D case).
bool fUseLogPdf
flag to indicate if we use the log of the PDF
double Sample1D() override
sample one event in one dimension better implementation could be provided by the derived classes
void SetDPdf(const ROOT::Math::IGenFunction &dpdf) override
set the Derivative of the PDF used for random sampling (one dim continuous case)
TUnuranSampler()
default constructor
bool fDiscrete
flag to indicate if the function is discrete
bool SampleBin(double prob, double &value, double *error=0) override
sample one bin given an estimated of the pdf in the bin (this can be function value at the center or ...
bool fOneDim
flag to indicate if the function is 1 dimension
void SetCdf(const ROOT::Math::IGenFunction &cdf) override
set the cumulative distribution function of the PDF used for random sampling (one dim case)
double fMode
mode of dist (1D)
std::vector< double > fNDMode
mode of the multi-dim distribution
int fLevel
debug level
~TUnuranSampler() override
virtual destructor
bool DoInitDiscrete1D(const char *algo)
Initialization for 1D discrete distributions.
TUnuran class.
Definition: TUnuran.h:79
int SampleDiscr()
Sample discrete distributions.
Definition: TUnuran.cxx:422
bool SampleMulti(double *x)
Sample multidimensional distributions.
Definition: TUnuran.cxx:436
bool Init(const std::string &distr, const std::string &method)
Initialize with Unuran string API interface.
Definition: TUnuran.cxx:75
double Sample()
Sample 1D distribution.
Definition: TUnuran.cxx:429
TRandom * GetRandom()
Return instance of the random engine used.
Definition: TUnuran.h:225
int GetDimension() const
Return the dimension of unuran generator method.
Definition: TUnuran.cxx:391
void SetSeed(unsigned int seed)
set the seed for the random number generator
Definition: TUnuran.cxx:444
void SetRandom(TRandom *r)
Set the random engine.
Definition: TUnuran.h:218
bool IsDistDiscrete() const
Return true for a discrete distribution.
Definition: TUnuran.cxx:413
Double_t x[n]
Definition: legend1.C:17
Namespace for new Math classes and functions.
std::string ToString(const T &val)
Utility function for conversion to strings.
Definition: Util.h:50
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
void function(const Char_t *name_, T fun, const Char_t *docstring=0)
Definition: RExports.h:167
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.