CMS 3D CMS Logo

CaloHitResponse.cc
Go to the documentation of this file.
14 
15 #include <CLHEP/Random/RandPoissonQ.h>
16 #include <CLHEP/Units/GlobalPhysicalConstants.h>
17 #include <CLHEP/Units/SystemOfUnits.h>
18 
19 #include <iostream>
20 
22  const CaloVShape *shape,
23  bool PreMix1,
24  bool HighFidelity)
25  : theAnalogSignalMap(),
26  theParameterMap(parametersMap),
27  theShapes(nullptr),
28  theShape(shape),
29  theHitCorrection(nullptr),
30  thePECorrection(nullptr),
31  theHitFilter(nullptr),
32  theGeometry(nullptr),
33  theMinBunch(-10),
34  theMaxBunch(10),
35  thePhaseShift_(1.),
36  storePrecise(HighFidelity),
37  preMixDigis(PreMix1),
38  highFidelityPreMix(HighFidelity),
39  ignoreTime(false) {}
40 
42  const CaloShapes *shapes,
43  bool PreMix1,
44  bool HighFidelity)
45  : theAnalogSignalMap(),
46  theParameterMap(parametersMap),
47  theShapes(shapes),
48  theShape(nullptr),
49  theHitCorrection(nullptr),
50  thePECorrection(nullptr),
51  theHitFilter(nullptr),
52  theGeometry(nullptr),
53  theMinBunch(-10),
54  theMaxBunch(10),
55  thePhaseShift_(1.),
56  storePrecise(HighFidelity),
57  preMixDigis(PreMix1),
58  highFidelityPreMix(HighFidelity),
59  ignoreTime(false) {}
60 
62 
66 }
67 
68 void CaloHitResponse::finalizeHits(CLHEP::HepRandomEngine *) {
69  // Convert any remaining HighFidelityPreMix DIGIs
70  if (!(preMixDigis and highFidelityPreMix)) {
71  for (AnalogSignalMap::iterator itr = theAnalogSignalMap.begin(); itr != theAnalogSignalMap.end(); ++itr) {
72  CaloSamples result(makeBlankSignal(itr->first));
73  result += itr->second;
74  itr->second = result;
75  }
76  }
77 }
78 
79 void CaloHitResponse::run(const MixCollection<PCaloHit> &hits, CLHEP::HepRandomEngine *engine) {
80  for (MixCollection<PCaloHit>::MixItr hitItr = hits.begin(); hitItr != hits.end(); ++hitItr) {
81  if (withinBunchRange(hitItr.bunch())) {
82  add(*hitItr, engine);
83  } // loop over hits
84  }
85 }
86 
87 void CaloHitResponse::add(const PCaloHit &hit, CLHEP::HepRandomEngine *engine) {
88  // check the hit time makes sense
89  if (edm::isNotFinite(hit.time())) {
90  return;
91  }
92 
93  // maybe it's not from this subdetector
94  if (theHitFilter == nullptr || theHitFilter->accepts(hit)) {
95  LogDebug("CaloHitResponse") << hit;
96  CaloSamples signal(makeAnalogSignal(hit, engine));
97  bool keep(keepBlank()); // here we check for blank signal if not keeping them
98  if (!keep) {
99  const unsigned int size(signal.size());
100  if (0 != size) {
101  for (unsigned int i(0); i != size; ++i) {
102  keep = keep || signal[i] > 1.e-7;
103  }
104  }
105  }
106 
107  if (keep)
108  add(signal);
109  }
110 }
111 
112 void CaloHitResponse::add(const CaloSamples &signal) {
113  DetId id(signal.id());
114  CaloSamples *oldSignal = findSignal(id);
115  if (oldSignal == nullptr) {
116  theAnalogSignalMap[id] = signal;
117 
118  } else {
119  (*oldSignal) += signal;
120  }
121 }
122 
123 CaloSamples CaloHitResponse::makeAnalogSignal(const PCaloHit &hit, CLHEP::HepRandomEngine *engine) const {
124  DetId detId(hit.id());
126  double signal = analogSignalAmplitude(detId, hit.energy(), parameters, engine);
127 
128  double time = hit.time();
129  double tof = timeOfFlight(detId);
130  if (ignoreTime)
131  time = tof;
132  if (theHitCorrection != nullptr) {
133  time += theHitCorrection->delay(hit, engine);
134  }
135  double jitter = time - tof;
136 
137  const CaloVShape *shape = theShape;
138  if (!shape) {
140  }
141  // assume bins count from zero, go for center of bin
142  const double tzero = (shape->timeToRise() + parameters.timePhase() - jitter -
143  BUNCHSPACE * (parameters.binOfMaximum() - thePhaseShift_));
144  double binTime = tzero;
145 
147 
148  if (storePrecise) {
149  result.resetPrecise();
150  int sampleBin(0);
151  // use 0.5ns binning for precise sample
152  for (int bin = 0; bin < result.preciseSize(); bin++) {
153  sampleBin = (preMixDigis and highFidelityPreMix) ? bin : bin / (BUNCHSPACE * invdt);
154  double pulseBit = (*shape)(binTime)*signal * dt;
155  result[sampleBin] += pulseBit;
156  result.preciseAtMod(bin) += pulseBit;
157  binTime += dt;
158  }
159  } else {
160  for (int bin = 0; bin < result.size(); bin++) {
161  result[bin] += (*shape)(binTime)*signal;
162  binTime += BUNCHSPACE;
163  }
164  }
165  return result;
166 }
167 
169  float energy,
171  CLHEP::HepRandomEngine *engine) const {
172  // OK, the "energy" in the hit could be a real energy, deposited energy,
173  // or pe count. This factor converts to photoelectrons
174  // GMA Smeared in photon production it self
175  double npe = energy * parameters.simHitToPhotoelectrons(detId);
176  // do we need to doPoisson statistics for the photoelectrons?
177  if (parameters.doPhotostatistics()) {
178  npe = CLHEP::RandPoissonQ::shoot(engine, npe);
179  }
180  if (thePECorrection)
181  npe = thePECorrection->correctPE(detId, npe, engine);
182  return npe;
183 }
184 
186  CaloSamples *result = nullptr;
187  AnalogSignalMap::iterator signalItr = theAnalogSignalMap.find(detId);
188  if (signalItr == theAnalogSignalMap.end()) {
189  result = nullptr;
190  } else {
191  result = &(signalItr->second);
192  }
193  return result;
194 }
195 
198  int readoutFrameSize = parameters.readoutFrameSize();
200  //preserve fidelity of time info
202  }
203  return readoutFrameSize;
204 }
205 
209  int preciseSize(storePrecise ? parameters.readoutFrameSize() * BUNCHSPACE * invdt : 0);
210  CaloSamples result(detId, readoutFrameSize, preciseSize);
211  result.setPresamples(parameters.binOfMaximum() - 1);
212  if (storePrecise) {
213  result.setPreciseSize(preciseSize);
214  result.setPrecise(result.presamples() * BUNCHSPACE * invdt, dt);
215  }
216  return result;
217 }
218 
220  // not going to assume there's one of these per subdetector.
221  // Take the whole CaloGeometry and find the right subdet
222  double result = 0.;
223  if (theGeometry == nullptr) {
224  edm::LogWarning("CaloHitResponse") << "No Calo Geometry set, so no time of flight correction";
225  } else {
226  auto cellGeometry = theGeometry->getSubdetectorGeometry(detId)->getGeometry(detId);
227  if (cellGeometry == nullptr) {
228  edm::LogWarning("CaloHitResponse") << "No Calo cell found for ID" << detId.rawId()
229  << " so no time-of-flight subtraction will be done";
230  } else {
231  double distance = cellGeometry->getPosition().mag();
232  result = distance * CLHEP::cm / c_light; // Units of c_light: mm/ns
233  }
234  }
235  return result;
236 }
size
Write out results.
virtual CellMayOwnPtr getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
CaloHitResponse(const CaloVSimParameterMap *parameterMap, const CaloVShape *shape, bool PreMix1=false, bool HighFidelity=false)
int size() const
get the size
Definition: CaloSamples.h:24
virtual ~CaloHitResponse()
doesn&#39;t delete the pointers passed in
constexpr bool isNotFinite(T x)
Definition: isFinite.h:9
Electronic response of the preamp.
Definition: CaloVShape.h:11
static constexpr int invdt
virtual void run(const MixCollection< PCaloHit > &hits, CLHEP::HepRandomEngine *)
Complete cell digitization.
Main class for Parameters in different subdetectors.
const CaloGeometry * theGeometry
virtual double correctPE(const DetId &detId, double npe, CLHEP::HepRandomEngine *) const =0
double analogSignalAmplitude(const DetId &id, float energy, const CaloSimParameters &parameters, CLHEP::HepRandomEngine *) const
const CaloVPECorrection * thePECorrection
DetId id() const
get the (generic) id
Definition: CaloSamples.h:21
virtual const CaloVShape * shape(const DetId &detId, bool precise=false) const
Definition: CaloShapes.h:14
int getReadoutFrameSize(const DetId &id) const
virtual bool keepBlank() const
virtual const CaloSimParameters & simParameters(const DetId &id) const =0
virtual bool accepts(const PCaloHit &hit) const =0
const CaloVHitCorrection * theHitCorrection
bool withinBunchRange(int bunchCrossing) const
check if crossing is within bunch range:
virtual double delay(const PCaloHit &hit, CLHEP::HepRandomEngine *) const =0
unsigned int id
AnalogSignalMap theAnalogSignalMap
Definition: DetId.h:17
const CaloShapes * theShapes
const CaloVSimParameterMap * theParameterMap
virtual CaloSamples makeAnalogSignal(const PCaloHit &inputHit, CLHEP::HepRandomEngine *) const
creates the signal corresponding to this hit
void setBunchRange(int minBunch, int maxBunch)
tells it which pileup bunches to do
double timeOfFlight(const DetId &detId) const
CaloSamples * findSignal(const DetId &detId)
users can look for the signal for a given cell
virtual void finalizeHits(CLHEP::HepRandomEngine *)
Finalize hits.
virtual void add(const PCaloHit &hit, CLHEP::HepRandomEngine *)
process a single SimHit
static constexpr double dt
static const double tzero[3]
const CaloVHitFilter * theHitFilter
const CaloVShape * theShape
Log< level::Warning, false > LogWarning
CaloSamples makeBlankSignal(const DetId &detId) const
creates an empty signal for this DetId
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:34
#define LogDebug(id)
static constexpr int BUNCHSPACE