The Event Record

The Event class for event records basically is a vector of Particles, so that it can expand to fit the event size. The index operator is overloaded, so that event[i] corresponds to the i'th particle of an Event object event. Thus event[i].id() returns the identity of the i'th particle. References to the first, i'th and last particle are obtained with event.front(), event.at(i) and event.back(), respectively.

The event size can be found with size(), i.e. valid particles are stored in 0 <= i < event.size().

Line 0 is used to represent the event as a whole, with its total four-momentum and invariant mass, but does not form part of the event history. Lines 1 and 2 contains the two incoming beams, and only from here on history tracing works as could be expected. That way unassigned mother and daughter indices can be put 0 without ambiguity. Depending on the task at hand, a loop may therefore start at an index 1 without any loss. Specifically, for translation to other event record formats such as HepMC [Dob01], where the first index is 1, the Pythia entry 0 definitely ought to be skipped in order to minimize the danger of errors.

New particles can be added to the end of the current event record with append(Particle), or append(id, status, mother1, mother2, daughter1, daughter2, col, acol, p, m, scale) where p is the four-momentum vector, and everything except id defaults to 0. The append method returns the index of the new particle position.

The existing particle at index iCopy can be copied to the end with copy(iCopy, newStatus = 0). By default, i.e. with newStatus = 0, everything is copied precisely as it is, which means that history information has to be modified further by hand to make sense. With a positive newStatus, the new copy is set up to be the daughter of the old, with status code newStatus, and the status code of iCopy is negated. With a negative newStatus, the new copy is instead set up to be the mother of iCopy.

The event record can be emptied for the next event by a clear(). The last n entries can be removed by popBack(n), where n = 1 by default. The = operator is overloaded to allow a copying of an event record, and += to append an event to an existing one. In the latter case mother, daughter and colour tags are shifted to make a consistent record. The zeroth particle of the appended event is not copied, but the zeroth particle of the combined event is updated to the full energy-momentum content.

A listing of the whole event is obtained with list(). The basic id, status, mother, daughter, colour, four-momentum and mass data are always given, but the method can also be called with a few optional arguments for further information:

method  list(showScaleAndVertex, showMothersAndDaughters, os)  
where
argument showScaleAndVertex (default = false) : optionally give a second line for each particle, with the production scale (in GeV), the production vertex (in mm or mm/c) and the invariant lifetime (also in mm/c).
argument showMothersAndDaughters (default = false) : gives a list of all daughters and mothers of a particle, as defined by the motherList(i) and daughterList(i) methods described below. It is mainly intended for debug purposes.
argument os (default = cout) : a reference to the ostream object to which the event listing will be directed.

Each particle in the event record has a pointer to the corresponding particle species in the particle database, used to find some particle properties. This pointer is automatically set whenever the particle identity is set by one of the normal methods. Of course its value is specific to the memory location of the current run, and so it has no sense to save it if events are written to file. Should you use some persistency scheme that bypasses the normal methods when the event is read back in, you can use restorePtrs() afterwards to set these pointers appropriately.

The user would normally be concerned with the Event object that is a public member event of the Pythia class. Thus, having declared a Pythia object pythia, pythia.event[i].id() would be used to return the identity of the i'th particle, and pythia.event.size() to give the size of the event record.

A Pythia object contains a second event record for the hard process alone, called process, used as input for the generation of the complete event. Thus one may e.g. call either pythia.process.list() or pythia.event.list(). To distinguish those two rapidly at visual inspection, the "Pythia Event Listing" header is printed out differently, in one case adding "(hard process)" and in the other "(complete event)". When += is used to append an event, the modified event is printed with "(combination of several events)" as a reminder.

One data member in an Event object is used to keep track of the largest col() or acol() tag set so far, so that new ones do not clash. The lastcolTag() method returns the last tag assigned, i.e. largest value in the current event, and nextColTag() ups it by one before returing the value. The latter method thus is used when a new colour tag is needed.

mode  Event:startColTag   (default = 100; minimum = 0; maximum = 1000)
This sets the initial value used, so that the first one assigned is startColTag+1, etc. The Les Houches accord [Boo01] suggests this number to be 500, but 100 works equally well.

The scale() methods can be used to set or get the scale (in GeV) of the event as a whole. Further methods for event properties may be added in the future.

A few methods exist to rotate and boost events. These derive from the Vec4 methods, and affect both the momentum and the vertex (position) components of all particles.

method  rot(theta, phi)  
rotate by this polar and azimuthal angle (expressed in radians).

method  bst(betaX, betaY, betaZ)  
boost by this vector. Optionally you may provide the gamma value as a fourth argument, if you deem this may help avoid roundoff errors for big boosts. You may alternatively supply a Vec4 four-vector, in which case the boost vector beta = p/E.

method  rotbst(M)  
rotate and boost by the combined action encoded in the RotBstMatrix M.

There are also a few methods with an individual particle index i as input, but requiring some search operations in the event record, and therefore not possible to define inside the Particle class:

method  motherList(i)  
returns a vector<int> containing a list of all the mothers of a particle. This list is empty for entries 0, 1 and 2, i.e. the "system" in line 0 is not counted as part of the history. Normally the list contains one or two mothers, but it can also be more, e.g. in string fragmentation the whole fragmenting system is counted as mothers to the primary hadrons. Mothers are listed in ascending order.

method  daughterList(i)  
returns a vector<int> containing a list of all the daughters of a particle. This list is empty for a particle that did not decay (or, if the evolution is stopped early enough, a parton that did not branch), while otherwise it can contain a list of varying length, from one to many. Many partons may have the same daughterList, e.g. in the hard process and fragmentation steps. For the two incoming beam particles, all shower initiators and beam remnants are counted as daughters, with the one in slot 0 being the one leading up to the hardest interaction. The "system" in line 0 does not have any daughters, i.e. is not counted as part of the history.

method  iTopCopy(i), iBotCopy(i)  
are used to trace carbon copies of the particle at index i up to its top mother or down to its bottom daughter. If there are no such carbon copies, i itself will be returned.

method  iTopCopyId(i), iBotCopyId(i)  
also trace top mother and bottom daughter, but do not require carbon copies, only that one can find an unbroken chain, of mothers or daughters, with the same flavour id code. When it encounters ambiguities, say a g -> g g branching or a u u -> u u hard scattering, it will stop the tracing and return the current position. It can be confused by nontrivial flavour changes, e.g. a hard process u d -> d u by W^+- exchange will give the wrong answer. These methods therefore are of limited use for common particles, in particular for the gluon, but should work well for "rare" particles.

method  sisterList(i)  
returns a vector<int> containing a list of all the sisters of a particle, i.e. all the daughters of the first mother, except the particle itself.

method  sisterListTopBot(i)  
returns a vector<int> containing a list of all the sisters of a particle, tracking up and back down through carbon copies if required. That is, the particle is first traced up with iTopCopy() before its mother is found, and then all the particles in the daughterList() of this mother are traced down with iBotCopy(), omitting the original particle itself. Any non-final particles are removed from the list. Should this make the list empty the search criterion is widened so that all final daughters are allowed, not only carbon-copy ones. A second argument false inhibits the second step, and increases the risk that an empty list is returned. A typical example of this is for ISR cascades, e.g. e -> e gamma where the photon may not have any obvious sister in the final state if the bottom copy of the photon is an electron that annihilates and thus is not part of the final state.

method  isAncestor(i, iAncestor)  
traces the particle i upwards through mother, grandmother, and so on, until either iAncestor is found or the top of the record is reached. Normally one unique mother is required, as is the case e.g. in decay chains or in parton showers, so that e.g. the tracing through a hard scattering would not work. For hadronization, first-rank hadrons are identified with the respective string endpoint quark, which may be useful e.g. for b physics, while higher-rank hadrons give false. Currently also ministrings that collapsed to one single hadron and junction topologies give false.

The Junction Class

The event record also contains a vector of junctions, which often is empty or else contains only a very few per event. Methods are available to add further junctions or query the current junction list. This is only for the expert user, however, and is not discussed further here, but only the main points.

A junction stores the properites associated with a baryon number that is fully resolved, i.e. where three different colour indices are involved. There are two main applications,

  1. baryon beams, where at least two valence quarks are kicked out, and so the motion of the baryon number is notrivial;
  2. baryon-number violating processes, e.g. in SUSY with broken R-parity.
Information on junctions is set, partly in the process generation, partly in the beam remnants machinery, and used by the fragmentation routines, but the normal user does not have to know the details.

For each junction, information is stored on the kind of junction, and on the three (anti)colour indices that are involved in the junction. The possibilities foreseen are:

The odd (even) kind codes corresponds to a +1 (-1) change in baryon number across the junction.
Warning: Currently only kind = 1, 2 are implemented.

The kind and colour information in the list of junctions can be set or read with methods of the Event class, but are not of common interest and so not described here.

A listing of current junctions can be obtained with the listJunctions() method.

Subsystems

The event record also contains a few vectors where parton indices can be stored, classified by subsystem. Such information is needed to interleave multiple interactions, initial-state showers, final-state showers and beam remnants. It could also be used in other places. It is intended to be accessed only by experts, such as implementors of new showering models.

A listing of current subsystems can be obtained with the listSystems() method.