ATLAS Offline Software
Loading...
Searching...
No Matches
TRTElectronicsNoise.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "CLHEP/Units/SystemOfUnits.h"
8
9// For the Athena-based random numbers.
10#include "CLHEP/Random/RandFlat.h"
11#include "CLHEP/Random/RandGaussZiggurat.h"
12#include "CLHEP/Random/RandomEngine.h"
13
14#include "TRTDigSettings.h"
15
16#include <cmath>
17#include <cstdlib>
18
19//_____________________________________________________________________________
21 CLHEP::HepRandomEngine *elecNoiseRndmEngine )
22 : m_settings(digset)
23{
24 //Need to initialize the signal shaping first as it is used in tabulateNoiseSignalShape()!
26 m_fractionOfSlowNoise = m_settings->slowPeriodicNoisePulseFraction();
28 this->reinitElectronicsNoise(200, elecNoiseRndmEngine);
29 const double slowPeriod(m_settings->slowPeriodicNoisePulseDistance());
30
31 //Must be rounded to nearest multiple of binwidth... (fixme - from options)
32 const double binwidth(m_settings->timeInterval()/m_settings->numberOfBins());
33 m_nbins_periodic = static_cast<int>(slowPeriod/binwidth + 0.5);
34}
35
36//_____________________________________________________________________________
38
39//_____________________________________________________________________________
40void TRTElectronicsNoise::getSamplesOfMaxLTOverNoiseAmp(std::vector<float>& maxLTOverNoiseAmp,
41 unsigned long nsamplings, CLHEP::HepRandomEngine* rndmEngine) {
42
43 // Note: The offset structure is not the same as in
44 // addElectronicsNoise(), but that is OK, since it is not the exact
45 // time-structure we are looking for here - but only the distribution
46 // of the highest amplitude.
47
48 maxLTOverNoiseAmp.resize(nsamplings);
49
50 reinitElectronicsNoise(500, rndmEngine);
51 unsigned int index = m_noiseSignalShape.size();
52 unsigned int nbinsinperiod = m_settings->numberOfBins();
53 unsigned int maxindex = m_cachedFastNoiseAfterSignalShaping.size() - nbinsinperiod;
54
55 for (unsigned int i = 0; i < nsamplings; ++i) {
56 maxLTOverNoiseAmp[i] = getMax(index, index, nbinsinperiod );
57 index += nbinsinperiod;
58 if ( index > maxindex ) {
59 reinitElectronicsNoise(500, rndmEngine);
61 }
62 }
63}
64
65//_____________________________________________________________________________
66double TRTElectronicsNoise::getMax(unsigned int firstbinslowsignal,
67 unsigned int firstbinfastsignal,
68 const unsigned int& binsinwindow )
69{
70
71 // This method assumes that firstbinslowsignal + binsinwindow doesn't
72 // exceed the cached array sizes (and same for fastsignal).
73
74 double max = -99999.0;
75 unsigned int lastslowbinplusone = firstbinslowsignal + binsinwindow;
76
77 while( firstbinslowsignal < lastslowbinplusone ) {
78 double totalsig =
79 m_cachedFastNoiseAfterSignalShaping[firstbinfastsignal++] +
80 m_cachedSlowNoiseAfterSignalShaping[firstbinslowsignal++];
81 if ( max<totalsig ) max = totalsig;
82 };
83
84 return max;
85}
86
87//_____________________________________________________________________________
88void TRTElectronicsNoise::reinitElectronicsNoise(const unsigned int& numberOfDigitLengths /*number of 75ns timeslices*/,
89 CLHEP::HepRandomEngine* rndmEngine)
90{
91 //This method gives the actual physics shape!
92 //Model parameters:
93
94 const double fastPeriod = m_settings->fastElectronicsNoisePulseDistance();
95 //Must be rounded to nearest multiple of binwidth... (fixme - from options)
96
97 const double slowPeriod = m_settings->slowPeriodicNoisePulseDistance();
98 //Must be rounded to nearest multiple of binwidth... (fixme - from options)
99
100 //For consistency we start the arrays a little earlier than the bins we use -
101 //the time back from where the signal shaping could carry a pulse:
102 unsigned int nbins = m_noiseSignalShape.size() + numberOfDigitLengths * m_settings->numberOfBins();
103
106
107 m_tmpArray.resize(nbins);
108
109 const double invbinwidth(m_settings->numberOfBins() / m_settings->timeInterval());
110 double timeOfNextPulse;
111 unsigned int binindex;
112
113 //### Fast signal:
114 double fractionOfFastNoise = 1.0-m_fractionOfSlowNoise;
115
116 //### First we produce the noise as it is BEFORE signal shaping:
117 for (unsigned int i(0); i < nbins; ++i) {
118 m_tmpArray[i] = 0.;
120 }
121
122 timeOfNextPulse = 0.5 * fastPeriod;
123 while ( true ) {
124 binindex = static_cast<unsigned int>(timeOfNextPulse*invbinwidth);
125 if (binindex >= nbins) break;
126 m_tmpArray[binindex] += CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., 1.);
127 timeOfNextPulse += fastPeriod;
128 };
129
130 //### Then (Anatolis) signal shaping:
131 for (unsigned int i(0); i < nbins; ++i) {
132 unsigned int limit(i+m_noiseSignalShape.size());
133 if ( limit > nbins ) limit = nbins;
134 for (unsigned int j(i); j < limit; ++j) {
136 m_tmpArray[i] * m_noiseSignalShape[j-i] * fractionOfFastNoise;
137 };
138 };
139
140 //### Slow periodic signal
141 for (unsigned int i(0); i < nbins; ++i) {
142 m_tmpArray[i] = 0.;
144 }
145
146 //### First we produce the noise as it is BEFORE signal shaping:
147 timeOfNextPulse = 0.5 * slowPeriod;
148 while (true) {
149 binindex = static_cast<unsigned int>(timeOfNextPulse*invbinwidth);
150 if (binindex >= nbins) break;
151 m_tmpArray[binindex] += CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0., 1.);
152 timeOfNextPulse += slowPeriod;
153 };
154
155 //### Then (Anatolis) signal shaping:
156 for (unsigned int i(0); i < nbins; ++i) {
157 unsigned int limit(i+m_noiseSignalShape.size());
158 if (limit > nbins) limit = nbins;
159 for (unsigned int j(i); j < limit; ++j) {
163 };
164 };
165
166}
167
168//_____________________________________________________________________________
170
171 m_noiseSignalShape.resize(0);
172
173 const double binwidth(m_settings->timeInterval()/m_settings->numberOfBins());
174
175 //Tabulate:
176 double shapemax = 0;
177 for ( double time(0.5*binwidth); time < m_settings->timeInterval(); time += binwidth ) {
178 m_noiseSignalShape.push_back(this->NoiseShape(time));
179 shapemax = std::max(shapemax,std::abs(m_noiseSignalShape.back()));
180 }
181
182 //Cut of trailing zeroes:
183 unsigned int noiseshapebins(m_noiseSignalShape.size()-1);
184 for ( ;noiseshapebins>0;--noiseshapebins) {
185 if (m_noiseSignalShape.at(noiseshapebins-1)>0.001*shapemax) break;
186 }
187 m_noiseSignalShape.resize(noiseshapebins);
188
189 //Normalize:
190 for (double & i : m_noiseSignalShape) {
191 i /= shapemax;
192 };
193
194}
195
196//_____________________________________________________________________________
197void TRTElectronicsNoise::addElectronicsNoise(std::vector<double>& signal,
198 const double& noiseamplitude,
199 CLHEP::HepRandomEngine *rndmEngine) {
200
201 // complain if uninitialized? (fixme)
202
203 // We "smear" the 25ns signal (simulating the fact that different
204 // straws have different offsets):
205 //
206 // Effectively, in 64% of the cases we choose the shift randomly in
207 // the interval [-1.56ns,3.9ns], and in the remaining 36% we choose
208 // the shift randomly in [4.7ns,17.97ns]. This scheme seems to
209 // reproduce the features of data well.
210
211 static const unsigned int n_slowperiodic_shift = 26;
212 static const int slowperiodic_constshift = -2;
213 static const double slowperiodic_shift_prob_comul[n_slowperiodic_shift] =
214 {0.08, 0.16, 0.24, 0.32, 0.40, 0.48, 0.56, 0.64, 0.66, 0.68,
215 0.70, 0.72, 0.74, 0.76, 0.78, 0.80, 0.82, 0.84, 0.86, 0.88,
216 0.90, 0.92, 0.94, 0.96, 0.98, 1.00};
217
218 //Find array offset for fast signal:
219 const unsigned int nsignalbins(signal.size());
220 const unsigned int offset_fast(CLHEP::RandFlat::shootInt(rndmEngine, m_cachedFastNoiseAfterSignalShaping.size()-nsignalbins));
221
222 //Find array offset for slow periodic signal:
223 int offset_slowperiodic(CLHEP::RandFlat::shootInt(rndmEngine,
225 - nsignalbins-n_slowperiodic_shift
226 - slowperiodic_constshift));
227
228 offset_slowperiodic -= ( offset_slowperiodic % m_nbins_periodic );
229 offset_slowperiodic -= slowperiodic_constshift;
230
231 const double rand(CLHEP::RandFlat::shoot(rndmEngine, 0., 1.));
232 for (unsigned int i(0); i < n_slowperiodic_shift; ++i) {
233 if ( rand < slowperiodic_shift_prob_comul[i] ) {
234 offset_slowperiodic -= i;
235 break;
236 };
237 };
238
239 //Fix for rare case when offset becomes negative
240 if (offset_slowperiodic<0)
241 offset_slowperiodic += (((-offset_slowperiodic)%m_nbins_periodic)+1)*m_nbins_periodic;
242
243 //Add the two components to the signal:
244 for ( unsigned int i(0); i<nsignalbins; ++i) {
245 signal[i] += noiseamplitude *
246 ( m_cachedFastNoiseAfterSignalShaping[offset_fast + i] +
247 m_cachedSlowNoiseAfterSignalShaping[offset_slowperiodic + i] );
248 };
249}
250
251//_____________________________________________________________________________
253
254 // For now we hardcode the noise shape parameters here:
255 // (I am not sure they make much sense in the DB in any case - a simple version flag should suffice).
256 // According to Anatoli, this shape can be the same for Xe, Kr and Ar.
257 m_noisepars1.clear();
258 m_noisepars1.push_back(263.1021);//N
259 m_noisepars1.push_back(4.611810);//mu
260 m_noisepars1.push_back(8.496722);//sigma
261 m_noisepars1.push_back(-226.9187);//a
262 m_noisepars1.push_back(-15.15887);//+bt
263 m_noisepars1.push_back(2.833467);//+ct**2
264 m_noisepars1.push_back(-.8981638E-01);//+dt**3
265 m_noisepars2.clear();
266 m_noisepars2.push_back(-131.7723);//N
267 m_noisepars2.push_back(12.94000);//mu
268 m_noisepars2.push_back(8.107412);//sigma
269 m_noisepars2.push_back(276.7422);//a
270 m_noisepars2.push_back(-6.767590);//+bt
271 m_noisepars2.push_back(-.3214721);//+ct**2
272 m_noisepars2.push_back(.8512509E-02);//+dt**3
273
274}
275
276//___________________________________________________________________
277double TRTElectronicsNoise::NoiseShape(const double& time) const {
278
279 //convert to nanoseconds:
280 const double time_ns(time/CLHEP::nanosecond);
281
282 if ( time_ns<0 || time_ns > 32 ) return 0;
283
284 double tmp(0);
285 for (unsigned int i(6); i>=4; --i) {
286 if (time_ns<15.5)
287 tmp = (tmp + m_noisepars1[i])*time_ns;
288 else
289 tmp = (tmp + m_noisepars2[i])*time_ns;
290 };
291
292 if (time_ns<15.5)
293 tmp += m_noisepars1[0]*exp(-0.5*((time_ns-m_noisepars1[1])/m_noisepars1[2])
294 *((time_ns-m_noisepars1[1])/m_noisepars1[2])) + m_noisepars1[3];
295 else
296 tmp += m_noisepars2[0]*exp(-0.5*((time_ns-m_noisepars2[1])/m_noisepars2[2])
297 *((time_ns-m_noisepars2[1])/m_noisepars2[2])) + m_noisepars2[3];
298
299 tmp *= 0.001;
300
301 return tmp;
302
303}
#define max(a, b)
Definition cfImp.cxx:41
Class containing parameters and settings used by TRT digitization.
TRTElectronicsNoise(const TRTDigSettings *, CLHEP::HepRandomEngine *rndmEngine)
Constructor: Calls tabulateNoiseSignalShape()
void getSamplesOfMaxLTOverNoiseAmp(std::vector< float > &maxLTOverNoiseAmp, unsigned long nsamplings, CLHEP::HepRandomEngine *rndmEngine)
From generated (and cached) noise samples, this function returns in vector maxLTOverNoiseAmp the maxi...
std::vector< double > m_noisepars2
Noise signal params 2 (t>15.5 ns)
std::vector< float > m_cachedFastNoiseAfterSignalShaping
Cached samples of electronics noise after signal shaping (fast input)
void addElectronicsNoise(std::vector< double > &signal, const double &noiseamplitude, CLHEP::HepRandomEngine *rndmEngine)
Add electronics noise to simulated signals in hit straws.
std::vector< double > m_noisepars1
Noise signal params 1 (t<15.5 ns)
void InitializeNoiseShaping()
Initialize signal shaping.
void reinitElectronicsNoise(const unsigned int &numberOfDigitLengths, CLHEP::HepRandomEngine *rndmEngine)
Re-initialize electronics noise table.
const TRTDigSettings * m_settings
double NoiseShape(const double &time) const
Get parameterized signal shape for noise hits.
std::vector< double > m_noiseSignalShape
Tabulated noise signal shape.
~TRTElectronicsNoise()
Destructor.
void tabulateNoiseSignalShape()
Tabulate noise signal shape.
double getMax(unsigned int firstbinslowsignal, unsigned int firstbinfastsignal, const unsigned int &binsinwindow)
Get max amplitude of noise signal from weighted sum of fast and slow varying noise in period.
std::vector< float > m_tmpArray
Here to avoid repeated memory allocs.
std::vector< float > m_cachedSlowNoiseAfterSignalShaping
Cached samples of electronics noise after signal shaping (slow input)
bool binwidth
Definition listroot.cxx:58
Definition index.py:1