CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ESFastTDigitizer.h
Go to the documentation of this file.
1 #ifndef EcalSimAlgos_ESFastTDigitizer_h
2 #define EcalSimAlgos_ESFastTDigitizer_h
3 
4 /* Based on CaloTDigitizer
5  Turns hits into digis. Assumes that
6  there's an ESElectronicsSimFast class with the
7  interface analogToDigital(const CaloSamples &, Digi &);
8 */
15 
16 #include "CLHEP/Random/RandGeneral.h"
17 #include "CLHEP/Random/RandPoissonQ.h"
18 #include "CLHEP/Random/RandFlat.h"
19 #include <gsl/gsl_sf_erf.h>
20 #include <gsl/gsl_sf_result.h>
21 
22 #include "TH3F.h"
23 #include <vector>
24 #include <cstdlib>
25 
27 {
28  public:
29 
30  ESFastTDigitizer(CaloHitResponse * hitResponse, ESElectronicsSimFast * electronicsSim, bool addNoise, int numESdetId)
31  : theHitResponse(hitResponse),
33  theElectronicsSim(electronicsSim),
34  theDetIds(0),
35  addNoise_(addNoise),
36  numESdetId_(numESdetId),
37  refHistos_ ( 0 ),
39  {
40 
41  setRefFile_ = true;
42 
43  }
44 
46  { delete histoDistribution_;
47  delete [] refHistos_; }
48 
50  void setGain (const int gain) {
51 
52  ESGain_ = gain;
53 
54  if (ESGain_ == 1) {
55  zsThreshold_ = 3;
56  refFile_ = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_LG.txt";
57  } else if (ESGain_ == 2) {
58  zsThreshold_ = 4;
59  refFile_ = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_HG.txt";
60  }
61 
62  if (addNoise_ && setRefFile_) {
64  setRefFile_ = false;
65  }
66  }
67 
70 
71  m_histofile = new ifstream (edm::FileInPath(refFile_).fullPath().c_str());
72  if (m_histofile == 0){
74  << "Reference histos file not opened" ;
75  return ;
76  }
77 
78  // number of bins
79  char buffer[200];
80  int thisLine = 0;
81  while( thisLine==0 ) {
82  m_histofile->getline(buffer,400);
83  if (!strstr(buffer,"#") && !(strspn(buffer," ") == strlen(buffer))){
84  float histoBin;
85  sscanf(buffer,"%f",&histoBin);
86  histoBin_ = (double)histoBin;
87  thisLine++;
88  }
89  }
90  int histoBin3 = (int)(histoBin_*histoBin_*histoBin_);
91  refHistos_ = new double[histoBin3];
92 
93  // all info
94  int thisBin = -2;
95  while( !(m_histofile->eof()) ){
96  m_histofile->getline(buffer,400);
97  if (!strstr(buffer,"#") && !(strspn(buffer," ") == strlen(buffer))){
98  if(thisBin==-2){ float histoInf; sscanf(buffer,"%f",&histoInf); histoInf_ = (double)histoInf; }
99  if(thisBin==-1){ float histoSup; sscanf(buffer,"%f",&histoSup); histoSup_ = (double)histoSup; }
100 
101  if (thisBin>=0){
102  float refBin;
103  sscanf(buffer,"%f",&refBin);
104  refHistos_[thisBin] = (double)refBin;
105  }
106  thisBin++;
107  }
108  }
109 
110  // creating the reference distribution to extract random numbers
112  if ( ! rng.isAvailable()) {
113  throw cms::Exception("Configuration")
114  << "ESFastTDigitizer requires the RandomNumberGeneratorService\n"
115  "which is not present in the configuration file. You must add the service\n"
116  "in the configuration file or remove the modules that require it.";
117  }
118  CLHEP::HepRandomEngine& engine = rng->getEngine();
119  histoDistribution_ = new CLHEP::RandGeneral(engine, refHistos_, histoBin3, 0);
120 
121  m_histofile->close();
122  delete m_histofile;
123  }
124 
126  void createNoisyList(std::vector<int> & abThreshCh) {
127 
129  if ( ! rng.isAvailable()) {
130  throw cms::Exception("Configuration")
131  << "ESFastTDigitizer requires the RandomNumberGeneratorService\n"
132  "which is not present in the configuration file. You must add the service\n"
133  "in the configuration file or remove the modules that require it.";
134  }
135  CLHEP::RandPoissonQ poissonDistribution_(rng->getEngine());
136  CLHEP::RandFlat flatDistribution_(rng->getEngine());
137 
138  gsl_sf_result result;
139  int status = gsl_sf_erf_Q_e(zsThreshold_, &result);
140  if (status != 0) std::cerr<<"ESFastTDigitizer::could not compute gaussian tail probability for the threshold chosen"<<std::endl;
141  double probabilityLeft = result.val;
142  double meanNumberOfNoisyChannels = probabilityLeft * numESdetId_;
143  int numberOfNoisyChannels = poissonDistribution_.fire(meanNumberOfNoisyChannels);
144  abThreshCh.reserve(numberOfNoisyChannels);
145  for (int i = 0; i < numberOfNoisyChannels; i++) {
146  std::vector<int>::iterator theChannel;
147  int theChannelNumber = 0;
148  do {
149  theChannelNumber = (int)flatDistribution_.fire(numESdetId_);
150  theChannel = find(abThreshCh.begin(), abThreshCh.end(), theChannelNumber);
151  }
152  while ( theChannel!=abThreshCh.end() );
153 
154  abThreshCh.push_back(theChannelNumber);
155  }
156  }
157 
158 
160  void setDetIds(const std::vector<DetId> & detIds) {theDetIds = &detIds;}
161 
164  }
165 
168 
169  assert( 0 != theDetIds &&
170  0 != theDetIds->size() );
171 
172  theHitResponse->run(input);
173 
175 
177 
178  // reserve space for how many digis we expect
179  int nDigisExpected = addNoise_ ? theDetIds->size() : theHitResponse->nSignals();
180  output.reserve(nDigisExpected);
181 
182  // random generation of channel above threshold
183  std::vector<int> abThreshCh;
184  if (addNoise_) createNoisyList(abThreshCh);
185 
186  // make a raw digi for evey cell where we have noise
187  int idxDetId=0;
188  for(std::vector<DetId>::const_iterator idItr = theDetIds->begin();
189  idItr != theDetIds->end(); ++idItr,++idxDetId) {
190 
191  bool needToDeleteSignal = false;
192  CaloSamples * analogSignal = theHitResponse->findSignal(*idItr);
193 
194  // signal or just noise?
195  bool wasEmpty = false;
196 
197  if (!analogSignal){ // no signal here
198  wasEmpty = true;
199  if (!addNoise_) continue;
200  else {
201  std::vector<int>::iterator thisChannel;
202  thisChannel = find( abThreshCh.begin(), abThreshCh.end(), idxDetId);
203  if( thisChannel != abThreshCh.end() ) {
204  analogSignal = new CaloSamples(theHitResponse->makeBlankSignal(*idItr));
205  needToDeleteSignal = true;
206  }
207  }
208  }
209 
210  if (analogSignal != 0){
211  // either we have a signal or we need to generate noise samples
212 
213  ESDataFrame digi(*idItr);
215  output.push_back(digi);
216  if (needToDeleteSignal) delete analogSignal;
217  }
218  }
219 
220  // free up some memory
222  }
223 
224 
225  void addNoiseHits() {
226  std::vector<PCaloHit> noiseHits;
228  for(std::vector<PCaloHit>::const_iterator hitItr = noiseHits.begin(),
229  hitEnd = noiseHits.end(); hitItr != hitEnd; ++hitItr) {
230  theHitResponse->add(*hitItr);
231  }
232  }
233 
234 
235  private:
236 
240  const std::vector<DetId>* theDetIds;
241  bool addNoise_;
244  int ESGain_;
245  double zsThreshold_;
246 
247  std::string refFile_;
248  ifstream *m_histofile;
249  double* refHistos_;
250  double histoBin_;
251  double histoInf_;
252  double histoSup_;
253 
254  CLHEP::RandGeneral *histoDistribution_;
255 };
256 
257 #endif
258 
int i
Definition: DBlmapReader.cc:9
CaloSamples makeBlankSignal(const DetId &detId) const
creates an empty signal for this DetId
ESFastTDigitizer(CaloHitResponse *hitResponse, ESElectronicsSimFast *electronicsSim, bool addNoise, int numESdetId)
void setNoiseHitGenerator(CaloVNoiseHitGenerator *generator)
void createNoisyList(std::vector< int > &abThreshCh)
preparing the list of channels where the noise has to be generated
void push_back(T const &t)
virtual void getNoiseHits(std::vector< PCaloHit > &noiseHits)=0
void run(MixCollection< PCaloHit > &input, ESDigiCollection &output)
turns hits into digis
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
return((rh^lh)&mask)
ESElectronicsSimFast * theElectronicsSim
Creates electronics signals from hits.
virtual void analogToDigital(const CaloSamples &cs, ESDataFrame &df, bool wasEmpty, CLHEP::RandGeneral *histoDistribution, double hInf, double hSup, double hBin) const
CaloVNoiseHitGenerator * theNoiseHitGenerator
tuple result
Definition: query.py:137
virtual void add(const PCaloHit &hit)
process a single SimHit
bool isAvailable() const
Definition: Service.h:47
ifstream * m_histofile
std::string refFile_
virtual CLHEP::HepRandomEngine & getEngine() const =0
Use this to get the random number engine, this is the only function most users should call...
tuple input
Definition: collect_tpl.py:10
const std::vector< DetId > * theDetIds
virtual void run(MixCollection< PCaloHit > &hits)
Complete cell digitization.
void setDetIds(const std::vector< DetId > &detIds)
tell the digitizer which cells exist
void setGain(const int gain)
set ES Gain
CaloHitResponse * theHitResponse
void readHistosFromFile()
taking reference histos
CaloSamples * findSignal(const DetId &detId)
users can look for the signal for a given cell
void clear()
frees up memory
CLHEP::RandGeneral * histoDistribution_
void reserve(size_type n)
void newEvent()
anything that needs to be done once per event
tuple status
Definition: ntuplemaker.py:245
int nSignals() const
number of signals in the current cache