Getting started

This note covers a brief overview of running ParticleBomb event generator (repository), which is used for generating simulation samples to train data reconstruction models in lartpc_mlreco3d package (repository).

What is an event generator?

In case you are not familiar with the term event generator, in High Energy Physics (HEP) experiments, an event generator is the first step of a simulation chain which consists of 3 major steps.

  1. Event Generator … generates a list of particles that will interact with an experiment detector. There are many event generators out there (e.g. GENIE, GLOBUS, GIBU, …) but they all do the same: generate a list of particles.

  2. Particle Tracking … takes the output of 1 (i.e. a list of particles), and simulate how each particle interacts with the detector medium. For this stage, almost all HEP experiments use a software called Geant4, which contains detailed physics models of how all kinds of particles interact with all kinds of materials. The output of Geant4 is energy deposition information in the form of a particle trajectory. For instance, if your event generator provide 1 muon as an input to this stage of simulation, Geant4 simulates how this muon go through all kinds of micro-physics processes such as multiple coulomb scattering, radiation of another particle, an interaction with electromagnetic field, a decay, energy deposition along its trajectory in a medium, etc..

  3. Detector response … takes the energy deposition information from Geant4, and simulates how your detector respond to them. This may include how your detector signal is created (e.g. for LArTPC, this might be ionization electrons and scintillation photons), how those signal propagate to sensitive detector electronics, and how those electronics respond to the signal. The output of this stage mimics the data that is recorded by your detector.

How to use ParticleBomb

This event generator can be run in 2+1 steps.

  1. Instantiate and configure

  2. Generate particles

  3. Convert into HEPEVT-like format (optional)

The generation is done after the 2nd step. The 3rd step is optional to convert the results into a HEPEVT-friendly format, which is used to feed the output of this generator into the next step of simulation = particle tracking using Geant4. We go over the HEPEVT format later in this note.

Step 1: instantiate and configure

The event generator package provides a utility Python function called create_generator. This function consumes a formatted configuration (Python dict), then create a ParticleBomb instance with the configuration parameters applied.

In this note, we don’t go over the configuration format. That will be the next section. For now, we use an example configuration provided by the package.

import yaml
from dlp_generator import create_generator, EXAMPLE_CONFIG

# parse configuration
cfg=yaml.load(EXAMPLE_CONFIG, Loader=yaml.Loader)

# create and configure a generator
gen = create_generator(cfg)
Welcome to JupyROOT 6.22/09

Step 2: run the generator

Just call Generate function :)

# run the generator
result = gen.Generate()

Yep, that’s it! But yeah, we don’t feel like this meant anything real. So let’s try one more time. This time, we enable a Debug flag so that the generator prints out some information as it runs.

# Set the Debug flag to True in the configuration
cfg['Debug'] = True

# create and configure a generator
gen = create_generator(cfg)

# run
result = gen.Generate()
ParticleBomb created with SEED 191001214

Running a new generation...


Interaction config 0 multiplicity: 1

  Generating an interaction 0 with 3 particles...
  Vertex at (58.8441,64.2406,38.0656) [mm] ... time @ 9.21129 [ns]
  Adding a virtual root particle (Graviton PDG 39)

    New particle PDG 13 Mass 0.105658 [GeV/c**2]
    Direction : (-0.281077,0.306403,-0.909457)
    Momentum  : 0.877377 [GeV/c]
    Energy    : 0.883716 [GeV/c**2]

    New particle PDG 111 Mass 0.134977 [GeV/c**2]
    Direction : (0.024766,0.776532,-0.629591)
    Momentum  : 0.873898 [GeV/c]
    Energy    : 0.884261 [GeV/c**2]

    New particle PDG 111 Mass 0.134977 [GeV/c**2]
    Direction : (0.210134,0.134103,-0.968432)
    Momentum  : 0.238619 [GeV/c]
    Energy    : 0.27415 [GeV/c**2]


Interaction config 1 multiplicity: 1

  Generating an interaction 0 with 4 particles...
  Vertex at (2.62791,83.9522,45.5753) [mm] ... time @ 2.6597 [ns]

    New particle PDG 13 Mass 0.105658 [GeV/c**2]
    Direction : (-0.660945,-0.514133,-0.546643)
    Momentum  : 1.10047 [GeV/c]
    Energy    : 1.10553 [GeV/c**2]

    New particle PDG 11 Mass 0.000510999 [GeV/c**2]
    Direction : (0.19581,-0.926872,0.320259)
    Momentum  : 0.395075 [GeV/c]
    Energy    : 0.395075 [GeV/c**2]

    New particle PDG 13 Mass 0.105658 [GeV/c**2]
    Direction : (0.532528,0.804466,-0.263152)
    Momentum  : 1.04484 [GeV/c]
    Energy    : 1.05017 [GeV/c**2]

    New particle PDG 13 Mass 0.105658 [GeV/c**2]
    Direction : (0.793337,0.544652,-0.271976)
    Momentum  : 0.685921 [GeV/c]
    Energy    : 0.694011 [GeV/c**2]

… and now we can see information about particles generated. It feels a bit more real :) In the above example, we set the debug flag in the configuration dictionary. Another way to set/unset is to simply call an attribute function of the generator.

gen.Debug(False)

Before step-3 … HEPEVT format

A HEPEVT format is a way to list necessary information about particles to be simulated by Geant4, and it’s pretty simple. For each particle, 15 values are recorded. It’s actually an ASCII text file listing 15 values (=one particle information) per line. Values are separated by a space. Here’re the list of values contained:

  1. status code … 1 = feed in Geant4, other values mean don’t track (but useful for the record)

  2. PDG code … an identifier for a type of a particle. See this reference to decode.

  3. Line number of the first parent particle (0 for initial entries)

  4. Line number of the second parent particle

  5. Line number of the first child particle

  6. Line number of the last child particle

  7. x momentum [GeV/c]

  8. y momentum [GeV/c]

  9. z momentum [GeV/c]

  10. energy [GeV]

  11. mass [GeV/c^2]

  12. x position [mm]

  13. y position [mm]

  14. z position [mm]

  15. time [ns]

For example, let’s consider 2 particles:

  • A muon at position (0,0,0), time=0, momentum (0,0,0) [GeV/c] with energy 105 GeV and mass 0.105 GeV/c^2

  • A photon at position (1,1,1), time=0, momentum (1,0,0) with energy 1 GeV and mass 0 GeV/c^2

The HEPEVT format would look like this:

1 13 0 0 0 0 0 0 0 105 105 0 0 0 0
1 22 0 0 0 0 1 0 0 1   0   1 1 1 0

Step-3: converting into HEPEVT-like format

So we would like to convert the resulting list of particles into HEPEVT format. ParticleBomb provides a utility function called Flatten to do this.

# Convert the result into HEPEVT-like format, which is an array of length-15-array
hepevt = gen.Flatten(result)

Let’s loop over the list of particles and print out 15 attribute values

for part in hepevt:
    line = ''
    for v in part: line += str(v) + ' '
    print(line)
3.0 39.0 0.0 0.0 1.0 3.0 -0.1748256942716093 0.9794408643543246 -1.5792221021301613 2.0421265939948103 0.0 58.844118962730676 64.24064919268643 38.065576928547564 9.211286770551714 
1.0 13.0 0.0 0.0 0.0 0.0 -0.24661059670281213 0.2688313149753433 -0.7979373272008057 0.8837163874353892 0.105658 58.844118962730676 64.24064919268643 38.065576928547564 9.211286770551714 
1.0 111.0 0.0 0.0 0.0 0.0 0.021642955460933394 0.6786100653347765 -0.5501981612020188 0.8842606207526356 0.134977 58.844118962730676 64.24064919268643 38.065576928547564 9.211286770551714 
1.0 111.0 0.0 0.0 0.0 0.0 0.05014194697026945 0.03199948404420488 -0.2310866137273369 0.2741495858067855 0.134977 58.844118962730676 64.24064919268643 38.065576928547564 9.211286770551714 
1.0 13.0 4.0 4.0 0.0 0.0 -0.7273510446945195 -0.5657885955670736 -0.6015643620489936 1.1055313526731765 0.105658 2.627906219459554 83.95223208791495 45.57534999327091 2.6596984489913917 
1.0 11.0 5.0 5.0 0.0 0.0 0.07735971240874666 -0.3661837304675006 0.1265261156851653 0.39507488990483935 0.00051099891 2.627906219459554 83.95223208791495 45.57534999327091 2.6596984489913917 
1.0 13.0 6.0 6.0 0.0 0.0 0.5564048120466765 0.8405357726260242 -0.27495069829673646 1.0501657961439175 0.105658 2.627906219459554 83.95223208791495 45.57534999327091 2.6596984489913917 
1.0 13.0 7.0 7.0 0.0 0.0 0.544166469861037 0.37358854234820293 -0.18655425194072087 0.6940112735222964 0.105658 2.627906219459554 83.95223208791495 45.57534999327091 2.6596984489913917 

OK that’s a nightmare (though you would need this for Geant4!). ParticleBomb also has a friendly function that prints out a formatted summary text showing a list of particle type and hierarchies.

# print out the hierarchy
gen.PrintHierarchy(hepevt)
Dumping hierarchy information for 8 particles...

  ---- Line 0 PDG 39 energy 2.04213 [GeV] ... 3 children particles
    |- Line 1 PDG 13 energy 0.883716 [GeV] ... parent 0
    |- Line 2 PDG 111 energy 0.884261 [GeV] ... parent 0
    |- Line 3 PDG 111 energy 0.27415 [GeV] ... parent 0

  ---- Line 4 PDG 13 energy 1.10553 [GeV]

  ---- Line 5 PDG 11 energy 0.395075 [GeV]

  ---- Line 6 PDG 13 energy 1.05017 [GeV]

  ---- Line 7 PDG 13 energy 0.694011 [GeV]

Reproducibility (seed)

Finally, when debugging, it’s often useful to have a full reproducibility. This is possible by creating a generator with a fixed random number seed. The seed used by the generator is printed out at the creation when you enable the debug mode. Or you can also just ask for it.

print('Seed:',gen.Seed())
Seed: 191001214

If the seed is not provided by the configuration, or provided as a negative value, the generator uses the timestamp as a seed, which changes all the time, in order to avoid always generating the same set of particles. Let’s try running the generator twice with the time seed. We expect the generated particle list to be different.

gen.Seed(-1)
gen.PrintHierarchy(gen.Flatten(gen.Generate()))

gen.Seed(-1)
gen.PrintHierarchy(gen.Flatten(gen.Generate()))
Dumping hierarchy information for 9 particles...

  ---- Line 0 PDG 39 energy 1.21141 [GeV] ... 3 children particles
    |- Line 1 PDG 22 energy 0.149153 [GeV] ... parent 0
    |- Line 2 PDG 211 energy 0.905686 [GeV] ... parent 0
    |- Line 3 PDG 111 energy 0.156573 [GeV] ... parent 0

  ---- Line 4 PDG 39 energy 1.85754 [GeV] ... 3 children particles
    |- Line 5 PDG 22 energy 0.0222408 [GeV] ... parent 4
    |- Line 6 PDG 2112 energy 0.976908 [GeV] ... parent 4
    |- Line 7 PDG 111 energy 0.858392 [GeV] ... parent 4

  ---- Line 8 PDG 13 energy 0.670584 [GeV]

Dumping hierarchy information for 11 particles...

  ---- Line 0 PDG 39 energy 3.21954 [GeV] ... 3 children particles
    |- Line 1 PDG 2112 energy 1.41252 [GeV] ... parent 0
    |- Line 2 PDG -211 energy 0.889894 [GeV] ... parent 0
    |- Line 3 PDG 13 energy 0.917127 [GeV] ... parent 0

  ---- Line 4 PDG 39 energy 2.37949 [GeV] ... 3 children particles
    |- Line 5 PDG 111 energy 0.52242 [GeV] ... parent 4
    |- Line 6 PDG 13 energy 0.84633 [GeV] ... parent 4
    |- Line 7 PDG 111 energy 1.01074 [GeV] ... parent 4

  ---- Line 8 PDG 13 energy 0.799991 [GeV]

  ---- Line 9 PDG 13 energy 0.86036 [GeV]

  ---- Line 10 PDG 13 energy 0.324973 [GeV]

When we debug the code, on the other hand, we often want to test the code behavior against a specific (fixed) state. We want a predictability in the output (to make sure it’s working). For this, you can set the seed and have a reproducible set of particles.

gen.Seed(1)
gen.PrintHierarchy(gen.Flatten(gen.Generate()))

gen.Seed(1)
gen.PrintHierarchy(gen.Flatten(gen.Generate()))
Dumping hierarchy information for 7 particles...

  ---- Line 0 PDG 39 energy 1.25777 [GeV] ... 3 children particles
    |- Line 1 PDG -211 energy 0.229023 [GeV] ... parent 0
    |- Line 2 PDG 11 energy 0.41918 [GeV] ... parent 0
    |- Line 3 PDG 111 energy 0.609571 [GeV] ... parent 0

  ---- Line 4 PDG 13 energy 0.895864 [GeV]

  ---- Line 5 PDG 13 energy 0.504029 [GeV]

  ---- Line 6 PDG 13 energy 0.994078 [GeV]

Dumping hierarchy information for 7 particles...

  ---- Line 0 PDG 39 energy 1.25777 [GeV] ... 3 children particles
    |- Line 1 PDG -211 energy 0.229023 [GeV] ... parent 0
    |- Line 2 PDG 11 energy 0.41918 [GeV] ... parent 0
    |- Line 3 PDG 111 energy 0.609571 [GeV] ... parent 0

  ---- Line 4 PDG 13 energy 0.895864 [GeV]

  ---- Line 5 PDG 13 energy 0.504029 [GeV]

  ---- Line 6 PDG 13 energy 0.994078 [GeV]

Hopefully this note helped you to learn how to run the ParticleBomb event generator. In the next section, we go over how to configure the generator so that we can dictate what kind of particles to be generated.