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