rivet is hosted by Hepforge, IPPP Durham
Rivet 4.0.0
ParticleIdUtils.hh
1// -*- C++ -*-
2//
3// This file is part of MCUtils -- https://gitlab.com/hepcedar/mcutils/
4// Copyright (C) 2013-2022 Andy Buckley <andy.buckley@cern.ch>
5//
6// Embedding of MCUtils code in other projects is permitted provided this
7// notice is retained and the MCUtils namespace and include path are changed.
8//
9#ifndef RIVET_PARTICLEIDUTILS_HH
10#define RIVET_PARTICLEIDUTILS_HH
11
14
15#include "Rivet/Tools/ParticleName.hh"
16#include "Rivet/Math/MathUtils.hh"
17#include <cassert>
18
19namespace Rivet {
20 namespace PID {
21
22
25
26 // /// Compile-time int^int power-raising function
27 // template <size_t N>
28 // inline int _intpow(int x) { return x * _intpow<N-1>(x); }
29 // template <>
30 // inline int _intpow<0>(int x) { return 1; }
31
33 // inline size_t _pow10(unsigned int power) {
34 // return (size_t) std::pow(10.0, power);
35 // }
37 inline size_t _pow10(unsigned int power) {
38 //assert(power >= 0 && "_pow10 only defined for positive powers");
39 assert(power < 16 && "_pow10 only defined for powers < 16");
40 static const size_t POWS10[] = {1, 10, 100, 1000, 10000, 100000, 1000000,
41 10000000, 100000000, 1000000000, 10000000000,
42 100000000000, 1000000000000, 10000000000000,
43 100000000000000, 1000000000000000, 10000000000000000};
44 return POWS10[power];
45 }
46 // /// Raise 10 to an integer power (constexpr)
47 // inline constexpr size_t _pow10(unsigned int power) {
48 // assert(power >= 0 && "_pow10 only defined for positive powers");
49 // return (power > 0) ? 10*_pow10(power-1) : 1;
50 // }
51
54 enum Location { nj=1, nq3, nq2, nq1, nl, nr, n, n8, n9, n10 };
55
61 inline unsigned short _digit(Location loc, int pid) {
62 const int div = _pow10(loc-1);
63 return (abs(pid)/div) % 10;
64 }
65
67 inline int _extraBits(int pid) {
68 return abs(pid)/10000000;
69 }
70
73 inline int _fundamentalID(int pid) {
74 if (_extraBits(pid) > 0) return 0;
75 if (_digit(nq2,pid) == 0 && _digit(nq1,pid) == 0) {
76 return abs(pid) % 10000;
77 } else if (abs(pid) <= 100) {
78 return abs(pid);
79 } else {
80 return 0;
81 }
82 }
83
85
86
87 // Forward declaration
88 inline bool isBSM(int pid);
89
90
93
102 inline bool isNucleus(int pid) {
103 // A proton can also be a Hydrogen nucleus
104 if (abs(pid) == 2212) return true;
105 // New standard: +/- 10LZZZAAAI
106 if (_digit(n10,pid) == 1 && _digit(n9,pid) == 0) {
107 // charge should always be less than or equal to baryon number
108 // the following line is A >= Z
109 if ((abs(pid)/10) % 1000 >= (abs(pid)/10000) % 1000) return true;
110 }
111 return false;
112 }
113
116 inline int nuclZ(int pid) {
117 // A proton can also be a Hydrogen nucleus
118 if (abs(pid) == 2212) {
119 return 1;
120 }
121 if (isNucleus(pid)) return (abs(pid)/10000) % 1000;
122 return 0;
123 }
124
127 inline int nuclA(int pid) {
128 // a proton can also be a Hydrogen nucleus
129 if (abs(pid) == 2212) {
130 return 1;
131 }
132 if (isNucleus(pid)) return (abs(pid)/10) % 1000;
133 return 0;
134 }
135
138 inline int nuclNlambda(int pid) {
139 // a proton can also be a Hydrogen nucleus
140 if (abs(pid) == 2212) {
141 return 0;
142 }
143 if (isNucleus(pid)) return _digit(n8,pid);
144 return 0;
145 }
146
148
149
152
154 inline bool isQuark(int pid) {
155 return in_closed_range(abs(pid), 1, 8);
156 }
157
159 inline bool isGluon(int pid) {
160 return pid == GLUON;
161 }
162
164 inline bool isParton(int pid) {
165 return isGluon(pid) || isQuark(pid);
166 }
167
168
170 inline bool isPhoton(int pid) {
171 return pid == PHOTON;
172 }
173
175 inline bool isElectron(int pid) {
176 return abs(pid) == ELECTRON;
177 }
178
180 inline bool isMuon(int pid) {
181 return abs(pid) == MUON;
182 }
183
185 inline bool isTau(int pid) {
186 return abs(pid) == TAU;
187 }
188
190 inline bool isChargedLepton(int pid) {
191 const long apid = abs(pid);
192 return apid == 11 || apid == 13 || apid == 15 || apid == 17;
193 }
194
196 inline bool isNeutrino(int pid) {
197 const long apid = abs(pid);
198 return apid == 12 || apid == 14 || apid == 16 || apid == 18;
199 }
200
201
203 inline bool isWplus(int pid) {
204 return pid == WPLUSBOSON;
205 }
206
208 inline bool isWminus(int pid) {
209 return pid == WMINUSBOSON;
210 }
211
213 inline bool isW(int pid) {
214 return abs(pid) == WPLUSBOSON;
215 }
216
218 inline bool isZ(int pid) {
219 return pid == Z0BOSON;
220 }
221
223 inline bool isHiggs(int pid) {
224 return pid == HIGGSBOSON || pid == 26; //< @todo Check on 26 still needed? (used in HERWIG SUSY, for example)
225 }
226
228
229
231 inline bool isGraviton(int pid) {
232 return pid == GRAVITON;
233 }
234
235
236 // /// Determine if the PID is that of a d/dbar
237 // inline bool isDown(int pid) { return abs(pid) == DQUARK; }
238
239 // /// Determine if the PID is that of a u/ubar
240 // inline bool isUp(int pid) { return abs(pid) == UQUARK; }
241
243 inline bool isStrange(int pid) {
244 return abs(pid) == SQUARK;
245 }
246
248 inline bool isCharm(int pid) {
249 return abs(pid) == CQUARK;
250 }
251
253 inline bool isBottom(int pid) {
254 return abs(pid) == BQUARK;
255 }
256
258 inline bool isTop(int pid) {
259 return abs(pid) == TQUARK;
260 }
261
263
264
267
269 inline bool isReggeon(int pid) {
270 return pid == 110 || pid == 990 || pid == 9990;
271 }
272
274 inline bool isMeson(int pid) {
275 if (_extraBits(pid) > 0) return false;
276 if (isBSM(pid)) return false;
277 const int aid = abs(pid);
278 if (aid == 130 || aid == 310 || aid == 210) return true; //< special cases for kaons
279 if (aid <= 100) return false;
280 if (_digit(nq1,pid) != 0) return false;
281 if (_digit(nq2,pid) == 0) return false;
282 if (_digit(nq3,pid) == 0) return false;
283 if (_digit(nq2,pid) < _digit(nq3,pid)) return false;
284 // EvtGen uses some odd numbers
286 if (aid == 150 || aid == 350 || aid == 510 || aid == 530) return true;
287 // Pomeron, Reggeon, etc.
288 if (isReggeon(pid)) return false; //true; //< WTF?
289 // Check for illegal antiparticles
290 if (_digit(nj,pid) > 0 && _digit(nq3,pid) > 0 && _digit(nq2,pid) > 0 && _digit(nq1,pid) == 0) {
291 return !(_digit(nq3,pid) == _digit(nq2,pid) && pid < 0);
292 }
293 return false;
294 }
295
297 inline bool isBaryon(int pid) {
298 if (_extraBits(pid) > 0) return false;
299 if (isBSM(pid)) return false;
300 if (abs(pid) <= 100) return false;
301 if (_fundamentalID(pid) <= 100 && _fundamentalID(pid) > 0) return false;
302 if (abs(pid) == 2110 || abs(pid) == 2210) return true;
303 if (_digit(nj,pid) == 0) return false;
304 if (_digit(nq1,pid) == 0 || _digit(nq2,pid) == 0 || _digit(nq3,pid) == 0) return false;
305 return true;
307 // if ((_digit(nq1,pid) >= _digit(nq2,pid) && _digit(nq2,pid) >= _digit(nq3,pid)) ||
308 // (_digit(nq1,pid) > _digit(nq3,pid) && _digit(nq3,pid) > _digit(nq2,pid)) || //< case 6b for lighter quarks in J=1
309 // (_digit(nq3,pid) > _digit(nq1,pid) && _digit(nq1,pid) > _digit(nq2,pid))) //< case 6e for extra states in excited multiplets
310 // return true;
311 // return false;
312 }
313
314 // Check to see if this is a valid diquark
315 inline bool isDiquark(int pid) {
316 if (_extraBits(pid) > 0) return false;
317 if (isBSM(pid)) return false;
318 if (abs(pid) <= 100) return false;
319 if (_fundamentalID(pid) <= 100 && _fundamentalID(pid) > 0) return false;
320 if (_digit(nq1,pid) == 0) return false;
321 if (_digit(nq2,pid) == 0) return false;
322 if (_digit(nq3,pid) != 0) return false;
323 if (_digit(nq1,pid) < _digit(nq2,pid)) return false;
324 if (_digit(nj,pid) > 0 && _digit(nq3,pid) == 0 && _digit(nq2,pid) > 0 && _digit(nq1,pid) > 0) return true; // diquark signature
325 // EvtGen uses the diquarks for quark pairs, so, for instance, 5501 is a valid "diquark" for EvtGen
326 // if (_digit(nj) == 1 && _digit(nq2) == _digit(nq1)) { // illegal
327 // return false;
328 // } else {
329 // return true;
330 // }
331 return false;
332 }
333
335 inline bool isPentaquark(int pid) {
336 // a pentaquark is of the form 9abcdej,
337 // where j is the spin and a, b, c, d, and e are quarks
338 if (_extraBits(pid) > 0) return false;
339 if (isBSM(pid)) return false;
340 if (_digit(n,pid) != 9) return false;
341 if (_digit(nr,pid) == 9 || _digit(nr,pid) == 0) return false;
342 if (_digit(nj,pid) == 9 || _digit(nl,pid) == 0) return false;
343 if (_digit(nq1,pid) == 0) return false;
344 if (_digit(nq2,pid) == 0) return false;
345 if (_digit(nq3,pid) == 0) return false;
346 if (_digit(nj,pid) == 0) return false;
347 // check ordering
348 if (_digit(nq2,pid) > _digit(nq1,pid)) return false;
349 if (_digit(nq1,pid) > _digit(nl,pid)) return false;
350 if (_digit(nl,pid) > _digit(nr,pid)) return false;
351 return true;
352 }
353
357 inline bool isHadron(int pid) {
358 if (_extraBits(pid) > 0) return false;
359 if (isBSM(pid) > 0) return false;
360 if (isMeson(pid)) return true;
361 if (isBaryon(pid)) return true;
362 if (isPentaquark(pid)) return true;
363 return false;
364 }
365
367
368
371
375 inline bool isLepton(int pid) {
376 if (_extraBits(pid) > 0) return false;
377 if (isBSM(pid) > 0) return false;
378 if (_fundamentalID(pid) >= 11 && _fundamentalID(pid) <= 18) return true;
379 return false;
380 }
381
383 inline bool isBSMBoson(int pid) {
384 return in_closed_range(abs(pid), 32, 37);
385 }
386
388 inline bool isSMFundamental(int pid) {
389 return isQuark(pid) || isLepton(pid) ||
390 isGluon(pid) || isPhoton(pid) || isW(pid) || isZ(pid) || isHiggs(pid) ||
392 }
393
397 inline bool isSUSY(int pid) {
398 // Fundamental SUSY particles have n = 1 or 2
399 if (_extraBits(pid) > 0) return false;
400 if (_digit(n,pid) != 1 && _digit(n,pid) != 2) return false;
401 if (_digit(nr,pid) != 0) return false;
402 // Check fundamental part for SM PID on which it is based
403 const int fundId = _fundamentalID(pid);
404 if (fundId == 0) return false;
405 if (_digit(n,pid) == 1) { // most superpartners, incl LH sfermions
406 return isSMFundamental(fundId);
407 } else if (_digit(n,pid) == 2) { // RH sfermions
408 return isQuark(fundId) || isChargedLepton(fundId);
409 }
410 return true;
411 }
412
414 inline bool isRHadron(int pid) {
415 // An R-hadron is of the form 10abcdj,
416 // where j is the spin and a, b, c, and d are quarks or gluons
417 if (_extraBits(pid) > 0) return false;
418 if (_digit(n,pid) != 1) return false;
419 if (_digit(nr,pid) != 0) return false;
420 // Make sure this isn't a SUSY particle
421 if (isSUSY(pid)) return false;
422 // All R-hadrons have at least 3 core digits
423 if (_digit(nq2,pid) == 0) return false;
424 if (_digit(nq3,pid) == 0) return false;
425 if (_digit(nj,pid) == 0) return false;
426 return true;
427 }
429 inline bool isRhadron(int pid) {
430 return isRHadron(pid);
431 }
432
434 inline bool isTechnicolor(int pid) {
435 if (_extraBits(pid) > 0) return false;
436 return _digit(n,pid) == 3;
437 }
438
440 inline bool isExcited(int pid) {
441 if (_extraBits(pid) > 0) return false;
442 return _digit(n,pid) == 4 && _digit(nr,pid) == 0;
443 }
444
446 inline bool isKK(int pid) {
447 if (_extraBits(pid) > 0) return false;
448 const int ndigit = _digit(n,pid);
449 return ndigit == 5 || ndigit == 6;
450 }
451
453 inline bool isLeptoQuark(int pid) {
454 // Many UFO models are extending the PDG standards... is this going to be official?
455 return abs(pid) == 42;
456 }
457
462 inline bool isDarkMatter(int pid) {
463 const int ndigit = _digit(n,pid);
464 const int nrdigit = _digit(nr,pid);
465 if ((ndigit == 0 && nrdigit == 0) || (ndigit == 5 && nrdigit == 9))
466 return in_closed_range(abs(_fundamentalID(pid)),50,60);
467 return false;
468 }
470 inline bool isDM(int pid) {
471 return isDarkMatter(pid);
472 }
473
475 inline bool isHiddenValley(int pid) {
476 return (_digit(n,pid) == 4 && _digit(nr,pid) == 9);
477 }
478
480 inline bool isExotic(int pid) {
481 // From the PDG definition, 40-80 reserved for exotic particles
482 // Some overlap with ranges from other functions (e.g. isDM)
483 // Also covers R0 (41)
484 return in_closed_range(abs(pid),40,80);
485 }
486
488 inline bool isFourthGen(int pid) {
489 return abs(pid) == BPRIME || abs(pid) == TPRIME || abs(pid) == LPRIME || abs(pid) == NUPRIME;
490 }
491
493 inline bool isMagMonopole(int pid) {
494 if (_digit(n,pid) != 4) return false;
495 if (_digit(nr,pid) != 1) return false;
496 if (_digit(nl,pid) != 1 && _digit(nl,pid) != 2) return false;
497 // Require at least 1 core digit
498 // NOT TRUE! Electrically neutral monopoles are possible
499 // if (_digit(nq3,pid) == 0) return false;
500 // Always have spin zero for now
501 if (_digit(nj,pid) != 0) return false;
502 return true;
503 }
505 inline bool isDyon(int pid) {
506 return isMagMonopole(pid);
507 }
508
511 inline bool isQBall(int pid) {
512 if (_extraBits(pid) != 1) return false;
513 if (_digit(n,pid) != 0) return false;
514 if (_digit(nr,pid) != 0) return false;
515 // Check the core number
516 if ((abs(pid)/10) % 10000 == 0) return false;
517 // These particles have spin zero for now
518 if (_digit(nj,pid) != 0) return false;
519 return true;
520 }
522 inline bool isQball(int pid) {
523 return isQBall(pid);
524 }
525
527 inline bool isExcitedLepton(int pid) {
528 if (!isExcited(pid)) return false;
529 return isLepton( _fundamentalID(pid) );
530 }
531
533 inline bool isBlackHole(int pid) {
534 if (_digit(n,pid) != 5 && _digit(n,pid) != 6) return false;
535 if (_digit(nl,pid) != 0) return false;
536 return _fundamentalID(pid)==40;
537 }
538
540 inline bool isAECO(int pid) {
541 if (_digit( n,pid) != 1) return false;
542 if (_digit(nr,pid) != 0) return false;
543 if (_digit(nl,pid) != 0) return false;
544 if (_digit(nj,pid) != 0) return false;
545 return true;
546 }
547
549 inline bool isBSM(int pid) {
550 return isSUSY(pid) || isRHadron(pid) || isTechnicolor(pid) ||
551 isExcited(pid) || isKK(pid) || isGraviton(pid) ||
554 isDyon(pid) || isQball(pid) || isAECO(pid);
555 }
556
558 inline bool _isValid(int pid) {
559 // Starting with 99 means anything goes (but nothing is known)
560 if (_digit(n, pid) == 9 && _digit(nr, pid) == 9) return true;
561 // Check that extra bits are only used for nuclei
562 if (_extraBits(pid) > 0) return (isNucleus(pid) || isQball(pid));
563 // Check that it fits into a standard non-nucleus convention
564 if (isBSM(pid)) return true;
565 if (isHadron(pid)) return true;
566 if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return false; // could only have been a tentative hadron, but !isHadron
567 if (isDiquark(pid)) return true;
568 if (isPentaquark(pid)) return true;
569 if (isReggeon(pid)) return true;
570 // // Quark digit orderings required by the standard
571 // if (_digit(nq1,pid) != 0 && _digit(nq1,pid) < _digit(nq2,pid)) return false;
572 // if (_digit(nq2,pid) != 0 && _digit(nq2,pid) < _digit(nq3,pid)) return false;
573 // Final check on fundamental ID
574 return (_fundamentalID(pid) > 0);
575 }
576 inline bool isValid(int pid) {
577 return _isValid(pid);
578 }
579
581
582
585
586 inline bool _hasQ(int pid, int q) {
587 if (abs(pid) == q) return true; //< trivial case!
588 if (!_isValid(pid)) return false;
589 // if (_extraBits(pid) > 0) return false;
590 // if (_fundamentalID(pid) > 0) return false;
591 if (isMagMonopole(pid)) return false;
592 if (isRHadron(pid)) {
593 int iz = 7;
594 for (int i = 6; i > 1; --i) {
595 if (_digit(Location(i), pid) == 0) {
596 iz = i;
597 } else if ( i == iz-1 ) {
598 // ignore squark or gluino
599 } else {
600 if (_digit(Location(i),pid) == q) return true;
601 }
602 }
603 return false;
604 }
605 if (_digit(nq3,pid) == q || _digit(nq2,pid) == q || _digit(nq1,pid) == q ) return true;
606 if (isPentaquark(pid)) {
607 if (_digit(nl,pid) == q || _digit(nr,pid) == q) return true;
608 }
609 return false;
610 }
611
613 inline bool hasDown(int pid) {
614 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 1);
615 }
617 inline bool hasUp(int pid) {
618 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 2);
619 }
621 inline bool hasStrange(int pid) {
622 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 3);
623 }
625 inline bool hasCharm(int pid) {
626 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 4);
627 }
629 inline bool hasBottom(int pid) {
630 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 5);
631 }
633 inline bool hasTop(int pid) {
634 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 6);
635 }
636
638
639
642
644 inline bool isHeavyFlavor(int pid) {
645 if (!isHadron(pid) && !isQuark(pid)) return false;
646 return hasCharm(pid) || hasBottom(pid) || hasTop(pid);
647 }
649 inline bool isHeavyFlavour(int pid) {
650 return isHeavyFlavor(pid);
651 }
652
653
654 // /// Determine if the particle is a light-flavour hadron or parton
655 // inline bool isLightFlavor(int pid) {
656 // return !isHeavyFlavor();
657 // }
658
659
661 inline bool isHeavyParton(int pid) {
662 return isParton(pid) && isHeavyFlavor(pid);
663 }
664
666 inline bool isLightParton(int pid) {
667 return isParton(pid) && !isHeavyFlavor(pid);
668 }
669
670
672 inline bool isHeavyMeson(int pid) {
673 return isMeson(pid) && isHeavyFlavor(pid);
674 }
675
677 inline bool isHeavyBaryon(int pid) {
678 return isBaryon(pid) && isHeavyFlavor(pid);
679 }
680
682 inline bool isHeavyHadron(int pid) {
683 return isHadron(pid) && isHeavyFlavor(pid);
684 }
685
687 inline bool isLightMeson(int pid) {
688 return isMeson(pid) && !isHeavyFlavor(pid);
689 }
690
692 inline bool isLightBaryon(int pid) {
693 return isBaryon(pid) && !isHeavyFlavor(pid);
694 }
695
697 inline bool isLightHadron(int pid) {
698 return isHadron(pid) && !isHeavyFlavor(pid);
699 }
700
701
703 inline bool isBottomMeson(int pid) {
704 return hasBottom(pid) && isMeson(pid);
705 }
706
708 inline bool isBottomBaryon(int pid) {
709 return hasBottom(pid) && isBaryon(pid);
710 }
711
713 inline bool isBottomHadron(int pid) {
714 return hasBottom(pid) && isHadron(pid);
715 }
716
717
722 inline bool isCharmMeson(int pid) {
723 return isMeson(pid) && hasCharm(pid) &&
724 !hasBottom(pid);
725 }
726
732 inline bool isCharmBaryon(int pid) {
733 return isBaryon(pid) && hasCharm(pid) &&
734 !hasBottom(pid);
735 }
736
742 inline bool isCharmHadron(int pid) {
743 return isHadron(pid) && hasCharm(pid) &&
744 !hasBottom(pid);
745 }
746
747
752 inline bool isStrangeMeson(int pid) {
753 return isMeson(pid) && hasStrange(pid) &&
754 !(hasBottom(pid) || hasCharm(pid));
755 }
756
761 inline bool isStrangeBaryon(int pid) {
762 return isBaryon(pid) && hasStrange(pid) &&
763 !(hasBottom(pid) || hasCharm(pid));
764 }
765
770 inline bool isStrangeHadron(int pid) {
771 return isHadron(pid) && hasStrange(pid) &&
772 !(hasBottom(pid) || hasCharm(pid));
773 }
774
776
777
778
781
783 inline int jSpin(int pid) {
784 const int fund = _fundamentalID(pid);
785 if (fund > 0) {
786 // some of these are known
787 if (fund > 0 && fund < 7) return 2;
788 if (fund == 9) return 3;
789 if (fund > 10 && fund < 17) return 2;
790 if (fund > 20 && fund < 25) return 3;
791 return 0;
792 } else if (_extraBits(pid) > 0) {
793 return 0;
794 }
795 return abs(pid) % 10;
796 }
797
799 inline int sSpin(int pid) {
800 // Handle invalid cases first
801 if (!isMeson(pid)) return 0;
802 if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return 0; // tentative ID
803 // Special generic DM particles with defined spins
804 const int fund = _fundamentalID(pid);
805 if (fund == 51 || fund == 54) return 1;
806 if (fund == 52) return 2;
807 if (fund == 53 || fund == 55) return 3;
808 // Calculate from nl and nj digits
809 const int inl = _digit(nl,pid);
810 const int js = _digit(nj,pid);
811 if (inl == 0 && js >= 3) return 1;
812 else if (inl == 0 && js == 1) return 0;
813 else if (inl == 1 && js >= 3) return 0;
814 else if (inl == 2 && js >= 3) return 1;
815 else if (inl == 1 && js == 1) return 1;
816 else if (inl == 3 && js >= 3) return 1;
817 // Default to zero
818 return 0;
819 }
820
822 inline int lSpin(int pid) {
823 // Handle invalid cases first
824 if (!isMeson(pid)) return 0;
825 if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return 0; // tentative ID
826 // Calculate from nl and nj digits
827 const int inl = _digit(nl,pid);
828 const int js = _digit(nj,pid);
829 if (inl == 0 && js == 3) return 0;
830 else if (inl == 0 && js == 5) return 1;
831 else if (inl == 0 && js == 7) return 2;
832 else if (inl == 0 && js == 9) return 3;
833 else if (inl == 0 && js == 1) return 0;
834 else if (inl == 1 && js == 3) return 1;
835 else if (inl == 1 && js == 5) return 2;
836 else if (inl == 1 && js == 7) return 3;
837 else if (inl == 1 && js == 9) return 4;
838 else if (inl == 2 && js == 3) return 1;
839 else if (inl == 2 && js == 5) return 2;
840 else if (inl == 2 && js == 7) return 3;
841 else if (inl == 2 && js == 9) return 4;
842 else if (inl == 1 && js == 1) return 1;
843 else if (inl == 3 && js == 3) return 2;
844 else if (inl == 3 && js == 5) return 3;
845 else if (inl == 3 && js == 7) return 4;
846 else if (inl == 3 && js == 9) return 5;
847 // Default to zero
848 return 0;
849 }
850
852
853
856
858 inline int charge3(int pid) {
859 static int ch100[100] = { -1, 2, -1, 2, -1, 2, -1, 2, 0, 0,
860 -3, 0, -3, 0, -3, 0, -3, 0, 0, 0,
861 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
862 0, 0, 0, 3, 0, 0, 3, 0, 0, 0,
863 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
864 0, 6, 3, 6, 0, 0, 0, 0, 0, 0,
865 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
866 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
867 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
868 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
869 // Shortcuts for common particles
870 const int ida = abs(pid);
871 if (pid == 21 || pid == 22) return 0; // gluon and photon
872 if (ida == 211) return std::signbit(pid) ? -3 : 3; // charged pion
873 if (pid == 111) return 0; // neutral pion
874 // if (ida == 12 || ida == 14 || ida == 16) return 0; // neutrinos
875 // if (ida == 11 || ida == 13 || ida == 15) return std::signbit(pid) ? +3 : -3; // leptons
876 // if (ida == 1 || ida == 3 || ida == 5) return std::signbit(pid) ? +1 : -1; // quarks
877 // if (ida == 2 || ida == 4 || ida == 6) return std::signbit(pid) ? -2 : +2; // quarks
878 // Standard decoding
879 const unsigned short q1 = _digit(nq1,pid);
880 const unsigned short q2 = _digit(nq2,pid);
881 const unsigned short q3 = _digit(nq3,pid);
882 const unsigned short ql = _digit(nl,pid);
883 const int sid = _fundamentalID(pid);
884 int ch3 = 0;
885 if (ida == 0 || _extraBits(pid) > 0) { // ion or illegal
886 return 0;
887 } else if (sid > 0 && sid <= 100) { // Use table
888 if (ida == 1000017 || ida == 1000018 || ida == 1000034) ch3 = 0;
889 else if (ida > 1000050 && ida <= 1000060) ch3 = 0; // ?
890 else if (ida > 50 && ida <= 60) ch3 = 0; // Generic DM
891 else if (ida == 5100061 || ida == 5100062) ch3 = 6;
892 else ch3 = ch100[sid-1];
893 } else if (_digit(nj,pid) == 0) { // KL, Ks, or undefined
894 return 0;
895 } else if (isMeson(pid)) { // Mesons
896 ch3 = ((q2 == 3 || q2 == 5) ? -1 : 1) * (ch100[q2-1] - ch100[q3-1]);
897 } else if (isBaryon(pid)) { // Baryons
898 ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
899 } else if (isQBall(pid) ) { // QBall
900 ch3 = 3*( (ida/10) % 10000);
901 } else if (isHiddenValley(pid) ) { // Hidden Valley
902 return 0;
903 } else if (isDyon(pid) ) { // Dyon
904 ch3 = 3*( (ida/10) % 1000) * (ql == 2 ? -1 : 1); //< NB. charge is flipped at the end if pid < 0
905 } else if (isRHadron(pid) ) { // R-hadron
907 if (q1 == 0 || q1 == 9) { //< gluino+q+qbar
908 if (q2 == 3 || q2 == 5) {
909 ch3 = ch100[q3-1] - ch100[q2-1];
910 } else {
911 ch3 = ch100[q2-1] - ch100[q3-1];
912 }
913 } else if (ql == 0) { //< squark+q+q
914 ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
915 } else if (_digit(nr,pid) == 0) { //< squark+q+q+q
916 ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1] + ch100[ql-1];
917 }
918 } else if (isDiquark(pid)) { // Diquarks
919 ch3 = ch100[q2-1] + ch100[q1-1];
920 } else { // Unknown
921 return 0;
922 }
923 if (pid < 0) ch3 *= -1;
924 return ch3;
925 }
926
928 inline int abscharge3(int pid) {
929 return std::abs(charge3(pid));
930 }
931
933 inline double charge(int pid) {
934 return charge3(pid)/3.0;
935 }
936
938 inline double abscharge(int pid) {
939 return std::abs(charge(pid));
940 }
941
943
944
947
949 inline bool isCharged(int pid) {
951 if (pid >= -8 && pid <= 8) return true; // quarks and anti-quarks
952 return charge3(pid) != 0; //< pions, photons and gluons already fast in here
953 }
954
956 inline bool isNeutral(int pid) {
957 return !isCharged(pid);
958 }
959
961
962
965
967 inline bool isStrongInteracting(int pid) {
968 return isParton(pid) || isHadron(pid);
969 }
970
972 inline bool isEMInteracting(int pid) {
973 return isCharged(pid) || isPhoton(pid);
974 }
975
980 inline bool isWeakInteracting(int pid) {
981 return !isGluon(pid) && !isGraviton(pid);
982 }
983
985
986
989
991 inline bool isGenSpecific(int pid) {
992 return in_range(pid, 80, 101);
993 }
994
999 inline bool isResonance(int pid) {
1000 return isW(pid) || isZ(pid) || isHiggs(pid) || isTop(pid);
1001 }
1002
1007 inline bool isTransportable(int pid) {
1008 // return !isResonance(pid) && !isParton(pid) && !isGenSpecific(pid);
1009 return isPhoton(pid) || isHadron(pid) || isLepton(pid);
1010 }
1011
1013
1014
1018
1019 inline bool isSameSign(PdgId a, PdgId b) { return a*b >= 0; }
1020 inline bool isOppSign(PdgId a, PdgId b) { return !isSameSign(a, b); }
1021 inline bool isSameFlav(PdgId a, PdgId b) { return abs(a) == abs(b); }
1022 inline bool isOppFlav(PdgId a, PdgId b) { return !isSameFlav(a, b); }
1023
1024 inline bool isOSSF(PdgId a, PdgId b) { return isOppSign(a, b) && isSameFlav(a, b); }
1025 inline bool isSSSF(PdgId a, PdgId b) { return isSameSign(a, b) && isSameFlav(a, b); }
1026 inline bool isOSOF(PdgId a, PdgId b) { return isOppSign(a, b) && isOppFlav(a, b); }
1027 inline bool isSSOF(PdgId a, PdgId b) { return isSameSign(a, b) && isOppFlav(a, b); }
1028
1030
1031
1032 }
1033}
1034
1035#endif
int sSpin(int pid)
sSpin returns 2S+1, where S is the spin
Definition ParticleIdUtils.hh:799
int jSpin(int pid)
jSpin returns 2J+1, where J is the total spin
Definition ParticleIdUtils.hh:783
int lSpin(int pid)
lSpin returns 2L+1, where L is the orbital angular momentum
Definition ParticleIdUtils.hh:822
bool isCharged(int pid)
Determine if the particle is electrically charged.
Definition ParticleIdUtils.hh:949
bool isNeutral(int pid)
Determine if the particle is electrically neutral.
Definition ParticleIdUtils.hh:956
int abscharge3(int pid)
Return the absolute value of 3 times the EM charge.
Definition ParticleIdUtils.hh:928
double charge(int pid)
Return the EM charge (as floating point)
Definition ParticleIdUtils.hh:933
double abscharge(int pid)
Return the EM charge (as floating point)
Definition ParticleIdUtils.hh:938
int charge3(int pid)
Three times the EM charge (as integer)
Definition ParticleIdUtils.hh:858
bool isBottom(int pid)
Determine if the PID is that of a b/bbar.
Definition ParticleIdUtils.hh:253
bool isParton(int pid)
Determine if the PID is that of a parton (quark or gluon)
Definition ParticleIdUtils.hh:164
bool isW(int pid)
Determine if the PID is that of a W+-.
Definition ParticleIdUtils.hh:213
bool isWminus(int pid)
Determine if the PID is that of a W-.
Definition ParticleIdUtils.hh:208
bool isZ(int pid)
Determine if the PID is that of a Z0.
Definition ParticleIdUtils.hh:218
bool isMuon(int pid)
Determine if the PID is that of an muon or antimuon.
Definition ParticleIdUtils.hh:180
bool isHiggs(int pid)
Determine if the PID is that of an SM/lightest SUSY Higgs.
Definition ParticleIdUtils.hh:223
bool isCharm(int pid)
Determine if the PID is that of a c/cbar.
Definition ParticleIdUtils.hh:248
bool isGraviton(int pid)
Is this a graviton?
Definition ParticleIdUtils.hh:231
bool isTau(int pid)
Determine if the PID is that of an tau or antitau.
Definition ParticleIdUtils.hh:185
bool isGluon(int pid)
Determine if the PID is that of a gluon.
Definition ParticleIdUtils.hh:159
bool isWplus(int pid)
Determine if the PID is that of a W+.
Definition ParticleIdUtils.hh:203
bool isPhoton(int pid)
Determine if the PID is that of a photon.
Definition ParticleIdUtils.hh:170
bool isNeutrino(int pid)
Determine if the PID is that of a neutrino.
Definition ParticleIdUtils.hh:196
bool isElectron(int pid)
Determine if the PID is that of an electron or positron.
Definition ParticleIdUtils.hh:175
bool isChargedLepton(int pid)
Determine if the PID is that of a charged lepton.
Definition ParticleIdUtils.hh:190
bool isQuark(int pid)
Determine if the PID is that of a quark.
Definition ParticleIdUtils.hh:154
bool isTop(int pid)
Determine if the PID is that of a t/tbar.
Definition ParticleIdUtils.hh:258
bool isStrange(int pid)
Determine if the PID is that of an s/sbar.
Definition ParticleIdUtils.hh:243
bool isRHadron(int pid)
Is this an R-hadron?
Definition ParticleIdUtils.hh:414
bool isQBall(int pid)
Definition ParticleIdUtils.hh:511
bool isSMFundamental(int pid)
Is this an SM fundamental particle?
Definition ParticleIdUtils.hh:388
bool isMagMonopole(int pid)
Is this from a magnetic monopole or dyon?
Definition ParticleIdUtils.hh:493
bool isLepton(int pid)
Definition ParticleIdUtils.hh:375
bool isSUSY(int pid)
Is this a fundamental SUSY particle?
Definition ParticleIdUtils.hh:397
bool isKK(int pid)
Is this a Kaluza-Klein excitation?
Definition ParticleIdUtils.hh:446
bool isRhadron(int pid)
Alias.
Definition ParticleIdUtils.hh:429
bool isExotic(int pid)
Is this an exotic particle?
Definition ParticleIdUtils.hh:480
bool isTechnicolor(int pid)
Is this a technicolor particle?
Definition ParticleIdUtils.hh:434
bool isLeptoQuark(int pid)
Is this a lepto-quark?
Definition ParticleIdUtils.hh:453
bool isAECO(int pid)
Is this an anomalously electrically charged particle (AECO)?
Definition ParticleIdUtils.hh:540
bool isExcitedLepton(int pid)
Is this an excited lepton?
Definition ParticleIdUtils.hh:527
bool isBSM(int pid)
Is this a BSM particle (including graviton)?
Definition ParticleIdUtils.hh:549
bool isFourthGen(int pid)
Is this a 4th generation particle?
Definition ParticleIdUtils.hh:488
bool isBSMBoson(int pid)
Is this a valid BSM boson (SUSY Higgs, W', Z')?
Definition ParticleIdUtils.hh:383
bool isExcited(int pid)
Is this an excited (composite) quark or lepton?
Definition ParticleIdUtils.hh:440
bool isDM(int pid)
Convenience alias.
Definition ParticleIdUtils.hh:470
bool isBlackHole(int pid)
Is this a black hole?
Definition ParticleIdUtils.hh:533
bool isHiddenValley(int pid)
Is this a Hidden Valley particle?
Definition ParticleIdUtils.hh:475
bool isQball(int pid)
Alias.
Definition ParticleIdUtils.hh:522
bool isDyon(int pid)
Just treat a dyon as an alias for magmonopole for now.
Definition ParticleIdUtils.hh:505
bool isDarkMatter(int pid)
Definition ParticleIdUtils.hh:462
bool isEMInteracting(int pid)
Determine if the PID is that of a electromagnetically interacting particle.
Definition ParticleIdUtils.hh:972
bool isWeakInteracting(int pid)
Definition ParticleIdUtils.hh:980
bool isStrongInteracting(int pid)
Determine if the PID is that of a strongly interacting particle.
Definition ParticleIdUtils.hh:967
int nuclA(int pid)
Definition ParticleIdUtils.hh:127
int nuclNlambda(int pid)
Definition ParticleIdUtils.hh:138
bool isNucleus(int pid)
Is this a nucleus PID?
Definition ParticleIdUtils.hh:102
int nuclZ(int pid)
Definition ParticleIdUtils.hh:116
bool isResonance(int pid)
Definition ParticleIdUtils.hh:999
bool isGenSpecific(int pid)
Determine if the PID is in the generator-specific range.
Definition ParticleIdUtils.hh:991
bool isTransportable(int pid)
Definition ParticleIdUtils.hh:1007
bool isLightHadron(int pid)
Determine if the PID is that of a light flavour (not b or c) hadron.
Definition ParticleIdUtils.hh:697
bool isCharmHadron(int pid)
Definition ParticleIdUtils.hh:742
bool isStrangeBaryon(int pid)
Definition ParticleIdUtils.hh:761
bool isHeavyFlavor(int pid)
Determine if the particle is a heavy flavour hadron or parton.
Definition ParticleIdUtils.hh:644
bool isHeavyHadron(int pid)
Determine if the PID is that of a heavy flavour (b or c) hadron.
Definition ParticleIdUtils.hh:682
bool isCharmMeson(int pid)
Determine if the PID is that of a c-meson.
Definition ParticleIdUtils.hh:722
bool isStrangeHadron(int pid)
Definition ParticleIdUtils.hh:770
bool isCharmBaryon(int pid)
Determine if the PID is that of a c-baryon.
Definition ParticleIdUtils.hh:732
bool isHeavyBaryon(int pid)
Determine if the PID is that of a heavy flavour (b or c) baryon.
Definition ParticleIdUtils.hh:677
bool isHeavyMeson(int pid)
Determine if the PID is that of a heavy flavour (b or c) meson.
Definition ParticleIdUtils.hh:672
bool isLightBaryon(int pid)
Determine if the PID is that of a light flavour (not b or c) baryon.
Definition ParticleIdUtils.hh:692
bool isBottomBaryon(int pid)
Determine if the PID is that of a b-baryon.
Definition ParticleIdUtils.hh:708
bool isLightParton(int pid)
Determine if the PID is that of a light parton (u,d,s)
Definition ParticleIdUtils.hh:666
bool isStrangeMeson(int pid)
Definition ParticleIdUtils.hh:752
bool isHeavyParton(int pid)
Determine if the PID is that of a heavy parton (c,b,t)
Definition ParticleIdUtils.hh:661
bool isBottomHadron(int pid)
Determine if the PID is that of a b-hadron.
Definition ParticleIdUtils.hh:713
bool isHeavyFlavour(int pid)
British-spelling alias for isHeavyFlavor.
Definition ParticleIdUtils.hh:649
bool isBottomMeson(int pid)
Determine if the PID is that of a b-meson.
Definition ParticleIdUtils.hh:703
bool isLightMeson(int pid)
Determine if the PID is that of a light flavour (not b or c) meson.
Definition ParticleIdUtils.hh:687
bool hasUp(int pid)
Does this particle contain an up quark?
Definition ParticleIdUtils.hh:617
bool hasTop(int pid)
Does this particle contain a top quark?
Definition ParticleIdUtils.hh:633
bool hasBottom(int pid)
Does this particle contain a bottom quark?
Definition ParticleIdUtils.hh:629
bool hasStrange(int pid)
Does this particle contain a strange quark?
Definition ParticleIdUtils.hh:621
bool hasDown(int pid)
Does this particle contain a down quark?
Definition ParticleIdUtils.hh:613
bool hasCharm(int pid)
Does this particle contain a charm quark?
Definition ParticleIdUtils.hh:625
bool isBaryon(int pid)
Check to see if this is a valid baryon.
Definition ParticleIdUtils.hh:297
bool isPentaquark(int pid)
Check to see if this is a valid pentaquark.
Definition ParticleIdUtils.hh:335
bool isMeson(int pid)
Check to see if this is a valid meson.
Definition ParticleIdUtils.hh:274
bool isHadron(int pid)
Definition ParticleIdUtils.hh:357
bool isReggeon(int pid)
Is this a pomeron, odderon, or generic reggeon?
Definition ParticleIdUtils.hh:269
Location
Definition ParticleIdUtils.hh:54
int pid(const Particle &p)
Unbound function access to PID code.
Definition ParticleUtils.hh:23
Definition MC_CENT_PPB_Projections.hh:10
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&std::is_arithmetic< N3 >::value, bool >::type in_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition MathUtils.hh:184
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&std::is_arithmetic< N3 >::value, bool >::type in_closed_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition MathUtils.hh:194