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 for(unsigned int i=0;i<512;++i) channel512_[i]=i;
00019 for(unsigned int i=0;i<768;++i) channel768_[i]=i;
00020 }
00021
00022
00023 void GaussianTailNoiseGenerator::generate(int NumberOfchannels,
00024 float threshold,
00025 float noiseRMS,
00026 std::map<int,float, std::less<int> >& theMap ) {
00027
00028
00029 gsl_sf_result result;
00030 int status = gsl_sf_erf_Q_e(threshold, &result);
00031
00032 if (status != 0) std::cerr<<"GaussianTailNoiseGenerator::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
00033
00034 float probabilityLeft = result.val;
00035 float meanNumberOfNoisyChannels = probabilityLeft * NumberOfchannels;
00036 int numberOfNoisyChannels = poissonDistribution_.fire(meanNumberOfNoisyChannels);
00037
00038 float lowLimit = threshold * noiseRMS;
00039 for (int i = 0; i < numberOfNoisyChannels; i++) {
00040
00041
00042 int theChannelNumber = (int)flatDistribution_.fire(NumberOfchannels);
00043
00044
00045 double noise = generate_gaussian_tail(lowLimit, noiseRMS);
00046
00047
00048 theMap[theChannelNumber] = noise;
00049
00050 }
00051 }
00052
00053
00054 void GaussianTailNoiseGenerator::generate(int NumberOfchannels,
00055 float threshold,
00056 float noiseRMS,
00057 std::vector<std::pair<int,float> > &theVector ) {
00058
00059
00060 gsl_sf_result result;
00061 int status = gsl_sf_erf_Q_e(threshold, &result);
00062 if (status != 0) std::cerr<<"GaussianTailNoiseGenerator::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
00063 double probabilityLeft = result.val;
00064 double meanNumberOfNoisyChannels = probabilityLeft * NumberOfchannels;
00065 int numberOfNoisyChannels = poissonDistribution_.fire(meanNumberOfNoisyChannels);
00066 if(numberOfNoisyChannels>NumberOfchannels) numberOfNoisyChannels=NumberOfchannels;
00067
00068
00069 theVector.reserve(numberOfNoisyChannels);
00070 float lowLimit = threshold * noiseRMS;
00071 int* channels = getRandomChannels(numberOfNoisyChannels,NumberOfchannels);
00072
00073 for (int i = 0; i < numberOfNoisyChannels; i++) {
00074
00075 double noise = generate_gaussian_tail(lowLimit, noiseRMS);
00076
00077 theVector.push_back(std::pair<int, float>(channels[i], noise));
00078 }
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 void GaussianTailNoiseGenerator::generateRaw(float noiseRMS,
00098 std::vector<double> &theVector ) {
00099
00100
00101
00102
00103
00104 unsigned int numberOfchannels = theVector.size();
00105 for (unsigned int i = 0; i < numberOfchannels; ++i) {
00106 if(theVector[i]==0) theVector[i] = gaussDistribution_.fire(0.,noiseRMS);
00107 }
00108 }
00109
00110 int*
00111 GaussianTailNoiseGenerator::getRandomChannels(int numberOfNoisyChannels, int numberOfchannels) {
00112 if(numberOfNoisyChannels>numberOfchannels) numberOfNoisyChannels = numberOfchannels;
00113 int* array = channel512_;
00114 if(numberOfchannels==768) array = channel768_;
00115 int theChannelNumber;
00116 for(int j=0;j<numberOfNoisyChannels;++j) {
00117 theChannelNumber = (int)flatDistribution_.fire(numberOfchannels-j)+j;
00118
00119 int b = array[j];
00120 array[j] = array[theChannelNumber];
00121 array[theChannelNumber] = b;
00122 }
00123 return array;
00124 }
00125
00126 double
00127 GaussianTailNoiseGenerator::generate_gaussian_tail(const double a, const double sigma){
00128
00129
00130
00131
00132 double s = a/sigma;
00133
00134 if (s < 1){
00135
00136
00137
00138
00139 double x;
00140
00141 do{
00142 x = gaussDistribution_.fire(0.,1.0);
00143 }
00144 while (x < s);
00145 return x * sigma;
00146
00147 }else{
00148
00149
00150
00151
00152
00153
00154
00155 double u, v, x;
00156
00157 do{
00158 u = flatDistribution_.fire();
00159 do{
00160 v = flatDistribution_.fire();
00161 }while (v == 0.0);
00162 x = sqrt(s * s - 2 * log(v));
00163 }
00164 while (x * u > s);
00165 return x * sigma;
00166 }
00167 }