CMS 3D CMS Logo

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