Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:16

0001 // @(#)root/mathcore:$Id$
0002 // Author: L. Moneta Fri Sep 22 15:06:47 2006
0003 
0004 /**********************************************************************
0005  *                                                                    *
0006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
0007  *                                                                    *
0008  *                                                                    *
0009  **********************************************************************/
0010 
0011 // Header file for class DistSampler
0012 
0013 #ifndef ROOT_Math_DistSampler
0014 #define ROOT_Math_DistSampler
0015 
0016 #include "Math/IFunctionfwd.h"
0017 
0018 #include "Math/WrappedFunction.h"
0019 
0020 #include <vector>
0021 #include <cassert>
0022 
0023 class TRandom;
0024 
0025 namespace ROOT {
0026 
0027    namespace Fit {
0028 
0029       class DataRange;
0030       class BinData;
0031       class UnBinData;
0032    }
0033 
0034    namespace Math {
0035 
0036       class DistSamplerOptions;
0037 
0038 /**
0039    @defgroup Random Interface classes for Random number generation
0040 
0041    Pseudo-random numbers generator classes and for generation of random number distributions.
0042    These classes implement several pseudo-random number generators and method for generation of random numbers
0043    according to arbitrary distributions
0044 
0045    @ingroup MathCore
0046 
0047 */
0048 
0049 /**
0050    Interface class for generic sampling of a distribution,
0051    i.e. generating random numbers according to arbitrary distributions
0052 
0053    @ingroup Random
0054 */
0055 
0056 
0057 class DistSampler {
0058 
0059 public:
0060 
0061    /// default constructor
0062    DistSampler() : fOwnFunc(false), fRange(nullptr), fFunc(nullptr) {}
0063 
0064 
0065    /// virtual destructor
0066    virtual ~DistSampler();
0067 
0068 
0069 
0070    /// set the parent function distribution to use for sampling (generic case)
0071    template<class Function>
0072    void SetFunction(Function & func, unsigned int dim) {
0073       WrappedMultiFunction<Function &> wf(func, dim);
0074       fData.resize(dim);
0075       // need to clone to avoid temporary
0076       DoSetFunction(wf,true);
0077    }
0078 
0079    /// set the parent function distribution to use for random sampling (one dim case)
0080    virtual void SetFunction(const ROOT::Math::IGenFunction & func)  {
0081       SetFunction<const ROOT::Math::IGenFunction>(func, 1);
0082    }
0083 
0084 
0085    /// set the parent function distribution to use for random sampling (multi-dim case)
0086    virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func)  {
0087       DoSetFunction(func,false);
0088    }
0089 
0090    /// return the dimension of the parent distribution (and the data)
0091    unsigned int NDim() const { return fData.size(); }
0092 
0093 
0094    /**
0095       Initialize the sampling generator with the given algorithm.
0096       Implemented by the derived classes who needs it
0097       (like UnuranSampler).
0098       If nothing is specified use default algorithm
0099       from DistSamplerOptions::SetDefaultAlgorithm
0100    */
0101    virtual bool Init(const char * =""/* algorithm */) { return true;}
0102 
0103    /**
0104       Initialize the generators with the given DistSamplerOption object.
0105       The string will include the algorithm and in case additional options
0106       which can be interpreted by a re-implemented method in the derived class.
0107       The default implementation just calls the above method
0108       passing just the algorithm name
0109    */
0110    virtual bool Init(const DistSamplerOptions & opt );
0111 
0112 
0113    /**
0114        Set the random engine to be used.
0115        To be implemented by the derived classes who provides
0116        random sampling
0117    */
0118    virtual void SetRandom(TRandom *  ) {}
0119 
0120    /**
0121        Set the random seed for the TRandom instances used by the sampler
0122        classes.
0123        To be implemented by the derived classes who provides random sampling
0124    */
0125    virtual void SetSeed(unsigned int /*seed*/ ) {}
0126 
0127    /**
0128       Get the random engine used by the sampler.
0129       To be implemented by the derived classes who needs it
0130       Returns zero by default
0131     */
0132    virtual TRandom * GetRandom() { return nullptr; }
0133 
0134    /// Set the range in a given dimension.
0135    void SetRange(double xmin, double xmax, int icoord = 0);
0136 
0137    /// Set the range for all dimensions.
0138    void SetRange(const double * xmin, const double * xmax);
0139    /// Set the range for all dimensions (use std::vector)
0140    void SetRange(const std::vector<double> & xmin, const std::vector<double> & xmax){
0141       assert(xmin.size() >= NDim() && xmax.size() >= NDim());
0142       SetRange(xmin.data(),xmax.data());
0143    }
0144 
0145    /// Set the range using the ROOT::Fit::DataRange class.
0146    void SetRange(const ROOT::Fit::DataRange & range);
0147 
0148    /// Set the mode of the distribution (1D case).
0149    /// It could be useful or needed by some sampling methods.
0150    /// It is implemented by derived classes if needed (e.g. TUnuranSampler)
0151    virtual void SetMode(double  ) {}
0152 
0153    /// Set the mode of the distribution (Multi-dim case).
0154    virtual void SetMode(const std::vector<double> &) {}
0155 
0156    /// Set the normalization area of distribution.
0157    /// Implemented by derived classes if needed
0158    virtual void SetArea(double) {}
0159 
0160    /// Use the log of the provided pdf.
0161    /// Implemented by the derived classes
0162    virtual void SetUseLogPdf(bool = true) {}
0163 
0164    /// Set usage of Derivative of PDF.
0165    /// Can be implemented by derived class
0166    virtual void SetDPdf(const ROOT::Math::IGenFunction & ) {}
0167 
0168    /// Set usage of Cumulative of PDF.
0169    /// Can be implemented by derived class
0170    virtual void SetCdf(const ROOT::Math::IGenFunction &) {}
0171 
0172    /// Get the parent distribution function (must be called after setting the function).
0173    const ROOT::Math::IMultiGenFunction & ParentPdf() const {
0174       return *fFunc;
0175    }
0176 
0177    /// Check if there is a parent distribution defined.
0178    bool HasParentPdf() const { return fFunc != nullptr; }
0179 
0180    /**
0181       Sample one event in one dimension.
0182       Specialized implementation could be provided by the derived classes
0183    */
0184    virtual double Sample1D() {
0185       Sample(&fData[0]);
0186       return fData[0];
0187    }
0188 
0189    /**
0190       Sample one event and return an array x with
0191       sample coordinates values.
0192     */
0193    const double *  Sample() {
0194       Sample(&fData[0]);
0195       return &fData.front();
0196    }
0197 
0198    /**
0199       Sample one event in multi-dimension by filling the given array.
0200       Return false if the sampling failed.
0201       Abstract method to be re-implemented by the derived classes
0202    */
0203    virtual bool Sample(double * x) = 0;
0204 
0205    /**
0206       Sample one bin given an estimate of the pdf in the bin.
0207       (this can be function value at the center or its integral in the bin
0208       divided by the bin width)
0209       By default do not do random sample, just return the function values
0210       Typically Poisson statistics will be used
0211     */
0212    virtual bool SampleBin(double prob, double & value, double * error = nullptr) {
0213       value = prob;
0214       if (error) *error = 0;
0215       return true;
0216    }
0217    /**
0218       Sample a set of bins given a vector of probabilities
0219       Typically multinomial statistics will be used and the sum of the probabilities
0220       will be equal to the total number of events to be generated
0221       For sampling the bins independently, SampleBin should be used
0222     */
0223    virtual bool SampleBins(unsigned int n, const double * prob, double * values, double * errors  = nullptr)  {
0224       std::copy(prob,prob+n, values); // default impl returns prob values (Asimov data)
0225       if (errors) std::fill(errors,errors+n,0);
0226       return true;
0227    }
0228 
0229 
0230    /**
0231       Generate a un-binned data set by filling the given data set object.
0232       If the data set object is not empty, the new generated data will be appended to the
0233       existing one.
0234    */
0235    virtual bool Generate(unsigned int nevt, ROOT::Fit::UnBinData & data);
0236    /**
0237       Generate a vector of events by filling the passed data vector.
0238       The flag eventRow indicates how the events are arranged in the multi-dim case.
0239       The can be arranged in rows or in columns.
0240       With eventRow=false events are the columns in data: {x1,x2,.....,xn},{y1,....yn}
0241       With eventRow=true  events are rows in data: {x1,y1},{x2,y2},.....{xn,yn}
0242    */
0243    virtual bool Generate(unsigned int nevt, double * data, bool eventRow = false);
0244 
0245    /**
0246       Generate a binned data set.
0247       A range must have been set before (otherwise inf is returned)
0248       and the bins are equidistant in the previously defined range
0249       bin center values must be present in given data set
0250       If the sampler is implemented by a random one, the entries
0251       will be binned according to the Poisson distribution
0252       It is assumed the distribution is normalized, otherwise the nevt must be scaled
0253       accordingly. The expected value/bin nexp  = f(x_i) * binArea/ nevt
0254       Extend control if use a fixed (i.e. multinomial statistics) or floating total number of events
0255    */
0256    virtual bool Generate(unsigned int nevt, const  int * nbins, ROOT::Fit::BinData & data, bool extend = true, bool expErr = true);
0257    /**
0258       Same as before but passing the range in case of 1 dim data.
0259     */
0260    bool Generate(unsigned int nevt, int nbins, double xmin, double xmax, ROOT::Fit::BinData & data, bool extend = true, bool expErr = true ) {
0261       SetRange(xmin,xmax);
0262       int nbs[1]; nbs[0] = nbins;
0263       return Generate(nevt, nbs, data, extend, expErr);
0264    }
0265 
0266 
0267 protected:
0268 
0269    // internal method to set the function
0270    virtual void DoSetFunction(const ROOT::Math::IMultiGenFunction & func, bool copy);
0271    // internal method to set the dimension
0272    virtual void DoSetDimension(unsigned int ndim);
0273    // check if generator have been initialized correctly and one can start generating
0274    bool IsInitialized() ;
0275    /// return the data range of the Pdf . Must be called after setting the function
0276    const ROOT::Fit::DataRange & PdfRange() const {
0277       assert(fRange);
0278       return *fRange;
0279    }
0280 
0281 private:
0282 
0283    // private methods
0284 
0285    bool fOwnFunc;                               ///< flag to indicate if the function is owned
0286    mutable std::vector<double> fData;           ///<! internal array used to cached the sample data
0287    ROOT::Fit::DataRange    *   fRange;          ///< data range
0288    const ROOT::Math::IMultiGenFunction * fFunc; ///< internal function (ND)
0289 
0290 
0291 };
0292 
0293    } // end namespace Math
0294 
0295 } // end namespace ROOT
0296 
0297 
0298 #endif /* ROOT_Math_DistSampler */