ATLAS Offline Software
Loading...
Searching...
No Matches
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
25using namespace JetSubStructureUtils;
26
27// make all static accessors static to this file, like extern but hip
44
45BoostedXbbTag::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),
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")),
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",
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
182 if(m_bad_configuration){
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
203std::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 {
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"},
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
352int 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
595std::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
609std::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
627 return m_correctedJetDecor(jet);
628}
629
630std::pair<float, float> BoostedXbbTag::get_mass_window(const xAOD::Jet& jet) const {
631 return m_massWindow(jet);
632}
633
634std::pair<float, std::string> BoostedXbbTag::get_D2_pivot(const xAOD::Jet& jet) const {
635 return m_D2Pivot(jet);
636}
#define APP_NAME
std::pair< std::vector< unsigned int >, bool > res
const bool debug
DataVector< IParticle > IParticleContainer
std::string PathResolverFindXMLFile(const std::string &logical_file_name)
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
const SG::AuxElement::Decorator< TLorentzVector > m_correctedJetDecor
static const SG::AuxElement::ConstAccessor< int > s_TransformType
std::vector< const xAOD::Muon * > get_matched_muons(const xAOD::Jet &jet) const
std::vector< const xAOD::Jet * > get_bTagged_trackJets(const xAOD::Jet &jet) const
static const SG::AuxElement::ConstAccessor< float > s_RClus
TLorentzVector get_correctedJet_TLV(const xAOD::Jet &jet) const
static const SG::AuxElement::ConstAccessor< ElementLink< xAOD::JetContainer > > s_parent
static const SG::AuxElement::ConstAccessor< float > s_RCut
static const SG::AuxElement::ConstAccessor< float > s_SizeParameter
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
static const SG::AuxElement::ConstAccessor< float > s_ECF2
static const SG::AuxElement::ConstAccessor< int > s_InputType
std::pair< float, std::string > get_D2_pivot(const xAOD::Jet &jet) const
static const SG::AuxElement::ConstAccessor< float > s_PtFrac
const SG::AuxElement::Decorator< std::pair< float, float > > m_massWindow
static const SG::AuxElement::ConstAccessor< char > s_BDRS
const SG::AuxElement::Decorator< int > m_isB
static const SG::AuxElement::ConstAccessor< int > s_AlgorithmType
std::unique_ptr< CP::MuonSelectionTool > m_muonSelectionTool
const SG::AuxElement::Decorator< std::vector< ElementLink< xAOD::IParticleContainer > > > m_matchedMuonsLink
const SG::AuxElement::Decorator< std::pair< float, std::string > > m_D2Pivot
int result(const xAOD::Jet &jet, const xAOD::MuonContainer *muons) const
static const SG::AuxElement::ConstAccessor< float > s_MuMax
static const SG::AuxElement::ConstAccessor< float > s_ZCut
static const SG::AuxElement::ConstAccessor< float > s_ECF3
static const SG::AuxElement::ConstAccessor< float > s_D2
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)
std::pair< float, float > get_mass_window(const xAOD::Jet &jet) const
static const SG::AuxElement::ConstAccessor< float > s_YMin
static const SG::AuxElement::ConstAccessor< float > s_ECF1
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:570
STL class.
STL class.
bool MVx_discriminant(const std::string &taggername, double &value) const
Class providing the definition of the 4-vector interface.
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...
bool verbose
Definition hcg.cxx:73
Select isolated Photons, Electrons and Muons.
Forward declaration.
STL namespace.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
const BTagging * getBTagging(const SG::AuxElement &part)
Access the default xAOD::BTagging object associated to an object.
ID
//////////////////////////////////////// JetAlgorithmType::ID defines most common physics jet finding...
Type
Enum for types of jet transformations.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Jet_v1 Jet
Definition of the current "jet version".
BTagging_v1 BTagging
Definition of the current "BTagging version".
Definition BTagging.h:17
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".