CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CaloHitResponse.cc
Go to the documentation of this file.
15 #include "CLHEP/Random/RandPoissonQ.h"
16 #include "CLHEP/Random/RandFlat.h"
19 
20 #include "CLHEP/Units/GlobalPhysicalConstants.h"
21 #include "CLHEP/Units/GlobalSystemOfUnits.h"
22 
23 #include<iostream>
24 
26  const CaloVShape * shape)
27 : theAnalogSignalMap(),
28  theParameterMap(parametersMap),
29  theShapes(0),
30  theShape(shape),
31  theHitCorrection(0),
32  thePECorrection(0),
33  theHitFilter(0),
34  theGeometry(0),
35  theRandPoisson(0),
36  theMinBunch(-10),
37  theMaxBunch(10),
38  thePhaseShift_(1.),
39  changeScale(false) {}
40 
42  const CaloShapes * shapes)
43 : theAnalogSignalMap(),
44  theParameterMap(parametersMap),
45  theShapes(shapes),
46  theShape(0),
47  theHitCorrection(0),
48  thePECorrection(0),
49  theHitFilter(0),
50  theGeometry(0),
51  theRandPoisson(0),
52  theMinBunch(-10),
53  theMaxBunch(10),
54  thePhaseShift_(1.),
55  changeScale(false) {}
56 
58  delete theRandPoisson;
59 }
60 
62 #ifdef ChangeHcalEnergyScale
63  for (int ij=0; ij<100; ij++) {
64  for (int jk=0; jk<72; jk++) {
65  for (int kl=0; kl<4; kl++) {
66  hcal_en_scale[ij][jk][kl] = 1.0;
67  }
68  }
69  }
70 #endif
71 }
72 
74 
75  std::ifstream infile(fileIn.c_str());
76  LogDebug("CaloHitResponse") << "Reading from " << fileIn;
77 #ifdef ChangeHcalEnergyScale
78  if (!infile.is_open()) {
79  edm::LogError("CaloHitResponse") << "** ERROR: Can't open '" << fileIn << "' for the input file";
80  } else {
81  int eta, phi, depth;
82  double cFactor;
83  while(1) {
84  infile >> eta >> phi >> depth >> cFactor;
85  if (!infile.good()) break;
86  hcal_en_scale[eta][phi][depth] = cFactor;
87  // LogDebug("CaloHitResponse") << "hcal_en_scale[" << eta << "][" << phi << "][" << depth << "] = " << hcal_en_scale[eta][phi][depth];
88  }
89  infile.close();
90  }
91  changeScale = true;
92 #endif
93 }
94 
95 void CaloHitResponse::setBunchRange(int minBunch, int maxBunch) {
96  theMinBunch = minBunch;
97  theMaxBunch = maxBunch;
98 }
99 
100 
101 void CaloHitResponse::setRandomEngine(CLHEP::HepRandomEngine & engine) {
102  theRandPoisson = new CLHEP::RandPoissonQ(engine);
103 }
104 
105 
107 
108  for(MixCollection<PCaloHit>::MixItr hitItr = hits.begin();
109  hitItr != hits.end(); ++hitItr) {
110  if(withinBunchRange(hitItr.bunch())) {
111  add(*hitItr);
112  } // loop over hits
113  }
114 }
115 
117  // check the hit time makes sense
118  if ( edm::isNotFinite(hit.time()) ) { return; }
119 
120  // maybe it's not from this subdetector
121  if(theHitFilter == 0 || theHitFilter->accepts(hit)) {
122  LogDebug("CaloHitResponse") << hit;
123  CaloSamples signal( makeAnalogSignal( hit ) ) ;
124 
125  bool keep ( keepBlank() ) ; // here we check for blank signal if not keeping them
126  if( !keep )
127  {
128  const unsigned int size ( signal.size() ) ;
129  if( 0 != size )
130  {
131  for( unsigned int i ( 0 ) ; i != size ; ++i )
132  {
133  keep = keep || signal[i] > 1.e-7 ;
134  }
135  }
136  }
137 
138 
139  // std::cout << "CaloHitResponse " << signal << std::endl;
140  if( keep ) add(signal);
141  }
142 }
143 
144 
145 void CaloHitResponse::add(const CaloSamples & signal)
146 {
147  DetId id(signal.id());
148  CaloSamples * oldSignal = findSignal(id);
149  if (oldSignal == 0) {
150  theAnalogSignalMap[id] = signal;
151  //std::cout << "CaloHitResponseAdd " << signal << std::endl;
152 
153  } else {
154  // need a "+=" to CaloSamples
155  int sampleSize = oldSignal->size();
156  assert(sampleSize == signal.size());
157  assert(signal.presamples() == oldSignal->presamples());
158 
159  for(int i = 0; i < sampleSize; ++i) {
160  (*oldSignal)[i] += signal[i];
161  }
162  //std::cout << "CaloHitResponseAdd " << (*oldSignal) << std::endl;
163  }
164 }
165 
166 
168 
169  DetId detId(hit.id());
171 
172  double signal = analogSignalAmplitude(detId, hit.energy(), parameters);
173 
174  double time = hit.time();
175  if(theHitCorrection != 0) {
176  time += theHitCorrection->delay(hit);
177  }
178  double jitter = hit.time() - timeOfFlight(detId);
179 
180  const CaloVShape * shape = theShape;
181  if(!shape) {
182  shape = theShapes->shape(detId);
183  }
184  // assume bins count from zero, go for center of bin
185  const double tzero = ( shape->timeToRise()
186  + parameters.timePhase()
187  - jitter
188  - BUNCHSPACE*( parameters.binOfMaximum()
189  - thePhaseShift_ ) ) ;
190  double binTime = tzero;
191 
193 
194  for(int bin = 0; bin < result.size(); bin++) {
195  result[bin] += (*shape)(binTime)* signal;
196  binTime += BUNCHSPACE;
197  }
198  return result;
199 }
200 
201 
203 
204  if(!theRandPoisson)
205  {
207  if ( ! rng.isAvailable()) {
208  throw cms::Exception("Configuration")
209  << "CaloHitResponse requires the RandomNumberGeneratorService\n"
210  "which is not present in the configuration file. You must add the service\n"
211  "in the configuration file or remove the modules that require it.";
212  }
213  theRandPoisson = new CLHEP::RandPoissonQ(rng->getEngine());
214  }
215 
216  // OK, the "energy" in the hit could be a real energy, deposited energy,
217  // or pe count. This factor converts to photoelectrons
218  //GMA Smeared in photon production it self
219  double scl =1.0;
220 #ifdef ChangeHcalEnergyScale
221  if (changeScale) {
222  if (detId.det()==DetId::Hcal ) {
223  HcalDetId dId = HcalDetId(detId);
224  if (dId.subdet()==HcalBarrel || dId.subdet()==HcalEndcap) {
225  int ieta = dId.ieta()+50;
226  int iphi = dId.iphi()-1;
227  int idep = dId.depth()-1;
228  scl = hcal_en_scale[ieta][iphi][idep];
229  LogDebug("CaloHitResponse") << " ID " << dId << " Scale " << scl;
230  }
231  }
232  }
233 #endif
234  double npe = scl * energy * parameters.simHitToPhotoelectrons(detId);
235  // do we need to doPoisson statistics for the photoelectrons?
236  if(parameters.doPhotostatistics()) {
237  npe = theRandPoisson->fire(npe);
238  }
239  if(thePECorrection) npe = thePECorrection->correctPE(detId, npe);
240  return npe;
241 }
242 
243 
245  CaloSamples * result = 0;
246  AnalogSignalMap::iterator signalItr = theAnalogSignalMap.find(detId);
247  if(signalItr == theAnalogSignalMap.end()) {
248  result = 0;
249  } else {
250  result = &(signalItr->second);
251  }
252  return result;
253 }
254 
255 
258  CaloSamples result(detId, parameters.readoutFrameSize());
259  result.setPresamples(parameters.binOfMaximum()-1);
260  return result;
261 }
262 
263 
264 double CaloHitResponse::timeOfFlight(const DetId & detId) const {
265  // not going to assume there's one of these per subdetector.
266  // Take the whole CaloGeometry and find the right subdet
267  double result = 0.;
268  if(theGeometry == 0) {
269  edm::LogWarning("CaloHitResponse") << "No Calo Geometry set, so no time of flight correction";
270  }
271  else {
272  const CaloCellGeometry* cellGeometry = theGeometry->getSubdetectorGeometry(detId)->getGeometry(detId);
273  if(cellGeometry == 0) {
274  edm::LogWarning("CaloHitResponse") << "No Calo cell found for ID"
275  << detId.rawId() << " so no time-of-flight subtraction will be done";
276  }
277  else {
278  double distance = cellGeometry->getPosition().mag();
279  result = distance * cm / c_light; // Units of c_light: mm/ns
280  }
281  }
282  return result;
283 }
284 
285 
#define LogDebug(id)
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:43
float hcal_en_scale[100][72][4]
int i
Definition: DBlmapReader.cc:9
dictionary parameters
Definition: Parameters.py:2
CaloSamples makeBlankSignal(const DetId &detId) const
creates an empty signal for this DetId
double time() const
Definition: PCaloHit.h:36
HcalSubdetector subdet() const
get the subdetector
Definition: HcalDetId.h:30
virtual ~CaloHitResponse()
doesn&#39;t delete the pointers passed in
CLHEP::RandPoissonQ * theRandPoisson
bool withinBunchRange(int bunchCrossing) const
check if crossing is within bunch range:
double energy() const
Definition: PCaloHit.h:29
virtual CaloSamples makeAnalogSignal(const PCaloHit &inputHit) const
creates the signal corresponding to this hit
int presamples() const
access presample information
Definition: CaloSamples.h:36
bool doPhotostatistics() const
whether or not to apply Poisson statistics to photoelectrons
virtual bool keepBlank() const
Electronic response of the preamp.
Definition: CaloVShape.h:11
CaloHitResponse(const CaloVSimParameterMap *parameterMap, const CaloVShape *shape)
T eta() const
Main class for Parameters in different subdetectors.
const CaloGeometry * theGeometry
virtual double delay(const PCaloHit &hit) const =0
virtual const CaloCellGeometry * getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
uint32_t rawId() const
get the raw id
Definition: DetId.h:43
iterator end()
const CaloVPECorrection * thePECorrection
const int keep
int depth() const
get the tower depth
Definition: HcalDetId.h:40
T mag() const
Definition: PV3DBase.h:67
bool isNotFinite(T x)
Definition: isFinite.h:10
tuple result
Definition: query.py:137
virtual void add(const PCaloHit &hit)
process a single SimHit
int ieta() const
get the cell ieta
Definition: HcalDetId.h:36
bool isAvailable() const
Definition: Service.h:46
double simHitToPhotoelectrons() const
void setHBHEScale(std::string &)
virtual double timeToRise() const =0
virtual const CaloSimParameters & simParameters(const DetId &id) const =0
virtual bool accepts(const PCaloHit &hit) const =0
unsigned int id() const
Definition: PCaloHit.h:43
double timeOfFlight(const DetId &detId) const
virtual CLHEP::HepRandomEngine & getEngine() const =0
Use this to get the random number engine, this is the only function most users should call...
double analogSignalAmplitude(const DetId &id, float energy, const CaloSimParameters &parameters) const
int readoutFrameSize() const
for now, the LinearFrames and trhe digis will be one-to-one.
const CaloVHitCorrection * theHitCorrection
AnalogSignalMap theAnalogSignalMap
int iphi() const
get the cell iphi
Definition: HcalDetId.h:38
virtual void run(MixCollection< PCaloHit > &hits)
Complete cell digitization.
Definition: DetId.h:18
iterator begin()
const CaloShapes * theShapes
const CaloVSimParameterMap * theParameterMap
int size() const
get the size
Definition: CaloSamples.h:24
void setBunchRange(int minBunch, int maxBunch)
tells it which pileup bunches to do
CaloSamples * findSignal(const DetId &detId)
users can look for the signal for a given cell
list infile
Definition: EdgesToViz.py:90
static const double tzero[3]
const CaloVHitFilter * theHitFilter
virtual void setRandomEngine(CLHEP::HepRandomEngine &engine)
volatile std::atomic< bool > shutdown_flag false
const CaloVShape * theShape
DetId id() const
get the (generic) id
Definition: CaloSamples.h:21
virtual double correctPE(const DetId &detId, double npe) const =0
Detector det() const
get the detector field from this detid
Definition: DetId.h:35
const GlobalPoint & getPosition() const
Returns the position of reference for this cell.
int binOfMaximum() const
tuple size
Write out results.
virtual const CaloVShape * shape(const DetId &detId) const
Definition: CaloShapes.h:15
Definition: DDAxes.h:10