File indexing completed on 2025-11-03 08:57:23
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Definitions/ParticleData.hpp"
0010 #include "Acts/Definitions/PdgParticle.hpp"
0011
0012 #include <algorithm>
0013 #include <array>
0014 #include <cmath>
0015 #include <ostream>
0016 #include <ranges>
0017 #include <utility>
0018 #include <vector>
0019
0020
0021
0022
0023
0024
0025
0026 namespace Acts {
0027 namespace {
0028
0029 class DecodedPID : public std::pair<int, std::vector<int>> {
0030 public:
0031 explicit DecodedPID(const int& p) {
0032 this->first = p;
0033 this->second.reserve(10);
0034 int ap = std::abs(p);
0035 for (; ap != 0; ap /= 10) {
0036 this->second.push_back(ap % 10);
0037 }
0038 std::ranges::reverse(this->second);
0039 }
0040 inline DecodedPID shift(const std::size_t n) const {
0041 return DecodedPID(this->first %
0042 static_cast<int>(std::pow(10, ndigits() - n)));
0043 }
0044 inline const int& operator()(const std::size_t n) const {
0045 return this->second.at(n);
0046 }
0047 inline const int& last() const { return this->second.back(); }
0048 inline const int& pid() const { return this->first; }
0049 inline int max_digit(const int m, const int n) const {
0050 return *std::max_element(second.rbegin() + m, second.rbegin() + n);
0051 }
0052 inline int min_digit(const int m, const int n) const {
0053 return *std::min_element(second.rbegin() + m, second.rbegin() + n);
0054 }
0055 inline std::size_t ndigits() const { return this->second.size(); }
0056 };
0057
0058 const int TABLESIZE = 100;
0059 const std::array<int, TABLESIZE> triple_charge = {
0060 +0, -1, +2, -1, +2, -1, +2, -1, +2, +0, +0, -3, +0, -3, +0, -3, +0,
0061 -3, +0, +0, +0, +0, +0, +0, +3, +0, +0, +0, +0, +0, +0, +0, +0, +0,
0062 +3, +0, +0, +3, +6, +0, +0, +0, -1, +0, +0, +0, +0, +0, +0, +0, +0,
0063 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
0064 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
0065 +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0};
0066
0067 const int DQUARK = 1;
0068 const int UQUARK = 2;
0069 const int SQUARK = 3;
0070 const int CQUARK = 4;
0071 const int BQUARK = 5;
0072 const int TQUARK = 6;
0073
0074 const int ELECTRON = 11;
0075 const int MUON = 13;
0076 const int TAU = 15;
0077
0078 const int GLUON = 21;
0079
0080
0081 const int COMPOSITEGLUON = 9;
0082 const int PHOTON = 22;
0083 const int Z0BOSON = 23;
0084 const int ZPRIME = 32;
0085 const int ZDBLPRIME = 33;
0086 const int LEPTOQUARK = 42;
0087
0088
0089
0090
0091
0092 const int MAVTOP = 60001;
0093
0094 const int K0L = 130;
0095
0096 const int K0S = 310;
0097 const int K0 = 311;
0098 const int PROTON = 2212;
0099
0100
0101
0102
0103
0104
0105
0106 const int GEANTINOPLUS = 998;
0107 const int GEANTINO0 = 999;
0108
0109
0110
0111
0112
0113
0114 bool isQuark(int p) {
0115 return p != 0 && (std::abs(p) <= 8 || std::abs(p) == MAVTOP);
0116 }
0117
0118 bool isSMQuark(int p) {
0119 return p != 0 && std::abs(p) <= TQUARK;
0120 }
0121
0122
0123
0124
0125 bool isDiquark(const DecodedPID& p) {
0126 if (p.ndigits() == 4 && p(0) >= p(1) && p(2) == 0 && p.last() % 2 == 1 &&
0127 p.max_digit(2, 4) <= TQUARK) {
0128 return true;
0129 }
0130 return false;
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140 bool isMeson(const DecodedPID& p) {
0141 if (p.ndigits() < 3) {
0142 return false;
0143 }
0144 if (p.ndigits() == 7 && (p(0) == 1 || p(0) == 2)) {
0145 return false;
0146 }
0147 if (std::abs(p.pid()) == K0S) {
0148 return true;
0149 }
0150 if (std::abs(p.pid()) == K0L) {
0151 return true;
0152 }
0153 if (std::abs(p.pid()) == K0) {
0154 return true;
0155 }
0156 if (p.last() % 2 != 1) {
0157 return false;
0158 }
0159 if (p.max_digit(1, 3) >= 6) {
0160 return false;
0161 }
0162 if (p.max_digit(1, 3) == 0) {
0163 return false;
0164 }
0165 if (p.ndigits() > 3 && *(p.second.rbegin() + 3) != 0) {
0166 return false;
0167 }
0168
0169 if (p.ndigits() == 3 && p(0) == p(1) && p.pid() < 0) {
0170 return false;
0171 }
0172 if (p.ndigits() == 5 && p(2) == p(3) && p.pid() < 0) {
0173 return false;
0174 }
0175 if (p.ndigits() == 7 && p(4) == p(5) && p.pid() < 0) {
0176 return false;
0177 }
0178
0179 if (p.ndigits() == 3 && p(0) >= p(1) && p(1) != 0) {
0180 return true;
0181 }
0182 if (p.ndigits() == 5 && p(2) >= p(3) && p(3) != 0 && p(0) == 1 && p(1) == 0) {
0183 return true;
0184 }
0185 if (p.ndigits() == 5 && p(2) >= p(3) && p(3) != 0 && p(0) == 2 && p(1) == 0 &&
0186 p.last() > 1) {
0187 return true;
0188 }
0189 if (p.ndigits() == 5 && p(2) >= p(3) && p(3) != 0 && p(0) == 3 && p(1) == 0 &&
0190 p.last() > 1) {
0191 return true;
0192 }
0193
0194 if (p.ndigits() == 6 && p(3) >= p(4) && p(4) != 0 && p.last() % 2 == 1) {
0195 return true;
0196 }
0197
0198 if (p.ndigits() == 7 && p(0) == 9 && p(1) == 0 && p(4) >= p(5) && p(5) != 0) {
0199 return true;
0200 }
0201
0202 return false;
0203 }
0204
0205
0206 bool isBaryon(const DecodedPID& p) {
0207 if (p.ndigits() < 4) {
0208 return false;
0209 }
0210 if (p.max_digit(1, 4) >= 6) {
0211 return false;
0212 }
0213 if (p.min_digit(1, 4) == 0) {
0214 return false;
0215 }
0216 if (p.ndigits() == 4 &&
0217 (p.last() == 2 || p.last() == 4 || p.last() == 6 || p.last() == 8)) {
0218 return true;
0219 }
0220
0221 if (p.ndigits() == 5 && p(0) == 1 && (p.last() == 2 || p.last() == 4)) {
0222 return true;
0223 }
0224 if (p.ndigits() == 5 && p(0) == 3 && (p.last() == 2 || p.last() == 4)) {
0225 return true;
0226 }
0227
0228 if (p.ndigits() == 6) {
0229 if (p(0) == 1 && p(1) == 0 && p.last() == 2) {
0230 return true;
0231 }
0232 if (p(0) == 1 && p(1) == 1 && p.last() == 2) {
0233 return true;
0234 }
0235 if (p(0) == 1 && p(1) == 2 && p.last() == 4) {
0236 return true;
0237 }
0238
0239 if (p(0) == 2 && p(1) == 0 && p.last() == 2) {
0240 return true;
0241 }
0242 if (p(0) == 2 && p(1) == 0 && p.last() == 4) {
0243 return true;
0244 }
0245 if (p(0) == 2 && p(1) == 1 && p.last() == 2) {
0246 return true;
0247 }
0248
0249 if (p(0) == 1 && p(1) == 0 && p.last() == 4) {
0250 return true;
0251 }
0252 if (p(0) == 1 && p(1) == 0 && p.last() == 6) {
0253 return true;
0254 }
0255 if (p(0) == 2 && p(1) == 0 && p.last() == 6) {
0256 return true;
0257 }
0258 if (p(0) == 2 && p(1) == 0 && p.last() == 8) {
0259 return true;
0260 }
0261 }
0262
0263 if (p.ndigits() == 5) {
0264 if (p(0) == 2 && p.last() == 2) {
0265 return true;
0266 }
0267 if (p(0) == 2 && p.last() == 4) {
0268 return true;
0269 }
0270 if (p(0) == 2 && p.last() == 6) {
0271 return true;
0272 }
0273 if (p(0) == 5 && p.last() == 2) {
0274 return true;
0275 }
0276 if (p(0) == 1 && p.last() == 6) {
0277 return true;
0278 }
0279 if (p(0) == 4 && p.last() == 2) {
0280 return true;
0281 }
0282 }
0283 return false;
0284 }
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 bool isTetraquark(const DecodedPID& p) {
0297 return (p.ndigits() == 9 && p(0) == 1 && p(5) == 0 &&
0298 p.max_digit(1, 3) <= 6 && p.min_digit(1, 3) > 0 &&
0299 p.max_digit(1 + 3, 3 + 3) <= 6 && p.min_digit(1 + 3, 3 + 3) > 0 &&
0300 (p(3) >= p(4) && p(6) >= p(7)) &&
0301 ((p(3) > p(6)) || (p(3) == p(6) && (p(4) >= p(7)))));
0302 }
0303
0304
0305
0306
0307
0308
0309
0310 bool isPentaquark(const DecodedPID& p) {
0311 return (p.ndigits() == 9 && p(0) == 1 && p.max_digit(1, 6) <= 6 &&
0312 p.min_digit(1, 6) > 0 &&
0313 (p(3) >= p(4) && p(4) >= p(5) && p(5) >= p(6)));
0314 }
0315
0316
0317 bool isHadron(const DecodedPID& p) {
0318 return isMeson(p) || isBaryon(p) || isTetraquark(p) || isPentaquark(p);
0319 }
0320
0321
0322
0323
0324
0325
0326
0327
0328 bool isGluon(int p) {
0329 return p == GLUON;
0330 }
0331
0332 bool isPhoton(int p) {
0333 return p == PHOTON;
0334 }
0335
0336 bool isZ(int p) {
0337 return p == Z0BOSON;
0338 }
0339
0340
0341
0342
0343
0344
0345
0346 bool isLeptoQuark(int p) {
0347 return std::abs(p) == LEPTOQUARK;
0348 }
0349
0350
0351
0352
0353 bool isGenSpecific(int p) {
0354 if (p >= 81 && p <= 100) {
0355 return true;
0356 }
0357 if (p >= 901 && p <= 930) {
0358 return true;
0359 }
0360 if (p >= 998 && p <= 999) {
0361 return true;
0362 }
0363 if (p >= 1901 && p <= 1930) {
0364 return true;
0365 }
0366 if (p >= 2901 && p <= 2930) {
0367 return true;
0368 }
0369 if (p >= 3901 && p <= 3930) {
0370 return true;
0371 }
0372 return false;
0373 }
0374
0375 bool isGeantino(int p) {
0376 return (std::abs(p) == GEANTINO0 || std::abs(p) == GEANTINOPLUS);
0377 }
0378
0379
0380 bool isGlueball(const DecodedPID& p) {
0381 if (p.ndigits() > 4) {
0382 return false;
0383 }
0384 return ((p.ndigits() == 3 && p(0) == COMPOSITEGLUON &&
0385 p(1) == COMPOSITEGLUON && (p(2) == 1 || p(2) == 5)) ||
0386 (p.ndigits() == 4 && p(0) == COMPOSITEGLUON &&
0387 p(1) == COMPOSITEGLUON && p(2) == COMPOSITEGLUON &&
0388 (p(3) == 3 || p(3) == 7)));
0389 }
0390
0391
0392
0393
0394
0395
0396
0397
0398 bool isSUSY(const DecodedPID& p) {
0399 return (p.ndigits() == 7 && (p(0) == 1 || p(0) == 2) &&
0400 !isGenSpecific(p.shift(2).pid()));
0401 }
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428 bool isRGlueball(const DecodedPID& p) {
0429 if (p.ndigits() != 7 || p(0) != 1) {
0430 return false;
0431 }
0432 auto pp = p.shift(1);
0433 return ((pp.ndigits() == 3 && pp(0) == COMPOSITEGLUON &&
0434 pp(1) == COMPOSITEGLUON && (pp(2) == 1 || pp(2) == 3)) ||
0435 (pp.ndigits() == 4 && pp(0) == COMPOSITEGLUON &&
0436 pp(1) == COMPOSITEGLUON && pp(2) == COMPOSITEGLUON &&
0437 (pp(3) == 1 || pp(3) == 5)));
0438 }
0439
0440
0441
0442
0443 bool isRMeson(const DecodedPID& p) {
0444 if (!(p.ndigits() == 7 && (p(0) == 1 || p(0) == 2))) {
0445 return false;
0446 }
0447 auto pp = p.shift(1);
0448 return (
0449
0450 (pp.ndigits() == 4 && pp(0) == COMPOSITEGLUON &&
0451 pp.max_digit(1, 3) < COMPOSITEGLUON && pp(2) <= pp(1) &&
0452 isSMQuark(pp(1)) && isSMQuark(pp(2)) &&
0453 (pp.last() == 1 || pp.last() == 3)) ||
0454
0455 (pp.ndigits() == 3 && pp.max_digit(1, 3) < COMPOSITEGLUON &&
0456 pp(1) <= pp(0) && isSMQuark(pp(0)) && isSMQuark(pp(1)) &&
0457 pp.last() == 2));
0458 }
0459
0460
0461
0462
0463
0464 bool isRBaryon(const DecodedPID& p) {
0465 if (!(p.ndigits() == 7 && (p(0) == 1 || p(0) == 2))) {
0466 return false;
0467 }
0468 auto pp = p.shift(1);
0469 return (
0470
0471 (pp.ndigits() == 5 && pp(0) == COMPOSITEGLUON &&
0472 pp.max_digit(1, 4) < COMPOSITEGLUON && pp(2) <= pp(1) &&
0473 pp(3) <= pp(2) && isSMQuark(pp(1)) && isSMQuark(pp(2)) &&
0474 isSMQuark(pp(3)) && (pp.last() == 2 || pp.last() == 4)) ||
0475
0476 (pp.ndigits() == 4 && pp.max_digit(1, 4) < COMPOSITEGLUON &&
0477 pp(1) <= pp(0) && pp(2) <= pp(1) && isSMQuark(pp(0)) &&
0478 isSMQuark(pp(1)) && isSMQuark(pp(2)) &&
0479 (pp.last() == 1 || pp.last() == 3)));
0480 }
0481
0482
0483
0484
0485
0486
0487
0488
0489 bool isMonopole(const DecodedPID& p) {
0490 return (p.ndigits() == 7 && p(0) == 4 && p(1) == 1 &&
0491 (p(2) == 1 || p(2) == 2) && p(6) == 0);
0492 }
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503 bool isGenericMultichargedParticle(const DecodedPID& p) {
0504 return (p.ndigits() == 8 && (p(0) == 1 || p(0) == 2) && p(1) == 0 &&
0505 p(2) == 0 && p(7) == 0);
0506 }
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522 bool isNucleus(const DecodedPID& p) {
0523 if (std::abs(p.pid()) == PROTON) {
0524 return true;
0525 }
0526 return (p.ndigits() == 10 && p(0) == 1 && p(1) == 0);
0527 }
0528
0529 int numberOfProtons(const DecodedPID& p) {
0530 if (std::abs(p.pid()) == PROTON) {
0531 return (p.pid() > 0) ? 1 : -1;
0532 }
0533 if (isNucleus(p)) {
0534 const int result = p(5) + 10 * p(4) + 100 * p(3);
0535 return (p.pid() > 0) ? result : -result;
0536 }
0537 return 0;
0538 }
0539
0540 inline int leadingQuark(const DecodedPID& p) {
0541 if (isQuark(p.pid())) {
0542 return std::abs(p.pid());
0543 }
0544 if (isMeson(p)) {
0545 return p.max_digit(1, 3);
0546 }
0547 if (isDiquark(p)) {
0548 return p.max_digit(2, 4);
0549 }
0550 if (isBaryon(p)) {
0551 return p.max_digit(1, 4);
0552 }
0553 if (isTetraquark(p)) {
0554 return p.max_digit(1, 5);
0555 }
0556 if (isPentaquark(p)) {
0557 return p.max_digit(1, 6);
0558 }
0559 if (isSUSY(p)) {
0560 auto pp = p.shift(1);
0561 if (pp.ndigits() == 1) {
0562 return 0;
0563 }
0564 if (pp.ndigits() == 3) {
0565 pp = DecodedPID(pp(1));
0566 }
0567 if (pp.ndigits() > 3) {
0568 pp = pp.shift(1);
0569 }
0570 return leadingQuark(pp);
0571 }
0572 return 0;
0573 }
0574
0575 bool isLightMeson(const DecodedPID& p) {
0576 auto lq = leadingQuark(p);
0577 return (lq == DQUARK || lq == UQUARK || lq == SQUARK) && isMeson(p);
0578 }
0579
0580 bool isStrangeMeson(const DecodedPID& p) {
0581 return leadingQuark(p) == SQUARK && isMeson(p);
0582 }
0583
0584 bool isCharmMeson(const DecodedPID& p) {
0585 return leadingQuark(p) == CQUARK && isMeson(p);
0586 }
0587
0588 bool isBottomMeson(const DecodedPID& p) {
0589 return leadingQuark(p) == BQUARK && isMeson(p);
0590 }
0591
0592 inline bool isCCbarMeson(const DecodedPID& p) {
0593 return leadingQuark(p) == CQUARK && isMeson(p) &&
0594 (*(p.second.rbegin() + 2)) == CQUARK &&
0595 (*(p.second.rbegin() + 1)) == CQUARK;
0596 }
0597
0598 inline bool isBBbarMeson(const DecodedPID& p) {
0599 return leadingQuark(p) == BQUARK && isMeson(p) &&
0600 (*(p.second.rbegin() + 2)) == BQUARK &&
0601 (*(p.second.rbegin() + 1)) == BQUARK;
0602 }
0603
0604 bool isLightBaryon(const DecodedPID& p) {
0605 auto lq = leadingQuark(p);
0606 return (lq == DQUARK || lq == UQUARK || lq == SQUARK) && isBaryon(p);
0607 }
0608
0609 bool isStrangeBaryon(const DecodedPID& p) {
0610 return leadingQuark(p) == SQUARK && isBaryon(p);
0611 }
0612
0613 bool isCharmBaryon(const DecodedPID& p) {
0614 return leadingQuark(p) == CQUARK && isBaryon(p);
0615 }
0616
0617 bool isBottomBaryon(const DecodedPID& p) {
0618 return leadingQuark(p) == BQUARK && isBaryon(p);
0619 }
0620
0621 double fractionalCharge(const DecodedPID& p);
0622 int charge3(const DecodedPID& p);
0623
0624 double charge(const DecodedPID& p) {
0625 if (isGenericMultichargedParticle(
0626 p)) {
0627
0628 return fractionalCharge(p);
0629 } else {
0630 return 1.0 * charge3(p) / 3.0;
0631 }
0632 }
0633
0634 int charge3(const DecodedPID& p) {
0635 auto ap = std::abs(p.pid());
0636 if (ap < TABLESIZE) {
0637 return p.pid() > 0 ? triple_charge.at(ap) : -triple_charge.at(ap);
0638 }
0639 if (ap == K0) {
0640 return 0;
0641 }
0642 if (ap == GEANTINO0) {
0643 return 0;
0644 }
0645 if (ap == GEANTINOPLUS) {
0646 return p.pid() > 0 ? 3 : -3;
0647 }
0648 if (ap == MAVTOP) {
0649 return p.pid() > 0 ? 2 : -2;
0650 }
0651 std::size_t nq = 0;
0652 int sign = 1;
0653 int signmult = 1;
0654 int result = 0;
0655 bool classified = false;
0656 if (!classified && isMeson(p)) {
0657 classified = true;
0658 nq = 2;
0659 if ((*(p.second.rbegin() + 2)) == 2 || (*(p.second.rbegin() + 2)) == 4) {
0660 sign = -1;
0661 }
0662 signmult = -1;
0663 }
0664 if (!classified && isDiquark(p)) {
0665 return triple_charge.at(p(0)) + triple_charge.at(p(1));
0666 }
0667 if (!classified && isBaryon(p)) {
0668 classified = true;
0669 nq = 3;
0670 }
0671 if (!classified && isTetraquark(p)) {
0672 return triple_charge.at(p(3)) + triple_charge.at(p(4)) -
0673 triple_charge.at(p(6)) - triple_charge.at(p(7));
0674 }
0675 if (!classified && isPentaquark(p)) {
0676 return triple_charge.at(p(3)) + triple_charge.at(p(4)) +
0677 triple_charge.at(p(5)) + triple_charge.at(p(6)) -
0678 triple_charge.at(p(7));
0679 }
0680 if (!classified && isNucleus(p)) {
0681 return 3 * numberOfProtons(p);
0682 }
0683 if (!classified && isSUSY(p)) {
0684 nq = 0;
0685 auto pp = p.shift(1);
0686 if (pp.ndigits() < 3) {
0687 return charge3(pp);
0688 }
0689 if (pp(0) == COMPOSITEGLUON) {
0690 if (pp(1) == COMPOSITEGLUON) {
0691 return 0;
0692 }
0693 if (pp.ndigits() == 4 || pp.ndigits() == 5) {
0694 pp = pp.shift(1);
0695 }
0696 }
0697 if (pp.ndigits() == 3) {
0698 classified = true;
0699 nq = 2;
0700 if (p.last() % 2 == 0) {
0701 sign = -1;
0702 }
0703 signmult = -1;
0704 }
0705 if (pp.ndigits() == 4) {
0706 classified = true;
0707 nq = 3;
0708 }
0709 }
0710 if (!classified && isMonopole(p)) {
0711
0712
0713
0714
0715 result = 3 * (p(3) * 100 + p(4) * 10 + p(5));
0716 return ((p.pid() > 0 && p(2) == 1) || (p.pid() < 0 && p(2) == 2)) ? result
0717 : -result;
0718 }
0719 if (!classified && isGenericMultichargedParticle(p)) {
0720 double abs_charge = 0.0;
0721 if (p(0) == 1) {
0722 abs_charge = p(3) * 100. + p(4) * 10. + p(5) * 1 +
0723 p(6) * 0.1;
0724
0725 }
0726 if (p(0) == 2) {
0727 abs_charge = (p(3) * 10. + p(4)) /
0728 (p(5) * 10.0 + p(6));
0729
0730 }
0731 int abs_threecharge = static_cast<int>(std::round(
0732 abs_charge *
0733 3.));
0734
0735
0736 return p.pid() > 0 ? abs_threecharge : -1 * abs_threecharge;
0737 }
0738 for (auto r = p.second.rbegin() + 1; r != p.second.rbegin() + 1 + nq; ++r) {
0739 result += triple_charge.at(*r) * sign;
0740 sign *= signmult;
0741 }
0742 return p.pid() > 0 ? result : -result;
0743 }
0744 double fractionalCharge(const DecodedPID& p) {
0745 if (!isGenericMultichargedParticle(p)) {
0746 return 1.0 * charge3(p) /
0747 3.0;
0748
0749 }
0750 double abs_charge = 0;
0751 if (p(0) == 1) {
0752 abs_charge = p(3) * 100. + p(4) * 10. + p(5) * 1 +
0753 p(6) * 0.1;
0754 }
0755
0756 if (p(0) == 2) {
0757 abs_charge =
0758 (p(3) * 10. + p(4)) /
0759 (p(5) * 10.0 + p(6));
0760 }
0761
0762 return p.pid() > 0 ? abs_charge : -1 * abs_charge;
0763 }
0764
0765
0766 bool isEMInteracting(const DecodedPID& p) {
0767 return (isPhoton(p.pid()) || isZ(p.pid()) || p.pid() == ZPRIME ||
0768 p.pid() == ZDBLPRIME ||
0769 std::abs(charge(p)) > std::numeric_limits<double>::epsilon() ||
0770 isMonopole(p));
0771 }
0772
0773 bool isRHadron(const DecodedPID& p) {
0774 return (isRBaryon(p) || isRMeson(p) || isRGlueball(p));
0775 }
0776
0777 bool isStrongInteracting(const DecodedPID& p) {
0778 return (isGluon(p.pid()) || isQuark(p.pid()) || isDiquark(p) ||
0779 isGlueball(p) || isLeptoQuark(p.pid()) || isHadron(p) ||
0780 isRHadron(p));
0781 }
0782
0783 }
0784
0785
0786 bool ParticleIdHelper::isHadron(PdgParticle pdg) {
0787 DecodedPID p(pdg);
0788 return isMeson(p) || isBaryon(p) || isTetraquark(p) || isPentaquark(p);
0789 }
0790
0791
0792 bool ParticleIdHelper::isLepton(PdgParticle pdg) {
0793 auto sp = std::abs(pdg);
0794 return sp >= 11 && sp <= 18;
0795 }
0796
0797 bool ParticleIdHelper::isMuon(PdgParticle pdg) {
0798 return std::abs(pdg) == MUON;
0799 }
0800
0801 bool ParticleIdHelper::isElectron(PdgParticle pdg) {
0802 return std::abs(pdg) == ELECTRON;
0803 }
0804
0805 bool ParticleIdHelper::isPhoton(PdgParticle pdg) {
0806 return std::abs(pdg) == PHOTON;
0807 }
0808
0809 bool ParticleIdHelper::isTau(PdgParticle pdg) {
0810 return std::abs(pdg) == TAU;
0811 }
0812
0813 HadronType ParticleIdHelper::hadronType(PdgParticle pdg) {
0814 DecodedPID p(pdg);
0815
0816 using enum HadronType;
0817
0818 if (isBBbarMeson(p)) {
0819 return BBbarMeson;
0820 }
0821 if (isCCbarMeson(p)) {
0822 return CCbarMeson;
0823 }
0824 if (isBottomMeson(p)) {
0825 return BottomMeson;
0826 }
0827 if (isCharmMeson(p)) {
0828 return CharmedMeson;
0829 }
0830 if (isBottomBaryon(p)) {
0831 return BottomBaryon;
0832 }
0833 if (isCharmBaryon(p)) {
0834 return CharmedBaryon;
0835 }
0836 if (isStrangeBaryon(p)) {
0837 return StrangeBaryon;
0838 }
0839 if (isLightBaryon(p)) {
0840 return LightBaryon;
0841 }
0842 if (isStrangeMeson(p)) {
0843 return StrangeMeson;
0844 }
0845 if (isLightMeson(p)) {
0846 return LightMeson;
0847 }
0848
0849 return Unknown;
0850 }
0851
0852
0853 bool ParticleIdHelper::isQuark(PdgParticle pdg) {
0854 return pdg != 0 && (std::abs(pdg) <= 8 || std::abs(pdg) == MAVTOP);
0855 }
0856
0857
0858 bool ParticleIdHelper::isInteracting(PdgParticle pdg) {
0859 DecodedPID p(pdg);
0860 return isStrongInteracting(p) || isEMInteracting(p) || isGeantino(pdg);
0861 }
0862
0863 std::ostream& operator<<(std::ostream& os, HadronType hadron) {
0864 switch (hadron) {
0865 using enum HadronType;
0866 case Hadron:
0867 return os << "Hadron";
0868 case BBbarMeson:
0869 return os << "BBbarMeson";
0870 case CCbarMeson:
0871 return os << "CCbarMeson";
0872 case BottomMeson:
0873 return os << "BottomMeson";
0874 case BottomBaryon:
0875 return os << "BottomBaryon";
0876 case CharmedMeson:
0877 return os << "CharmedMeson";
0878 case CharmedBaryon:
0879 return os << "CharmedBaryon";
0880 case StrangeMeson:
0881 return os << "StrangeMeson";
0882 case StrangeBaryon:
0883 return os << "StrangeBaryon";
0884 case LightMeson:
0885 return os << "LightMeson";
0886 case LightBaryon:
0887 return os << "LightBaryon";
0888 case Unknown:
0889 return os << "Unknown";
0890 }
0891 return os;
0892 }
0893 }