ATLAS Offline Software
Loading...
Searching...
No Matches
FatVertex.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
8
9#include <stdexcept>
10
11namespace ParticleJetTools {
12 namespace FatVertex {
13
14 TLorentzVector sum_4vec(const std::vector<const xAOD::TruthParticle*>& parts) {
15 TLorentzVector sum;
16 for ( auto part : parts ) {
17 if ( !part ) continue;
18 sum += part->p4();
19 }
20 return sum;
21 }
22
24 if ( part->nChildren() == 0 ) { return 0; }
25 if ( !part->hasDecayVtx() || !part->decayVtx() ) { return 0; }
26 int num_valid = 0;
27 for ( auto child : part->decayVtx()->particles_out() ) {
28 if ( child ) num_valid++;
29 }
30 return num_valid;
31 }
32
34 if ( part->nChildren() == 0 ) { return false; }
35 if ( !part->hasDecayVtx() || !part->decayVtx() ) { return false; }
36 for ( auto child : part->decayVtx()->particles_out() ) {
37 if ( child ) return true;
38 }
39 return false;
40 }
41
42 std::vector<const xAOD::TruthParticle*> get_valid_children_by_pt(const xAOD::TruthParticle* part) {
43 std::vector<const xAOD::TruthParticle*> children;
44 if ( !part->hasDecayVtx() || !part->decayVtx() ) return children;
45 for ( auto child : part->decayVtx()->particles_out() ) {
46 if ( child ) children.push_back(child);
47 }
48 std::sort(children.begin(), children.end(),
49 [](const xAOD::TruthParticle* a, const xAOD::TruthParticle* b) { return a->pt() > b->pt(); });
50 return children;
51 }
52
54 if ( !v1 || !v2 ) return NAN;
55 return std::sqrt(
56 std::pow(v1->x() - v2->x(), 2) + std::pow(v1->y() - v2->y(), 2) +
57 std::pow(v1->z() - v2->z(), 2)
58 );
59 }
60
62 if ( !v1 || !v2 ) return NAN;
63 return std::sqrt(
64 std::pow(v1->x() - v2->x(), 2) + std::pow(v1->y() - v2->y(), 2)
65 );
66 }
67
78 const xAOD::TruthVertex* vertex,
79 std::vector<const xAOD::TruthParticle*>& fat_inparts,
80 std::vector<const xAOD::TruthParticle*>& fat_internal,
81 std::vector<const xAOD::TruthParticle*>& fat_outparts,
82 bool internal,
83 const float truthVertexMergeDistance,
84 const std::vector<const xAOD::TruthParticle*>& additional_in_parts
85 ) {
86 if ( !vertex ) return;
87 std::vector<const xAOD::TruthParticle*> out_particles = vertex->particles_out();
88 std::vector<const xAOD::TruthParticle*> in_particles = vertex->particles_in();
89
90 for(auto part : additional_in_parts){
91 if(part){
92 if (std::find(in_particles.begin(), in_particles.end(), part) == in_particles.end()){
93 in_particles.push_back(part);
94 }
95
96 if(part->hasDecayVtx() && part->decayVtx()){
97 for(auto child : part->decayVtx()->particles_out()){
98 if(child && std::find(out_particles.begin(), out_particles.end(), child) == out_particles.end()){
99 out_particles.push_back(child);
100 }
101 }
102 }
103 }
104 }
105 for ( auto part : in_particles ) {
106 if ( !part ) continue;
107 // Check that the current particle being checked is not already in the fat vertex
108 if ( std::find(fat_inparts.begin(), fat_inparts.end(), part) == fat_inparts.end()
109 && std::find(fat_internal.begin(), fat_internal.end(), part) == fat_internal.end()
110 && std::find(fat_outparts.begin(), fat_outparts.end(), part) == fat_outparts.end() ) {
111 // If 'internal' is false, we treat any 'internal' parts of a process as inputs
112 if ( internal ) fat_internal.push_back(part);
113 else fat_inparts.push_back(part);
114 }
115 }
116 for ( auto part : out_particles ) {
117 if ( !part ) continue;
118 if (
119 std::find(fat_inparts.begin(), fat_inparts.end(), part) != fat_inparts.end() ||
120 std::find(fat_internal.begin(), fat_internal.end(), part) != fat_internal.end() ||
121 std::find(fat_outparts.begin(), fat_outparts.end(), part) != fat_outparts.end()
122 ) continue;
123 // Simulation particles (status != 1,2) without a usable decay vertex:
124 // add as outparts (they're stable children of the current vertex).
125 // Sim particles WITH a decay vertex fall through to normal processing
126 // (merge distance check, single-child skip, outpart logic).
127 if (!(part->status() == 1 || part->status() == 2)){
128 if (!part->hasDecayVtx() || !part->decayVtx() || !has_valid_child(part)) {
129 fat_outparts.push_back(part);
130 continue;
131 }
132 }
133
134 // We have a particle which says it has a child, but its invalid -> end state particle,
135 // ->we add it to the outputs
136 if ( !has_valid_child(part) || !(part->hasDecayVtx() && part->decayVtx()) ) {
137 fat_outparts.push_back(part);
138 continue;
139 }
140
141 if(
142 !fat_inparts.empty() &&
143 part->hasDecayVtx() && part->decayVtx() &&
144 fat_inparts[0]->hasDecayVtx() && fat_inparts[0]->decayVtx() &&
145 vertex_distance(part->decayVtx(), fat_inparts[0]->decayVtx()) < truthVertexMergeDistance
146 ){
148 part->decayVtx(), fat_inparts, fat_internal, fat_outparts, true, truthVertexMergeDistance
149 );
150 continue;
151 }
152
153 // Check valid children sorted by pT
154 std::vector<const xAOD::TruthParticle*> valid_children = get_valid_children_by_pt(part);
155
156 // Single valid child with same pdgId = simple scattering (e- -> e-, pi -> pi)
157 // Not a reconstructable vertex — absorb as internal and continue
158 if ( valid_children.size() == 1 &&
159 valid_children[0]->pdgId() == part->pdgId() ) {
161 part->decayVtx(), fat_inparts, fat_internal, fat_outparts, true,
162 truthVertexMergeDistance
163 );
164 continue;
165 }
166
167 // Multiple children but highest-pT has same pdgId = brem/scattering + radiation
168 // (e- -> e- + gamma). The leading child is the same particle continuing —
169 // absorb as internal so the vertex is attributed to where it actually interacts
170 if ( valid_children.size() >= 2 &&
171 valid_children[0]->pdgId() == part->pdgId() ) {
173 part->decayVtx(), fat_inparts, fat_internal, fat_outparts, true,
174 truthVertexMergeDistance
175 );
176 continue;
177 }
178
179 // Strange hadron oscillation (K0 -> K0bar etc)
180 if ( valid_children.size() == 1 &&
181 part->isStrangeHadron() && valid_children[0]->isStrangeHadron() ) {
183 part->decayVtx(), fat_inparts, fat_internal, fat_outparts, true,
184 truthVertexMergeDistance
185 );
186 continue;
187 }
188 fat_outparts.push_back(part);
189 }
190 }
191
192 std::vector<FatVertex> generateFatVertices(
193 const xAOD::TruthVertex* pv,
194 const float truthVertexMergeDistance,
195 const std::vector<const xAOD::TruthParticle*>& truth_particles
196 ) {
197 std::vector<FatVertex> fat_vertices;
198 std::vector<const xAOD::TruthParticle*> searched;
199 std::vector<const xAOD::TruthParticle*> to_search;
200
201 to_search.push_back(pv->incomingParticle(0));
202
203 bool is_pv = true;
204 while ( !to_search.empty() ) {
205 const xAOD::TruthParticle* part = to_search.back();
206
207 to_search.pop_back();
208 searched.push_back(part);
209 if (!part || !part->hasDecayVtx() ) continue;
210 // If the particles first child is invalid, then all are, and we can skip it...
211 if(num_valid_children(part) == 0){
212 continue;
213 }
214 std::vector<const xAOD::TruthParticle*> inparts, internal, outparts;
216 part->decayVtx(), inparts, internal, outparts,
217 false, truthVertexMergeDistance,
218 is_pv ? truth_particles : std::vector<const xAOD::TruthParticle*>(0, nullptr)
219 );
220 // A vertex requires multiple outgoing particles. Accept if either:
221 // - multiple outparts survived thinning, OR
222 // - the inpart's nChildren >= 2 (truth record says real multi-body
223 // decay/interaction, even if some children were thinned)
224 bool is_real_vertex = outparts.size() > 1;
225 if (!is_real_vertex && !inparts.empty() && inparts[0] && inparts[0]->nChildren() >= 2) {
226 is_real_vertex = true;
227 }
228 if ( is_real_vertex ){
229 fat_vertices.push_back(FatVertex(inparts, internal, outparts, is_pv));
230 is_pv = false;
231 }
232
233 // Once a fat-vertex is completed, we ensure we don't search any of its particles
234 // again
235 for ( auto inp : inparts ) {
236 if ( std::find(searched.begin(), searched.end(), inp) == searched.end() ) {
237 searched.push_back(inp);
238 }
239 if(std::find(to_search.begin(), to_search.end(), inp) != to_search.end()){
240 to_search.erase(
241 std::remove(to_search.begin(), to_search.end(), inp),
242 to_search.end());
243 }
244 }
245 for ( auto intern : internal ) {
246 if ( std::find(searched.begin(), searched.end(), intern) == searched.end() ) {
247 searched.push_back(intern);
248 }
249 if(std::find(to_search.begin(), to_search.end(), intern) != to_search.end()){
250 to_search.erase(
251 std::remove(to_search.begin(), to_search.end(), intern),
252 to_search.end());
253 }
254 }
255 for ( auto outp : outparts ) {
256 if ( std::find(searched.begin(), searched.end(), outp) == searched.end()
257 && std::find(to_search.begin(), to_search.end(), outp) == to_search.end() ) {
258 to_search.push_back(outp);
259 }
260 }
261 }
262
263 // Iterate all fat vertices, and remove any with 0 out particles, as these are actually
264 // just stable particles
265 fat_vertices.erase(
267 fat_vertices.begin(),
268 fat_vertices.end(),
269 [](const FatVertex& fv) {
270 return fv.outparts.empty();
271 }
272 ),
273 fat_vertices.end()
274 );
275
276 return fat_vertices;
277 }
278
279
280 float FatVertex::getPT() const {
281 if ( inparts.size() == 1 ) { return inparts[0]->pt(); }
282 return sum_4vec(inparts).Pt();
283 }
284
285 int FatVertex::getNumChargedDecays(float minPt) const {
286 int num_charged = 0;
287 for ( auto part : outparts ) {
288 if ( part->isCharged() && part->pt() >= minPt ) num_charged++;
289 }
290 return num_charged;
291 }
292
293 int FatVertex::getNumNeutralDecays(float minPt, bool include_neutrinos) const {
294 int num_neutral = 0;
295 for ( auto part : outparts ) {
296 if ( part->isNeutral() && part->pt() >= minPt && (include_neutrinos || !part->isNeutrino()) )
297 num_neutral++;
298 }
299 return num_neutral;
300 }
301
303 const SG::ConstAccessor<int>& uid_accessor
304 ) const {
306 if ( inparts.size() != 1 ) return DetailedVertexType::OtherNInparts;
307 if ( outparts.empty() ) return DetailedVertexType::OtherNoOutparts;
308
309 // Get first valid child
310 const xAOD::TruthParticle* input_child = nullptr;
311 for (auto child : inparts[0]->decayVtx()->particles_out()) {
312 if (child) { input_child = child; break; }
313 }
314 if ( !input_child ) return DetailedVertexType::Other;
315
316 bool has_parent = parent != nullptr;
317 DetailedVertexType parent_type = has_parent
318 ? parent->getType(uid_accessor).detailedType
320
321 // Heavy flavor: B and C hadron decays
323 if ( inparts[0]->isCharmHadron() ) {
324 if (has_parent && parent_type == DetailedVertexType::BHadronDecay)
327 }
328
329 // Tau decay (can fall through if it's tau bremsstrahlung that doesn't match)
330 if ( inparts[0]->isTau() ) {
331 if (auto t = classifyTauVertex(parent_type, has_parent)) return *t;
332 }
333
334 // Compute shared context for remaining classifiers
335 size_t truth_out_parts = inparts[0]->nChildren();
336 size_t truth_valid_out_parts = num_valid_children(inparts[0]);
337 std::vector<const xAOD::TruthParticle*> truth_children;
338 for ( auto child : inparts[0]->decayVtx()->particles_out() ) {
339 if ( child ) truth_children.push_back(child);
340 }
341 TLorentzVector in4 = inparts[0]->p4();
342 TLorentzVector out4 = sum_4vec(inparts[0]->decayVtx()->particles_out());
343 float deltaE = std::abs(in4.E() - out4.E());
344
345 // Energy-based material interaction (all valid children, large energy loss)
346 if ( truth_out_parts == truth_valid_out_parts && truth_valid_out_parts > 1 ) {
347 if ( deltaE > 100.0 ) return DetailedVertexType::MaterialInteraction;
348 }
349
350 // Mass-based material interaction: if the sum of children rest masses
351 // exceeds the parent rest mass, mass was created from kinetic energy
352 // via nuclear interaction with detector material. In a genuine decay,
353 // parent >= sum(m_children) always holds by conservation.
354 if ( truth_valid_out_parts > 1 ) {
355 double children_mass_sum = 0.0;
356 for (const auto& child : truth_children) {
357 children_mass_sum += child->p4().M();
358 }
359 if ( children_mass_sum > in4.M() + 1.0 ) { // 1 MeV tolerance
361 }
362 }
363
364 // Strange hadron
365 if ( inparts[0]->isStrangeHadron() ) {
366 if (auto t = classifyStrangeVertex(parent_type, has_parent)) return *t;
367 }
368
369 // Photon (conversion, photoelectric, compton)
370 if ( inparts[0]->isPhoton() ) {
371 if (auto t = classifyPhotonVertex(truth_out_parts, truth_valid_out_parts, truth_children)) return *t;
372 }
373
374 // Charged lepton (bremsstrahlung, e+e- annihilation, material interaction)
375 if ( inparts[0]->isChLepton() ) {
376 if (auto t = classifyLeptonVertex(uid_accessor, truth_out_parts, truth_valid_out_parts, truth_children)) return *t;
377 }
378
379 // Pion decay: pi0 -> gamma gamma is always a decay.
380 // Charged pi -> mu + nu: check for muon+neutrino signature.
381 // Anything else from a charged pion (hadronic products, nuclear
382 // fragments) is a material interaction.
383 if ( std::abs(inparts[0]->pdgId()) == 111 ) {
385 }
386 if ( std::abs(inparts[0]->pdgId()) == 211 ) {
387 bool has_muon = false, has_neutrino = false;
388 for (auto c : truth_children) {
389 if (std::abs(c->pdgId()) == 13) has_muon = true;
390 if (std::abs(c->pdgId()) == 14) has_neutrino = true;
391 }
392 if (has_muon && has_neutrino) return DetailedVertexType::PionDecay;
394 }
395
396 // Fallback: simulation particle with missing children
397 if ( truth_out_parts > truth_valid_out_parts && truth_out_parts > 1 &&
398 inparts[0]->child(0) && HepMC::is_simulation_particle(inparts[0]->child(0)) ) {
400 }
401
402 // Single output particle fallbacks
403 if ( truth_out_parts == 1 && truth_valid_out_parts == 1 ) {
404 if ( deltaE > 10 ) return DetailedVertexType::MaybeMaterialInteraction;
406 }
407
409 }
410
411 std::optional<DetailedVertexType> FatVertex::classifyTauVertex(
412 DetailedVertexType parent_type, bool has_parent
413 ) const {
414 int num_child_taus = 0;
415 int num_child_photons = 0;
416 for ( auto child : outparts ) {
417 if ( child->isTau() ) num_child_taus++;
418 else if ( child->isPhoton() ) num_child_photons++;
419 }
420 if ( num_child_taus == 0 ) {
421 if (has_parent && parent_type == DetailedVertexType::BHadronDecay)
424 }
425 if ( num_child_taus == 1 && num_child_photons == 1 )
427 return std::nullopt;
428 }
429
430 std::optional<DetailedVertexType> FatVertex::classifyStrangeVertex(
431 DetailedVertexType parent_type, bool has_parent
432 ) const {
433 if ( outparts.size() == 1 && outparts[0]->isStrangeHadron() )
435 if ( !has_parent ) return DetailedVertexType::StrangeDecay;
436 switch (parent_type) {
447 default:
449 }
450 }
451
452 std::optional<DetailedVertexType> FatVertex::classifyPhotonVertex(
453 size_t truth_out_parts, size_t truth_valid_out_parts,
454 const std::vector<const xAOD::TruthParticle*>& truth_children
455 ) const {
456 // Gamma -> e+e- : Conversion
457 if ( outparts.size() == 2 && outparts[0]->isChLepton() && outparts[1]->isChLepton() &&
458 (outparts[0]->pdgId() + outparts[1]->pdgId()) == 0 ) {
460 }
461 // Conversion from truth children (handles cases where fat vertex merging changed outparts)
462 if ( truth_valid_out_parts == 2 &&
463 (truth_children[0]->pdgId() + truth_children[1]->pdgId()) == 0 ) {
465 }
466 // Photon -> single electron: photoelectric emission
467 if ( std::abs(outparts[0]->pdgId()) == 11 ) {
469 }
470 // Conversion where one lepton was absorbed by material
471 if ( outparts.size() == 1 && internal.size() == 1 &&
472 internal[0]->isChLepton() && outparts[0]->isChLepton() ) {
474 }
475 // Conversion with missing truth record for one lepton
476 if ( outparts.size() == 1 && internal.empty() && truth_out_parts == 2 &&
477 truth_valid_out_parts == 1 && outparts[0]->isChLepton() ) {
479 }
480 // gamma -> gamma + e : Compton scattering
481 if ( outparts.size() == 2 &&
482 ((outparts[0]->isPhoton() && outparts[1]->pdgId() == 11) ||
483 (outparts[1]->isPhoton() && outparts[0]->pdgId() == 11)) ) {
485 }
486 // Catch-all for photon vertices with 3+ outparts containing electrons:
487 // conversion + bremsstrahlung merged by fat vertex builder
488 for (auto p : outparts) {
489 if (p && p->isChLepton()) return DetailedVertexType::Conversion;
490 }
491 // Photon interaction with no electrons — generic material interaction
493 }
494
495 std::optional<DetailedVertexType> FatVertex::classifyLeptonVertex(
496 const SG::ConstAccessor<int>& uid_accessor,
497 size_t truth_out_parts, size_t truth_valid_out_parts,
498 const std::vector<const xAOD::TruthParticle*>& truth_children
499 ) const {
500 // Standard lep->lep+gamma : Bremsstrahlung
501 if ( outparts.size() == 2 &&
502 ((outparts[0]->isPhoton() && outparts[1]->isChLepton()) ||
503 (outparts[1]->isPhoton() && outparts[0]->isChLepton())) ) {
505 }
506 // e->e+gamma but the electron doesn't stay in the truth record
507 if ( (truth_out_parts == 2 || truth_out_parts == 1) && truth_valid_out_parts == 1 &&
508 outparts[0]->isPhoton() ) {
510 }
511 // l -> gamma + l which is still brem
512 if ( truth_valid_out_parts == 2 &&
513 ((truth_children[0]->isPhoton() && truth_children[1]->pdgId() == inparts[0]->pdgId()) ||
514 (truth_children[1]->isPhoton() && truth_children[0]->pdgId() == inparts[0]->pdgId())) ) {
516 }
517 // e+ e- annihilation: e+ -> gamma gamma
518 if ( inparts[0]->pdgId() == -11 && outparts.size() == 2 &&
519 outparts[0]->isPhoton() && outparts[1]->isPhoton() ) {
521 }
522 // e+ -> gamma (boosted, partner low energy)
523 if ( inparts[0]->pdgId() == -11 && outparts.size() == 1 &&
524 outparts[0]->isPhoton() ) {
526 }
527 // e+ -> child is single photon
528 if ( inparts[0]->pdgId() == -11 && inparts[0]->nChildren() == 1 &&
529 inparts[0]->child(0)->isPhoton() ) {
531 }
532 // Lepton scattering via Geant (same base UID → material interaction)
533 int in_base_bar = uid_accessor(*inparts[0]) % HepMC::SIM_REGENERATION_INCREMENT;
534 if ( truth_valid_out_parts == 2 && truth_out_parts == 2 &&
535 (in_base_bar == uid_accessor(*outparts[0]) % HepMC::SIM_REGENERATION_INCREMENT ||
536 in_base_bar == uid_accessor(*outparts[1]) % HepMC::SIM_REGENERATION_INCREMENT) ) {
538 }
539 return std::nullopt;
540 }
541
542 bool FatVertex::operator<(const FatVertex& other) const {
543 if ( inparts.size() != other.inparts.size() )
544 return inparts.size() < other.inparts.size();
545 if ( internal.size() != other.internal.size() )
546 return internal.size() < other.internal.size();
547 if ( outparts.size() != other.outparts.size() )
548 return outparts.size() < other.outparts.size();
549 return getPT() < other.getPT();
550 }
551
552 bool FatVertex::operator==(const FatVertex& other) const {
553 return this->inparts == other.inparts && this->internal == other.internal &&
554 this->outparts == other.outparts;
555 }
556
557
558 void FatVertex::doParentChildLinks(std::vector<FatVertex>& vertices) {
559 // Iterates through all the vertices to set parent and children
560
561 FatVertex* found_parent = nullptr;
562 std::vector<const FatVertex*> found_children;
563
564 for (auto& vertex2 : vertices) {
565 if ( this == &vertex2) continue; // Compare addresses, not objects
566
567 // Check if any of vertex2's outputs match vertex's inputs
568 if (std::find(vertex2.outparts.begin(), vertex2.outparts.end(), inparts[0]) != vertex2.outparts.end()) {
569 if (found_parent) {
570 throw std::runtime_error("Multiple parents detected for a vertex");
571 }
572 found_parent = &vertex2;
573 }
574
575 // Check if vertex2 is a child
576 if (std::find(outparts.begin(), outparts.end(), vertex2.inparts[0]) != outparts.end()) {
577 found_children.push_back(&vertex2);
578 }
579 }
580
581 parent = found_parent;
582 children = std::move(found_children);
583 }
584 } // End of FatVertex namespace
585} // End of ParticleJetTools namespace
bool isTau(const T &p)
Definition AtlasPID.h:208
bool isChLepton(const T &p)
APID: the fourth generation leptons are leptons.
Definition AtlasPID.h:199
bool isStrangeHadron(const T &p)
Definition AtlasPID.h:910
bool isBottomHadron(const T &p)
Definition AtlasPID.h:912
bool isPhoton(const T &p)
Definition AtlasPID.h:376
bool isCharmHadron(const T &p)
Definition AtlasPID.h:911
ATLAS-specific HepMC functions.
static Double_t a
Helper class to provide constant type-safe access to aux data.
float z() const
Vertex longitudinal distance along the beam line form the origin.
float y() const
Vertex y displacement.
float x() const
Vertex x displacement.
std::ostream * outp
send output to here ...
Definition hcg.cxx:78
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...
constexpr int SIM_REGENERATION_INCREMENT
Constant defining the barcode threshold for regenerated particles, i.e. particles surviving an intera...
bool has_valid_child(const xAOD::TruthParticle *part)
Definition FatVertex.cxx:33
TLorentzVector sum_4vec(const std::vector< const xAOD::TruthParticle * > &parts)
Definition FatVertex.cxx:14
float vertex_distance(const xAOD::TruthVertex *v1, const xAOD::TruthVertex *v2)
Definition FatVertex.cxx:53
std::vector< const xAOD::TruthParticle * > get_valid_children_by_pt(const xAOD::TruthParticle *part)
Definition FatVertex.cxx:42
void generateFatVertex(const xAOD::TruthVertex *vertex, std::vector< const xAOD::TruthParticle * > &fat_inparts, std::vector< const xAOD::TruthParticle * > &fat_internal, std::vector< const xAOD::TruthParticle * > &fat_outparts, bool internal, const float truthVertexMergeDistance, const std::vector< const xAOD::TruthParticle * > &additional_in_parts=std::vector< const xAOD::TruthParticle * >())
Generates a fat vertex by recursively searching children of the provided truth vertex and adding them...
Definition FatVertex.cxx:77
int num_valid_children(const xAOD::TruthParticle *part)
Definition FatVertex.cxx:23
float vertex_distance_xy(const xAOD::TruthVertex *v1, const xAOD::TruthVertex *v2)
Definition FatVertex.cxx:61
std::vector< FatVertex > generateFatVertices(const xAOD::TruthVertex *pv, const float truthVertexMergeDistance, const std::vector< const xAOD::TruthParticle * > &truth_particles)
DataModel_detail::iterator< DVL > remove(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, const T &value)
Specialization of remove for DataVector/List.
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.
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition TruthVertex.h:15
TruthParticle_v1 TruthParticle
Typedef to implementation.
void doParentChildLinks(std::vector< FatVertex > &vertices)
VertexType getType(const SG::ConstAccessor< int > &uid_accessor) const
bool operator<(const FatVertex &other) const
int getNumChargedDecays(float minPt=0.0) const
std::vector< const xAOD::TruthParticle * > inparts
Definition FatVertex.h:121
FatVertex(std::vector< const xAOD::TruthParticle * > in_parts, std::vector< const xAOD::TruthParticle * > intern, std::vector< const xAOD::TruthParticle * > out_parts, bool pv)
Definition FatVertex.h:128
bool operator==(const FatVertex &other) const
std::vector< const xAOD::TruthParticle * > internal
Definition FatVertex.h:122
std::optional< DetailedVertexType > classifyPhotonVertex(size_t truth_out_parts, size_t truth_valid_out_parts, const std::vector< const xAOD::TruthParticle * > &truth_children) const
std::optional< DetailedVertexType > classifyLeptonVertex(const SG::ConstAccessor< int > &uid_accessor, size_t truth_out_parts, size_t truth_valid_out_parts, const std::vector< const xAOD::TruthParticle * > &truth_children) const
int getNumNeutralDecays(float minPt=0.0, bool include_neutrinos=false) const
std::optional< DetailedVertexType > classifyStrangeVertex(DetailedVertexType parent_type, bool has_parent) const
std::vector< const FatVertex * > children
Definition FatVertex.h:126
std::optional< DetailedVertexType > classifyTauVertex(DetailedVertexType parent_type, bool has_parent) const
std::vector< const xAOD::TruthParticle * > outparts
Definition FatVertex.h:123