CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
EcalSeverityLevelAlgo.cc
Go to the documentation of this file.
2 
4 
6  const EcalRecHitCollection & recHits,
7  const EcalChannelStatus & chStatus,
8  float recHitEtThreshold,
9  SpikeId spId,
10  float spIdThreshold,
11  float recHitEnergyThresholdForTiming,
12  float recHitEnergyThresholdForEE,
13  float spIdThresholdIEta85
14  )
15 {
16 
17  // get DB flag
18  uint16_t dbStatus = retrieveDBStatus( id, chStatus );
19  // get recHit flags
20  EcalRecHitCollection::const_iterator it = recHits.find( id );
21  if ( it == recHits.end() ) {
22  // the channel is not in the recHit collection:
23  // dead or zero-suppressed?
24  if ( dbStatus >= 10 ) { // originally dead
25  return kBad;
26  } else if ( dbStatus > 0 && dbStatus < 10 ) {
27  // zero-suppressed and originally problematic
28  return kProblematic;
29  } else if ( dbStatus == 0 ) {
30  // zero-suppressed and originally good
31  return kGood;
32  }
33  } else {
34  // the channel is in the recHit collection
35  // .. is it a spike?
36  // check the topology
37  if ( id.subdetId() == EcalBarrel ) {
38  if ( abs(((EBDetId)id).ieta()) == 85 && spId == kSwissCrossBordersIncluded && spikeFromNeighbours(id, recHits, recHitEtThreshold, spId) > spIdThresholdIEta85 ) return kWeird;
39  if ( spikeFromNeighbours(id, recHits, recHitEtThreshold, spId) > spIdThreshold ) return kWeird;
40  }
41  // check the timing (currently only a trivial check)
42  if ( id.subdetId() == EcalBarrel && spikeFromTiming(*it, recHitEnergyThresholdForTiming) ) return kTime;
43  // filtering on VPT discharges in the endcap
44  // introduced >= kSwisscross to take borders too, SA 20100913
45  float re = 0; // protect the log function: make the computation possible only for re > 0
46  if ( id.subdetId() == EcalEndcap && spId >= kSwissCross && (re = recHitE(id, recHits)) > 0 && ( 1-swissCross(id, recHits, recHitEnergyThresholdForEE, spId) < 0.02*log(re/4.) ) ) return kWeird;
47 
48  // .. not a spike, return the normal severity level
49  return severityLevel( *it, chStatus );
50  }
51  return kGood;
52 }
53 
55  const EcalChannelStatus &chStatus )
56 {
57  // the channel is there, check its flags
58  // and combine with DB (not needed at the moment)
59  uint32_t rhFlag = recHit.recoFlag();
60  uint16_t dbStatus = retrieveDBStatus( recHit.id(), chStatus );
61  return severityLevel( rhFlag, dbStatus );
62 }
63 
64 int EcalSeverityLevelAlgo::severityLevel( uint32_t rhFlag, uint16_t chStatus )
65 {
66  // DB info currently not used at this level
67  if ( rhFlag == EcalRecHit::kPoorReco
68  || rhFlag == EcalRecHit::kOutOfTime
69  || rhFlag == EcalRecHit::kNoisy
70  || rhFlag == EcalRecHit::kPoorCalib
71  || rhFlag == EcalRecHit::kFaultyHardware
72  ) {
73  // problematic
74  return kProblematic;
75  } else if ( rhFlag == EcalRecHit::kLeadingEdgeRecovered
77  || rhFlag == EcalRecHit::kTowerRecovered
78  ) {
79  // recovered
80  return kRecovered;
81  } else if ( rhFlag == EcalRecHit::kDead
82  || rhFlag == EcalRecHit::kSaturated
83  //|| rhFlag == EcalRecHit::kFake // will be uncommented when validated
84  || rhFlag == EcalRecHit::kFakeNeighbours
85  || rhFlag == EcalRecHit::kKilled ) {
86  // recovery failed (or not tried) or signal is fake or channel
87  // is dead
88  return kBad;
89  }
90  // good
91  return kGood;
92 }
93 
95 {
96  EcalChannelStatus::const_iterator chIt = chStatus.find( id );
97  uint16_t dbStatus = 0;
98  if ( chIt != chStatus.end() ) {
99  dbStatus = chIt->getStatusCode();
100  } else {
101  edm::LogError("EcalSeverityLevelError") << "No channel status found for xtal "
102  << id.rawId()
103  << "! something wrong with EcalChannelStatus in your DB? ";
104  }
105  return dbStatus;
106 }
107 
109  const EcalRecHitCollection & recHits,
110  float recHitThreshold,
111  SpikeId spId
112  )
113 {
114  switch( spId ) {
115  case kE1OverE9:
116  return E1OverE9( id, recHits, recHitThreshold );
117  break;
118  case kSwissCross:
119  return swissCross( id, recHits, recHitThreshold , true);
120  break;
122  return swissCross( id, recHits, recHitThreshold , false);
123  break;
124  default:
125  edm::LogInfo("EcalSeverityLevelAlgo") << "Algorithm number " << spId
126  << " not known. Please check the enum in EcalSeverityLevelAlgo.h";
127  break;
128 
129  }
130  return 0;
131 }
132 
133 float EcalSeverityLevelAlgo::E1OverE9( const DetId id, const EcalRecHitCollection & recHits, float recHitEtThreshold )
134 {
135  // compute E1 over E9
136  if ( id.subdetId() == EcalBarrel ) {
137  // select recHits with Et above recHitEtThreshold
138  if ( recHitApproxEt( id, recHits ) < recHitEtThreshold ) return 0;
139  EBDetId ebId( id );
140  float s9 = 0;
141  for ( int deta = -1; deta <= +1; ++deta ) {
142  for ( int dphi = -1; dphi <= +1; ++dphi ) {
143  s9 += recHitE( id, recHits, deta, dphi );
144  }
145  }
146  return recHitE(id, recHits) / s9;
147  } else if( id.subdetId() == EcalEndcap ) {
148  // select recHits with Et above recHitEtThreshold
149  if ( recHitApproxEt( id, recHits ) < recHitEtThreshold ) return 0;
150  EEDetId eeId( id );
151  float s9 = 0;
152  for ( int dx = -1; dx <= +1; ++dx ) {
153  for ( int dy = -1; dy <= +1; ++dy ) {
154  s9 += recHitE( id, recHits, dx, dy );
155  }
156  }
157  return recHitE(id, recHits) / s9;
158 
159  }
160  return 0;
161 }
162 
163 float EcalSeverityLevelAlgo::swissCross( const DetId id, const EcalRecHitCollection & recHits, float recHitThreshold , bool avoidIeta85)
164 {
165  // compute swissCross
166  if ( id.subdetId() == EcalBarrel ) {
167  EBDetId ebId( id );
168  // avoid recHits at |eta|=85 where one side of the neighbours is missing
169  // (may improve considering also eta module borders, but no
170  // evidence for the time being that there the performance is
171  // different)
172  if ( abs(ebId.ieta())==85 && avoidIeta85) return 0;
173  // select recHits with Et above recHitThreshold
174  if ( recHitApproxEt( id, recHits ) < recHitThreshold ) return 0;
175  float s4 = 0;
176  float e1 = recHitE( id, recHits );
177  // protect against nan (if 0 threshold is given above)
178  if ( e1 == 0 ) return 0;
179  s4 += recHitE( id, recHits, 1, 0 );
180  s4 += recHitE( id, recHits, -1, 0 );
181  s4 += recHitE( id, recHits, 0, 1 );
182  s4 += recHitE( id, recHits, 0, -1 );
183  return 1 - s4 / e1;
184  } else if ( id.subdetId() == EcalEndcap ) {
185  EEDetId eeId( id );
186  // select recHits with E above recHitThreshold
187  float e1 = recHitE( id, recHits );
188  if ( e1 < recHitThreshold ) return 0;
189  float s4 = 0;
190  // protect against nan (if 0 threshold is given above)
191  if ( e1 == 0 ) return 0;
192  s4 += recHitE( id, recHits, 1, 0 );
193  s4 += recHitE( id, recHits, -1, 0 );
194  s4 += recHitE( id, recHits, 0, 1 );
195  s4 += recHitE( id, recHits, 0, -1 );
196  return 1 - s4 / e1;
197  }
198  return 0;
199 }
200 
202  int di, int dj )
203 {
204  // in the barrel: di = dEta dj = dPhi
205  // in the endcap: di = dX dj = dY
206 
207  DetId nid;
208  if( id.subdetId() == EcalBarrel) nid = EBDetId::offsetBy( id, di, dj );
209  else if( id.subdetId() == EcalEndcap) nid = EEDetId::offsetBy( id, di, dj );
210 
211  return ( nid == DetId(0) ? 0 : recHitE( nid, recHits ) );
212 }
213 
215 {
216  if ( id == DetId(0) ) {
217  return 0;
218  } else {
219  EcalRecHitCollection::const_iterator it = recHits.find( id );
220  if ( it != recHits.end() ) return (*it).energy();
221  }
222  return 0;
223 }
224 
225 
227 {
228  // for the time being works only for the barrel
229  if ( id.subdetId() == EcalBarrel ) {
230  return recHitE( id, recHits ) / cosh( EBDetId::approxEta( id ) );
231  }
232  return 0;
233 }
234 
235 
236 bool EcalSeverityLevelAlgo::spikeFromTiming( const EcalRecHit &recHit, float recHitEnergyThreshold)
237 {
238  if ( recHit.energy() < recHitEnergyThreshold ) return false;
239  if ( recHit.recoFlag() == EcalRecHit::kOutOfTime ) return true;
240  return false;
241 }
242 
243 
244 
246  float recHitEtThreshold, float recHitEtThreshold2 ,
247  bool avoidIeta85, bool KillSecondHit)
248 {
249 
250  // compute e2overe9
251  //
252  // | | | |
253  // +-+-+-+
254  // | |1|2|
255  // +-+-+-+
256  // | | | |
257  //
258  // 1 - input hit, 2 - highest energy hit in a 3x3 around 1
259  //
260  // rechit 1 must have E_t > recHitEtThreshold
261  // rechit 2 must have E_t > recHitEtThreshold2
262  //
263  // function returns value of E2/E9 centered around 1 (E2=energy of hits 1+2) if energy of 1>2
264  //
265  // if energy of 2>1 and KillSecondHit is set to true, function returns value of E2/E9 centered around 2
266  // *provided* that 1 is the highest energy hit in a 3x3 centered around 2, otherwise, function returns 0
267 
268 
269  if ( id.subdetId() == EcalBarrel ) {
270 
271  EBDetId ebId( id );
272 
273  // avoid recHits at |eta|=85 where one side of the neighbours is missing
274  if ( abs(ebId.ieta())==85 && avoidIeta85) return 0;
275 
276  // select recHits with Et above recHitEtThreshold
277 
278 
279  float e1 = recHitE( id, recHits );
280  float ete1=recHitApproxEt( id, recHits );
281 
282 
283  // check that rechit E_t is above threshold
284 
285  if (ete1 < std::min(recHitEtThreshold,recHitEtThreshold2) ) return 0;
286 
287  if (ete1 < recHitEtThreshold && !KillSecondHit ) return 0;
288 
289 
290  float e2=-1;
291  float ete2=0;
292  float s9 = 0;
293 
294  // coordinates of 2nd hit relative to central hit
295  int e2eta=0;
296  int e2phi=0;
297 
298  // LOOP OVER 3x3 ARRAY CENTERED AROUND HIT 1
299 
300  for ( int deta = -1; deta <= +1; ++deta ) {
301  for ( int dphi = -1; dphi <= +1; ++dphi ) {
302 
303  // compute 3x3 energy
304 
305  float etmp=recHitE( id, recHits, deta, dphi );
306  s9 += etmp;
307 
308  EBDetId idtmp=EBDetId::offsetBy(id,deta,dphi);
309  float eapproxet=recHitApproxEt( idtmp, recHits );
310 
311  // remember 2nd highest energy deposit (above threshold) in 3x3 array
312  if (etmp>e2 && eapproxet>recHitEtThreshold2 && !(deta==0 && dphi==0)) {
313 
314  e2=etmp;
315  ete2=eapproxet;
316  e2eta=deta;
317  e2phi=dphi;
318 
319  }
320 
321  }
322  }
323 
324  if ( e1 == 0 ) return 0;
325 
326  // return 0 if 2nd hit is below threshold
327  if ( e2 == -1 ) return 0;
328 
329  // compute e2/e9 centered around 1st hit
330 
331  float e2nd=e1+e2;
332  float e2e9=0;
333 
334  if (s9!=0) e2e9=e2nd/s9;
335 
336  // if central hit has higher energy than 2nd hit
337  // return e2/e9 if 1st hit is above E_t threshold
338 
339  if (e1 > e2 && ete1>recHitEtThreshold) return e2e9;
340 
341  // if second hit has higher energy than 1st hit
342 
343  if ( e2 > e1 ) {
344 
345 
346  // return 0 if user does not want to flag 2nd hit, or
347  // hits are below E_t thresholds - note here we
348  // now assume the 2nd hit to be the leading hit.
349 
350  if (!KillSecondHit || ete2<recHitEtThreshold || ete1<recHitEtThreshold2) {
351 
352  return 0;
353 
354  }
355 
356 
357  else {
358 
359  // LOOP OVER 3x3 ARRAY CENTERED AROUND HIT 2
360 
361  float s92nd=0;
362 
363  float e2nd_prime=0;
364  int e2prime_eta=0;
365  int e2prime_phi=0;
366 
367  EBDetId secondid=EBDetId::offsetBy(id,e2eta,e2phi);
368 
369 
370  for ( int deta = -1; deta <= +1; ++deta ) {
371  for ( int dphi = -1; dphi <= +1; ++dphi ) {
372 
373  // compute 3x3 energy
374 
375  float etmp=recHitE( secondid, recHits, deta, dphi );
376  s92nd += etmp;
377 
378  if (etmp>e2nd_prime && !(deta==0 && dphi==0)) {
379  e2nd_prime=etmp;
380  e2prime_eta=deta;
381  e2prime_phi=dphi;
382  }
383 
384  }
385  }
386 
387  // if highest energy hit around E2 is not the same as the input hit, return 0;
388 
389  if (!(e2prime_eta==-e2eta && e2prime_phi==-e2phi))
390  {
391  return 0;
392  }
393 
394 
395  // compute E2/E9 around second hit
396  float e2e9_2=0;
397  if (s92nd!=0) e2e9_2=e2nd/s92nd;
398 
399  // return the value of E2/E9 calculated around 2nd hit
400 
401  return e2e9_2;
402 
403 
404  }
405 
406  }
407 
408 
409  } else if ( id.subdetId() == EcalEndcap ) {
410  // only used for EB at the moment
411  return 0;
412  }
413  return 0;
414 }
415 
float approxEta() const
Definition: EBDetId.h:93
static float E2overE9(const DetId id, const EcalRecHitCollection &, float recHitEtThreshold=10.0, float recHitEtThreshold2=1.0, bool avoidIeta85=false, bool KillSecondHit=true)
std::vector< T >::const_iterator const_iterator
#define abs(x)
Definition: mlp_lapack.h:159
#define min(a, b)
Definition: mlp_lapack.h:161
EEDetId offsetBy(int nrStepsX, int nrStepsY) const
Definition: EEDetId.cc:490
uint32_t recoFlag() const
Definition: EcalRecHit.h:78
static bool spikeFromTiming(const EcalRecHit &, float recHitEnergyThreshold)
float energy() const
Definition: CaloRecHit.h:19
EBDetId offsetBy(int nrStepsEta, int nrStepsPhi) const
Definition: EBDetId.cc:111
int ieta() const
get the crystal ieta
Definition: EBDetId.h:44
const_iterator end() const
Definition: DetId.h:20
static float recHitApproxEt(const DetId id, const EcalRecHitCollection &recHits)
static uint16_t retrieveDBStatus(const DetId, const EcalChannelStatus &chStatus)
Log< T >::type log(const T &t)
Definition: Log.h:22
DetId id() const
get the id
Definition: EcalRecHit.h:74
std::vector< Item >::const_iterator const_iterator
static float recHitE(const DetId id, const EcalRecHitCollection &recHits)
iterator find(key_type k)
static float spikeFromNeighbours(const DetId id, const EcalRecHitCollection &, float recHitEtThreshold, SpikeId spId)
static float swissCross(const DetId id, const EcalRecHitCollection &, float recHitEtThreshold=0., bool avoidIeta85=true)
const_iterator find(uint32_t rawId) const
static int severityLevel(const DetId, const EcalRecHitCollection &, const EcalChannelStatus &, float recHitEtThreshold=5., SpikeId spId=kSwissCross, float spIdThreshold=0.95, float recHitEnergyThresholdForTiming=2., float recHitEnergyThresholdForEE=15, float spIdThresholdIEta85=0.999)
const_iterator end() const
static float E1OverE9(const DetId id, const EcalRecHitCollection &, float recHitEtThreshold=0.)