ATLAS Offline Software
BoostedXbbTag.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #ifndef ROOTCORE
9 #endif
10 
12 
13 // root includes
14 #include <TSystem.h>
15 #include <TFile.h>
16 #include <TH2F.h>
17 
18 // c++ includes
19 #include <iostream>
20 #include <sstream>
21 #include <fstream>
22 
23 #define APP_NAME "BoostedXbbTag"
24 
25 using namespace JetSubStructureUtils;
26 
27 // make all static accessors static to this file, like extern but hip
44 
45 BoostedXbbTag::BoostedXbbTag( const std::string& working_point,
46  const std::string& recommendations_file,
47  const std::string& boson_type,
48  const std::string& algorithm_name,
49  int num_bTags,
50  const std::string& decor_prefix,
51  bool debug,
52  bool verbose) :
53  m_working_point(working_point),
54  m_recommendations_file(recommendations_file),
55  m_boson_type(boson_type),
56  m_algorithm_name(algorithm_name),
57  m_num_bTags(num_bTags),
58  m_decor_prefix(decor_prefix),
59  m_debug(debug),
60  m_verbose(verbose),
61  m_bTagCut(FLT_MIN),
62  m_bTagCutCharm(FLT_MIN),
63  m_massMin(FLT_MIN),
64  m_massMax(FLT_MAX),
65  m_D2_params(5, FLT_MIN),
66  m_D2_cut_direction("None"),
67  m_muonSelectionTool(new CP::MuonSelectionTool("JSSU_MuonSelection")),
68  m_bad_configuration(false),
69  m_isB(SG::AuxElement::Decorator<int>(m_decor_prefix+"m_isB")),
70  m_matchedMuonsLink(SG::AuxElement::Decorator<std::vector<ElementLink<xAOD::IParticleContainer> > >(m_decor_prefix+"MatchedMuonsLink")),
71  m_correctedJetDecor(SG::AuxElement::Decorator<TLorentzVector>(m_decor_prefix+"CorrectedJetP4")),
72  m_massWindow(SG::AuxElement::Decorator<std::pair<float, float>>(m_decor_prefix+"MassWindow")),
73  m_D2Pivot(SG::AuxElement::Decorator<std::pair<float, std::string>>(m_decor_prefix+"m_D2Pivot"))
74 {
75 
76  /* check configurations passed in, use m_bad_configuration as flag:
77  - flag it to true if something is badly configured
78  - otherwise, it should be false if everything seems ok
79  */
80 
81  if(m_debug)
82  printf("<%s>: Attempting to configure with\r\n\t"
83  "Working Point %s\r\n\t"
84  "Recommendations File %s\r\n\t"
85  "Boson Type %s\r\n\t"
86  "Algorithm Name %s\r\n\t"
87  "Debug Output? %s\r\n\t"
88  "Verbose Output? %s\r\n"
89  "=========================================\r\n",
90  APP_NAME, m_working_point.c_str(),
91  m_recommendations_file.c_str(),
92  m_boson_type.c_str(), m_algorithm_name.c_str(),
93  m_debug?"Yes":"No", m_verbose?"Yes":"No");
94 
95  if(!m_muonSelectionTool->initialize().isSuccess()){
96  printf("<%s>: Could not initialize the MuonSelectionTool.\r\n", APP_NAME);
97  m_bad_configuration |= true;
98  }
99 
100  std::set<std::string> validWorkingPoints = {"tight", "medium", "loose", "veryloose", "single", "single_loose", "single_medium"};
101  if( validWorkingPoints.find(m_working_point) == validWorkingPoints.end()){
102  printf("<%s>: Unknown working point requested.\r\n\tExpected: single, single_loose, single_medium, veryloose, loose, medium, tight\r\n\tGiven: %s\r\n", APP_NAME, m_working_point.c_str());
103  m_bad_configuration |= true;
104  } else {
105  if(m_verbose) printf("<%s>: Valid working point requested.\r\n", APP_NAME);
106  }
107 
108  std::set<std::string> validBosonTypes = {"Higgs"};
109  if( validBosonTypes.find(m_boson_type) == validBosonTypes.end()){
110  printf("<%s>: Unknown boson type requested.\r\n\tHiggs\r\n\tGiven: %s\r\n", APP_NAME, m_boson_type.c_str());
111  m_bad_configuration |= true;
112  } else {
113  if(m_verbose) printf("<%s>: Valid boson type requested.\r\n", APP_NAME);
114  }
115 
116 #ifdef ROOTCORE
117  m_recommendations_file = gSystem->ExpandPathName(m_recommendations_file.c_str());
118 #else
120 #endif
121 
122  bool found_configuration = false;
123 
124  /* https://root.cern.ch/root/roottalk/roottalk02/5332.html */
125  FileStat_t fStats;
126  int fSuccess = gSystem->GetPathInfo(m_recommendations_file.c_str(), fStats);
127  if(fSuccess != 0){
128  printf("<%s>: Recommendations file could not be found.\r\n\tGiven: %s\r\n", APP_NAME, m_recommendations_file.c_str());
129  m_bad_configuration |= true;
130  } else {
131  if(m_verbose) printf("<%s>: Recommendations file was found.\r\n", APP_NAME);
132 
133  // if we made it here, everything appears ok with our file, attempt to read it
134  std::ifstream f_in;
135  f_in.open(m_recommendations_file, std::ios::in);
136  if( f_in.fail() ){
137  printf("<%s>: Something is wrong with the recommendations file. Could not open for reading.\r\n", APP_NAME);
138  m_bad_configuration |= true;
139  } else {
140  if(m_verbose) printf("<%s>: Recommendations file opened for reading.\r\n", APP_NAME);
141 
142  std::string line;
143  while( std::getline(f_in, line) ){
144  if(line.empty()) continue; // skip empty lines
145  if(line[0] == '#') continue; // skip commented lines
146 
147  /* token contains the current splitted text */
148  std::string token;
149 
150  // split by space
151  std::istringstream ss(line);
152  /* lineDetails is an array of the splits */
153  std::vector<std::string> lineDetails{std::istream_iterator<std::string>{ss}, std::istream_iterator<std::string>{}};
154  if(lineDetails.size() != 14) continue;
155 
156  if(m_verbose) printf("<%s>: Reading in line\r\n\t'%s'\r\n", APP_NAME, line.c_str());
157  if(lineDetails[0] != m_boson_type) continue;
158  if(lineDetails[1] != m_working_point) continue;
159  if(lineDetails[2] != m_algorithm_name) continue;
160  if(std::stoi(lineDetails[3]) != m_num_bTags) continue;
161 
162  m_bTagCut = std::stof(lineDetails[4]);
163  m_bTagCutCharm = std::stof(lineDetails[5]);
164  m_massMin = std::stof(lineDetails[6]);
165  m_massMax = std::stof(lineDetails[7]);
166  for(int i=0; i < 5; i++)
167  m_D2_params[i] = std::stof(lineDetails[i+8]);
168  m_D2_cut_direction = lineDetails[13];
169 
170  if(m_verbose) printf("<%s>: Found the configuration! We're done reading the file.\r\n", APP_NAME);
171  found_configuration = true;
172  break;
173  }
174  }
175  }
176 
177  if(!found_configuration){
178  printf("<%s>: Could not configure the tool. The configuration does not exist in the recommendations file.\r\n", APP_NAME);
179  m_bad_configuration |= true;
180  }
181 
183  std::cout << "|=====================================================|" << std::endl;
184  std::cout << "| WARNING WARNING WARNING |" << std::endl;
185  std::cout << "| WARNING WARNING WARNING |" << std::endl;
186  std::cout << "| WARNING WARNING WARNING |" << std::endl;
187  std::cout << "| WARNING WARNING WARNING |" << std::endl;
188  std::cout << "|-----------------------------------------------------|" << std::endl;
189  std::cout << "| |" << std::endl;
190  std::cout << "| |" << std::endl;
191  std::cout << "| |" << std::endl;
192  std::cout << "| BoostedXbbTagger is misconfigured! |" << std::endl;
193  std::cout << "| |" << std::endl;
194  std::cout << "| |" << std::endl;
195  std::cout << "| |" << std::endl;
196  std::cout << "|=====================================================|" << std::endl;
197  } else {
198  if(m_verbose) printf("<%s>: BoostedXbbTagger is configured successfuly! Congratulations on such an achievement.\r\n", APP_NAME);
199  }
200 
201 }
202 
203 std::pair<bool, std::string> BoostedXbbTag::get_algorithm_name(const xAOD::Jet& jet,
204  const xAOD::JetAlgorithmType::ID jet_algorithm,
205  const float size_parameter,
206  const xAOD::JetInput::Type jet_input,
207  const xAOD::JetTransform::Type jet_transform) const {
208  bool error_flag(false);
209 
210  /* http://acode-browser.usatlas.bnl.gov/lxr/source/atlas/Event/xAOD/xAODJet/xAODJet/JetContainerInfo.h */
211  static const std::map<int, std::string> mapAlgorithmType = {
215  };
216 
217  static const std::map<int, std::string> mapInputType {
218  {xAOD::JetInput::LCTopo, "LC"},
219  {xAOD::JetInput::EMTopo, "EM"},
220  {xAOD::JetInput::Truth, "TRU"},
221  {xAOD::JetInput::Track, "TRA"},
222  {xAOD::JetInput::PFlow, "PFL"}
223  };
224 
225  static const std::map<int, std::string> mapTransformType {
226  {xAOD::JetTransform::Trim, "TRIM"},
227  {xAOD::JetTransform::Prune, "PRUN"},
229  };
230 
231  // beginning of the algorithm_name
232  std::string algorithm_name = mapAlgorithmType.at(jet_algorithm)
233  + std::to_string(static_cast<int>(size_parameter*10))
234  + mapInputType.at(jet_input)
235  + mapTransformType.at(jet_transform);
236 
237 
238  // ending of algorithm_name
239  switch(jet_transform){
241  if( !s_PtFrac.isAvailable(jet) ){
242  if(m_debug) printf("<%s>: PtFrac is not defined for the input jet.\r\n", APP_NAME);
243  error_flag |= true;
244  }
245  if( !s_RClus.isAvailable(jet) ){
246  if(m_debug) printf("<%s>: RClus is not defined for the input jet.\r\n" , APP_NAME);
247  error_flag |= true;
248  }
249 
250  if(m_verbose) printf("<%s>: PtFrac: %0.2f\tRClus: %0.2f\r\n", APP_NAME, s_PtFrac(jet), s_RClus(jet));
251  algorithm_name += "F" + std::to_string(static_cast<int>(s_PtFrac(jet)*100))
252  + "R" + std::to_string(static_cast<int>(s_RClus(jet)*100));
253  break;
255  if( !s_RCut.isAvailable(jet) ){
256  if(m_debug) printf("<%s>: RCut is not defined for the input jet.\r\n", APP_NAME);
257  error_flag |= true;
258  }
259  if( !s_ZCut.isAvailable(jet) ){
260  if(m_debug) printf("<%s>: ZCut is not defined for the input jet.\r\n", APP_NAME);
261  error_flag |= true;
262  }
263 
264  if(m_verbose) printf("<%s>: RCut: %0.2f\tZCut: %0.2f\r\n", APP_NAME, s_RCut(jet), s_ZCut(jet));
265  algorithm_name += "R" + std::to_string(static_cast<int>(s_RCut(jet)*100))
266  + "Z" + std::to_string(static_cast<int>(s_ZCut(jet)*100));
267  break;
269  if( !s_MuMax.isAvailable(jet) ){
270  if(m_debug) printf("<%s>: MuMax is not defined for the input jet.\r\n", APP_NAME);
271  error_flag |= true;
272  }
273  if( !s_RClus.isAvailable(jet) ){
274  if(m_debug) printf("<%s>: RClus is not defined for the input jet.\r\n", APP_NAME);
275  error_flag |= true;
276  }
277  if( !s_YMin.isAvailable(jet) ){
278  if(m_debug) printf("<%s>: YMin is not defined for the input jet.\r\n" , APP_NAME);
279  error_flag |= true;
280  }
281  if( !s_BDRS.isAvailable(jet) ){
282  if(m_debug) printf("<%s>: BDRS is not defined for the input jet.\r\n" , APP_NAME);
283  error_flag |= true;
284  }
285 
286  if(m_verbose) printf("<%s>: MuMax: %0.2f\tRClus: %0.2f\tYMin: %0.2f\r\n", APP_NAME, s_MuMax(jet), s_RClus(jet), s_YMin(jet));
287  algorithm_name += "M" + std::to_string(static_cast<int>(s_MuMax(jet)*100))
288  + "R" + std::to_string(static_cast<int>(s_RClus(jet)*100))
289  + "Y" + std::to_string(static_cast<int>(s_YMin(jet)*100));
290  break;
291  default:
292  if(m_debug) printf("<%s>: Current value of xAOD::JetTransform::Type is not supported!\r\n", APP_NAME);
293  error_flag |= true;
294  break;
295  }
296 
297  return std::pair<bool, std::string>(!error_flag, algorithm_name);
298 }
299 
300 
302 {
303  // bad configuration
305  if(m_debug) printf("<%s>: BoostedXbbTag has a bad configuration!\r\n", APP_NAME);
306  return -9;
307  }
308 
309  // if we call via this method, we need these 4 things defined
310  if( !s_AlgorithmType.isAvailable(jet) ){
311  if(m_debug) printf("<%s>: AlgorithmType is not defined for the jet.\r\n", APP_NAME);
312  return -9;
313  }
314  if( !s_SizeParameter.isAvailable(jet) ){
315  if(m_debug) printf("<%s>: SizeParameter is not defined for the jet.\r\n", APP_NAME);
316  return -9;
317  }
318  if( !s_InputType.isAvailable(jet) ) {
319  if(m_debug) printf("<%s>: InputType is not defined for the jet.\r\n" , APP_NAME);
320  return -9;
321  }
322  if( !s_TransformType.isAvailable(jet) ){
323  if(m_debug) printf("<%s>: TransformType is not defined for the jet.\r\n", APP_NAME);
324  return -9;
325  }
326 
327  if(m_verbose) printf("<%s>: Jet has the 4 main properties set.\r\n\t"
328  "AlgorithmType: %d\r\n\t"
329  "Size Parameter: %0.2f\r\n\t"
330  "Input Type: %d\r\n\t"
331  "Transform Type: %d\r\n",
333 
334  // get the algorithm name and check result
335  std::pair<bool, std::string> res = get_algorithm_name(jet,
338  static_cast<xAOD::JetInput::Type>(s_InputType(jet)),
340 
341  // is it a valid result?
342  if(!res.first){
343  if(m_debug) printf("<%s>: Could not determine what jet you are using.\r\n", APP_NAME);
344  return -9;
345  } else {
346  if(m_verbose) printf("<%s>: Jet introspection successful.\r\n", APP_NAME);
347  }
348 
349  return result(jet, res.second, muons);
350 }
351 
352 int BoostedXbbTag::result(const xAOD::Jet& jet, const std::string& algorithm_name, const xAOD::MuonContainer* muons) const {
353  // bad configuration
355  if(m_debug) printf("<%s>: BoostedXbbTag has a bad configuration!\r\n", APP_NAME);
356  return -9;
357  }
358 
359  // check basic kinematic selection
360  if(jet.pt()/1.e3 < 250.0 || std::fabs(jet.eta()) > 2.0){
361  if(m_verbose) printf("<%s>: Jet does not pass basic kinematic selection. pT > 250 GeV, |eta| < 2.0\r\n\tJet Pt: %0.6f GeV\r\n\tJet |eta|: %0.6f\r\n", APP_NAME, jet.pt()/1.e3, std::fabs(jet.eta()));
362  return -5;
363  }
364  // upper pT cut from 2015 not needed anymore because uncertainties are now available
365  //if(jet.pt()/1.e3 > 2000.0){
366  // printf("<%s>: Warning, jet has pT > 2 TeV!\r\nJet Pt: %0.6f GeV", APP_NAME, jet.pt()/1.e3);
367  // return -5;
368  //}
369 
370  // make sure we are using the right kind of jet
371  if(algorithm_name != m_algorithm_name){
372  if(m_debug) printf("<%s>: You configured for %s but you passed in a jet of type %s.\r\n", APP_NAME, m_algorithm_name.c_str(), algorithm_name.c_str());
373  return -9;
374  }
375 
376  /* Steps:
377  1. Get all AntiKt2TrackJets asssociated with the ungroomed jet
378  2. B-tag the two leading track-jets
379  - if double b-tagging, require that both track-jets are b-tagged
380  - if single b-tagging, and there is more than one track-jet, take the highest MV2 of the leading two jets
381  3. Match the muon (if any) to these b-tagged track-jets
382  - if more than 1 muon matches a track jet (within the radius of the track jet), only use the muon closest in DR
383  4. Correct the fat-jet mass by putting the matched muon back (if there is a matched muon)
384  5. Set a cut on the corrected fat jet mass
385  6. Cut on the D2 of the fat-jet (D2 from calorimeter constituents only)
386  */
387 
388  // global pass variables, set to false by default
389  bool pass_mass = false,
390  pass_d2 = false,
391  pass_btag = false;
392 
393  // Step 1
394  std::vector<const xAOD::Jet*> associated_trackJets;
395  // get the track jets from the s_parent
396  bool problemWithParent = false;
398  if(!s_parent.isAvailable(jet)) problemWithParent = true;
399  else parentEL = s_parent(jet);
400  if(problemWithParent || !parentEL.isValid()){
401  if(m_debug) printf("<%s>: ", APP_NAME);
402  if(problemWithParent && m_debug) printf("Parent decoration does not exist. ");
403  if(!parentEL.isValid() && m_debug) printf("Parent link is not valid. ");
404  if(m_debug) printf("\r\n");
405  return -2; // do not fallback -- comment out to enable fallback
407  //if(m_debug) printf("Get track jets from groomed jet.\r\n");
408  //if(!jet.getAssociatedObjects<xAOD::Jet>("GhostAntiKt2TrackJet", associated_trackJets)){
409  // if(m_verbose) printf("<%s>: No associated track jets found on jet.\r\n", APP_NAME);
410  // return -2;
411  //}
412  //else if(m_verbose) printf("<%s>: Got track jets from groomed jet.\r\n", APP_NAME);
413  } else {
414  const xAOD::Jet* parentJet = *parentEL;
415  if(!parentJet->getAssociatedObjects<xAOD::Jet>("GhostAntiKt2TrackJet", associated_trackJets)){
416  if(m_verbose) printf("<%s>: No associated track jets found on s_parent jet.\r\n", APP_NAME);
417  return -2; // do not fallback -- comment out to enable fallback
419  //if(m_debug) printf("Get track jets from groomed jet.\r\n");
420  //if(!jet.getAssociatedObjects<xAOD::Jet>("GhostAntiKt2TrackJet", associated_trackJets)){
421  // if(m_verbose) printf("<%s>: No associated track jets found on jet.\r\n", APP_NAME);
422  // return -2;
423  //}
424  //else if(m_verbose) printf("<%s>: Got track jets from groomed jet.\r\n", APP_NAME);
425  }
426  else if(m_verbose) printf("<%s>: Got track jets from parent jet.\r\n", APP_NAME);
427  }
428 
429  // decorate all trackjets by default
430  for(const auto& trackJet: associated_trackJets)
431  m_isB(*trackJet) = 0;
432 
433  // filter out the track jets we do not want (pT > 10 GeV and |eta| < 2.5 and at least 2 constituents)
434  associated_trackJets.erase(
435  std::remove_if(associated_trackJets.begin(), associated_trackJets.end(), [](const xAOD::Jet* jet) -> bool { return (jet->pt()/1.e3 < 10.0 || fabs(jet->eta()) > 2.5 || jet->numConstituents() < 2); }),
436  associated_trackJets.end());
437  if(associated_trackJets.size() < 2){
438  if(m_working_point.find("single") == std::string::npos){
439  if(m_verbose) printf("<%s>: We need at least two associated track jets for working point %s.\r\n", APP_NAME, m_working_point.c_str());
440  return -2;
441  }
442  else if(associated_trackJets.empty()){
443  if(m_verbose) printf("<%s>: We need at least one associated track jet for working point %s.\r\n", APP_NAME, m_working_point.c_str());
444  return -2;
445  }
446  }
447 
448  // Step 2
449  std::sort(associated_trackJets.begin(), associated_trackJets.end(), [](const xAOD::IParticle* lhs, const xAOD::IParticle* rhs) -> bool { return (lhs->pt() > rhs->pt()); });
450  int num_bTags(0);
451  int num_trackJets_toLookAt = std::min((int)associated_trackJets.size(), 2);
452  for(int i = 0; i < num_trackJets_toLookAt; i++){
453  auto& trackJet = associated_trackJets.at(i);
454 
455  // MV2c10
456  double mv2c10(FLT_MIN);
457  const xAOD::BTagging* btag = xAOD::BTaggingUtilities::getBTagging( *trackJet );
458  if(!btag->MVx_discriminant("MV2c10", mv2c10)){
459  if(m_verbose) printf("<%s>: Could not retrieve the MV2c10 discriminant.\r\n", APP_NAME);
460  return -9;
461  }
462  int isBTagged = static_cast<int>(mv2c10 > m_bTagCut);
463 
464 // // MV2c20
465 // double mv2c20(FLT_MIN);
466 // if(!trackJet->btagging()->MVx_discriminant("MV2c20", mv2c20)){
467 // if(m_verbose) printf("<%s>: Could not retrieve the MV2c20 discriminant.\r\n", APP_NAME);
468 // return -9;
469 // }
470 // int isBTagged = static_cast<int>(mv2c20 > m_bTagCut);
471 
472 // // 2D b-tagging
473 // double mv2c00(FLT_MIN);
474 // double mv2c100(FLT_MIN);
475 // if(!trackJet->btagging()->MVx_discriminant("MV2c00", mv2c00)){
476 // if(m_verbose) printf("<%s>: Could not retrieve the MV2c00 discriminant.\r\n", APP_NAME);
477 // return -9;
478 // }
479 // if(!trackJet->btagging()->MVx_discriminant("MV2c100", mv2c100)){
480 // if(m_verbose) printf("<%s>: Could not retrieve the MV2c100 discriminant.\r\n", APP_NAME);
481 // return -9;
482 // }
483 // int isBTagged = static_cast<int>(mv2c00 > m_bTagCut && mv2c100 > m_bTagCutCharm);
484 
485  m_isB(*trackJet) = isBTagged;
486  num_bTags += isBTagged;
487  }
488  if( num_bTags < m_num_bTags ){
489  if(m_verbose) printf("<%s>: We require the %d leading track jet%s b-tagged. %d %s b-tagged.\r\n", APP_NAME, m_num_bTags, (m_num_bTags == 1)?"":"s", num_bTags, (num_bTags == 1)?"was":"were");
490  //return -2;
491  } else {
492  pass_btag = true;
493  }
494 
495  // Step 3
496  std::vector<const xAOD::Muon*> matched_muons;
497  // first select the muons: Combined, Medium, pT > 10 GeV, |eta| < 2.5
498  std::vector<const xAOD::Muon*> preselected_muons(muons->size(), nullptr);
499  // [Next line: selection for muon matching. IF PROBLEMS with getQuality, disable muon matching temporarily by using the second line below instead]
500  auto it = std::copy_if(muons->begin(), muons->end(), preselected_muons.begin(), [this](const xAOD::Muon* muon) -> bool { return (muon->pt()/1.e3 > 10.0 && m_muonSelectionTool->getQuality(*muon) <= xAOD::Muon::Medium && fabs(muon->eta()) < 2.5); });
501  //auto it = std::copy_if(muons->begin(), muons->end(), preselected_muons.begin(), [this](const xAOD::Muon* muon) -> bool { return false; });
502  preselected_muons.resize(std::distance(preselected_muons.begin(), it)); // shrink container to new size
503  if(preselected_muons.empty()){
504  if(m_verbose) printf("<%s>: There are no muons that passed the kinematic preselection.\r\n", APP_NAME);
505  //return -3;
506  } else {
507  for(int i = 0; i < num_trackJets_toLookAt; i++){
508  auto& trackJet = associated_trackJets.at(i);
509  // only match muon to b-tagged track jets
510  if(m_isB(*trackJet) == 0) continue;
511  // it's b-tagged, try to match it
512  float maxDR(0.2);
513  trackJet->getAttribute("SizeParameter", maxDR);
514  const xAOD::Muon *closest_muon(nullptr);
515  for(const auto *const muon: preselected_muons){
516  float DR( trackJet->p4().DeltaR(muon->p4()) );
517  if(DR > maxDR) continue;
518  maxDR = DR;
519  closest_muon = muon;
520  }
521  if(closest_muon) {
522  matched_muons.push_back(closest_muon);
523  }
524  }
525  }
526 
527  // Step 4
528  TLorentzVector corrected_jet = jet.p4();
529  if(m_verbose) printf("<%s>: There are %d matched muons.\r\n", APP_NAME, (int)matched_muons.size());
530  std::vector<ElementLink<xAOD::IParticleContainer> > matched_muons_links;
531  for(const auto *muon : matched_muons) {
532  float eLoss(0.0);
533  muon->parameter(eLoss,xAOD::Muon::EnergyLoss);
534  if(m_debug) printf("<%s>: getELossTLV xAOD::Muon eLoss= %0.2f\r\n", APP_NAME, eLoss);
535  auto mTLV = muon->p4();
536  double eLossX = eLoss*sin(mTLV.Theta())*cos(mTLV.Phi());
537  double eLossY = eLoss*sin(mTLV.Theta())*sin(mTLV.Phi());
538  double eLossZ = eLoss*cos(mTLV.Theta());
539  auto mLoss = TLorentzVector(eLossX,eLossY,eLossZ,eLoss);
540  corrected_jet = corrected_jet + mTLV - mLoss;
541 
542  ElementLink<xAOD::IParticleContainer> el_muon( *muons, muon->index() );
543  matched_muons_links.push_back(el_muon);
544  }
545  // may not always be the corrected jet, but always contains what is used to cut against
546  m_correctedJetDecor(jet) = corrected_jet;
547  m_matchedMuonsLink(jet) = matched_muons_links;
548 
549  std::string buffer;
550 
551  // Step 5
552  m_massWindow(jet) = std::pair<float, float>(m_massMin, m_massMax);
553  buffer = "<%s>: Jet %s the mass window cut.\r\n\tMass: %0.6f GeV\r\n\tMass Window: [ %0.6f, %0.6f ]\r\n";
554  if(corrected_jet.M()/1.e3 < m_massMin || corrected_jet.M()/1.e3 > m_massMax){
555  if(m_verbose) printf(buffer.c_str(), APP_NAME, "failed", corrected_jet.M()/1.e3, m_massMin, m_massMax);
556  //return 0;
557  } else {
558  if(m_verbose) printf(buffer.c_str(), APP_NAME, "passed", corrected_jet.M()/1.e3, m_massMin, m_massMax);
559  pass_mass = true;
560  }
561 
562  // Step 6
563  if(m_D2_cut_direction == "LEFT" || m_D2_cut_direction == "RIGHT"){
564  float d2(0.0);
565  if(s_D2.isAvailable(jet)){
566  d2 = s_D2(jet);
567  } else {
568  if((!s_ECF1.isAvailable(jet) || !s_ECF2.isAvailable(jet) || !s_ECF3.isAvailable(jet))){
569  if(m_debug) printf("<%s>: D2 wasn't calculated. ECF# variables are not available.\r\n", APP_NAME);
570  return -9;
571  }
572  d2 = s_ECF3(jet) * pow(s_ECF1(jet), 3.0) / pow(s_ECF2(jet), 3.0);
573  }
574  buffer = "<%s>: Jet %s the D2 cut from %s\r\n\tD2: %0.6f\r\n\tCut: %0.6f\r\n";
575  // then calculate d2 and check that
576  float D2Cut = m_D2_params[0] + m_D2_params[1] * jet.pt()/1.e3 + m_D2_params[2] * pow(jet.pt()/1.e3, 2) + m_D2_params[3] * pow(jet.pt()/1.e3, 3) + m_D2_params[4] * pow(jet.pt()/1.e3, 4);
577  m_D2Pivot(jet) = std::pair<float, std::string>(D2Cut, m_D2_cut_direction);
578  if((d2 > D2Cut && m_D2_cut_direction == "RIGHT") || (d2 < D2Cut && m_D2_cut_direction == "LEFT")){
579  if(m_verbose) printf(buffer.c_str(), APP_NAME, "failed", (m_D2_cut_direction == "RIGHT")?"above":"below", d2, D2Cut);
580  //return 0;
581  } else {
582  if(m_verbose) printf(buffer.c_str(), APP_NAME, "passed", (m_D2_cut_direction == "RIGHT")?"above":"below", d2, D2Cut);
583  pass_d2 = true;
584  }
585  } else {
586  if(m_verbose) printf("<%s>: No D2 cut has been requested here. The cut direction specified was %s which is not 'LEFT' or 'RIGHT'.\r\n", APP_NAME, m_D2_cut_direction.c_str());
587  }
588 
589  if(m_verbose) printf("<%s>: Jet is tagged as %s.\r\n", APP_NAME, m_boson_type.c_str());
590  //return 1;
591  return static_cast<int>((pass_mass << 2)|(pass_d2 << 1)|(pass_btag << 0));
592 
593 }
594 
595 std::vector<const xAOD::Jet*> BoostedXbbTag::get_bTagged_trackJets(const xAOD::Jet& jet) const {
596  std::vector<const xAOD::Jet*> associated_trackJets;
597  // get the track jets from the s_parent
598  (*s_parent(jet))->getAssociatedObjects<xAOD::Jet>("GhostAntiKt2TrackJet", associated_trackJets);
600  //jet.getAssociatedObjects<xAOD::Jet>("GhostAntiKt2TrackJet", associated_trackJets);
601  std::vector<const xAOD::Jet*> bTagged_trackJets;
602  for(const auto& trackJet: associated_trackJets){
603  if(m_isB(*trackJet) == 0) continue;
604  bTagged_trackJets.push_back(trackJet);
605  }
606  return bTagged_trackJets;
607 }
608 
609 std::vector<const xAOD::Muon*> BoostedXbbTag::get_matched_muons(const xAOD::Jet& jet) const {
610  std::vector<const xAOD::Muon*> muons;
611 
612  auto muonsLink = m_matchedMuonsLink(jet);
613  for(const auto& muonLink : muonsLink) {
614  if(!muonLink.isValid()) {
615  muons.push_back(nullptr);
616  }
617  else {
618  muons.push_back(static_cast<const xAOD::Muon*>(*muonLink));
619  }
620  }
621 
622  return muons;
623 }
624 
625 
626 TLorentzVector BoostedXbbTag::get_correctedJet_TLV(const xAOD::Jet& jet) const {
627  return m_correctedJetDecor(jet);
628 }
629 
630 std::pair<float, float> BoostedXbbTag::get_mass_window(const xAOD::Jet& jet) const {
631  return m_massWindow(jet);
632 }
633 
634 std::pair<float, std::string> BoostedXbbTag::get_D2_pivot(const xAOD::Jet& jet) const {
635  return m_D2Pivot(jet);
636 }
JetSubStructureUtils::BoostedXbbTag::get_correctedJet_TLV
TLorentzVector get_correctedJet_TLV(const xAOD::Jet &jet) const
Definition: BoostedXbbTag.cxx:626
BTaggingUtilities.h
JetSubStructureUtils::BoostedXbbTag::s_parent
static const SG::AuxElement::ConstAccessor< ElementLink< xAOD::JetContainer > > s_parent
Definition: BoostedXbbTag.h:114
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
JetSubStructureUtils::BoostedXbbTag::m_isB
const SG::AuxElement::Decorator< int > m_isB
Definition: BoostedXbbTag.h:117
JetSubStructureUtils::BoostedXbbTag::m_verbose
bool m_verbose
Definition: BoostedXbbTag.h:72
checkFileSG.line
line
Definition: checkFileSG.py:75
JetSubStructureUtils::BoostedXbbTag::s_D2
static const SG::AuxElement::ConstAccessor< float > s_D2
Definition: BoostedXbbTag.h:108
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
xAOD::JetInput::PFlow
@ PFlow
Definition: JetContainerInfo.h:62
BoostedXbbTag.h
JetSubStructureUtils::BoostedXbbTag::m_matchedMuonsLink
const SG::AuxElement::Decorator< std::vector< ElementLink< xAOD::IParticleContainer > > > m_matchedMuonsLink
Definition: BoostedXbbTag.h:118
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
xAOD::JetTransform::Type
Type
Enum for types of jet transformations.
Definition: JetContainerInfo.h:112
xAOD::JetAlgorithmType::kt_algorithm
@ kt_algorithm
Definition: JetContainerInfo.h:31
JetSubStructureUtils::BoostedXbbTag::s_ECF1
static const SG::AuxElement::ConstAccessor< float > s_ECF1
Definition: BoostedXbbTag.h:109
JetSubStructureUtils::BoostedXbbTag::s_PtFrac
static const SG::AuxElement::ConstAccessor< float > s_PtFrac
Definition: BoostedXbbTag.h:93
JetSubStructureUtils::BoostedXbbTag::m_D2Pivot
const SG::AuxElement::Decorator< std::pair< float, std::string > > m_D2Pivot
Definition: BoostedXbbTag.h:121
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
xAOD::JetInput::Track
@ Track
Definition: JetContainerInfo.h:61
CSV_InDetExporter.new
new
Definition: CSV_InDetExporter.py:145
skel.it
it
Definition: skel.GENtoEVGEN.py:423
JetSubStructureUtils::BoostedXbbTag::m_massWindow
const SG::AuxElement::Decorator< std::pair< float, float > > m_massWindow
Definition: BoostedXbbTag.h:120
JetSubStructureUtils::BoostedXbbTag::m_massMin
float m_massMin
Definition: BoostedXbbTag.h:76
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
JetSubStructureUtils::BoostedXbbTag::s_RClus
static const SG::AuxElement::ConstAccessor< float > s_RClus
Definition: BoostedXbbTag.h:92
JetSubStructureUtils::BoostedXbbTag::s_AlgorithmType
static const SG::AuxElement::ConstAccessor< int > s_AlgorithmType
Definition: BoostedXbbTag.h:86
JetSubStructureUtils::BoostedXbbTag::m_boson_type
std::string m_boson_type
Definition: BoostedXbbTag.h:67
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
JetSubStructureUtils::BoostedXbbTag::m_D2_params
std::vector< float > m_D2_params
Definition: BoostedXbbTag.h:78
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
JetSubStructureUtils::BoostedXbbTag::m_bTagCutCharm
float m_bTagCutCharm
Definition: BoostedXbbTag.h:75
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
CP
Select isolated Photons, Electrons and Muons.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:48
JetSubStructureUtils::BoostedXbbTag::get_algorithm_name
std::pair< bool, std::string > get_algorithm_name(const xAOD::Jet &jet, const xAOD::JetAlgorithmType::ID jet_algorithm, const float size_parameter, const xAOD::JetInput::Type jet_input, const xAOD::JetTransform::Type jet_transform) const
Definition: BoostedXbbTag.cxx:203
xAOD::JetInput::LCTopo
@ LCTopo
Definition: JetContainerInfo.h:55
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
JetSubStructureUtils::BoostedXbbTag::s_BDRS
static const SG::AuxElement::ConstAccessor< char > s_BDRS
Definition: BoostedXbbTag.h:101
JetSubStructureUtils
Definition: RCJet.h:49
JetSubStructureUtils::BoostedXbbTag::s_ECF3
static const SG::AuxElement::ConstAccessor< float > s_ECF3
Definition: BoostedXbbTag.h:111
xAOD::Jet_v1::getAssociatedObjects
std::vector< const T * > getAssociatedObjects(const std::string &name) const
get associated objects as a vector<object> this compact form throws an exception if the object is not...
JetSubStructureUtils::BoostedXbbTag::get_matched_muons
std::vector< const xAOD::Muon * > get_matched_muons(const xAOD::Jet &jet) const
Definition: BoostedXbbTag.cxx:609
JetSubStructureUtils::BoostedXbbTag::s_TransformType
static const SG::AuxElement::ConstAccessor< int > s_TransformType
Definition: BoostedXbbTag.h:89
JetSubStructureUtils::BoostedXbbTag::get_mass_window
std::pair< float, float > get_mass_window(const xAOD::Jet &jet) const
Definition: BoostedXbbTag.cxx:630
JetSubStructureUtils::BoostedXbbTag::m_algorithm_name
std::string m_algorithm_name
Definition: BoostedXbbTag.h:68
JetSubStructureUtils::BoostedXbbTag::s_ZCut
static const SG::AuxElement::ConstAccessor< float > s_ZCut
Definition: BoostedXbbTag.h:97
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:12
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
JetSubStructureUtils::BoostedXbbTag::m_muonSelectionTool
std::unique_ptr< CP::MuonSelectionTool > m_muonSelectionTool
Definition: BoostedXbbTag.h:80
lumiFormat.i
int i
Definition: lumiFormat.py:92
JetSubStructureUtils::BoostedXbbTag::m_massMax
float m_massMax
Definition: BoostedXbbTag.h:77
JetSubStructureUtils::BoostedXbbTag::result
int result(const xAOD::Jet &jet, const xAOD::MuonContainer *muons) const
Definition: BoostedXbbTag.cxx:301
PathResolverFindXMLFile
std::string PathResolverFindXMLFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:374
APP_NAME
#define APP_NAME
Definition: BoostedXbbTag.cxx:23
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
JetSubStructureUtils::BoostedXbbTag::BoostedXbbTag
BoostedXbbTag(const std::string &working_point="medium", const std::string &recommendations_file="JetSubStructureUtils/data/config_13TeV_Htagging_MC15c_77WP_20160522.dat", const std::string &boson_type="Higgs", const std::string &algorithm_name="AK10LCTRIMF5R20", int num_bTags=2, const std::string &decor_prefix="", bool debug=false, bool verbose=false)
Definition: BoostedXbbTag.cxx:45
AnalysisUtils::copy_if
Out copy_if(In first, const In &last, Out res, const Pred &p)
Definition: IFilterUtils.h:30
xAOD::JetInput::Truth
@ Truth
Definition: JetContainerInfo.h:59
xAOD::JetAlgorithmType::ID
ID
//////////////////////////////////////// JetAlgorithmType::ID defines most common physics jet finding...
Definition: JetContainerInfo.h:29
xAOD::BTagging_v1
Definition: BTagging_v1.h:39
xAOD::JetInput::Type
Type
Definition: JetContainerInfo.h:54
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
JetSubStructureUtils::BoostedXbbTag::s_RCut
static const SG::AuxElement::ConstAccessor< float > s_RCut
Definition: BoostedXbbTag.h:96
JetSubStructureUtils::BoostedXbbTag::m_D2_cut_direction
std::string m_D2_cut_direction
Definition: BoostedXbbTag.h:79
xAOD::JetTransform::MassDrop
@ MassDrop
Definition: JetContainerInfo.h:117
min
#define min(a, b)
Definition: cfImp.cxx:40
PathResolver.h
debug
const bool debug
Definition: MakeUncertaintyPlots.cxx:53
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
JetSubStructureUtils::BoostedXbbTag::m_debug
bool m_debug
Definition: BoostedXbbTag.h:71
JetSubStructureUtils::BoostedXbbTag::s_MuMax
static const SG::AuxElement::ConstAccessor< float > s_MuMax
Definition: BoostedXbbTag.h:105
JetSubStructureUtils::BoostedXbbTag::m_bTagCut
float m_bTagCut
Definition: BoostedXbbTag.h:74
xAOD::JetAlgorithmType::cambridge_algorithm
@ cambridge_algorithm
Definition: JetContainerInfo.h:32
JetSubStructureUtils::BoostedXbbTag::m_bad_configuration
bool m_bad_configuration
Definition: BoostedXbbTag.h:83
xAOD::JetAlgorithmType::antikt_algorithm
@ antikt_algorithm
Definition: JetContainerInfo.h:33
xAOD::JetInput::EMTopo
@ EMTopo
Definition: JetContainerInfo.h:56
xAOD::BTaggingUtilities::getBTagging
const BTagging * getBTagging(const SG::AuxElement &part)
Access the default xAOD::BTagging object associated to an object.
Definition: BTaggingUtilities.cxx:37
xAOD::JetTransform::Trim
@ Trim
Definition: JetContainerInfo.h:115
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
xAOD::JetTransform::Prune
@ Prune
Definition: JetContainerInfo.h:116
JetSubStructureUtils::BoostedXbbTag::m_recommendations_file
std::string m_recommendations_file
Definition: BoostedXbbTag.h:66
JetSubStructureUtils::BoostedXbbTag::s_SizeParameter
static const SG::AuxElement::ConstAccessor< float > s_SizeParameter
Definition: BoostedXbbTag.h:87
JetSubStructureUtils::BoostedXbbTag::s_InputType
static const SG::AuxElement::ConstAccessor< int > s_InputType
Definition: BoostedXbbTag.h:88
python.TriggerHandler.verbose
verbose
Definition: TriggerHandler.py:297
dq_defect_virtual_defect_validation.d2
d2
Definition: dq_defect_virtual_defect_validation.py:81
JetSubStructureUtils::BoostedXbbTag::get_bTagged_trackJets
std::vector< const xAOD::Jet * > get_bTagged_trackJets(const xAOD::Jet &jet) const
Definition: BoostedXbbTag.cxx:595
JetSubStructureUtils::BoostedXbbTag::m_correctedJetDecor
const SG::AuxElement::Decorator< TLorentzVector > m_correctedJetDecor
Definition: BoostedXbbTag.h:119
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
JetSubStructureUtils::BoostedXbbTag::s_YMin
static const SG::AuxElement::ConstAccessor< float > s_YMin
Definition: BoostedXbbTag.h:104
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
readCCLHist.float
float
Definition: readCCLHist.py:83
JetSubStructureUtils::BoostedXbbTag::m_working_point
std::string m_working_point
Definition: BoostedXbbTag.h:65
JetSubStructureUtils::BoostedXbbTag::get_D2_pivot
std::pair< float, std::string > get_D2_pivot(const xAOD::Jet &jet) const
Definition: BoostedXbbTag.cxx:634
JetSubStructureUtils::BoostedXbbTag::s_ECF2
static const SG::AuxElement::ConstAccessor< float > s_ECF2
Definition: BoostedXbbTag.h:110
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
xAOD::BTagging_v1::MVx_discriminant
bool MVx_discriminant(const std::string &taggername, double &value) const
Definition: BTagging_v1.cxx:381
JetSubStructureUtils::BoostedXbbTag::m_num_bTags
int m_num_bTags
Definition: BoostedXbbTag.h:69