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