Rivet 3.1.9
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
28 inline int abspid(int pid) {
29 return abs(pid);
30 }
31
32
33 // /// Compile-time int^int power-raising function
34 // template <size_t N>
35 // inline int _intpow(int x) { return x * _intpow<N-1>(x); }
36 // template <>
37 // inline int _intpow<0>(int x) { return 1; }
38
40 // inline size_t _pow10(unsigned int power) {
41 // return (size_t) std::pow(10.0, power);
42 // }
44 inline size_t _pow10(unsigned int power) {
45 //assert(power >= 0 && "_pow10 only defined for positive powers");
46 assert(power < 16 && "_pow10 only defined for powers < 16");
47 static const size_t POWS10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000};
48 return POWS10[power];
49 }
50 // /// Raise 10 to an integer power (constexpr)
51 // inline constexpr size_t _pow10(unsigned int power) {
52 // assert(power >= 0 && "_pow10 only defined for positive powers");
53 // return (power > 0) ? 10*_pow10(power-1) : 1;
54 // }
55
58 enum Location { nj=1, nq3, nq2, nq1, nl, nr, n, n8, n9, n10 };
59
65 inline unsigned short _digit(Location loc, int pid) {
66 const int div = _pow10(loc-1);
67 return (abs(pid)/div) % 10;
68 }
69
71 inline int _extraBits(int pid) {
72 return abs(pid)/10000000;
73 }
74
77 inline int _fundamentalID(int pid) {
78 if (_extraBits(pid) > 0) return 0;
79 if (_digit(nq2,pid) == 0 && _digit(nq1,pid) == 0) {
80 return abs(pid) % 10000;
81 } else if (abs(pid) <= 100) {
82 return abs(pid);
83 } else {
84 return 0;
85 }
86 }
87
89
90
91 // Forward declaration
92 inline bool isBSM(int pid);
93
94
97
106 inline bool isNucleus(int pid) {
107 // A proton can also be a Hydrogen nucleus
108 if (abs(pid) == 2212) return true;
109 // New standard: +/- 10LZZZAAAI
110 if (_digit(n10,pid) == 1 && _digit(n9,pid) == 0) {
111 // charge should always be less than or equal to baryon number
112 // the following line is A >= Z
113 if ((abs(pid)/10) % 1000 >= (abs(pid)/10000) % 1000) return true;
114 }
115 return false;
116 }
117
120 inline int nuclZ(int pid) {
121 // A proton can also be a Hydrogen nucleus
122 if (abs(pid) == 2212) {
123 return 1;
124 }
125 if (isNucleus(pid)) return (abs(pid)/10000) % 1000;
126 return 0;
127 }
129 inline int Z(int pid) {
130 return nuclZ(pid);
131 }
132
135 inline int nuclA(int pid) {
136 // a proton can also be a Hydrogen nucleus
137 if (abs(pid) == 2212) {
138 return 1;
139 }
140 if (isNucleus(pid)) return (abs(pid)/10) % 1000;
141 return 0;
142 }
144 inline int A(int pid) {
145 return nuclA(pid);
146 }
147
150 inline int nuclNlambda(int pid) {
151 // a proton can also be a Hydrogen nucleus
152 if (abs(pid) == 2212) {
153 return 0;
154 }
155 if (isNucleus(pid)) return _digit(n8,pid);
156 return 0;
157 }
159 inline int lambda(int pid) {
160 return nuclNlambda(pid);
161 }
162
164
165
168
170 inline bool isQuark(int pid) {
171 return in_closed_range(abs(pid), 1, 8);
172 }
173
175 inline bool isGluon(int pid) {
176 return pid == GLUON;
177 }
178
180 inline bool isParton(int pid) {
181 return isGluon(pid) || isQuark(pid);
182 }
183
184
186 inline bool isPhoton(int pid) {
187 return pid == PHOTON;
188 }
189
191 inline bool isElectron(int pid) {
192 return abs(pid) == ELECTRON;
193 }
194
196 inline bool isMuon(int pid) {
197 return abs(pid) == MUON;
198 }
199
201 inline bool isTau(int pid) {
202 return abs(pid) == TAU;
203 }
204
206 inline bool isChargedLepton(int pid) {
207 const long apid = abs(pid);
208 return apid == 11 || apid == 13 || apid == 15 || apid == 17;
209 }
212 inline bool isChLepton(int pid) {
213 return isChargedLepton(pid);
214 }
215
217 inline bool isNeutrino(int pid) {
218 const long apid = abs(pid);
219 return apid == 12 || apid == 14 || apid == 16 || apid == 18;
220 }
221
222
224 inline bool isWplus(int pid) {
225 return pid == WPLUSBOSON;
226 }
227
229 inline bool isWminus(int pid) {
230 return pid == WMINUSBOSON;
231 }
232
234 inline bool isW(int pid) {
235 return abs(pid) == WPLUSBOSON;
236 }
237
239 inline bool isZ(int pid) {
240 return pid == Z0BOSON;
241 }
242
244 inline bool isHiggs(int pid) {
245 return pid == HIGGSBOSON || pid == 26; //< @todo Check on 26 still needed? (used in HERWIG SUSY, for example)
246 }
247
249
250
252 inline bool isGraviton(int pid) {
253 return pid == GRAVITON;
254 }
255
256
257 // /// Determine if the PID is that of a d/dbar
258 // inline bool isDown(int pid) { return abs(pid) == DQUARK; }
259
260 // /// Determine if the PID is that of a u/ubar
261 // inline bool isUp(int pid) { return abs(pid) == UQUARK; }
262
264 inline bool isStrange(int pid) {
265 return abs(pid) == SQUARK;
266 }
267
269 inline bool isCharm(int pid) {
270 return abs(pid) == CQUARK;
271 }
272
274 inline bool isBottom(int pid) {
275 return abs(pid) == BQUARK;
276 }
277
279 inline bool isTop(int pid) {
280 return abs(pid) == TQUARK;
281 }
282
284
285
288
290 inline bool isReggeon(int pid) {
291 return pid == 110 || pid == 990 || pid == 9990;
292 }
293
295 inline bool isMeson(int pid) {
296 if (_extraBits(pid) > 0) return false;
297 if (isBSM(pid)) return false;
298 const int aid = abs(pid);
299 if (aid == 130 || aid == 310 || aid == 210) return true; //< special cases for kaons
300 if (aid <= 100) return false;
301 if (_digit(nq1,pid) != 0) return false;
302 if (_digit(nq2,pid) == 0) return false;
303 if (_digit(nq3,pid) == 0) return false;
304 if (_digit(nq2,pid) < _digit(nq3,pid)) return false;
305 // EvtGen uses some odd numbers
307 if (aid == 150 || aid == 350 || aid == 510 || aid == 530) return true;
308 // Pomeron, Reggeon, etc.
309 if (isReggeon(pid)) return false; //true; //< WTF?
310 // Check for illegal antiparticles
311 if (_digit(nj,pid) > 0 && _digit(nq3,pid) > 0 && _digit(nq2,pid) > 0 && _digit(nq1,pid) == 0) {
312 return !(_digit(nq3,pid) == _digit(nq2,pid) && pid < 0);
313 }
314 return false;
315 }
316
318 inline bool isBaryon(int pid) {
319 if (_extraBits(pid) > 0) return false;
320 if (isBSM(pid)) return false;
321 if (abs(pid) <= 100) return false;
322 if (_fundamentalID(pid) <= 100 && _fundamentalID(pid) > 0) return false;
323 if (abs(pid) == 2110 || abs(pid) == 2210) return true;
324 if (_digit(nj,pid) == 0) return false;
325 if (_digit(nq1,pid) == 0 || _digit(nq2,pid) == 0 || _digit(nq3,pid) == 0) return false;
326 return true;
328 // if ((_digit(nq1,pid) >= _digit(nq2,pid) && _digit(nq2,pid) >= _digit(nq3,pid)) ||
329 // (_digit(nq1,pid) > _digit(nq3,pid) && _digit(nq3,pid) > _digit(nq2,pid)) || //< case 6b for lighter quarks in J=1
330 // (_digit(nq3,pid) > _digit(nq1,pid) && _digit(nq1,pid) > _digit(nq2,pid))) //< case 6e for extra states in excited multiplets
331 // return true;
332 // return false;
333 }
334
335 // Check to see if this is a valid diquark
336 inline bool isDiquark(int pid) {
337 if (_extraBits(pid) > 0) return false;
338 if (isBSM(pid)) return false;
339 if (abs(pid) <= 100) return false;
340 if (_fundamentalID(pid) <= 100 && _fundamentalID(pid) > 0) return false;
341 if (_digit(nq1,pid) == 0) return false;
342 if (_digit(nq2,pid) == 0) return false;
343 if (_digit(nq3,pid) != 0) return false;
344 if (_digit(nq1,pid) < _digit(nq2,pid)) return false;
345 if (_digit(nj,pid) > 0 && _digit(nq3,pid) == 0 && _digit(nq2,pid) > 0 && _digit(nq1,pid) > 0) return true; // diquark signature
346 // EvtGen uses the diquarks for quark pairs, so, for instance, 5501 is a valid "diquark" for EvtGen
347 // if (_digit(nj) == 1 && _digit(nq2) == _digit(nq1)) { // illegal
348 // return false;
349 // } else {
350 // return true;
351 // }
352 return false;
353 }
355 inline bool isDiQuark(int pid) {
356 return isDiquark(pid);
357 }
358
360 inline bool isPentaquark(int pid) {
361 // a pentaquark is of the form 9abcdej,
362 // where j is the spin and a, b, c, d, and e are quarks
363 if (_extraBits(pid) > 0) return false;
364 if (isBSM(pid)) return false;
365 if (_digit(n,pid) != 9) return false;
366 if (_digit(nr,pid) == 9 || _digit(nr,pid) == 0) return false;
367 if (_digit(nj,pid) == 9 || _digit(nl,pid) == 0) return false;
368 if (_digit(nq1,pid) == 0) return false;
369 if (_digit(nq2,pid) == 0) return false;
370 if (_digit(nq3,pid) == 0) return false;
371 if (_digit(nj,pid) == 0) return false;
372 // check ordering
373 if (_digit(nq2,pid) > _digit(nq1,pid)) return false;
374 if (_digit(nq1,pid) > _digit(nl,pid)) return false;
375 if (_digit(nl,pid) > _digit(nr,pid)) return false;
376 return true;
377 }
378
382 inline bool isHadron(int pid) {
383 if (_extraBits(pid) > 0) return false;
384 if (isBSM(pid) > 0) return false;
385 if (isMeson(pid)) return true;
386 if (isBaryon(pid)) return true;
387 if (isPentaquark(pid)) return true;
388 return false;
389 }
390
392
393
396
400 inline bool isLepton(int pid) {
401 if (_extraBits(pid) > 0) return false;
402 if (isBSM(pid) > 0) return false;
403 if (_fundamentalID(pid) >= 11 && _fundamentalID(pid) <= 18) return true;
404 return false;
405 }
406
408 inline bool isBSMBoson(int pid) {
409 return in_closed_range(abs(pid), 32, 37);
410 }
411
413 inline bool isSMFundamental(int pid) {
414 return isQuark(pid) || isLepton(pid) ||
415 isGluon(pid) || isPhoton(pid) || isW(pid) || isZ(pid) || isHiggs(pid) ||
417 }
418
422 inline bool isSUSY(int pid) {
423 // Fundamental SUSY particles have n = 1 or 2
424 if (_extraBits(pid) > 0) return false;
425 if (_digit(n,pid) != 1 && _digit(n,pid) != 2) return false;
426 if (_digit(nr,pid) != 0) return false;
427 // Check fundamental part for SM PID on which it is based
428 const int fundId = _fundamentalID(pid);
429 if (fundId == 0) return false;
430 if (_digit(n,pid) == 1) { // most superpartners, incl LH sfermions
431 return isSMFundamental(fundId);
432 } else if (_digit(n,pid) == 2) { // RH sfermions
433 return isQuark(fundId) || isChargedLepton(fundId);
434 }
435 return true;
436 }
437
439 inline bool isRHadron(int pid) {
440 // An R-hadron is of the form 10abcdj,
441 // where j is the spin and a, b, c, and d are quarks or gluons
442 if (_extraBits(pid) > 0) return false;
443 if (_digit(n,pid) != 1) return false;
444 if (_digit(nr,pid) != 0) return false;
445 // Make sure this isn't a SUSY particle
446 if (isSUSY(pid)) return false;
447 // All R-hadrons have at least 3 core digits
448 if (_digit(nq2,pid) == 0) return false;
449 if (_digit(nq3,pid) == 0) return false;
450 if (_digit(nj,pid) == 0) return false;
451 return true;
452 }
454 inline bool isRhadron(int pid) {
455 return isRHadron(pid);
456 }
457
459 inline bool isTechnicolor(int pid) {
460 if (_extraBits(pid) > 0) return false;
461 return _digit(n,pid) == 3;
462 }
463
465 inline bool isExcited(int pid) {
466 if (_extraBits(pid) > 0) return false;
467 return _digit(n,pid) == 4 && _digit(nr,pid) == 0;
468 }
469
471 inline bool isKK(int pid) {
472 if (_extraBits(pid) > 0) return false;
473 const int ndigit = _digit(n,pid);
474 return ndigit == 5 || ndigit == 6;
475 }
476
478 inline bool isLeptoQuark(int pid) {
479 // Many UFO models are extending the PDG standards... is this going to be official?
480 return abs(pid) == 42;
481 }
482
487 inline bool isDarkMatter(int pid) {
488 const int ndigit = _digit(n,pid);
489 const int nrdigit = _digit(nr,pid);
490 if ((ndigit == 0 && nrdigit == 0) || (ndigit == 5 && nrdigit == 9))
491 return in_closed_range(abs(_fundamentalID(pid)),50,60);
492 return false;
493 }
495 inline bool isDM(int pid) {
496 return isDarkMatter(pid);
497 }
498
500 inline bool isHiddenValley(int pid) {
501 return (_digit(n,pid) == 4 && _digit(nr,pid) == 9);
502 }
503
505 inline bool isExotic(int pid) {
506 // From the PDG definition, 40-80 reserved for exotic particles
507 // Some overlap with ranges from other functions (e.g. isDM)
508 // Also covers R0 (41)
509 return in_closed_range(abs(pid),40,80);
510 }
511
513 inline bool isFourthGen(int pid) {
514 return abs(pid) == BPRIME || abs(pid) == TPRIME || abs(pid) == LPRIME || abs(pid) == NUPRIME;
515 }
516
518 inline bool isMagMonopole(int pid) {
519 if (_digit(n,pid) != 4) return false;
520 if (_digit(nr,pid) != 1) return false;
521 if (_digit(nl,pid) != 1 && _digit(nl,pid) != 2) return false;
522 // Require at least 1 core digit
523 // NOT TRUE! Electrically neutral monopoles are possible
524 // if (_digit(nq3,pid) == 0) return false;
525 // Always have spin zero for now
526 if (_digit(nj,pid) != 0) return false;
527 return true;
528 }
530 inline bool isDyon(int pid) {
531 return isMagMonopole(pid);
532 }
533
536 inline bool isQBall(int pid) {
537 if (_extraBits(pid) != 1) return false;
538 if (_digit(n,pid) != 0) return false;
539 if (_digit(nr,pid) != 0) return false;
540 // Check the core number
541 if ((abs(pid)/10) % 10000 == 0) return false;
542 // These particles have spin zero for now
543 if (_digit(nj,pid) != 0) return false;
544 return true;
545 }
547 inline bool isQball(int pid) {
548 return isQBall(pid);
549 }
550
552 inline bool isExcitedLepton(int pid) {
553 if (!isExcited(pid)) return false;
554 return isLepton( _fundamentalID(pid) );
555 }
556
558 inline bool isBlackHole(int pid) {
559 if (_digit(n,pid) != 5 && _digit(n,pid) != 6) return false;
560 if (_digit(nl,pid) != 0) return false;
561 return _fundamentalID(pid)==40;
562 }
563
565 inline bool isAECO(int pid) {
566 if (_digit( n,pid) != 1) return false;
567 if (_digit(nr,pid) != 0) return false;
568 if (_digit(nl,pid) != 0) return false;
569 if (_digit(nj,pid) != 0) return false;
570 return true;
571 }
572
574 inline bool isBSM(int pid) {
575 return isSUSY(pid) || isRHadron(pid) || isTechnicolor(pid) ||
576 isExcited(pid) || isKK(pid) || isGraviton(pid) ||
579 isDyon(pid) || isQball(pid) || isAECO(pid);
580 }
581
583 inline bool _isValid(int pid) {
584 // Starting with 99 means anything goes (but nothing is known)
585 if (_digit(n, pid) == 9 && _digit(nr, pid) == 9) return true;
586 // Check that extra bits are only used for nuclei
587 if (_extraBits(pid) > 0) return (isNucleus(pid) || isQball(pid));
588 // Check that it fits into a standard non-nucleus convention
589 if (isBSM(pid)) return true;
590 if (isHadron(pid)) return true;
591 if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return false; // could only have been a tentative hadron, but !isHadron
592 if (isDiquark(pid)) return true;
593 if (isPentaquark(pid)) return true;
594 if (isReggeon(pid)) return true;
595 // // Quark digit orderings required by the standard
596 // if (_digit(nq1,pid) != 0 && _digit(nq1,pid) < _digit(nq2,pid)) return false;
597 // if (_digit(nq2,pid) != 0 && _digit(nq2,pid) < _digit(nq3,pid)) return false;
598 // Final check on fundamental ID
599 return (_fundamentalID(pid) > 0);
600 }
601 inline bool isValid(int pid) {
602 return _isValid(pid);
603 }
604
606
607
610
611 inline bool _hasQ(int pid, int q) {
612 if (abs(pid) == q) return true; //< trivial case!
613 if (!_isValid(pid)) return false;
614 // if (_extraBits(pid) > 0) return false;
615 // if (_fundamentalID(pid) > 0) return false;
616 if (isMagMonopole(pid)) return false;
617 if (isRHadron(pid)) {
618 int iz = 7;
619 for (int i = 6; i > 1; --i) {
620 if (_digit(Location(i), pid) == 0) {
621 iz = i;
622 } else if ( i == iz-1 ) {
623 // ignore squark or gluino
624 } else {
625 if (_digit(Location(i),pid) == q) return true;
626 }
627 }
628 return false;
629 }
630 if (_digit(nq3,pid) == q || _digit(nq2,pid) == q || _digit(nq1,pid) == q ) return true;
631 if (isPentaquark(pid)) {
632 if (_digit(nl,pid) == q || _digit(nr,pid) == q) return true;
633 }
634 return false;
635 }
636
638 inline bool hasDown(int pid) {
639 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 1);
640 }
642 inline bool hasUp(int pid) {
643 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 2);
644 }
646 inline bool hasStrange(int pid) {
647 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 3);
648 }
650 inline bool hasCharm(int pid) {
651 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 4);
652 }
654 inline bool hasBottom(int pid) {
655 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 5);
656 }
658 inline bool hasTop(int pid) {
659 return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 6);
660 }
661
663
664
667
669 inline bool isHeavyFlavor(int pid) {
670 if (!isHadron(pid) && !isQuark(pid)) return false;
671 return hasCharm(pid) || hasBottom(pid) || hasTop(pid);
672 }
674 inline bool isHeavyFlavour(int pid) {
675 return isHeavyFlavor(pid);
676 }
677
678
679 // /// Determine if the particle is a light-flavour hadron or parton
680 // inline bool isLightFlavor(int pid) {
681 // return !isHeavyFlavor();
682 // }
683
684
686 inline bool isHeavyParton(int pid) {
687 return isParton(pid) && isHeavyFlavor(pid);
688 }
689
691 inline bool isLightParton(int pid) {
692 return isParton(pid) && !isHeavyFlavor(pid);
693 }
694
695
697 inline bool isHeavyMeson(int pid) {
698 return isMeson(pid) && isHeavyFlavor(pid);
699 }
700
702 inline bool isHeavyBaryon(int pid) {
703 return isBaryon(pid) && isHeavyFlavor(pid);
704 }
705
707 inline bool isHeavyHadron(int pid) {
708 return isHadron(pid) && isHeavyFlavor(pid);
709 }
710
712 inline bool isLightMeson(int pid) {
713 return isMeson(pid) && !isHeavyFlavor(pid);
714 }
715
717 inline bool isLightBaryon(int pid) {
718 return isBaryon(pid) && !isHeavyFlavor(pid);
719 }
720
722 inline bool isLightHadron(int pid) {
723 return isHadron(pid) && !isHeavyFlavor(pid);
724 }
725
726
728 inline bool isBottomMeson(int pid) {
729 return hasBottom(pid) && isMeson(pid);
730 }
731
733 inline bool isBottomBaryon(int pid) {
734 return hasBottom(pid) && isBaryon(pid);
735 }
736
738 inline bool isBottomHadron(int pid) {
739 return hasBottom(pid) && isHadron(pid);
740 }
741
742
747 inline bool isCharmMeson(int pid) {
748 return isMeson(pid) && hasCharm(pid) &&
749 !hasBottom(pid);
750 }
751
757 inline bool isCharmBaryon(int pid) {
758 return isBaryon(pid) && hasCharm(pid) &&
759 !hasBottom(pid);
760 }
761
767 inline bool isCharmHadron(int pid) {
768 return isHadron(pid) && hasCharm(pid) &&
769 !hasBottom(pid);
770 }
771
772
777 inline bool isStrangeMeson(int pid) {
778 return isMeson(pid) && hasStrange(pid) &&
779 !(hasBottom(pid) || hasCharm(pid));
780 }
781
786 inline bool isStrangeBaryon(int pid) {
787 return isBaryon(pid) && hasStrange(pid) &&
788 !(hasBottom(pid) || hasCharm(pid));
789 }
790
795 inline bool isStrangeHadron(int pid) {
796 return isHadron(pid) && hasStrange(pid) &&
797 !(hasBottom(pid) || hasCharm(pid));
798 }
799
801
802
803
806
808 inline int jSpin(int pid) {
809 const int fund = _fundamentalID(pid);
810 if (fund > 0) {
811 // some of these are known
812 if (fund > 0 && fund < 7) return 2;
813 if (fund == 9) return 3;
814 if (fund > 10 && fund < 17) return 2;
815 if (fund > 20 && fund < 25) return 3;
816 return 0;
817 } else if (_extraBits(pid) > 0) {
818 return 0;
819 }
820 return abs(pid) % 10;
821 }
822
824 inline int sSpin(int pid) {
825 // Handle invalid cases first
826 if (!isMeson(pid)) return 0;
827 if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return 0; // tentative ID
828 // Special generic DM particles with defined spins
829 const int fund = _fundamentalID(pid);
830 if (fund == 51 || fund == 54) return 1;
831 if (fund == 52) return 2;
832 if (fund == 53 || fund == 55) return 3;
833 // Calculate from nl and nj digits
834 const int inl = _digit(nl,pid);
835 const int js = _digit(nj,pid);
836 if (inl == 0 && js >= 3) return 1;
837 else if (inl == 0 && js == 1) return 0;
838 else if (inl == 1 && js >= 3) return 0;
839 else if (inl == 2 && js >= 3) return 1;
840 else if (inl == 1 && js == 1) return 1;
841 else if (inl == 3 && js >= 3) return 1;
842 // Default to zero
843 return 0;
844 }
845
847 inline int lSpin(int pid) {
848 // Handle invalid cases first
849 if (!isMeson(pid)) return 0;
850 if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return 0; // tentative ID
851 // Calculate from nl and nj digits
852 const int inl = _digit(nl,pid);
853 const int js = _digit(nj,pid);
854 if (inl == 0 && js == 3) return 0;
855 else if (inl == 0 && js == 5) return 1;
856 else if (inl == 0 && js == 7) return 2;
857 else if (inl == 0 && js == 9) return 3;
858 else if (inl == 0 && js == 1) return 0;
859 else if (inl == 1 && js == 3) return 1;
860 else if (inl == 1 && js == 5) return 2;
861 else if (inl == 1 && js == 7) return 3;
862 else if (inl == 1 && js == 9) return 4;
863 else if (inl == 2 && js == 3) return 1;
864 else if (inl == 2 && js == 5) return 2;
865 else if (inl == 2 && js == 7) return 3;
866 else if (inl == 2 && js == 9) return 4;
867 else if (inl == 1 && js == 1) return 1;
868 else if (inl == 3 && js == 3) return 2;
869 else if (inl == 3 && js == 5) return 3;
870 else if (inl == 3 && js == 7) return 4;
871 else if (inl == 3 && js == 9) return 5;
872 // Default to zero
873 return 0;
874 }
875
877
878
881
883 inline int charge3(int pid) {
884 static int ch100[100] = { -1, 2, -1, 2, -1, 2, -1, 2, 0, 0,
885 -3, 0, -3, 0, -3, 0, -3, 0, 0, 0,
886 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
887 0, 0, 0, 3, 0, 0, 3, 0, 0, 0,
888 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
889 0, 6, 3, 6, 0, 0, 0, 0, 0, 0,
890 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
891 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
892 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
893 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
894 };
895 const int ida = abs(pid);
896 // Shortcuts for common particles
897 if (pid == 21 || pid == 22) return 0; // gluon and photon
898 if (ida == 211) return std::signbit(pid) ? -3 : 3; // charged pion
899 if (pid == 111) return 0; // neutral pion
900 // if (ida == 12 || ida == 14 || ida == 16) return 0; // neutrinos
901 // if (ida == 11 || ida == 13 || ida == 15) return std::signbit(pid) ? +3 : -3; // leptons
902 // if (ida == 1 || ida == 3 || ida == 5) return std::signbit(pid) ? +1 : -1; // quarks
903 // if (ida == 2 || ida == 4 || ida == 6) return std::signbit(pid) ? -2 : +2; // quarks
904 // Standard decoding
905 const unsigned short q1 = _digit(nq1,pid);
906 const unsigned short q2 = _digit(nq2,pid);
907 const unsigned short q3 = _digit(nq3,pid);
908 const unsigned short ql = _digit(nl,pid);
909 const int sid = _fundamentalID(pid);
910 int ch3 = 0;
911 if (ida == 0 || _extraBits(pid) > 0) { // ion or illegal
912 return 0;
913 } else if (sid > 0 && sid <= 100) { // Use table
914 if (ida == 1000017 || ida == 1000018 || ida == 1000034) ch3 = 0;
915 else if (ida > 1000050 && ida <= 1000060) ch3 = 0; // ?
916 else if (ida > 50 && ida <= 60) ch3 = 0; // Generic DM
917 else if (ida == 5100061 || ida == 5100062) ch3 = 6;
918 else ch3 = ch100[sid-1];
919 } else if (_digit(nj,pid) == 0) { // KL, Ks, or undefined
920 return 0;
921 } else if (isMeson(pid)) { // Mesons
922 ch3 = ((q2 == 3 || q2 == 5) ? -1 : 1) * (ch100[q2-1] - ch100[q3-1]);
923 } else if (isBaryon(pid)) { // Baryons
924 ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
925 } else if (isQBall(pid) ) { // QBall
926 ch3 = 3*( (ida/10) % 10000);
927 } else if (isHiddenValley(pid) ) { // Hidden Valley
928 return 0;
929 } else if (isDyon(pid) ) { // Dyon
930 ch3 = 3*( (ida/10) % 1000) * (ql == 2 ? -1 : 1); //< NB. charge is flipped at the end if pid < 0
931 } else if (isRHadron(pid) ) { // R-hadron
933 if (q1 == 0 || q1 == 9) { //< gluino+q+qbar
934 if (q2 == 3 || q2 == 5) {
935 ch3 = ch100[q3-1] - ch100[q2-1];
936 } else {
937 ch3 = ch100[q2-1] - ch100[q3-1];
938 }
939 } else if (ql == 0) { //< squark+q+q
940 ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
941 } else if (_digit(nr,pid) == 0) { //< squark+q+q+q
942 ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1] + ch100[ql-1];
943 }
944 } else if (isDiQuark(pid)) { // Diquarks
945 ch3 = ch100[q2-1] + ch100[q1-1];
946 } else { // Unknown
947 return 0;
948 }
949 if (pid < 0) ch3 *= -1;
950 return ch3;
951 }
952
955 inline int threeCharge(int pid) {
956 return charge3(pid);
957 }
958
960 inline int abscharge3(int pid) {
961 return std::abs(charge3(pid));
962 }
963
965 inline double charge(int pid) {
966 return charge3(pid)/3.0;
967 }
968
970 inline double abscharge(int pid) {
971 return std::abs(charge(pid));
972 }
973
975
976
979
981 inline bool isCharged(int pid) {
982 return charge3(pid) != 0;
983 }
984
986 inline bool isNeutral(int pid) {
987 return charge3(pid) == 0;
988 }
989
991
992
995
997 inline bool isStrongInteracting(int pid) {
998 return isParton(pid) || isHadron(pid);
999 }
1000
1002 inline bool isEMInteracting(int pid) {
1003 return isCharged(pid) || isPhoton(pid);
1004 }
1005
1010 inline bool isWeakInteracting(int pid) {
1011 return !isGluon(pid) && !isGraviton(pid);
1012 }
1013
1015
1016
1019
1021 inline bool isGenSpecific(int pid) {
1022 return in_range(pid, 80, 101);
1023 }
1024
1028 inline bool isResonance(int pid) {
1029 return isW(pid) || isZ(pid) || isHiggs(pid) || isTop(pid);
1030 }
1031
1036 inline bool isTransportable(int pid) {
1037 // return !isResonance(pid) && !isParton(pid) && !isGenSpecific(pid);
1038 return isPhoton(pid) || isHadron(pid) || isLepton(pid);
1039 }
1040
1042
1043
1047
1048 inline bool isSameSign(PdgId a, PdgId b) { return a*b >= 0; }
1049 inline bool isOppSign(PdgId a, PdgId b) { return !isSameSign(a, b); }
1050 inline bool isSameFlav(PdgId a, PdgId b) { return abs(a) == abs(b); }
1051 inline bool isOppFlav(PdgId a, PdgId b) { return !isSameFlav(a, b); }
1052
1053 inline bool isOSSF(PdgId a, PdgId b) { return isOppSign(a, b) && isSameFlav(a, b); }
1054 inline bool isSSSF(PdgId a, PdgId b) { return isSameSign(a, b) && isSameFlav(a, b); }
1055 inline bool isOSOF(PdgId a, PdgId b) { return isOppSign(a, b) && isOppFlav(a, b); }
1056 inline bool isSSOF(PdgId a, PdgId b) { return isSameSign(a, b) && isOppFlav(a, b); }
1057
1059
1060
1061 }
1062}
1063
1064#endif
int sSpin(int pid)
sSpin returns 2S+1, where S is the spin
Definition ParticleIdUtils.hh:824
int jSpin(int pid)
jSpin returns 2J+1, where J is the total spin
Definition ParticleIdUtils.hh:808
int lSpin(int pid)
lSpin returns 2L+1, where L is the orbital angular momentum
Definition ParticleIdUtils.hh:847
bool isCharged(int pid)
Determine if the particle is electrically charged.
Definition ParticleIdUtils.hh:981
bool isNeutral(int pid)
Determine if the particle is electrically neutral.
Definition ParticleIdUtils.hh:986
int threeCharge(int pid)
Definition ParticleIdUtils.hh:955
int abscharge3(int pid)
Return the absolute value of 3 times the EM charge.
Definition ParticleIdUtils.hh:960
double charge(int pid)
Return the EM charge (as floating point)
Definition ParticleIdUtils.hh:965
double abscharge(int pid)
Return the EM charge (as floating point)
Definition ParticleIdUtils.hh:970
int charge3(int pid)
Three times the EM charge (as integer)
Definition ParticleIdUtils.hh:883
bool isBottom(int pid)
Determine if the PID is that of a b/bbar.
Definition ParticleIdUtils.hh:274
bool isParton(int pid)
Determine if the PID is that of a parton (quark or gluon)
Definition ParticleIdUtils.hh:180
bool isW(int pid)
Determine if the PID is that of a W+-.
Definition ParticleIdUtils.hh:234
bool isWminus(int pid)
Determine if the PID is that of a W-.
Definition ParticleIdUtils.hh:229
bool isZ(int pid)
Determine if the PID is that of a Z0.
Definition ParticleIdUtils.hh:239
bool isMuon(int pid)
Determine if the PID is that of an muon or antimuon.
Definition ParticleIdUtils.hh:196
bool isHiggs(int pid)
Determine if the PID is that of an SM/lightest SUSY Higgs.
Definition ParticleIdUtils.hh:244
bool isCharm(int pid)
Determine if the PID is that of a c/cbar.
Definition ParticleIdUtils.hh:269
bool isGraviton(int pid)
Is this a graviton?
Definition ParticleIdUtils.hh:252
bool isChLepton(int pid)
Definition ParticleIdUtils.hh:212
bool isTau(int pid)
Determine if the PID is that of an tau or antitau.
Definition ParticleIdUtils.hh:201
bool isGluon(int pid)
Determine if the PID is that of a gluon.
Definition ParticleIdUtils.hh:175
bool isWplus(int pid)
Determine if the PID is that of a W+.
Definition ParticleIdUtils.hh:224
bool isPhoton(int pid)
Determine if the PID is that of a photon.
Definition ParticleIdUtils.hh:186
bool isNeutrino(int pid)
Determine if the PID is that of a neutrino.
Definition ParticleIdUtils.hh:217
bool isElectron(int pid)
Determine if the PID is that of an electron or positron.
Definition ParticleIdUtils.hh:191
bool isChargedLepton(int pid)
Determine if the PID is that of a charged lepton.
Definition ParticleIdUtils.hh:206
bool isQuark(int pid)
Determine if the PID is that of a quark.
Definition ParticleIdUtils.hh:170
bool isTop(int pid)
Determine if the PID is that of a t/tbar.
Definition ParticleIdUtils.hh:279
bool isStrange(int pid)
Determine if the PID is that of an s/sbar.
Definition ParticleIdUtils.hh:264
bool isRHadron(int pid)
Is this an R-hadron?
Definition ParticleIdUtils.hh:439
bool isQBall(int pid)
Definition ParticleIdUtils.hh:536
bool isSMFundamental(int pid)
Is this an SM fundamental particle?
Definition ParticleIdUtils.hh:413
bool isMagMonopole(int pid)
Is this from a magnetic monopole or dyon?
Definition ParticleIdUtils.hh:518
bool isLepton(int pid)
Definition ParticleIdUtils.hh:400
bool isSUSY(int pid)
Is this a fundamental SUSY particle?
Definition ParticleIdUtils.hh:422
bool isKK(int pid)
Is this a Kaluza-Klein excitation?
Definition ParticleIdUtils.hh:471
bool isRhadron(int pid)
Alias.
Definition ParticleIdUtils.hh:454
bool isExotic(int pid)
Is this an exotic particle?
Definition ParticleIdUtils.hh:505
bool isTechnicolor(int pid)
Is this a technicolor particle?
Definition ParticleIdUtils.hh:459
bool isLeptoQuark(int pid)
Is this a lepto-quark?
Definition ParticleIdUtils.hh:478
bool isAECO(int pid)
Is this an anomalously electrically charged particle (AECO)?
Definition ParticleIdUtils.hh:565
bool isExcitedLepton(int pid)
Is this an excited lepton?
Definition ParticleIdUtils.hh:552
bool isBSM(int pid)
Is this a BSM particle (including graviton)?
Definition ParticleIdUtils.hh:574
bool isFourthGen(int pid)
Is this a 4th generation particle?
Definition ParticleIdUtils.hh:513
bool isBSMBoson(int pid)
Is this a valid BSM boson (SUSY Higgs, W', Z')?
Definition ParticleIdUtils.hh:408
bool isExcited(int pid)
Is this an excited (composite) quark or lepton?
Definition ParticleIdUtils.hh:465
bool isDM(int pid)
Convenience alias.
Definition ParticleIdUtils.hh:495
bool isBlackHole(int pid)
Is this a black hole?
Definition ParticleIdUtils.hh:558
bool isHiddenValley(int pid)
Is this a Hidden Valley particle?
Definition ParticleIdUtils.hh:500
bool isQball(int pid)
Alias.
Definition ParticleIdUtils.hh:547
bool isDyon(int pid)
Just treat a dyon as an alias for magmonopole for now.
Definition ParticleIdUtils.hh:530
bool isDarkMatter(int pid)
Definition ParticleIdUtils.hh:487
bool isEMInteracting(int pid)
Determine if the PID is that of a electromagnetically interacting particle.
Definition ParticleIdUtils.hh:1002
bool isWeakInteracting(int pid)
Definition ParticleIdUtils.hh:1010
bool isStrongInteracting(int pid)
Determine if the PID is that of a strongly interacting particle.
Definition ParticleIdUtils.hh:997
int lambda(int pid)
Definition ParticleIdUtils.hh:159
int nuclA(int pid)
Definition ParticleIdUtils.hh:135
int Z(int pid)
Definition ParticleIdUtils.hh:129
int A(int pid)
Definition ParticleIdUtils.hh:144
int nuclNlambda(int pid)
Definition ParticleIdUtils.hh:150
bool isNucleus(int pid)
Is this a nucleus PID?
Definition ParticleIdUtils.hh:106
int nuclZ(int pid)
Definition ParticleIdUtils.hh:120
bool isResonance(int pid)
Definition ParticleIdUtils.hh:1028
bool isGenSpecific(int pid)
Determine if the PID is in the generator-specific range.
Definition ParticleIdUtils.hh:1021
bool isTransportable(int pid)
Definition ParticleIdUtils.hh:1036
bool isLightHadron(int pid)
Determine if the PID is that of a light flavour (not b or c) hadron.
Definition ParticleIdUtils.hh:722
bool isCharmHadron(int pid)
Definition ParticleIdUtils.hh:767
bool isStrangeBaryon(int pid)
Definition ParticleIdUtils.hh:786
bool isHeavyFlavor(int pid)
Determine if the particle is a heavy flavour hadron or parton.
Definition ParticleIdUtils.hh:669
bool isHeavyHadron(int pid)
Determine if the PID is that of a heavy flavour (b or c) hadron.
Definition ParticleIdUtils.hh:707
bool isCharmMeson(int pid)
Determine if the PID is that of a c-meson.
Definition ParticleIdUtils.hh:747
bool isStrangeHadron(int pid)
Definition ParticleIdUtils.hh:795
bool isCharmBaryon(int pid)
Determine if the PID is that of a c-baryon.
Definition ParticleIdUtils.hh:757
bool isHeavyBaryon(int pid)
Determine if the PID is that of a heavy flavour (b or c) baryon.
Definition ParticleIdUtils.hh:702
bool isHeavyMeson(int pid)
Determine if the PID is that of a heavy flavour (b or c) meson.
Definition ParticleIdUtils.hh:697
bool isLightBaryon(int pid)
Determine if the PID is that of a light flavour (not b or c) baryon.
Definition ParticleIdUtils.hh:717
bool isBottomBaryon(int pid)
Determine if the PID is that of a b-baryon.
Definition ParticleIdUtils.hh:733
bool isLightParton(int pid)
Determine if the PID is that of a light parton (u,d,s)
Definition ParticleIdUtils.hh:691
bool isStrangeMeson(int pid)
Definition ParticleIdUtils.hh:777
bool isHeavyParton(int pid)
Determine if the PID is that of a heavy parton (c,b,t)
Definition ParticleIdUtils.hh:686
bool isBottomHadron(int pid)
Determine if the PID is that of a b-hadron.
Definition ParticleIdUtils.hh:738
bool isHeavyFlavour(int pid)
British-spelling alias for isHeavyFlavor.
Definition ParticleIdUtils.hh:674
bool isBottomMeson(int pid)
Determine if the PID is that of a b-meson.
Definition ParticleIdUtils.hh:728
bool isLightMeson(int pid)
Determine if the PID is that of a light flavour (not b or c) meson.
Definition ParticleIdUtils.hh:712
bool hasUp(int pid)
Does this particle contain an up quark?
Definition ParticleIdUtils.hh:642
bool hasTop(int pid)
Does this particle contain a top quark?
Definition ParticleIdUtils.hh:658
bool hasBottom(int pid)
Does this particle contain a bottom quark?
Definition ParticleIdUtils.hh:654
bool hasStrange(int pid)
Does this particle contain a strange quark?
Definition ParticleIdUtils.hh:646
bool hasDown(int pid)
Does this particle contain a down quark?
Definition ParticleIdUtils.hh:638
bool hasCharm(int pid)
Does this particle contain a charm quark?
Definition ParticleIdUtils.hh:650
bool isBaryon(int pid)
Check to see if this is a valid baryon.
Definition ParticleIdUtils.hh:318
bool isDiQuark(int pid)
Definition ParticleIdUtils.hh:355
bool isPentaquark(int pid)
Check to see if this is a valid pentaquark.
Definition ParticleIdUtils.hh:360
bool isMeson(int pid)
Check to see if this is a valid meson.
Definition ParticleIdUtils.hh:295
bool isHadron(int pid)
Definition ParticleIdUtils.hh:382
bool isReggeon(int pid)
Is this a pomeron, odderon, or generic reggeon?
Definition ParticleIdUtils.hh:290
Location
Definition ParticleIdUtils.hh:58
int abspid(int pid)
Definition ParticleIdUtils.hh:28
int pid(const Particle &p)
Unbound function access to PID code.
Definition ParticleUtils.hh:23
Definition MC_Cent_pPb.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