CMS 3D CMS Logo

JetIDHelper.cc
Go to the documentation of this file.
2 
4 
11 
12 
15 // JetIDHelper needs a much more detailed description that the one in HcalTopology,
16 // so to be consistent, all needed constants are hardwired in JetIDHelper.cc itself
19 
20 #include "TMath.h"
21 #include <vector>
22 #include <numeric>
23 #include <iostream>
24 
25 using namespace std;
26 
27 // defining stuff useful only for this class (not needed in header)
28 namespace reco {
29 
30  namespace helper {
31 
32  // select2nd exists only in some std and boost implementations, so let's control our own fate
33  // and it can't be a non-static member function.
34  static double select2nd (std::map<int,double>::value_type const &pair) {return pair.second;}
35 
37  return x.E <= 0;
38  }
39 
41  reco::helper::JetIDHelper::subtower j ) { return i.E > j.E; }
42  std::atomic<int> JetIDHelper::sanity_checks_left_{100};
43  }
44 }
45 
47 {
48  useRecHits_ = pset.getParameter<bool>("useRecHits");
49  if( useRecHits_ ) {
50  hbheRecHitsColl_ = pset.getParameter<edm::InputTag>("hbheRecHitsColl");
51  hoRecHitsColl_ = pset.getParameter<edm::InputTag>("hoRecHitsColl");
52  hfRecHitsColl_ = pset.getParameter<edm::InputTag>("hfRecHitsColl");
53  ebRecHitsColl_ = pset.getParameter<edm::InputTag>("ebRecHitsColl");
54  eeRecHitsColl_ = pset.getParameter<edm::InputTag>("eeRecHitsColl");
55  }
56  initValues();
57 
58  input_HBHERecHits_token_ = iC.consumes<HBHERecHitCollection>(hbheRecHitsColl_);
59  input_HORecHits_token_ = iC.consumes<HORecHitCollection>(hoRecHitsColl_);
60  input_HFRecHits_token_ = iC.consumes<HFRecHitCollection>(hfRecHitsColl_);
61  input_EBRecHits_token_ = iC.consumes<EBRecHitCollection>(ebRecHitsColl_);
62  input_EERecHits_token_ = iC.consumes<EERecHitCollection>(eeRecHitsColl_);
63 
64 
65 }
66 
68 {
69  fHPD_= -1.0;
70  fRBX_= -1.0;
71  n90Hits_ = -1;
72  fSubDetector1_= -1.0;
73  fSubDetector2_= -1.0;
74  fSubDetector3_= -1.0;
75  fSubDetector4_= -1.0;
76  restrictedEMF_= -1.0;
77  nHCALTowers_ = -1;
78  nECALTowers_ = -1;
79  approximatefHPD_ = -1.0;
80  approximatefRBX_ = -1.0;
81  hitsInN90_ = -1;
82  fEB_ = fEE_ = fHB_ = fHE_ = fHO_ = fLong_ = fShort_ = -1.0;
83  fLS_ = fHFOOT_ = -1.0;
84 }
85 
87 {
88  iDesc.ifValue( edm::ParameterDescription<bool>("useRecHits", true, true),
89  true >> (edm::ParameterDescription<edm::InputTag>("hbheRecHitsColl", edm::InputTag(), true) and
90  edm::ParameterDescription<edm::InputTag>("hoRecHitsColl", edm::InputTag(), true) and
91  edm::ParameterDescription<edm::InputTag>("hfRecHitsColl", edm::InputTag(), true) and
92  edm::ParameterDescription<edm::InputTag>("ebRecHitsColl", edm::InputTag(), true) and
94  )
95  )->setComment("If using RecHits to calculate the precise jet ID variables that need them, "
96  "their sources need to be specified");
97 }
98 
99 
101 {
102  initValues();
103 
104  // --------------------------------------------------
105  // 1) jet ID variable derived from existing fractions
106  // --------------------------------------------------
107 
108  double E_EM = TMath::Max( float(0.), jet.emEnergyInHF() )
109  + TMath::Max( float(0.), jet.emEnergyInEB() )
110  + TMath::Max( float(0.), jet.emEnergyInEE() );
111  double E_Had = TMath::Max( float(0.), jet.hadEnergyInHB() )
112  + TMath::Max( float(0.), jet.hadEnergyInHE() )
113  + TMath::Max( float(0.), jet.hadEnergyInHO() )
114  + TMath::Max( float(0.), jet.hadEnergyInHF() );
115  if( E_Had + E_EM > 0 ) restrictedEMF_ = E_EM / ( E_EM + E_Had );
116  if( iDbg > 1 ) cout<<"jet pT: "<<jet.pt()<<", eT: "<<jet.et()<<", E: "
117  <<jet.energy()<<" rEMF: "<<restrictedEMF_<<endl;
118 
119  // ------------------------
120  // 2) tower based variables
121  // ------------------------
122  vector<subtower> subtowers, Ecal_subtowers, Hcal_subtowers, HO_subtowers;
123  vector<double> HPD_energies, RBX_energies;
124 
125  classifyJetTowers( event, jet,
126  subtowers, Ecal_subtowers, Hcal_subtowers, HO_subtowers,
127  HPD_energies, RBX_energies, iDbg );
128  if( iDbg > 1 ) {
129  cout<<"E:";
130  for (unsigned int i=0; i<subtowers.size(); ++i) cout<<" "<<subtowers[i].E<<","<<subtowers[i].Nhit;
131  cout<<"\nECal_E:";
132  for (unsigned int i=0; i<Ecal_subtowers.size(); ++i) cout<<" "<<Ecal_subtowers[i].E<<","<<Ecal_subtowers[i].Nhit;
133  cout<<"\nHCal_E:";
134  for (unsigned int i=0; i<Hcal_subtowers.size(); ++i) cout<<" "<<Hcal_subtowers[i].E<<","<<Hcal_subtowers[i].Nhit;
135  cout<<"\nHO_E:";
136  for (unsigned int i=0; i<HO_subtowers.size(); ++i) cout<<" "<<HO_subtowers[i].E<<","<<HO_subtowers[i].Nhit;
137  cout<<"\nHPD_E:";
138  for (unsigned int i=0; i<HPD_energies.size(); ++i) cout<<" "<<HPD_energies[i];
139  cout<<"\nRBX_E:";
140  for (unsigned int i=0; i<RBX_energies.size(); ++i) cout<<" "<<RBX_energies[i];
141  cout<<endl;
142  }
143 
144  // counts
145  hitsInN90_ = hitsInNCarrying( 0.9, subtowers );
146  nHCALTowers_ = Hcal_subtowers.size();
147  vector<subtower>::const_iterator it;
148  it = find_if( Ecal_subtowers.begin(), Ecal_subtowers.end(), hasNonPositiveE );
149  nECALTowers_ = it - Ecal_subtowers.begin(); // ignores negative energies from HF!
150 
151  // energy fractions
152  double max_HPD_energy = 0., max_RBX_energy = 0.;
153  std::vector<double>::const_iterator it_max_HPD_energy = std::max_element( HPD_energies.begin(), HPD_energies.end() );
154  std::vector<double>::const_iterator it_max_RBX_energy = std::max_element( RBX_energies.begin(), RBX_energies.end() );
155  if ( it_max_HPD_energy != HPD_energies.end() ) {
156  max_HPD_energy = *it_max_HPD_energy;
157  }
158  if ( it_max_RBX_energy != RBX_energies.end() ) {
159  max_RBX_energy = *it_max_RBX_energy;
160  }
161  if( jet.energy() > 0 ) {
162  if( !HPD_energies.empty() ) approximatefHPD_ = max_HPD_energy / jet.energy();
163  if( !RBX_energies.empty() ) approximatefRBX_ = max_HPD_energy / jet.energy();
164  }
165 
166  // -----------------------
167  // 3) cell based variables
168  // -----------------------
169  if( useRecHits_ ) {
170  vector<double> energies, subdet_energies, Ecal_energies, Hcal_energies, HO_energies;
171  double LS_bad_energy, HF_OOT_energy;
172  classifyJetComponents( event, setup, jet,
173  energies, subdet_energies, Ecal_energies, Hcal_energies, HO_energies,
174  HPD_energies, RBX_energies, LS_bad_energy, HF_OOT_energy, iDbg );
175 
176  // counts
177  n90Hits_ = nCarrying( 0.9, energies );
178 
179  // energy fractions
180  if( jet.energy() > 0 ) {
181  if( !HPD_energies.empty() ) fHPD_ = max_HPD_energy / jet.energy();
182  if( !RBX_energies.empty() ) fRBX_ = max_RBX_energy / jet.energy();
183  if( !subdet_energies.empty() ) fSubDetector1_ = subdet_energies.at( 0 ) / jet.energy();
184  if( subdet_energies.size() > 1 ) fSubDetector2_ = subdet_energies.at( 1 ) / jet.energy();
185  if( subdet_energies.size() > 2 ) fSubDetector3_ = subdet_energies.at( 2 ) / jet.energy();
186  if( subdet_energies.size() > 3 ) fSubDetector4_ = subdet_energies.at( 3 ) / jet.energy();
187  fLS_ = LS_bad_energy / jet.energy();
188  fHFOOT_ = HF_OOT_energy / jet.energy();
189 
190  if( iDbg > 0 && sanity_checks_left_.load(std::memory_order_acquire) > 0 ) {
191  --sanity_checks_left_;
192  double EH_sum = accumulate( Ecal_energies.begin(), Ecal_energies.end(), 0. );
193  EH_sum = accumulate( Hcal_energies.begin(), Hcal_energies.end(), EH_sum );
194  double EHO_sum = accumulate( HO_energies.begin(), HO_energies.end(), EH_sum );
195  if( jet.energy() > 0.001 && abs( EH_sum/jet.energy() - 1 ) > 0.01 && abs( EHO_sum/jet.energy() - 1 ) > 0.01 )
196  edm::LogWarning("BadInput")<<"Jet energy ("<<jet.energy()
197  <<") does not match the total energy in the recHits ("<<EHO_sum
198  <<", or without HO: "<<EH_sum<<") . Are these the right recHits? "
199  <<"Were jet energy corrections mistakenly applied before jet ID? A bug?";
200  if( iDbg > 1 ) cout<<"Sanity check - E: "<<jet.energy()<<" =? EH_sum: "<<EH_sum<<" / EHO_sum: "<<EHO_sum<<endl;
201  }
202  }
203 
204  if( iDbg > 1 ) {
205  cout<<"DBG - fHPD: "<<fHPD_<<", fRBX: "<<fRBX_<<", nh90: "<<n90Hits_<<", fLS: "<<fLS_<<", fHFOOT: "<<fHFOOT_<<endl;
206  cout<<" -~fHPD: "<<approximatefHPD_<<", ~fRBX: "<<approximatefRBX_
207  <<", hits in n90: "<<hitsInN90_<<endl;
208  cout<<" - nHCALTowers: "<<nHCALTowers_<<", nECALTowers: "<<nECALTowers_
209  <<"; subdet fractions: "<<fSubDetector1_<<", "<<fSubDetector2_<<", "<<fSubDetector3_<<", "<<fSubDetector4_<<endl;
210  }
211  }
212 }
213 
214 
215 unsigned int reco::helper::JetIDHelper::nCarrying( double fraction, const std::vector< double >& descending_energies )
216 {
217  double totalE = 0;
218  for( unsigned int i = 0; i < descending_energies.size(); ++i ) totalE += descending_energies[ i ];
219 
220  double runningE = 0;
221  unsigned int NC = descending_energies.size();
222 
223  // slightly odd loop structure avoids round-off problems when runningE never catches up with totalE
224  for( unsigned int i = descending_energies.size(); i > 0; --i ) {
225  runningE += descending_energies[ i-1 ];
226  if (runningE < ( 1-fraction ) * totalE) NC = i-1;
227  }
228  return NC;
229 }
230 
231 
232 unsigned int reco::helper::JetIDHelper::hitsInNCarrying( double fraction, const std::vector< subtower >& descending_towers )
233 {
234  double totalE = 0;
235  for( unsigned int i = 0; i < descending_towers.size(); ++i ) totalE += descending_towers[ i ].E;
236 
237  double runningE = 0;
238  unsigned int NH = 0;
239 
240  // slightly odd loop structure avoids round-off problems when runningE never catches up with totalE
241  for( unsigned int i = descending_towers.size(); i > 0; --i ) {
242  runningE += descending_towers[ i-1 ].E;
243  if (runningE >= ( 1-fraction ) * totalE) NH += descending_towers[ i-1 ].Nhit;
244  }
245  return NH;
246 }
247 
249  const reco::CaloJet &jet,
250  vector< double > &energies,
251  vector< double > &subdet_energies,
252  vector< double > &Ecal_energies,
253  vector< double > &Hcal_energies,
254  vector< double > &HO_energies,
255  vector< double > &HPD_energies,
256  vector< double > &RBX_energies,
257  double& LS_bad_energy, double& HF_OOT_energy, const int iDbg )
258 {
259  energies.clear(); subdet_energies.clear(); Ecal_energies.clear(); Hcal_energies.clear(); HO_energies.clear();
260  HPD_energies.clear(); RBX_energies.clear();
261  LS_bad_energy = HF_OOT_energy = 0.;
262 
263  edm::ESHandle<HcalTopology> theHcalTopology;
264  setup.get<HcalRecNumberingRecord>().get( theHcalTopology );
265 
266  std::map< int, double > HPD_energy_map, RBX_energy_map;
267  vector< double > EB_energies, EE_energies, HB_energies, HE_energies, short_energies, long_energies;
273  // the jet only contains DetIds, so first read recHit collection
274  event.getByToken(input_HBHERecHits_token_, HBHERecHits );
275  event.getByToken(input_HORecHits_token_, HORecHits );
276  event.getByToken(input_HFRecHits_token_, HFRecHits );
277  event.getByToken(input_EBRecHits_token_, EBRecHits );
278  event.getByToken(input_EERecHits_token_, EERecHits );
279  if( iDbg > 2 ) cout<<"# of rechits found - HBHE: "<<HBHERecHits->size()
280  <<", HO: "<<HORecHits->size()<<", HF: "<<HFRecHits->size()
281  <<", EB: "<<EBRecHits->size()<<", EE: "<<EERecHits->size()<<endl;
282 
283  vector< CaloTowerPtr > towers = jet.getCaloConstituents ();
284  int nTowers = towers.size();
285  if( iDbg > 9 ) cout<<"In classifyJetComponents. # of towers found: "<<nTowers<<endl;
286 
287  for( int iTower = 0; iTower <nTowers ; iTower++ ) {
288 
289  CaloTowerPtr& tower = towers[iTower];
290 
291  int nCells = tower->constituentsSize();
292  if( iDbg ) cout<<"tower #"<<iTower<<" has "<<nCells<<" cells. "
293  <<"It's at iEta: "<<tower->ieta()<<", iPhi: "<<tower->iphi()<<endl;
294 
295  const vector< DetId >& cellIDs = tower->constituents(); // cell == recHit
296 
297  for( int iCell = 0; iCell < nCells; ++iCell ) {
298  DetId::Detector detNum = cellIDs[iCell].det();
299  if( detNum == DetId::Hcal ) {
300  HcalDetId HcalID = cellIDs[ iCell ];
301  HcalSubdetector HcalNum = HcalID.subdet();
302  double hitE = 0;
303  if( HcalNum == HcalOuter ) {
304  HORecHitCollection::const_iterator theRecHit=HORecHits->find(HcalID);
305  if (theRecHit == HORecHits->end()) {
306  edm::LogWarning("UnexpectedEventContents")<<"Can't find the HO recHit with ID: "<<HcalID;
307  continue;
308  }
309  hitE = theRecHit->energy();
310  HO_energies.push_back( hitE );
311 
312  } else if( HcalNum == HcalForward ) {
313 
314  HFRecHitCollection::const_iterator theRecHit=HFRecHits->find( HcalID );
315  if( theRecHit == HFRecHits->end() ) {
316  edm::LogWarning("UnexpectedEventContents")<<"Can't find the HF recHit with ID: "<<HcalID;
317  continue;
318  }
319  hitE = theRecHit->energy();
320  if( iDbg>4 ) cout
321  << "hit #"<<iCell<<" is HF , E: "<<hitE<<" iEta: "<<theRecHit->id().ieta()
322  <<", depth: "<<theRecHit->id().depth()<<", iPhi: "
323  <<theRecHit->id().iphi();
324 
325  if( HcalID.depth() == 1 )
326  long_energies.push_back( hitE );
327  else
328  short_energies.push_back( hitE );
329 
330  uint32_t flags = theRecHit->flags();
331  if( flags & (1<<HcalCaloFlagLabels::HFLongShort) ) LS_bad_energy += hitE;
332  if( flags & ( (1<<HcalCaloFlagLabels::HFDigiTime) |
336  (1<<HcalCaloFlagLabels::TimingErrorBit) ) ) HF_OOT_energy += hitE;
337  if( iDbg>4 && flags ) cout<<"flags: "<<flags
338  <<" -> LS_bad_energy: "<<LS_bad_energy<<", HF_OOT_energy: "<<HF_OOT_energy<<endl;
339 
340  } else { // HBHE
341 
342  HBHERecHitCollection::const_iterator theRecHit = HBHERecHits->find( HcalID );
343  if( theRecHit == HBHERecHits->end() ) {
344  edm::LogWarning("UnexpectedEventContents")<<"Can't find the HBHE recHit with ID: "<<HcalID;
345  continue;
346  }
347  hitE = theRecHit->energy();
348  int iEta = theRecHit->id().ieta();
349  int depth = theRecHit->id().depth();
350  Region region = HBHE_region( theRecHit->id().rawId() );
351  int hitIPhi = theRecHit->id().iphi();
352  if( iDbg>3 ) cout<<"hit #"<<iCell<<" is HBHE, E: "<<hitE<<" iEta: "<<iEta
353  <<", depth: "<<depth<<", iPhi: "<<theRecHit->id().iphi()
354  <<" -> "<<region;
355 
356  if(theHcalTopology->mergedDepth29(theRecHit->id()))
357  hitE /= 2; // Depth 3 at the HE forward edge is split over tower 28 & 29, and jet reco. assigns half each
358 
359  int iHPD = 100 * region;
360  int iRBX = 100 * region + ((hitIPhi + 1) % 72) / 4; // 71,72,1,2 are in the same RBX module
361 
362  if( std::abs( iEta ) >= 21 ) {
363  if( (0x1 & hitIPhi) == 0 ) {
364  edm::LogError("CodeAssumptionsViolated")<<"Bug?! Jet ID code assumes no even iPhi recHits at HE edges";
365  return;
366  }
367  bool oddnessIEta = HBHE_oddness( iEta, depth );
368  bool upperIPhi = (( hitIPhi%4 ) == 1 || ( hitIPhi%4 ) == 2); // the upper iPhi indices in the HE wedge
369  // remap the iPhi so it fits the one in the inner HE regions, change in needed in two cases:
370  // 1) in the upper iPhis of the module, the even iEtas belong to the higher iPhi
371  // 2) in the loewr iPhis of the module, the odd iEtas belong to the higher iPhi
372  if( upperIPhi != oddnessIEta ) ++hitIPhi;
373  // note that hitIPhi could not be 72 before, so it's still in the legal range [1,72]
374  }
375  iHPD += hitIPhi;
376 
377  // book the energies
378  HPD_energy_map[ iHPD ] += hitE;
379  RBX_energy_map[ iRBX ] += hitE;
380  if( iDbg > 5 ) cout<<" --> H["<<iHPD<<"]="<<HPD_energy_map[iHPD]
381  <<", R["<<iRBX<<"]="<<RBX_energy_map[iRBX];
382  if( iDbg > 1 ) cout<<endl;
383 
384  if( region == HBneg || region == HBpos )
385  HB_energies.push_back( hitE );
386  else
387  HE_energies.push_back( hitE );
388 
389  } // if HBHE
390  if( hitE == 0 ) edm::LogWarning("UnexpectedEventContents")<<"HCal hitE==0? (or unknown subdetector?)";
391 
392  } // if HCAL
393 
394  else if (detNum == DetId::Ecal) {
395 
396  int EcalNum = cellIDs[iCell].subdetId();
397  double hitE = 0;
398  if( EcalNum == 1 ){
399  EBDetId EcalID = cellIDs[iCell];
400  EBRecHitCollection::const_iterator theRecHit=EBRecHits->find(EcalID);
401  if( theRecHit == EBRecHits->end() ) {edm::LogWarning("UnexpectedEventContents")
402  <<"Can't find the EB recHit with ID: "<<EcalID; continue;}
403  hitE = theRecHit->energy();
404  EB_energies.push_back( hitE );
405  } else if( EcalNum == 2 ){
406  EEDetId EcalID = cellIDs[iCell];
407  EERecHitCollection::const_iterator theRecHit=EERecHits->find(EcalID);
408  if( theRecHit == EERecHits->end() ) {edm::LogWarning("UnexpectedEventContents")
409  <<"Can't find the EE recHit with ID: "<<EcalID; continue;}
410  hitE = theRecHit->energy();
411  EE_energies.push_back( hitE );
412  }
413  if( hitE == 0 ) edm::LogWarning("UnexpectedEventContents")<<"ECal hitE==0? (or unknown subdetector?)";
414  if( iDbg > 6 ) cout<<"EcalNum: "<<EcalNum<<" hitE: "<<hitE<<endl;
415  } //
416  } // loop on cells
417  } // loop on towers
418 
419  /* Disabling check until HO is accounted for in EMF. Check was used in CMSSW_2, where HE was excluded.
420  double expHcalE = jet.energy() * (1-jet.emEnergyFraction());
421  if( totHcalE + expHcalE > 0 &&
422  TMath::Abs( totHcalE - expHcalE ) > 0.01 &&
423  ( totHcalE - expHcalE ) / ( totHcalE + expHcalE ) > 0.0001 ) {
424  edm::LogWarning("CodeAssumptionsViolated")<<"failed to account for all Hcal energies"
425  <<totHcalE<<"!="<<expHcalE;
426  } */
427  // concatenate Hcal and Ecal lists
428  Hcal_energies.insert( Hcal_energies.end(), HB_energies.begin(), HB_energies.end() );
429  Hcal_energies.insert( Hcal_energies.end(), HE_energies.begin(), HE_energies.end() );
430  Hcal_energies.insert( Hcal_energies.end(), short_energies.begin(), short_energies.end() );
431  Hcal_energies.insert( Hcal_energies.end(), long_energies.begin(), long_energies.end() );
432  Ecal_energies.insert( Ecal_energies.end(), EB_energies.begin(), EB_energies.end() );
433  Ecal_energies.insert( Ecal_energies.end(), EE_energies.begin(), EE_energies.end() );
434 
435  // sort the energies
436  // std::sort( Hcal_energies.begin(), Hcal_energies.end(), greater<double>() );
437  // std::sort( Ecal_energies.begin(), Ecal_energies.end(), greater<double>() );
438 
439  // put the energy sums (the 2nd entry in each pair of the maps) into the output vectors and sort them
440  std::transform( HPD_energy_map.begin(), HPD_energy_map.end(),
441  std::inserter (HPD_energies, HPD_energies.end()), select2nd );
442  // std::select2nd<std::map<int,double>::value_type>());
443  // std::sort( HPD_energies.begin(), HPD_energies.end(), greater<double>() );
444  std::transform( RBX_energy_map.begin(), RBX_energy_map.end(),
445  std::inserter (RBX_energies, RBX_energies.end()), select2nd );
446  // std::select2nd<std::map<int,double>::value_type>());
447  // std::sort( RBX_energies.begin(), RBX_energies.end(), greater<double>() );
448 
449  energies.insert( energies.end(), Hcal_energies.begin(), Hcal_energies.end() );
450  energies.insert( energies.end(), Ecal_energies.begin(), Ecal_energies.end() );
451  energies.insert( energies.end(), HO_energies.begin(), HO_energies.end() );
452  std::sort( energies.begin(), energies.end(), greater<double>() );
453 
454  // prepare sub detector energies, then turn them into fractions
455  fEB_ = std::accumulate( EB_energies.begin(), EB_energies.end(), 0. );
456  fEE_ = std::accumulate( EE_energies.begin(), EE_energies.end(), 0. );
457  fHB_ = std::accumulate( HB_energies.begin(), HB_energies.end(), 0. );
458  fHE_ = std::accumulate( HE_energies.begin(), HE_energies.end(), 0. );
459  fHO_ = std::accumulate( HO_energies.begin(), HO_energies.end(), 0. );
460  fShort_ = std::accumulate( short_energies.begin(), short_energies.end(), 0. );
461  fLong_ = std::accumulate( long_energies.begin(), long_energies.end(), 0. );
462  subdet_energies.push_back( fEB_ );
463  subdet_energies.push_back( fEE_ );
464  subdet_energies.push_back( fHB_ );
465  subdet_energies.push_back( fHE_ );
466  subdet_energies.push_back( fHO_ );
467  subdet_energies.push_back( fShort_ );
468  subdet_energies.push_back( fLong_ );
469  std::sort( subdet_energies.begin(), subdet_energies.end(), greater<double>() );
470  if( jet.energy() > 0 ) {
471  fEB_ /= jet.energy();
472  fEE_ /= jet.energy();
473  fHB_ /= jet.energy();
474  fHE_ /= jet.energy();
475  fHO_ /= jet.energy();
476  fShort_ /= jet.energy();
477  fLong_ /= jet.energy();
478  } else {
479  if( fEB_ > 0 || fEE_ > 0 || fHB_ > 0 || fHE_ > 0 || fHO_ > 0 || fShort_ > 0 || fLong_ > 0 )
480  edm::LogError("UnexpectedEventContents")<<"Jet ID Helper found energy in subdetectors and jet E <= 0";
481  }
482 }
483 
485  vector< subtower > &subtowers,
486  vector< subtower > &Ecal_subtowers,
487  vector< subtower > &Hcal_subtowers,
488  vector< subtower > &HO_subtowers,
489  vector< double > &HPD_energies,
490  vector< double > &RBX_energies,
491  const int iDbg )
492 {
493  subtowers.clear(); Ecal_subtowers.clear(); Hcal_subtowers.clear(); HO_subtowers.clear();
494  HPD_energies.clear(); RBX_energies.clear();
495 
496  std::map< int, double > HPD_energy_map, RBX_energy_map;
497 
498  vector< CaloTowerPtr > towers = jet.getCaloConstituents ();
499  int nTowers = towers.size();
500  if( iDbg > 9 ) cout<<"classifyJetTowers started. # of towers found: "<<nTowers<<endl;
501 
502  for( int iTower = 0; iTower <nTowers ; iTower++ ) {
503 
504  CaloTowerPtr& tower = towers[iTower];
505 
506  int nEM = 0, nHad = 0, nHO = 0;
507  const vector< DetId >& cellIDs = tower->constituents(); // cell == recHit
508  int nCells = cellIDs.size();
509  if( iDbg ) cout<<"tower #"<<iTower<<" has "<<nCells<<" cells. "
510  <<"It's at iEta: "<<tower->ieta()<<", iPhi: "<<tower->iphi()<<endl;
511 
512  for( int iCell = 0; iCell < nCells; ++iCell ) {
513  DetId::Detector detNum = cellIDs[iCell].det();
514  if( detNum == DetId::Hcal ) {
515  HcalDetId HcalID = cellIDs[ iCell ];
516  HcalSubdetector HcalNum = HcalID.subdet();
517  if( HcalNum == HcalOuter ) {
518  ++nHO;
519  } else {
520  ++nHad;
521  }
522  } else if (detNum == DetId::Ecal) {
523  ++nEM;
524  }
525  }
526 
527  double E_em = tower->emEnergy();
528  if( E_em != 0 ) Ecal_subtowers.push_back( subtower( E_em, nEM ) );
529 
530  double E_HO = tower->outerEnergy();
531  if( E_HO != 0 ) HO_subtowers.push_back( subtower( E_HO, nHO ) );
532 
533  double E_had = tower->hadEnergy();
534  if( E_had != 0 ) {
535  Hcal_subtowers.push_back( subtower( E_had, nHad ) );
536  // totHcalE += E_had;
537 
538  int iEta = tower->ieta();
539  Region reg = region( iEta );
540  int iPhi = tower->iphi();
541  if( iDbg>3 ) cout<<"tower has E_had: "<<E_had<<" iEta: "<<iEta
542  <<", iPhi: "<<iPhi<<" -> "<<reg;
543 
544  if( reg == HEneg || reg == HBneg || reg == HBpos || reg == HEpos ) {
545  int oddnessIEta = HBHE_oddness( iEta );
546  if( oddnessIEta < 0 ) break; // can't assign this tower to a single readout component
547 
548  int iHPD = 100 * reg;
549  int iRBX = 100 * reg + ((iPhi + 1) % 72) / 4; // 71,72,1,2 are in the same RBX module
550 
551  if(( reg == HEneg || reg == HEpos ) && std::abs( iEta ) >= 21 ) { // at low-granularity edge of HE
552  if( (0x1 & iPhi) == 0 ) {
553  edm::LogError("CodeAssumptionsViolated")<<
554  "Bug?! Jet ID code assumes no even iPhi recHits at HE edges";
555  return;
556  }
557  bool boolOddnessIEta = oddnessIEta;
558  bool upperIPhi = (( iPhi%4 ) == 1 || ( iPhi%4 ) == 2); // the upper iPhi indices in the HE wedge
559  // remap the iPhi so it fits the one in the inner HE regions, change in needed in two cases:
560  // 1) in the upper iPhis of the module, the even IEtas belong to the higher iPhi
561  // 2) in the loewr iPhis of the module, the odd IEtas belong to the higher iPhi
562  if( upperIPhi != boolOddnessIEta ) ++iPhi;
563  // note that iPhi could not be 72 before, so it's still in the legal range [1,72]
564  } // if at low-granularity edge of HE
565  iHPD += iPhi;
566 
567  // book the energies
568  HPD_energy_map[ iHPD ] += E_had;
569  RBX_energy_map[ iRBX ] += E_had;
570  if( iDbg > 5 ) cout<<" --> H["<<iHPD<<"]="<<HPD_energy_map[iHPD]
571  <<", R["<<iRBX<<"]="<<RBX_energy_map[iRBX];
572  } // HBHE
573  } // E_had > 0
574  } // loop on towers
575 
576  // sort the subtowers
577  // std::sort( Hcal_subtowers.begin(), Hcal_subtowers.end(), subtower_has_greater_E );
578  // std::sort( Ecal_subtowers.begin(), Ecal_subtowers.end(), subtower_has_greater_E );
579 
580  // put the energy sums (the 2nd entry in each pair of the maps) into the output vectors and sort them
581  std::transform( HPD_energy_map.begin(), HPD_energy_map.end(),
582  std::inserter (HPD_energies, HPD_energies.end()), select2nd );
583  // std::select2nd<std::map<int,double>::value_type>());
584  // std::sort( HPD_energies.begin(), HPD_energies.end(), greater<double>() );
585  std::transform( RBX_energy_map.begin(), RBX_energy_map.end(),
586  std::inserter (RBX_energies, RBX_energies.end()), select2nd );
587  // std::select2nd<std::map<int,double>::value_type>());
588  // std::sort( RBX_energies.begin(), RBX_energies.end(), greater<double>() );
589 
590  subtowers.insert( subtowers.end(), Hcal_subtowers.begin(), Hcal_subtowers.end() );
591  subtowers.insert( subtowers.end(), Ecal_subtowers.begin(), Ecal_subtowers.end() );
592  subtowers.insert( subtowers.end(), HO_subtowers.begin(), HO_subtowers.end() );
593  std::sort( subtowers.begin(), subtowers.end(), subtower_has_greater_E );
594 }
595 
596 // ---------------------------------------------------------------------------------------------------------
597 // private helper functions to figure out detector & readout geometry as needed
598 
600 {
601  int ae = TMath::Abs( iEta );
602  if( ae == 29 && depth == 1 ) ae += 1; // observed that: hits are at depths 1 & 2; 1 goes with the even pattern
603  return ae & 0x1;
604 }
605 
607 {
608  HcalDetId id(rawid);
609  if( id.subdet() == HcalEndcap)
610  {
611  if( id.ieta() < 0 ) return HEneg;
612  else return HEpos;
613  }
614  if( id.subdet() == HcalBarrel && id.ieta() < 0) return HBneg;
615  return HBpos;
616 }
617 
619 {
620  int ae = TMath::Abs( iEta );
621  if( ae == 29 ) return -1; // can't figure it out without RecHits
622  return ae & 0x1;
623 }
624 
626 {
627  if( iEta == 16 || iEta == -16 ) return unknown_region; // both HB and HE cells belong to these towers
628  if( iEta == 29 || iEta == -29 ) return unknown_region; // both HE and HF cells belong to these towers
629  if( iEta <= -30 ) return HFneg;
630  if( iEta >= 30 ) return HFpos;
631  if( iEta <= -17 ) return HEneg;
632  if( iEta >= 17 ) return HEpos;
633  if( iEta < 0 ) return HBneg;
634  return HBpos;
635 }
float hadEnergyInHE() const
Definition: CaloJet.h:108
float emEnergyInEE() const
Definition: CaloJet.h:114
T getParameter(std::string const &) const
void setComment(std::string const &value)
ParameterDescriptionNode * ifValue(ParameterDescription< T > const &switchParameter, std::unique_ptr< ParameterDescriptionCases< T >> cases)
Region region(int iEta)
Definition: JetIDHelper.cc:625
bool subtower_has_greater_E(reco::helper::JetIDHelper::subtower i, reco::helper::JetIDHelper::subtower j)
Definition: JetIDHelper.cc:40
bool mergedDepth29(HcalDetId id) const
Definition: HcalTopology.h:107
Definition: helper.py:1
void classifyJetComponents(const edm::Event &event, const edm::EventSetup &setup, const reco::CaloJet &jet, std::vector< double > &energies, std::vector< double > &subdet_energies, std::vector< double > &Ecal_energies, std::vector< double > &Hcal_energies, std::vector< double > &HO_energies, std::vector< double > &HPD_energies, std::vector< double > &RBX_energies, double &LS_bad_energy, double &HF_OOT_energy, const int iDbg=0)
Definition: JetIDHelper.cc:248
Jets made from CaloTowers.
Definition: CaloJet.h:29
HcalSubdetector subdet() const
get the subdetector
Definition: HcalDetId.h:146
std::vector< T >::const_iterator const_iterator
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:2
float emEnergyInHF() const
Definition: CaloJet.h:116
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
double pt() const final
transverse momentum
unsigned int nCarrying(double fraction, const std::vector< double > &descending_energies)
Definition: JetIDHelper.cc:215
virtual std::vector< CaloTowerPtr > getCaloConstituents() const
get all constituents
Definition: CaloJet.cc:93
void calculate(const edm::Event &event, const edm::EventSetup &setup, const reco::CaloJet &jet, const int iDbg=0)
Definition: JetIDHelper.cc:100
bool hasNonPositiveE(reco::helper::JetIDHelper::subtower x)
Definition: JetIDHelper.cc:36
Region HBHE_region(uint32_t)
Definition: JetIDHelper.cc:606
float hadEnergyInHO() const
Definition: CaloJet.h:106
int depth() const
get the tower depth
Definition: HcalDetId.h:166
double et() const final
transverse energy
float emEnergyInEB() const
Definition: CaloJet.h:112
T Abs(T a)
Definition: MathUtil.h:49
int ieta() const
get the cell ieta
Definition: HcalDetId.h:159
double energy() const final
energy
HcalSubdetector
Definition: HcalAssistant.h:31
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static double select2nd(std::map< int, double >::value_type const &pair)
Definition: JetIDHelper.cc:34
void fillDescription(edm::ParameterSetDescription &iDesc)
Definition: JetIDHelper.cc:86
void classifyJetTowers(const edm::Event &event, const reco::CaloJet &jet, std::vector< subtower > &subtowers, std::vector< subtower > &Ecal_subtowers, std::vector< subtower > &Hcal_subtowers, std::vector< subtower > &HO_subtowers, std::vector< double > &HPD_energies, std::vector< double > &RBX_energies, const int iDbg=0)
Definition: JetIDHelper.cc:484
const_iterator end() const
T Max(T a, T b)
Definition: MathUtil.h:44
Detector
Definition: DetId.h:26
int HBHE_oddness(int iEta, int depth)
Definition: JetIDHelper.cc:599
iterator find(key_type k)
fixed size matrix
size_type size() const
T get() const
Definition: EventSetup.h:71
float hadEnergyInHB() const
Definition: CaloJet.h:104
float hadEnergyInHF() const
Definition: CaloJet.h:110
unsigned int hitsInNCarrying(double fraction, const std::vector< subtower > &descending_towers)
Definition: JetIDHelper.cc:232
Definition: event.py:1