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  LogDebug("CaloHitResponse") << signal;
138  if( keep ) add(signal);
139  }
140 }
141 
142 
143 void CaloHitResponse::add(const CaloSamples & signal)
144 {
145  DetId id(signal.id());
146  CaloSamples * oldSignal = findSignal(id);
147  if (oldSignal == 0) {
148  theAnalogSignalMap[id] = signal;
149  } else {
150  // need a "+=" to CaloSamples
151  int sampleSize = oldSignal->size();
152  assert(sampleSize == signal.size());
153  assert(signal.presamples() == oldSignal->presamples());
154 
155  for(int i = 0; i < sampleSize; ++i) {
156  (*oldSignal)[i] += signal[i];
157  }
158  }
159 }
160 
161 
163 
164  DetId detId(hit.id());
166 
167  double signal = analogSignalAmplitude(detId, hit.energy(), parameters);
168 
169  double time = hit.time();
170  if(theHitCorrection != 0) {
171  time += theHitCorrection->delay(hit);
172  }
173  double jitter = hit.time() - timeOfFlight(detId);
174 
175  const CaloVShape * shape = theShape;
176  if(!shape) {
177  shape = theShapes->shape(detId);
178  }
179  // assume bins count from zero, go for center of bin
180  const double tzero = ( shape->timeToRise()
181  + parameters.timePhase()
182  - jitter
183  - BUNCHSPACE*( parameters.binOfMaximum()
184  - thePhaseShift_ ) ) ;
185  double binTime = tzero;
186 
188 
189  for(int bin = 0; bin < result.size(); bin++) {
190  result[bin] += (*shape)(binTime)* signal;
191  binTime += BUNCHSPACE;
192  }
193  return result;
194 }
195 
196 
198 
199  if(!theRandPoisson)
200  {
202  if ( ! rng.isAvailable()) {
203  throw cms::Exception("Configuration")
204  << "CaloHitResponse requires the RandomNumberGeneratorService\n"
205  "which is not present in the configuration file. You must add the service\n"
206  "in the configuration file or remove the modules that require it.";
207  }
208  theRandPoisson = new CLHEP::RandPoissonQ(rng->getEngine());
209  }
210 
211  // OK, the "energy" in the hit could be a real energy, deposited energy,
212  // or pe count. This factor converts to photoelectrons
213  //GMA Smeared in photon production it self
214  double scl =1.0;
215 #ifdef ChangeHcalEnergyScale
216  if (changeScale) {
217  if (detId.det()==DetId::Hcal ) {
218  HcalDetId dId = HcalDetId(detId);
219  if (dId.subdet()==HcalBarrel || dId.subdet()==HcalEndcap) {
220  int ieta = dId.ieta()+50;
221  int iphi = dId.iphi()-1;
222  int idep = dId.depth()-1;
223  scl = hcal_en_scale[ieta][iphi][idep];
224  LogDebug("CaloHitResponse") << " ID " << dId << " Scale " << scl;
225  }
226  }
227  }
228 #endif
229  double npe = scl * energy * parameters.simHitToPhotoelectrons(detId);
230  // do we need to doPoisson statistics for the photoelectrons?
231  if(parameters.doPhotostatistics()) {
232  npe = theRandPoisson->fire(npe);
233  }
234  if(thePECorrection) npe = thePECorrection->correctPE(detId, npe);
235  return npe;
236 }
237 
238 
240  CaloSamples * result = 0;
241  AnalogSignalMap::iterator signalItr = theAnalogSignalMap.find(detId);
242  if(signalItr == theAnalogSignalMap.end()) {
243  result = 0;
244  } else {
245  result = &(signalItr->second);
246  }
247  return result;
248 }
249 
250 
253  CaloSamples result(detId, parameters.readoutFrameSize());
254  result.setPresamples(parameters.binOfMaximum()-1);
255  return result;
256 }
257 
258 
259 double CaloHitResponse::timeOfFlight(const DetId & detId) const {
260  // not going to assume there's one of these per subdetector.
261  // Take the whole CaloGeometry and find the right subdet
262  double result = 0.;
263  if(theGeometry == 0) {
264  edm::LogWarning("CaloHitResponse") << "No Calo Geometry set, so no time of flight correction";
265  }
266  else {
267  const CaloCellGeometry* cellGeometry = theGeometry->getSubdetectorGeometry(detId)->getGeometry(detId);
268  if(cellGeometry == 0) {
269  edm::LogWarning("CaloHitResponse") << "No Calo cell found for ID"
270  << detId.rawId() << " so no time-of-flight subtraction will be done";
271  }
272  else {
273  double distance = cellGeometry->getPosition().mag();
274  result = distance * cm / c_light; // Units of c_light: mm/ns
275  }
276  }
277  return result;
278 }
279 
280 
#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