ATLAS Offline Software
Loading...
Searching...
No Matches
TruthClassifiers.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef TRUTHUTILS_TRUTHCLASSIFIERS_H
5#define TRUTHUTILS_TRUTHCLASSIFIERS_H
8#include <utility>
9#include <bitset>
10#include <vector>
11#include <string>
13namespace MCTruthPartClassifier {
15{
16 if (pType == CCbarMesonPart && abs(motherPDG) == MC::JPSI) return JPsi;
17 if (pType == BBbarMesonPart) return BBbarMeson;
18 if (pType == BottomMesonPart) return BottomMeson;
19 if (pType == BottomBaryonPart) return BottomBaryon;
20 if (pType == CCbarMesonPart) return CCbarMeson;
21 if (pType == CharmedMesonPart) return CharmedMeson;
22 if (pType == CharmedBaryonPart) return CharmedBaryon;
23 if (pType == StrangeBaryonPart) return StrangeBaryon;
24 if (pType == StrangeMesonPart) return StrangeMeson;
25 if (pType == LightBaryonPart) return LightBaryon;
26 if (pType == LightMesonPart) return LightMeson;
27 return NonDefined;
28}
29
31 if (abs(pdg) == MC::JPSI) return JPsi;
32 if (MC::isBBbarMeson(pdg)) return BBbarMeson;
33 if (MC::isCCbarMeson(pdg)) return CCbarMeson;
34 if (MC::isBottomMeson(pdg)) return BottomMeson;
35 if (MC::isCharmMeson(pdg)) return CharmedMeson;
36 if (MC::isBottomBaryon(pdg)) return BottomBaryon;
37 if (MC::isCharmBaryon(pdg)) return CharmedBaryon;
38 if (MC::isStrangeBaryon(pdg)) return StrangeBaryon;
39 if (MC::isLightBaryon(pdg)) return LightBaryon;
40 if (MC::isStrangeMeson(pdg)) return StrangeMeson;
41 if (MC::isLightMeson(pdg)) return LightMeson;
42 return NonDefined;
43}
44
46 if (MC::isBBbarMeson(pdg)) return BBbarMesonPart;
47 if (MC::isCCbarMeson(pdg)) return CCbarMesonPart;
48 if (MC::isBottomMeson(pdg)) return BottomMesonPart;
49 if (MC::isCharmMeson(pdg)) return CharmedMesonPart;
50 if (MC::isBottomBaryon(pdg)) return BottomBaryonPart;
51 if (MC::isCharmBaryon(pdg)) return CharmedBaryonPart;
53 if (MC::isLightBaryon(pdg)) return LightBaryonPart;
54 if (MC::isStrangeMeson(pdg)) return StrangeMesonPart;
55 if (MC::isLightMeson(pdg)) return LightMesonPart;
56 return Unknown;
57}
58
59
61
62 if (EleOrig == NonDefined)
63 return UnknownElectron;
64
65 if (EleOrig == WBoson || EleOrig == ZBoson || EleOrig == top || EleOrig == SingleElec || EleOrig == Higgs ||
66 EleOrig == HiggsMSSM || EleOrig == HeavyBoson || EleOrig == WBosonLRSM || EleOrig == NuREle || EleOrig == NuRMu ||
67 EleOrig == NuRTau || EleOrig == LQ || EleOrig == SUSY || EleOrig == DiBoson || EleOrig == ZorHeavyBoson ||
68 EleOrig == OtherBSM || EleOrig == MultiBoson || isPrompt) {
69 return IsoElectron;
70 }
71 if (EleOrig == JPsi || EleOrig == BottomMeson || EleOrig == CharmedMeson || EleOrig == BottomBaryon ||
72 EleOrig == CharmedBaryon || EleOrig == TauLep || EleOrig == Mu || EleOrig == QuarkWeakDec) {
73 return NonIsoElectron;
74 }
75 return BkgElectron;
76}
77
78
80
81 if (MuOrig == NonDefined) return UnknownMuon;
82
83 if (MuOrig == WBoson || MuOrig == ZBoson || MuOrig == top || MuOrig == SingleMuon || MuOrig == Higgs ||
84 MuOrig == HiggsMSSM || MuOrig == HeavyBoson || MuOrig == WBosonLRSM || MuOrig == NuREle || MuOrig == NuRMu ||
85 MuOrig == NuRTau || MuOrig == LQ || MuOrig == SUSY || MuOrig == DiBoson || MuOrig == ZorHeavyBoson ||
86 MuOrig == OtherBSM || MuOrig == MultiBoson || isPrompt) {
87 return IsoMuon;
88 }
89 if (MuOrig == JPsi || MuOrig == BottomMeson || MuOrig == CharmedMeson || MuOrig == BottomBaryon ||
90 MuOrig == CharmedBaryon || MuOrig == TauLep || MuOrig == QuarkWeakDec) {
91 return NonIsoMuon;
92 }
93 // if (MuOrig == Pion || MuOrig == Kaon ) return DecayMuon;
94 return BkgMuon;
95}
96
98 if (TauOrig == NonDefined) return UnknownTau;
99
100 if (TauOrig == WBoson || TauOrig == ZBoson || TauOrig == top || TauOrig == SingleMuon || TauOrig == Higgs ||
101 TauOrig == HiggsMSSM || TauOrig == HeavyBoson || TauOrig == WBosonLRSM || TauOrig == NuREle || TauOrig == NuRMu ||
102 TauOrig == NuRTau || TauOrig == SUSY || TauOrig == DiBoson || TauOrig == ZorHeavyBoson || TauOrig == OtherBSM ||
103 TauOrig == MultiBoson)
104 return IsoTau;
105
106 if (TauOrig == JPsi || TauOrig == BottomMeson || TauOrig == CharmedMeson || TauOrig == BottomBaryon ||
107 TauOrig == CharmedBaryon || TauOrig == QuarkWeakDec)
108 return NonIsoTau;
109
110 return BkgTau;
111}
112
113
115{
116 if (PhotOrig == NonDefined) return UnknownPhoton;
117
118 if (PhotOrig == WBoson || PhotOrig == ZBoson || PhotOrig == SinglePhot || PhotOrig == Higgs ||
119 PhotOrig == HiggsMSSM || PhotOrig == HeavyBoson || PhotOrig == PromptPhot || PhotOrig == SUSY ||
120 PhotOrig == OtherBSM)
121 return IsoPhoton;
122
123 if (PhotOrig == ISRPhot || PhotOrig == FSRPhot || PhotOrig == TauLep || PhotOrig == Mu || PhotOrig == NuREle ||
124 PhotOrig == NuRMu || PhotOrig == NuRTau)
125 return NonIsoPhoton;
126
127 return BkgPhoton;
128}
129
130template <class T> ParticleOrigin defJetOrig(const T& allJetMothers) {
131 ParticleOrigin partOrig = NonDefined;
132 for (const auto& it: allJetMothers) {
133 int pdg = abs(it->pdg_id());
134 if (MC::isTop(pdg)) partOrig = top;
135 if (MC::isZ(pdg)) partOrig = ZBoson;
136 if (MC::isW(pdg) && !(partOrig == top)) partOrig = WBoson;
137 if ((MC::isQuark(pdg) || MC::isGluon(pdg)) && partOrig != top && partOrig != ZBoson && partOrig != WBoson) partOrig = QCD;
138 if (MC::isHiggs(pdg)) return Higgs;
139 if (pdg == 35 || pdg == 36 || pdg == 37) return HiggsMSSM;
140 if (pdg == 32 || pdg == 33 || pdg == 34) return HeavyBoson;
141 if (pdg == 42) return LQ;
142 if (MC::isSUSY(pdg)) return SUSY;
143 if (MC::isBSM(pdg)) return OtherBSM;
144 }
145 return partOrig;
146}
147 enum MCTC_bits : unsigned int { HadTau=0, Tau, hadron, frombsm, uncat, isbsm, isgeant, stable, totalBits };
148
149template <class T> std::tuple<unsigned int, T> defOrigOfParticle(T thePart) {
150
151 T parent_hadron_ptr = nullptr;
152
153 bool uncat = 0, fromHad = 0, fromTau = 0;
154 bool isPhysical = MC::isPhysical(thePart);
155 bool isGeant = HepMC::is_simulation_particle(thePart);
156 bool isBSM = MC::isBSM(thePart);
157 bool fromBSM = isBSM; // just to initialise
158
159 auto prodVtx = thePart->production_vertex();
160 if (isPhysical && prodVtx && !isGeant) {
161 fromHad = MC::isFromHadron(thePart, parent_hadron_ptr, fromTau, fromBSM);
162 }
163 else uncat = 1;
164
165 std::bitset<MCTC_bits::totalBits> classifier;
166 classifier[MCTC_bits::stable] = isPhysical;
167 classifier[MCTC_bits::isgeant] = isGeant;
168 classifier[MCTC_bits::isbsm] = isBSM;
169 classifier[MCTC_bits::uncat] = uncat;
170 classifier[MCTC_bits::frombsm] = fromBSM;
171 classifier[MCTC_bits::hadron] = fromHad;
172 classifier[MCTC_bits::Tau] = fromTau;
173 classifier[MCTC_bits::HadTau] = fromHad && fromTau;
174 unsigned int outputvalue = static_cast<unsigned int>(classifier.to_ulong());
175
176 return std::make_tuple(outputvalue,parent_hadron_ptr);
177}
178
179inline int isPrompt(const unsigned int classify, bool allow_prompt_tau_decays = true) {
180 std::bitset<MCTC_bits::totalBits> res(classify);
181 if (res.test(MCTC_bits::uncat)) return -1;
182 bool fromPromptTau = res.test(MCTC_bits::Tau) && !res.test(MCTC_bits::HadTau);
183 if (fromPromptTau) return int(allow_prompt_tau_decays);
184 return !res.test(MCTC_bits::hadron);
185 }
186
187template <class T> ParticleOutCome defOutComeOfElectron(T thePart) {
188 ParticleOutCome PartOutCome = UnknownOutCome;
189 auto EndVert = MC::findSimulatedEndVertex(thePart);
190 if (EndVert == nullptr) return NonInteract;
191
192 int ElecOutNumOfNucFr(0);
193 int ElecOutNumOfElec(0);
194 int NumOfHadr(0);
195 auto outgoing = EndVert->particles_out();
196 int NumOfElecDaug = outgoing.size();
197 for (const auto& p: outgoing) {
198 if (!p) continue;
199 int EndDaugType = p->pdg_id();
200 if (MC::isElectron(EndDaugType)) ElecOutNumOfElec++;
201 if (MC::isHadron(p) && !MC::isBeam(p)) NumOfHadr++;
202 if (EndDaugType > 1000000000 || EndDaugType == 0 || abs(EndDaugType) == 2212 || abs(EndDaugType) == 2112) ElecOutNumOfNucFr++;
203 }
204
205 if (ElecOutNumOfNucFr != 0 || NumOfHadr != 0) PartOutCome = NuclInteraction;
206 if (ElecOutNumOfElec == 1 && NumOfElecDaug == 1) PartOutCome = ElectrMagInter;
207
208 return PartOutCome;
209}
210
211template <class T> ParticleOutCome defOutComeOfMuon(T thePart) {
212 ParticleOutCome PartOutCome = UnknownOutCome;
213 auto EndVert = MC::findSimulatedEndVertex(thePart);
214 if (EndVert == nullptr) return NonInteract;
215 int MuOutNumOfNucFr(0);
216 int NumOfHadr(0);
217 int NumOfEleNeutr(0);
218 int NumOfMuonNeutr(0);
219 int NumOfElec(0);
220 auto outgoing = EndVert->particles_out();
221 int NumOfMuDaug = outgoing.size();
222 for (const auto& p: outgoing) {
223 if (!p) continue;
224 int EndDaugType = p->pdg_id();
225 if (MC::isElectron(EndDaugType)) NumOfElec++;
226 if (abs(EndDaugType) == 12) NumOfEleNeutr++;
227 if (abs(EndDaugType) == 14) NumOfMuonNeutr++;
228 if (MC::isHadron(p) && !MC::isBeam(p)) NumOfHadr++;
229 if (EndDaugType > 1000000000 || EndDaugType == 0 || abs(EndDaugType) == 2212 || abs(EndDaugType) == 2112) MuOutNumOfNucFr++;
230 }
231
232 if (MuOutNumOfNucFr != 0 || NumOfHadr != 0) PartOutCome = NuclInteraction;
233 if (NumOfMuDaug == 3 && NumOfElec == 1 && NumOfEleNeutr == 1 && NumOfMuonNeutr == 1) PartOutCome = DecaytoElectron;
234
235 return PartOutCome;
236}
237template <class T> ParticleOutCome defOutComeOfTau(T thePart) {
238 ParticleOutCome PartOutCome = UnknownOutCome;
239 auto EndVert = MC::findSimulatedEndVertex(thePart);
240 if (EndVert == nullptr) return NonInteract;
241 int NumOfTauDaug = EndVert->nOutgoingParticles();
242 auto tauFinalStatePart = MC::findFinalStateParticles(EndVert);
243 auto PD = DecayProducts(tauFinalStatePart);
244 int NumOfElec = PD.apd(11);
245 int NumOfMuon = PD.apd(13);
246 int NumOfElecNeut = PD.apd(12);
247 int NumOfMuonNeut = PD.apd(14);
248 int NumOfPhot = PD.apd(22);
249 int NumOfPi = PD.apd(211);
250 int NumOfKaon = PD.apd(321);
251 int NumOfNucFr = PD.apd(0) + PD.apd(1000000000, std::numeric_limits<int>::max());
252
253 if (NumOfNucFr != 0) PartOutCome = NuclInteraction;
254 if ((NumOfTauDaug == 3 && NumOfElec == 1 && NumOfElecNeut == 1) || (NumOfTauDaug == (3 + NumOfPhot) && NumOfElecNeut == 1)) PartOutCome = DecaytoElectron;
255 if ((NumOfTauDaug == 3 && NumOfMuon == 1 && NumOfMuonNeut == 1) || (NumOfTauDaug == (3 + NumOfPhot) && NumOfMuonNeut == 1)) PartOutCome = DecaytoMuon;
256
257 if (NumOfPi == 1 || NumOfKaon == 1) PartOutCome = OneProng;
258 if (NumOfPi + NumOfKaon == 3) PartOutCome = ThreeProng;
259 if (NumOfPi + NumOfKaon == 5) PartOutCome = FiveProng;
260
261
262 return PartOutCome;
263}
264
265template <class T> ParticleOutCome defOutComeOfPhoton(T thePart) {
266 ParticleOutCome PartOutCome = UnknownOutCome;
267 auto EndVert = MC::findSimulatedEndVertex(thePart);
268 if (EndVert == nullptr) return UnConverted;
269
270 int PhtOutNumOfNucFr(0);
271 int PhtOutNumOfEl(0);
272 int PhtOutNumOfPos(0);
273 int PhtOutNumOfHadr(0);
274
275 auto outgoing = EndVert->particles_out();
276 int NumOfPhtDaug = outgoing.size();
277 for (const auto& p: outgoing) {
278 if (!p) continue;
279 int EndDaugType = p->pdg_id();
280 if (EndDaugType > 1000000000 || EndDaugType == 0 || abs(EndDaugType) == 2212 || abs(EndDaugType) == 2112) PhtOutNumOfNucFr++;
281 if (EndDaugType == 11) PhtOutNumOfEl++;
282 if (EndDaugType == -11) PhtOutNumOfPos++;
283 if (MC::isHadron(p) && !MC::isBeam(p)) PhtOutNumOfHadr++;
284 }
285
286 if (PhtOutNumOfEl == 1 && PhtOutNumOfPos == 1 && NumOfPhtDaug == 2) PartOutCome = Converted;
287 if ((NumOfPhtDaug > 1 && PhtOutNumOfNucFr != 0) || PhtOutNumOfHadr > 0) PartOutCome = NuclInteraction;
288
289 return PartOutCome;
290}
291
292}
293#endif
bool isBSM(const T &p)
APID: graviton and all Higgs extensions are BSM.
Definition AtlasPID.h:852
ATLAS-specific HepMC functions.
std::pair< std::vector< unsigned int >, bool > res
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...
ParticleOutCome defOutComeOfElectron(T thePart)
ParticleOutCome defOutComeOfPhoton(T thePart)
ParticleOrigin defJetOrig(const T &allJetMothers)
ParticleType defTypeOfPhoton(ParticleOrigin PhotOrig)
ParticleOrigin convHadronTypeToOrig(ParticleType pType, int motherPDG)
ParticleOutCome defOutComeOfTau(T thePart)
ParticleType defTypeOfTau(ParticleOrigin TauOrig)
ParticleType defTypeOfMuon(ParticleOrigin MuOrig, bool isPrompt)
ParticleOrigin defHadronType(int pdg)
ParticleType defTypeOfHadron(int pdg)
int isPrompt(const unsigned int classify, bool allow_prompt_tau_decays=true)
ParticleOutCome defOutComeOfMuon(T thePart)
ParticleType defTypeOfElectron(ParticleOrigin EleOrig, bool isPrompt)
std::tuple< unsigned int, T > defOrigOfParticle(T thePart)
bool isZ(const T &p)
bool isStrangeBaryon(const T &p)
bool isLightBaryon(const T &p)
bool isLightMeson(const T &p)
bool isStrangeMeson(const T &p)
bool isBottomMeson(const T &p)
bool isCharmBaryon(const T &p)
bool isW(const T &p)
bool isCCbarMeson(const T &p)
bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM)
Function to classify the particle.
bool isBottomBaryon(const T &p)
bool isCharmMeson(const T &p)
bool isElectron(const T &p)
bool isBBbarMeson(const T &p)
bool isTop(const T &p)
bool isSUSY(const T &p)
auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out())
Function to find the stable particle descendants of the given vertex..
bool isQuark(const T &p)
PDG rule 2: Quarks and leptons are numbered consecutively starting from 1 and 11 respectively; to do ...
static const int JPSI
bool isHiggs(const T &p)
APID: HIGGS boson is only one particle.
bool isBeam(const T &p)
Identify if the particle is beam particle.
bool isHadron(const T &p)
bool isGluon(const T &p)
auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex())
Function to find the end vertex of a particle.
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
bool isBSM(const T &p)
APID: graviton and all Higgs extensions are BSM.