ATLAS Offline Software
Loading...
Searching...
No Matches
JetTruthLabelingTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
13
15 asg::AsgTool(name)
16{}
17
19
20 ATH_MSG_INFO("Initializing " << name());
21
24 if(m_truthLabelName == "R10TruthLabel_R21Consolidated") {
25 m_truthJetCollectionName="AntiKt10TruthTrimmedPtFrac5SmallR20Jets";
27 m_dRTruthJet = 0.75;
28 m_useDRMatch = true;
29 m_dRTruthPart = 0.75;
30 m_useWZMassHigh = true;
31 m_mLowTop = 140.0;
32 m_mLowW = 50.0;
33 m_mHighW = 100.0;
34 m_mLowZ = 60.0;
35 m_mHighZ = 110.0;
37 }
39 else if(m_truthLabelName == "R10TruthLabel_R21Precision") {
40 m_truthJetCollectionName="AntiKt10TruthJets";
42 m_dRTruthJet = 0.75;
43 m_useDRMatch = false;
44 m_useWZMassHigh = true;
45 m_mLowTop = 140.0;
46 m_mLowW = 50.0;
47 m_mHighW = 100.0;
48 m_mLowZ = 60.0;
49 m_mHighZ = 110.0;
51 }
53 else if( m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" or m_truthLabelName == "R10TruthLabel_R22v1" ) {
54 m_truthJetCollectionName="AntiKt10TruthJets";
56 m_dRTruthJet = 0.75;
57 m_useDRMatch = false;
58 m_useWZMassHigh = false;
59 m_mLowTop = 140.0;
60 m_mLowW = 50.0;
61 m_mLowZ = 50.0;
62 if ( m_truthLabelName == "R10TruthLabel_R22v1" ) {
64 m_truthGroomedJetCollectionName = "AntiKt10TruthSoftDropBeta100Zcut10Jets";
65 } else {
67 }
68 }
70 else if( m_truthLabelName == "R10WZTruthLabel_R22v1" ) {
71 m_truthJetCollectionName="AntiKt10TruthDressedWZJets";
73 m_dRTruthJet = 0.75;
74 m_useDRMatch = false;
75 m_useWZMassHigh = false;
76 m_mLowTop = 140.0;
77 m_mLowW = 50.0;
78 m_mLowZ = 50.0;
80 m_truthGroomedJetCollectionName = "AntiKt10TruthDressedWZSoftDropBeta100Zcut10Jets";
81 }
82
83 print();
84
86
87 bool isSupportedLabel = false;
88 isSupportedLabel = isSupportedLabel || (m_truthLabelName=="R10TruthLabel_R21Consolidated");
89 isSupportedLabel = isSupportedLabel || (m_truthLabelName=="R10TruthLabel_R21Precision");
90 isSupportedLabel = isSupportedLabel || (m_truthLabelName=="R10TruthLabel_R21Precision_2022v1");
91 isSupportedLabel = isSupportedLabel || (m_truthLabelName=="R10TruthLabel_R22v1");
92 isSupportedLabel = isSupportedLabel || (m_truthLabelName=="R10WZTruthLabel_R22v1");
93
94 if(!isSupportedLabel) {
95 ATH_MSG_ERROR("TruthLabelName " << m_truthLabelName << " is not supported. Exiting...");
96 return StatusCode::FAILURE;
97 }
98
105 m_split12_truthKey = m_truthJetCollectionName.key() + ".Split12";
106 m_split23_truthKey = m_truthJetCollectionName.key() + ".Split23";
107
108 if(!m_isTruthJetCol){
115 m_truthSplit12_recoKey = m_jetContainerName + "." + m_truthLabelName + "_TruthJetSplit12";
116 m_truthSplit23_recoKey = m_jetContainerName + "." + m_truthLabelName + "_TruthJetSplit23";
119 m_truthGroomedJetMass_recoKey = m_jetContainerName + "." + m_truthLabelName + "_TruthGroomedJetMass";
120 m_truthGroomedJetPt_recoKey = m_jetContainerName + "." + m_truthLabelName + "_TruthGroomedJetPt";
121 }
122
123 ATH_CHECK(m_evtInfoKey.initialize());
129
130 ATH_CHECK(m_label_truthKey.initialize());
135 ATH_CHECK(m_NB_truthKey.initialize());
136
137 ATH_CHECK(m_split12_truthKey.initialize(m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" || m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1"));
138 ATH_CHECK(m_split23_truthKey.initialize(m_truthLabelName == "R10TruthLabel_R21Precision" || m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" || m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1"));
139
146 ATH_CHECK(m_truthSplit12_recoKey.initialize(!m_isTruthJetCol && (m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" || m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1") ));
147 ATH_CHECK(m_truthSplit23_recoKey.initialize(!m_isTruthJetCol && (m_truthLabelName == "R10TruthLabel_R21Precision" || m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" || m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1")));
150
153
154 return StatusCode::SUCCESS;
155}
156
158 ATH_MSG_INFO("Parameters for " << name());
159
160 ATH_MSG_INFO("xAOD information:");
161 ATH_MSG_INFO("TruthLabelName: " << m_truthLabelName);
162 ATH_MSG_INFO("UseTRUTH3: " << ( m_useTRUTH3 ? "True" : "False"));
163
164 if(m_useTRUTH3) {
165 ATH_MSG_INFO("TruthBosonContainerName: " << m_truthBosonContainerName);
166 ATH_MSG_INFO("TruthTopQuarkContainerName: " << m_truthTopQuarkContainerName);
167 }
168 else {
169 ATH_MSG_INFO("TruthParticleContainerName: " << m_truthParticleContainerName);
170 }
171
172 ATH_MSG_INFO("TruthJetCollectionName: " << m_truthJetCollectionName.key());
173 ATH_MSG_INFO("dRTruthJet: " << std::to_string(m_dRTruthJet));
174
175 if ( m_useDRMatch ) {
176 ATH_MSG_INFO("dRTruthPart: " << std::to_string(m_dRTruthPart));
177 }
178
179 ATH_MSG_INFO("mLowTop: " << std::to_string(m_mLowTop));
180 ATH_MSG_INFO("mLowW: " << std::to_string(m_mLowW));
182 ATH_MSG_INFO("mHighW: " << std::to_string(m_mHighW));
183 ATH_MSG_INFO("mLowZ: " << std::to_string(m_mLowZ));
185 ATH_MSG_INFO("mHighZ: " << std::to_string(m_mHighZ));
186
188 ATH_MSG_INFO("truthGroomedJetCollectionName: " << m_truthGroomedJetCollectionName.key());
189 }
190}
191
192
194 (const JetTruthLabelingTool& tool, const EventContext& ctx)
195{
196 auto maybeInit = [&] (auto& h,
198 {
199 if (!k.key().empty()) h.emplace (k, ctx);
200 };
201 maybeInit (labelHandle, tool.m_label_truthKey);
202 maybeInit (nbHandle, tool.m_NB_truthKey);
203 maybeInit (labelRecoHandle, tool.m_label_recoKey);
204 maybeInit (nbRecoHandle, tool.m_NB_recoKey);
205 maybeInit (dRWHandle, tool.m_dR_W_truthKey);
206 maybeInit (dRZHandle, tool.m_dR_Z_truthKey);
207 maybeInit (dRHHandle, tool.m_dR_H_truthKey);
208 maybeInit (dRTopHandle, tool.m_dR_Top_truthKey);
209 maybeInit (dRWRecoHandle, tool.m_dR_W_recoKey);
210 maybeInit (dRZRecoHandle, tool.m_dR_Z_recoKey);
211 maybeInit (dRHRecoHandle, tool.m_dR_H_recoKey);
212 maybeInit (dRTopRecoHandle, tool.m_dR_Top_recoKey);
213 maybeInit (split23Handle, tool.m_truthSplit23_recoKey);
214 maybeInit (split12Handle, tool.m_truthSplit12_recoKey);
215 maybeInit (truthMassHandle, tool.m_truthJetMass_recoKey);
216 maybeInit (truthPtHandle, tool.m_truthJetPt_recoKey);
217 maybeInit (truthGroomedMassHandle, tool.m_truthGroomedJetMass_recoKey);
218 maybeInit (truthGroomedPtHandle, tool.m_truthGroomedJetPt_recoKey);
219}
220
222 const xAOD::Jet &jet,
223 const std::vector<std::pair<TLorentzVector,int> >& tlv_truthParts,
224 const EventContext& ctx) const {
225
227 bool matchW = false;
228 bool matchZ = false;
229 bool matchH = false;
230 bool matchTop = false;
231
233 float dR_W = 9999;
234 float dR_Z = 9999;
235 float dR_H = 9999;
236 float dR_Top = 9999;
237
238 for (const auto& tlv_truth : tlv_truthParts) {
239 float dR = tlv_truth.first.DeltaR(jet.p4());
240 if( dR < m_dRTruthPart ) {
241
242 if ( MC::isZ(tlv_truth.second) && !matchZ ) {
243 dR_Z = dR;
244 matchZ = true;
245 }
246
247 if ( MC::isW(tlv_truth.second) && !matchW ) {
248 dR_W = dR;
249 matchW = true;
250 }
251
252 if ( MC::isHiggs(tlv_truth.second) && !matchH ) {
253 dR_H = dR;
254 matchH = true;
255 }
256
257 if ( MC::isTop(tlv_truth.second) && !matchTop ) {
258 dR_Top = dR;
259 matchTop = true;
260 }
261
262 }
263 }
264
266 (*dh.dRWHandle)(jet) = dR_W;
267 (*dh.dRZHandle)(jet) = dR_Z;
268 (*dh.dRHHandle)(jet) = dR_H;
269 (*dh.dRTopHandle)(jet) = dR_Top;
270
271 return getLabel( dh, jet, matchH, matchW, matchZ, matchTop, ctx );
272
273}
274
276 const xAOD::Jet &jet,
277 const EventContext& ctx ) const
278{
280 bool matchW = false;
281 bool matchZ = false;
282 bool matchH = false;
283 bool matchTop = false;
284
286 int nMatchW = getNGhostParticles( jet, "GhostWBosons" );
287
288 if ( nMatchW ) {
289 matchW = true;
290 }
291
293 int nMatchZ = getNGhostParticles( jet, "GhostZBosons" );
294
295 if ( nMatchZ ) {
296 matchZ = true;
297 }
298
300 int nMatchH = getNGhostParticles( jet, "GhostHBosons" );
301
302 if ( nMatchH ) {
303 matchH = true;
304 }
305
307 int nMatchTop = getNGhostParticles( jet, "GhostTQuarksFinal" );
308
309 if ( nMatchTop ) {
310 matchTop = true;
311 }
312
313 return getLabel( dh, jet, matchH, matchW, matchZ, matchTop, ctx );
314
315}
316
318 const EventContext& ctx = Gaudi::Hive::currentContext();
319 DecorHandles dh (*this, ctx);
320
322 if(m_isTruthJetCol) {
323 return labelTruthJets(dh, jets, ctx);
324 }
325
327 else {
328 ATH_CHECK( labelTruthJets(dh, ctx) );
329 return labelRecoJets(dh, jets, ctx);
330 }
331
332 return StatusCode::SUCCESS;
333}
334
336 const xAOD::JetContainer& jets,
337 const EventContext& ctx) const {
338
340 SG::ReadHandle<xAOD::JetContainer> truthGroomedJets;
342 truthGroomedJets = SG::makeHandle(m_truthGroomedJetCollectionName, ctx);
343 }
345 static const SG::ConstAccessor< ElementLink< xAOD::JetContainer > > ParentAcc ("Parent");
346 for(const xAOD::Jet *jet : jets) {
347
349 const xAOD::Jet* parent = nullptr;
351 ElementLink<xAOD::JetContainer> element_link = ParentAcc (*jet);
352 if ( element_link.isValid() ) {
353 parent = *element_link;
354 }
355 else {
356 ATH_MSG_ERROR("Unable to get a link to the parent jet! Returning a NULL pointer.");
357 return StatusCode::FAILURE;
358 }
359 }
360
362 float dRmin = 9999;
363 const xAOD::Jet* matchTruthJet = nullptr;
364 float dRminGroomed = 9999;
365 const xAOD::Jet* matchTruthGroomedJet = nullptr;
366
367 // Ensure that the reco jet has at least one constituent
368 // (and thus a well-defined four-vector)
369 if(jet->numConstituents() > 0){
370 for ( const xAOD::Jet* truthJet : *truthJets ) {
371 float dR = jet->p4().DeltaR( truthJet->p4() );
373 if ( parent ) dR = parent->p4().DeltaR( truthJet->p4() );
375 if ( m_dRTruthJet < 0 || dR < m_dRTruthJet ) {
376 if ( dR < dRmin ) {
377 dRmin = dR;
378 matchTruthJet = truthJet;
379 }
380 }
381 }
382 }
383
385 float dR_truthJet_W = 9999;
386 float dR_truthJet_Z = 9999;
387 float dR_truthJet_Top = 9999;
388 float dR_truthJet_H = 9999;
389 int truthJetNB = -1;
390 float truthJetSplit12 = -9999;
391 float truthJetSplit23 = -9999;
392 float truthJetMass = -9999;
393 float truthJetPt = -9999;
394
395 if ( matchTruthJet ) {
396 // Can't use the WriteDecorHandle to read --- the decoration may have
397 // been added and locked by a previous algorithm.
398 SG::ConstAccessor<int> labelAcc (dh.labelHandle->auxid());
399 label = labelAcc(*matchTruthJet);
400 if ( m_useDRMatch ) {
401 if(dh.dRWHandle->isAvailable()) dR_truthJet_W = (*dh.dRWHandle)(*matchTruthJet);
402 if(dh.dRZHandle->isAvailable()) dR_truthJet_Z = (*dh.dRZHandle)(*matchTruthJet);
403 if(dh.dRHHandle->isAvailable()) dR_truthJet_H = (*dh.dRHHandle)(*matchTruthJet);
404 if(dh.dRTopHandle->isAvailable()) dR_truthJet_Top = (*dh.dRTopHandle)(*matchTruthJet);
405 }
406 if ( m_truthLabelName == "R10TruthLabel_R21Precision" ) {
408 if(split23Handle.isAvailable()) truthJetSplit23 = split23Handle(*matchTruthJet);
409 }
410 if ( m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" || m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1" ) {
412 if(split23Handle.isAvailable()) truthJetSplit23 = split23Handle(*matchTruthJet);
414 if(split12Handle.isAvailable()) truthJetSplit12 = split12Handle(*matchTruthJet);
415 }
416 if(nbAcc.isAvailable(*matchTruthJet)) truthJetNB = nbAcc (*matchTruthJet);
417 truthJetMass = matchTruthJet->m();
418 truthJetPt = matchTruthJet->pt();
419 }
420
421 // Save Groomed Truth Jet variables
422 float truthGroomedJetMass = -9999;
423 float truthGroomedJetPt = -9999;
425 if ( matchTruthJet ) {
426 for ( const xAOD::Jet* truthGroomedJet : *truthGroomedJets ) {
427 ElementLink<xAOD::JetContainer> element_link = ParentAcc (*truthGroomedJet);
428 if ( !element_link.isValid() ) { continue; }
429 if ( matchTruthJet == *element_link ) {
430 matchTruthGroomedJet = truthGroomedJet;
431 break;
432 }
433 }
434 }
435 // If no matched jet found or matched jet has no corresponding groomed jet, use dR matching
436 if ( !matchTruthGroomedJet ) {
437 for ( const xAOD::Jet* truthGroomedJet : *truthGroomedJets ) {
438 float dR = jet->p4().DeltaR( truthGroomedJet->p4() );
440 if ( m_dRTruthJet < 0 || dR < m_dRTruthJet ) {
441 if ( dR < dRminGroomed ) {
442 dRminGroomed = dR;
443 matchTruthGroomedJet = truthGroomedJet;
444 }
445 }
446 }
447 }
448 if ( matchTruthGroomedJet ) {
449 truthGroomedJetMass = matchTruthGroomedJet->m();
450 truthGroomedJetPt = matchTruthGroomedJet->pt();
451 }
452 }
453
455 (*dh.labelRecoHandle)(*jet) = label;
456
458 if ( m_useDRMatch ) {
459 (*dh.dRWRecoHandle)(*jet) = dR_truthJet_W;
460 (*dh.dRZRecoHandle)(*jet) = dR_truthJet_Z;
461 (*dh.dRHRecoHandle)(*jet) = dR_truthJet_H;
462 (*dh.dRTopRecoHandle)(*jet) = dR_truthJet_Top;
463 }
464 if ( m_truthLabelName == "R10TruthLabel_R21Precision" ) {
465 (*dh.split23Handle)(*jet) = truthJetSplit23;
466 }
467
468 if ( m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" || m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1" ) {
469 (*dh.split23Handle)(*jet) = truthJetSplit23;
470 (*dh.split12Handle)(*jet) = truthJetSplit12;
471 }
472
473 (*dh.nbRecoHandle)(*jet) = truthJetNB;
474 (*dh.truthMassHandle)(*jet) = truthJetMass;
475 (*dh.truthPtHandle)(*jet) = truthJetPt;
476
478 (*dh.truthGroomedMassHandle)(*jet) = truthGroomedJetMass;
479 (*dh.truthGroomedPtHandle)(*jet) = truthGroomedJetPt;
480 }
481 }
482
483 return StatusCode::SUCCESS;
484}
485
487 const EventContext& ctx) const {
488
491
493 if ( !truthJets.isValid() ) {
494 ATH_MSG_ERROR("No truth jet container retrieved. Please make sure you are using a supported TruthLabelName.");
495 return StatusCode::FAILURE;
496 }
497
498 return labelTruthJets(dh, *truthJets, ctx);
499
500}
501
503 const xAOD::JetContainer &truthJets,
504 const EventContext& ctx) const
505{
507 if ( !(truthJets.size()) ) return StatusCode::SUCCESS;
508
510 if(dh.labelHandle->isAvailable()){
511 // Beware: if we get here, the configuration is probably not MT-compatible.
512 ATH_MSG_DEBUG("labelTruthJets: Truth jet collection already labelled with " << m_truthLabelName);
513 return StatusCode::SUCCESS;
514 }
515
517 int channelNumber = -999;
518
521 if(!eventInfo.isValid()){
522 ATH_MSG_ERROR("Failed to retrieve event information.");
523 return StatusCode::FAILURE;
524 }
525
527 std::vector<std::pair<TLorentzVector,int> > tlv_truthParts;
528
530 if ( m_useDRMatch ) {
531
532 channelNumber = eventInfo->mcChannelNumber();
533
534 if ( channelNumber < 0 ) {
535 ATH_MSG_ERROR("Channel number was not set correctly");
536 return StatusCode::FAILURE;
537 }
538
540 bool isSherpa = getIsSherpa(channelNumber);
541
542 if ( m_useTRUTH3 && isSherpa ) {
543 ATH_MSG_ERROR("Cannot apply truth labels to Sherpa 2.2.1 samples using TRUTH3 containers");
544 return StatusCode::FAILURE;
545 }
546
548 if( m_useTRUTH3 ) {
551 if(!truthPartsBoson.isValid()){
552 ATH_MSG_ERROR("Unable to find " << m_truthBosonContainerName.key() << ". Please check the content of your input file.");
553 return StatusCode::FAILURE;
554 }
557 if(!truthPartsTop.isValid()){
558 ATH_MSG_ERROR("Unable to find " << m_truthTopQuarkContainerName.key() << ". Please check the content of your input file.");
559 return StatusCode::FAILURE;
560 }
562 getTLVs(tlv_truthParts, truthPartsBoson.cptr(), truthPartsTop.cptr(), isSherpa);
563 }
564
566 else {
568 if(!truthParts.isValid()){
569 ATH_MSG_ERROR("Unable to find " << m_truthParticleContainerName << ". Please check the content of your input file.");
570 return StatusCode::FAILURE;
571 }
573 getTLVs(tlv_truthParts, truthParts.cptr(), truthParts.cptr(), isSherpa);
574 }
575 }
576
579 for ( const xAOD::Jet *jet : truthJets ) {
580
581 if ( m_useDRMatch ) {
582 ATH_MSG_DEBUG("Getting truth label using dR matching");
583 label = getTruthJetLabelDR(dh, *jet, tlv_truthParts, ctx);
584 }
585
586 else {
587 ATH_MSG_DEBUG("Getting truth label using ghost-association");
588 label = getTruthJetLabelGA(dh, *jet, ctx);
589 }
590
591 (*dh.labelHandle)(*jet) = label;
592 }
593
594 return StatusCode::SUCCESS;
595}
596
597void JetTruthLabelingTool::getTLVs( std::vector<std::pair<TLorentzVector,int> > &tlvs, const xAOD::TruthParticleContainer *truthBosons, const xAOD::TruthParticleContainer *truthTop, bool isSherpa ) const {
598
599 tlvs.clear();
600
602 if(isSherpa) {
603 int countStatus3 = 0;
604
606 TLorentzVector p1(0,0,0,0);
607 TLorentzVector p2(0,0,0,0);
608
610 TLorentzVector WZCand(0,0,0,0);
611
613 bool isWPCand = false;
614 bool isWMCand = false;
615 bool isZCand = false;
616
618 bool inMassWindow = false;
619
620 for ( unsigned int ipart = 0; ipart < truthBosons->size(); ipart++ ){
621
622 const xAOD::TruthParticle* part1 = truthBosons->at(ipart);
623
625 if ( MC::isPhysical(part1) ) continue;
626
628 if ( std::abs(part1->pdgId()) > MC::BQUARK ) continue;
629
630 countStatus3++;
632 if ( countStatus3 > 3 ) continue;
634 p1 = part1->p4();
635
637 for ( unsigned int jpart = ipart+1; jpart < truthBosons->size(); jpart++ ) {
638
639 const xAOD::TruthParticle* part2 = truthBosons->at(jpart);
640
642 if ( MC::isPhysical(part2) ) continue;
643
645 if ( std::abs(part2->pdgId()) > MC::BQUARK ) continue;
646
647 p2 = part2->p4();
648
650 if ( part1->pdgId() + part2->pdgId() == 0 ) {
651 isZCand = true;
652 }
654 else if ( part1->pdgId() == MC::UQUARK || part1->pdgId() == MC::CQUARK || part2->pdgId() == MC::UQUARK || part2->pdgId() == MC::CQUARK ) {
655 isWPCand = true;
656 }
658 else {
659 isWMCand = true;
660 }
661
663 break;
664
665 }
666
667 WZCand = p1 + p2;
668
670 if ( 60000 < WZCand.M() && WZCand.M() < 140000. ) {
671 inMassWindow = true;
672 break;
673 }
674
675 }
676
677 if ( inMassWindow && (isWPCand || isWMCand || isZCand) ) {
678 std::pair<TLorentzVector,int> WZ;
679 if ( isZCand ) {
680 WZ = std::make_pair(WZCand,23);
681 }
682 if ( isWPCand ) {
683 WZ = std::make_pair(WZCand,24);
684 }
685 if ( isWMCand ) {
686 WZ = std::make_pair(WZCand,-24);
687 }
688 tlvs.push_back(WZ);
689 }
690
691 }
692
694 for ( const xAOD::TruthParticle* part : *truthBosons ) {
697 tlvs.push_back(std::make_pair(part->p4(),part->pdgId()));
698 }
699
701 for ( const xAOD::TruthParticle* part : *truthTop ) {
702 if ( !selectTruthParticle(part,MC::TQUARK) ) continue;
704 tlvs.push_back(std::make_pair(part->p4(),part->pdgId()));
705 }
706
707}
708
710 if ( std::abs(tp->pdgId()) != pdgId ) return false;
711 for ( unsigned int iChild = 0; iChild < tp->nChildren(); iChild++ ) {
712 const xAOD::TruthParticle *child = tp->child(iChild);
713 if ( !child ) continue;
714 if ( child->pdgId() == tp->pdgId() ) return false;
715 }
716 return true;
717}
718
720
723
724 float split12 = -999.0;
725
726 if ( m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" || m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1") {
727 const float c0 = 55.25;
728 const float c1 = -2.34e-3;
729
730 split12 = c0 * std::exp( c1 * pt );
731 }
732
733 return split12;
734
735}
736
738
741
742 float split23 = -999.0;
743
744 if ( m_truthLabelName == "R10TruthLabel_R21Precision" ||
745 m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" ||
746 m_truthLabelName == "R10TruthLabel_R22v1" ||
747 m_truthLabelName == "R10WZTruthLabel_R22v1") {
748
749 const float c0 = 3.3;
750 const float c1 = -6.98e-4;
751
752 split23 = std::exp( c0 + c1 * pt );
753
754 }
755
756 return split23;
757}
758
759int JetTruthLabelingTool::getNGhostParticles( const xAOD::Jet &jet, std::string collection ) const {
760
761 int nMatchPart = 0;
762
763 if( !jet.getAttribute<int>( collection+"Count", nMatchPart ) ){
764
765 std::vector<const xAOD::TruthParticle*> ghostParts;
766 if( !jet.getAssociatedObjects<xAOD::TruthParticle>( collection, ghostParts ) ){
767 ATH_MSG_ERROR( collection + " cannot be retrieved! Truth label definition might be wrong" );
768 }
769 nMatchPart = ghostParts.size();
770 }
771
772 return nMatchPart;
773}
774
776 const xAOD::Jet &jet,
777 bool matchH,
778 bool matchW,
779 bool matchZ,
780 bool matchTop,
781 const EventContext& ctx) const {
782
783 // store GhostBHadronsFinal count
784 int nMatchB = getNGhostParticles( jet, "GhostBHadronsFinal" );
785 (*dh.nbHandle)(jet) = nMatchB;
786
788 bool is_bb = false;
789 bool is_cc = false;
790 bool is_tautauEl = false;
791 bool is_tautauMu = false;
792 bool is_tautauHad = false;
793 bool isTop = false;
794 bool isW = false;
795 bool isZ = false;
796
798 if ( m_truthLabelName == "R10TruthLabel_R21Consolidated" ) {
799 is_bb = ( nMatchB > 1 );
800 isTop = ( matchTop && nMatchB > 0 && jet.m() / 1000. > m_mLowTop );
801 isW = matchW && nMatchB == 0 && jet.m() / 1000. > m_mLowW && jet.m() / 1000. < m_mHighW;
802 isZ = matchZ && jet.m() / 1000. > m_mLowZ && jet.m() / 1000. < m_mHighZ;
803 }
804
806 if ( m_truthLabelName == "R10TruthLabel_R21Precision" ) {
808 is_bb = ( nMatchB > 1 );
809 isTop = ( matchTop && matchW && nMatchB > 0 && jet.m() / 1000. > m_mLowTop && split23Handle(jet) / 1000. > getTopSplit23Cut( jet.pt() / 1000. ) );
810 isW = matchW && nMatchB == 0 && jet.m() / 1000. > m_mLowW && jet.m() / 1000. < m_mHighW;
811 isZ = matchZ && jet.m() / 1000. > m_mLowZ && jet.m() / 1000. < m_mHighZ;
812 }
813
814 // Use R21Precision_2022v1 definition
815 if ( m_truthLabelName == "R10TruthLabel_R21Precision_2022v1" ) {
818 is_bb = ( nMatchB > 1 );
819 isTop = ( matchTop && matchW && nMatchB > 0 && jet.m() / 1000. > m_mLowTop && split23Handle(jet) / 1000. > getTopSplit23Cut( jet.pt() / 1000. ) );
820 isW = matchW && nMatchB == 0 && jet.m() / 1000. > m_mLowW && split12Handle(jet) / 1000. > getWZSplit12Cut( jet.pt() / 1000. );
821 isZ = matchZ && jet.m() / 1000. > m_mLowZ && split12Handle(jet) / 1000. > getWZSplit12Cut( jet.pt() / 1000. );
822 }
823
824 // Use R10TruthLabel_R22v1 definition
825 if ( m_truthLabelName == "R10TruthLabel_R22v1" || m_truthLabelName == "R10WZTruthLabel_R22v1") {
826 // get extended ghost associated truth label
827 int extended_GA_label = -1;
828 if (not jet.getAttribute("HadronGhostExtendedTruthLabelID", extended_GA_label)) {
829 ATH_MSG_ERROR( "HadronGhostExtendedTruthLabelID not available for " + m_truthJetCollectionName.key() );
830 }
831
834 is_bb = ( extended_GA_label == 55 );
835 is_cc = ( extended_GA_label == 44 );
836 is_tautauEl = ( extended_GA_label == 151511 );
837 is_tautauMu = ( extended_GA_label == 151513 );
838 is_tautauHad = ( extended_GA_label == 1515 );
839 isTop = ( matchTop && matchW && nMatchB > 0 && jet.m() / 1000. > m_mLowTop && split23Handle(jet) / 1000. > getTopSplit23Cut( jet.pt() / 1000. ) );
840 isW = matchW && nMatchB == 0 && jet.m() / 1000. > m_mLowW && split12Handle(jet) / 1000. > getWZSplit12Cut( jet.pt() / 1000. );
841 isZ = matchZ && jet.m() / 1000. > m_mLowZ && split12Handle(jet) / 1000. > getWZSplit12Cut( jet.pt() / 1000. );
842 }
843
844
846
847 /* The default priority of labels is:
848 * 1) Hbb/cc/tautau
849 * 2) Contained top
850 * 3) Contained W
851 * 4) Contained Zbb/cc/qq/tautau
852 * 5) Uncontained top
853 * 6) Uncontained V
854 */
855
857 if( !(matchTop || matchW || matchZ || matchH) ) {
859 }
860
861 // Higgs
862 if ( matchH ) {
864 if ( is_bb ) return LargeRJetTruthLabel::Hbb;
866 if ( is_cc ) return LargeRJetTruthLabel::Hcc;
868 if ( is_tautauEl ) return LargeRJetTruthLabel::HtautauEl;
869 if ( is_tautauMu ) return LargeRJetTruthLabel::HtautauMu;
870 if ( is_tautauHad ) return LargeRJetTruthLabel::HtautauHad;
873 }
874
876 if ( isTop ) return LargeRJetTruthLabel::tqqb;
877
878 if ( isW ) {
880 if ( matchTop ) return LargeRJetTruthLabel::Wqq_From_t;
883 }
884
885 if ( matchZ ) {
887 if ( is_bb ) return LargeRJetTruthLabel::Zbb;
889 if ( is_cc ) return LargeRJetTruthLabel::Zcc;
891 if ( is_tautauEl ) return LargeRJetTruthLabel::ZtautauEl;
892 if ( is_tautauMu ) return LargeRJetTruthLabel::ZtautauMu;
893 if ( is_tautauHad ) return LargeRJetTruthLabel::ZtautauHad;
894 }
895 if ( isZ ) {
898 }
899
901 if ( matchTop ) return LargeRJetTruthLabel::other_From_t;
902
905
906}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading a decoration on an object.
Handle class for reading from StoreGate.
Handle class for adding a decoration to an object.
bool isW(const T &p)
Definition AtlasPID.h:382
bool isZ(const T &p)
Definition AtlasPID.h:379
bool isTop(const T &p)
Definition AtlasPID.h:185
Helper class to provide constant type-safe access to aux data.
ATLAS-specific HepMC functions.
Header file for AthHistogramAlgorithm.
const T * at(size_type n) const
Access an element, as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
Gaudi::Property< std::string > m_jetContainerName
Gaudi::Property< std::string > m_truthLabelName
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthTopQuarkContainerName
double m_mHighZ
Lower mass cut for Z label.
bool m_getTruthGroomedJetValues
Use the ungroomed reco jet parent to match to truth jet.
double m_mLowZ
Upper mass cut for W label.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_truthJetMass_recoKey
double m_dRTruthPart
dR to match truth jet to reco jet
SG::WriteDecorHandleKey< xAOD::JetContainer > m_NB_truthKey
StatusCode labelRecoJets(DecorHandles &dh, const xAOD::JetContainer &jets, const EventContext &ctx) const
Apply labels to all jets in a container.
float getTopSplit23Cut(float pt) const
Get top label Split23 cut.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_label_recoKey
StatusCode labelTruthJets(DecorHandles &dh, const EventContext &ctx) const
Label truth jet collection.
double m_mLowTop
dR to match truth particles to truth jet
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthBosonContainerName
Gaudi::Property< bool > m_useTRUTH3
TRUTH1 or TRUTH3.
void print() const override
Print configured parameters.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_truthJetPt_recoKey
bool selectTruthParticle(const xAOD::TruthParticle *tp, int pdgId) const
Check if truth particle has correct DSID and isn't self decay.
int getTruthJetLabelGA(DecorHandles &dh, const xAOD::Jet &jet, const EventContext &ctx) const
Get truth label using ghost-associated particles.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_truthGroomedJetPt_recoKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_H_recoKey
Gaudi::Property< bool > m_isTruthJetCol
void getTLVs(std::vector< std::pair< TLorentzVector, int > > &tlvs, const xAOD::TruthParticleContainer *truthBosons, const xAOD::TruthParticleContainer *truthTop, bool isSherpa=false) const
Extract heavy particle 4-vectors from truth record.
SG::ReadHandleKey< xAOD::JetContainer > m_truthGroomedJetCollectionName
int getLabel(DecorHandles &dh, const xAOD::Jet &jet, bool matchH, bool matchW, bool matchZ, bool matchTop, const EventContext &ctx) const
Get label based on matching and containment criteria.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_truthSplit23_recoKey
bool m_useWZMassHigh
Use dR to match partons to truth jet.
float getWZSplit12Cut(float pt) const
Get W/Z label Split12 cut.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_H_truthKey
int getNGhostParticles(const xAOD::Jet &jet, std::string collection) const
Get number of ghost associated particles.
SG::ReadDecorHandleKey< xAOD::JetContainer > m_split23_truthKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_Top_recoKey
SG::ReadDecorHandleKey< xAOD::JetContainer > m_split12_truthKey
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleContainerName
SG::WriteDecorHandleKey< xAOD::JetContainer > m_truthSplit12_recoKey
SG::ReadHandleKey< xAOD::EventInfo > m_evtInfoKey
int getTruthJetLabelDR(DecorHandles &dh, const xAOD::Jet &jet, const std::vector< std::pair< TLorentzVector, int > > &tlv_truthParts, const EventContext &ctx) const
Get truth label using dR-matched particles.
bool m_matchUngroomedParent
Use upper mass cut for W/Z labels.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_Z_recoKey
JetTruthLabelingTool(const std::string &name="JetTruthLabelingTool")
default constructor - to be used in all derived classes
SG::WriteDecorHandleKey< xAOD::JetContainer > m_label_truthKey
StatusCode decorate(const xAOD::JetContainer &jets) const override
decorate truth label to a jet collection
SG::ReadHandleKey< xAOD::JetContainer > m_truthJetCollectionName
parameters for truth labeling
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_Z_truthKey
double m_mLowW
Lower mass cut for top label.
SG::WriteDecorHandleKey< xAOD::JetContainer > m_NB_recoKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_W_truthKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_truthGroomedJetMass_recoKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_W_recoKey
SG::WriteDecorHandleKey< xAOD::JetContainer > m_dR_Top_truthKey
bool getIsSherpa(const int DSID) const
Check for Sherpa DSIDs.
double m_dRTruthJet
When truth jet matching to ungroomed truth, allow saving properties of groomed truth jets.
double m_mHighW
Lower mass cut for W label.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
Handle class for reading a decoration on an object.
bool isAvailable()
Test to see if this variable exists in the store, for the referenced object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
Property holding a SG store/key/clid/attr name from which a WriteDecorHandle is made.
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition Jet_v1.cxx:44
virtual double m() const
The invariant mass of the particle.
Definition Jet_v1.cxx:59
int pdgId() const
PDG ID code.
std::string label(const std::string &format, int i)
Definition label.h:19
int enumToInt(const TypeEnum type)
static const int UQUARK
bool isZ(const T &p)
static const int Z0BOSON
static const int CQUARK
bool isW(const T &p)
static const int TQUARK
bool isTop(const T &p)
static const int HIGGSBOSON
static const int BQUARK
bool isHiggs(const T &p)
APID: HIGGS boson is only one particle.
static const int WPLUSBOSON
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition part1.py:1
Definition part2.py:1
Jet_v1 Jet
Definition of the current "jet version".
TruthParticle_v1 TruthParticle
Typedef to implementation.
JetContainer_v1 JetContainer
Definition of the current "jet container version".
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.
DecorHandles(const JetTruthLabelingTool &tool, const EventContext &ctx)