1 // Event.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2008 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
6 // Function definitions (not found in the header) for the
7 // Particle and Event classes, and some related global functions.
13 //**************************************************************************
16 // This class holds info on a particle in general.
20 // Constants: could be changed here if desired, but normally should not.
21 // These are of technical nature, as described for each.
23 // Small number to avoid division by zero.
24 const double Particle::TINY = 1e-20;
28 // Functions for rapidity and pseudorapidity.
30 double Particle::y() const {
31 double temp = log( ( pSave.e() + abs(pSave.pz()) ) / max( TINY, mT() ) );
32 return (pSave.pz() > 0) ? temp : -temp;
35 double Particle::eta() const {
36 double temp = log( ( pSave.pAbs() + abs(pSave.pz()) ) / max( TINY, pT() ) );
37 return (pSave.pz() > 0) ? temp : -temp;
42 // Particle name, with status but imposed maximum length -> may truncate.
44 string Particle::nameWithStatus(int maxLen) const {
46 string temp = (statusSave > 0) ? particlePtr->name(idSave)
47 : "(" + particlePtr->name(idSave) + ")";
48 while (int(temp.length()) > maxLen) {
49 // Remove from end, excluding closing bracket and charge.
50 int iRem = temp.find_last_not_of(")+-0");
58 // Add offsets to mother and daughter pointers (must be non-negative).
60 void Particle::offsetHistory( int minMother, int addMother, int minDaughter,
63 if (addMother < 0 || addDaughter < 0) return;
64 if ( mother1Save > minMother ) mother1Save += addMother;
65 if ( mother2Save > minMother ) mother2Save += addMother;
66 if (daughter1Save > minDaughter) daughter1Save += addDaughter;
67 if (daughter2Save > minDaughter) daughter2Save += addDaughter;
73 // Add offsets to colour and anticolour (must be positive).
75 void Particle::offsetCol( int addCol) {
77 if (addCol < 0) return;
78 if ( colSave > 0) colSave += addCol;
79 if (acolSave > 0) acolSave += addCol;
85 // Set the ParticleDataEntry pointer, using the stored idSave value.
87 void Particle::setParticlePtr() {
89 particlePtr = ParticleDataTable::particleDataPtr(idSave);
95 // Invariant mass of a pair and its square.
96 // (Not part of class proper, but tightly linked.)
98 double m(const Particle& pp1, const Particle& pp2) {
99 double m2 = pow2(pp1.e() + pp2.e()) - pow2(pp1.px() + pp2.px())
100 - pow2(pp1.py() + pp2.py()) - pow2(pp1.pz() + pp2.pz());
101 return (m2 > 0. ? sqrt(m2) : 0.);
104 double m2(const Particle& pp1, const Particle& pp2) {
105 double m2 = pow2(pp1.e() + pp2.e()) - pow2(pp1.px() + pp2.px())
106 - pow2(pp1.py() + pp2.py()) - pow2(pp1.pz() + pp2.pz());
110 //**************************************************************************
113 // This class holds info on the complete event record.
117 // Constants: could be changed here if desired, but normally should not.
118 // These are of technical nature, as described for each.
120 // Maxmimum number of mothers or daughter indices per line in listing.
121 const int Event::IPERLINE = 20;
125 // Copy all information from one event record to another.
127 Event& Event::operator=( const Event& oldEvent) {
129 // Do not copy if same.
130 if (this != &oldEvent) {
132 // Reset all current info in the event.
135 // Copy all the particles one by one.
136 for (int i = 0; i < oldEvent.size(); ++i) append( oldEvent[i] );
138 // Copy all the junctions one by one.
139 for (int i = 0; i < oldEvent.sizeJunction(); ++i)
140 appendJunction( oldEvent.getJunction(i) );
142 // Copy values in the system arrays.
143 for (int i = 0; i < int(oldEvent.beginSys.size()); ++i)
144 beginSys.push_back( oldEvent.beginSys[i] );
145 for (int i = 0; i < int(oldEvent.sizeSys.size()); ++i)
146 sizeSys.push_back( oldEvent.sizeSys[i] );
147 for (int i = 0; i < int(oldEvent.memberSys.size()); ++i)
148 memberSys.push_back( oldEvent.memberSys[i] );
150 // Copy all other values.
151 startColTag = oldEvent.startColTag;
152 maxColTag = oldEvent.maxColTag;
153 savedSize = oldEvent.savedSize;
154 savedJunctionSize = oldEvent.savedJunctionSize;
155 scaleSave = oldEvent.scaleSave;
156 scaleSecondSave = oldEvent.scaleSecondSave;
157 headerList = oldEvent.headerList;
167 // Initialize colour and header specification for event listing.
169 void Event::init( string headerIn) {
171 // The starting colour tag for the event.
172 startColTag = Settings::mode("Event:startColTag");
174 // Set header specification for event listing.
175 headerList.replace(0, headerIn.length() + 2, headerIn + " ");
181 // Add a copy of an existing particle at the end of the event record;
182 // return index. Three cases, depending on sign of new status code:
183 // Positive: copy is viewed as daughter, status of original is negated.
184 // Negative: copy is viewed as mother, status of original is unchanged.
185 // Zero: the new is a perfect carbon copy (maybe to be changed later).
187 int Event::copy(int iCopy, int newStatus) {
189 // Simple carbon copy.
190 entry.push_back(entry[iCopy]);
191 int iNew = entry.size() - 1;
193 // Set up to make new daughter of old.
195 entry[iCopy].daughters(iNew,iNew);
196 entry[iCopy].statusNeg();
197 entry[iNew].mothers(iCopy, iCopy);
198 entry[iNew].status(newStatus);
200 // Set up to make new mother of old.
201 } else if (newStatus < 0) {
202 entry[iCopy].mothers(iNew,iNew);
203 entry[iNew].daughters(iCopy, iCopy);
204 entry[iNew].status(newStatus);
216 void Event::list(bool showScaleAndVertex, bool showMothersAndDaughters,
220 os << "\n -------- PYTHIA Event Listing " << headerList << "----------"
221 << "------------------------------------------------- \n \n no "
222 << " id name status mothers daughters colou"
223 << "rs p_x p_y p_z e m \n";
224 if (showScaleAndVertex)
226 << " xProd yProd zProd tProd "
229 // At high energy switch to scientific format for momenta.
230 bool useFixed = (entry[0].e() < 1e5);
232 // Listing of complete event.
234 double chargeSum = 0.;
235 for (int i = 0; i < int(entry.size()); ++i) {
236 const Particle& pt = entry[i];
238 // Basic line for a particle, always printed.
239 os << setw(6) << i << setw(10) << pt.id() << " " << left
240 << setw(18) << pt.nameWithStatus(18) << right << setw(4)
241 << pt.status() << setw(6) << pt.mother1() << setw(6)
242 << pt.mother2() << setw(6) << pt.daughter1() << setw(6)
243 << pt.daughter2() << setw(6) << pt.col() << setw(6) << pt.acol()
244 << ( (useFixed) ? fixed : scientific ) << setprecision(3)
245 << setw(11) << pt.px() << setw(11) << pt.py() << setw(11)
246 << pt.pz() << setw(11) << pt.e() << setw(11) << pt.m() << "\n";
248 // Optional extra line for scale value and production vertex.
249 if (showScaleAndVertex)
250 os << " " << setw(11) << pt.scale()
252 << setprecision(3) << setw(11) << pt.xProd() << setw(11)
253 << pt.yProd() << setw(11) << pt.zProd() << setw(11)
254 << pt.tProd() << setw(11) << pt.tau() << "\n";
256 // Optional extra line, giving a complete list of mothers and daughters.
257 if (showMothersAndDaughters) {
260 vector<int> allMothers = motherList(i);
261 for (int j = 0; j < int(allMothers.size()); ++j) {
262 os << " " << allMothers[j];
263 if (++linefill == IPERLINE) {os << "\n "; linefill = 0;}
265 os << "; daughters:";
266 vector<int> allDaughters = daughterList(i);
267 for (int j = 0; j < int(allDaughters.size()); ++j) {
268 os << " " << allDaughters[j];
269 if (++linefill == IPERLINE) {os << "\n "; linefill = 0;}
271 if (linefill !=0) os << "\n";
274 // Statistics on momentum and charge.
275 if (entry[i].status() > 0) {
276 pSum += entry[i].p();
277 chargeSum += entry[i].charge();
281 // Line with sum charge, momentum, energy and invariant mass.
282 os << fixed << setprecision(3) << " "
283 << "Charge sum:" << setw(7) << chargeSum << " Momentum sum:"
284 << ( (useFixed) ? fixed : scientific ) << setprecision(3)
285 << setw(11) << pSum.px() << setw(11) << pSum.py() << setw(11)
286 << pSum.pz() << setw(11) << pSum.e() << setw(11) << pSum.mCalc()
290 os << "\n -------- End PYTHIA Event Listing ----------------------------"
291 << "-------------------------------------------------------------------"
297 // Find complete list of mothers.
299 vector<int> Event::motherList(int i) const {
301 // Vector of all the mothers; created empty.
304 // Read out the two official mother indices and status code.
305 int mother1 = entry[i].mother1();
306 int mother2 = entry[i].mother2();
307 int statusAbs = entry[i].statusAbs();
309 // Special cases in the beginning, where the meaning of zero is unclear.
310 if (statusAbs == 11 || statusAbs == 12) ;
311 else if (mother1 == 0 && mother2 == 0) mothers.push_back(0);
313 // One mother or a carbon copy
314 else if (mother2 == 0 || mother2 == mother1) mothers.push_back(mother1);
316 // A range of mothers from string fragmentation.
317 else if ( statusAbs > 80 && statusAbs < 90)
318 for (int iRange = mother1; iRange <= mother2; ++iRange)
319 mothers.push_back(iRange);
321 // Two separate mothers.
323 mothers.push_back( min(mother1, mother2) );
324 mothers.push_back( max(mother1, mother2) );
334 // Find complete list of daughters.
336 vector<int> Event::daughterList(int i) const {
338 // Vector of all the daughters; created empty.
339 vector<int> daughters;
341 // Read out the two official daughter indices.
342 int daughter1 = entry[i].daughter1();
343 int daughter2 = entry[i].daughter2();
345 // Simple cases: no or one daughter.
346 if (daughter1 == 0 && daughter2 == 0) ;
347 else if (daughter2 == 0 || daughter2 == daughter1)
348 daughters.push_back(daughter1);
350 // A range of daughters.
351 else if (daughter2 > daughter1)
352 for (int iRange = daughter1; iRange <= daughter2; ++iRange)
353 daughters.push_back(iRange);
355 // Two separated daughters.
357 daughters.push_back(daughter2);
358 daughters.push_back(daughter1);
361 // Special case for two incoming beams: attach further
362 // initiators and remnants that have beam as mother.
363 if (entry[i].statusAbs() == 12 || entry[i].statusAbs() == 13)
364 for (int iDau = 3; iDau < size(); ++iDau)
365 if (entry[iDau].mother1() == i) {
367 for (int iIn = 0; iIn < int(daughters.size()); ++iIn)
368 if (iDau == daughters[iIn]) isIn = true;
369 if (!isIn) daughters.push_back(iDau);
379 // Trace the first and last copy of one and the same particle.
381 int Event::iTopCopy( int i) const {
384 while ( iUp > 0 && entry[iUp].mother2() == entry[iUp].mother1()
385 && entry[iUp].mother1() > 0) iUp = entry[iUp].mother1();
390 int Event::iBotCopy( int i) const {
393 while ( iDn > 0 && entry[iDn].daughter2() == entry[iDn].daughter1()
394 && entry[iDn].daughter1() > 0) iDn = entry[iDn].daughter1();
401 // Trace the first and last copy of one and the same particle,
402 // also through shower branchings, making use of flavour matches.
403 // Stops tracing when this gives ambiguities.
405 int Event::iTopCopyId( int i) const {
407 int id = entry[i].id();
410 int mother1 = entry[iUp].mother1();
411 int id1 = (mother1 > 0) ? entry[mother1].id() : 0;
412 int mother2 = entry[iUp].mother2();
413 int id2 = (mother2 > 0) ? entry[mother2].id() : 0;
414 if (mother2 != mother1 && id2 == id1) break;
429 int Event::iBotCopyId( int i) const {
431 int id = entry[i].id();
434 int daughter1 = entry[iDn].daughter1();
435 int id1 = (daughter1 > 0) ? entry[daughter1].id() : 0;
436 int daughter2 = entry[iDn].daughter2();
437 int id2 = (daughter2 > 0) ? entry[daughter2].id() : 0;
438 if (daughter2 != daughter1 && id2 == id1) break;
455 // Find complete list of sisters.
457 vector<int> Event::sisterList(int i) const {
459 // Vector of all the sisters; created empty.
461 if (entry[i].statusAbs() == 11) return sisters;
463 // Find mother and all its daughters.
464 int iMother = entry[i].mother1();
465 vector<int> daughters = daughterList(iMother);
467 // Copy all daughters, excepting the input particle itself.
468 for (int j = 0; j < int(daughters.size()); ++j)
469 if (daughters[j] != i) sisters.push_back( daughters[j] );
478 // Find complete list of sisters. Traces up with iTopCopy and
479 // down with iBotCopy to give sisters at same level of evolution.
480 // Should this not give any final particles, the search is widened.
482 vector<int> Event::sisterListTopBot(int i, bool widenSearch) const {
484 // Vector of all the sisters; created empty.
486 if (entry[i].statusAbs() == 11) return sisters;
488 // Trace up to first copy of current particle.
489 int iUp = iTopCopy(i);
491 // Find mother and all its daughters.
492 int iMother = entry[iUp].mother1();
493 vector<int> daughters = daughterList(iMother);
495 // Trace all daughters down, excepting the input particle itself.
496 for (int jD = 0; jD < int(daughters.size()); ++jD)
497 if (daughters[jD] != iUp)
498 sisters.push_back( iBotCopy( daughters[jD] ) );
500 // Prune any non-final particles from list.
502 while (jP < int(sisters.size())) {
503 if (entry[sisters[jP]].status() > 0) ++jP;
505 sisters[jP] = sisters.back();
510 // If empty list then restore immediate daughters.
511 if (sisters.size() == 0 && widenSearch) {
512 for (int jR = 0; jR < int(daughters.size()); ++jR)
513 if (daughters[jR] != iUp)
514 sisters.push_back( iBotCopy( daughters[jR] ) );
516 // Then trace all daughters, not only bottom copy.
517 for (int jT = 0; jT < int(sisters.size()); ++jT) {
518 daughters = daughterList( sisters[jT] );
519 for (int k = 0; k < int(daughters.size()); ++k)
520 sisters.push_back( daughters[k] );
523 // And then prune any non-final particles from list.
525 while (jN < int(sisters.size())) {
526 if (entry[sisters[jN]].status() > 0) ++jN;
528 sisters[jN] = sisters.back();
541 // Check whether a given particle is an arbitrarily-steps-removed
542 // mother to another. For the parton -> hadron transition, only
543 // first-rank hadrons are associated with the respective end quark.
545 bool Event::isAncestor(int i, int iAncestor) const {
547 // Begin loop to trace upwards from the daughter.
551 // If positive match then done.
552 if (iUp == iAncestor) return true;
554 // If out of range then failed to find match.
555 if (iUp <= 0 || iUp > size()) return false;
557 // If unique mother then keep on moving up the chain.
558 int mother1 = entry[iUp].mother1();
559 int mother2 = entry[iUp].mother2();
560 if (mother2 == mother1 || mother2 == 0) {iUp = mother1; continue;}
562 // If many mothers, except hadronization, then fail tracing.
563 int status = entry[iUp].statusAbs();
564 if (status < 81 || status > 86) return false;
566 // For hadronization step, fail if not first rank, else move up.
568 iUp = (iUp + 1 < size() && entry[iUp + 1].mother1() == mother1)
569 ? mother1 : mother2; continue;
572 if (entry[iUp - 1].mother1() == mother1) return false;
573 iUp = mother1; continue;
576 if (iUp + 1 < size() && entry[iUp + 1].mother1() == mother1)
578 iUp = mother1; continue;
581 // Fail for ministring -> one hadron and for junctions.
585 // End of loop. Should never reach beyond here.
592 // Erase junction stored in specified slot and move up the ones under.
594 void Event::eraseJunction(int i) {
596 for (int j = i; j < int(junction.size()) - 1; ++j)
597 junction[j] = junction[j + 1];
604 // Print the junctions in an event.
606 void Event::listJunctions(ostream& os) const {
609 os << "\n -------- PYTHIA Junction Listing "
610 << headerList.substr(0,30) << "\n \n no kind col0 col1 col2 "
611 << "endc0 endc1 endc2 stat0 stat1 stat2\n";
613 // Loop through junctions in event and list them.
614 for (int i = 0; i < sizeJunction(); ++i)
615 os << setw(6) << i << setw(6) << kindJunction(i) << setw(6)
616 << colJunction(i, 0) << setw(6) << colJunction(i, 1) << setw(6)
617 << colJunction(i, 2) << setw(6) << endColJunction(i, 0) << setw(6)
618 << endColJunction(i, 1) << setw(6) << endColJunction(i, 2) << setw(6)
619 << statusJunction(i, 0) << setw(6) << statusJunction(i, 1) << setw(6)
620 << statusJunction(i, 2) << "\n";
622 // Alternative if no junctions. Listing finished.
623 if (sizeJunction() == 0) os << " no junctions present \n";
624 os << "\n -------- End PYTHIA Junction Listing --------------------"
630 // Add parton to system, by shifting everything below to make room.
632 void Event::addToSystem(int iSys, int iPos) {
634 int newPos = beginSys[iSys] + sizeSys[iSys];
635 memberSys.push_back(0);
636 for (int i = int(memberSys.size()) - 2; i >= newPos; --i)
637 memberSys[i+1] = memberSys[i];
638 memberSys[newPos] = iPos;
640 for (int i = iSys + 1; i < int(beginSys.size()); ++i) ++beginSys[i];
646 // Replace existing value by new one in given system but unknown member.
648 void Event::replaceInSystem(int iSys, int iPosOld, int iPosNew) {
650 for (int i = beginSys[iSys]; i < beginSys[iSys] + sizeSys[iSys]; ++i)
651 if (memberSys[i] == iPosOld) memberSys[i] = iPosNew;
657 // Print members in systems; for debug mainly.
659 void Event::listSystems(ostream& os) const {
663 os << "\n -------- PYTHIA Systems Listing " << headerList
664 << "------------ \n \n no members \n";
666 // Loop over system list and over members in each system.
667 for (int iSys = 0; iSys < int(beginSys.size()); ++iSys) {
668 os << " " << setw(5) << iSys << " ";
669 for (int iMem = 0; iMem < sizeSys[iSys]; ++iMem) {
670 if (iMem%16 == 0 && iMem > 0) os << "\n ";
671 os << " " << setw(4) << memberSys[beginSys[iSys] + iMem];
676 // Alternative if no systems. Done.
677 if (beginSys.size() == 0) os << " no systems defined \n";
678 os << "\n -------- End PYTHIA Systems Listing ----------------------"
679 << "--------------------------" << endl;
685 // Operator overloading allows to append one event to an existing one.
687 Event& Event::operator+=( const Event& addEvent) {
689 // Find offsets. One less since won't copy line 0.
690 int offsetIdx = entry.size() - 1;
691 int offsetCol = maxColTag;
693 // Add energy to zeroth line and calculate new invariant mass.
694 entry[0].p( entry[0].p() + addEvent[0].p() );
695 entry[0].m( entry[0].mCalc() );
697 // Read out particles from line 1 (not 0) onwards.
699 for (int i = 1; i < addEvent.size(); ++i) {
702 // Add offset to nonzero mother, daughter and colour indices.
703 if (temp.mother1() > 0) temp.mother1( temp.mother1() + offsetIdx );
704 if (temp.mother2() > 0) temp.mother2( temp.mother2() + offsetIdx );
705 if (temp.daughter1() > 0) temp.daughter1( temp.daughter1() + offsetIdx );
706 if (temp.daughter2() > 0) temp.daughter2( temp.daughter2() + offsetIdx );
707 if (temp.col() > 0) temp.col( temp.col() + offsetCol );
708 if (temp.acol() > 0) temp.acol( temp.acol() + offsetCol );
710 // Append particle to summed event.
714 // Read out junctions one by one.
717 for (int i = 0; i < addEvent.sizeJunction(); ++i) {
718 tempJ = addEvent.getJunction(i);
720 // Add colour offsets to all three legs.
721 for (int j = 0; j < 3; ++j) {
722 begCol = tempJ.col(j);
723 endCol = tempJ.endCol(j);
724 if (begCol > 0) begCol += offsetCol;
725 if (endCol > 0) endCol += offsetCol;
726 tempJ.cols( j, begCol, endCol);
729 // Append junction to summed event.
730 appendJunction( tempJ );
733 // Read out systems one by one. Append new system to event.
734 for (int i = 0; i < addEvent.sizeSystems(); ++i) {
735 int iNew = newSystem();
737 // Append members in system, with offset.
738 for (int j = 0; j < addEvent.sizeSystem(i); ++j)
739 addToSystem( iNew, addEvent.getInSystem( i, j) + offsetIdx );
742 // Set header that indicates character as sum of events.
743 headerList = "(combination of several events) -------";
750 //**************************************************************************
752 } // end namespace Pythia8