ATLAS Offline Software
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 
5 #include "TRTElectronicsNoise.h"
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()!
25  this->InitializeNoiseShaping();
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)
33  m_nbins_periodic = static_cast<int>(slowPeriod/binwidth + 0.5);
34 }
35 
36 //_____________________________________________________________________________
38 
39 //_____________________________________________________________________________
40 void 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);
60  index = m_noiseSignalShape.size();
61  }
62  }
63 }
64 
65 //_____________________________________________________________________________
66 double 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 //_____________________________________________________________________________
88 void 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 
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 //_____________________________________________________________________________
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 //___________________________________________________________________
277 double 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 }
max
#define max(a, b)
Definition: cfImp.cxx:41
TRTElectronicsNoise::m_tmpArray
std::vector< float > m_tmpArray
Here to avoid repeated memory allocs.
Definition: TRTElectronicsNoise.h:106
python.SystemOfUnits.nanosecond
int nanosecond
Definition: SystemOfUnits.py:119
TRTDigSettings::fastElectronicsNoisePulseDistance
double fastElectronicsNoisePulseDistance() const
Get fast electronics noise pulse distance (time)
TRTDigSettings.h
index
Definition: index.py:1
TRTElectronicsNoise::m_noisepars1
std::vector< double > m_noisepars1
Noise signal params 1 (t<15.5 ns)
Definition: TRTElectronicsNoise.h:123
binwidth
bool binwidth
Definition: listroot.cxx:58
TRTElectronicsNoise::m_nbins_periodic
unsigned int m_nbins_periodic
Definition: TRTElectronicsNoise.h:109
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
TRTElectronicsNoise::m_noisepars2
std::vector< double > m_noisepars2
Noise signal params 2 (t>15.5 ns)
Definition: TRTElectronicsNoise.h:124
TRTElectronicsNoise::reinitElectronicsNoise
void reinitElectronicsNoise(const unsigned int &numberOfDigitLengths, CLHEP::HepRandomEngine *rndmEngine)
Re-initialize electronics noise table.
Definition: TRTElectronicsNoise.cxx:88
TRTElectronicsNoise::m_noiseSignalShape
std::vector< double > m_noiseSignalShape
Tabulated noise signal shape.
Definition: TRTElectronicsNoise.h:99
SCT_CalibAlgs::nbins
@ nbins
Definition: SCT_CalibNumbers.h:10
LArG4FSStartPointFilter.rand
rand
Definition: LArG4FSStartPointFilter.py:80
lumiFormat.i
int i
Definition: lumiFormat.py:92
TRTElectronicsNoise::tabulateNoiseSignalShape
void tabulateNoiseSignalShape()
Tabulate noise signal shape.
Definition: TRTElectronicsNoise.cxx:169
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
TRTElectronicsNoise::m_cachedFastNoiseAfterSignalShaping
std::vector< float > m_cachedFastNoiseAfterSignalShaping
Cached samples of electronics noise after signal shaping (fast input)
Definition: TRTElectronicsNoise.h:102
TRTDigSettings::numberOfBins
unsigned int numberOfBins() const
Get number of time bins used for internal shaping of signal.
TRTElectronicsNoise::addElectronicsNoise
void addElectronicsNoise(std::vector< double > &signal, const double &noiseamplitude, CLHEP::HepRandomEngine *rndmEngine)
Add electronics noise to simulated signals in hit straws.
Definition: TRTElectronicsNoise.cxx:197
Cut::signal
@ signal
Definition: SUSYToolsAlg.cxx:64
TRTElectronicsNoise::m_settings
const TRTDigSettings * m_settings
Definition: TRTElectronicsNoise.h:79
VP1PartSpect::E
@ E
Definition: VP1PartSpectFlags.h:21
TRTDigSettings::slowPeriodicNoisePulseDistance
double slowPeriodicNoisePulseDistance() const
Get slow periodic noise pulse distance (time)
TRTElectronicsNoise.h
TRTElectronicsNoise::TRTElectronicsNoise
TRTElectronicsNoise(const TRTDigSettings *, CLHEP::HepRandomEngine *rndmEngine)
Constructor: Calls tabulateNoiseSignalShape()
Definition: TRTElectronicsNoise.cxx:20
TRTElectronicsNoise::getMax
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.
Definition: TRTElectronicsNoise.cxx:66
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
TRTDigSettings::timeInterval
double timeInterval() const
Get time interval covered by each digit.
TRTElectronicsNoise::~TRTElectronicsNoise
~TRTElectronicsNoise()
Destructor.
TRTElectronicsNoise::m_fractionOfSlowNoise
double m_fractionOfSlowNoise
Definition: TRTElectronicsNoise.h:108
TRTElectronicsNoise::InitializeNoiseShaping
void InitializeNoiseShaping()
Initialize signal shaping.
Definition: TRTElectronicsNoise.cxx:252
TRTElectronicsNoise::NoiseShape
double NoiseShape(const double &time) const
Get parameterized signal shape for noise hits.
Definition: TRTElectronicsNoise.cxx:277
TRTDigSettings
Class containing parameters and settings used by TRT digitization.
Definition: TRTDigSettings.h:35
TRTElectronicsNoise::getSamplesOfMaxLTOverNoiseAmp
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...
Definition: TRTElectronicsNoise.cxx:40
updateCoolNtuple.limit
int limit
Definition: updateCoolNtuple.py:45
TRTElectronicsNoise::m_cachedSlowNoiseAfterSignalShaping
std::vector< float > m_cachedSlowNoiseAfterSignalShaping
Cached samples of electronics noise after signal shaping (slow input)
Definition: TRTElectronicsNoise.h:104
TRTDigSettings::slowPeriodicNoisePulseFraction
double slowPeriodicNoisePulseFraction() const
Get slow periodic noise pulse fraction.