Rivet  3.1.2
ParticleIdUtils.hh
1 // -*- C++ -*-
2 //
3 // This file is part of MCUtils -- https://bitbucket.org/andybuckley/mcutils
4 // Copyright (C) 2013-2016 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 
18 namespace Rivet {
19  namespace PID {
20 
21 
24 
27  inline int abspid(int pid) { return abs(pid); }
28 
31  enum Location { nj=1, nq3, nq2, nq1, nl, nr, n, n8, n9, n10 };
32 
34  inline unsigned short _digit(Location loc, int pid) {
35  // PID digits (base 10) are: n nr nl nq1 nq2 nq3 nj (cf. Location)
36  int numerator = (int) std::pow(10.0, (loc-1));
37  return (abs(pid)/numerator) % 10;
38  }
39 
41  inline int _extraBits(int pid) {
42  return abs(pid)/10000000;
43  }
44 
47  inline int _fundamentalID(int pid) {
48  if (_extraBits(pid) > 0) return 0;
49  if (_digit(nq2,pid) == 0 && _digit(nq1,pid) == 0) {
50  return abs(pid) % 10000;
51  } else if (abs(pid) <= 100) {
52  return abs(pid);
53  } else {
54  return 0;
55  }
56  }
57 
59 
60 
61  // Forward declaration
62  inline bool isBSM(int pid);
63 
64 
67 
76  inline bool isNucleus(int pid) {
77  // A proton can also be a Hydrogen nucleus
78  if (abs(pid) == 2212) return true;
79  // New standard: +/- 10LZZZAAAI
80  if (_digit(n10,pid) == 1 && _digit(n9,pid) == 0) {
81  // charge should always be less than or equal to baryon number
82  // the following line is A >= Z
83  if ((abs(pid)/10) % 1000 >= (abs(pid)/10000) % 1000) return true;
84  }
85  return false;
86  }
87 
90  inline int nuclZ(int pid) {
91  // A proton can also be a Hydrogen nucleus
92  if (abs(pid) == 2212) { return 1; }
93  if (isNucleus(pid)) return (abs(pid)/10000) % 1000;
94  return 0;
95  }
96 
99  inline int nuclA(int pid) {
100  // a proton can also be a Hydrogen nucleus
101  if (abs(pid) == 2212) { return 1; }
102  if (isNucleus(pid)) return (abs(pid)/10) % 1000;
103  return 0;
104  }
105 
108  inline int nuclNlambda(int pid) {
109  // a proton can also be a Hydrogen nucleus
110  if (abs(pid) == 2212) { return 0; }
111  if (isNucleus(pid)) return _digit(n8,pid);
112  return 0;
113  }
114 
116 
117 
120 
122  inline bool isQuark(int pid) {
123  return in_closed_range(abs(pid), 1, 8);
124  }
125 
127  inline bool isGluon(int pid) {
128  return pid == GLUON;
129  }
130 
132  inline bool isParton(int pid) {
133  return isGluon(pid) || isQuark(pid);
134  }
135 
136 
138  inline bool isPhoton(int pid) {
139  return pid == PHOTON;
140  }
141 
143  inline bool isElectron(int pid) {
144  return abs(pid) == ELECTRON;
145  }
146 
148  inline bool isMuon(int pid) {
149  return abs(pid) == MUON;
150  }
151 
153  inline bool isTau(int pid) {
154  return abs(pid) == TAU;
155  }
156 
158  inline bool isChargedLepton(int pid) {
159  const long apid = abs(pid);
160  return apid == 11 || apid == 13 || apid == 15 || apid == 17;
161  }
164  inline bool isChLepton(int pid) { return isChargedLepton(pid); }
165 
167  inline bool isNeutrino(int pid) {
168  const long apid = abs(pid);
169  return apid == 12 || apid == 14 || apid == 16 || apid == 18;
170  }
171 
172 
174  inline bool isWplus(int pid) {
175  return pid == WPLUSBOSON;
176  }
177 
179  inline bool isWminus(int pid) {
180  return pid == WMINUSBOSON;
181  }
182 
184  inline bool isW(int pid) {
185  return abs(pid) == WPLUSBOSON;
186  }
187 
189  inline bool isZ(int pid) {
190  return pid == Z0BOSON;
191  }
192 
194  inline bool isHiggs(int pid) {
195  return pid == HIGGSBOSON || pid == 26; //< @todo Check on 26 still needed? (used in HERWIG SUSY, for example)
196  }
197 
199 
200 
202  inline bool isGraviton(int pid) {
203  return pid == GRAVITON;
204  }
205 
206 
207  // /// Determine if the PID is that of a d/dbar
208  // inline bool isDown(int pid) { return abs(pid) == DQUARK; }
209 
210  // /// Determine if the PID is that of a u/ubar
211  // inline bool isUp(int pid) { return abs(pid) == UQUARK; }
212 
214  inline bool isStrange(int pid) { return abs(pid) == SQUARK; }
215 
217  inline bool isCharm(int pid) { return abs(pid) == CQUARK; }
218 
220  inline bool isBottom(int pid) { return abs(pid) == BQUARK; }
221 
223  inline bool isTop(int pid) { return abs(pid) == TQUARK; }
224 
226 
227 
230 
232  inline bool isReggeon(int pid) {
233  return pid == 110 || pid == 990 || pid == 9990;
234  }
235 
237  inline bool isMeson(int pid) {
238  if (_extraBits(pid) > 0) return false;
239  if (isBSM(pid)) return false;
240  const int aid = abs(pid);
241  if (aid == 130 || aid == 310 || aid == 210) return true; //< special cases for kaons
242  if (aid <= 100) return false;
243  if (_digit(nq1,pid) != 0) return false;
244  if (_digit(nq2,pid) == 0) return false;
245  if (_digit(nq3,pid) == 0) return false;
246  if (_digit(nq2,pid) < _digit(nq3,pid)) return false;
247  // EvtGen uses some odd numbers
249  if (aid == 150 || aid == 350 || aid == 510 || aid == 530) return true;
250  // Pomeron, Reggeon, etc.
251  if (isReggeon(pid)) return false; //true; //< WTF?
252  // Check for illegal antiparticles
253  if (_digit(nj,pid) > 0 && _digit(nq3,pid) > 0 && _digit(nq2,pid) > 0 && _digit(nq1,pid) == 0) {
254  return !(_digit(nq3,pid) == _digit(nq2,pid) && pid < 0);
255  }
256  return false;
257  }
258 
260  inline bool isBaryon(int pid) {
261  if (_extraBits(pid) > 0) return false;
262  if (isBSM(pid)) return false;
263  if (abs(pid) <= 100) return false;
264  if (_fundamentalID(pid) <= 100 && _fundamentalID(pid) > 0) return false;
265  if (abs(pid) == 2110 || abs(pid) == 2210) return true;
266  if (_digit(nj,pid) == 0) return false;
267  if (_digit(nq1,pid) == 0 || _digit(nq2,pid) == 0 || _digit(nq3,pid) == 0) return false;
268  return true;
270  // if ((_digit(nq1,pid) >= _digit(nq2,pid) && _digit(nq2,pid) >= _digit(nq3,pid)) ||
271  // (_digit(nq1,pid) > _digit(nq3,pid) && _digit(nq3,pid) > _digit(nq2,pid)) || //< case 6b for lighter quarks in J=1
272  // (_digit(nq3,pid) > _digit(nq1,pid) && _digit(nq1,pid) > _digit(nq2,pid))) //< case 6e for extra states in excited multiplets
273  // return true;
274  // return false;
275  }
276 
277  // Check to see if this is a valid diquark
278  inline bool isDiquark(int pid) {
279  if (_extraBits(pid) > 0) return false;
280  if (isBSM(pid)) return false;
281  if (abs(pid) <= 100) return false;
282  if (_fundamentalID(pid) <= 100 && _fundamentalID(pid) > 0) return false;
283  if (_digit(nq1,pid) == 0) return false;
284  if (_digit(nq2,pid) == 0) return false;
285  if (_digit(nq3,pid) != 0) return false;
286  if (_digit(nq1,pid) < _digit(nq2,pid)) return false;
287  if (_digit(nj,pid) > 0 && _digit(nq3,pid) == 0 && _digit(nq2,pid) > 0 && _digit(nq1,pid) > 0) return true; // diquark signature
288  // EvtGen uses the diquarks for quark pairs, so, for instance, 5501 is a valid "diquark" for EvtGen
289  // if (_digit(nj) == 1 && _digit(nq2) == _digit(nq1)) { // illegal
290  // return false;
291  // } else {
292  // return true;
293  // }
294  return false;
295  }
297  inline bool isDiQuark(int pid) { return isDiquark(pid); }
298 
300  inline bool isPentaquark(int pid) {
301  // a pentaquark is of the form 9abcdej,
302  // where j is the spin and a, b, c, d, and e are quarks
303  if (_extraBits(pid) > 0) return false;
304  if (isBSM(pid)) return false;
305  if (_digit(n,pid) != 9) return false;
306  if (_digit(nr,pid) == 9 || _digit(nr,pid) == 0) return false;
307  if (_digit(nj,pid) == 9 || _digit(nl,pid) == 0) return false;
308  if (_digit(nq1,pid) == 0) return false;
309  if (_digit(nq2,pid) == 0) return false;
310  if (_digit(nq3,pid) == 0) return false;
311  if (_digit(nj,pid) == 0) return false;
312  // check ordering
313  if (_digit(nq2,pid) > _digit(nq1,pid)) return false;
314  if (_digit(nq1,pid) > _digit(nl,pid)) return false;
315  if (_digit(nl,pid) > _digit(nr,pid)) return false;
316  return true;
317  }
318 
322  inline bool isHadron(int pid) {
323  if (_extraBits(pid) > 0) return false;
324  if (isBSM(pid) > 0) return false;
325  if (isMeson(pid)) return true;
326  if (isBaryon(pid)) return true;
327  if (isPentaquark(pid)) return true;
328  return false;
329  }
330 
332 
333 
336 
340  inline bool isLepton(int pid) {
341  if (_extraBits(pid) > 0) return false;
342  if (isBSM(pid) > 0) return false;
343  if (_fundamentalID(pid) >= 11 && _fundamentalID(pid) <= 18) return true;
344  return false;
345  }
346 
348  inline bool isBSMBoson(int pid) {
349  return in_closed_range(abs(pid), 32, 37);
350  }
351 
353  inline bool isSMFundamental(int pid) {
354  return isQuark(pid) || isLepton(pid) ||
355  isGluon(pid) || isPhoton(pid) || isW(pid) || isZ(pid) || isHiggs(pid) ||
356  isBSMBoson(pid) || isGraviton(pid);
357  }
358 
362  inline bool isSUSY(int pid) {
363  // Fundamental SUSY particles have n = 1 or 2
364  if (_extraBits(pid) > 0) return false;
365  if (_digit(n,pid) != 1 && _digit(n,pid) != 2) return false;
366  if (_digit(nr,pid) != 0) return false;
367  // Check fundamental part for SM PID on which it is based
368  const int fundId = _fundamentalID(pid);
369  if (fundId == 0) return false;
370  if (_digit(n,pid) == 1) { // most superpartners, incl LH sfermions
371  return isSMFundamental(fundId);
372  } else if (_digit(n,pid) == 2) { // RH sfermions
373  return isQuark(fundId) || isChargedLepton(fundId);
374  }
375  return true;
376  }
377 
379  inline bool isRHadron(int pid) {
380  // An R-hadron is of the form 10abcdj,
381  // where j is the spin and a, b, c, and d are quarks or gluons
382  if (_extraBits(pid) > 0) return false;
383  if (_digit(n,pid) != 1) return false;
384  if (_digit(nr,pid) != 0) return false;
385  // Make sure this isn't a SUSY particle
386  if (isSUSY(pid)) return false;
387  // All R-hadrons have at least 3 core digits
388  if (_digit(nq2,pid) == 0) return false;
389  if (_digit(nq3,pid) == 0) return false;
390  if (_digit(nj,pid) == 0) return false;
391  return true;
392  }
394  inline bool isRhadron(int pid) { return isRHadron(pid); }
395 
397  inline bool isTechnicolor(int pid) {
398  if (_extraBits(pid) > 0) return false;
399  return _digit(n,pid) == 3;
400  }
401 
403  inline bool isExcited(int pid) {
404  if (_extraBits(pid) > 0) return false;
405  return _digit(n,pid) == 4 && _digit(nr,pid) == 0;
406  }
407 
409  inline bool isKK(int pid) {
410  if (_extraBits(pid) > 0) return false;
411  const int ndigit = _digit(n,pid);
412  return ndigit == 5 || ndigit == 6;
413  }
414 
416  inline bool isLeptoQuark(int pid) {
417  // Many UFO models are extending the PDG standards
418  return abs(pid)==42;
419  }
420 
425  inline bool isDarkMatter(int pid) {
426  const int ndigit = _digit(n,pid);
427  const int nrdigit = _digit(nr,pid);
428  if ((ndigit == 0 && nrdigit == 0) || (ndigit == 5 && nrdigit == 9))
429  return in_closed_range(abs(_fundamentalID(pid)),50,60);
430  return false;
431  }
433  inline bool isDM(int pid) {
434  return isDarkMatter(pid);
435  }
436 
438  inline bool isHiddenValley(int pid) {
439  return (_digit(n,pid) == 4 && _digit(nr,pid) == 9);
440  }
441 
443  inline bool isExotic(int pid){
444  // From the PDG definition, 40-80 reserved for exotic particles
445  // Some overlap with ranges from other functions (e.g. isDM)
446  // Also covers R0 (41)
447  return in_closed_range(abs(pid),40,80);
448  }
449 
451  inline bool isFourthGen(int pid) {
452  return abs(pid) == BPRIME || abs(pid) == TPRIME || abs(pid) == LPRIME || abs(pid) == NUPRIME;
453  }
454 
456  inline bool isMagMonopole(int pid) {
457  if (_digit(n,pid) != 4) return false;
458  if (_digit(nr,pid) != 1) return false;
459  if (_digit(nl,pid) != 1 && _digit(nl,pid) != 2) return false;
460  // Require at least 1 core digit
461  if (_digit(nq3,pid) == 0) { return false; }
462  // Always have spin zero for now
463  if (_digit(nj,pid) != 0) return false;
464  return true;
465  }
467  inline bool isDyon(int pid) {
468  return isMagMonopole(pid);
469  }
470 
473  inline bool isQBall(int pid) {
474  if (_extraBits(pid) != 1) return false;
475  if (_digit(n,pid) != 0) return false;
476  if (_digit(nr,pid) != 0) return false;
477  // Check the core number
478  if ((abs(pid)/10) % 10000 == 0) return false;
479  // These particles have spin zero for now
480  if (_digit(nj,pid) != 0) return false;
481  return true;
482  }
484  inline bool isQball(int pid) {
485  return isQBall(pid);
486  }
487 
489  inline bool isExcitedLepton(int pid) {
490  if (!isExcited(pid)) return false;
491  return isLepton( _fundamentalID(pid) );
492  }
493 
494  // Is this a black hole?
495  inline bool isBlackHole(int pid) {
496  if (_digit(n,pid) != 5 && _digit(n,pid) != 6) return false;
497  if (_digit(nl,pid) != 0) return false;
498  return _fundamentalID(pid)==40;
499  }
500 
502  inline bool isAECO(int pid) {
503  if (_digit( n,pid) != 1) return false;
504  if (_digit(nr,pid) != 0) return false;
505  if (_digit(nl,pid) != 0) return false;
506  if (_digit(nj,pid) != 0) return false;
507  return true;
508  }
509 
511  inline bool isBSM(int pid) {
512  return isSUSY(pid) || isRHadron(pid) || isTechnicolor(pid) ||
513  isExcited(pid) || isKK(pid) || isGraviton(pid) ||
514  isBSMBoson(pid) || isLeptoQuark(pid) || isDM(pid) || isHiddenValley(pid) ||
515  isExotic(pid) || isFourthGen(pid) || isBlackHole(pid) ||
516  isDyon(pid) || isQball(pid) || isAECO(pid);
517  }
518 
520  inline bool _isValid(int pid) {
521  // Starting with 99 means anything goes (but nothing is known)
522  if (_digit(n, pid) == 9 && _digit(nr, pid) == 9) return true;
523  // Check that extra bits are only used for nuclei
524  if (_extraBits(pid) > 0) return (isNucleus(pid) || isQball(pid));
525  // Check that it fits into a standard non-nucleus convention
526  if (isBSM(pid)) return true;
527  if (isHadron(pid)) return true;
528  if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return false; // could only have been a tentative hadron, but !isHadron
529  if (isDiquark(pid)) return true;
530  if (isPentaquark(pid)) return true;
531  if (isReggeon(pid)) return true;
532  // // Quark digit orderings required by the standard
533  // if (_digit(nq1,pid) != 0 && _digit(nq1,pid) < _digit(nq2,pid)) return false;
534  // if (_digit(nq2,pid) != 0 && _digit(nq2,pid) < _digit(nq3,pid)) return false;
535  // Final check on fundamental ID
536  return (_fundamentalID(pid) > 0);
537  }
538  inline bool isValid(int pid) { return _isValid(pid); }
539 
541 
542 
545 
546  inline bool _hasQ(int pid, int q) {
547  if (abs(pid) == q) return true; //< trivial case!
548  if (!_isValid(pid)) return false;
549  // if (_extraBits(pid) > 0) return false;
550  // if (_fundamentalID(pid) > 0) return false;
551  if (isMagMonopole(pid)) return false;
552  if (isRHadron(pid)) {
553  int iz = 7;
554  for (int i = 6; i > 1; --i) {
555  if (_digit(Location(i), pid) == 0) {
556  iz = i;
557  } else if ( i == iz-1 ) {
558  // ignore squark or gluino
559  } else {
560  if (_digit(Location(i),pid) == q) return true;
561  }
562  }
563  return false;
564  }
565  if (_digit(nq3,pid) == q || _digit(nq2,pid) == q || _digit(nq1,pid) == q ) return true;
566  if (isPentaquark(pid)) {
567  if (_digit(nl,pid) == q || _digit(nr,pid) == q) return true;
568  }
569  return false;
570  }
571 
573  inline bool hasDown(int pid) { return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 1); }
575  inline bool hasUp(int pid) { return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 2); }
577  inline bool hasStrange(int pid) { return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 3); }
579  inline bool hasCharm(int pid) { return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 4); }
581  inline bool hasBottom(int pid) { return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 5); }
583  inline bool hasTop(int pid) { return (isHadron(pid) || isQuark(pid)) && _hasQ(pid, 6); }
584 
586 
587 
590 
592  inline bool isHeavyFlavour(int pid) {
593  if (!isHadron(pid) && !isQuark(pid)) return false;
594  return hasCharm(pid) || hasBottom(pid) || hasTop(pid);
595  }
596 
597  // /// Determine if the particle is a light-flavour flavour hadron or parton
598  // inline bool isLightFlavour(int pid) {
599  // return !isHeavyFlavour();
600  // }
601 
603  inline bool isHeavyParton(int pid) {
604  return isParton(pid) && isHeavyFlavour(pid);
605  }
606 
608  inline bool isLightParton(int pid) {
609  return isParton(pid) && !isHeavyFlavour(pid);
610  }
611 
612 
614  inline bool isHeavyMeson(int pid) {
615  return isMeson(pid) && isHeavyFlavour(pid);
616  }
617 
619  inline bool isHeavyBaryon(int pid) {
620  return isBaryon(pid) && isHeavyFlavour(pid);
621  }
622 
624  inline bool isHeavyHadron(int pid) {
625  return isHadron(pid) && isHeavyFlavour(pid);
626  }
627 
629  inline bool isLightMeson(int pid) {
630  return isMeson(pid) && !isHeavyFlavour(pid);
631  }
632 
634  inline bool isLightBaryon(int pid) {
635  return isBaryon(pid) && !isHeavyFlavour(pid);
636  }
637 
639  inline bool isLightHadron(int pid) {
640  return isHadron(pid) && !isHeavyFlavour(pid);
641  }
642 
643 
645  inline bool isBottomMeson(int pid) {
646  return hasBottom(pid) && isMeson(pid);
647  }
648 
650  inline bool isBottomBaryon(int pid) {
651  return hasBottom(pid) && isBaryon(pid);
652  }
653 
655  inline bool isBottomHadron(int pid) {
656  return hasBottom(pid) && isHadron(pid);
657  }
658 
659 
664  inline bool isCharmMeson(int pid) {
665  return isMeson(pid) && hasCharm(pid) &&
666  !hasBottom(pid);
667  }
668 
674  inline bool isCharmBaryon(int pid) {
675  return isBaryon(pid) && hasCharm(pid) &&
676  !hasBottom(pid);
677  }
678 
684  inline bool isCharmHadron(int pid) {
685  return isHadron(pid) && hasCharm(pid) &&
686  !hasBottom(pid);
687  }
688 
689 
694  inline bool isStrangeMeson(int pid) {
695  return isMeson(pid) && hasStrange(pid) &&
696  !(hasBottom(pid) || hasCharm(pid));
697  }
698 
703  inline bool isStrangeBaryon(int pid) {
704  return isBaryon(pid) && hasStrange(pid) &&
705  !(hasBottom(pid) || hasCharm(pid));
706  }
707 
712  inline bool isStrangeHadron(int pid) {
713  return isHadron(pid) && hasStrange(pid) &&
714  !(hasBottom(pid) || hasCharm(pid));
715  }
716 
718 
719 
720 
723 
725  inline int jSpin(int pid) {
726  const int fund = _fundamentalID(pid);
727  if (fund > 0) {
728  // some of these are known
729  if (fund > 0 && fund < 7) return 2;
730  if (fund == 9) return 3;
731  if (fund > 10 && fund < 17) return 2;
732  if (fund > 20 && fund < 25) return 3;
733  return 0;
734  } else if (_extraBits(pid) > 0) {
735  return 0;
736  }
737  return abs(pid) % 10;
738  }
739 
741  inline int sSpin(int pid) {
742  // Handle invalid cases first
743  if (!isMeson(pid)) return 0;
744  if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return 0; // tentative ID
745  // Special generic DM particles with defined spins
746  const int fund = _fundamentalID(pid);
747  if (fund == 51 || fund == 54) return 1;
748  if (fund == 52) return 2;
749  if (fund == 53 || fund == 55) return 3;
750  // Calculate from nl and nj digits
751  const int inl = _digit(nl,pid);
752  const int js = _digit(nj,pid);
753  if (inl == 0 && js >= 3) return 1;
754  else if (inl == 0 && js == 1) return 0;
755  else if (inl == 1 && js >= 3) return 0;
756  else if (inl == 2 && js >= 3) return 1;
757  else if (inl == 1 && js == 1) return 1;
758  else if (inl == 3 && js >= 3) return 1;
759  // Default to zero
760  return 0;
761  }
762 
764  inline int lSpin(int pid) {
765  // Handle invalid cases first
766  if (!isMeson(pid)) return 0;
767  if (_digit(n,pid) == 9 && _digit(nr,pid) == 0) return 0; // tentative ID
768  // Calculate from nl and nj digits
769  const int inl = _digit(nl,pid);
770  const int js = _digit(nj,pid);
771  if (inl == 0 && js == 3) return 0;
772  else if (inl == 0 && js == 5) return 1;
773  else if (inl == 0 && js == 7) return 2;
774  else if (inl == 0 && js == 9) return 3;
775  else if (inl == 0 && js == 1) return 0;
776  else if (inl == 1 && js == 3) return 1;
777  else if (inl == 1 && js == 5) return 2;
778  else if (inl == 1 && js == 7) return 3;
779  else if (inl == 1 && js == 9) return 4;
780  else if (inl == 2 && js == 3) return 1;
781  else if (inl == 2 && js == 5) return 2;
782  else if (inl == 2 && js == 7) return 3;
783  else if (inl == 2 && js == 9) return 4;
784  else if (inl == 1 && js == 1) return 1;
785  else if (inl == 3 && js == 3) return 2;
786  else if (inl == 3 && js == 5) return 3;
787  else if (inl == 3 && js == 7) return 4;
788  else if (inl == 3 && js == 9) return 5;
789  // Default to zero
790  return 0;
791  }
792 
794 
795 
798 
800  inline int charge3(int pid) {
801  static int ch100[100] = { -1, 2, -1, 2, -1, 2, -1, 2, 0, 0,
802  -3, 0, -3, 0, -3, 0, -3, 0, 0, 0,
803  0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
804  0, 0, 0, 3, 0, 0, 3, 0, 0, 0,
805  0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
806  0, 6, 3, 6, 0, 0, 0, 0, 0, 0,
807  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
808  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
809  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
810  0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
811  const unsigned short q1 = _digit(nq1,pid);
812  const unsigned short q2 = _digit(nq2,pid);
813  const unsigned short q3 = _digit(nq3,pid);
814  const unsigned short ql = _digit(nl,pid);
815  const int ida = abs(pid);
816  const int sid = _fundamentalID(pid);
817  int ch3 = 0;
818  if (ida == 0 || _extraBits(pid) > 0) { // ion or illegal
819  return 0;
820  } else if( isQBall(pid) ) { // QBall
821  ch3 = 3*( (ida/10) % 10000);
822  } else if( isHiddenValley(pid) ) { // Hidden Valley
823  return 0;
824  } else if( isDyon(pid) ) { // Dyon
825  ch3 = 3*( (ida/10) % 1000) * (ql == 2 ? -1 : 1); //< NB. charge is flipped at the end if pid < 0
826  } else if (sid > 0 && sid <= 100) { // Use table
827  if (ida == 1000017 || ida == 1000018 || ida == 1000034) ch3 = 0;
828  else if (ida > 1000050 && ida <= 1000060) ch3 = 0; // ?
829  else if (ida > 50 && ida <= 60) ch3 = 0; // Generic DM
830  else if (ida == 5100061 || ida == 5100062) ch3 = 6;
831  else ch3 = ch100[sid-1];
832  } else if (_digit(nj,pid) == 0) { // KL, Ks, or undefined
833  return 0;
834  } else if (isMeson(pid)) { // Mesons
835  ch3 = ((q2 == 3 || q2 == 5) ? -1 : 1) * (ch100[q2-1] - ch100[q3-1]);
836  } else if (isRHadron(pid) ) { // R-hadron
838  if (q1 == 0 || q1 == 9) { //< gluino+q+qbar
839  if (q2 == 3 || q2 == 5) {
840  ch3 = ch100[q3-1] - ch100[q2-1];
841  } else {
842  ch3 = ch100[q2-1] - ch100[q3-1];
843  }
844  } else if (ql == 0) { //< squark+q+q
845  ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
846  } else if (_digit(nr,pid) == 0) { //< squark+q+q+q
847  ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1] + ch100[ql-1];
848  }
849  } else if (isDiQuark(pid)) { // Diquarks
850  ch3 = ch100[q2-1] + ch100[q1-1];
851  } else if (isBaryon(pid)) { // Baryons
852  ch3 = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
853  } else { // Unknown
854  return 0;
855  }
856  if (pid < 0) ch3 *= -1;
857  return ch3;
858  }
859 
862  inline int threeCharge(int pid) { return charge3(pid); }
863 
865  inline int abscharge3(int pid) { return std::abs(charge3(pid)); }
866 
868  inline double charge(int pid) { return charge3(pid)/3.0; }
869 
871  inline double abscharge(int pid) { return std::abs(charge(pid)); }
872 
874 
875 
878 
880  inline bool isCharged(int pid) {
881  return charge3(pid) != 0;
882  }
883 
885  inline bool isNeutral(int pid) {
886  return charge3(pid) == 0;
887  }
888 
890 
891 
894 
896  inline bool isStrongInteracting(int pid) {
897  return isParton(pid) || isHadron(pid);
898  }
899 
901  inline bool isEMInteracting(int pid) {
902  return isCharged(pid) || isPhoton(pid);
903  }
904 
909  inline bool isWeakInteracting(int pid) {
910  return !isGluon(pid) && !isGraviton(pid);
911  }
912 
914 
915 
918 
920  inline bool isGenSpecific(int pid) {
921  return in_range(pid, 80, 101);
922  }
923 
927  inline bool isResonance(int pid) {
928  return isW(pid) || isZ(pid) || isHiggs(pid) || isTop(pid);
929  }
930 
935  inline bool isTransportable(int pid) {
936  // return !isResonance(pid) && !isParton(pid) && !isGenSpecific(pid);
937  return isPhoton(pid) || isHadron(pid) || isLepton(pid);
938  }
939 
941 
942 
945 
946 
947  inline bool isSameSign(PdgId a, PdgId b) { return a*b >= 0; }
948  inline bool isOppSign(PdgId a, PdgId b) { return !isSameSign(a, b); }
949  inline bool isSameFlav(PdgId a, PdgId b) { return abs(a) == abs(b); }
950  inline bool isOppFlav(PdgId a, PdgId b) { return !isSameFlav(a, b); }
951 
952  inline bool isOSSF(PdgId a, PdgId b) { return isOppSign(a, b) && isSameFlav(a, b); }
953  inline bool isSSSF(PdgId a, PdgId b) { return isSameSign(a, b) && isSameFlav(a, b); }
954  inline bool isOSOF(PdgId a, PdgId b) { return isOppSign(a, b) && isOppFlav(a, b); }
955  inline bool isSSOF(PdgId a, PdgId b) { return isSameSign(a, b) && isOppFlav(a, b); }
956 
958 
959 
960  }
961 }
962 
963 #endif
bool isGluon(int pid)
Determine if the PID is that of a gluon.
Definition: ParticleIdUtils.hh:127
Definition: MC_Cent_pPb.hh:10
int abscharge3(int pid)
Return the absolute value of 3 times the EM charge.
Definition: ParticleIdUtils.hh:865
bool isLightBaryon(int pid)
Determine if the PID is that of a light flavour (not b or c) baryon.
Definition: ParticleIdUtils.hh:634
bool isBottomBaryon(int pid)
Determine if the PID is that of a b-baryon.
Definition: ParticleIdUtils.hh:650
int nuclA(int pid)
Definition: ParticleIdUtils.hh:99
bool isPhoton(int pid)
Determine if the PID is that of a photon.
Definition: ParticleIdUtils.hh:138
bool hasDown(int pid)
Does this particle contain a down quark?
Definition: ParticleIdUtils.hh:573
bool isHiggs(int pid)
Determine if the PID is that of an SM/lightest SUSY Higgs.
Definition: ParticleIdUtils.hh:194
bool isElectron(int pid)
Determine if the PID is that of an electron or positron.
Definition: ParticleIdUtils.hh:143
bool isTechnicolor(int pid)
Is this a technicolor particle?
Definition: ParticleIdUtils.hh:397
bool isDiQuark(int pid)
Definition: ParticleIdUtils.hh:297
bool isParton(int pid)
Determine if the PID is that of a parton (quark or gluon)
Definition: ParticleIdUtils.hh:132
bool hasUp(int pid)
Does this particle contain an up quark?
Definition: ParticleIdUtils.hh:575
bool isNeutral(int pid)
Determine if the particle is electrically neutral.
Definition: ParticleIdUtils.hh:885
bool isBSMBoson(int pid)
Is this a valid BSM boson (SUSY Higgs, W&#39;, Z&#39;)?
Definition: ParticleIdUtils.hh:348
int threeCharge(int pid)
Definition: ParticleIdUtils.hh:862
bool isStrange(int pid)
Determine if the PID is that of an s/sbar.
Definition: ParticleIdUtils.hh:214
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:163
bool isWminus(int pid)
Determine if the PID is that of a W-.
Definition: ParticleIdUtils.hh:179
bool isBSM(int pid)
Is this a BSM particle (including graviton)?
Definition: ParticleIdUtils.hh:511
bool isHeavyBaryon(int pid)
Determine if the PID is that of a heavy flavour (b or c) baryon.
Definition: ParticleIdUtils.hh:619
bool isBaryon(int pid)
Check to see if this is a valid baryon.
Definition: ParticleIdUtils.hh:260
double charge(int pid)
Return the EM charge (as floating point)
Definition: ParticleIdUtils.hh:868
bool isCharged(int pid)
Determine if the particle is electrically charged.
Definition: ParticleIdUtils.hh:880
bool isHeavyMeson(int pid)
Determine if the PID is that of a heavy flavour (b or c) meson.
Definition: ParticleIdUtils.hh:614
bool isLightMeson(int pid)
Determine if the PID is that of a light flavour (not b or c) meson.
Definition: ParticleIdUtils.hh:629
bool isLightHadron(int pid)
Determine if the PID is that of a light flavour (not b or c) hadron.
Definition: ParticleIdUtils.hh:639
bool hasStrange(int pid)
Does this particle contain a strange quark?
Definition: ParticleIdUtils.hh:577
bool isMuon(int pid)
Determine if the PID is that of an muon or antimuon.
Definition: ParticleIdUtils.hh:148
bool isSUSY(int pid)
Is this a fundamental SUSY particle?
Definition: ParticleIdUtils.hh:362
bool isMagMonopole(int pid)
Is this from a magnetic monopole or dyon?
Definition: ParticleIdUtils.hh:456
bool isFourthGen(int pid)
Is this a 4th generation particle?
Definition: ParticleIdUtils.hh:451
int pid(const Particle &p)
Unbound function access to PID code.
Definition: ParticleUtils.hh:23
int nuclZ(int pid)
Definition: ParticleIdUtils.hh:90
int lSpin(int pid)
lSpin returns 2L+1, where L is the orbital angular momentum
Definition: ParticleIdUtils.hh:764
bool isDarkMatter(int pid)
Definition: ParticleIdUtils.hh:425
bool isExcitedLepton(int pid)
Is this an excited lepton?
Definition: ParticleIdUtils.hh:489
bool isAECO(int pid)
Is this an anomalously electrically charged particle (AECO)?
Definition: ParticleIdUtils.hh:502
bool isCharm(int pid)
Determine if the PID is that of a c/cbar.
Definition: ParticleIdUtils.hh:217
bool isHadron(int pid)
Definition: ParticleIdUtils.hh:322
bool isBottom(int pid)
Determine if the PID is that of a b/bbar.
Definition: ParticleIdUtils.hh:220
bool isPentaquark(int pid)
Check to see if this is a valid pentaquark.
Definition: ParticleIdUtils.hh:300
bool isDM(int pid)
Convenience alias.
Definition: ParticleIdUtils.hh:433
int charge3(int pid)
Three times the EM charge (as integer)
Definition: ParticleIdUtils.hh:800
bool isBottomHadron(int pid)
Determine if the PID is that of a b-hadron.
Definition: ParticleIdUtils.hh:655
bool isTau(int pid)
Determine if the PID is that of an tau or antitau.
Definition: ParticleIdUtils.hh:153
bool isStrangeBaryon(int pid)
Definition: ParticleIdUtils.hh:703
bool isQBall(int pid)
Definition: ParticleIdUtils.hh:473
bool isQball(int pid)
Alias.
Definition: ParticleIdUtils.hh:484
bool isDyon(int pid)
Just treat a dyon as an alias for magmonopole for now.
Definition: ParticleIdUtils.hh:467
bool isGraviton(int pid)
Is this a graviton?
Definition: ParticleIdUtils.hh:202
bool isRHadron(int pid)
Is this an R-hadron?
Definition: ParticleIdUtils.hh:379
bool isLepton(int pid)
Definition: ParticleIdUtils.hh:340
bool isStrangeMeson(int pid)
Definition: ParticleIdUtils.hh:694
bool isTop(int pid)
Determine if the PID is that of a t/tbar.
Definition: ParticleIdUtils.hh:223
double abscharge(int pid)
Return the EM charge (as floating point)
Definition: ParticleIdUtils.hh:871
bool isReggeon(int pid)
Is this a pomeron, odderon, or generic reggeon?
Definition: ParticleIdUtils.hh:232
bool isW(int pid)
Determine if the PID is that of a W+-.
Definition: ParticleIdUtils.hh:184
int abspid(const Particle &p)
Unbound function access to abs PID code.
Definition: ParticleUtils.hh:26
bool hasBottom(int pid)
Does this particle contain a bottom quark?
Definition: ParticleIdUtils.hh:581
bool isTransportable(int pid)
Definition: ParticleIdUtils.hh:935
Location
Definition: ParticleIdUtils.hh:31
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:173
bool hasCharm(int pid)
Does this particle contain a charm quark?
Definition: ParticleIdUtils.hh:579
bool isHeavyParton(int pid)
Determine if the PID is that of a heavy parton (c,b,t)
Definition: ParticleIdUtils.hh:603
bool isQuark(int pid)
Determine if the PID is that of a quark.
Definition: ParticleIdUtils.hh:122
bool isGenSpecific(int pid)
Determine if the PID is in the generator-specific range.
Definition: ParticleIdUtils.hh:920
bool hasTop(int pid)
Does this particle contain a top quark?
Definition: ParticleIdUtils.hh:583
bool isNucleus(int pid)
Is this a nucleus PID?
Definition: ParticleIdUtils.hh:76
int nuclNlambda(int pid)
Definition: ParticleIdUtils.hh:108
bool isCharmMeson(int pid)
Determine if the PID is that of a c-meson.
Definition: ParticleIdUtils.hh:664
bool isRhadron(int pid)
Alias.
Definition: ParticleIdUtils.hh:394
bool isChLepton(int pid)
Definition: ParticleIdUtils.hh:164
bool isHeavyHadron(int pid)
Determine if the PID is that of a heavy flavour (b or c) hadron.
Definition: ParticleIdUtils.hh:624
bool isWplus(int pid)
Determine if the PID is that of a W+.
Definition: ParticleIdUtils.hh:174
bool isExotic(int pid)
Is this an exotic particle?
Definition: ParticleIdUtils.hh:443
int jSpin(int pid)
jSpin returns 2J+1, where J is the total spin
Definition: ParticleIdUtils.hh:725
bool isKK(int pid)
Is this a Kaluza-Klein excitation?
Definition: ParticleIdUtils.hh:409
bool isCharmHadron(int pid)
Definition: ParticleIdUtils.hh:684
bool isStrongInteracting(int pid)
Determine if the PID is that of a strongly interacting particle.
Definition: ParticleIdUtils.hh:896
bool isLightParton(int pid)
Determine if the PID is that of a light parton (u,d,s)
Definition: ParticleIdUtils.hh:608
bool isSMFundamental(int pid)
Is this an SM fundamental particle?
Definition: ParticleIdUtils.hh:353
bool isZ(int pid)
Determine if the PID is that of a Z0.
Definition: ParticleIdUtils.hh:189
bool isResonance(int pid)
Definition: ParticleIdUtils.hh:927
bool isStrangeHadron(int pid)
Definition: ParticleIdUtils.hh:712
bool isMeson(int pid)
Check to see if this is a valid meson.
Definition: ParticleIdUtils.hh:237
bool isHeavyFlavour(int pid)
Determine if the particle is a heavy flavour hadron or parton.
Definition: ParticleIdUtils.hh:592
bool isEMInteracting(int pid)
Determine if the PID is that of a electromagnetically interacting particle.
Definition: ParticleIdUtils.hh:901
bool isNeutrino(int pid)
Determine if the PID is that of a neutrino.
Definition: ParticleIdUtils.hh:167
bool isLeptoQuark(int pid)
Is this a lepto-quark?
Definition: ParticleIdUtils.hh:416
bool isExcited(int pid)
Is this an excited (composite) quark or lepton?
Definition: ParticleIdUtils.hh:403
bool isCharmBaryon(int pid)
Determine if the PID is that of a c-baryon.
Definition: ParticleIdUtils.hh:674
bool isHiddenValley(int pid)
Is this a Hidden Valley particle.
Definition: ParticleIdUtils.hh:438
bool isWeakInteracting(int pid)
Definition: ParticleIdUtils.hh:909
int sSpin(int pid)
sSpin returns 2S+1, where S is the spin
Definition: ParticleIdUtils.hh:741
bool isChargedLepton(int pid)
Determine if the PID is that of a charged lepton.
Definition: ParticleIdUtils.hh:158
bool isBottomMeson(int pid)
Determine if the PID is that of a b-meson.
Definition: ParticleIdUtils.hh:645