CMS 3D CMS Logo

CaloTowersCreationAlgo.cc
Go to the documentation of this file.
2 
10 #include "Math/Interpolator.h"
11 
12 #include <cmath>
13 
14 //#define EDM_ML_DEBUG
15 
17  : theEBthreshold(-1000.),
18  theEEthreshold(-1000.),
19 
20  theUseEtEBTresholdFlag(false),
21  theUseEtEETresholdFlag(false),
22  theUseSymEBTresholdFlag(false),
23  theUseSymEETresholdFlag(false),
24 
25  theHcalThreshold(-1000.),
26  theHBthreshold(-1000.),
27  theHBthreshold1(-1000.),
28  theHBthreshold2(-1000.),
29  theHESthreshold(-1000.),
30  theHESthreshold1(-1000.),
31  theHEDthreshold(-1000.),
32  theHEDthreshold1(-1000.),
33  theHOthreshold0(-1000.),
34  theHOthresholdPlus1(-1000.),
35  theHOthresholdMinus1(-1000.),
36  theHOthresholdPlus2(-1000.),
37  theHOthresholdMinus2(-1000.),
38  theHF1threshold(-1000.),
39  theHF2threshold(-1000.),
40  theEBGrid(std::vector<double>(5, 10.)),
41  theEBWeights(std::vector<double>(5, 1.)),
42  theEEGrid(std::vector<double>(5, 10.)),
43  theEEWeights(std::vector<double>(5, 1.)),
44  theHBGrid(std::vector<double>(5, 10.)),
45  theHBWeights(std::vector<double>(5, 1.)),
46  theHESGrid(std::vector<double>(5, 10.)),
47  theHESWeights(std::vector<double>(5, 1.)),
48  theHEDGrid(std::vector<double>(5, 10.)),
49  theHEDWeights(std::vector<double>(5, 1.)),
50  theHOGrid(std::vector<double>(5, 10.)),
51  theHOWeights(std::vector<double>(5, 1.)),
52  theHF1Grid(std::vector<double>(5, 10.)),
53  theHF1Weights(std::vector<double>(5, 1.)),
54  theHF2Grid(std::vector<double>(5, 10.)),
55  theHF2Weights(std::vector<double>(5, 1.)),
56  theEBweight(1.),
57  theEEweight(1.),
58  theHBweight(1.),
59  theHESweight(1.),
60  theHEDweight(1.),
61  theHOweight(1.),
62  theHF1weight(1.),
63  theHF2weight(1.),
64  theEcutTower(-1000.),
65  theEBSumThreshold(-1000.),
66  theEESumThreshold(-1000.),
67  theEBEScale(50.),
68  theEEEScale(50.),
69  theHBEScale(50.),
70  theHESEScale(50.),
71  theHEDEScale(50.),
72  theHOEScale(50.),
73  theHF1EScale(50.),
74  theHF2EScale(50.),
75  theHcalTopology(nullptr),
76  theGeometry(nullptr),
77  theTowerConstituentsMap(nullptr),
78  theHcalAcceptSeverityLevel(0),
79  theRecoveredHcalHitsAreUsed(false),
80  theRecoveredEcalHitsAreUsed(false),
81  useRejectedHitsOnly(false),
82  theHcalAcceptSeverityLevelForRejectedHit(0),
83  useRejectedRecoveredHcalHits(0),
84  useRejectedRecoveredEcalHits(0),
86  theHOIsUsed(true),
87  // (for momentum reconstruction algorithm)
88  theMomConstrMethod(0),
89  theMomHBDepth(0.),
90  theMomHEDepth(0.),
91  theMomEBDepth(0.),
92  theMomEEDepth(0.),
93  theHcalPhase(0) {}
94 
96  double EEthreshold,
97 
98  bool useEtEBTreshold,
99  bool useEtEETreshold,
100  bool useSymEBTreshold,
101  bool useSymEETreshold,
102 
103  double HcalThreshold,
104  double HBthreshold,
105  double HBthreshold1,
106  double HBthreshold2,
107  double HESthreshold,
108  double HESthreshold1,
109  double HEDthreshold,
110  double HEDthreshold1,
111  double HOthreshold0,
112  double HOthresholdPlus1,
113  double HOthresholdMinus1,
114  double HOthresholdPlus2,
115  double HOthresholdMinus2,
116  double HF1threshold,
117  double HF2threshold,
118  double EBweight,
119  double EEweight,
120  double HBweight,
121  double HESweight,
122  double HEDweight,
123  double HOweight,
124  double HF1weight,
125  double HF2weight,
126  double EcutTower,
127  double EBSumThreshold,
128  double EESumThreshold,
129  bool useHO,
130  // (momentum reconstruction algorithm)
131  int momConstrMethod,
132  double momHBDepth,
133  double momHEDepth,
134  double momEBDepth,
135  double momEEDepth,
136  int hcalPhase)
137 
138  : theEBthreshold(EBthreshold),
139  theEEthreshold(EEthreshold),
140 
141  theUseEtEBTresholdFlag(useEtEBTreshold),
142  theUseEtEETresholdFlag(useEtEETreshold),
143  theUseSymEBTresholdFlag(useSymEBTreshold),
144  theUseSymEETresholdFlag(useSymEETreshold),
145 
146  theHcalThreshold(HcalThreshold),
147  theHBthreshold(HBthreshold),
148  theHBthreshold1(HBthreshold1),
149  theHBthreshold2(HBthreshold2),
150  theHESthreshold(HESthreshold),
151  theHESthreshold1(HESthreshold1),
152  theHEDthreshold(HEDthreshold),
153  theHEDthreshold1(HEDthreshold1),
154  theHOthreshold0(HOthreshold0),
155  theHOthresholdPlus1(HOthresholdPlus1),
156  theHOthresholdMinus1(HOthresholdMinus1),
157  theHOthresholdPlus2(HOthresholdPlus2),
158  theHOthresholdMinus2(HOthresholdMinus2),
159  theHF1threshold(HF1threshold),
160  theHF2threshold(HF2threshold),
161  theEBGrid(std::vector<double>(5, 10.)),
162  theEBWeights(std::vector<double>(5, 1.)),
163  theEEGrid(std::vector<double>(5, 10.)),
164  theEEWeights(std::vector<double>(5, 1.)),
165  theHBGrid(std::vector<double>(5, 10.)),
166  theHBWeights(std::vector<double>(5, 1.)),
167  theHESGrid(std::vector<double>(5, 10.)),
168  theHESWeights(std::vector<double>(5, 1.)),
169  theHEDGrid(std::vector<double>(5, 10.)),
170  theHEDWeights(std::vector<double>(5, 1.)),
171  theHOGrid(std::vector<double>(5, 10.)),
172  theHOWeights(std::vector<double>(5, 1.)),
173  theHF1Grid(std::vector<double>(5, 10.)),
174  theHF1Weights(std::vector<double>(5, 1.)),
175  theHF2Grid(std::vector<double>(5, 10.)),
176  theHF2Weights(std::vector<double>(5, 1.)),
177  theEBweight(EBweight),
178  theEEweight(EEweight),
179  theHBweight(HBweight),
180  theHESweight(HESweight),
181  theHEDweight(HEDweight),
182  theHOweight(HOweight),
183  theHF1weight(HF1weight),
184  theHF2weight(HF2weight),
185  theEcutTower(EcutTower),
186  theEBSumThreshold(EBSumThreshold),
187  theEESumThreshold(EESumThreshold),
188  theEBEScale(50.),
189  theEEEScale(50.),
190  theHBEScale(50.),
191  theHESEScale(50.),
192  theHEDEScale(50.),
193  theHOEScale(50.),
194  theHF1EScale(50.),
195  theHF2EScale(50.),
196  theHcalTopology(nullptr),
197  theGeometry(nullptr),
198  theTowerConstituentsMap(nullptr),
199  theHcalAcceptSeverityLevel(0),
200  theRecoveredHcalHitsAreUsed(false),
201  theRecoveredEcalHitsAreUsed(false),
202  useRejectedHitsOnly(false),
203  theHcalAcceptSeverityLevelForRejectedHit(0),
204  useRejectedRecoveredHcalHits(0),
205  useRejectedRecoveredEcalHits(0),
207  theHOIsUsed(useHO),
208  // (momentum reconstruction algorithm)
209  theMomConstrMethod(momConstrMethod),
210  theMomHBDepth(momHBDepth),
211  theMomHEDepth(momHEDepth),
212  theMomEBDepth(momEBDepth),
213  theMomEEDepth(momEEDepth),
214  theHcalPhase(hcalPhase) {}
215 
217  double EEthreshold,
218  bool useEtEBTreshold,
219  bool useEtEETreshold,
220  bool useSymEBTreshold,
221  bool useSymEETreshold,
222 
223  double HcalThreshold,
224  double HBthreshold,
225  double HBthreshold1,
226  double HBthreshold2,
227  double HESthreshold,
228  double HESthreshold1,
229  double HEDthreshold,
230  double HEDthreshold1,
231  double HOthreshold0,
232  double HOthresholdPlus1,
233  double HOthresholdMinus1,
234  double HOthresholdPlus2,
235  double HOthresholdMinus2,
236  double HF1threshold,
237  double HF2threshold,
238  const std::vector<double>& EBGrid,
239  const std::vector<double>& EBWeights,
240  const std::vector<double>& EEGrid,
241  const std::vector<double>& EEWeights,
242  const std::vector<double>& HBGrid,
243  const std::vector<double>& HBWeights,
244  const std::vector<double>& HESGrid,
245  const std::vector<double>& HESWeights,
246  const std::vector<double>& HEDGrid,
247  const std::vector<double>& HEDWeights,
248  const std::vector<double>& HOGrid,
249  const std::vector<double>& HOWeights,
250  const std::vector<double>& HF1Grid,
251  const std::vector<double>& HF1Weights,
252  const std::vector<double>& HF2Grid,
253  const std::vector<double>& HF2Weights,
254  double EBweight,
255  double EEweight,
256  double HBweight,
257  double HESweight,
258  double HEDweight,
259  double HOweight,
260  double HF1weight,
261  double HF2weight,
262  double EcutTower,
263  double EBSumThreshold,
264  double EESumThreshold,
265  bool useHO,
266  // (for the momentum construction algorithm)
267  int momConstrMethod,
268  double momHBDepth,
269  double momHEDepth,
270  double momEBDepth,
271  double momEEDepth,
272  int hcalPhase)
273 
274  : theEBthreshold(EBthreshold),
275  theEEthreshold(EEthreshold),
276 
277  theUseEtEBTresholdFlag(useEtEBTreshold),
278  theUseEtEETresholdFlag(useEtEETreshold),
279  theUseSymEBTresholdFlag(useSymEBTreshold),
280  theUseSymEETresholdFlag(useSymEETreshold),
281 
282  theHcalThreshold(HcalThreshold),
283  theHBthreshold(HBthreshold),
284  theHBthreshold1(HBthreshold1),
285  theHBthreshold2(HBthreshold2),
286  theHESthreshold(HESthreshold),
287  theHESthreshold1(HESthreshold1),
288  theHEDthreshold(HEDthreshold),
289  theHEDthreshold1(HEDthreshold1),
290  theHOthreshold0(HOthreshold0),
291  theHOthresholdPlus1(HOthresholdPlus1),
292  theHOthresholdMinus1(HOthresholdMinus1),
293  theHOthresholdPlus2(HOthresholdPlus2),
294  theHOthresholdMinus2(HOthresholdMinus2),
295  theHF1threshold(HF1threshold),
296  theHF2threshold(HF2threshold),
297  theEBGrid(EBGrid),
298  theEBWeights(EBWeights),
299  theEEGrid(EEGrid),
300  theEEWeights(EEWeights),
301  theHBGrid(HBGrid),
302  theHBWeights(HBWeights),
303  theHESGrid(HESGrid),
304  theHESWeights(HESWeights),
305  theHEDGrid(HEDGrid),
306  theHEDWeights(HEDWeights),
307  theHOGrid(HOGrid),
308  theHOWeights(HOWeights),
309  theHF1Grid(HF1Grid),
310  theHF1Weights(HF1Weights),
311  theHF2Grid(HF2Grid),
312  theHF2Weights(HF2Weights),
313  theEBweight(EBweight),
314  theEEweight(EEweight),
315  theHBweight(HBweight),
316  theHESweight(HESweight),
317  theHEDweight(HEDweight),
318  theHOweight(HOweight),
319  theHF1weight(HF1weight),
320  theHF2weight(HF2weight),
321  theEcutTower(EcutTower),
322  theEBSumThreshold(EBSumThreshold),
323  theEESumThreshold(EESumThreshold),
324  theEBEScale(50.),
325  theEEEScale(50.),
326  theHBEScale(50.),
327  theHESEScale(50.),
328  theHEDEScale(50.),
329  theHOEScale(50.),
330  theHF1EScale(50.),
331  theHF2EScale(50.),
332  theHcalTopology(nullptr),
333  theGeometry(nullptr),
334  theTowerConstituentsMap(nullptr),
335  theHcalAcceptSeverityLevel(0),
336  theRecoveredHcalHitsAreUsed(false),
337  theRecoveredEcalHitsAreUsed(false),
338  useRejectedHitsOnly(false),
339  theHcalAcceptSeverityLevelForRejectedHit(0),
340  useRejectedRecoveredHcalHits(0),
341  useRejectedRecoveredEcalHits(0),
343  theHOIsUsed(useHO),
344  // (momentum reconstruction algorithm)
345  theMomConstrMethod(momConstrMethod),
346  theMomHBDepth(momHBDepth),
347  theMomHEDepth(momHEDepth),
348  theMomEBDepth(momEBDepth),
349  theMomEEDepth(momEEDepth),
350  theHcalPhase(hcalPhase) {
351  // static int N = 0;
352  // std::cout << "VI Algo " << ++N << std::endl;
353  // nalgo=N;
354 }
355 
357  ecalCuts = EcalCuts;
358  hcalCuts = HcalCuts;
359 }
360 
362  const CaloTowerConstituentsMap* ctmap,
363  const HcalTopology* htopo,
364  const CaloGeometry* geo) {
365  theTowerTopology = cttopo;
366  theTowerConstituentsMap = ctmap;
367  theHcalTopology = htopo;
368  theGeometry = geo;
370 
371  //initialize ecal bad channel map
373 }
374 
376  theTowerMap.clear();
377  theTowerMapSize = 0;
378  //hcalDropChMap.clear();
379 }
380 
382  for (HBHERecHitCollection::const_iterator hbheItr = hbhe.begin(); hbheItr != hbhe.end(); ++hbheItr)
383  assignHitHcal(&(*hbheItr));
384 }
385 
387  for (HORecHitCollection::const_iterator hoItr = ho.begin(); hoItr != ho.end(); ++hoItr)
388  assignHitHcal(&(*hoItr));
389 }
390 
392  for (HFRecHitCollection::const_iterator hfItr = hf.begin(); hfItr != hf.end(); ++hfItr)
393  assignHitHcal(&(*hfItr));
394 }
395 
397  for (EcalRecHitCollection::const_iterator ecItr = ec.begin(); ecItr != ec.end(); ++ecItr)
398  assignHitEcal(&(*ecItr));
399 }
400 
401 // this method should not be used any more as the towers in the changed format
402 // can not be properly rescaled with the "rescale" method.
403 // "rescale was replaced by "rescaleTowers"
404 //
406  for (CaloTowerCollection::const_iterator ctcItr = ctc.begin(); ctcItr != ctc.end(); ++ctcItr) {
407  rescale(&(*ctcItr));
408  }
409 }
410 
412  // now copy this map into the final collection
413  result.reserve(theTowerMapSize);
414  // auto k=0U;
415  // if (!theEbHandle.isValid()) std::cout << "VI ebHandle not valid" << std::endl;
416  // if (!theEeHandle.isValid()) std::cout << "VI eeHandle not valid" << std::endl;
417 
418  for (auto const& mt : theTowerMap) {
419  // Convert only if there is at least one constituent in the metatower.
420  // The check of constituents size in the coverted tower is still needed!
421  if (!mt.empty()) {
422  convert(mt.id, mt, result);
423  } // ++k;}
424  }
425 
426  // assert(k==theTowerMapSize);
427  // std::cout << "VI TowerMap " << theTowerMapSize << " " << k << std::endl;
428 
429  theTowerMap.clear(); // save the memory
430  theTowerMapSize = 0;
431 }
432 
434  for (CaloTowerCollection::const_iterator ctcItr = ctc.begin(); ctcItr != ctc.end(); ++ctcItr) {
435  CaloTowerDetId twrId = ctcItr->id();
436  double newE_em = ctcItr->emEnergy();
437  double newE_had = ctcItr->hadEnergy();
438  double newE_outer = ctcItr->outerEnergy();
439 
440  double threshold = 0.0; // not used: we do not change thresholds
441  double weight = 1.0;
442 
443  // HF
444  if (ctcItr->ietaAbs() >= theTowerTopology->firstHFRing()) {
445  double E_short = 0.5 * newE_had; // from the definitions for HF
446  double E_long = newE_em + 0.5 * newE_had; //
447  // scale
448  E_long *= theHF1weight;
449  E_short *= theHF2weight;
450  // convert
451  newE_em = E_long - E_short;
452  newE_had = 2.0 * E_short;
453  }
454 
455  else { // barrel/endcap
456 
457  // find if its in EB, or EE; determine from first ecal constituent found
458  for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
459  DetId constId = ctcItr->constituent(iConst);
460  if (constId.det() != DetId::Ecal)
461  continue;
463  newE_em *= weight;
464  break;
465  }
466  // HO
467  for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
468  DetId constId = ctcItr->constituent(iConst);
469  if (constId.det() != DetId::Hcal)
470  continue;
471  if (HcalDetId(constId).subdet() != HcalOuter)
472  continue;
474  newE_outer *= weight;
475  break;
476  }
477  // HB/HE
478  for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
479  DetId constId = ctcItr->constituent(iConst);
480  if (constId.det() != DetId::Hcal)
481  continue;
482  if (HcalDetId(constId).subdet() == HcalOuter)
483  continue;
485  newE_had *= weight;
486  if (ctcItr->ietaAbs() > theTowerTopology->firstHERing())
487  newE_outer *= weight;
488  break;
489  }
490 
491  } // barrel/endcap region
492 
493  // now make the new tower
494 
495  double newE_hadTot =
496  (theHOIsUsed && twrId.ietaAbs() <= theTowerTopology->lastHORing()) ? newE_had + newE_outer : newE_had;
497 
498  GlobalPoint emPoint = ctcItr->emPosition();
499  GlobalPoint hadPoint = ctcItr->emPosition();
500 
501  double f_em = 1.0 / cosh(emPoint.eta());
502  double f_had = 1.0 / cosh(hadPoint.eta());
503 
505 
506  if (ctcItr->ietaAbs() < theTowerTopology->firstHFRing()) {
507  if (newE_em > 0)
508  towerP4 += CaloTower::PolarLorentzVector(newE_em * f_em, emPoint.eta(), emPoint.phi(), 0);
509  if (newE_hadTot > 0)
510  towerP4 += CaloTower::PolarLorentzVector(newE_hadTot * f_had, hadPoint.eta(), hadPoint.phi(), 0);
511  } else {
512  double newE_tot = newE_em + newE_had;
513  // for HF we use common point for ecal, hcal shower positions regardless of the method
514  if (newE_tot > 0)
515  towerP4 += CaloTower::PolarLorentzVector(newE_tot * f_had, hadPoint.eta(), hadPoint.phi(), 0);
516  }
517 
518  CaloTower rescaledTower(twrId, newE_em, newE_had, newE_outer, -1, -1, towerP4, emPoint, hadPoint);
519  // copy the timings, have to convert back to int, 1 unit = 0.01 ns
520  rescaledTower.setEcalTime(int(ctcItr->ecalTime() * 100.0 + 0.5));
521  rescaledTower.setHcalTime(int(ctcItr->hcalTime() * 100.0 + 0.5));
522  //add topology info
523  rescaledTower.setHcalSubdet(theTowerTopology->lastHBRing(),
527 
528  std::vector<DetId> contains;
529  for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
530  contains.push_back(ctcItr->constituent(iConst));
531  }
532  rescaledTower.addConstituents(contains);
533 
534  rescaledTower.setCaloTowerStatus(ctcItr->towerStatusWord());
535 
536  ctcResult.push_back(rescaledTower);
537 
538  } // end of loop over towers
539 }
540 
542  DetId detId = recHit->detid();
543  DetId detIdF(detId);
546 #ifdef EDM_ML_DEBUG
547  std::cout << "AssignHitHcal DetId " << HcalDetId(detId) << " Front " << HcalDetId(detIdF) << std::endl;
548 #endif
549  }
550 
551  unsigned int chStatusForCT = hcalChanStatusForCaloTower(recHit);
552 
553  // this is for skipping channls: mostly needed for the creation of
554  // bad towers from hits i the bad channel collections.
555  if (chStatusForCT == CaloTowersCreationAlgo::IgnoredChan)
556  return;
557 
558  double threshold, weight;
560 
561  double energy = recHit->energy(); // original RecHit energy is used to apply thresholds
562  double e = energy * weight; // energies scaled by user weight: used in energy assignments
563 
564  // SPECIAL handling of tower 28 merged depths --> half into tower 28 and half into tower 29
565  bool merge(false);
566  if (detIdF.det() == DetId::Hcal && HcalDetId(detIdF).subdet() == HcalEndcap &&
567  (theHcalPhase == 0 || theHcalPhase == 1) &&
568  //HcalDetId(detId).depth()==3 &&
569  HcalDetId(detIdF).ietaAbs() == theHcalTopology->lastHERing() - 1) {
571 #ifdef EDM_ML_DEBUG
572  std::cout << "Merge " << HcalDetId(detIdF) << ":" << merge << std::endl;
573 #endif
574  }
575  if (merge) {
577 
578  // bad channels are counted regardless of energy threshold
579 
580  if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
582  if (towerDetId.null())
583  return;
584  MetaTower& tower28 = find(towerDetId);
585  CaloTowerDetId towerDetId29(towerDetId.ieta() + towerDetId.zside(), towerDetId.iphi());
586  MetaTower& tower29 = find(towerDetId29);
587  tower28.numBadHcalCells += 1;
588  tower29.numBadHcalCells += 1;
589  }
590 
591  else if (0.5 * energy >= threshold) { // not bad channel: use energy if above threshold
592 
594  if (towerDetId.null())
595  return;
596  MetaTower& tower28 = find(towerDetId);
597  CaloTowerDetId towerDetId29(towerDetId.ieta() + towerDetId.zside(), towerDetId.iphi());
598  MetaTower& tower29 = find(towerDetId29);
599 
600  if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
601  tower28.numRecHcalCells += 1;
602  tower29.numRecHcalCells += 1;
603  } else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
604  tower28.numProbHcalCells += 1;
605  tower29.numProbHcalCells += 1;
606  }
607 
608  // NOTE DIVIDE BY 2!!!
609  double e28 = 0.5 * e;
610  double e29 = 0.5 * e;
611 
612  tower28.E_had += e28;
613  tower28.E += e28;
614  std::pair<DetId, float> mc(detId, e28);
615  tower28.metaConstituents.push_back(mc);
616 
617  tower29.E_had += e29;
618  tower29.E += e29;
619  tower29.metaConstituents.push_back(mc);
620 
621  // time info: do not use in averaging if timing error is found: need
622  // full set of status info to implement: use only "good" channels for now
623 
624  if (chStatusForCT == CaloTowersCreationAlgo::GoodChan) {
625  tower28.hadSumTimeTimesE += (e28 * recHit->time());
626  tower28.hadSumEForTime += e28;
627  tower29.hadSumTimeTimesE += (e29 * recHit->time());
628  tower29.hadSumEForTime += e29;
629  }
630 
631  // store the energy in layer 3 also in E_outer
632  tower28.E_outer += e28;
633  tower29.E_outer += e29;
634  } // not a "bad" hit
635  } // end of special case
636 
637  else {
638  HcalDetId hcalDetId(detId);
639 
641 
642  if (hcalDetId.subdet() == HcalOuter) {
644  if (towerDetId.null())
645  return;
646  MetaTower& tower = find(towerDetId);
647 
648  if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
649  if (theHOIsUsed)
650  tower.numBadHcalCells += 1;
651  }
652 
653  else if (energy >= threshold) {
654  tower.E_outer += e; // store HO energy even if HO is not used
655  // add energy of the tower and/or flag if theHOIsUsed
656  if (theHOIsUsed) {
657  tower.E += e;
658 
659  if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
660  tower.numRecHcalCells += 1;
661  } else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
662  tower.numProbHcalCells += 1;
663  }
664  } // HO is used
665 
666  // add HO to constituents even if it is not used: JetMET wants to keep these towers
667  std::pair<DetId, float> mc(detId, e);
668  tower.metaConstituents.push_back(mc);
669 
670  } // not a bad channel, energy above threshold
671 
672  } // HO hit
673 
674  // HF calculates EM fraction differently
675  else if (hcalDetId.subdet() == HcalForward) {
676  if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
678  if (towerDetId.null())
679  return;
680  MetaTower& tower = find(towerDetId);
681  tower.numBadHcalCells += 1;
682  }
683 
684  else if (energy >= threshold) {
686  if (towerDetId.null())
687  return;
688  MetaTower& tower = find(towerDetId);
689 
690  if (hcalDetId.depth() == 1) {
691  // long fiber, so E_EM = E(Long) - E(Short)
692  tower.E_em += e;
693  } else {
694  // short fiber, EHAD = 2 * E(Short)
695  tower.E_em -= e;
696  tower.E_had += 2. * e;
697  }
698  tower.E += e;
699  if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
700  tower.numRecHcalCells += 1;
701  } else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
702  tower.numProbHcalCells += 1;
703  }
704 
705  // put the timing in HCAL -> have to check timing errors when available
706  // for now use only good channels
707  if (chStatusForCT == CaloTowersCreationAlgo::GoodChan) {
708  tower.hadSumTimeTimesE += (e * recHit->time());
709  tower.hadSumEForTime += e;
710  }
711 
712  std::pair<DetId, float> mc(detId, e);
713  tower.metaConstituents.push_back(mc);
714 
715  } // not a bad HF channel, energy above threshold
716 
717  } // HF hit
718 
719  else {
720  // HCAL situation normal in HB/HE
721  if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
723  if (towerDetId.null())
724  return;
725  MetaTower& tower = find(towerDetId);
726  tower.numBadHcalCells += 1;
727  } else if (energy >= threshold) {
729  if (towerDetId.null())
730  return;
731  MetaTower& tower = find(towerDetId);
732  tower.E_had += e;
733  tower.E += e;
734  if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
735  tower.numRecHcalCells += 1;
736  } else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
737  tower.numProbHcalCells += 1;
738  }
739 
740  // Timing information: need specific accessors
741  // for now use only good channels
742  if (chStatusForCT == CaloTowersCreationAlgo::GoodChan) {
743  tower.hadSumTimeTimesE += (e * recHit->time());
744  tower.hadSumEForTime += e;
745  }
746  // store energy in highest depth for towers 18-27 (for electron,photon ID in endcap)
747  // also, store energy in HE part of tower 16 (for JetMET cleanup)
748  HcalDetId hcalDetId(detId);
749  if (hcalDetId.subdet() == HcalEndcap) {
750  if (theHcalPhase == 0) {
751  if ((hcalDetId.depth() == 2 && hcalDetId.ietaAbs() >= 18 && hcalDetId.ietaAbs() < 27) ||
752  (hcalDetId.depth() == 3 && hcalDetId.ietaAbs() == 27) ||
753  (hcalDetId.depth() == 3 && hcalDetId.ietaAbs() == 16)) {
754  tower.E_outer += e;
755  }
756  }
757  //combine depths in phase0-like way
758  else if (theHcalPhase == 1) {
759  if ((hcalDetId.depth() >= 3 && hcalDetId.ietaAbs() >= 18 && hcalDetId.ietaAbs() < 26) ||
760  (hcalDetId.depth() >= 4 && (hcalDetId.ietaAbs() == 26 || hcalDetId.ietaAbs() == 27)) ||
761  (hcalDetId.depth() == 3 && hcalDetId.ietaAbs() == 17) ||
762  (hcalDetId.depth() == 4 && hcalDetId.ietaAbs() == 16)) {
763  tower.E_outer += e;
764  }
765  }
766  }
767 
768  std::pair<DetId, float> mc(detId, e);
769  tower.metaConstituents.push_back(mc);
770 
771  } // not a "bad" channel, energy above threshold
772 
773  } // channel in HBHE (excluding twrs 28,29)
774 
775  } // recHit normal case (not in HE towers 28,29)
776 
777 } // end of assignHitHcal method
778 
780  DetId detId = recHit->detid();
781 
782  unsigned int chStatusForCT;
783  bool ecalIsBad = false;
784  std::tie(chStatusForCT, ecalIsBad) = ecalChanStatusForCaloTower(recHit);
785 
786  // this is for skipping channls: mostly needed for the creation of
787  // bad towers from hits i the bad channel collections.
788  if (chStatusForCT == CaloTowersCreationAlgo::IgnoredChan)
789  return;
790 
791  double threshold, weight;
793 
794  double energy = recHit->energy(); // original RecHit energy is used to apply thresholds
795  double e = energy * weight; // energies scaled by user weight: used in energy assignments
796 
798 
799  // For ECAL we count all bad channels after the metatower is complete
800 
801  // Include options for symmetric thresholds and cut on Et
802  // for ECAL RecHits
803 
804  bool passEmThreshold = false;
805 
806  if (detId.subdetId() == EcalBarrel) {
808  energy /= cosh((theGeometry->getGeometry(detId)->getPosition()).eta());
810  passEmThreshold = (fabs(energy) >= threshold);
811  else
812  passEmThreshold = (energy >= threshold);
813 
814  } else if (detId.subdetId() == EcalEndcap) {
816  energy /= cosh((theGeometry->getGeometry(detId)->getPosition()).eta());
818  passEmThreshold = (fabs(energy) >= threshold);
819  else
820  passEmThreshold = (energy >= threshold);
821  }
822 
824  if (towerDetId.null())
825  return;
826  MetaTower& tower = find(towerDetId);
827 
828  // count bad cells and avoid double counting with those from DB (Recovered are counted bad)
829 
830  // somehow misses some
831  // if ( (chStatusForCT == CaloTowersCreationAlgo::BadChan) & (!ecalIsBad) ) ++tower.numBadEcalCells;
832 
833  // a bit slower...
834  if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
835  auto thisEcalSevLvl = theEcalSevLvlAlgo->severityLevel(detId);
836  // check if the Ecal severity is ok to keep
837  auto sevit = std::find(theEcalSeveritiesToBeExcluded.begin(), theEcalSeveritiesToBeExcluded.end(), thisEcalSevLvl);
838  if (sevit == theEcalSeveritiesToBeExcluded.end())
839  ++tower.numBadEcalCells; // notinDB
840  }
841 
842  // if (chStatusForCT != CaloTowersCreationAlgo::BadChan && energy >= threshold) {
843  if (chStatusForCT != CaloTowersCreationAlgo::BadChan && passEmThreshold) {
844  tower.E_em += e;
845  tower.E += e;
846 
847  if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
848  tower.numRecEcalCells += 1;
849  } else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
850  tower.numProbEcalCells += 1;
851  }
852 
853  // change when full status info is available
854  // for now use only good channels
855 
856  // add e>0 check (new options allow e<0)
857  if (chStatusForCT == CaloTowersCreationAlgo::GoodChan && e > 0) {
858  tower.emSumTimeTimesE += (e * recHit->time());
859  tower.emSumEForTime += e; // see above
860  }
861 
862  std::pair<DetId, float> mc(detId, e);
863  tower.metaConstituents.push_back(mc);
864  }
865 } // end of assignHitEcal method
866 
867 // This method is not flexible enough for the new CaloTower format.
868 // For now make a quick compatibility "fix" : WILL NOT WORK CORRECTLY with anything
869 // except the default simple p4 assignment!!!
870 // Must be rewritten for full functionality.
872  double threshold, weight;
873  CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(ct->id());
874  if (towerDetId.null())
875  return;
876  MetaTower& tower = find(towerDetId);
877 
878  tower.E_em = 0.;
879  tower.E_had = 0.;
880  tower.E_outer = 0.;
881  for (unsigned int i = 0; i < ct->constituentsSize(); i++) {
882  DetId detId = ct->constituent(i);
884  DetId::Detector det = detId.det();
885  if (det == DetId::Ecal) {
886  tower.E_em = ct->emEnergy() * weight;
887  } else {
888  HcalDetId hcalDetId(detId);
889  if (hcalDetId.subdet() == HcalForward) {
890  if (hcalDetId.depth() == 1)
891  tower.E_em = ct->emEnergy() * weight;
892  if (hcalDetId.depth() == 2)
893  tower.E_had = ct->hadEnergy() * weight;
894  } else if (hcalDetId.subdet() == HcalOuter) {
895  tower.E_outer = ct->outerEnergy() * weight;
896  } else {
897  tower.E_had = ct->hadEnergy() * weight;
898  }
899  }
900  tower.E = tower.E_had + tower.E_em + tower.E_outer;
901 
902  // this is to be compliant with the new MetaTower setup
903  // used only for the default simple vector assignment
904  std::pair<DetId, float> mc(detId, 0);
905  tower.metaConstituents.push_back(mc);
906  }
907 
908  // preserve time inforamtion
909  tower.emSumTimeTimesE = ct->ecalTime();
910  tower.hadSumTimeTimesE = ct->hcalTime();
911  tower.emSumEForTime = 1.0;
912  tower.hadSumEForTime = 1.0;
913 }
914 
916  if (theTowerMap.empty()) {
918  }
919 
921 
922  if (mt.empty()) {
923  mt.id = detId;
924  mt.metaConstituents.reserve(detId.ietaAbs() < theTowerTopology->firstHFRing() ? 12 : 2);
925  ++theTowerMapSize;
926  }
927 
928  return mt;
929 }
930 
932  assert(id.rawId() != 0);
933 
934  double ecalThres = (id.ietaAbs() <= 17) ? (theEBSumThreshold) : (theEESumThreshold);
935  double E = mt.E;
936  double E_em = mt.E_em;
937  double E_had = mt.E_had;
938  double E_outer = mt.E_outer;
939 
940  // Note: E_outer is used to save HO energy OR energy in the outermost depths in endcap region
941  // In the methods with separate treatment of EM and HAD components:
942  // - HO is not used to determine direction, however HO energy is added to get "total had energy"
943  // => Check if the tower is within HO coverage before adding E_outer to the "total had" energy
944  // else the energy will be double counted
945  // When summing up the energy of the tower these checks are performed in the loops over RecHits
946 
947  std::vector<std::pair<DetId, float> > metaContains = mt.metaConstituents;
948  if (id.ietaAbs() < theTowerTopology->firstHFRing() && E_em < ecalThres) { // ignore EM threshold in HF
949  E -= E_em;
950  E_em = 0;
951  std::vector<std::pair<DetId, float> > metaContains_noecal;
952 
953  for (std::vector<std::pair<DetId, float> >::iterator i = metaContains.begin(); i != metaContains.end(); ++i)
954  if (i->first.det() != DetId::Ecal)
955  metaContains_noecal.push_back(*i);
956  metaContains.swap(metaContains_noecal);
957  }
958  if (id.ietaAbs() < theTowerTopology->firstHFRing() && E_had < theHcalThreshold) {
959  E -= E_had;
960 
962  E -= E_outer; // not subtracted before, think it should be done
963 
964  E_had = 0;
965  E_outer = 0;
966  std::vector<std::pair<DetId, float> > metaContains_nohcal;
967 
968  for (std::vector<std::pair<DetId, float> >::iterator i = metaContains.begin(); i != metaContains.end(); ++i)
969  if (i->first.det() != DetId::Hcal)
970  metaContains_nohcal.push_back(*i);
971  metaContains.swap(metaContains_nohcal);
972  }
973 
974  if (metaContains.empty())
975  return;
976 
977  if (missingHcalRescaleFactorForEcal > 0 && E_had == 0 && E_em > 0) {
978  auto match = hcalDropChMap.find(id);
979  if (match != hcalDropChMap.end() && match->second.second) {
980  E_had = missingHcalRescaleFactorForEcal * E_em;
981  E += E_had;
982  }
983  }
984 
985  double E_had_tot = (theHOIsUsed && id.ietaAbs() <= theTowerTopology->lastHORing()) ? E_had + E_outer : E_had;
986 
987  // create CaloTower using the selected algorithm
988 
989  GlobalPoint emPoint, hadPoint;
990 
991  // this is actually a 4D vector
992  Basic3DVectorF towerP4;
993  bool massless = true;
994  // float mass1=0;
995  float mass2 = 0;
996 
997  // conditional assignment of depths for barrel/endcap
998  // Some additional tuning may be required in the transitional region
999  // 14<|iEta|<19
1000  double momEmDepth = 0.;
1001  double momHadDepth = 0.;
1002  if (id.ietaAbs() <= 17) {
1003  momHadDepth = theMomHBDepth;
1004  momEmDepth = theMomEBDepth;
1005  } else {
1006  momHadDepth = theMomHEDepth;
1007  momEmDepth = theMomEEDepth;
1008  }
1009 
1010  switch (theMomConstrMethod) {
1011  // FIXME : move to simple cartesian algebra
1012  case 0: { // Simple 4-momentum assignment
1013  GlobalPoint p = theTowerGeometry->getGeometry(id)->getPosition();
1014  towerP4 = p.basicVector().unit();
1015  towerP4.mathVector()[3] = 1.f; // energy
1016  towerP4 *= E;
1017 
1018  // double pf=1.0/cosh(p.eta());
1019  // if (E>0) towerP4 = CaloTower::PolarLorentzVector(E*pf, p.eta(), p.phi(), 0);
1020 
1021  emPoint = p;
1022  hadPoint = p;
1023  } // end case 0
1024  break;
1025 
1026  case 1: { // separate 4-vectors for ECAL, HCAL, add to get the 4-vector of the tower (=>tower has mass!)
1027  if (id.ietaAbs() < theTowerTopology->firstHFRing()) {
1028  Basic3DVectorF emP4;
1029  if (E_em > 0) {
1030  emPoint = emShwrPos(metaContains, momEmDepth, E_em);
1031  emP4 = emPoint.basicVector().unit();
1032  emP4.mathVector()[3] = 1.f; // energy
1033  towerP4 = emP4 * E_em;
1034 
1035  // double emPf = 1.0/cosh(emPoint.eta());
1036  // towerP4 += CaloTower::PolarLorentzVector(E_em*emPf, emPoint.eta(), emPoint.phi(), 0);
1037  }
1038  if ((E_had + E_outer) > 0) {
1039  massless = (E_em <= 0);
1040  hadPoint = hadShwrPos(id, momHadDepth);
1041  auto lP4 = hadPoint.basicVector().unit();
1042  lP4.mathVector()[3] = 1.f; // energy
1043  if (!massless) {
1044  auto diff = lP4 - emP4;
1045  mass2 = std::sqrt(E_em * E_had_tot * diff.mag2());
1046  }
1047  lP4 *= E_had_tot;
1048  towerP4 += lP4;
1049  /*
1050  if (!massless) {
1051  auto p = towerP4;
1052  double m2 = double(p[3]*p[3]) - double(p[0]*p[0])+double(p[1]*p[1])+double(p[2]*p[2]); mass1 = m2>0 ? std::sqrt(m2) : 0;
1053  }
1054  */
1055  // double hadPf = 1.0/cosh(hadPoint.eta());
1056  // if (E_had_tot>0) {
1057  // towerP4 += CaloTower::PolarLorentzVector(E_had_tot*hadPf, hadPoint.eta(), hadPoint.phi(), 0);
1058  // }
1059  }
1060  } else { // forward detector: use the CaloTower position
1061  GlobalPoint p = theTowerGeometry->getGeometry(id)->getPosition();
1062  towerP4 = p.basicVector().unit();
1063  towerP4.mathVector()[3] = 1.f; // energy
1064  towerP4 *= E;
1065  // double pf=1.0/cosh(p.eta());
1066  // if (E>0) towerP4 = CaloTower::PolarLorentzVector(E*pf, p.eta(), p.phi(), 0); // simple momentum assignment, same position
1067  emPoint = p;
1068  hadPoint = p;
1069  }
1070  } // end case 1
1071  break;
1072 
1073  case 2: { // use ECAL position for the tower (when E_cal>0), else default CaloTower position (massless tower)
1074  if (id.ietaAbs() < theTowerTopology->firstHFRing()) {
1075  if (E_em > 0)
1076  emPoint = emShwrLogWeightPos(metaContains, momEmDepth, E_em);
1077  else
1078  emPoint = theTowerGeometry->getGeometry(id)->getPosition();
1079  towerP4 = emPoint.basicVector().unit();
1080  towerP4.mathVector()[3] = 1.f; // energy
1081  towerP4 *= E;
1082 
1083  // double sumPf = 1.0/cosh(emPoint.eta());
1085 
1086  hadPoint = emPoint;
1087  } else { // forward detector: use the CaloTower position
1088  GlobalPoint p = theTowerGeometry->getGeometry(id)->getPosition();
1089  towerP4 = p.basicVector().unit();
1090  towerP4.mathVector()[3] = 1.f; // energy
1091  towerP4 *= E;
1092 
1093  // double pf=1.0/cosh(p.eta());
1094  // if (E>0) towerP4 = CaloTower::PolarLorentzVector(E*pf, p.eta(), p.phi(), 0); // simple momentum assignment, same position
1095  emPoint = p;
1096  hadPoint = p;
1097  }
1098  } // end case 2
1099  break;
1100 
1101  } // end of decision on p4 reconstruction method
1102 
1103  // insert in collection (remove and return if below threshold)
1104  if UNLIKELY ((towerP4[3] == 0) & (E_outer > 0)) {
1105  float val = theHOIsUsed ? 0 : 1E-9; // to keep backwards compatibility for theHOIsUsed == true
1106  collection.emplace_back(id,
1107  E_em,
1108  E_had,
1109  E_outer,
1110  -1,
1111  -1,
1112  CaloTower::PolarLorentzVector(val, hadPoint.eta(), hadPoint.phi(), 0),
1113  emPoint,
1114  hadPoint);
1115  } else {
1116  collection.emplace_back(
1117  id, E_em, E_had, E_outer, -1, -1, GlobalVector(towerP4), towerP4[3], mass2, emPoint, hadPoint);
1118  }
1119  auto& caloTower = collection.back();
1120 
1121  // if (!massless) std::cout << "massive " << id <<' ' << mass1 <<' ' << mass2 <<' ' << caloTower.mass() << std::endl;
1122  // std::cout << "CaloTowerVI " <<theMomConstrMethod <<' ' << id <<' '<< E_em <<' '<< E_had <<' '<< E_outer <<' '<< GlobalVector(towerP4) <<' '<< towerP4[3] <<' '<< emPoint <<' '<< hadPoint << std::endl;
1123  //if (towerP4[3]==0) std::cout << "CaloTowerVIzero " << theEcutTower << ' ' << collection.back().eta() <<' '<< collection.back().phi() << std::endl;
1124 
1125  if (caloTower.energy() < theEcutTower) {
1126  collection.pop_back();
1127  return;
1128  }
1129 
1130  // set the timings
1131  float ecalTime = (mt.emSumEForTime > 0) ? mt.emSumTimeTimesE / mt.emSumEForTime : -9999;
1132  float hcalTime = (mt.hadSumEForTime > 0) ? mt.hadSumTimeTimesE / mt.hadSumEForTime : -9999;
1133  caloTower.setEcalTime(compactTime(ecalTime));
1134  caloTower.setHcalTime(compactTime(hcalTime));
1135  //add topology info
1136  caloTower.setHcalSubdet(theTowerTopology->lastHBRing(),
1140 
1141  // set the CaloTower status word =====================================
1142  // Channels must be counter exclusively in the defined cathegories
1143  // "Bad" channels (not used in energy assignment) can be flagged during
1144  // CaloTower creation only if specified in the configuration file
1145 
1146  unsigned int numBadHcalChan = mt.numBadHcalCells;
1147  // unsigned int numBadEcalChan = mt.numBadEcalCells;
1148  unsigned int numBadEcalChan = 0; //
1149 
1150  unsigned int numRecHcalChan = mt.numRecHcalCells;
1151  unsigned int numRecEcalChan = mt.numRecEcalCells;
1152  unsigned int numProbHcalChan = mt.numProbHcalCells;
1153  unsigned int numProbEcalChan = mt.numProbEcalCells;
1154 
1155  // now add dead/off/... channels not used in RecHit reconstruction for HCAL
1156  HcalDropChMap::iterator dropChItr = hcalDropChMap.find(id);
1157  if (dropChItr != hcalDropChMap.end())
1158  numBadHcalChan += dropChItr->second.first;
1159 
1160  // for ECAL the number of all bad channels is obtained here -----------------------
1161 
1162  /*
1163  // old hyper slow algorithm
1164  // get all possible constituents of the tower
1165  std::vector<DetId> allConstituents = theTowerConstituentsMap->constituentsOf(id);
1166 
1167  for (std::vector<DetId>::iterator ac_it=allConstituents.begin();
1168  ac_it!=allConstituents.end(); ++ac_it) {
1169 
1170  if (ac_it->det()!=DetId::Ecal) continue;
1171 
1172  int thisEcalSevLvl = -999;
1173 
1174  if (ac_it->subdetId() == EcalBarrel && theEbHandle.isValid()) {
1175  thisEcalSevLvl = theEcalSevLvlAlgo->severityLevel( *ac_it, *theEbHandle);//, *theEcalChStatus);
1176  }
1177  else if (ac_it->subdetId() == EcalEndcap && theEeHandle.isValid()) {
1178  thisEcalSevLvl = theEcalSevLvlAlgo->severityLevel( *ac_it, *theEeHandle);//, *theEcalChStatus);
1179  }
1180 
1181  // check if the Ecal severity is ok to keep
1182  std::vector<int>::const_iterator sevit = std::find(theEcalSeveritiesToBeExcluded.begin(),
1183  theEcalSeveritiesToBeExcluded.end(),
1184  thisEcalSevLvl);
1185  if (sevit!=theEcalSeveritiesToBeExcluded.end()) {
1186  ++numBadEcalChan;
1187  }
1188 
1189  }
1190 
1191  // compare with fast version
1192 
1193  // hcal:
1194  int inEcals[2] = {0,0};
1195  for (std::vector<std::pair<DetId,float> >::iterator i=metaContains.begin(); i!=metaContains.end(); ++i) {
1196  DetId detId = i->first;
1197  if(detId.det() == DetId::Ecal){
1198  if( detId.subdetId()==EcalBarrel ) inEcals[0] =1;
1199  else if( detId.subdetId()==EcalEndcap ) inEcals[1] =1;
1200  }
1201  }
1202 
1203  auto numBadEcalChanNew = ecalBadChs[theTowerTopology->denseIndex(id)]+mt.numBadEcalCells; // - mt.numRecEcalCells
1204  if (int(numBadEcalChanNew)!=int(numBadEcalChan)) {
1205  std::cout << "VI wrong " << ((inEcals[1]==1) ? "EE" : "" ) << id << " " << numBadEcalChanNew << " " << numBadEcalChan
1206  << " " << mt.numBadEcalCells << " " << mt.numRecEcalCells << std::endl;
1207  }
1208  */
1209 
1210  numBadEcalChan = ecalBadChs[theTowerTopology->denseIndex(id)] + mt.numBadEcalCells; // - mt.numRecEcalCells
1211 
1212  //--------------------------------------------------------------------------------------
1213 
1214  caloTower.setCaloTowerStatus(
1215  numBadHcalChan, numBadEcalChan, numRecHcalChan, numRecEcalChan, numProbHcalChan, numProbEcalChan);
1216 
1217  double maxCellE = -999.0; // for storing the hottest cell E in the calotower
1218 
1219  std::vector<DetId> contains;
1220  contains.reserve(metaContains.size());
1221  for (std::vector<std::pair<DetId, float> >::iterator i = metaContains.begin(); i != metaContains.end(); ++i) {
1222  contains.push_back(i->first);
1223 
1224  if (maxCellE < i->second) {
1225  // need an extra check because of the funny towers that are empty except for the presence of an HO
1226  // hit in the constituents (JetMET wanted them saved)
1227  // This constituent is only used for storing the tower, but should not be concidered as a hot cell canditate for
1228  // configurations with useHO = false
1229 
1230  if (i->first.det() == DetId::Ecal) { // ECAL
1231  maxCellE = i->second;
1232  } else { // HCAL
1233  if (HcalDetId(i->first).subdet() != HcalOuter)
1234  maxCellE = i->second;
1235  else if (theHOIsUsed)
1236  maxCellE = i->second;
1237  }
1238 
1239  } // found higher E cell
1240 
1241  } // loop over matacontains
1242 
1243  caloTower.setConstituents(std::move(contains));
1244  caloTower.setHottestCellE(maxCellE);
1245 
1246  // std::cout << "CaloTowerVI " << nalgo << ' ' << caloTower.id() << ((inEcals[1]==1) ? "EE " : " " ) << caloTower.pt() << ' ' << caloTower.et() << ' ' << caloTower.mass() << ' '
1247  // << caloTower.constituentsSize() <<' '<< caloTower.towerStatusWord() << std::endl;
1248 }
1249 
1251  DetId::Detector det = detId.det();
1252  weight = 0; // in case the hit is not identified
1253 
1254  if (det == DetId::Ecal) {
1255  // may or may not be EB. We'll find out.
1256 
1257  EcalSubdetector subdet = (EcalSubdetector)(detId.subdetId());
1258  if (subdet == EcalBarrel) {
1259  if (ecalCuts == nullptr) { // this means that ecalRecHitThresh_ is false
1261  } else {
1262  threshold = (*ecalCuts)[detId];
1263  }
1264  weight = theEBweight;
1265  if (weight <= 0.) {
1266  ROOT::Math::Interpolator my(theEBGrid, theEBWeights, ROOT::Math::Interpolation::kAKIMA);
1267  weight = my.Eval(theEBEScale);
1268  }
1269  } else if (subdet == EcalEndcap) {
1270  if (ecalCuts == nullptr) {
1272  } else {
1273  threshold = (*ecalCuts)[detId];
1274  }
1275  weight = theEEweight;
1276  if (weight <= 0.) {
1277  ROOT::Math::Interpolator my(theEEGrid, theEEWeights, ROOT::Math::Interpolation::kAKIMA);
1278  weight = my.Eval(theEEEScale);
1279  }
1280  }
1281  } else if (det == DetId::Hcal) {
1282  HcalDetId hcalDetId(detId);
1283  HcalSubdetector subdet = hcalDetId.subdet();
1284  int depth = hcalDetId.depth();
1285 
1286  if (subdet == HcalBarrel) {
1287  if (hcalCuts == nullptr) { // this means cutsFromDB is false
1289  } else { // hcalCuts is not nullptr, i.e. cutsFromDB is true
1290  const HcalPFCut* item = hcalCuts->getValues(hcalDetId.rawId());
1291  threshold = item->noiseThreshold();
1292  }
1293  weight = theHBweight;
1294  if (weight <= 0.) {
1295  ROOT::Math::Interpolator my(theHBGrid, theHBWeights, ROOT::Math::Interpolation::kAKIMA);
1296  weight = my.Eval(theHBEScale);
1297  }
1298  }
1299 
1300  else if (subdet == HcalEndcap) {
1301  // check if it's single or double tower
1302  if (hcalDetId.ietaAbs() < theHcalTopology->firstHEDoublePhiRing()) {
1303  if (hcalCuts == nullptr) { // this means cutsFromDB is false
1305  } else { // hcalCuts is not nullptr, i.e. cutsFromDB is true
1306  const HcalPFCut* item = hcalCuts->getValues(hcalDetId.rawId());
1307  threshold = item->noiseThreshold();
1308  }
1309  weight = theHESweight;
1310  if (weight <= 0.) {
1311  ROOT::Math::Interpolator my(theHESGrid, theHESWeights, ROOT::Math::Interpolation::kAKIMA);
1312  weight = my.Eval(theHESEScale);
1313  }
1314  } else {
1315  if (hcalCuts == nullptr) { // this means cutsFromDB is false
1317  } else { // hcalCuts is not nullptr, i.e. cutsFromDB is true
1318  const HcalPFCut* item = hcalCuts->getValues(hcalDetId.rawId());
1319  threshold = item->noiseThreshold();
1320  }
1321  weight = theHEDweight;
1322  if (weight <= 0.) {
1323  ROOT::Math::Interpolator my(theHEDGrid, theHEDWeights, ROOT::Math::Interpolation::kAKIMA);
1324  weight = my.Eval(theHEDEScale);
1325  }
1326  }
1327  }
1328 
1329  else if (subdet == HcalOuter) {
1330  //check if it's ring 0 or +1 or +2 or -1 or -2
1331  if (hcalDetId.ietaAbs() <= 4)
1333  else if (hcalDetId.ieta() < 0) {
1334  // set threshold for ring -1 or -2
1335  threshold = (hcalDetId.ietaAbs() <= 10) ? theHOthresholdMinus1 : theHOthresholdMinus2;
1336  } else {
1337  // set threshold for ring +1 or +2
1338  threshold = (hcalDetId.ietaAbs() <= 10) ? theHOthresholdPlus1 : theHOthresholdPlus2;
1339  }
1340  weight = theHOweight;
1341  if (weight <= 0.) {
1342  ROOT::Math::Interpolator my(theHOGrid, theHOWeights, ROOT::Math::Interpolation::kAKIMA);
1343  weight = my.Eval(theHOEScale);
1344  }
1345  }
1346 
1347  else if (subdet == HcalForward) {
1348  if (hcalDetId.depth() == 1) {
1350  weight = theHF1weight;
1351  if (weight <= 0.) {
1352  ROOT::Math::Interpolator my(theHF1Grid, theHF1Weights, ROOT::Math::Interpolation::kAKIMA);
1353  weight = my.Eval(theHF1EScale);
1354  }
1355  } else {
1357  weight = theHF2weight;
1358  if (weight <= 0.) {
1359  ROOT::Math::Interpolator my(theHF2Grid, theHF2Weights, ROOT::Math::Interpolation::kAKIMA);
1360  weight = my.Eval(theHF2EScale);
1361  }
1362  }
1363  }
1364  } else {
1365  edm::LogError("CaloTowersCreationAlgo") << "Bad cell: " << det << std::endl;
1366  }
1367 }
1368 
1370  if (scale > 0.00001)
1371  *&theEBEScale = scale;
1372  else
1373  *&theEBEScale = 50.;
1374 }
1375 
1377  if (scale > 0.00001)
1378  *&theEEEScale = scale;
1379  else
1380  *&theEEEScale = 50.;
1381 }
1382 
1384  if (scale > 0.00001)
1385  *&theHBEScale = scale;
1386  else
1387  *&theHBEScale = 50.;
1388 }
1389 
1391  if (scale > 0.00001)
1392  *&theHESEScale = scale;
1393  else
1394  *&theHESEScale = 50.;
1395 }
1396 
1398  if (scale > 0.00001)
1399  *&theHEDEScale = scale;
1400  else
1401  *&theHEDEScale = 50.;
1402 }
1403 
1405  if (scale > 0.00001)
1406  *&theHOEScale = scale;
1407  else
1408  *&theHOEScale = 50.;
1409 }
1410 
1412  if (scale > 0.00001)
1413  *&theHF1EScale = scale;
1414  else
1415  *&theHF1EScale = 50.;
1416 }
1417 
1419  if (scale > 0.00001)
1420  *&theHF2EScale = scale;
1421  else
1422  *&theHF2EScale = 50.;
1423 }
1424 
1426  auto cellGeometry = theGeometry->getGeometry(detId);
1427  GlobalPoint point = cellGeometry->getPosition(); // face of the cell
1428 
1429  if (fracDepth <= 0)
1430  return point;
1431  if (fracDepth > 1)
1432  fracDepth = 1;
1433 
1434  const GlobalPoint& backPoint = cellGeometry->getBackPoint();
1435  point += fracDepth * (backPoint - point);
1436 
1437  return point;
1438 }
1439 
1441  // same code as above
1442  return emCrystalShwrPos(detId, fracDepth);
1443 }
1444 
1445 GlobalPoint CaloTowersCreationAlgo::hadShwrPos(const std::vector<std::pair<DetId, float> >& metaContains,
1446  float fracDepth,
1447  double hadE) {
1448  // this is based on available RecHits, can lead to different actual depths if
1449  // hits in multi-depth towers are not all there
1450 #ifdef EDM_ML_DEBUG
1451  std::cout << "hadShwrPos called with " << metaContains.size() << " elements and energy " << hadE << ":" << fracDepth
1452  << std::endl;
1453 #endif
1454  if (hadE <= 0)
1455  return GlobalPoint(0, 0, 0);
1456 
1457  double hadX = 0.0;
1458  double hadY = 0.0;
1459  double hadZ = 0.0;
1460 
1461  int nConst = 0;
1462 
1463  std::vector<std::pair<DetId, float> >::const_iterator mc_it = metaContains.begin();
1464  for (; mc_it != metaContains.end(); ++mc_it) {
1465  if (mc_it->first.det() != DetId::Hcal)
1466  continue;
1467  // do not use HO for deirection calculations for now
1468  if (HcalDetId(mc_it->first).subdet() == HcalOuter)
1469  continue;
1470  ++nConst;
1471 
1472  GlobalPoint p = hadSegmentShwrPos(mc_it->first, fracDepth);
1473 
1474  // longitudinal segmentation: do not weight by energy,
1475  // get the geometrical position
1476  hadX += p.x();
1477  hadY += p.y();
1478  hadZ += p.z();
1479  }
1480 
1481  return GlobalPoint(hadX / nConst, hadY / nConst, hadZ / nConst);
1482 }
1483 
1485  // set depth using geometry of cells that are associated with the
1486  // tower (regardless if they have non-zero energies)
1487 
1488  // if (hadE <= 0) return GlobalPoint(0, 0, 0);
1489 #ifdef EDM_ML_DEBUG
1490  std::cout << "hadShwrPos " << towerId << " frac " << fracDepth << std::endl;
1491 #endif
1492  if (fracDepth < 0)
1493  fracDepth = 0;
1494  else if (fracDepth > 1)
1495  fracDepth = 1;
1496 
1497  GlobalPoint point(0, 0, 0);
1498 
1499  int iEta = towerId.ieta();
1500  int iPhi = towerId.iphi();
1501 
1502  HcalDetId frontCellId, backCellId;
1503 
1504  if (towerId.ietaAbs() >= theTowerTopology->firstHFRing()) {
1505  // forward, take the geometry for long fibers
1506  frontCellId = HcalDetId(HcalForward, towerId.zside() * theTowerTopology->convertCTtoHcal(abs(iEta)), iPhi, 1);
1507  backCellId = HcalDetId(HcalForward, towerId.zside() * theTowerTopology->convertCTtoHcal(abs(iEta)), iPhi, 1);
1508  } else {
1509  //use constituents map
1510  std::vector<DetId> items = theTowerConstituentsMap->constituentsOf(towerId);
1511  int frontDepth = 1000;
1512  int backDepth = -1000;
1513  for (unsigned i = 0; i < items.size(); i++) {
1514  if (items[i].det() != DetId::Hcal)
1515  continue;
1516  HcalDetId hid(items[i]);
1517  if (hid.subdet() == HcalOuter)
1518  continue;
1519  if (!theHcalTopology->validHcal(hid, 2))
1520  continue;
1521 
1522  if (theHcalTopology->idFront(hid).depth() < frontDepth) {
1523  frontCellId = hid;
1524  frontDepth = theHcalTopology->idFront(hid).depth();
1525  }
1526  if (theHcalTopology->idBack(hid).depth() > backDepth) {
1527  backCellId = hid;
1528  backDepth = theHcalTopology->idBack(hid).depth();
1529  }
1530  }
1531 #ifdef EDM_ML_DEBUG
1532  std::cout << "Front " << frontCellId << " Back " << backCellId << " Depths " << frontDepth << ":" << backDepth
1533  << std::endl;
1534 #endif
1535  //fix for tower 28/29 - no tower 29 at highest depths
1536  if (towerId.ietaAbs() == theTowerTopology->lastHERing() && (theHcalPhase == 0 || theHcalPhase == 1)) {
1537  CaloTowerDetId towerId28(towerId.ieta() - towerId.zside(), towerId.iphi());
1538  std::vector<DetId> items28 = theTowerConstituentsMap->constituentsOf(towerId28);
1539 #ifdef EDM_ML_DEBUG
1540  std::cout << towerId28 << " with " << items28.size() << " constituents:";
1541  for (unsigned k = 0; k < items28.size(); ++k)
1542  if (items28[k].det() == DetId::Hcal)
1543  std::cout << " " << HcalDetId(items28[k]);
1544  std::cout << std::endl;
1545 #endif
1546  for (unsigned i = 0; i < items28.size(); i++) {
1547  if (items28[i].det() != DetId::Hcal)
1548  continue;
1549  HcalDetId hid(items28[i]);
1550  if (hid.subdet() == HcalOuter)
1551  continue;
1552 
1553  if (theHcalTopology->idBack(hid).depth() > backDepth) {
1554  backCellId = hid;
1555  backDepth = theHcalTopology->idBack(hid).depth();
1556  }
1557  }
1558  }
1559 #ifdef EDM_ML_DEBUG
1560  std::cout << "Back " << backDepth << " ID " << backCellId << std::endl;
1561 #endif
1562  }
1563  point = hadShwPosFromCells(DetId(frontCellId), DetId(backCellId), fracDepth);
1564 
1565  return point;
1566 }
1567 
1568 GlobalPoint CaloTowersCreationAlgo::hadShwPosFromCells(DetId frontCellId, DetId backCellId, float fracDepth) {
1569  // uses the "front" and "back" cells
1570  // to determine the axis. point set by the predefined depth.
1571 
1572  HcalDetId hid1(frontCellId), hid2(backCellId);
1574  hid1 = theHcalTopology->idFront(frontCellId);
1575 #ifdef EDM_ML_DEBUG
1576  std::cout << "Front " << HcalDetId(frontCellId) << " " << hid1 << "\n";
1577 #endif
1578  hid2 = theHcalTopology->idBack(backCellId);
1579 #ifdef EDM_ML_DEBUG
1580  std::cout << "Back " << HcalDetId(backCellId) << " " << hid2 << "\n";
1581 #endif
1582  }
1583 
1584  auto frontCellGeometry = theGeometry->getGeometry(DetId(hid1));
1585  auto backCellGeometry = theGeometry->getGeometry(DetId(hid2));
1586 
1587  GlobalPoint point = frontCellGeometry->getPosition();
1588  const GlobalPoint& backPoint = backCellGeometry->getBackPoint();
1589 
1590  point += fracDepth * (backPoint - point);
1591 
1592  return point;
1593 }
1594 
1595 GlobalPoint CaloTowersCreationAlgo::emShwrPos(const std::vector<std::pair<DetId, float> >& metaContains,
1596  float fracDepth,
1597  double emE) {
1598  if (emE <= 0)
1599  return GlobalPoint(0, 0, 0);
1600 
1601  double emX = 0.0;
1602  double emY = 0.0;
1603  double emZ = 0.0;
1604 
1605  double eSum = 0;
1606 
1607  std::vector<std::pair<DetId, float> >::const_iterator mc_it = metaContains.begin();
1608  for (; mc_it != metaContains.end(); ++mc_it) {
1609  if (mc_it->first.det() != DetId::Ecal)
1610  continue;
1611  GlobalPoint p = emCrystalShwrPos(mc_it->first, fracDepth);
1612  double e = mc_it->second;
1613 
1614  if (e > 0) {
1615  emX += p.x() * e;
1616  emY += p.y() * e;
1617  emZ += p.z() * e;
1618  eSum += e;
1619  }
1620  }
1621 
1622  return GlobalPoint(emX / eSum, emY / eSum, emZ / eSum);
1623 }
1624 
1625 GlobalPoint CaloTowersCreationAlgo::emShwrLogWeightPos(const std::vector<std::pair<DetId, float> >& metaContains,
1626  float fracDepth,
1627  double emE) {
1628  double emX = 0.0;
1629  double emY = 0.0;
1630  double emZ = 0.0;
1631 
1632  double weight = 0;
1633  double sumWeights = 0;
1634  double sumEmE = 0; // add crystals with E/E_EM > 1.5%
1635  double crystalThresh = 0.015 * emE;
1636 
1637  std::vector<std::pair<DetId, float> >::const_iterator mc_it = metaContains.begin();
1638  for (; mc_it != metaContains.end(); ++mc_it) {
1639  if (mc_it->second < 0)
1640  continue;
1641  if (mc_it->first.det() == DetId::Ecal && mc_it->second > crystalThresh)
1642  sumEmE += mc_it->second;
1643  }
1644 
1645  for (mc_it = metaContains.begin(); mc_it != metaContains.end(); ++mc_it) {
1646  if (mc_it->first.det() != DetId::Ecal || mc_it->second < crystalThresh)
1647  continue;
1648 
1649  GlobalPoint p = emCrystalShwrPos(mc_it->first, fracDepth);
1650 
1651  weight = 4.2 + log(mc_it->second / sumEmE);
1652  sumWeights += weight;
1653 
1654  emX += p.x() * weight;
1655  emY += p.y() * weight;
1656  emZ += p.z() * weight;
1657  }
1658 
1659  return GlobalPoint(emX / sumWeights, emY / sumWeights, emZ / sumWeights);
1660 }
1661 
1663  const float timeUnit = 0.01; // discretization (ns)
1664 
1665  if (time > 300.0)
1666  return 30000;
1667  if (time < -300.0)
1668  return -30000;
1669 
1670  return int(time / timeUnit + 0.5);
1671 }
1672 
1673 //========================================================
1674 //
1675 // Bad/anomolous cell handling
1676 
1678  // This method fills the map of number of dead channels for the calotower,
1679  // The key of the map is CaloTowerDetId.
1680  // By definition these channels are not going to be in the RecHit collections.
1681  hcalDropChMap.clear();
1682  std::vector<DetId> allChanInStatusCont = theHcalChStatus->getAllChannels();
1683 
1684 #ifdef EDM_ML_DEBUG
1685  std::cout << "DropChMap with " << allChanInStatusCont.size() << " channels" << std::endl;
1686 #endif
1687  for (std::vector<DetId>::iterator it = allChanInStatusCont.begin(); it != allChanInStatusCont.end(); ++it) {
1688  const uint32_t dbStatusFlag = theHcalChStatus->getValues(*it)->getValue();
1689  if (theHcalSevLvlComputer->dropChannel(dbStatusFlag)) {
1691 
1693 
1694  hcalDropChMap[twrId].first += 1;
1695 
1696  HcalDetId hid(*it);
1697 
1698  // special case for tower 29: if HCAL hit is in depth 3 add to twr 29 as well
1699  if (hid.subdet() == HcalEndcap && (theHcalPhase == 0 || theHcalPhase == 1) &&
1700  hid.ietaAbs() == theHcalTopology->lastHERing() - 1) {
1701  bool merge = theHcalTopology->mergedDepth29(hid);
1702  if (merge) {
1703  CaloTowerDetId twrId29(twrId.ieta() + twrId.zside(), twrId.iphi());
1704  hcalDropChMap[twrId29].first += 1;
1705  }
1706  }
1707  }
1708  }
1709  // now I know how many bad channels, but I also need to know if there's any good ones
1711  for (auto& pair : hcalDropChMap) {
1712  if (pair.second.first == 0)
1713  continue; // unexpected, but just in case
1714  int ngood = 0, nbad = 0;
1715  for (DetId id : theTowerConstituentsMap->constituentsOf(pair.first)) {
1716  if (id.det() != DetId::Hcal)
1717  continue;
1718  HcalDetId hid(id);
1719  if (hid.subdet() != HcalBarrel && hid.subdet() != HcalEndcap)
1720  continue;
1721  const uint32_t dbStatusFlag = theHcalChStatus->getValues(id)->getValue();
1722  if (dbStatusFlag == 0 || !theHcalSevLvlComputer->dropChannel(dbStatusFlag)) {
1723  ngood += 1;
1724  } else {
1725  nbad += 1; // recount, since pair.second.first may include HO
1726  }
1727  }
1728  if (nbad > 0 && nbad >= ngood) {
1729  //uncomment for debug (may be useful to tune the criteria above)
1730  //CaloTowerDetId id(pair.first);
1731  //std::cout << "CaloTower at ieta = " << id.ieta() << ", iphi " << id.iphi() << ": set Hcal as not efficient (ngood =" << ngood << ", nbad = " << nbad << ")" << std::endl;
1732  pair.second.second = true;
1733  }
1734  }
1735  }
1736 }
1737 
1739  // std::cout << "VI making EcalBadChs ";
1740 
1741  // for ECAL the number of all bad channels is obtained here -----------------------
1742 
1743  for (auto ind = 0U; ind < theTowerTopology->sizeForDenseIndexing(); ++ind) {
1744  auto& numBadEcalChan = ecalBadChs[ind];
1745  numBadEcalChan = 0;
1746  auto id = theTowerTopology->detIdFromDenseIndex(ind);
1747 
1748  // this is utterly slow... (can be optmized if really needed)
1749 
1750  // get all possible constituents of the tower
1751  std::vector<DetId> allConstituents = theTowerConstituentsMap->constituentsOf(id);
1752 
1753  for (std::vector<DetId>::iterator ac_it = allConstituents.begin(); ac_it != allConstituents.end(); ++ac_it) {
1754  if (ac_it->det() != DetId::Ecal)
1755  continue;
1756 
1757  auto thisEcalSevLvl = theEcalSevLvlAlgo->severityLevel(*ac_it);
1758 
1759  // check if the Ecal severity is ok to keep
1760  std::vector<int>::const_iterator sevit =
1762  if (sevit != theEcalSeveritiesToBeExcluded.end()) {
1763  ++numBadEcalChan;
1764  }
1765  }
1766 
1767  // if (0!=numBadEcalChan) std::cout << id << ":" << numBadEcalChan << ", ";
1768  }
1769 
1770  /*
1771  int tot=0;
1772  for (auto ind=0U; ind<theTowerTopology->sizeForDenseIndexing(); ++ind) {
1773  if (ecalBadChs[ind]!=0) ++tot;
1774  }
1775  std::cout << " | " << tot << std::endl;
1776  */
1777 }
1778 
1780 
1782  HcalDetId hid(hit->detid());
1783  DetId id = theHcalTopology->idFront(hid);
1784 #ifdef EDM_ML_DEBUG
1785  std::cout << "ChanStatusForCaloTower for " << hid << " to " << HcalDetId(id) << std::endl;
1786 #endif
1787  const uint32_t recHitFlag = hit->flags();
1788  const uint32_t dbStatusFlag = theHcalChStatus->getValues(id)->getValue();
1789 
1790  int severityLevel = theHcalSevLvlComputer->getSeverityLevel(id, recHitFlag, dbStatusFlag);
1791  bool isRecovered = theHcalSevLvlComputer->recoveredRecHit(id, recHitFlag);
1792 
1793  // For use with hits rejected in the default reconstruction
1794  if (useRejectedHitsOnly) {
1795  if (!isRecovered) {
1799  // this hit was either already accepted or is worse than
1800  } else {
1802  // skip recovered hits either because they were already used or because there was an explicit instruction
1804  } else if (useRejectedRecoveredHcalHits) {
1806  }
1807 
1808  } // recovered channels
1809 
1810  // clasify channels as problematic: no good hits are supposed to be present in the
1811  // extra rechit collections
1813 
1814  } // treatment of rejected hits
1815 
1816  // this is for the regular reconstruction sequence
1817 
1818  if (severityLevel == 0)
1820 
1821  if (isRecovered) {
1823  } else {
1826  } else {
1828  }
1829  }
1830 }
1831 
1833  // const DetId id = hit->detid();
1834 
1835  // uint16_t dbStatus = theEcalChStatus->find(id)->getStatusCode();
1836  // uint32_t rhFlags = hit->flags();
1837  // int severityLevel = theEcalSevLvlAlgo->severityLevel(rhFlags, dbStatus);
1838  // The methods above will become private and cannot be usef for flagging ecal spikes.
1839  // Use the recommended interface - we leave the parameters for spilke removal to be specified by ECAL.
1840 
1841  // int severityLevel = 999;
1842 
1843  EcalRecHit const& rh = *reinterpret_cast<EcalRecHit const*>(hit);
1845 
1846  // if (id.subdetId() == EcalBarrel) severityLevel = theEcalSevLvlAlgo->severityLevel( id, *theEbHandle);//, *theEcalChStatus);
1847  // else if (id.subdetId() == EcalEndcap) severityLevel = theEcalSevLvlAlgo->severityLevel( id, *theEeHandle);//, *theEcalChStatus);
1848 
1849  // there should be no other ECAL types used in this reconstruction
1850 
1851  // The definition of ECAL severity levels uses categories that
1852  // are similar to the defined for CaloTower. (However, the categorization
1853  // for CaloTowers depends on the specified maximum acceptabel severity and therefore cannnot
1854  // be exact correspondence between the two. ECAL has additional categories describing modes of failure.)
1855  // This approach is different from the initial idea and from
1856  // the implementation for HCAL. Still make the logic similar to HCAL so that one has the ability to
1857  // exclude problematic channels as defined by ECAL.
1858  // For definitions of ECAL severity levels see RecoLocalCalo/EcalRecAlgos/interface/EcalSeverityLevelAlgo.h
1859 
1860  bool isBad = (severityLevel == EcalSeverityLevel::kBad);
1861 
1862  bool isRecovered = (severityLevel == EcalSeverityLevel::kRecovered);
1863 
1864  // check if the severity is compatible with our configuration
1865  // This applies to the "default" tower cleaning
1866  std::vector<int>::const_iterator sevit =
1868  bool accepted = (sevit == theEcalSeveritiesToBeExcluded.end());
1869 
1870  // For use with hits that were rejected in the regular reconstruction:
1871  // This is for creating calotowers with lower level of cleaning by merging
1872  // the information from the default towers and a collection of towers created from
1873  // bad rechits
1874 
1875  if (useRejectedHitsOnly) {
1876  if (!isRecovered) {
1877  if (accepted || std::find(theEcalSeveritiesToBeUsedInBadTowers.begin(),
1880  return std::make_tuple(CaloTowersCreationAlgo::IgnoredChan, isBad);
1881  // this hit was either already accepted, or is not eligible for inclusion
1882  } else {
1884  // skip recovered hits either because they were already used or because there was an explicit instruction
1885  return std::make_tuple(CaloTowersCreationAlgo::IgnoredChan, isBad);
1886  ;
1887  } else if (useRejectedRecoveredEcalHits) {
1888  return std::make_tuple(CaloTowersCreationAlgo::RecoveredChan, isBad);
1889  }
1890 
1891  } // recovered channels
1892 
1893  // clasify channels as problematic
1894  return std::make_tuple(CaloTowersCreationAlgo::ProblematicChan, isBad);
1895 
1896  } // treatment of rejected hits
1897 
1898  // for normal reconstruction
1900  return std::make_tuple(CaloTowersCreationAlgo::GoodChan, false);
1901 
1902  if (isRecovered) {
1903  return std::make_tuple(
1905  } else {
1906  return std::make_tuple(accepted ? CaloTowersCreationAlgo::ProblematicChan : CaloTowersCreationAlgo::BadChan, isBad);
1907  }
1908 }
std::vector< double > theHBGrid
bool mergedDepth29(HcalDetId id) const
Definition: HcalTopology.h:111
Definition: merge.py:1
bool getMergePositionFlag() const
Definition: HcalTopology.h:167
const HcalChannelQuality * theHcalChStatus
uint32_t sizeForDenseIndexing() const
std::vector< std::pair< DetId, float > > metaConstituents
bool contains(EventRange const &lh, EventID const &rh)
Definition: EventRange.cc:37
int ietaAbs() const
get the absolute value of the tower ieta
int merge(int argc, char *argv[])
Definition: DiMuonVmerge.cc:28
void getThresholdAndWeight(const DetId &detId, double &threshold, double &weight) const
helper method to look up the appropriate threshold & weight
constexpr int ietaAbs() const
get the absolute value of the cell ieta
Definition: HcalDetId.h:148
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
void setCaloTowerStatus(unsigned int numBadHcalChan, unsigned int numBadEcalChan, unsigned int numRecHcalChan, unsigned int numRecEcalChan, unsigned int numProbHcalChan, unsigned int numProbEcalChan)
Definition: CaloTower.cc:221
bool recoveredRecHit(const DetId &myid, const uint32_t &myflag) const
CaloTowerDetId towerOf(const DetId &id) const
Get the tower id for this det id (or null if not known)
std::vector< double > theHESGrid
std::vector< double > theHEDGrid
GlobalPoint emCrystalShwrPos(DetId detId, float fracDepth)
void assignHitHcal(const CaloRecHit *recHit)
std::vector< int > theEcalSeveritiesToBeUsedInBadTowers
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: LeafCandidate.h:25
T eta() const
Definition: PV3DBase.h:73
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
std::vector< T >::const_iterator const_iterator
void push_back(T const &t)
Definition: weight.py:1
void finish(CaloTowerCollection &destCollection)
std::vector< double > theHOWeights
MetaTower & find(const CaloTowerDetId &id)
looks for a given tower in the internal cache. If it can&#39;t find it, it makes it.
Log< level::Error, false > LogError
std::vector< double > theEEGrid
void rescale(const CaloTower *ct)
int lastHFRing() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
assert(be >=bs)
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:46
void setHcalSubdet(int lastHB, int lastHE, int lastHF, int lastHO)
Definition: CaloTower.h:85
const Item * getValues(DetId fId, bool throwOnFail=true) const
const EcalPFRecHitThresholds * ecalCuts
EcalSeverityLevel::SeverityLevel severityLevel(const DetId &id) const
Evaluate status from id use channelStatus from DB.
std::vector< double > theEEWeights
int lastHERing() const
int lastHORing() const
std::vector< double > theHESWeights
U second(std::pair< T, U > const &p)
void setGeometry(const CaloTowerTopology *cttopo, const CaloTowerConstituentsMap *ctmap, const HcalTopology *htopo, const CaloGeometry *geo)
ALPAKA_FN_ACC ALPAKA_FN_INLINE uint32_t ietaAbs(uint32_t id)
constexpr bool null() const
is this a null id ?
Definition: DetId.h:59
constexpr HcalSubdetector subdet() const
get the subdetector
Definition: HcalDetId.h:138
const CaloSubdetectorGeometry * theTowerGeometry
void addConstituents(const std::vector< DetId > &ids)
Definition: CaloTower.cc:199
unsigned int hcalChanStatusForCaloTower(const CaloRecHit *hit)
CaloTowerDetId detIdFromDenseIndex(uint32_t din) const
int firstHERing() const
std::vector< double > theHF2Grid
HcalDetId idFront(const HcalDetId &id) const
Definition: HcalTopology.h:170
std::vector< double > theHEDWeights
unsigned towerId(DetId const &, EcalElectronicsMapping const *)
void rescaleTowers(const CaloTowerCollection &ctInput, CaloTowerCollection &ctResult)
static const int SubdetId
constexpr int ieta() const
get the cell ieta
Definition: HcalDetId.h:155
T sqrt(T t)
Definition: SSEVec.h:23
const CaloGeometry * theGeometry
int convertCTtoHcal(int ct_ieta) const
HcalDetId idBack(const HcalDetId &id) const
Definition: HcalTopology.h:171
HcalSubdetector
Definition: HcalAssistant.h:31
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::shared_ptr< const CaloCellGeometry > getGeometry(const DetId &id) const
Get the cell geometry of a given detector id.
Definition: CaloGeometry.cc:60
std::vector< double > theHOGrid
void assignHitEcal(const EcalRecHit *recHit)
adds a single hit to the tower
std::vector< DetId > getAllChannels() const
const CaloTowerConstituentsMap * theTowerConstituentsMap
void convert(const CaloTowerDetId &id, const MetaTower &mt, CaloTowerCollection &collection)
const CaloTowerTopology * theTowerTopology
std::vector< double > theHF1Weights
const_iterator begin() const
GlobalPoint hadSegmentShwrPos(DetId detId, float fracDepth)
MathVector const & mathVector() const
const BasicVectorType & basicVector() const
Definition: PV3DBase.h:53
uint32_t getValue() const
bool theHOIsUsed
only affects energy and ET calculation. HO is still recorded in the tower
virtual std::shared_ptr< const CaloCellGeometry > getGeometry(const DetId &id) const
Get the cell geometry of a given detector id. Should return false if not found.
void process(const HBHERecHitCollection &hbhe)
const_iterator end() const
std::vector< double > theHBWeights
const HcalSeverityLevelComputer * theHcalSevLvlComputer
Definition: DetId.h:17
GlobalPoint hadShwrPos(const std::vector< std::pair< DetId, float >> &metaContains, float fracDepth, double hadE)
int iphi() const
get the tower iphi
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
Detector
Definition: DetId.h:24
int firstHEDoublePhiRing() const
Definition: HcalTopology.h:101
GlobalPoint hadShwPosFromCells(DetId frontCell, DetId backCell, float fracDepth)
int ieta() const
get the tower ieta
const HcalTopology * theHcalTopology
bool validHcal(const HcalDetId &id) const
std::vector< int > theEcalSeveritiesToBeExcluded
std::vector< unsigned short > ecalBadChs
void setEcalTime(int t)
Definition: CaloTower.h:83
HcalDetId mergedDepthDetId(const HcalDetId &id) const
Definition: HcalTopology.h:166
void setThresFromDB(const EcalPFRecHitThresholds *EcalCuts, const HcalPFCuts *HcalCuts)
GlobalPoint emShwrPos(const std::vector< std::pair< DetId, float >> &metaContains, float fracDepth, double totEmE)
const EcalSeverityLevelAlgo * theEcalSevLvlAlgo
int zside() const
get the z-side of the tower (1/-1)
int lastHERing() const
Definition: HcalTopology.h:94
int getSeverityLevel(const DetId &myid, const uint32_t &myflag, const uint32_t &mystatus) const
int firstHFRing() const
std::vector< double > theHF1Grid
uint32_t denseIndex(const DetId &id) const
std::vector< double > theEBGrid
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
Basic3DVector unit() const
std::vector< double > theHF2Weights
#define UNLIKELY(x)
Definition: Likely.h:21
unsigned int theHcalAcceptSeverityLevelForRejectedHit
std::tuple< unsigned int, bool > ecalChanStatusForCaloTower(const EcalRecHit *hit)
void setHcalTime(int t)
Definition: CaloTower.h:84
EcalSubdetector
std::vector< double > theEBWeights
if(threadIdxLocalY==0 &&threadIdxLocalX==0)
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:34
std::vector< DetId > constituentsOf(const CaloTowerDetId &id) const
Get the constituent detids for this tower id ( not yet implemented )
def move(src, dest)
Definition: eostools.py:511
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
Global3DVector GlobalVector
Definition: GlobalVector.h:10
GlobalPoint emShwrLogWeightPos(const std::vector< std::pair< DetId, float >> &metaContains, float fracDepth, double totEmE)
int lastHBRing() const
bool dropChannel(const uint32_t &mystatus) const
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: Candidate.h:38
constexpr int depth() const
get the tower depth
Definition: HcalDetId.h:164