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.
14 
15 #include "CLHEP/Random/RandPoissonQ.h"
16 #include "CLHEP/Units/GlobalPhysicalConstants.h"
17 #include "CLHEP/Units/GlobalSystemOfUnits.h"
18 
19 #include<iostream>
20 
22  const CaloVShape * shape)
23 : theAnalogSignalMap(),
24  theParameterMap(parametersMap),
25  theShapes(0),
26  theShape(shape),
27  theHitCorrection(0),
28  thePECorrection(0),
29  theHitFilter(0),
30  theGeometry(0),
31  theMinBunch(-10),
32  theMaxBunch(10),
33  thePhaseShift_(1.),
34  changeScale(false) {}
35 
37  const CaloShapes * shapes)
38 : theAnalogSignalMap(),
39  theParameterMap(parametersMap),
40  theShapes(shapes),
41  theShape(0),
42  theHitCorrection(0),
43  thePECorrection(0),
44  theHitFilter(0),
45  theGeometry(0),
46  theMinBunch(-10),
47  theMaxBunch(10),
48  thePhaseShift_(1.),
49  changeScale(false) {}
50 
52 }
53 
55 #ifdef ChangeHcalEnergyScale
56  for (int ij=0; ij<100; ij++) {
57  for (int jk=0; jk<72; jk++) {
58  for (int kl=0; kl<4; kl++) {
59  hcal_en_scale[ij][jk][kl] = 1.0;
60  }
61  }
62  }
63 #endif
64 }
65 
67 
68  std::ifstream infile(fileIn.c_str());
69  LogDebug("CaloHitResponse") << "Reading from " << fileIn;
70 #ifdef ChangeHcalEnergyScale
71  if (!infile.is_open()) {
72  edm::LogError("CaloHitResponse") << "** ERROR: Can't open '" << fileIn << "' for the input file";
73  } else {
74  int eta, phi, depth;
75  double cFactor;
76  while(1) {
77  infile >> eta >> phi >> depth >> cFactor;
78  if (!infile.good()) break;
79  hcal_en_scale[eta][phi][depth] = cFactor;
80  // LogDebug("CaloHitResponse") << "hcal_en_scale[" << eta << "][" << phi << "][" << depth << "] = " << hcal_en_scale[eta][phi][depth];
81  }
82  infile.close();
83  }
84  changeScale = true;
85 #endif
86 }
87 
88 void CaloHitResponse::setBunchRange(int minBunch, int maxBunch) {
89  theMinBunch = minBunch;
90  theMaxBunch = maxBunch;
91 }
92 
93 void CaloHitResponse::run(MixCollection<PCaloHit> & hits, CLHEP::HepRandomEngine* engine) {
94 
95  for(MixCollection<PCaloHit>::MixItr hitItr = hits.begin();
96  hitItr != hits.end(); ++hitItr) {
97  if(withinBunchRange(hitItr.bunch())) {
98  add(*hitItr, engine);
99  } // loop over hits
100  }
101 }
102 
103 void CaloHitResponse::add( const PCaloHit& hit, CLHEP::HepRandomEngine* engine ) {
104  // check the hit time makes sense
105  if ( edm::isNotFinite(hit.time()) ) { return; }
106 
107  // maybe it's not from this subdetector
108  if(theHitFilter == 0 || theHitFilter->accepts(hit)) {
109  LogDebug("CaloHitResponse") << hit;
110  CaloSamples signal( makeAnalogSignal( hit, engine ) ) ;
111 
112  bool keep ( keepBlank() ) ; // here we check for blank signal if not keeping them
113  if( !keep )
114  {
115  const unsigned int size ( signal.size() ) ;
116  if( 0 != size )
117  {
118  for( unsigned int i ( 0 ) ; i != size ; ++i )
119  {
120  keep = keep || signal[i] > 1.e-7 ;
121  }
122  }
123  }
124 
125 
126  // std::cout << "CaloHitResponse " << signal << std::endl;
127  if( keep ) add(signal);
128  }
129 }
130 
131 
132 void CaloHitResponse::add(const CaloSamples & signal)
133 {
134  DetId id(signal.id());
135  CaloSamples * oldSignal = findSignal(id);
136  if (oldSignal == 0) {
137  theAnalogSignalMap[id] = signal;
138  //std::cout << "CaloHitResponseAdd " << signal << std::endl;
139 
140  } else {
141  // need a "+=" to CaloSamples
142  int sampleSize = oldSignal->size();
143  assert(sampleSize == signal.size());
144  assert(signal.presamples() == oldSignal->presamples());
145 
146  for(int i = 0; i < sampleSize; ++i) {
147  (*oldSignal)[i] += signal[i];
148  }
149  //std::cout << "CaloHitResponseAdd " << (*oldSignal) << std::endl;
150  }
151 }
152 
153 
154 CaloSamples CaloHitResponse::makeAnalogSignal(const PCaloHit & hit, CLHEP::HepRandomEngine* engine) const {
155 
156  DetId detId(hit.id());
158 
159  double signal = analogSignalAmplitude(detId, hit.energy(), parameters, engine);
160 
161  double time = hit.time();
162  if(theHitCorrection != 0) {
163  time += theHitCorrection->delay(hit, engine);
164  }
165  double jitter = hit.time() - timeOfFlight(detId);
166 
167  const CaloVShape * shape = theShape;
168  if(!shape) {
169  shape = theShapes->shape(detId);
170  }
171  // assume bins count from zero, go for center of bin
172  const double tzero = ( shape->timeToRise()
173  + parameters.timePhase()
174  - jitter
175  - BUNCHSPACE*( parameters.binOfMaximum()
176  - thePhaseShift_ ) ) ;
177  double binTime = tzero;
178 
180 
181  for(int bin = 0; bin < result.size(); bin++) {
182  result[bin] += (*shape)(binTime)* signal;
183  binTime += BUNCHSPACE;
184  }
185  return result;
186 }
187 
188 double CaloHitResponse::analogSignalAmplitude(const DetId & detId, float energy, const CaloSimParameters & parameters, CLHEP::HepRandomEngine* engine) const {
189 
190  // OK, the "energy" in the hit could be a real energy, deposited energy,
191  // or pe count. This factor converts to photoelectrons
192  //GMA Smeared in photon production it self
193  double scl =1.0;
194 #ifdef ChangeHcalEnergyScale
195  if (changeScale) {
196  if (detId.det()==DetId::Hcal ) {
197  HcalDetId dId = HcalDetId(detId);
198  if (dId.subdet()==HcalBarrel || dId.subdet()==HcalEndcap) {
199  int ieta = dId.ieta()+50;
200  int iphi = dId.iphi()-1;
201  int idep = dId.depth()-1;
202  scl = hcal_en_scale[ieta][iphi][idep];
203  LogDebug("CaloHitResponse") << " ID " << dId << " Scale " << scl;
204  }
205  }
206  }
207 #endif
208  double npe = scl * energy * parameters.simHitToPhotoelectrons(detId);
209  // do we need to doPoisson statistics for the photoelectrons?
210  if(parameters.doPhotostatistics()) {
211  CLHEP::RandPoissonQ randPoissonQ(*engine, npe);
212  npe = randPoissonQ.fire();
213  }
214  if(thePECorrection) npe = thePECorrection->correctPE(detId, npe, engine);
215  return npe;
216 }
217 
218 
220  CaloSamples * result = 0;
221  AnalogSignalMap::iterator signalItr = theAnalogSignalMap.find(detId);
222  if(signalItr == theAnalogSignalMap.end()) {
223  result = 0;
224  } else {
225  result = &(signalItr->second);
226  }
227  return result;
228 }
229 
230 
233  CaloSamples result(detId, parameters.readoutFrameSize());
234  result.setPresamples(parameters.binOfMaximum()-1);
235  return result;
236 }
237 
238 
239 double CaloHitResponse::timeOfFlight(const DetId & detId) const {
240  // not going to assume there's one of these per subdetector.
241  // Take the whole CaloGeometry and find the right subdet
242  double result = 0.;
243  if(theGeometry == 0) {
244  edm::LogWarning("CaloHitResponse") << "No Calo Geometry set, so no time of flight correction";
245  }
246  else {
247  const CaloCellGeometry* cellGeometry = theGeometry->getSubdetectorGeometry(detId)->getGeometry(detId);
248  if(cellGeometry == 0) {
249  edm::LogWarning("CaloHitResponse") << "No Calo cell found for ID"
250  << detId.rawId() << " so no time-of-flight subtraction will be done";
251  }
252  else {
253  double distance = cellGeometry->getPosition().mag();
254  result = distance * cm / c_light; // Units of c_light: mm/ns
255  }
256  }
257  return result;
258 }
259 
260 
#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
bool withinBunchRange(int bunchCrossing) const
check if crossing is within bunch range:
double energy() const
Definition: PCaloHit.h:29
virtual void run(MixCollection< PCaloHit > &hits, CLHEP::HepRandomEngine *)
Complete cell digitization.
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 correctPE(const DetId &detId, double npe, CLHEP::HepRandomEngine *) 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
virtual CaloSamples makeAnalogSignal(const PCaloHit &inputHit, CLHEP::HepRandomEngine *) const
creates the signal corresponding to this hit
tuple result
Definition: query.py:137
int ieta() const
get the cell ieta
Definition: HcalDetId.h:36
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
int readoutFrameSize() const
for now, the LinearFrames and trhe digis will be one-to-one.
const CaloVHitCorrection * theHitCorrection
virtual double delay(const PCaloHit &hit, CLHEP::HepRandomEngine *) const =0
AnalogSignalMap theAnalogSignalMap
int iphi() const
get the cell iphi
Definition: HcalDetId.h:38
Definition: DetId.h:18
double analogSignalAmplitude(const DetId &id, float energy, const CaloSimParameters &parameters, CLHEP::HepRandomEngine *) const
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
virtual void add(const PCaloHit &hit, CLHEP::HepRandomEngine *)
process a single SimHit
static const double tzero[3]
const CaloVHitFilter * theHitFilter
volatile std::atomic< bool > shutdown_flag false
const CaloVShape * theShape
DetId id() const
get the (generic) id
Definition: CaloSamples.h:21
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