ATLAS Offline Software
InDetTrackTruthOriginTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
7 
12 
13 #include <math.h>
14 
15 namespace InDet {
16 
17  InDetTrackTruthOriginTool::InDetTrackTruthOriginTool(const std::string& name) :
18  asg::AsgTool(name)
19  {
20 
21 #ifndef XAOD_STANDALONE
22  declareInterface<IInDetTrackTruthOriginTool>(this);
23 #endif
24 
25  declareProperty("matchingProbabilityCut", m_matchingProbabilityCut = 0.5);
26 
27  declareProperty("truthParticleLinkName", m_truthParticleLinkName = "truthParticleLink");
28  declareProperty("truthMatchProbabilityAuxName", m_truthMatchProbabilityAuxName = "truthMatchProbability");
29  declareProperty("isFullPileUpTruth", m_isFullPileupTruth = false);
30 
31  }
32 
33  InDetTrackTruthOriginTool::~InDetTrackTruthOriginTool() = default;
34 
36  if(m_isFullPileupTruth) ATH_MSG_INFO("InDetTrackTruthOriginTool configured for full pile-up truth sample");
37  return StatusCode::SUCCESS;
38  }
39 
41 
42  // if the track doesnt't have a valid truth link, skip to the next track
43  // in practice, all tracks seem to have a truth link, but we need to also
44  // check whether it's valid
46  static const SG::ConstAccessor<TruthLink>
47  truthParticleLinkAcc ("truthParticleLink");
48  if ( !truthParticleLinkAcc.isAvailable(*track) ) {
49  return nullptr;
50  }
51 
52  // retrieve the link and check its validity
53  const TruthLink &link = truthParticleLinkAcc(*track);
54 
55  // a missing or invalid link implies truth particle has been dropped from
56  // the truth record at some stage - probably it was from pilup which by
57  // default we don't store truth information for
58  if(!link or !link.isValid()) {
59  return nullptr;
60  }
61 
62  // seems safe to access and return the linked truth particle
63  return *link;
64  }
65 
67 
68  int origin = 0;
69 
70  // is it fragmentation? yes until proven otherwise
71  bool isFragmentation = true;
72 
73  // from B decay chain?
74  if(isFrom(truth, 5)) {
75  origin = origin | (0x1 << InDet::TrkOrigin::BHadronDecay);
76  isFragmentation = false;
77  }
78 
79  // from D decay chain?
80  if(isFrom(truth, 4)) {
81  origin = origin | (0x1 << InDet::TrkOrigin::DHadronDecay);
82  isFragmentation = false;
83  }
84 
85  // from tau decay chain?
86  if(isFrom(truth, 15)) {
87  origin = origin | (0x1 << InDet::TrkOrigin::TauDecay);
88  isFragmentation = false;
89  }
90 
91  // Secondary?
92  if (HepMC::is_simulation_particle(truth)) {
93 
94  // unknown origin (e.g. parent not in the record)
95  if(truth->nParents() != 1) {
96  origin = origin | (0x1 << InDet::TrkOrigin::OtherOrigin);
97  }
98 
99  else {
100  const xAOD::TruthParticle *parent = truth->parent(0);
101 
102  // in some cases particle has a parent, but that parent's barcode is zero
103  if(parent == nullptr) {
104  origin = origin | (0x1 << InDet::TrkOrigin::OtherOrigin);
105  }
106 
107  // sub-categorize secondaries which have one valid parent
108  else {
109 
110  int pdgId = truth->pdgId();
111  int parentId = parent->pdgId();
112 
113  // photon conversion
114  if(parent->isPhoton() && truth->isElectron()) {
115  origin = origin | (0x1 << InDet::TrkOrigin::GammaConversion);
116  }
117 
118  // Strange Mesons
119  else if(parent->isStrangeMeson() && parent->nChildren() == 2) {
120  origin = origin | (0x1 << InDet::TrkOrigin::StrangeMesonDecay);
121  // specifically Kshort
122  if (abs(pdgId) == 211 && parentId == 310) {
123  origin = origin | (0x1 << InDet::TrkOrigin::KshortDecay);
124  }
125  }
126 
127  // Strange Baryons
128  else if(parent->isStrangeBaryon() && parent->nChildren() == 2) {
129  origin = origin | (0x1 << InDet::TrkOrigin::StrangeBaryonDecay);
130  // specifically Lambdas
131  if ((abs(pdgId) == 211 || abs(pdgId) == 2212) && abs(parentId) == 3122) {
132  origin = origin | (0x1 << InDet::TrkOrigin::LambdaDecay);
133  }
134  }
135 
136  // other long living particle decays
137  else if(parent->isHadron() && parent->nChildren() == 2) {
138  origin = origin | (0x1 << InDet::TrkOrigin::OtherDecay);
139  }
140 
141  // hadronic interactions
142  else if(parent->nChildren() > 2) {
143  origin = origin | (0x1 << InDet::TrkOrigin::HadronicInteraction);
144  }
145 
146  // other secondaries
147  else {
148  origin = origin | (0x1 << InDet::TrkOrigin::OtherSecondary);
149  }
150  }
151  }
152 
153  isFragmentation = false;
154  }
155 
156  // uncategorized: call it fragmentation
157  if(isFragmentation) {
158  origin = origin | (0x1 << InDet::TrkOrigin::Fragmentation);
159  }
160 
161  return origin;
162  }
163 
165 
166  // get truth particle
167  const xAOD::TruthParticle* truth = getTruth( track );
168 
169  // get track TMP
171  float truthProb = tmpAcc( *track );
172 
173  int origin = 0;
174 
175  // truth link is broken: call it from pileup (not true for < 100 MeV and some specialised samples!)
176  if (!truth){
177  origin = origin | (0x1 << InDet::TrkOrigin::Pileup);
178  }
179 
180  // For full pile-up truth samples, check explicitly if truth record is present among hard-scatter collection to assign Pileup origin
181  else if(m_isFullPileupTruth){
182  const xAOD::TruthEventContainer* truthEventContainer(nullptr);
183  if(evtStore()->retrieve(truthEventContainer, "TruthEvents").isFailure()){
184  ATH_MSG_ERROR("InDetTrackTruthOriginTool configured for full pile-up truth but could not retrieve TruthEvents container");
185  }
186  const xAOD::TruthEvent* event = truthEventContainer ? truthEventContainer->at(0) : nullptr;
187 
188  if(event){
189  const auto& links = event->truthParticleLinks();
190 
191  bool isFromHSProdVtx = false;
192  for (const auto& link : links){
193  if(link.isValid() && truth == *link){
194  isFromHSProdVtx = true;
195  break;
196  }
197  }
198 
199  if(!isFromHSProdVtx) origin = origin | (0x1 << InDet::TrkOrigin::Pileup);
200  }
201  }
202 
203  // low TruthMatchProbability: call it fake (also includes poorly reconstructed tracks)
204  if(truthProb < m_matchingProbabilityCut) {
205  origin = origin | (0x1 << InDet::TrkOrigin::Fake);
206  }
207 
208  // truth link is present: find truth origin
209  if (truth) {
210  origin = origin | getTruthOrigin(truth);
211  }
212 
213  return origin;
214  }
215 
216  bool InDetTrackTruthOriginTool::isFrom(const xAOD::TruthParticle* truth, int flav) const {
217  return isFromRec( truth, flav, 0 );
218  }
219 
220  bool InDetTrackTruthOriginTool::isFromRec(const xAOD::TruthParticle* truth, int flav, int depth) const {
221 
222  if ( truth == nullptr ) return false;
223 
224  if ( depth > 30 ) return false;
225 
226  if( flav != 5 && flav != 4 && flav != 15 ) return false;
227 
228  if( flav == 5 && truth->isBottomHadron() ) return true;
229 
230  if( flav == 4 && truth->isCharmHadron() ) return true;
231 
232  if( flav == 15 && abs(truth->pdgId()) == 15 ) return true;
233 
234 
235  for(unsigned int p=0; p<truth->nParents(); p++) {
236  const xAOD::TruthParticle* parent = truth->parent(p);
237  if(parent == truth ) continue ; // avoid infinite recursion
238  if( isFromRec(parent, flav, depth+1) ) return true;
239  }
240 
241  return false;
242  }
243 
244  // Not used in getTruthOrigin anymore, kept for backwards compatibility
246 
247  // no parents? is anything even there?
248  if(truth->nParents() != 1) return -3;
249 
250  int pdgId = truth->pdgId();
251 
252  const xAOD::TruthParticle *parent = truth->parent(0);
253 
254  // in some files, the particle has a parent but that parent's barcode is zero.
255  // treat this as "other" (anything less than -2)
256  if (parent == nullptr) return -4;
257 
258  int parentId = parent->pdgId();
259 
260  // photon conversions:
261  if(parent->isPhoton() && truth->isElectron()) return parentId;
262 
263  // Kshort:
264  if(abs(pdgId) == 211 && parentId == 310 && parent->nChildren() == 2) return parentId;
265 
266  // Lambdas
267  if((abs(pdgId) == 211 || abs(pdgId) == 2212) && abs(parentId) == 3122 && parent->nChildren() == 2) return parentId;
268 
269  // other decays:
270  if(parent->isHadron() && parent->nChildren() == 2) return parentId;
271 
272  // hadronic interactions
273  if(parent->nChildren() > 2) return -1;
274 
275  // other secondaries: is anything even there??
276  return -2;
277  }
278 
279 }
InDet::TrkOrigin::StrangeMesonDecay
@ StrangeMesonDecay
Definition: InDetTrackTruthOriginDefs.h:23
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
xAOD::TruthParticle_v1::parent
const TruthParticle_v1 * parent(size_t i=0) const
Retrieve the i-th mother (TruthParticle) of this TruthParticle.
Definition: TruthParticle_v1.cxx:131
egammaParameters::depth
@ depth
pointing depth of the shower as calculated in egammaqgcld
Definition: egammaParamDefs.h:276
InDet::InDetTrackTruthOriginTool::m_truthMatchProbabilityAuxName
std::string m_truthMatchProbabilityAuxName
Definition: InDetTrackTruthOriginTool.h:59
xAOD::TruthParticle_v1::isElectron
bool isElectron() const
Whether the particle is an electron (or positron)
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
InDet::TrkOrigin::Pileup
@ Pileup
Definition: InDetTrackTruthOriginDefs.h:20
xAOD::TruthParticle_v1::isCharmHadron
bool isCharmHadron() const
Determine if the PID is that of a c-hadron.
InDet::InDetTrackTruthOriginTool::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: InDetTrackTruthOriginTool.cxx:35
InDet::InDetTrackTruthOriginTool::isFromRec
virtual bool isFromRec(const xAOD::TruthParticle *truth, int flav, int depth=0) const
recursion-safe(r) version of isFrom
Definition: InDetTrackTruthOriginTool.cxx:220
InDet
DUMMY Primary Vertex Finder.
Definition: VP1ErrorUtils.h:36
TruthParticleContainer.h
InDet::TrkOrigin::Fake
@ Fake
Definition: InDetTrackTruthOriginDefs.h:18
InDet::InDetTrackTruthOriginTool::m_matchingProbabilityCut
float m_matchingProbabilityCut
Definition: InDetTrackTruthOriginTool.h:56
TruthLink
ElementLink< xAOD::TruthParticleContainer > TruthLink
Definition: TruthRelatedMuonPlotOrganizer.cxx:12
InDet::TrkOrigin::TauDecay
@ TauDecay
Definition: InDetTrackTruthOriginDefs.h:26
asg
Definition: DataHandleTestTool.h:28
InDet::TrkOrigin::KshortDecay
@ KshortDecay
Definition: InDetTrackTruthOriginDefs.h:22
InDet::TrkOrigin::DHadronDecay
@ DHadronDecay
Definition: InDetTrackTruthOriginDefs.h:33
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
PowhegPy8EG_H2a.pdgId
dictionary pdgId
Definition: PowhegPy8EG_H2a.py:128
InDet::TrkOrigin::OtherOrigin
@ OtherOrigin
Definition: InDetTrackTruthOriginDefs.h:37
InDet::InDetTrackTruthOriginTool::getTrackOrigin
virtual int getTrackOrigin(const xAOD::TrackParticle *track) const override
Computes the track origin.
Definition: InDetTrackTruthOriginTool.cxx:164
AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Definition: AthCommonDataStore.h:85
xAOD::TruthParticle_v1::nParents
size_t nParents() const
Number of parents of this particle.
Definition: TruthParticle_v1.cxx:122
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
HepMC::is_simulation_particle
bool is_simulation_particle(const T &p)
Method to establish if a particle (or barcode) was created during the simulation (TODO update to be s...
Definition: MagicNumbers.h:299
InDet::InDetTrackTruthOriginTool::m_isFullPileupTruth
bool m_isFullPileupTruth
Definition: InDetTrackTruthOriginTool.h:61
InDet::TrkOrigin::BHadronDecay
@ BHadronDecay
Definition: InDetTrackTruthOriginDefs.h:32
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
DMTest::links
links
Definition: CLinks_v1.cxx:22
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:41
InDet::TrkOrigin::StrangeBaryonDecay
@ StrangeBaryonDecay
Definition: InDetTrackTruthOriginDefs.h:25
test_pyathena.parent
parent
Definition: test_pyathena.py:15
xAOD::TruthEvent_v1
Class describing a signal truth event in the MC record.
Definition: TruthEvent_v1.h:35
InDet::TrkOrigin::GammaConversion
@ GammaConversion
Definition: InDetTrackTruthOriginDefs.h:27
InDet::InDetTrackTruthOriginTool::isFrom
virtual bool isFrom(const xAOD::TruthParticle *truth, int flav) const override
Check if a truth particle is from the specified origin (from B or D hadron, or tau)
Definition: InDetTrackTruthOriginTool.cxx:216
InDet::TrkOrigin::LambdaDecay
@ LambdaDecay
Definition: InDetTrackTruthOriginDefs.h:24
InDet::TrkOrigin::OtherDecay
@ OtherDecay
Definition: InDetTrackTruthOriginDefs.h:28
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
xAOD::TruthParticle_v1::isBottomHadron
bool isBottomHadron() const
Determine if the PID is that of a b-hadron.
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MagicNumbers.h
InDet::InDetTrackTruthOriginTool::getParentID
int getParentID(const xAOD::TruthParticle *part) const
Definition: InDetTrackTruthOriginTool.cxx:245
InDetTrackTruthOriginTool.h
InDet::TrkOrigin::Fragmentation
@ Fragmentation
Definition: InDetTrackTruthOriginDefs.h:35
InDetTrackTruthOriginDefs.h
InDet::TrkOrigin::isFragmentation
bool isFragmentation(int origin)
not from B, D, or any secondary
Definition: InDetTrackTruthOriginDefs.h:143
InDet::InDetTrackTruthOriginTool::getTruth
virtual const xAOD::TruthParticle * getTruth(const xAOD::TrackParticle *track) const override
Safely access a track's linked truth particle, if available.
Definition: InDetTrackTruthOriginTool.cxx:40
InDet::TrkOrigin::OtherSecondary
@ OtherSecondary
Definition: InDetTrackTruthOriginDefs.h:30
xAOD::parentId
@ parentId
Definition: TrackingPrimitives.h:516
InDet::TrkOrigin::HadronicInteraction
@ HadronicInteraction
Definition: InDetTrackTruthOriginDefs.h:29
declareProperty
#define declareProperty(n, p, h)
Definition: BaseFakeBkgTool.cxx:15
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
DataVector::at
const T * at(size_type n) const
Access an element, as an rvalue.
ConstAccessor.h
Helper class to provide constant type-safe access to aux data.
TruthEventContainer.h
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
InDet::InDetTrackTruthOriginTool::getTruthOrigin
virtual int getTruthOrigin(const xAOD::TruthParticle *truth) const override
Computes the truth particle origin.
Definition: InDetTrackTruthOriginTool.cxx:66