rivet is hosted by Hepforge, IPPP Durham
ParticleIdUtils.hh
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // This file is part of MCUtils -- https://bitbucket.org/andybuckley/mcutils
00004 // Copyright (C) 2013-2014 Andy Buckley <andy.buckley@cern.ch>
00005 //
00006 // Embedding of MCUtils code in other projects is permitted provided this
00007 // notice is retained and the MCUtils namespace and include path are changed.
00008 //
00009 #ifndef RIVET_PARTICLEIDUTILS_HH
00010 #define RIVET_PARTICLEIDUTILS_HH
00011 
00012 /// @file Utility functions for querying PDG ID codes (many from HepPID)
00013 /// @author Andy Buckley <andy.buckley@cern.ch>
00014 
00015 //#include "Rivet/Tools/MCUtils/PIDCodes.h"
00016 #include "Rivet/Math/MathUtils.hh"
00017 
00018 namespace Rivet {
00019   namespace PID {
00020 
00021 
00022     /// @name Utility functions
00023     //@{
00024 
00025     /// Absolute value (just use abs()!)
00026     inline int abspid(int pid) {
00027       return abs(pid);
00028     }
00029 
00030     ///  PID digits (base 10) are: n nr nl nq1 nq2 nq3 nj
00031     ///  The Location enum provides a convenient index into the PID.
00032     enum Location { nj=1, nq3, nq2, nq1, nl, nr, n, n8, n9, n10 };
00033 
00034     /// Split the PID into constituent integers
00035     inline unsigned short digit(Location loc, int pid) {
00036       //  PID digits (base 10) are: n nr nl nq1 nq2 nq3 nj (cf. Location)
00037       int numerator = (int) std::pow(10.0, (loc-1));
00038       return (abspid(pid)/numerator) % 10;
00039     }
00040 
00041     /// Returns everything beyond the 7th digit (e.g. outside the numbering scheme)
00042     inline int extraBits(int pid) {
00043       return abspid(pid)/10000000;
00044     }
00045 
00046     /// @brief Return the first two digits if this is a "fundamental" particle
00047     /// @note ID = 100 is a special case (internal generator ID's are 81-100)
00048     inline int fundamentalID(int pid) {
00049       if (extraBits(pid) > 0) return 0;
00050       if (digit(nq2,pid) == 0 && digit(nq1,pid) == 0) {
00051         return abspid(pid) % 10000;
00052       } else if (abspid(pid) <= 100) {
00053         return abspid(pid);
00054       } else {
00055         return 0;
00056       }
00057     }
00058 
00059     //@}
00060 
00061 
00062     /// @name Nucleus/ion functions
00063     //@{
00064 
00065     /// @brief Is this a nucleus PID?
00066     ///
00067     /// This implements the 2006 Monte Carlo nuclear code scheme.
00068     /// Ion numbers are +/- 10LZZZAAAI.
00069     /// AAA is A - total baryon number
00070     /// ZZZ is Z - total charge
00071     /// L is the total number of strange quarks.
00072     /// I is the isomer number, with I=0 corresponding to the ground state.
00073     inline bool isNucleus(int pid) {
00074       // a proton can also be a Hydrogen nucleus
00075       if (abspid(pid) == 2212) { return true; }
00076       // new standard: +/- 10LZZZAAAI
00077       if ((digit(n10,pid) == 1) && (digit(n9,pid) == 0)) {
00078         // charge should always be less than or equal to baryon number
00079         // the following line is A >= Z
00080         if ((abspid(pid)/10)%1000 >= (abspid(pid)/10000)%1000) { return true; }
00081       }
00082       return false;
00083     }
00084 
00085     /// Get the atomic number (number of protons) in a nucleus/ion
00086     /// @note Ion numbers are +/- 10LZZZAAAI.
00087     inline int Z(int pid) {
00088       // A proton can also be a Hydrogen nucleus
00089       if (abspid(pid) == 2212) { return 1; }
00090       if (isNucleus(pid)) return (abspid(pid)/10000)%1000;
00091       return 0;
00092     }
00093 
00094     /// Get the atomic weight (number of nucleons) in a nucleus/ion
00095     /// @note Ion numbers are +/- 10LZZZAAAI.
00096     inline int A(int pid) {
00097       // a proton can also be a Hydrogen nucleus
00098       if (abspid(pid) == 2212) { return 1; }
00099       if (isNucleus(pid)) return (abspid(pid)/10)%1000;
00100       return 0;
00101     }
00102 
00103     /// If this is a nucleus (ion), get nLambda
00104     /// @note Ion numbers are +/- 10LZZZAAAI.
00105     inline int lambda(int pid) {
00106       // a proton can also be a Hydrogen nucleus
00107       if (abspid(pid) == 2212) { return 0; }
00108       if (isNucleus(pid)) return digit(n8,pid);
00109       return 0;
00110     }
00111 
00112     //@}
00113 
00114 
00115     /// @name Quark composite functions
00116     //@{
00117 
00118     /// Check to see if this is a valid meson
00119     inline bool isMeson(int pid) {
00120       if (extraBits(pid) > 0) { return false; }
00121       if (abspid(pid) <= 100) { return false; }
00122       if (fundamentalID(pid) <= 100 && fundamentalID(pid) > 0) { return false; }
00123       int aid = abspid(pid);
00124       if (aid == 130 || aid == 310 || aid == 210) { return true; }
00125       // EvtGen uses some odd numbers
00126       if (aid == 150 || aid == 350 || aid == 510 || aid == 530) { return true; }
00127       // pomeron, etc.
00128       if (pid == 110 || pid == 990 || pid == 9990) { return true; }
00129       if (digit(nj,pid) > 0 && digit(nq3,pid) > 0 && digit(nq2,pid) > 0 && digit(nq1,pid) == 0) {
00130         // check for illegal antiparticles
00131         if (digit(nq3,pid) == digit(nq2,pid) && pid < 0) {
00132           return false;
00133         } else {
00134           return true;
00135         }
00136       }
00137       return false;
00138     }
00139 
00140     /// Check to see if this is a valid baryon
00141     inline bool isBaryon(int pid) {
00142       if (extraBits(pid) > 0) { return false; }
00143       if (abspid(pid) <= 100) { return false; }
00144       if (fundamentalID(pid) <= 100 && fundamentalID(pid) > 0) { return false; }
00145       if (abspid(pid) == 2110 || abspid(pid) == 2210) { return true; }
00146       if (digit(nj,pid) > 0  && digit(nq3,pid) > 0 && digit(nq2,pid) > 0 && digit(nq1,pid) > 0) { return true; }
00147       return false;
00148     }
00149 
00150     // Check to see if this is a valid diquark
00151     inline bool isDiquark(int pid) {
00152       if (extraBits(pid) > 0) { return false; }
00153       if (abspid(pid) <= 100) { return false; }
00154       if (fundamentalID(pid) <= 100 && fundamentalID(pid) > 0) { return false; }
00155       if (digit(nj,pid) > 0  && digit(nq3,pid) == 0 && digit(nq2,pid) > 0 && digit(nq1,pid) > 0) {  // diquark signature
00156         // EvtGen uses the diquarks for quark pairs, so, for instance,
00157         //   5501 is a valid "diquark" for EvtGen
00158         //if (digit(nj) == 1 && digit(nq2) == digit(nq1)) {    // illegal
00159         //   return false;
00160         //} else {
00161         return true;
00162         //}
00163       }
00164       return false;
00165     }
00166     inline bool isDiQuark(int pid) { return isDiquark(pid); }
00167 
00168     /// Check to see if this is a valid pentaquark
00169     inline bool isPentaquark(int pid) {
00170       // a pentaquark is of the form 9abcdej,
00171       // where j is the spin and a, b, c, d, and e are quarks
00172       if (extraBits(pid) > 0) { return false; }
00173       if (digit(n,pid) != 9)  { return false; }
00174       if (digit(nr,pid) == 9 || digit(nr,pid) == 0)  { return false; }
00175       if (digit(nj,pid) == 9 || digit(nl,pid) == 0)  { return false; }
00176       if (digit(nq1,pid) == 0)  { return false; }
00177       if (digit(nq2,pid) == 0)  { return false; }
00178       if (digit(nq3,pid) == 0)  { return false; }
00179       if (digit(nj,pid) == 0)  { return false; }
00180       // check ordering
00181       if (digit(nq2,pid) > digit(nq1,pid))  { return false; }
00182       if (digit(nq1,pid) > digit(nl,pid))  { return false; }
00183       if (digit(nl,pid) > digit(nr,pid))  { return false; }
00184       return true;
00185     }
00186 
00187     /// Is this a valid hadron ID?
00188     inline bool isHadron(int pid) {
00189       if (extraBits(pid) > 0) { return false; }
00190       if (isMeson(pid))   { return true; }
00191       if (isBaryon(pid))  { return true; }
00192       if (isPentaquark(pid)) { return true; }
00193       return false;
00194     }
00195 
00196     //@}
00197 
00198 
00199     /// @name More general particle class identification functions
00200     //@{
00201 
00202     /// Is this a valid lepton ID?
00203     inline bool isLepton(int pid) {
00204       if (extraBits(pid) > 0) { return false; }
00205       if (fundamentalID(pid) >= 11 && fundamentalID(pid) <= 18) { return true; }
00206       return false;
00207     }
00208 
00209     /// Is this a fundamental SUSY particle?
00210     inline bool isSUSY(int pid) {
00211       // fundamental SUSY particles have n = 1 or 2
00212       if (extraBits(pid) > 0) { return false; }
00213       if (digit(n,pid) != 1 && digit(n,pid) != 2)  { return false; }
00214       if (digit(nr,pid) != 0)  { return false; }
00215       // check fundamental part
00216       if (fundamentalID(pid) == 0)  { return false; }
00217       return true;
00218     }
00219 
00220     /// Is this an R-hadron?
00221     inline bool isRhadron(int pid) {
00222       // an R-hadron is of the form 10abcdj,
00223       // where j is the spin and a, b, c, and d are quarks or gluons
00224       if (extraBits(pid) > 0) { return false; }
00225       if (digit(n,pid) != 1)  { return false; }
00226       if (digit(nr,pid) != 0)  { return false; }
00227       // make sure this isn't a SUSY particle
00228       if (isSUSY(pid)) { return false; }
00229       // All R-hadrons have at least 3 core digits
00230       if (digit(nq2,pid) == 0)  { return false; }
00231       if (digit(nq3,pid) == 0)  { return false; }
00232       if (digit(nj,pid) == 0)  { return false; }
00233       return true;
00234     }
00235     inline bool isRHadron(int pid) { return isRhadron(pid); }
00236 
00237     /// Is this a technicolor particle?
00238     inline bool isTechnicolor(int pid) {
00239       if (extraBits(pid) > 0) { return false; }
00240       return digit(n,pid) == 3;
00241     }
00242 
00243     /// Is this an excited (composite) quark or lepton?
00244     inline bool isExcited(int pid) {
00245       if (extraBits(pid) > 0) { return false; }
00246       return digit(n,pid) == 4;
00247     }
00248 
00249     /// Is this a Kaluza-Klein excitation?
00250     inline bool isKK(int pid) {
00251       if (extraBits(pid) > 0) { return false; }
00252       const int ndigit = digit(n,pid);
00253       return ndigit == 5 || ndigit == 6;
00254     }
00255 
00256     /// Is this a graviton?
00257     inline bool isGraviton(int pid) {
00258       return pid == 39;
00259     }
00260 
00261     /// Is this a BSM particle (including graviton)?
00262     inline bool isBSM(int pid) {
00263       return isSUSY(pid) || isRhadron(pid) || isTechnicolor(pid) ||
00264         isExcited(pid) || isKK(pid) || isGraviton(pid);
00265     }
00266 
00267     /// Is this a pomeron, odderon, or generic reggeon?
00268     inline bool isReggeon(int pid) {
00269       return pid == 110 || pid == 990 || pid == 9990;
00270     }
00271 
00272     /// Check to see if this is a valid PID (i.e. matches any known scheme)
00273     inline bool isValid(int pid) {
00274       if (extraBits(pid) > 0) {
00275         if (isNucleus(pid)) return true;
00276         return false;
00277       }
00278       if (isBSM(pid)) return true;
00279       if (isHadron(pid)) return true;
00280       if (isDiquark(pid)) return true;
00281       if (fundamentalID(pid) > 0) {
00282         return true;
00283         // AB - disabled this to remove need for PID -> name lookup.
00284         // if (pid > 0) return true; else return hasFundamentalAnti(pid);
00285       }
00286       // Don't recognize this number
00287       return false;
00288     }
00289 
00290     //@}
00291 
00292 
00293     /// @name Parton content functions
00294     //@{
00295 
00296     /// Does this particle contain an up quark?
00297     inline bool hasUp(const int & pid) {
00298       if (extraBits(pid) > 0) { return false; }
00299       if (fundamentalID(pid) > 0) { return false; }
00300       if (digit(nq3,pid) == 2 || digit(nq2,pid) == 2 || digit(nq1,pid) == 2) return true;
00301       return false;
00302     }
00303     /// Does this particle contain a down quark?
00304     inline bool hasDown(const int & pid) {
00305       if (extraBits(pid) > 0) { return false; }
00306       if (fundamentalID(pid) > 0) { return false; }
00307       if (digit(nq3,pid) == 1 || digit(nq2,pid) == 1 || digit(nq1,pid) == 1) return true;
00308       return false;
00309     }
00310     /// Does this particle contain a strange quark?
00311     inline bool hasStrange(int pid) {
00312       if (extraBits(pid) > 0) { return false; }
00313       if (fundamentalID(pid) > 0) { return false; }
00314       if (digit(nq3,pid) == 3 || digit(nq2,pid) == 3 || digit(nq1,pid) == 3) return true;
00315       return false;
00316     }
00317     /// Does this particle contain a charm quark?
00318     inline bool hasCharm(int pid) {
00319       if (extraBits(pid) > 0) { return false; }
00320       if (fundamentalID(pid) > 0) { return false; }
00321       if (digit(nq3,pid) == 4 || digit(nq2,pid) == 4 || digit(nq1,pid) == 4) return true;
00322       return false;
00323     }
00324     /// Does this particle contain a bottom quark?
00325     inline bool hasBottom(int pid) {
00326       if (extraBits(pid) > 0) { return false; }
00327       if (fundamentalID(pid) > 0) { return false; }
00328       if (digit(nq3,pid) == 5 || digit(nq2,pid) == 5 || digit(nq1,pid) == 5) return true;
00329       return false;
00330     }
00331     /// Does this particle contain a top quark?
00332     inline bool hasTop(int pid) {
00333       if (extraBits(pid) > 0) { return false; }
00334       if (fundamentalID(pid) > 0) { return false; }
00335       if (digit(nq3,pid) == 6 || digit(nq2,pid) == 6 || digit(nq1,pid) == 6) return true;
00336       return false;
00337     }
00338 
00339     //@}
00340 
00341 
00342     /// @name Angular momentum functions
00343     //@{
00344 
00345     /// jSpin returns 2J+1, where J is the total spin
00346     inline int jSpin(int pid) {
00347       if (fundamentalID(pid) > 0) {
00348         // some of these are known
00349         int fund = fundamentalID(pid);
00350         if (fund > 0 && fund < 7) return 2;
00351         if (fund == 9) return 3;
00352         if (fund > 10 && fund < 17) return 2;
00353         if (fund > 20 && fund < 25) return 3;
00354         return 0;
00355       } else if (extraBits(pid) > 0) {
00356         return 0;
00357       }
00358       return abspid(pid)%10;
00359     }
00360 
00361     /// sSpin returns 2S+1, where S is the spin
00362     inline int  sSpin(int pid) {
00363       if (!isMeson(pid)) { return 0; }
00364       int inl = digit(nl,pid);
00365       //int tent = digit(n,pid);
00366       int js = digit(nj,pid);
00367       if (digit(n,pid) == 9) { return 0; } // tentative ID
00368       //if (tent == 9) { return 0; }   // tentative assignment
00369       if (inl == 0 && js >= 3) {
00370         return 1;
00371       } else if (inl == 0  && js == 1) {
00372         return 0;
00373       } else if (inl == 1  && js >= 3) {
00374         return 0;
00375       } else if (inl == 2  && js >= 3) {
00376         return 1;
00377       } else if (inl == 1  && js == 1) {
00378         return 1;
00379       } else if (inl == 3  && js >= 3) {
00380         return 1;
00381       }
00382       // Default to zero
00383       return 0;
00384     }
00385 
00386     /// lSpin returns 2L+1, where L is the orbital angular momentum
00387     inline int lSpin(int pid) {
00388       if (!isMeson(pid)) { return 0; }
00389       int inl = digit(nl,pid);
00390       //int tent = digit(n,pid);
00391       int js = digit(nj,pid);
00392       if (digit(n,pid) == 9) { return 0; } // tentative ID
00393       if (inl == 0 && js == 3) {
00394         return 0;
00395       } else if (inl == 0 && js == 5) {
00396         return 1;
00397       } else if (inl == 0 && js == 7) {
00398         return 2;
00399       } else if (inl == 0 && js == 9) {
00400         return 3;
00401       } else if (inl == 0  && js == 1) {
00402         return 0;
00403       } else if (inl == 1  && js == 3) {
00404         return 1;
00405       } else if (inl == 1  && js == 5) {
00406         return 2;
00407       } else if (inl == 1  && js == 7) {
00408         return 3;
00409       } else if (inl == 1  && js == 9) {
00410         return 4;
00411       } else if (inl == 2  && js == 3) {
00412         return 1;
00413       } else if (inl == 2  && js == 5) {
00414         return 2;
00415       } else if (inl == 2  && js == 7) {
00416         return 3;
00417       } else if (inl == 2  && js == 9) {
00418         return 4;
00419       } else if (inl == 1  && js == 1) {
00420         return 1;
00421       } else if (inl == 3  && js == 3) {
00422         return 2;
00423       } else if (inl == 3  && js == 5) {
00424         return 3;
00425       } else if (inl == 3  && js == 7) {
00426         return 4;
00427       } else if (inl == 3  && js == 9) {
00428         return 5;
00429       }
00430       // Default to zero
00431       return 0;
00432     }
00433 
00434     //@}
00435 
00436 
00437     /// @name Charge functions
00438     //@{
00439 
00440     /// Three times the charge (as integer)
00441     inline int threeCharge(int pid) {
00442       int charge=0;
00443       int ida, sid;
00444       unsigned short q1, q2, q3;
00445       static int ch100[100] = { -1, 2,-1, 2,-1, 2,-1, 2, 0, 0,
00446                                 -3, 0,-3, 0,-3, 0,-3, 0, 0, 0,
00447                                 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
00448                                 0, 0, 0, 3, 0, 0, 3, 0, 0, 0,
00449                                 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
00450                                 0, 6, 3, 6, 0, 0, 0, 0, 0, 0,
00451                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00452                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00453                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00454                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00455       q1 = digit(nq1,pid);
00456       q2 = digit(nq2,pid);
00457       q3 = digit(nq3,pid);
00458       ida = abspid(pid);
00459       sid = fundamentalID(pid);
00460       if (ida == 0 || extraBits(pid) > 0) {      // ion or illegal
00461         return 0;
00462       } else if (sid > 0 && sid <= 100) {  // use table
00463         charge = ch100[sid-1];
00464         if(ida==1000017 || ida==1000018) { charge = 0; }
00465         if(ida==1000034 || ida==1000052) { charge = 0; }
00466         if(ida==1000053 || ida==1000054) { charge = 0; }
00467         if(ida==5100061 || ida==5100062) { charge = 6; }
00468       } else if (digit(nj,pid) == 0) {         // KL, Ks, or undefined
00469         return 0;
00470       } else if (isMeson(pid)) {           // mesons
00471         if (q2 == 3 || q2 == 5) {
00472           charge = ch100[q3-1] - ch100[q2-1];
00473         } else {
00474           charge = ch100[q2-1] - ch100[q3-1];
00475         }
00476       } else if (isDiQuark(pid)) {         // diquarks
00477         charge = ch100[q2-1] + ch100[q1-1];
00478       } else if (isBaryon(pid)) {          // baryons
00479         charge = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
00480       } else {      // unknown
00481         return 0;
00482       }
00483       if (charge == 0) {
00484         return 0;
00485       } else if (pid < 0) {
00486         charge = -charge;
00487       }
00488       return charge;
00489     }
00490 
00491 
00492     /// Return the charge (as floating point)
00493     inline double charge(int pid) { return threeCharge(pid)/3.0; }
00494 
00495     //@}
00496 
00497 
00498     /// @name General PID-based classifier functions
00499     //@{
00500 
00501     /// Determine if the particle is electrically charged
00502     inline bool isCharged(int pid) {
00503       return threeCharge(pid) != 0;
00504     }
00505 
00506     /// Determine if the particle is electrically neutral
00507     inline bool isNeutral(int pid) {
00508       return threeCharge(pid) == 0;
00509     }
00510 
00511     //@}
00512 
00513 
00514     /// @name Fundamental particles
00515     //@{
00516 
00517     /// Determine if the PID is that of a quark
00518     inline bool isQuark(int pid) {
00519       return in_closed_range(abs(pid), 1, 6);
00520     }
00521 
00522     /// Determine if the PID is that of a parton (quark or gluon)
00523     inline bool isParton(int pid) {
00524       return pid == GLUON || isQuark(pid);
00525     }
00526 
00527     /// Determine if the PID is that of a photon
00528     inline bool isPhoton(int pid) {
00529       return pid == PHOTON;
00530     }
00531 
00532     /// Determine if the PID is that of an electron or positron
00533     inline bool isElectron(int pid) {
00534       return abs(pid) == ELECTRON;
00535     }
00536 
00537     /// Determine if the PID is that of an muon or antimuon
00538     inline bool isMuon(int pid) {
00539       return abs(pid) == MUON;
00540     }
00541 
00542     /// Determine if the PID is that of an tau or antitau
00543     inline bool isTau(int pid) {
00544       return abs(pid) == TAU;
00545     }
00546 
00547     /// Determine if the PID is that of a charged lepton
00548     inline bool isChLepton(int pid) {
00549       const long apid = abs(pid);
00550       return apid == 11 || apid == 13 || apid == 15;
00551     }
00552 
00553     /// Determine if the PID is that of a neutrino
00554     inline bool isNeutrino(int pid) {
00555       const long apid = abs(pid);
00556       return apid == 12 || apid == 14 || apid == 16;
00557     }
00558 
00559 
00560 
00561     /// @todo Add isElectron, Muon, Tau (and +- specific versions?)... and is(Anti)Proton?
00562 
00563     /// Determine if the PID is that of a W+
00564     inline bool isWplus(int pid) {
00565       return pid == WPLUSBOSON;
00566     }
00567 
00568     /// Determine if the PID is that of a W-
00569     inline bool isWminus(int pid) {
00570       return pid == WMINUSBOSON;
00571     }
00572 
00573     /// Determine if the PID is that of a W+-
00574     inline bool isW(int pid) {
00575       return abs(pid) == WPLUSBOSON;
00576     }
00577 
00578     /// Determine if the PID is that of a Z0
00579     inline bool isZ(int pid) {
00580       return pid == Z0BOSON;
00581     }
00582 
00583     /// Determine if the PID is that of an SM/lightest SUSY Higgs
00584     inline bool isHiggs(int pid) {
00585       return pid == HIGGSBOSON || pid == 26; ///< @todo Check on 26 still needed? (used in HERWIG SUSY, for example)
00586     }
00587 
00588     /// @todo isSUSYHiggs?
00589 
00590     /// Determine if the PID is that of a t/tbar
00591     inline bool isTop(int pid) {
00592       return abs(pid) == 6;
00593     }
00594 
00595     //@}
00596 
00597 
00598     /// @name Hadron and parton flavour classification
00599     //@{
00600 
00601     /// Determine if the particle is a heavy flavour hadron or parton
00602     inline bool isHeavyFlavour(int pid) {
00603       return hasCharm(pid) || hasBottom(pid) || hasTop(pid);
00604     }
00605 
00606     // /// Determine if the particle is a light-flavour flavour hadron or parton
00607     // inline bool isLightFlavour(int pid) {
00608     //   return !isHeavyFlavour();
00609     // }
00610 
00611     /// Determine if the PID is that of a heavy parton (c,b,t)
00612     inline bool isHeavyParton(int pid) {
00613       return isParton(pid) && isHeavyFlavour(pid);
00614     }
00615 
00616     /// Determine if the PID is that of a light parton (u,d,s)
00617     inline bool isLightParton(int pid) {
00618       return isParton(pid) && !isHeavyFlavour(pid);
00619     }
00620 
00621 
00622     /// Determine if the PID is that of a heavy flavour (b or c) meson
00623     inline bool isHeavyMeson(int pid) {
00624       return isMeson(pid) && isHeavyFlavour(pid);
00625     }
00626 
00627     /// Determine if the PID is that of a heavy flavour (b or c) baryon
00628     inline bool isHeavyBaryon(int pid) {
00629       return isBaryon(pid) && isHeavyFlavour(pid);
00630     }
00631 
00632     /// Determine if the PID is that of a heavy flavour (b or c) hadron
00633     inline bool isHeavyHadron(int pid) {
00634       return isHadron(pid) && isHeavyFlavour(pid);
00635     }
00636 
00637     /// Determine if the PID is that of a light flavour (not b or c) meson
00638     inline bool isLightMeson(int pid) {
00639       return isMeson(pid) && !isHeavyFlavour(pid);
00640     }
00641 
00642     /// Determine if the PID is that of a light flavour (not b or c) baryon
00643     inline bool isLightBaryon(int pid) {
00644       return isBaryon(pid) && !isHeavyFlavour(pid);
00645     }
00646 
00647     /// Determine if the PID is that of a light flavour (not b or c) hadron
00648     inline bool isLightHadron(int pid) {
00649       return isHadron(pid) && !isHeavyFlavour(pid);
00650     }
00651 
00652 
00653     /// Determine if the PID is that of a b-meson.
00654     inline bool isBottomMeson(int pid) {
00655       return hasBottom(pid) && isMeson(pid);
00656     }
00657 
00658     /// Determine if the PID is that of a b-baryon.
00659     inline bool isBottomBaryon(int pid) {
00660       return hasBottom(pid) && isBaryon(pid);
00661     }
00662 
00663     /// Determine if the PID is that of a b-hadron.
00664     inline bool isBottomHadron(int pid) {
00665       return hasBottom(pid) && isHadron(pid);
00666     }
00667 
00668 
00669     /// @brief Determine if the PID is that of a c-meson.
00670     ///
00671     /// Specifically, the _heaviest_ quark is a c: a B_c is a b-meson and NOT a c-meson.
00672     /// Charmonia (closed charm) are counted as c-mesons here.
00673     inline bool isCharmMeson(int pid) {
00674       return isMeson(pid) && hasCharm(pid) && !hasBottom(pid);
00675     }
00676 
00677     /// @brief Determine if the PID is that of a c-baryon.
00678     ///
00679     /// Specifically, the _heaviest_ quark is a c: a baryon containing a b & c
00680     /// is a b-baryon and NOT a c-baryon. To test for the simpler case, just use
00681     /// a combination of hasCharm() and isBaryon().
00682     inline bool isCharmBaryon(int pid) {
00683       return isBaryon(pid) && hasCharm(pid) && !hasBottom(pid);
00684     }
00685 
00686     /// Determine if the PID is that of a c-hadron.
00687     ///
00688     /// Specifically, the _heaviest_ quark is a c: a baryon containing a b & c
00689     /// is a b-baryon and NOT a c-baryon. To test for the simpler case, just use
00690     /// a combination of hasCharm() and isBaryon().
00691     inline bool isCharmHadron(int pid) {
00692       return isHadron(pid) && hasCharm(pid) && !hasBottom(pid);
00693     }
00694 
00695 
00696     // /// Determine if the PID is that of a strange meson
00697     // inline bool isStrangeMeson(int pid) {
00698     //   return isMeson(pid) && hasStrange(pid);
00699     // }
00700 
00701     // /// Determine if the PID is that of a strange baryon
00702     // inline bool isStrangeBaryon(int pid) {
00703     //   return isBaryon(pid) && hasStrange(pid);
00704     // }
00705 
00706     // /// Determine if the PID is that of a strange hadron
00707     // inline bool isStrangeHadron(int pid) {
00708     //   return isHadron(pid) && hasStrange(pid);
00709     // }
00710 
00711     //@}
00712 
00713 
00714     /// @name Other classifiers
00715     //@{
00716 
00717     /// Determine if the PID is in the generator-specific range
00718     inline bool isGenSpecific(int pid) {
00719       return in_range(pid, 80, 101);
00720     }
00721 
00722     /// Determine if the PID is that of an EW scale resonance
00723     ///
00724     /// @todo Also include SUSY, technicolor, etc. etc.? Maybe via a isStandardModel(pid) function, but there are stable BSM particles (in principle)
00725     inline bool isResonance(int pid) {
00726       return isW(pid) || isZ(pid) || isHiggs(pid) || isTop(pid);
00727     }
00728 
00729     /// Check the PID for usability in transport codes like Geant4
00730     ///
00731     /// @todo Should exclude neutrinos/LSP, since the ATLAS G4 interface deletes them immediately?
00732     inline bool isTransportable(int pid) {
00733       // return !isResonance(pid) && !isParton(pid) && !isGenSpecific(pid);
00734       return isPhoton(pid) || isHadron(pid) || isLepton(pid);
00735     }
00736 
00737     //@}
00738 
00739 
00740   }
00741 }
00742 
00743 #endif