CMS 3D CMS Logo

ESDigitizer.cc
Go to the documentation of this file.
5 
6 #include "CLHEP/Random/RandGeneral.h"
7 #include "CLHEP/Random/RandPoissonQ.h"
8 #include "CLHEP/Random/RandFlat.h"
9 
10 #include <gsl/gsl_sf_erf.h>
11 #include <gsl/gsl_sf_result.h>
12 
14  ESElectronicsSimFast* electronicsSim ,
15  bool addNoise ) :
16  EcalTDigitizer< ESDigitizerTraits >( hitResponse, electronicsSim, addNoise ) ,
17  m_detIds ( nullptr ) ,
18  m_ranGeneral ( nullptr ) ,
19  m_ESGain ( 0 ) ,
20  m_histoBin ( 0 ) ,
21  m_histoInf ( 0 ) ,
22  m_histoWid ( 0 ) ,
23  m_meanNoisy ( 0 ) ,
24  m_trip ( )
25 {
26  m_trip.reserve( 2500 ) ;
27 }
28 
30 {
31  delete m_ranGeneral ;
32 }
33 
35 void
36 ESDigitizer::setDetIds( const std::vector<DetId>& detIds )
37 {
38  assert( nullptr == m_detIds ||
39  &detIds == m_detIds ) ; // sanity check; don't allow to change midstream
40  m_detIds = &detIds ;
41 }
42 
43 void
45 {
46  if( 0 != m_ESGain )
47  {
48  assert( gain == m_ESGain ) ; // only allow one value
49  }
50  else
51  {
52  assert( nullptr != m_detIds &&
53  !m_detIds->empty() ) ; // detIds must already be set as we need size
54 
55  assert( 1 == gain ||
56  2 == gain ) ; // legal values
57 
58  m_ESGain = gain ;
59 
60  if( addNoise() )
61  {
62  double zsThresh ( 0. ) ;
63  std::string refFile ;
64 
65  if( 1 == m_ESGain )
66  {
67  zsThresh = 3 ;
68  refFile = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_LG.txt";
69  }
70  else
71  {
72  zsThresh = 4 ;
73  refFile = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_HG.txt";
74  }
75 
76  gsl_sf_result result ;
77  int status = gsl_sf_erf_Q_e( zsThresh, &result ) ;
78  if( status != 0 ) std::cerr << "ESDigitizer::could not compute gaussian tail probability for the threshold chosen" << std::endl ;
79 
80  const double probabilityLeft ( result.val ) ;
81  m_meanNoisy = probabilityLeft * m_detIds->size() ;
82 
83  std::ifstream histofile ( edm::FileInPath( refFile ).fullPath().c_str() ) ;
84  if( !histofile.good() )
85  {
87  << "Reference histos file not opened" ;
88  }
89  else
90  {
91  // number of bins
92  char buffer[200] ;
93  int thisLine = 0 ;
94  while( 0 == thisLine )
95  {
96  histofile.getline( buffer, 200 ) ;
97  if( !strstr(buffer,"#") &&
98  !(strspn(buffer," ") == strlen(buffer) ) )
99  {
100  float histoBin ;
101  sscanf( buffer, "%f" , &histoBin ) ;
102  m_histoBin = (double) histoBin ;
103  ++thisLine ;
104  }
105  }
106  const uint32_t histoBin1 ( (int) m_histoBin ) ;
107  const uint32_t histoBin2 ( histoBin1*histoBin1 ) ;
108 
109  double t_histoSup ( 0 ) ;
110 
111  std::vector<double> t_refHistos ;
112  t_refHistos.reserve( 2500 ) ;
113 
114  int thisBin = -2 ;
115  while( !( histofile.eof() ) )
116  {
117  histofile.getline( buffer, 200 ) ;
118  if( !strstr( buffer, "#" ) &&
119  !( strspn( buffer, " " ) == strlen( buffer ) ) )
120  {
121  if( -2 == thisBin )
122  {
123  float histoInf ;
124  sscanf( buffer, "%f" , &histoInf ) ;
125  m_histoInf = (double) histoInf ;
126  }
127  if( -1 == thisBin )
128  {
129  float histoSup ;
130  sscanf( buffer, "%f" , &histoSup ) ;
131  t_histoSup = (double) histoSup ;
132  }
133  if( 0 <= thisBin )
134  {
135  float refBin ;
136  sscanf( buffer, "%f", &refBin ) ;
137  if( 0.5 < refBin )
138  {
139  t_refHistos.push_back( (double) refBin ) ;
140  const uint32_t i2 ( thisBin/histoBin2 ) ;
141  const uint32_t off ( i2*histoBin2 ) ;
142  const uint32_t i1 ( ( thisBin - off )/histoBin1 ) ;
143  const uint32_t i0 ( thisBin - off - i1*histoBin1 ) ;
144  m_trip.emplace_back(i0, i1, i2) ;
145  }
146  }
147  ++thisBin ;
148  }
149  }
150  m_histoWid = ( t_histoSup - m_histoInf )/m_histoBin ;
151 
152  m_histoInf -= 1000. ;
153 
154  // creating the reference distribution to extract random numbers
155  m_ranGeneral = new CLHEP::RandGeneral( nullptr ,
156  &t_refHistos.front() ,
157  t_refHistos.size() ,
158  0 ) ;
159  histofile.close();
160  }
161  }
162  }
163 }
164 
166 void
167 ESDigitizer::run( ESDigiCollection& output, CLHEP::HepRandomEngine* engine )
168 {
169  assert( nullptr != m_detIds &&
170  !m_detIds->empty() &&
171  ( !addNoise() ||
172  nullptr != m_ranGeneral ) ) ; // sanity check
173 
174  // reserve space for how many digis we expect, with some cushion
175  output.reserve( 2*( (int) m_meanNoisy ) + hitResponse()->samplesSize() ) ;
176 
177  EcalTDigitizer< ESDigitizerTraits >::run( output, engine ) ;
178 
179  // random generation of channel above threshold
180  std::vector<DetId> abThreshCh ;
181  if( addNoise() ) createNoisyList( abThreshCh, engine ) ;
182 
183  // first make a raw digi for every cell where we have noise
184  for( std::vector<DetId>::const_iterator idItr ( abThreshCh.begin() ) ;
185  idItr != abThreshCh.end(); ++idItr )
186  {
187  if( hitResponse()->findDetId( *idItr )->zero() ) // only if no true hit!
188  {
189  ESHitResponse::ESSamples analogSignal ( *idItr, 3 ) ; // space for the noise hit
190  uint32_t myBin ( (uint32_t) m_trip.size()*m_ranGeneral->shoot(engine) ) ;
191  if( myBin == m_trip.size() ) --myBin ; // guard against roundup
192  assert( myBin < m_trip.size() ) ;
193  const Triplet& trip ( m_trip[ myBin ] ) ;
194  analogSignal[ 0 ] = m_histoInf + m_histoWid*trip.first ;
195  analogSignal[ 1 ] = m_histoInf + m_histoWid*trip.second ;
196  analogSignal[ 2 ] = m_histoInf + m_histoWid*trip.third ;
197  ESDataFrame digi( *idItr ) ;
198  const_cast<ESElectronicsSimFast*>(elecSim())->
199  analogToDigital( engine,
200  analogSignal ,
201  digi ,
202  true ) ;
203  output.push_back( std::move(digi) ) ;
204  }
205  }
206 }
207 
208 // preparing the list of channels where the noise has to be generated
209 void
210 ESDigitizer::createNoisyList( std::vector<DetId>& abThreshCh, CLHEP::HepRandomEngine* engine )
211 {
212  CLHEP::RandPoissonQ randPoissonQ(*engine, m_meanNoisy);
213  const unsigned int nChan (randPoissonQ.fire());
214  abThreshCh.reserve( nChan ) ;
215 
216  for( unsigned int i ( 0 ) ; i != nChan ; ++i )
217  {
218  std::vector<DetId>::const_iterator idItr ( abThreshCh.end() ) ;
219  uint32_t iChan ( 0 ) ;
220  DetId id ;
221  do
222  {
223  iChan = (uint32_t) CLHEP::RandFlat::shoot(engine, m_detIds->size());
224  if( iChan == m_detIds->size() ) --iChan ; //protect against roundup at end
225  assert( m_detIds->size() > iChan ) ; // sanity check
226  id = (*m_detIds)[ iChan ] ;
227  idItr = find( abThreshCh.begin() ,
228  abThreshCh.end() ,
229  id ) ;
230  }
231  while( idItr != abThreshCh.end() ) ;
232 
233  abThreshCh.push_back( std::move(id) ) ;
234  }
235 }
void setDetIds(const std::vector< DetId > &detIds)
tell the digitizer which cells exist; cannot change during a run
Definition: ESDigitizer.cc:36
std::vector< Triplet > m_trip
Definition: ESDigitizer.h:61
#define nullptr
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
const EcalSamples * findDetId(const DetId &detId) const
const ElectronicsSim * elecSim() const
CLHEP::RandGeneral * m_ranGeneral
Definition: ESDigitizer.h:37
void createNoisyList(std::vector< DetId > &abThreshCh, CLHEP::HepRandomEngine *)
Definition: ESDigitizer.cc:210
void setGain(const int gain)
Definition: ESDigitizer.cc:44
double m_meanNoisy
Definition: ESDigitizer.h:42
double m_histoBin
Definition: ESDigitizer.h:39
double m_histoInf
Definition: ESDigitizer.h:40
void reserve(size_t isize)
Definition: DetId.h:18
const std::vector< DetId > * m_detIds
Definition: ESDigitizer.h:36
~ESDigitizer() override
Definition: ESDigitizer.cc:29
void push_back(unsigned int i)
virtual void run(DigiCollection &output, CLHEP::HepRandomEngine *)
void run(ESDigiCollection &output, CLHEP::HepRandomEngine *) override
turns hits into digis
Definition: ESDigitizer.cc:167
double m_histoWid
Definition: ESDigitizer.h:41
const EcalHitResponse * hitResponse() const
ESDigitizer(EcalHitResponse *hitResponse, ElectronicsSim *electronicsSim, bool addNoise)
Definition: ESDigitizer.cc:13
def move(src, dest)
Definition: eostools.py:511
bool zero() const