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