Python Interface
- HepMC3 Output
- Batch Generation
- Event Visualization
- Simplified Interface
- Installation
- Examples
- Interface Generation
Python is a
powerful, high-level interpreted language that is widely used within
the particle physics community. It is particularly useful as an
interactive language that provides fast proto-typing of code. A Python
interface to PYTHIA is available. This interface is automatically
generated with Binder using the PyBind11
template library. Please note that this interface has not been
extensively tested and consequently issues may arise. If bugs are
found or additional features are required, as usual, please report
them to the PYTHIA authors. This interface is a significant departure
from the previous interface generated with SWIG, which does not
support C++11.
A complete interface ships with PYTHIA. However, in some cases this
interface might be more than needed by users and so a simplified
lightweight interface can also be generated. Note, not all PYTHIA
classes are available through this simplified interface. It is also
possible for users to automatically generate their own interface. This
is particularly useful if users modify the PYTHIA source code and need
to update the interface. When generating the interface there are three
options: the simplified interface, a full interface, and a user
defined interface. The process of generating these interfaces is
described in more detail below.
There are some idiosyncrasies when working with standard template
library classes. One of the notable examples are maps with keys as
strings. In many cases, it is useful to be able to access the settings
maps from the Settings class of a Pythia
instance. Rather than calling something like
getFlagMap(), getFlagMap("") must be called
so the interface knows how to map the keys. A full working example is
given below.
import pythia8
pythia = pythia8.Pythia("", False)
settings = pythia.settings
flags = settings.getFlagMap("")
for key, val in settings.getFlagMap("").items(): print(key)
The following points highlight some of the features of the interface.
- Documentation through the built-in help function in Python
provides the relevant mappings between the Python interface and the
C++ code. For documentation on the purpose of the code, see the user
HTML manual and Doxygen.
- Templated C++ types are returned as native Python types,
e.g. vectors are returned as lists, etc. Similarly, native Python
types can be passed as arguments and are converted to their equivalent
C++ templates.
- No difference is made between passing by reference or pointer;
methods in C++ which take a pointer as an argument in Python
simply take the object, e.g.
foo(Vec4*) and
foo(Vec4&) are the same in the Python interface.
- All operators defined in C++, e.g.
Vec4*double are
available. Note that reverse operators are not,
e.g. double*Vec4.
- Classes with defined
[] operators are iterable, using
standard Python iteration, e.g. for prt in
pythia.event.
- Classes with a
<< operator can be printed via
the built-in print function in Python. Note this means that a string
representation via str is also available for these
classes in Python.
- Derived classes in Python can be passed back to PYTHIA, and should
be available for all classes. See
main293.py for a direct
Python translation of the C++ main242.cc example which
uses a derived class from the UserHooks class to veto
events.
- Events can be generated in parallel using
PythiaParallel and providing an analysis function written
in Python. This is demonstrated in main292.py.
- Events can be generated in batch using Awkward arrays, see below
for more details as well as
main247.py and
main248.py.
- The constant
Pythia::info member is available as
Pythia::infoPython. Note, this creates a new instance of
the Info class, and so needs to be called each time the
information might be updated.
In general, most code using PYTHIA implemented through C++ is also
possible in the Python interface. There are a number of issues, such
as passing streams, which cannot be handled in the Python
interface. Additionally, protected members of classes are exposed as
fully public members in the Python interface.
HepMC3 Output
The PYTHIA Python interface does not include external dependencies,
and the additional helper classes available as headers in
include/Pythia8Plugins that have compile-time
dependencies are not available. This includes the
HepMC interfaces. However, since
the HepMC3 standard is so widely used to interace between particle
physics tools, a pure Python implementation of the
Pythia8ToFilteredHepMC3 class is available through the
Python interface.An example of how to use the tool is given in
examples/main299.py.
convert = pythia8.Pythia8ToFilteredHepMC3()
event = convert.hepmc3.GenEvent()
convert.fill_next_event(event, pythia = pythia)
Here, hepmc3 is the Python module providing the HepMC backend. This class uses either the
pyhepmc or
HepMC3
Python packages as this HepMC3 backend. The preferred backend can be
passed to the converter constructor.
import pyhepmc
convert = pythia8.Pythia8ToFilteredHepMC3(pyhepmc)
If no argument is passed to the constructor, an attempt is made to
first load the pyhepmc backend, followed by the
HepMC3 backend. The backend is then available via the
hepmc3 member of the converter.
The selector function can be set as follows.
# Keep all Pythia hard process particles and all necessary HepMC particles.
def selector(pyev, idx):
return (0 < pyev[idx].statusHepMC() < 5) or (
10 < pyev[idx].statusAbs() < 40)
convert = pythia8.Pythia8ToFilteredHepMC3()
convert.selector = selector
For full details on the converter, see the
Pythia8ToFilteredHepMC3 documentation.
There are currently a few limitations of the Python implementation of
this interface with respect to its C++ equivalent.
- Heavy ion information is not available via the
Info
class in the PYTHIA Python bindings, and so this information is not
included.
- The
weightContainerPtr object is not available from
the Info class and so different multi-weight
cross-sections are not available.
- If using the
HepMC3 package as a backend, the
weights container cannot be modified for a
GenEvent object, and so weights are stored as an event
attribute instead.
Batch Generation
Individually generating events and then accessing each particle by the Python
interface can slow things down considerably with respect to running directly
in C++. This is because the Python interface must translate the C++ PYTHIA
event record into Python as each particle is accessed by the user. Similarly,
using PythiaParallel where a Python function is passed back to
the Pythia C++ code to perform an analysis can result in a slow down. Another
option is to batch translate events to Python using the
Awkward array
library. In this way, the event translation is all done in a
single C++ call for a group of events, rather than on a per particle
basis. An example on how to generate events with the Awkward interface
are given in main297.py.
For this batch interface to work, your Python version must be greater
than 3.5 and the Awkward module must be available in
Python. This can be installed via pip or the Python package manager of
your choice.
python -m pip install awkward
It should then be possible to use the nextBatch method of
the Pythia class which is called with two arguments
nextBatch(nEvents, errorMode), where the second argument is
optional. In the following code, 100 events are generated and returned via the
Awkward array named events.
pythia = pythia.Pythia()
pythia.readString("HardProcess:all = on")
pythia.init()
events = pythia.nextBatch(100)
For a single Pythia instance, failed events can be treated in
different ways using the optional errorMode argument that
can be passed to nextBatch.
"none" - events that fail to generate are included
in the Awkward array as None objects.
"skip" - this is the default behavior, and is similar
to what PythiaParallel also does. Events that fail to
generate are skipped, and events are generated until the requested
nEvents is reached.
"fail" - if an event fails to generate, then an
exception is thrown.
fac - here, fac is a real number greater
than 1. This is the same as "skip" but event
generation will terminate after fac*nEvents attempts have
been made to generate an event and an exception will be thrown.
Some examples are given in main298.py.
There are two other features for batch generation. First,
nextBatch can also be called from a
PythiaParallel instance, but without the optional
errorMode as PythiaParallel handles failed
events internally. Second, the momentum and production vertex
four-vectors can automatically be translated into a four-vector class
using the
scikit-hep/vector library.
python -m pip install vector
Translating automatically to this library can then be accomplished
with the following code.
import vector
vector.register_awkward()
This allows for analyses to be performed on the event record with
slicing. Some examples can be found in the Awkward array documentation, as well as in
main297.py.
Limited event-level information is available through the batch interface.
The names for this information can be accessed as follows.
events.info.fields
The naming scheme between these fields in the Info class
is intended to be one-to-one when possible. The following fields are
available: id1, id2, x1,
x2, pdf1, pdf2,
alphaS, alphaEM, Q2Fac,
Q2Ren, mHat, sHat,
tHat, uHat, pT2Hat, and
weights. The weights are accessed via the
Info::numberOfWeights and
Info::weightValueByIndex methods. This includes weights
from all sources, including atomic weights. The name for each weight
can be accessed via the Info::weightNameByIndex method,
which should remain the same across all events for a single batch
call.
Some older C++ compiler versions are not compatible with the C++11
templating that is required for the Awkward array bindings. However,
it is possible to generate the Python interface without the Awkward
array bindings by passing the --no-batch flag to the
generate script. See below for more details on how to
generate the Python interface.
Event Visualization
The Vistas class of the Python interface provides an interactive
tool to visualize Pythia events using the Hep Software Foundation (HSF)
Phoenix event
display viewer. The main300.py example demonstrates how to
use this visualization class. Once an event has been generated,
the following will then launch a web-browser display of the event.
viewer = pythia8.Vistas(pythia)
viewer.display()
An interactive Jupyter tutorial on how to explore these visualized events is
available through the
MCgen repository.
Simplified Interface
An attempt has been made to provide the everyday functionality of
PYTHIA through the simplified interface. However, if classes or
methods appear to be missing, please contact the PYTHIA authors;
additional functionality can be included upon request. The following
list highlights the available classes and methods in this interface,
roughly categorized by function. Note that help(pythia8)
will return all the available classes and methods in the interface.
- top level:
Pythia
- event access:
Event, Particle,
Vec4, RotBstMatrix
- particle data:
ParticleData,
ParticleDataEntry, DecayChannel
- settings and information:
Info, HIInfo,
Settings, Flag, Mode,
Parm, Word, FVec,
MVec, PVec, WVec
- user interface pointers:
Rndm, PDF,
DecayHandler, RndmEngine,
UserHooks, MergingHooks,
BeamShape, SigmaProcess,
TimeShower, SpaceShower,
HeavyIons, PartonVertex
- analysis tools:
Hist, HistPlot,
CellJet, ClusterJet, SlowJet,
SlowJetHook, Sphericity,
Thrust
- kinematic functions:
m, m2,
dot3, cross3, cross4,
theta, costheta, phi,
cosphi, RRapPhi, REtaPhi
Installation
Below, details are given on how to build the Python interface from the
Pythia source code. However, pre-built wheels for the package are
available through the
pythia8mc
package on the Python Package Index (PyPi). To install use the
following.
pip install pythia8mc
Note, when using the PyPi package, the module name is
pythia8mc and not the normal pythia8.
To install the Python interface, the Python system header
Python.h must be available. By default when configuring
using --with-python the system python-config
script will be used to determine the location of
Python.h. In some cases, users might wish to use a
different version of Python, and so --with-python-config
can be used to set the Python configuration script used to pick up
paths. Alternatively, the directory containing Python.h
can be set manually with the option
--with-python-include. Some example configurations could be
as follows,
./configure --with-python
./configure --with-python-config=python3-config
./configure --with-python-include=/usr/include/python2.7
where the Python configuration script and path must be changed
accordingly for the local system.
After configuring the Python interface for PYTHIA to be built and
running make as usual, the following files should be
generated in the directory lib.
pythia8.so: compiled Python module.
libpythia8.[so,dylib]: the standard shared PYTHIA
library.
To ensure that the pythia8.so module is available to
Python, the system variable PYTHONPATH should be set
similar to
export PYTHONPATH=$(PREFIX_LIB):$PYTHONPATH
where PREFIX_LIB is the directory lib which
contains pythia8.so. Generally, the library paths should
be set correctly, but it also may be necessary to set
export LD_LIBRARY_PATH=$(PREFIX_LIB):$LD_LIBRARY_PATH
where DYLD should be substituted for LD in
OS X. Alternatively, it is also possible to define the Python path
from within Python, as is done within the provided examples. Note that
the Python module is always compiled as pythia8.so, even
in OS X. This is because older versions of Python in OS X do not
correctly recognize modules ending with the dylib suffix.
Examples
To use the Python interface for PYTHIA, start Python
and import pythia8. The provided examples can be run
by python mainNNN.py where NNN is the number
of the example.
Interface Generation
A script for automatically generating the Python interface,
generate, is available in plugins/python/
and should be run from this directory. This script requires that the
user has Docker installed. A small Docker image of roughly 80 MB will
be pulled to run the necessary generation code. There are a number of
command line arguments which can be passed.
--help prints the help message for the script.
--part generates the simplified interface. When
generate is run without arguments, then this is the
default behaviour. Note that this requires running the interface
generation twice. The first time the required classes are interfaced,
the second time additional classes are removed.
--full generates the full interface.
--no-batch exclude the Awkward-array batch interface.
--user=FILE generates a user defined interface using
the Binder configuration given by FILE.
--debug can be specified with any of the options
above and stops the temporary files used in generation from being
removed.
Whenever PYTHIA headers are modified, the Python interface is
invalidated, and so this automatic generation is particularly useful
in such a situation. An example of generating the full Python
interface is as follows.
cd plugins/python
./generate --full