CMS 3D CMS Logo

GaussianTailNoiseGenerator.cc
Go to the documentation of this file.
2 #include "CLHEP/Random/RandPoissonQ.h"
3 #include "CLHEP/Random/RandGaussQ.h"
4 #include "CLHEP/Random/RandFlat.h"
5 
6 #include <cmath>
7 
8 #include <gsl/gsl_sf_erf.h>
9 #include <gsl/gsl_sf_result.h>
10 
12  // we have two cases: 512 and 768 channels
13  // other cases are not allowed so far (performances issue)
14  for(unsigned int i=0;i<512;++i) channel512_[i]=i;
15  for(unsigned int i=0;i<768;++i) channel768_[i]=i;
16 }
17 
18 // this version is used by pixel
19 void GaussianTailNoiseGenerator::generate(int NumberOfchannels,
20  float threshold,
21  float noiseRMS,
22  std::map<int,float, std::less<int> >& theMap,
23  CLHEP::HepRandomEngine* engine ) {
24 
25  // Gaussian tail probability
26  gsl_sf_result result;
27  int status = gsl_sf_erf_Q_e(threshold, &result);
28 
29  if (status != 0) std::cerr<<"GaussianTailNoiseGenerator::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
30 
31  float probabilityLeft = result.val;
32  float meanNumberOfNoisyChannels = probabilityLeft * NumberOfchannels;
33 
34  CLHEP::RandPoissonQ randPoissonQ(*engine, meanNumberOfNoisyChannels);
35  int numberOfNoisyChannels = randPoissonQ.fire();
36 
37  float lowLimit = threshold * noiseRMS;
38  for (int i = 0; i < numberOfNoisyChannels; i++) {
39 
40  // Find a random channel number
41  int theChannelNumber = (int)CLHEP::RandFlat::shoot(engine, NumberOfchannels);
42 
43  // Find random noise value
44  double noise = generate_gaussian_tail(lowLimit, noiseRMS, engine);
45 
46  // Fill in map
47  theMap[theChannelNumber] = noise;
48 
49  }
50 }
51 
52 // this version is used by strips
53 void GaussianTailNoiseGenerator::generate(int NumberOfchannels,
54  float threshold,
55  float noiseRMS,
56  std::vector<std::pair<int,float> > &theVector,
57  CLHEP::HepRandomEngine* engine ) {
58  // Compute number of channels with noise above threshold
59  // Gaussian tail probability
60  gsl_sf_result result;
61  int status = gsl_sf_erf_Q_e(threshold, &result);
62  if (status != 0) std::cerr<<"GaussianTailNoiseGenerator::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
63  double probabilityLeft = result.val;
64  double meanNumberOfNoisyChannels = probabilityLeft * NumberOfchannels;
65 
66  CLHEP::RandPoissonQ randPoissonQ(*engine, meanNumberOfNoisyChannels);
67  int numberOfNoisyChannels = randPoissonQ.fire();
68 
69  if(numberOfNoisyChannels>NumberOfchannels) numberOfNoisyChannels=NumberOfchannels;
70 
71  // Compute the list of noisy channels
72  theVector.reserve(numberOfNoisyChannels);
73  float lowLimit = threshold * noiseRMS;
74  int* channels = getRandomChannels(numberOfNoisyChannels,NumberOfchannels, engine);
75 
76  for (int i = 0; i < numberOfNoisyChannels; i++) {
77  // Find random noise value
78  double noise = generate_gaussian_tail(lowLimit, noiseRMS, engine);
79  // Fill in the vector
80  theVector.push_back(std::pair<int, float>(channels[i], noise));
81  }
82 }
83 
84 /*
85 // used by strips in VR mode
86 void GaussianTailNoiseGenerator::generateRaw(int NumberOfchannels,
87  float noiseRMS,
88  std::vector<std::pair<int,float> > &theVector,
89  CLHEP::HepRandomEngine* engine ) {
90  theVector.reserve(NumberOfchannels);
91  for (int i = 0; i < NumberOfchannels; i++) {
92  // Find random noise value
93  float noise = CLHEP::RandGaussQ::shoot(engine, 0., noiseRMS);
94  // Fill in the vector
95  theVector.push_back(std::pair<int, float>(i,noise));
96  }
97 }
98 */
99 
100 // used by strips in VR mode
102  std::vector<double> &theVector,
103  CLHEP::HepRandomEngine* engine ) {
104  // it was shown that a complex approach, inspired from the ZS case,
105  // does not allow to gain much.
106  // A cut at 2 sigmas only saves 25% of the processing time, while the cost
107  // in terms of meaning is huge.
108  // We therefore use here the trivial approach (as in the early 2XX cycle)
109  unsigned int numberOfchannels = theVector.size();
110  for (unsigned int i = 0; i < numberOfchannels; ++i) {
111  if(theVector[i]==0) theVector[i] = CLHEP::RandGaussQ::shoot(engine, 0., noiseRMS);
112  }
113 }
114 
115 int*
116 GaussianTailNoiseGenerator::getRandomChannels(int numberOfNoisyChannels, int numberOfchannels, CLHEP::HepRandomEngine* engine) {
117  if(numberOfNoisyChannels>numberOfchannels) numberOfNoisyChannels = numberOfchannels;
118  int* array = channel512_;
119  if(numberOfchannels==768) array = channel768_;
120  int theChannelNumber;
121  for(int j=0;j<numberOfNoisyChannels;++j) {
122  theChannelNumber = (int)CLHEP::RandFlat::shoot(engine, numberOfchannels-j) + j;
123  // swap the two array elements... this is optimized by the compiler
124  int b = array[j];
125  array[j] = array[theChannelNumber];
126  array[theChannelNumber] = b;
127  }
128  return array;
129 }
130 
131 double
132 GaussianTailNoiseGenerator::generate_gaussian_tail(const double a, const double sigma, CLHEP::HepRandomEngine* engine){
133  /* Returns a gaussian random variable larger than a
134  * This implementation does one-sided upper-tailed deviates.
135  */
136 
137  double s = a/sigma;
138 
139  if (s < 1){
140  /*
141  For small s, use a direct rejection method. The limit s < 1
142  can be adjusted to optimise the overall efficiency
143  */
144  double x;
145 
146  do{
147  x = CLHEP::RandGaussQ::shoot(engine, 0., 1.0);
148  }
149  while (x < s);
150  return x * sigma;
151 
152  }else{
153 
154  /* Use the "supertail" deviates from the last two steps
155  * of Marsaglia's rectangle-wedge-tail method, as described
156  * in Knuth, v2, 3rd ed, pp 123-128. (See also exercise 11, p139,
157  * and the solution, p586.)
158  */
159 
160  double u, v, x;
161 
162  do{
163  u = CLHEP::RandFlat::shoot(engine);
164  do{
165  v = CLHEP::RandFlat::shoot(engine);
166  }while (v == 0.0);
167  x = sqrt(s * s - 2 * log(v));
168  }
169  while (x * u > s);
170  return x * sigma;
171  }
172 }
double generate_gaussian_tail(const double, const double, CLHEP::HepRandomEngine *)
T sqrt(T t)
Definition: SSEVec.h:18
void generate(int NumberOfchannels, float threshold, float noiseRMS, std::map< int, float > &theMap, CLHEP::HepRandomEngine *)
int * getRandomChannels(int, int, CLHEP::HepRandomEngine *)
double b
Definition: hdecay.h:120
double a
Definition: hdecay.h:121
void generateRaw(float noiseRMS, std::vector< double > &, CLHEP::HepRandomEngine *)