Mu2e Home
Geant4 Notes

This page holds a collection of notes about Geant4. Once we have collected enough we will figure out a way to organize them.

  1. The Decay pi+ -> e+ nu_e
  2. G4 Particle ID Codes
  3. How to use G4ParticleTable::G4PTblDicIterator

The Decay pi+ -> e+ nu_e

In default Geant4 the particle decay table for pi+ contains only one decay, pi+-> mu+ nu_mu; therefore the decay mode pi+-> e+ nu_e is absent from the decay table. Similarly for pi-. As of July 10, 2012, the Mu2e code adds the decay pi+-> e+ nu_e (and its charge conjugate) to the decay tables, using the PDG value for the branchinig fraction. This behaviour can be controlled at run time using two parameters in geom_01.txt

string g4.PiENuPolicy          = PDG;
int    g4.PiENuPolicyVerbosity = 0;
The first parameter may take any of the following 4 values,
   PDG   - Set the pi -> e nu and pi -> mu nu branching fractions to their PDG values.
   None  - Leave the decay table unchanged ( 100% pi-> mu nu ).
   All   - Set the pi-> e nu branching fraction to 100% and pi-> mu nu to 0%
   nnnnn - where nnnnn is a numerical value in the range [0., 1.]
           Set the e nu branching fraction to the specified number and the mu nu branching fraction to (1-nnnnn).

If the parameter is absent from the geometry file, the value PDG will be used.

If the second parameter is set to a number greater than 0, the code will print the decay table of the pi+ and the pi- after the changes, if any, are made.

This code is implemented in Mu2eG4/src/, which is called from Mu2eG4/src/ The later code is called by in the beginRun method, immediately after the call to G4RunManager::Initialize().

G4 Particle ID Codes

The particle types inside Geant4 are identified by a superset of the standard PDG particle ID codes. If a particle is one of those defined by the PDG particle ID encoding scheme, then the Geant4 particle Id code is the same as the PDG code. However Geant4 needs codes to describe particles that are not present in the PDG scheme, such as ions, nuclei, excited states of atoms and nuclei, and so on. Geant4 represents these as integers > 1,000,000,000. When you ask an object of type mu2e::SimParticle for its pdgId, you actually get a GeantId particle Id, which can sometimes have values > 1,000,000,000.

The Mu2e particle data table (PDT) only includes the standard PDG particles; it does not include the Geant4 extensions. To deal with this the PDT class returns information about particles via a "safe" reference class:

    SimParticle const& sim = ... ;
    ConditionsHandle pdt("ignored");

    ParticleDataTable::maybe_ref particle = pdt->particle(sim.pdgId());

    if ( particle ) {
       HepPDT::ParticleData const& pdata = particle.ref();
       //  pdata holds the particle name, mass, width etc
    } else {
       // The particle is not in the table
The type ParticleDataTable::maybe_ref is defined in Offline/ConditionsService/inc/ParticleDataTable.hh; it is defined in terms of the class template cet::maybe_ref which is discussed on the page that discusses handles.

We advise that you test the maybe_ref object rather than testing to see if the particle ID is greater than some large number. If you do this, then your code will work should we decide to extend our particle table to include the extra ids defined by Geant4. It will also protect you against the possible case that our particle table gets out of sync with the Geant4 table.

How to use G4ParticleTable::G4PTblDicIterator

The iterator class G4ParticleTable::G4PTblDicIterator is very unusual and does not follow any pattern that I have seen before. This note describes how to use it. This construct is used in Mu2eG4/src/ and Mu2eG4/src/ .

The G4ParticleTable class internally contains a std::map<G4String,ParticleDefinition*>. Users of the class need to be able to loop over the map. To provide this functionality the designers of the class chose to provide a custom written iterator. ( Current best practice would be to provide a typedef to the underlying stl iterator type. It is possible that this design was frozen before std::map was robust and that this class provides a work around that once had been necessary. )

The rules for using this iterator are:

  1. You must call reset() before starting the loop. If you forget, the iterator will usually, but not always, start the iteration past the end of the map, which produces undefined behaviour.
  2. The call to operator ():
  3. At any time, a call to key() or to value() will return the information pointed to by the interally held iterator.
A code fragment illustrating this use appears below:

    G4ParticleTable::G4PTblDicIterator* iter = G4ParticleTable::GetParticleTable()->GetIterator();

    while( (*iter)() ){
      G4ParticleDefinition* particle = iter->value();
      cout << particle->GetParticleName() << endl;

A particularly bizarre feature is that the G4ParticleTable class holds its own iterator. When you ask for an iterator, you actually get a pointer to this one iterator. Therefore, if you try to write a nested loop over the map you will get really strange behaviour.

Fermilab at Work ]  [ Mu2e Home ]  [ Mu2e @ Work ]  [ Mu2e DocDB ]  [ Mu2e Search ]

For web related questions:
For content related questions: genser@youknow.where.
This file last modified Wednesday, 11-Jul-2012 13:21:35 CDT
Security, Privacy, Legal Fermi National Accelerator Laboratory