CMS 3D CMS Logo

GaussianTailNoiseGenerator.cc

Go to the documentation of this file.
00001 #include "SimGeneral/NoiseGenerators/interface/GaussianTailNoiseGenerator.h"
00002 #include "CLHEP/Random/RandPoissonQ.h"
00003 #include "CLHEP/Random/RandGaussQ.h"
00004 #include "CLHEP/Random/RandFlat.h"
00005 
00006 #include <math.h>
00007 
00008 #include <gsl/gsl_sf_erf.h>
00009 #include <gsl/gsl_sf_result.h>
00010 
00011 GaussianTailNoiseGenerator::GaussianTailNoiseGenerator(CLHEP::HepRandomEngine& eng ) :
00012   gaussDistribution_(eng),
00013   poissonDistribution_(eng),
00014   flatDistribution_(eng)
00015 {
00016 }
00017 
00018 void GaussianTailNoiseGenerator::generate(int NumberOfchannels, 
00019                                           float threshold, 
00020                                           float noiseRMS, 
00021                                           std::map<int,float, std::less<int> >& theMap ) {
00022 
00023    // Gaussian tail probability
00024   gsl_sf_result result;
00025   int status = gsl_sf_erf_Q_e(threshold, &result);
00026 
00027   if (status != 0) std::cerr<<"GaussianTailNoiseGenerator::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
00028 
00029   float probabilityLeft = result.val;  
00030   float meanNumberOfNoisyChannels = probabilityLeft * NumberOfchannels;
00031   int numberOfNoisyChannels = poissonDistribution_.fire(meanNumberOfNoisyChannels);
00032 
00033   float lowLimit = threshold * noiseRMS;
00034   for (int i = 0; i < numberOfNoisyChannels; i++) {
00035 
00036     // Find a random channel number    
00037     int theChannelNumber = (int)flatDistribution_.fire(NumberOfchannels);
00038 
00039     // Find random noise value
00040     double noise = generate_gaussian_tail(lowLimit, noiseRMS);
00041               
00042     // Fill in map
00043     theMap[theChannelNumber] = noise;
00044     
00045   }
00046 }
00047 
00048 void GaussianTailNoiseGenerator::generate(int NumberOfchannels, 
00049                                           float threshold, 
00050                                           float noiseRMS, 
00051                                           std::vector<std::pair<int,float> > &theVector ) {
00052   // Compute number of channels with noise above threshold
00053   // Gaussian tail probability
00054   gsl_sf_result result;
00055   int status = gsl_sf_erf_Q_e(threshold, &result);
00056   
00057   if (status != 0) std::cerr<<"GaussianTailNoiseGenerator::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
00058   
00059   double probabilityLeft = result.val;  
00060   double meanNumberOfNoisyChannels = probabilityLeft * NumberOfchannels;
00061   int numberOfNoisyChannels = poissonDistribution_.fire(meanNumberOfNoisyChannels);
00062 
00063   theVector.reserve(numberOfNoisyChannels);
00064   float lowLimit = threshold * noiseRMS;
00065   for (int i = 0; i < numberOfNoisyChannels; i++) {
00066 
00067     // Find a random channel number    
00068     int theChannelNumber = (int)flatDistribution_.fire(NumberOfchannels);
00069     
00070     // Find random noise value
00071     double noise = generate_gaussian_tail(lowLimit, noiseRMS);
00072               
00073     // Fill in the vector
00074     theVector.push_back(std::pair<int, float>(theChannelNumber, noise));
00075   }
00076 }
00077 
00078 void GaussianTailNoiseGenerator::generateRaw(int NumberOfchannels, 
00079                                              float noiseRMS, 
00080                                              std::vector<std::pair<int,float> > &theVector ) {
00081   theVector.reserve(NumberOfchannels);
00082   for (int i = 0; i < NumberOfchannels; i++) {
00083     // Find random noise value
00084     float noise = gaussDistribution_.fire(0.,noiseRMS);
00085     // Fill in the vector
00086     theVector.push_back(std::pair<int, float>(i,noise));
00087   }
00088 }
00089 
00090 double
00091 GaussianTailNoiseGenerator::generate_gaussian_tail(const double a, const double sigma){
00092   /* Returns a gaussian random variable larger than a
00093    * This implementation does one-sided upper-tailed deviates.
00094    */
00095   
00096   double s = a/sigma;
00097   
00098   if (s < 1){
00099     /*
00100       For small s, use a direct rejection method. The limit s < 1
00101       can be adjusted to optimise the overall efficiency 
00102     */
00103     double x;
00104     
00105     do{
00106       x = gaussDistribution_.fire(0.,1.0);
00107     }
00108     while (x < s);
00109     return x * sigma;
00110     
00111   }else{
00112     
00113     /* Use the "supertail" deviates from the last two steps
00114      * of Marsaglia's rectangle-wedge-tail method, as described
00115      * in Knuth, v2, 3rd ed, pp 123-128.  (See also exercise 11, p139,
00116      * and the solution, p586.)
00117      */
00118     
00119     double u, v, x;
00120     
00121     do{
00122       u = flatDistribution_.fire();
00123       do{
00124         v = flatDistribution_.fire();
00125       }while (v == 0.0);
00126       x = sqrt(s * s - 2 * log(v));
00127     }
00128     while (x * u > s);
00129     return x * sigma;
00130   }
00131 }

Generated on Tue Jun 9 17:47:28 2009 for CMSSW by  doxygen 1.5.4