CMS 3D CMS Logo

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