ATLAS Offline Software
Loading...
Searching...
No Matches
MagicNumbers.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4/* Author: Andrii Verbytskyi andrii.verbytskyi@mpp.mpg.de */
5
6#ifndef TRUTHUTILS_MAGICNUMBERS_H
7#define TRUTHUTILS_MAGICNUMBERS_H
8
9#include <limits>
10#include <cstdint>
11#include <memory>
12#include <algorithm>
13#include <deque>
14#include <type_traits>
15#if !defined(XAOD_STANDALONE)
16#include "AtlasHepMC/GenEvent.h"
19#endif
20namespace xAOD {
21 // Temporarily specialize for xAOD::Truth classes ahead of the barcode migration - TODO remove this
22 class TruthParticle_v1;
23 class TruthVertex_v1;
24}
25class TrackRecord;
28
29enum EBC_SUPPRESSED_TRUTH : unsigned char {
30 EBC_UNSUPPRESSED = 0, // Truth particle expected to be found in McEventCollection
31 EBC_PU_SUPPRESSED, // Link points to a suppressed pile-up truth particle do not attempt to resolve it.
33};
34
35namespace HepMC {
36
38 constexpr int SIM_BARCODE_THRESHOLD = 200000;
39
41 constexpr int SIM_REGENERATION_INCREMENT = 1000000;
42
44 constexpr int SIM_STATUS_INCREMENT = 100000;
45
47 constexpr int SIM_STATUS_THRESHOLD = 20000;
48
51
53 constexpr int SUPPRESSED_PILEUP_BARCODE(std::numeric_limits<int32_t>::max());
54
55 constexpr int INVALID_PARTICLE_BARCODE = -1;
56
57 constexpr int UNDEFINED_ID = 0;
58 constexpr int INVALID_PARTICLE_ID = -1;
59 constexpr int INVALID_VERTEX_ID = 1;
60
61 // TODO The definitions of is_smart_ptr and remove_smart_pointer
62 // below are probably too generic for this header, but putting them
63 // here initially.
64 template <typename T> struct is_smart_ptr : std::false_type {};
65 template <typename T> struct is_smart_ptr<std::shared_ptr<T>> : std::true_type {};
66 template <typename T> struct is_smart_ptr<std::unique_ptr<T>> : std::true_type {};
67 template <typename T> struct is_smart_ptr<std::weak_ptr<T>> : std::true_type {};
68 template <class T> inline constexpr bool is_smart_ptr_v = is_smart_ptr<T>::value;
69
70 template <class T> struct remove_smart_pointer { typedef T type; };
71 template <class T> struct remove_smart_pointer<std::shared_ptr<T>> { typedef T type; };
72 template <class T> struct remove_smart_pointer<std::unique_ptr<T>> { typedef T type; };
73 template <class T> struct remove_smart_pointer<std::weak_ptr<T>> { typedef T type; };
74 template <class T> using remove_smart_pointer_t = typename remove_smart_pointer<T>::type;
75
76#if defined(XAOD_STANDALONE)
77 // Needed as we can't pick up the helper functions from AtlasHepMC in this case
78 template <class T> inline int barcode(const T& p){
79 if constexpr (std::is_pointer_v<T> || is_smart_ptr_v<T>){ //T is ptr
80 return p->barcode();
81 }
82 else {
83 return p.barcode();
84 }
85 }
86 template <> inline int barcode(const int& p){ return p;}
87#endif
88 // Temporarily specialize uniqueID for xAOD::Truth classes ahead of the barcode migration - TODO remove this
89 template <typename T> inline int uniqueID(const T& p) {
90 if constexpr (std::is_integral_v<T>) {
91 return p;
92 }
93 else if constexpr (std::is_integral_v<std::remove_pointer_t<T>>) {
94 return *p;
95 }
96 else if constexpr (std::is_same_v<T, xAOD::TruthParticle_v1> || std::is_same_v<T, xAOD::TruthVertex_v1>) {
97 return p.uid();
98 }
99 else if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, xAOD::TruthParticle_v1> || std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, xAOD::TruthVertex_v1>) {
100 return p->uid();
101 }
102 else if constexpr (std::is_same_v<T, CaloCalibrationHit>) {
103 return p.particleUID();
104 }
105 else if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, CaloCalibrationHit>) {
106 return p->particleUID();
107 }
108 else if constexpr (std::is_pointer_v<T> || is_smart_ptr_v<T>){ //T is ptr
109 return p->id();
110 }
111 else {
112 return p.id();
113 }
114 }
115 template <typename T> inline int status(const T& p) {
116 if constexpr (std::is_integral_v<T>) {
117 return p;
118 }
119 else if constexpr (std::is_integral_v<std::remove_pointer_t<T>>) {
120 return *p;
121 }
122 else if constexpr (std::is_pointer_v<T> || is_smart_ptr_v<T>){ //T is ptr
123 return p->status();
124 }
125 else {
126 return p.status();
127 }
128 }
129
131 template <class T> inline void get_particle_history(const T& p, std::deque<int>& out, const int direction = 0) {
132 if (direction < 0) {
133 if (p->status()>SIM_STATUS_INCREMENT) {
134 auto pv = p->production_vertex();
135 if (pv) {
136 for (auto pa: pv->particles_in()) {
137 if (!pa || pa->pdg_id() != p->pdg_id()) continue;
138 out.push_front(uniqueID(p));
139 get_particle_history(pa, out, -1);
140 break;
141 }
142 }
143 }
144 }
145 if (direction > 0) {
146 if (p->status()>SIM_STATUS_INCREMENT) {
147 auto pv = p->end_vertex();
148 if (pv) {
149 for (auto pa: pv->particles_out()) {
150 if (!pa || pa->pdg_id() != p->pdg_id()) continue;
151 out.push_back(uniqueID(p));
152 get_particle_history(pa, out, 1);
153 break;
154 }
155 }
156 }
157 }
158 }
159
160 template <class T> inline std::deque<int> simulation_history(const T& p, const int direction ) { std::deque<int> res; res.push_back(uniqueID(p)); get_particle_history(p, res, direction); return res;}
161
162 namespace BarcodeBased {
164 template <class T> inline bool is_truth_suppressed_pileup(const T& p){ return (barcode(p) == SUPPRESSED_PILEUP_BARCODE);}
165
167 template <class T> inline bool no_truth_link(const T& p){ return (barcode(p) == UNDEFINED_ID);}
168
170 template <class T> inline bool ignoreTruthLink(const T& p, bool vetoPileUp){ const int b = barcode(p); return no_truth_link(b) || (vetoPileUp && is_truth_suppressed_pileup(b)); }
171
173 template <class T> inline bool is_simulation_particle(const T& p){ return (barcode(p)>SIM_BARCODE_THRESHOLD);}
174
176 template <class T> inline bool is_sim_secondary(const T& p){ return (barcode(p)%SIM_REGENERATION_INCREMENT > SIM_BARCODE_THRESHOLD); }
177
179 template <class T> inline int generations(const T& p){ return (barcode(p)/SIM_REGENERATION_INCREMENT);}
180
182 template <class T> inline bool is_simulation_vertex(const T& v){ return (barcode(v)<-SIM_BARCODE_THRESHOLD);}
183
185 template <class T1, class T2> inline bool is_same_generator_particle(const T1& p1,const T2& p2) { int b1 = barcode(p1); int b2 = barcode(p2); return b1% SIM_REGENERATION_INCREMENT == b2 % SIM_REGENERATION_INCREMENT; }
186
188 template <class T1, class T2> inline bool is_same_object(const T1& p1,const T2& p2) { int b1 = uniqueID(p1); int b2 = uniqueID(p2); return b1 == b2; } // NB Still need to adapt CaloCalibrationHits
189
191 template <class T1, class T2> inline bool is_sim_descendant(const T1& p1,const T2& p2) { int b1 = barcode(p1); int b2 = barcode(p2); return b1 % SIM_REGENERATION_INCREMENT == b2;}
192 }
193
194 namespace StatusBased {
196 template <class T> inline bool is_truth_suppressed_pileup(const T& p){
197 if constexpr (std::is_same_v<std::remove_const_t<T>, HepMcParticleLink>) {
198 return p.getTruthSuppressionType() == EBC_PU_SUPPRESSED;
199 }
200 else if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, HepMcParticleLink>) {
201 return p->getTruthSuppressionType() == EBC_PU_SUPPRESSED;
202 }
203 else {
204 return p == EBC_PU_SUPPRESSED;
205 }
206 }
207
209 template <class T> inline bool no_truth_link(const T& p){
210 if constexpr (std::is_same_v<std::remove_const_t<T>, HepMcParticleLink>) {
211 return p.linkIsNull();
212 }
213 else if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, HepMcParticleLink>) {
214 return p->linkIsNull();
215 }
216 else {
217 return (uniqueID(p) == UNDEFINED_ID);
218 }
219 }
220
222 template <class T> inline bool ignoreTruthLink(const T& p, bool vetoPileUp){
223 if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, HepMcParticleLink>) {
224 return no_truth_link(p) || (vetoPileUp && is_truth_suppressed_pileup(p));
225 }
226 else {
227 const int u = uniqueID(p); return no_truth_link(u) || (vetoPileUp && is_truth_suppressed_pileup(u));
228 }
229 }
230
232 template <class T> inline bool is_simulation_particle(const T& p){ return (status(p)>SIM_STATUS_THRESHOLD);}
233
235 template <class T> inline bool is_sim_secondary(const T& p){ return (status(p)%SIM_STATUS_INCREMENT > SIM_STATUS_THRESHOLD); }
236
238 template <class T> inline int generations(const T& p){ return (status(p)/SIM_STATUS_INCREMENT);}
239
241 template <class T> inline bool is_simulation_vertex(const T& v){ return (status(v)>SIM_STATUS_THRESHOLD);}
242
244 template <class T1, class T2> inline bool is_same_generator_particle(const T1& p1,const T2& p2) {
245 const int id1 = uniqueID(p1);
246 const int id2 = uniqueID(p2);
247 if (id1 == id2) { return true;} // simplest case
248 const int generations1 = generations(p1);
249 const int generations2 = generations(p2);
250 if (generations1 == generations2) { return false; } // if the id values don't match and the particles have the same generation number then they cannot be the same particle.
251 if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T1>>>, TrackRecord>) {
252 // No choice, but to get the history of one of the particles:
253 const int direction = (generations2 > generations1) ? -1 : 1;
254 std::deque<int> history2 = simulation_history( p2, direction );
255 if (std::find(history2.begin(),history2.end(), id1) == history2.end()) { return false; }
256 }
257 else {
258 // No choice, but to get the history of one of the particles:
259 const int direction = (generations1 > generations2) ? -1 : 1;
260 std::deque<int> history1 = simulation_history( p1, direction );
261 if (std::find(history1.begin(),history1.end(), id2) == history1.end()) { return false; }
262 }
263 return true;
264 }
265
267 template <class T1, class T2> inline bool is_same_object(const T1& p1,const T2& p2) {
268 const int id1 = uniqueID(p1);
269 const int id2 = uniqueID(p2);
270 return (id1 == id2);
271 }
272
273
275 template <class T1, class T2> inline bool is_sim_descendant(const T1& p1,const T2& p2) {
276 const int id1 = uniqueID(p1);
277 const int id2 = uniqueID(p2);
278 if (id1 == id2) { return true;} // simplest case
279 const int generations1 = generations(p1);
280 const int generations2 = generations(p2);
281 if (generations1 == generations2) { return false; } // if the id values don't match and the particles have the same generation number then they cannot be the same particle.
282 if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T1>>>, TrackRecord>) {
283 // No choice, but to get the descendents of p2
284 constexpr int descendents = 1;
285 std::deque<int> history2 = simulation_history( p2, descendents );
286 if (std::find(history2.begin(),history2.end(), id1) == history2.end()) { return false; }
287 }
288 else {
289 // No choice, but to get the history of p1
290 constexpr int ancestors = -1;
291 std::deque<int> history1 = simulation_history( p1, ancestors );
292 if (std::find(history1.begin(),history1.end(), id2) == history1.end()) { return false; }
293 }
294 return true;
295 }
296 }
297
299 template <class T> inline bool is_truth_suppressed_pileup(const T& p){
300 if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, HepMcParticleLink>) {
302 }
303 else {
305 }
306 }
307
309 template <class T> inline bool no_truth_link(const T& p){ return StatusBased::no_truth_link(p);}
310
312 template <class T> inline bool ignoreTruthLink(const T& p, bool vetoPileUp){
313 if constexpr (std::is_same_v<std::remove_const_t<remove_smart_pointer_t<std::remove_pointer_t<T>>>, HepMcParticleLink>) {
314 return StatusBased::ignoreTruthLink(p, vetoPileUp);
315 }
316 else {
317 return BarcodeBased::ignoreTruthLink(p, vetoPileUp);
318 }
319 }
320
322 template <class T> inline bool is_simulation_particle(const T& p){ return StatusBased::is_simulation_particle(p);}
323
325 template <class T> inline int generations(const T& p){ return StatusBased::generations(p);}
326
328 template <class T> inline bool is_simulation_vertex(const T& v){ return StatusBased::is_simulation_vertex(v);}
329
331 template <class T1,class T2> inline bool is_same_generator_particle(const T1& p1,const T2& p2) { return StatusBased::is_same_generator_particle(p1, p2); }
332
334 template <class T1,class T2> inline bool is_same_particle(const T1& p1,const T2& p2) { return StatusBased::is_same_object(p1, p2); }
335
337 template <class T1,class T2> inline bool is_same_vertex(const T1& p1,const T2& p2) { return StatusBased::is_same_object(p1, p2); }
338
340 template <class T1,class T2> inline bool is_sim_descendant(const T1& p1,const T2& p2) { return StatusBased::is_sim_descendant(p1, p2);}
341
343 template <class T> void old_to_new_simulation_scheme(T& evt) {
344 auto particle_status = [] (int barcode, int status) {
348 return status;
349 };
350 auto vertex_status = [] (int barcode, int status) {
352 return status;
353 };
354 for (auto p: evt->particles()) {
355 p->set_status (particle_status (HepMC::barcode(p), p->status()));
356 }
357 for (auto v: evt->vertices()) {
358 v->set_status (vertex_status (HepMC::barcode(v), v->status()));
359 }
360 }
361
363 inline int new_particle_status_from_old(const int oldStatus,const int barcode) {
364 int generations_barcode_based = (barcode/SIM_REGENERATION_INCREMENT);
365 bool is_sim_secondary_barcode_based = (barcode%SIM_REGENERATION_INCREMENT > SIM_BARCODE_THRESHOLD);
366 return oldStatus + SIM_STATUS_INCREMENT*generations_barcode_based + (is_sim_secondary_barcode_based? SIM_STATUS_THRESHOLD : 0);
367 }
368
370 inline int old_particle_status_from_new(const int newStatus) { return newStatus%SIM_STATUS_THRESHOLD; }
371
373 inline int new_vertex_status_from_old(const int oldStatus,const int barcode) {
374 bool is_simulation_vertex_barcode_based = (barcode<-SIM_BARCODE_THRESHOLD);
375 return (is_simulation_vertex_barcode_based? SIM_STATUS_THRESHOLD : 0) + oldStatus;
376 }
377
379 inline int old_vertex_status_from_new(const int newStatus) {
380 bool is_simulation_vertex_status_based = (newStatus>SIM_STATUS_THRESHOLD);
381 return ( is_simulation_vertex_status_based ? -SIM_STATUS_THRESHOLD : 0) + newStatus; }
382}
383#if !defined(XAOD_STANDALONE)
384namespace HepMC {
386inline int maxGeneratedParticleBarcode(const HepMC::GenEvent *genEvent) {
387 int maxBarcode = 0;
388 auto allbarcodes = genEvent->attribute<HepMC::GenEventBarcodes>(HepMCStr::barcodes);
389 for (const auto& bp: allbarcodes->barcode_to_particle_map()) {
390 if (!HepMC::BarcodeBased::is_simulation_particle(bp.first)) { maxBarcode=std::max(maxBarcode,bp.first); }
391 }
392 return maxBarcode;
393}
394
396inline int maxGeneratedVertexBarcode(const HepMC::GenEvent *genEvent) {
397 int maxBarcode=0;
398 auto allbarcodes = genEvent->attribute<HepMC::GenEventBarcodes>(HepMCStr::barcodes);
399 for (const auto& bp: allbarcodes->barcode_to_vertex_map()) {
400 if (!HepMC::BarcodeBased::is_simulation_vertex(bp.first)) { maxBarcode=std::min(maxBarcode,bp.first); }
401 }
402 return maxBarcode;
403}
404}
405#endif
406
407#endif
std::pair< std::vector< unsigned int >, bool > res
EBC_SUPPRESSED_TRUTH
@ EBC_NSUPP
@ EBC_PU_SUPPRESSED
@ EBC_UNSUPPRESSED
Class to store calorimeter calibration hit.
STL class.
Class describing a truth particle in the MC record.
Class describing a truth vertex in the MC record.
const std::string barcodes
bool is_same_object(const T1 &p1, const T2 &p2)
Method to establish if two particles/vertices in the GenEvent actually represent the same generated p...
bool is_sim_secondary(const T &p)
Method to establish if a particle (or barcode) is a new seondary created during the simulation (only ...
bool is_truth_suppressed_pileup(const T &p)
Method to establish if a particle (or barcode) corresponds to truth-suppressed pile-up.
bool is_simulation_vertex(const T &v)
Method to establish if the vertex was created during simulation (only to be used in legacy TP convert...
int generations(const T &p)
Method to return how many interactions a particle has undergone during simulation (only to be used in...
bool is_same_generator_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same generated particle.
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
bool no_truth_link(const T &p)
Method to establish if a if the object is linked to something which was never saved to the HepMC Trut...
bool is_simulation_particle(const T &p)
Method to establish if a particle (or barcode) was created during the simulation (only to be used in ...
bool is_sim_descendant(const T1 &p1, const T2 &p2)
Method to check if the first particle is a descendant of the second in the simulation,...
bool is_sim_secondary(const T &p)
Method to establish if a particle is a new seondary created during the simulation based on the status...
int generations(const T &p)
Method to return how many interactions a particle has undergone during simulation based on the status...
bool is_simulation_vertex(const T &v)
Method to establish if the vertex was created during simulation from the status.
bool is_same_object(const T1 &p1, const T2 &p2)
Method to establish if two particles/vertices in the GenEvent actually represent the same particle.
bool is_truth_suppressed_pileup(const T &p)
Method to establish if a particle corresponds to truth-suppressed pile-up.
bool is_simulation_particle(const T &p)
Method to establish if a particle was created during the simulation based on the status value.
bool is_same_generator_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same generated particle.
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
bool is_sim_descendant(const T1 &p1, const T2 &p2)
Method to check if the first particle is a descendant of the second in the simulation,...
bool no_truth_link(const T &p)
Method to establish if a if the object is linked to something which was never saved to the HepMC Trut...
int maxGeneratedVertexBarcode(const HepMC::GenEvent *genEvent)
Get the maximal absolute value of barcode of vertex present in the event. Returns a negative number.
bool is_same_generator_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same generated particle.
constexpr int INVALID_PARTICLE_ID
bool is_simulation_vertex(const T &v)
Method to establish if the vertex was created during simulation (TODO migrate to be based on status).
void old_to_new_simulation_scheme(T &evt)
Function that converts the old scheme of labeling the simulation particles (barcodes) into the new sc...
int barcode(const T *p)
Definition Barcode.h:15
int uniqueID(const T &p)
constexpr int UNDEFINED_ID
void get_particle_history(const T &p, std::deque< int > &out, const int direction=0)
Function to calculate all the descendants(direction=1)/ancestors(direction=-1) of the particle.
typename remove_smart_pointer< T >::type remove_smart_pointer_t
constexpr int SUPPRESSED_PILEUP_BARCODE(std::numeric_limits< int32_t >::max())
This barcode is used by objects matched to particles from pile-up interactions in standard MC Product...
constexpr int INVALID_PARTICLE_BARCODE
constexpr int SIM_STATUS_INCREMENT
Constant defining the barcode threshold for regenerated particles, i.e. particles surviving an intera...
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
int status(const T &p)
bool is_same_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same particle.
int new_vertex_status_from_old(const int oldStatus, const int barcode)
Get vertex status in the new scheme from the barcode and status in the old scheme.
int old_vertex_status_from_new(const int newStatus)
Get vertex status in the old scheme from the status in the new scheme.
bool is_truth_suppressed_pileup(const T &p)
Method to establish if a particle (or barcode) corresponds to truth-suppressed pile-up (TODO update t...
int maxGeneratedParticleBarcode(const HepMC::GenEvent *genEvent)
Get the maximal value of barcode of particle present in the event.
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 INVALID_VERTEX_ID
constexpr int FORWARD_TRANSPORT_MODEL_PROCESS
Special Forward transport Geant process for vertices.
int new_particle_status_from_old(const int oldStatus, const int barcode)
Get particle status in the new scheme from the barcode and status in the old scheme.
constexpr bool is_smart_ptr_v
bool no_truth_link(const T &p)
Method to establish if a if the object is linked to something which was never saved to the HepMC Trut...
int old_particle_status_from_new(const int newStatus)
Get particle status in the old scheme from the status in the new scheme.
std::deque< int > simulation_history(const T &p, const int direction)
Function to calculate all the descendants(direction=1)/ancestors(direction=-1) of the particle.
bool is_same_vertex(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same vertex.
int generations(const T &p)
Method to return how many interactions a particle has undergone during simulation (TODO migrate to be...
constexpr int SIM_BARCODE_THRESHOLD
Constant defining the barcode threshold for simulated particles, eg. can be used to separate generato...
bool is_sim_descendant(const T1 &p1, const T2 &p2)
Method to check if the first particle is a descendant of the second in the simulation,...
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
constexpr int SIM_REGENERATION_INCREMENT
Constant defining the barcode threshold for regenerated particles, i.e. particles surviving an intera...
STL namespace.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.