4 #ifndef TRUTHUTILS_ATLASPID_H
5 #define TRUTHUTILS_ATLASPID_H
16 class DecodedPID:
public std::pair<int,std::vector<int>> {
22 for(;
ap;
ap/=10) this->
second.push_back( ap%10 );
27 inline const int&
last()
const {
return this->
second.back();}
28 inline const int&
pid()
const {
return this->
first;}
34 static const int TABLESIZE = 100;
35 static const std::array<int,TABLESIZE> triple_charge = {
36 +0, -1, +2, -1, +2, -1, +2, -1, +2, +0,
37 +0, -3, +0, -3, +0, -3, +0, -3, +0, +0,
38 +0, +0, +0, +0, +3, +0, +0, +0, +0, +0,
39 +0, +0, +0, +0, +3, +0, +0, +3, +0, +0,
40 +0, +0, -1, +0, +0, +0, +0, +0, +0, +0,
41 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
42 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
43 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
44 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
45 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0
49 static const int UQUARK = 1;
50 static const int DQUARK = 2;
51 static const int SQUARK = 3;
52 static const int CQUARK = 4;
53 static const int BQUARK = 5;
54 static const int TQUARK = 6;
56 static const int ELECTRON = 11;
57 static const int POSITRON = -ELECTRON;
58 static const int NU_E = 12;
59 static const int MUON = 13;
60 static const int NU_MU = 14;
61 static const int TAU = 15;
62 static const int NU_TAU = 16;
64 static const int GLUON = 21;
66 static const int COMPOSITEGLUON = 9;
67 static const int PHOTON = 22;
68 static const int Z0BOSON = 23;
69 static const int WPLUSBOSON = 24;
70 static const int HIGGSBOSON = 25;
71 static const int GRAVITON = 39;
72 static const int LEPTOQUARK = 42;
78 static const int DARKPHOTON = 60000;
79 static const int MAVTOP = 60001;
81 static const int PIPLUS = 211;
82 static const int PIMINUS = -PIPLUS;
83 static const int PI0 = 111;
84 static const int K0L = 130;
86 static const int K0S = 310;
87 static const int K0 = 311;
88 static const int KPLUS = 321;
89 static const int DPLUS = 411;
90 static const int DSTAR = 413;
91 static const int D0 = 421;
92 static const int DSPLUS = 431;
93 static const int JPSI = 443;
94 static const int B0 = 511;
95 static const int BCPLUS = 541;
96 static const int PROTON = 2212;
97 static const int LAMBDA0 = 3122;
98 static const int LAMBDACPLUS = 4122;
99 static const int LAMBDAB0 = 5122;
100 static const int PSI2S = 20443;
104 static const int POMERON = 990;
105 static const int ODDERON = 9990;
106 static const int REGGEON = 110;
113 static const int GEANTINOPLUS = 998;
114 static const int GEANTINO0 = 999;
123 template<>
inline bool isQuark(
const int&
p) {
return p != 0 && (std::abs(
p) <= 8 || std::abs(
p) == MAVTOP);}
127 template<>
inline bool isStrange(
const int&
p){
return std::abs(
p) == 3;}
130 template<>
inline bool isCharm(
const int&
p){
return std::abs(
p) == 4;}
133 template<>
inline bool isBottom(
const int&
p){
return std::abs(
p) == 5;}
136 template<>
inline bool isTop(
const int&
p){
return std::abs(
p) == 6;}
140 template<>
inline bool isLepton(
const int&
p){
auto sp = std::abs(
p);
return sp >= 11 && sp <= 18; }
144 template<>
inline bool isSMLepton(
const int&
p){
auto sp = std::abs(
p);
return sp >= 11 && sp <= 16; }
149 template<>
inline bool isChLepton(
const int&
p){
auto sp = std::abs(
p);
return sp >= 11 && sp <= 18 && sp%2 == 1; }
152 template<>
inline bool isElectron(
const int&
p){
return std::abs(
p) == ELECTRON;}
155 template<>
inline bool isMuon(
const int&
p){
return std::abs(
p) ==
MUON;}
158 template<>
inline bool isTau(
const int&
p){
return std::abs(
p) == TAU;}
162 template<>
inline bool isNeutrino(
const int&
p){
auto sp = std::abs(
p);
return sp == NU_E || sp == NU_MU || sp == NU_TAU || sp == 18; }
165 template<>
inline bool isSMNeutrino(
const int&
p){
auto sp = std::abs(
p);
return sp == NU_E || sp == NU_MU || sp == NU_TAU; }
168 template<>
inline bool isGluon(
const int&
p){
return p == GLUON; }
171 template<>
inline bool isPhoton(
const int&
p){
return p == PHOTON; }
173 template<
class T>
inline bool isZ(
const T&
p){
return isZ(
p->pdg_id());}
174 template<>
inline bool isZ(
const int&
p){
return p == Z0BOSON; }
176 template<
class T>
inline bool isW(
const T&
p){
return isW(
p->pdg_id());}
177 template<>
inline bool isW(
const int&
p){
return std::abs(
p) == WPLUSBOSON; }
189 template<
class T>
inline bool isDM(
const T&
p){
return isDM(
p->pdg_id());}
190 template<>
inline bool isDM(
const int&
p){
auto sp = std::abs(
p);
return (sp >= 51 && sp <= 60) || sp == DARKPHOTON; }
196 template<>
inline bool isTrajectory(
const int&
p){
return std::abs(
p) == POMERON || std::abs(
p) == ODDERON || std::abs(
p) == REGGEON; }
200 template<>
inline bool isHiggs(
const int&
p){
return p == HIGGSBOSON; }
205 template<>
inline bool isGraviton(
const int&
p){
return p == GRAVITON; }
208 template<>
inline bool isLeptoQuark(
const int&
p){
return std::abs(
p) == LEPTOQUARK; }
213 template<
class T>
inline bool isKK(
const T&
p){
return isKK(
p->pdg_id());}
236 if (
p >= 81 &&
p <= 100)
return true;
237 if (
p >= 901 &&
p <= 930)
return true;
238 if (
p >= 998 &&
p <= 999)
return true;
239 if (
p >= 1901 &&
p <= 1930)
return true;
240 if (
p >= 2901 &&
p <= 2930)
return true;
241 if (
p >= 3901 &&
p <= 3930)
return true;
245 template<>
inline bool isGeantino(
const int&
p){
return (std::abs(
p) == GEANTINO0 || std::abs(
p) == GEANTINOPLUS);}
250 if (
p.ndigits() > 4)
return false;
252 for (
size_t i = 1;
i + 1 <
p.ndigits(); ++
i) {
253 if (
p(
i) == COMPOSITEGLUON)
ng++;
255 return (*(
p.second.rbegin()+2)) == COMPOSITEGLUON && (*(
p.second.rbegin()+1)) == COMPOSITEGLUON &&
ng > 0;
286 template<>
inline bool isKK(
const DecodedPID&
p){
return (
p.ndigits() == 7 && (
p(0) == 5 ||
p(0) == 6 ) );}
295 template<>
inline bool isMonopole(
const DecodedPID&
p){
return (
p.ndigits() == 7 &&
p(0) == 4 &&
p(1) == 1 && (
p(2) == 1 ||
p(2) == 2 ) &&
p(6) == 0);}
319 if (
p.ndigits() == 4 &&
p(0) >=
p(1) &&
p(2) == 0 &&
p.last() % 2 == 1
320 &&
p.max_digit(1,3) <= 6
334 if (
p.ndigits() < 3 )
return false;
335 if (std::abs(
p.pid()) == K0S)
return true;
336 if (std::abs(
p.pid()) == K0L)
return true;
337 if (std::abs(
p.pid()) == K0)
return true;
338 if (
p.last() % 2 != 1 )
return false;
339 if (
p.max_digit(1,3) >= 6 )
return false;
340 if (
p.max_digit(1,3) == 0 )
return false;
342 if (
p.ndigits() == 3 &&
p(0) ==
p(1) &&
p.pid() < 0 )
return false;
343 if (
p.ndigits() == 5 &&
p(2) ==
p(3) &&
p.pid() < 0 )
return false;
344 if (
p.ndigits() == 7 &&
p(4) ==
p(5) &&
p.pid() < 0 )
return false;
347 if (
p.ndigits() == 3 &&
p(0) >=
p(1) &&
p(1) != 0 )
return true;
348 if (
p.ndigits() == 5 &&
p(2) >=
p(3) &&
p(3) != 0 &&
p(0) == 1 &&
p(1) == 0)
return true;
349 if (
p.ndigits() == 5 &&
p(2) >=
p(3) &&
p(3) != 0 &&
p(0) == 2 &&
p(1) == 0 &&
p.last() > 1 )
return true;
350 if (
p.ndigits() == 5 &&
p(2) >=
p(3) &&
p(3) != 0 &&
p(0) == 3 &&
p(1) == 0 &&
p.last() > 1 )
return true;
352 if (
p.ndigits() == 6 &&
p(3) >=
p(4) &&
p(4) != 0 &&
p.last() % 2 == 1 )
return true;
354 if (
p.ndigits() == 7 &&
p(4) >=
p(5) &&
p(5) != 0)
return true;
360 if (
p.ndigits() < 4 )
return false;
361 if (
p.max_digit(1,4) >= 6 )
return false;
362 if (
p.min_digit(1,4) == 0)
return false;
363 if (
p.ndigits() == 4 && (
p.last() == 2 ||
p.last() == 4||
p.last() == 6||
p.last() == 8) )
return true;
365 if (
p.ndigits() == 5 &&
p(0) == 1 && (
p.last() == 2 ||
p.last() == 4) )
return true;
366 if (
p.ndigits() == 5 &&
p(0) == 3 && (
p.last() == 2 ||
p.last() == 4) )
return true;
368 if (
p.ndigits() == 6 ) {
369 if (
p(0) == 1 &&
p(1) == 0 &&
p.last() == 2 )
return true;
370 if (
p(0) == 1 &&
p(1) == 1 &&
p.last() == 2 )
return true;
371 if (
p(0) == 1 &&
p(1) == 2 &&
p.last() == 4 )
return true;
373 if (
p(0) == 2 &&
p(1) == 0 &&
p.last() == 2 )
return true;
374 if (
p(0) == 2 &&
p(1) == 0 &&
p.last() == 4 )
return true;
375 if (
p(0) == 2 &&
p(1) == 1 &&
p.last() == 2 )
return true;
377 if (
p(0) == 1 &&
p(1) == 0 &&
p.last() == 4 )
return true;
378 if (
p(0) == 1 &&
p(1) == 0 &&
p.last() == 6 )
return true;
379 if (
p(0) == 2 &&
p(1) == 0 &&
p.last() == 6 )
return true;
380 if (
p(0) == 2 &&
p(1) == 0 &&
p.last() == 8 )
return true;
383 if (
p.ndigits() == 5 ) {
384 if (
p(0) == 2 &&
p.last() == 2 )
return true;
385 if (
p(0) == 2 &&
p.last() == 4 )
return true;
386 if (
p(0) == 2 &&
p.last() == 6 )
return true;
387 if (
p(0) == 5 &&
p.last() == 2 )
return true;
388 if (
p(0) == 1 &&
p.last() == 6 )
return true;
389 if (
p(0) == 4 &&
p.last() == 2 )
return true;
400 return (
p.ndigits() == 9 &&
p(0) == 1 &&
401 p.max_digit(1,6) <= 6 &&
p.min_digit(1,6) > 0 &&
402 (
p(3) >=
p(4) &&
p(4) >=
p(5) &&
p(5) >=
p(6)) );
411 return (
p.ndigits() == 9 &&
p(0) == 1 &&
p(5) == 0 &&
412 p.max_digit(1,3) <= 6 &&
p.min_digit(1,3) > 0 &&
413 p.max_digit(1+3,3+3) <= 6 &&
p.min_digit(1+3,3+3) > 0 &&
414 (
p(3) >=
p(4) &&
p(6) >=
p(7) ) && ( (
p(3) >
p(6) ) || (
p(3) ==
p(6) && (
p(4) >=
p(7))))
427 if (std::abs(
p.pid()) == PROTON)
return true;
428 return (
p.ndigits() == 10 &&
p(0) == 1 &&
p(1) == 0 );
432 if (
p.pid() == GRAVITON || std::abs(
p.pid()) == MAVTOP ||
p.pid() == DARKPHOTON)
return true;
433 if (std::abs(
p.pid()) > 16 && std::abs(
p.pid()) < 19)
return true;
434 if (std::abs(
p.pid()) > 31 && std::abs(
p.pid()) < 38)
return true;
435 if (std::abs(
p.pid()) > 39 && std::abs(
p.pid()) < 81)
return true;
436 if (std::abs(
p.pid()) > 6 && std::abs(
p.pid()) < 9)
return true;
440 if (
isKK(
p))
return true;
453 template<>
inline bool isBSM(
const int&
p){
454 if (
p == GRAVITON || std::abs(
p) == MAVTOP ||
p == DARKPHOTON)
return true;
455 if (std::abs(
p) > 16 && std::abs(
p) < 19)
return true;
456 if (std::abs(
p) > 31 && std::abs(
p) < 38)
return true;
457 if (std::abs(
p) > 39 && std::abs(
p) < 81)
return true;
458 if (std::abs(
p) > 6 && std::abs(
p) < 9)
return true;
468 template<>
inline bool isValid(
const int&
p){
if (!
p)
return false;
if (std::abs(
p) < 42)
return true;
475 if (
isQuark(
p.pid())) {
return (std::abs(
p.pid()) ==
q );}
476 if (
isMeson(
p)) {
return *(
p.second.rbegin() + 1) ==
q ||*(
p.second.rbegin()+2) ==
q;}
478 if (
isBaryon(
p)) {
auto i =
std::find(
p.second.rbegin() + 1,
p.second.rbegin()+4,
q);
return (
i!=
p.second.rbegin()+4);}
481 if (
isNucleus(
p) &&
p.first != PROTON) {
return q==3 &&
p(2) > 0;}
489 if (
isQuark(
p.pid())) {
return std::abs(
p.pid());}
490 if (
isMeson(
p)) {
return p.max_digit(1,3);}
538 template<
class T>
inline double charge(
const T&
p){
551 auto ap = std::abs(
p.pid());
552 if (
ap < TABLESIZE )
return p.pid() > 0 ? triple_charge.at(
ap) : -triple_charge.at(
ap);
553 if (
ap == K0)
return 0;
554 if (
ap == GEANTINO0)
return 0;
555 if (
ap == GEANTINOPLUS)
return p.pid() > 0 ? 3 : -3;
556 if (
ap == MAVTOP)
return p.pid() > 0 ? 2 : -2;
561 bool classified =
false;
562 if (!classified &&
isMeson(
p)) { classified =
true; nq = 2;
if ((*(
p.second.rbegin()+2)) == 2||(*(
p.second.rbegin()+2)) == 4 ) {
sign=-1;} signmult =-1; }
563 if (!classified &&
isDiquark(
p)) {
return triple_charge.at(
p(0))+triple_charge.at(
p(1)); }
564 if (!classified &&
isBaryon(
p)) { classified =
true; nq = 3; }
565 if (!classified &&
isTetraquark(
p)){
return triple_charge.at(
p(3)) + triple_charge.at(
p(4)) - triple_charge.at(
p(6)) - triple_charge.at(
p(7)); }
566 if (!classified &&
isPentaquark(
p)){
return triple_charge.at(
p(3)) + triple_charge.at(
p(4)) + triple_charge.at(
p(5)) + triple_charge.at(
p(6)) - triple_charge.at(
p(7)); }
567 if (!classified &&
isNucleus(
p)) { classified =
true; nq=0;
result = 3*(
p(3)*100 +
p(4)*10 +
p(5)) + (-1)*
p(2);}
568 if (!classified &&
isSUSY(
p)) { nq = 0;
570 auto pp =
p.shift(1);
if (pp.ndigits() > 2) pp = pp.shift(1);
577 return ( (
p.pid() > 0 &&
p(2) == 1) || (
p.pid() < 0 &&
p(2) == 2) ) ?
result : -
result;
580 double abs_charge = 0.0;
581 if (
p(0) == 1) abs_charge =
p(3)*100. +
p(4)*10. +
p(5)*1 +
p(6)*0.1;
582 if (
p(0) == 2) abs_charge = (
p(3)*10. +
p(4))/(
p(5)*10.0 +
p(6));
583 int abs_threecharge =
static_cast<int>(
std::round(abs_charge * 3.));
584 return p.pid() > 0 ? abs_threecharge : -1 * abs_threecharge;
586 for (
auto r =
p.second.rbegin() + 1;
r !=
p.second.rbegin() + 1 + nq; ++
r) {
593 int ap = std::abs(
p);
594 if (
ap < TABLESIZE)
return p > 0 ? triple_charge.at(
ap):-triple_charge.at(
ap);
601 double abs_charge = 0;
602 if (
p(0) == 1) abs_charge =
p(3)*100. +
p(4)*10. +
p(5)*1 +
p(6)*0.1;
603 if (
p(0) == 2) abs_charge = (
p(3)*10. +
p(4))/(
p(5)*10.0 +
p(6));
604 return p.pid() > 0 ? abs_charge : -1 * abs_charge;
629 if (
p.ndigits() != 7)
return false;
630 auto pp =
p.shift(2);
635 template<>
inline bool isRHadron(
const DecodedPID&
p) {
if (!
isSUSY(
p))
return false;
auto pp =
p.shift(1);
if (pp.ndigits() < 2)
return false;
if ( pp(1) == 7 || pp(1) == 8 )
return false;
if (pp.ndigits() > 2) pp = pp.shift(1);
return (
isHadron(pp) ||
isRGlueball(
p)); }
639 template<>
inline bool isRMeson(
const DecodedPID&
p) {
if (!
isSUSY(
p))
return false;
auto pp =
p.shift(1);
if (pp.ndigits() < 2)
return false;
if ( pp(1) == 7 || pp(1) == 8 )
return false;
if (pp.ndigits() > 2) pp = pp.shift(1);
return isMeson(pp); }
643 template<>
inline bool isRBaryon(
const DecodedPID&
p) {
if (!
isSUSY(
p))
return false;
auto pp =
p.shift(1);
if (pp.ndigits() < 2)
return false;
if ( pp(1) == 7 || pp(1) == 8 )
return false;
if (pp.ndigits() > 2) pp = pp.shift(1);
return isBaryon(pp); }
659 template<
class T>
inline bool spin(
const T&
p) {
return spin(
p->pdg_id()); }
660 template<>
inline bool spin(
const int&
p) {
return p%10; }
666 if (pp.ndigits() > 2) pp = pp.shift(1);
668 std::vector<int> quarks;
669 for (
int i = 1;
i<=6; ++
i)
676 if (
p.ndigits() == 7 && (
p(0) == 1 ||
p(0) == 2)) {
677 auto pp =
p.shift(1);
678 return ( pp.ndigits() == 1 &&
isQuark(pp) );
684 template<
class T>
inline bool hasSquark(
const T&
p,
const int&
q);
686 if (
p.ndigits() == 7 && (
p(0) == 1 ||
p(0) == 2)) {
687 auto pp =
p.shift(1);
688 if ( pp.ndigits() == 2) {
return false; }