rivet is hosted by Hepforge, IPPP Durham
ParticleIdUtils.cc
Go to the documentation of this file.
00001 // ----------------------------------------------------------------------
00002 //
00003 // ParticleIdUtils.cc
00004 // Stolen from HepPID
00005 //
00006 // ----------------------------------------------------------------------
00007 
00008 #include <cmath>    // for pow()
00009 
00010 #include "Rivet/Tools/ParticleIdUtils.hh"
00011 
00012 namespace Rivet {
00013 
00014   namespace PID {
00015 
00016 
00017     ///  PID digits (base 10) are: n nr nl nq1 nq2 nq3 nj
00018     ///  The location enum provides a convenient index into the PID.
00019     enum location { nj=1, nq3, nq2, nq1, nl, nr, n, n8, n9, n10 };
00020 
00021     /// return the digit at a named location in the PID
00022     unsigned short digit( location loc, const int & pid );
00023 
00024     /// extract fundamental ID (1-100) if this is a "fundamental" particle
00025     int fundamentalID( const int & pid );
00026     /// if this is a fundamental particle, does it have a valid antiparticle?
00027     //bool hasFundamentalAnti( const int & pid );
00028 
00029     /// returns everything beyond the 7th digit
00030     /// (e.g. outside the standard numbering scheme)
00031     int extraBits( const int & pid );
00032 
00033 
00034     // absolute value
00035     int abspid( const int & pid )
00036     {
00037       return (pid < 0) ? -pid : pid;
00038     }
00039 
00040     // returns everything beyond the 7th digit (e.g. outside the numbering scheme)
00041     int extraBits( const int & pid )
00042     {
00043         return abspid(pid)/10000000;
00044     }
00045 
00046     //  split the PID into constituent integers
00047     unsigned short digit( location loc, const int & pid )
00048     {
00049         //  PID digits (base 10) are: n nr nl nq1 nq2 nq3 nj
00050         //  the location enum provides a convenient index into the PID
00051         int numerator = (int) std::pow(10.0,(loc-1));
00052         return (abspid(pid)/numerator)%10;
00053     }
00054 
00055     //  return the first two digits if this is a "fundamental" particle
00056     //  ID = 100 is a special case (internal generator ID's are 81-100)
00057     int fundamentalID( const int & pid )
00058     {
00059         if( extraBits(pid) > 0 ) return 0;
00060         if( digit(nq2,pid) == 0 && digit(nq1,pid) == 0) {
00061             return abspid(pid)%10000;
00062         } else if( abspid(pid) <= 100 ) {
00063             return abspid(pid);
00064         } else {
00065             return 0;
00066         }
00067     }
00068 
00069     // Ion numbers are +/- 10LZZZAAAI.
00070     int Z( const int & pid )
00071     {
00072         // a proton can also be a Hydrogen nucleus
00073         if( abspid(pid) == 2212 ) { return 1; }
00074         if( isNucleus(pid) ) return (abspid(pid)/10000)%1000;
00075         return 0;
00076     }
00077 
00078     // Ion numbers are +/- 10LZZZAAAI.
00079     int A( const int & pid )
00080     {
00081         // a proton can also be a Hydrogen nucleus
00082         if( abspid(pid) == 2212 ) { return 1; }
00083         if( isNucleus(pid) ) return (abspid(pid)/10)%1000;
00084         return 0;
00085     }
00086 
00087     // if this is a nucleus (ion), get nLambda
00088     // Ion numbers are +/- 10LZZZAAAI.
00089     int lambda( const int & pid )
00090     {
00091         // a proton can also be a Hydrogen nucleus
00092         if( abspid(pid) == 2212 ) { return 0; }
00093         if( isNucleus(pid) ) return digit(n8,pid);
00094         return 0;
00095     }
00096 
00097 
00098     // ---  boolean methods:
00099     //
00100 
00101     //  check to see if this is a valid PID
00102     bool isValid( const int & pid )
00103     {
00104         if( extraBits(pid) > 0 ) {
00105             if( isNucleus(pid) )   { return true; }
00106             return false;
00107         }
00108         if( isSUSY(pid) ) { return true; }
00109         if( isRhadron(pid) ) { return true; }
00110         // Meson signature
00111         if( isMeson(pid) )   { return true; }
00112         // Baryon signature
00113         if( isBaryon(pid) )  { return true; }
00114         // DiQuark signature
00115         if( isDiQuark(pid) ) { return true; }
00116         // fundamental particle
00117         if( fundamentalID(pid) > 0 ) {
00118           if(pid > 0 ) {
00119             return true;
00120           } else {
00121             // AB - disabled this to remove need for PID -> name lookup.
00122             //if( hasFundamentalAnti(pid) ) { return true; }
00123             return false;
00124           }
00125         }
00126         // pentaquark
00127         if( isPentaquark(pid) ) { return true; }
00128         // don't recognize this number
00129         return false;
00130     }
00131 
00132     // // if this is a fundamental particle, does it have a valid antiparticle?
00133     // bool hasFundamentalAnti( const int & pid )
00134     // {
00135     //     // these are defined by the generator and therefore are always valid
00136     //     if( fundamentalID(pid) <= 100 && fundamentalID(pid) >= 80 ) { return true; }
00137     //     // check id's from 1 to 79
00138     //     if( fundamentalID(pid) > 0 && fundamentalID(pid) < 80 ) {
00139     //        if( validParticleName(-pid) ) { return true; }
00140     //     }
00141     //     return false;
00142     // }
00143 
00144     //  check to see if this is a valid meson
00145     bool isMeson( const int & pid )
00146     {
00147         if( extraBits(pid) > 0 ) { return false; }
00148         if( abspid(pid) <= 100 ) { return false; }
00149         if( fundamentalID(pid) <= 100 && fundamentalID(pid) > 0 ) { return false; }
00150         int aid = abspid(pid);
00151         if( aid == 130 || aid == 310 || aid == 210 ) { return true; }
00152         // EvtGen uses some odd numbers
00153         if( aid == 150 || aid == 350 || aid == 510 || aid == 530 ) { return true; }
00154         // pomeron, etc.
00155         if( pid == 110 || pid == 990 || pid == 9990 ) { return true; }
00156         if(    digit(nj,pid) > 0 && digit(nq3,pid) > 0
00157             && digit(nq2,pid) > 0 && digit(nq1,pid) == 0 ) {
00158             // check for illegal antiparticles
00159             if( digit(nq3,pid) == digit(nq2,pid) && pid < 0 ) {
00160                 return false;
00161             } else {
00162                 return true;
00163             }
00164         }
00165         return false;
00166     }
00167 
00168     //  check to see if this is a valid baryon
00169     bool isBaryon( const int & pid )
00170     {
00171         if( extraBits(pid) > 0 ) { return false; }
00172         if( abspid(pid) <= 100 ) { return false; }
00173         if( fundamentalID(pid) <= 100 && fundamentalID(pid) > 0 ) { return false; }
00174         if( abspid(pid) == 2110 || abspid(pid) == 2210 ) { return true; }
00175         if(    digit(nj,pid) > 0  && digit(nq3,pid) > 0
00176             && digit(nq2,pid) > 0 && digit(nq1,pid) > 0 ) { return true; }
00177         return false;
00178     }
00179 
00180     //  check to see if this is a valid diquark
00181     bool isDiQuark( const int & pid )
00182     {
00183         if( extraBits(pid) > 0 ) { return false; }
00184         if( abspid(pid) <= 100 ) { return false; }
00185         if( fundamentalID(pid) <= 100 && fundamentalID(pid) > 0 ) { return false; }
00186         if(    digit(nj,pid) > 0  && digit(nq3,pid) == 0
00187             && digit(nq2,pid) > 0 && digit(nq1,pid) > 0 ) {  // diquark signature
00188            // EvtGen uses the diquarks for quark pairs, so, for instance,
00189            //   5501 is a valid "diquark" for EvtGen
00190            //if( digit(nj) == 1 && digit(nq2) == digit(nq1) ) {     // illegal
00191            //   return false;
00192            //} else {
00193               return true;
00194            //}
00195         }
00196         return false;
00197     }
00198 
00199     // is this a valid hadron ID?
00200     bool isHadron( const int & pid )
00201     {
00202         if( extraBits(pid) > 0 ) { return false; }
00203         if( isMeson(pid) )   { return true; }
00204         if( isBaryon(pid) )  { return true; }
00205         if( isPentaquark(pid) ) { return true; }
00206         return false;
00207     }
00208     // is this a valid lepton ID?
00209     bool isLepton( const int & pid )
00210     {
00211         if( extraBits(pid) > 0 ) { return false; }
00212         if( fundamentalID(pid) >= 11 && fundamentalID(pid) <= 18 ) { return true; }
00213         return false;
00214     }
00215     // is this a neutrino ID?
00216     bool isNeutrino( const int & pid )
00217     {
00218         if( extraBits(pid) > 0 ) { return false; }
00219         if( fundamentalID(pid) == 12 || fundamentalID(pid) == 14 || fundamentalID(pid) == 16 ) { return true; }
00220         return false;
00221     }
00222 
00223     //
00224     // This implements the 2006 Monte Carlo nuclear code scheme.
00225     // Ion numbers are +/- 10LZZZAAAI.
00226     // AAA is A - total baryon number
00227     // ZZZ is Z - total charge
00228     // L is the total number of strange quarks.
00229     // I is the isomer number, with I=0 corresponding to the ground state.
00230     bool isNucleus( const int & pid )
00231     {
00232          // a proton can also be a Hydrogen nucleus
00233          if( abspid(pid) == 2212 ) { return true; }
00234          // new standard: +/- 10LZZZAAAI
00235          if( ( digit(n10,pid) == 1 ) && ( digit(n9,pid) == 0 ) ) {
00236             // charge should always be less than or equal to baryon number
00237         // the following line is A >= Z
00238             if( (abspid(pid)/10)%1000 >= (abspid(pid)/10000)%1000 ) { return true; }
00239          }
00240          return false;
00241     }
00242 
00243     //  check to see if this is a valid pentaquark
00244     bool isPentaquark( const int & pid )
00245     {
00246         // a pentaquark is of the form 9abcdej,
00247         // where j is the spin and a, b, c, d, and e are quarks
00248         if( extraBits(pid) > 0 ) { return false; }
00249         if( digit(n,pid) != 9 )  { return false; }
00250         if( digit(nr,pid) == 9 || digit(nr,pid) == 0 )  { return false; }
00251         if( digit(nj,pid) == 9 || digit(nl,pid) == 0 )  { return false; }
00252         if( digit(nq1,pid) == 0 )  { return false; }
00253         if( digit(nq2,pid) == 0 )  { return false; }
00254         if( digit(nq3,pid) == 0 )  { return false; }
00255         if( digit(nj,pid) == 0 )  { return false; }
00256         // check ordering
00257         if( digit(nq2,pid) > digit(nq1,pid) )  { return false; }
00258         if( digit(nq1,pid) > digit(nl,pid) )  { return false; }
00259         if( digit(nl,pid) > digit(nr,pid) )  { return false; }
00260         return true;
00261     }
00262 
00263     // is this a SUSY?
00264     bool isSUSY( const int & pid )
00265     {
00266         // fundamental SUSY particles have n = 1 or 2
00267         if( extraBits(pid) > 0 ) { return false; }
00268         if( digit(n,pid) != 1 && digit(n,pid) != 2 )  { return false; }
00269         if( digit(nr,pid) != 0 )  { return false; }
00270         // check fundamental part
00271         if( fundamentalID(pid) == 0 )  { return false; }
00272         return true;
00273     }
00274 
00275     // is this an R-hadron?
00276     bool isRhadron( const int & pid )
00277     {
00278         // an R-hadron is of the form 10abcdj,
00279         // where j is the spin and a, b, c, and d are quarks or gluons
00280         if( extraBits(pid) > 0 ) { return false; }
00281         if( digit(n,pid) != 1 )  { return false; }
00282         if( digit(nr,pid) != 0 )  { return false; }
00283         // make sure this isn't a SUSY particle
00284         if( isSUSY(pid) ) { return false; }
00285         // All R-hadrons have at least 3 core digits
00286         if( digit(nq2,pid) == 0 )  { return false; }
00287         if( digit(nq3,pid) == 0 )  { return false; }
00288         if( digit(nj,pid) == 0 )  { return false; }
00289         return true;
00290     }
00291 
00292     // does this particle contain an up quark?
00293     bool hasUp( const int & pid)
00294     {
00295         if( extraBits(pid) > 0 ) { return false; }
00296         if( fundamentalID(pid) > 0 ) { return false; }
00297         if( digit(nq3,pid) == 2 || digit(nq2,pid) == 2 || digit(nq1,pid) == 2 ) { return true; }
00298         return false;
00299     }
00300     // does this particle contain a down quark?
00301     bool hasDown( const int & pid)
00302     {
00303         if( extraBits(pid) > 0 ) { return false; }
00304         if( fundamentalID(pid) > 0 ) { return false; }
00305         if( digit(nq3,pid) == 1 || digit(nq2,pid) == 1 || digit(nq1,pid) == 1 ) { return true; }
00306         return false;
00307     }
00308     // does this particle contain a strange quark?
00309     bool hasStrange( const int & pid )
00310     {
00311         if( extraBits(pid) > 0 ) { return false; }
00312         if( fundamentalID(pid) > 0 ) { return false; }
00313         if( digit(nq3,pid) == 3 || digit(nq2,pid) == 3 || digit(nq1,pid) == 3 ) { return true; }
00314         return false;
00315     }
00316     // does this particle contain a charm quark?
00317     bool hasCharm( const int & pid )
00318     {
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     bool hasBottom( const int & pid )
00326     {
00327         if( extraBits(pid) > 0 ) { return false; }
00328         if( fundamentalID(pid) > 0 ) { return false; }
00329         if( digit(nq3,pid) == 5 || digit(nq2,pid) == 5 || digit(nq1,pid) == 5 ) { return true; }
00330         return false;
00331     }
00332     // does this particle contain a top quark?
00333     bool hasTop( const int & pid )
00334     {
00335         if( extraBits(pid) > 0 ) { return false; }
00336         if( fundamentalID(pid) > 0 ) { return false; }
00337         if( digit(nq3,pid) == 6 || digit(nq2,pid) == 6 || digit(nq1,pid) == 6 ) { return true; }
00338         return false;
00339     }
00340 
00341     // ---  other information
00342     //
00343     // jSpin returns 2J+1, where J is the total spin
00344     int  jSpin( const int & pid )
00345     {
00346         if( fundamentalID(pid) > 0 ) {
00347         // some of these are known
00348         int fund = fundamentalID(pid);
00349         if( fund > 0 && fund < 7 ) return 2;
00350         if( fund == 9 ) return 3;
00351         if( fund > 10 && fund < 17 ) return 2;
00352         if( fund > 20 && fund < 25 ) return 3;
00353             return 0;
00354         } else if( extraBits(pid) > 0 ) {
00355             return 0;
00356         }
00357         return abspid(pid)%10;
00358     }
00359     // sSpin returns 2S+1, where S is the spin
00360     int  sSpin( const int & pid )
00361     {
00362         if( !isMeson(pid) ) { return 0; }
00363         int inl = digit(nl,pid);
00364         //int tent = digit(n,pid);
00365         int js = digit(nj,pid);
00366         if( digit(n,pid) == 9 ) { return 0; }   // tentative ID
00367         //if( tent == 9 ) { return 0; } // tentative assignment
00368         if( inl == 0 && js >= 3 ) {
00369             return 1;
00370         } else if( inl == 0  && js == 1 ) {
00371             return 0;
00372         } else if( inl == 1  && js >= 3 ) {
00373             return 0;
00374         } else if( inl == 2  && js >= 3 ) {
00375             return 1;
00376         } else if( inl == 1  && js == 1 ) {
00377             return 1;
00378         } else if( inl == 3  && js >= 3 ) {
00379             return 1;
00380         }
00381         // default to zero
00382         return 0;
00383     }
00384     // lSpin returns 2L+1, where L is the orbital angular momentum
00385     int  lSpin( const int & pid )
00386     {
00387         if( !isMeson(pid) ) { return 0; }
00388         int inl = digit(nl,pid);
00389         //int tent = digit(n,pid);
00390         int js = digit(nj,pid);
00391         if( digit(n,pid) == 9 ) { return 0; }   // tentative ID
00392         if( inl == 0 && js == 3 ) {
00393             return 0;
00394         } else if( inl == 0 && js == 5 ) {
00395             return 1;
00396         } else if( inl == 0 && js == 7 ) {
00397             return 2;
00398         } else if( inl == 0 && js == 9 ) {
00399             return 3;
00400         } else if( inl == 0  && js == 1 ) {
00401             return 0;
00402         } else if( inl == 1  && js == 3 ) {
00403             return 1;
00404         } else if( inl == 1  && js == 5 ) {
00405             return 2;
00406         } else if( inl == 1  && js == 7 ) {
00407             return 3;
00408         } else if( inl == 1  && js == 9 ) {
00409             return 4;
00410         } else if( inl == 2  && js == 3 ) {
00411             return 1;
00412         } else if( inl == 2  && js == 5 ) {
00413             return 2;
00414         } else if( inl == 2  && js == 7 ) {
00415             return 3;
00416         } else if( inl == 2  && js == 9 ) {
00417             return 4;
00418         } else if( inl == 1  && js == 1 ) {
00419             return 1;
00420         } else if( inl == 3  && js == 3 ) {
00421             return 2;
00422         } else if( inl == 3  && js == 5 ) {
00423             return 3;
00424         } else if( inl == 3  && js == 7 ) {
00425             return 4;
00426         } else if( inl == 3  && js == 9 ) {
00427             return 5;
00428         }
00429         // default to zero
00430         return 0;
00431     }
00432 
00433     // 3 times the charge
00434     int threeCharge( const int & pid )
00435     {
00436         int charge=0;
00437         int ida, sid;
00438         unsigned short q1, q2, q3;
00439         static int ch100[100] = { -1, 2,-1, 2,-1, 2,-1, 2, 0, 0,
00440                            -3, 0,-3, 0,-3, 0,-3, 0, 0, 0,
00441                             0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
00442                             0, 0, 0, 3, 0, 0, 3, 0, 0, 0,
00443                             0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
00444                             0, 6, 3, 6, 0, 0, 0, 0, 0, 0,
00445                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00446                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00447                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00448                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00449         q1 = digit(nq1,pid);
00450         q2 = digit(nq2,pid);
00451         q3 = digit(nq3,pid);
00452         ida = abspid(pid);
00453         sid = fundamentalID(pid);
00454         if( ida == 0 || extraBits(pid) > 0 ) {      // ion or illegal
00455             return 0;
00456         } else if( sid > 0 && sid <= 100 ) {    // use table
00457             charge = ch100[sid-1];
00458             if(ida==1000017 || ida==1000018) { charge = 0; }
00459             if(ida==1000034 || ida==1000052) { charge = 0; }
00460             if(ida==1000053 || ida==1000054) { charge = 0; }
00461             if(ida==5100061 || ida==5100062) { charge = 6; }
00462         } else if( digit(nj,pid) == 0 ) {       // KL, Ks, or undefined
00463             return 0;
00464         } else if( isMeson(pid) ) {         // mesons
00465                 if( q2 == 3 || q2 == 5 ) {
00466                     charge = ch100[q3-1] - ch100[q2-1];
00467                 } else {
00468                     charge = ch100[q2-1] - ch100[q3-1];
00469                 }
00470         } else if( isDiQuark(pid) ) {           // diquarks
00471             charge = ch100[q2-1] + ch100[q1-1];
00472         } else if( isBaryon(pid) ) {            // baryons
00473             charge = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
00474         } else {        // unknown
00475             return 0;
00476         }
00477         if( charge == 0 ) {
00478             return 0;
00479         } else if( pid < 0 ) {
00480             charge = -charge;
00481         }
00482         return charge;
00483     }
00484 
00485 
00486   }
00487 }