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
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
00037 int theChannelNumber = (int)flatDistribution_.fire(NumberOfchannels);
00038
00039
00040 double noise = generate_gaussian_tail(lowLimit, noiseRMS);
00041
00042
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
00053
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
00068 int theChannelNumber = (int)flatDistribution_.fire(NumberOfchannels);
00069
00070
00071 double noise = generate_gaussian_tail(lowLimit, noiseRMS);
00072
00073
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
00084 float noise = gaussDistribution_.fire(0.,noiseRMS);
00085
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
00093
00094
00095
00096 double s = a/sigma;
00097
00098 if (s < 1){
00099
00100
00101
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
00114
00115
00116
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 }