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 
00216     //
00217     // This implements the 2006 Monte Carlo nuclear code scheme.
00218     // Ion numbers are +/- 10LZZZAAAI.
00219     // AAA is A - total baryon number
00220     // ZZZ is Z - total charge
00221     // L is the total number of strange quarks.
00222     // I is the isomer number, with I=0 corresponding to the ground state.
00223     bool isNucleus( const int & pid )
00224     {
00225          // a proton can also be a Hydrogen nucleus
00226          if( abspid(pid) == 2212 ) { return true; }
00227          // new standard: +/- 10LZZZAAAI
00228          if( ( digit(n10,pid) == 1 ) && ( digit(n9,pid) == 0 ) ) {
00229             // charge should always be less than or equal to baryon number
00230         // the following line is A >= Z
00231             if( (abspid(pid)/10)%1000 >= (abspid(pid)/10000)%1000 ) { return true; }
00232          }
00233          return false;
00234     }
00235 
00236     //  check to see if this is a valid pentaquark
00237     bool isPentaquark( const int & pid )
00238     {
00239         // a pentaquark is of the form 9abcdej,
00240         // where j is the spin and a, b, c, d, and e are quarks
00241         if( extraBits(pid) > 0 ) { return false; }
00242         if( digit(n,pid) != 9 )  { return false; }
00243         if( digit(nr,pid) == 9 || digit(nr,pid) == 0 )  { return false; }
00244         if( digit(nj,pid) == 9 || digit(nl,pid) == 0 )  { return false; }
00245         if( digit(nq1,pid) == 0 )  { return false; }
00246         if( digit(nq2,pid) == 0 )  { return false; }
00247         if( digit(nq3,pid) == 0 )  { return false; }
00248         if( digit(nj,pid) == 0 )  { return false; }
00249         // check ordering
00250         if( digit(nq2,pid) > digit(nq1,pid) )  { return false; }
00251         if( digit(nq1,pid) > digit(nl,pid) )  { return false; }
00252         if( digit(nl,pid) > digit(nr,pid) )  { return false; }
00253         return true;
00254     }
00255 
00256     // is this a SUSY?
00257     bool isSUSY( const int & pid )
00258     {
00259         // fundamental SUSY particles have n = 1 or 2
00260         if( extraBits(pid) > 0 ) { return false; }
00261         if( digit(n,pid) != 1 && digit(n,pid) != 2 )  { return false; }
00262         if( digit(nr,pid) != 0 )  { return false; }
00263         // check fundamental part
00264         if( fundamentalID(pid) == 0 )  { return false; }
00265         return true;
00266     }
00267 
00268     // is this an R-hadron?
00269     bool isRhadron( const int & pid )
00270     {
00271         // an R-hadron is of the form 10abcdj,
00272         // where j is the spin and a, b, c, and d are quarks or gluons
00273         if( extraBits(pid) > 0 ) { return false; }
00274         if( digit(n,pid) != 1 )  { return false; }
00275         if( digit(nr,pid) != 0 )  { return false; }
00276         // make sure this isn't a SUSY particle
00277         if( isSUSY(pid) ) { return false; }
00278         // All R-hadrons have at least 3 core digits
00279         if( digit(nq2,pid) == 0 )  { return false; }
00280         if( digit(nq3,pid) == 0 )  { return false; }
00281         if( digit(nj,pid) == 0 )  { return false; }
00282         return true;
00283     }
00284 
00285     // does this particle contain an up quark?
00286     bool hasUp( const int & pid)
00287     {
00288         if( extraBits(pid) > 0 ) { return false; }
00289         if( fundamentalID(pid) > 0 ) { return false; }
00290         if( digit(nq3,pid) == 2 || digit(nq2,pid) == 2 || digit(nq1,pid) == 2 ) { return true; }
00291         return false;
00292     }
00293     // does this particle contain a down quark?
00294     bool hasDown( const int & pid)
00295     {
00296         if( extraBits(pid) > 0 ) { return false; }
00297         if( fundamentalID(pid) > 0 ) { return false; }
00298         if( digit(nq3,pid) == 1 || digit(nq2,pid) == 1 || digit(nq1,pid) == 1 ) { return true; }
00299         return false;
00300     }
00301     // does this particle contain a strange quark?
00302     bool hasStrange( const int & pid )
00303     {
00304         if( extraBits(pid) > 0 ) { return false; }
00305         if( fundamentalID(pid) > 0 ) { return false; }
00306         if( digit(nq3,pid) == 3 || digit(nq2,pid) == 3 || digit(nq1,pid) == 3 ) { return true; }
00307         return false;
00308     }
00309     // does this particle contain a charm quark?
00310     bool hasCharm( const int & pid )
00311     {
00312         if( extraBits(pid) > 0 ) { return false; }
00313         if( fundamentalID(pid) > 0 ) { return false; }
00314         if( digit(nq3,pid) == 4 || digit(nq2,pid) == 4 || digit(nq1,pid) == 4 ) { return true; }
00315         return false;
00316     }
00317     // does this particle contain a bottom quark?
00318     bool hasBottom( const int & pid )
00319     {
00320         if( extraBits(pid) > 0 ) { return false; }
00321         if( fundamentalID(pid) > 0 ) { return false; }
00322         if( digit(nq3,pid) == 5 || digit(nq2,pid) == 5 || digit(nq1,pid) == 5 ) { return true; }
00323         return false;
00324     }
00325     // does this particle contain a top quark?
00326     bool hasTop( const int & pid )
00327     {
00328         if( extraBits(pid) > 0 ) { return false; }
00329         if( fundamentalID(pid) > 0 ) { return false; }
00330         if( digit(nq3,pid) == 6 || digit(nq2,pid) == 6 || digit(nq1,pid) == 6 ) { return true; }
00331         return false;
00332     }
00333 
00334     // ---  other information
00335     //
00336     // jSpin returns 2J+1, where J is the total spin
00337     int  jSpin( const int & pid )
00338     {
00339         if( fundamentalID(pid) > 0 ) {
00340         // some of these are known
00341         int fund = fundamentalID(pid);
00342         if( fund > 0 && fund < 7 ) return 2;
00343         if( fund == 9 ) return 3;
00344         if( fund > 10 && fund < 17 ) return 2;
00345         if( fund > 20 && fund < 25 ) return 3;
00346             return 0;
00347         } else if( extraBits(pid) > 0 ) {
00348             return 0;
00349         }
00350         return abspid(pid)%10;
00351     }
00352     // sSpin returns 2S+1, where S is the spin
00353     int  sSpin( const int & pid )
00354     {
00355         if( !isMeson(pid) ) { return 0; }
00356         int inl = digit(nl,pid);
00357         //int tent = digit(n,pid);
00358         int js = digit(nj,pid);
00359         if( digit(n,pid) == 9 ) { return 0; }   // tentative ID
00360         //if( tent == 9 ) { return 0; } // tentative assignment
00361         if( inl == 0 && js >= 3 ) {
00362             return 1;
00363         } else if( inl == 0  && js == 1 ) {
00364             return 0;
00365         } else if( inl == 1  && js >= 3 ) {
00366             return 0;
00367         } else if( inl == 2  && js >= 3 ) {
00368             return 1;
00369         } else if( inl == 1  && js == 1 ) {
00370             return 1;
00371         } else if( inl == 3  && js >= 3 ) {
00372             return 1;
00373         }
00374         // default to zero
00375         return 0;
00376     }
00377     // lSpin returns 2L+1, where L is the orbital angular momentum
00378     int  lSpin( const int & pid )
00379     {
00380         if( !isMeson(pid) ) { return 0; }
00381         int inl = digit(nl,pid);
00382         //int tent = digit(n,pid);
00383         int js = digit(nj,pid);
00384         if( digit(n,pid) == 9 ) { return 0; }   // tentative ID
00385         if( inl == 0 && js == 3 ) {
00386             return 0;
00387         } else if( inl == 0 && js == 5 ) {
00388             return 1;
00389         } else if( inl == 0 && js == 7 ) {
00390             return 2;
00391         } else if( inl == 0 && js == 9 ) {
00392             return 3;
00393         } else if( inl == 0  && js == 1 ) {
00394             return 0;
00395         } else if( inl == 1  && js == 3 ) {
00396             return 1;
00397         } else if( inl == 1  && js == 5 ) {
00398             return 2;
00399         } else if( inl == 1  && js == 7 ) {
00400             return 3;
00401         } else if( inl == 1  && js == 9 ) {
00402             return 4;
00403         } else if( inl == 2  && js == 3 ) {
00404             return 1;
00405         } else if( inl == 2  && js == 5 ) {
00406             return 2;
00407         } else if( inl == 2  && js == 7 ) {
00408             return 3;
00409         } else if( inl == 2  && js == 9 ) {
00410             return 4;
00411         } else if( inl == 1  && js == 1 ) {
00412             return 1;
00413         } else if( inl == 3  && js == 3 ) {
00414             return 2;
00415         } else if( inl == 3  && js == 5 ) {
00416             return 3;
00417         } else if( inl == 3  && js == 7 ) {
00418             return 4;
00419         } else if( inl == 3  && js == 9 ) {
00420             return 5;
00421         }
00422         // default to zero
00423         return 0;
00424     }
00425 
00426     // 3 times the charge
00427     int threeCharge( const int & pid )
00428     {
00429         int charge=0;
00430         int ida, sid;
00431         unsigned short q1, q2, q3;
00432         static int ch100[100] = { -1, 2,-1, 2,-1, 2,-1, 2, 0, 0,
00433                            -3, 0,-3, 0,-3, 0,-3, 0, 0, 0,
00434                             0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
00435                             0, 0, 0, 3, 0, 0, 3, 0, 0, 0,
00436                             0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
00437                             0, 6, 3, 6, 0, 0, 0, 0, 0, 0,
00438                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00439                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00440                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00441                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00442         q1 = digit(nq1,pid);
00443         q2 = digit(nq2,pid);
00444         q3 = digit(nq3,pid);
00445         ida = abspid(pid);
00446         sid = fundamentalID(pid);
00447         if( ida == 0 || extraBits(pid) > 0 ) {      // ion or illegal
00448             return 0;
00449         } else if( sid > 0 && sid <= 100 ) {    // use table
00450             charge = ch100[sid-1];
00451             if(ida==1000017 || ida==1000018) { charge = 0; }
00452             if(ida==1000034 || ida==1000052) { charge = 0; }
00453             if(ida==1000053 || ida==1000054) { charge = 0; }
00454             if(ida==5100061 || ida==5100062) { charge = 6; }
00455         } else if( digit(nj,pid) == 0 ) {       // KL, Ks, or undefined
00456             return 0;
00457         } else if( isMeson(pid) ) {         // mesons
00458                 if( q2 == 3 || q2 == 5 ) {
00459                     charge = ch100[q3-1] - ch100[q2-1];
00460                 } else {
00461                     charge = ch100[q2-1] - ch100[q3-1];
00462                 }
00463         } else if( isDiQuark(pid) ) {           // diquarks
00464             charge = ch100[q2-1] + ch100[q1-1];
00465         } else if( isBaryon(pid) ) {            // baryons
00466             charge = ch100[q3-1] + ch100[q2-1] + ch100[q1-1];
00467         } else {        // unknown
00468             return 0;
00469         }
00470         if( charge == 0 ) {
00471             return 0;
00472         } else if( pid < 0 ) {
00473             charge = -charge;
00474         }
00475         return charge;
00476     }
00477 
00478 
00479   }
00480 }