Plugins
 
  - Loading a Plugin
- Plugin Library Paths
- Writing a Plugin Library
Pythia is designed as a standalone package, with no external 
dependencies.  However, there are many use cases for interfacing 
external packages with Pythia. To that end, theinclude/Pythia8Plugins directory provides a number of 
header interfaces, which are then demonstrated in 
examples. However, this method of including external 
dependencies in Pythia is not always sufficient, and so a plugin 
system is also available. The system works as follows (more details 
are given later): 
 
- A user creates a standalone plugin library, which implements 
derived classes from Pythia. This plugin library can be linked against 
external libraries.
- At runtime, a Pythiaobject loads this plugin 
library.
- Any new object requested by the user from this plugin library is 
created and returned as a shared pointer. The shared pointer is the 
same type as the Pythia base class of the plugin object. For example, 
consider a plugin library that implements a new MyPDFclass which derives from the PythiaPDFclass. The plugin 
system will then return a shared pointer of typePDFwhich allows access to aMyPDFobject.
This type of system has a number of advantages over the header interface 
style of plugins. 
- The external dependencies only need to be handled once. For 
example, consider using HepMC to write out event files. With the 
plugin system, we only need to link the standalone plugin library with 
HepMC at compile time. Then, any main program we might build after 
this does not need to be linked against HepMC (headers or libraries), 
but can still write HepMC output to file.
- In some cases, we might want to replace core functionality in 
Pythia with code that requires external dependencies. A good example 
of this is LHAPDF, which can be used to replace the internal Pythia 
PDF sets. Here, we can allow LHAPDF sets to be used seamlessly within 
Pythia without introducing any external dependencies to the core 
Pythia code.
- We oftentimes want to use libraries that provide duplicate 
symbols. This is happens when linking against FORTRAN libraries with 
standard common blocks, or libraries that were generated using some 
automated tool. An example of this is the matrix element corrections 
provided via MG5 for the parton shower. Here, MG5 builds libraries 
with identical symbol names and so we cannot link against multiple 
versions of these libraries. The plugin system allows us to not only 
choose which MG5 matrix element correction library we load at runtime, 
but also load multiple libraries without causing symbol 
conflicts.
- It is now possible to create a Pythia executable, where all 
interactions by the user are through command files, and no code needs 
to be compiled.
Within Pythia, the plugin library is already used to provide access to 
external libraries such as LHAPDF and MG5 matrix element corrections 
in the parton shower.Loading a Plugin
 
 
There are two ways to load plugins within Pythia code. The first is to 
provide a list of plugins to Pythia via the Init:plugins 
option (see Main Program Settings 
for the definition of this option). To give an example, consider 
writing a UserHooks class called MyUserHooks 
and compiling this in the plugin library libMyPlugins.so. To 
automatically load this user hook and pass it to your Pythia object, the 
following command should be given to Pythia. 
 
 
 
Init:plugins = {libMyPlugins.so::MyUserHooks} 
 
 
 
Then, when pythia.init() is called, a MyUserHooks 
object will be automatically created and set as the UserHooks 
object for the Pythia object via the method 
pythia.setUserHooksPtr. For most plugin object classes of 
generic type BaseClass, the relevant pointer will be set 
via the corresponding pythia.setBaseClassPtr method. For 
some class types, there are options to either set the 
pointer, overwriting any previous pointer, or add or 
insert the pointer to a list of pointers that will all be 
used. To specify whether the plugin should be set, inserted, or added, 
a third optional keyword can be specified, 
 
 
 
Init:plugins = {libMyPlugins.so::MyUserHooks::set} 
 
 
 
where this third keyword can be either set (the default), 
add, or insert(i). Here, i 
specifies the index in the list of pointers where the new pointer 
should be inserted. In this example, if there was a previous 
UserHooks pointer, it would be replaced by a new 
MyUserHooks pointer. 
 
 
The treatment of this third keyword is different for PDF plugins, 
where it specifies the beam type (and the PDF pointer is always set, 
rather than added). For example, 
 
 
 
Init:plugins = {libMyPlugins.so::MyPDF1::A, libMyPlugins.so::MyPDF2::B} 
 
 
 
sets MyPDF1 for beam A, while 
MyPDF2 is set for beam B. This beam type can be taken from the 
list of arguments to the 
Pythia::setPDFPtr method in 
Program Flow, with the 
pdf prefix and Ptr suffix stripped from the 
argument name, for example pdfPomAPtr becomes 
PomA. 
 
If there are new settings which are defined in the 
libMyPlugins.so library, these settings are registered before the 
MyUserHooks object is created. In this way, it is possible to 
pass settings to the MyUserHooks object from a command file. 
This would be done as, 
 
 
 
Init:plugins = {libMyPlugins.so::MyUserHooks::set::plugin.cmnd} 
 
 
 
where plugin.cmnd is a standard command file for 
Pythia. It is also possible to use the subrun feature of the Pythia 
command files. 
 
 
 
Init:plugins = {libMyPlugins.so::MyUserHooks::set::plugin.cmnd::2} 
 
 
 
This command tells Pythia to load the specific commands for subrun two 
from the plugin.cmnd file. 
 
 
The plugin functionality is available for a number of Pythia base classes 
which can be passed as external pointers to a Pythia object. These include: 
 
- PDFset via- Pythia::setPDFPtr
- LHAupset via- Pythia::setLHAupPtr
- DecayHandlerset via- Pythia::setDecayPtr
- RndmEngineset via- Pythia::setRndmEnginePtr
- UserHooksset via- Pythia::set/add/insertUserHooksPtr
- Mergingset via- Pythia::setMergingPtr
- MergingHooksset via- Pythia::setMergingHooksPtr
- BeamShapeset via- Pythia::setBeamShapePtr
- SigmaProcessset via- Pythia::set/add/insertSigmaPtrwith a null argument for the- PhaseSpacepointer
- PhaseSpaceset via the second argument of- Pythia::set/add/insertSigmaPtr; the previous plugin must be the- SigmaProcesswhich uses this phase-space generator
- ResonanceWidthsset via- Pythia::set/add/insertResonancePtr
- ShowerModelset via- Pythia::setShowerModelPtr
- FragmentationModelset via- Pythia::set/add/insertFragmentationPtr
- HeavyIonsset via- Pythia::setHeavyIonsPtr
- HIUserHooksset via- Pythia::setHIHooks
The second method for loading a plugin can be used directly in user 
code, with or without aPythia instance, using a number of 
helper functions. The simplest is as follows. 
 
 shared_ptr<BaseClass> make_plugin<BaseClass>( string libName, string className)   
creates a shared pointer of type BaseClass from the plugin 
library libName and the plugin class className. 
argument libName, className   :  
the plugin library name, typically of the form lib*.so, and 
the plugin class name to load. 
   
   
 
 shared_ptr<BaseClass> make_plugin<BaseClass>( string libName, string className, Pythia* pythiaPtr)   
same as above, but with an optional Pythia pointer that 
is passed to the constructor of the plugin class. 
argument pythiaPtr   :  
pointer to a Pythia instance. This pointer is 
passed to the constructor of the plugin object, and can be used by 
that object. 
   
   
 
 shared_ptr<BaseClass> make_plugin<BaseClass>( string libName, string className, Pythia* pythiaPtr, Settings* settingsPtr, Logger* loggerPtr)   
same as above, but with an optional Settings and 
Logger pointer. 
argument settingsPtr   :  
optional pointer to a Settings instance. This pointer is 
passed to the plugin object constructor. If a valid 
pythiaPtr is provided, but no settingsPtr, 
then the settingsPtr is taken from the 
pythiaPtr object. 
   
argument loggerPtr   :  
optional pointer to a Logger instance, similar to 
settingsPtr. 
   
   
 
 
Plugin classes are always required to take a Pythia, 
Settings, and Logger pointer in their 
constructors. However, none of these pointers is required to be 
valid. If a plugin class requires one of these pointers to be valid, 
it is possible to specify this when creating the plugin library (see below). 
A plugin library may optionally register new settings in a 
Settings object passed to the plugin library. This allows 
the settings to pass a wide range of arguments to a plugin object. The 
idea is as follows. First, the plugin library settings are registered 
with a Settings object. Then, the new settings from the 
plugin in this Settings object can be modified by the 
user. Finally, the plugin object is created, with the 
Settings object passed to the constructor so that it can 
access these specialised settings. The following method registers the 
settings from a plugin library. 
 
 bool Settings::registerPluginLibrary(string libName, string startFile)   
register any settings provided in a plugin library. Typically, this 
method is not needed by the user. 
argument libName   :  
the plugin library name, typically of the form lib*.so. 
   
argument startFile  (default = "") :  
read in the settings from all the files listed in this file, and 
assumed to be located in the same subdirectory. 
   
   
 
 
The following methods then combine these three steps together into a 
single method. 
 
 shared_ptr<BaseClass> make_plugin<BaseClass>( string libName, string className, Pythia* pythiaPtr, vector<string>& cmnds)   
register the plugin settings with the Pythia instance and 
read the commands of cmnds into the 
pythiaPtr. 
argument cmnds   :  
vector of commands to read into Pythia before loading the plugin, 
but after registering the plugin settings. 
   
   
 
 shared_ptr<BaseClass> make_plugin<BaseClass>( string libName, string className, Pythia* pythiaPtr, string fileName, int subrun = SUBRUNDEFAULT)   
register the plugin settings with the Pythia instance and 
read the commands of the file fileName with optional 
subrun. 
argument fileName   :  
name of the file to read into the Pythia object. 
   
argument subrun   :  
optionally specify the commands from the subrun to use. 
   
   
 
 
The following demonstrates the simplest construction. 
 
 
 
PDFPtr pdf = make_plugin<PDF>("libMyPlugins.so", "MyPDF"); 
 
 
 
To register settings and pass these to the plugin, the following could 
be done. 
 
 
 
Settings settings; 
settings.registerPluginLibrary("libMyPlugins.so"); 
// Modify the settings here. 
PDFPtr pdf = make_plugin<PDF>("libMyPlugins.so", "MyPDF", nullptr, 
  &settings, nullptr); 
 
 
 
Alternatively, if working with a Pythia object, the 
multistep functions can be used. 
 
 
 
Pythia pythia; 
vector<string> cmnds; 
 
// Fill the command string. 
PDFPtr pdf1 = make_plugin<PDF>( 
  "libMyPlugins.so", "MyPDF", &pythia, cmnds); 
 
// Alternatively, read the commands from a file. 
PDFPtr pdf2 = make_plugin<PDF>( 
  "libMyPlugins.so", "MyPDF", &pythia, "plugin.cmnd"); 
 
 
 
Note that in this example, two unique objects from the plugin library 
are created. 
 
 
Plugin Library Paths
 
 
When libName is specified for any of the settings, 
methods, or functions above, it can be passed as either just the 
library name (e.g. libMyPlugins.so), the library name 
with a relative path (e.g. ./libMyPlugins.so), or the 
library name with an absolute path 
(e.g. /plugins/libMyPlugins.so). When the path is 
specified (i.e. the latter two options) then that file must exist, as 
the plugin library. When no path is specified then the same mechanism 
used for resolving library paths at runtime is used. This means that 
both the runtime search path specified to the linker at compile time 
will be searched (i.e. the RPATH mechanism using 
-Wl,rpath), as well as the path specified via the 
environment variable LD_LIBRARY_PATH. 
 
 
Writing a Plugin Library
 
 
A plugin library consists of two parts: user defined classes 
inheriting from any Pythia class, and a function which registers 
settings. Arbitrary classes can be defined by the user, as long as they 
derive from a Pythia class. Additionally, the constructor for the class 
must always take the following form: 
 
 
 
MyClass(Pythia* pythiaPtr, Settings* settingsPtr, Logger* loggerPtr) 
 
 
 
As discussed above, the validity of these three pointers is not 
guaranteed, and so the class must accordingly check their validity if 
needed. After a class is defined, it must then be made externally 
available so that it can be loaded from the plugin library. It is 
possible when making the class externally available to specify that 
certain pointers are required. This is done with the following macro. 
 
 
 
PYTHIA8_PLUGIN_CLASS(BaseClass, MyClass, RequirePythia, RequireSettings, 
  RequireLogger) 
 
 
 
Here, BaseClass is whatever class the user wishes the 
MyClass> to be loaded as using the 
make_plugin functions. The argument 
ReqirePythia should be a boolean, and specifies whether 
the Pythia pointer is required by the plugin 
class. Similarly, the RequireSettings and 
RequireLogger arguments must also be booleans specifying 
whether the Settings and Logger pointers 
must be valid or not. Note, this macro can only be used once per 
class, and consequently can only be returned as a single base class. 
 
The settings can be registered by a function that follows the 
following form: 
 
 
 
void registerMySettings(Settings* settingsPtr) 
 
 
 
which is then made externally available by the following macro. 
 
 
 
PYTHIA8_PLUGIN_SETTINGS(registerMySettings) 
 
 
 
This macro can only be used once in a plugin library, and so all 
settings must be registered by a single function. Registering settings 
in a plugin library is optional. 
 
Users may also provide XML files, similar to the Pythia XML files, to 
define both setttings and documentation. This is done with the macro, 
 
 
 
PYTHIA8_PLUGIN_XML("pluginLibraryName/xmldoc/startFile.xml") 
 
 
 
which takes a string as an argument. The string should provide the 
relative path to the XML index for the library, similar to 
Pythia8/xmldoc/Index.xml for Pythia. Here, 
pluginLibraryName should be the name of the plugin 
library, and startFile.xml is the index XML file which 
includes all other XML files needed for the plugin library. When a 
plugin library is loaded, an attempt will first be made to find the 
starting XML file on the path specified by the environment variable 
PYTHIA8CONTRIB, so here the full path would be 
PYTHIA8CONTRIB/pluginLibraryName/xmldoc/startFile.xml. If 
this path is not valid, then the path PYTHIA8DATA/../../ 
will be tried, followed by the provided path itself. 
 
Finally, it is required to define the versions of Pythia that the plugin 
library is compatible with. This is done with the macro: 
 
 
 
PYTHIA8_PLUGIN_VERSIONS(8310, 8311) 
 
 
 
where a comma separated list of integer Pythia versions is passed as 
an argument. This list can be variable length, including length 
one. In this example, the plugin library is compatible with versions 
8.309 and 8.310. When a user loads a plugin 
library the versions from this list are checked against the current 
Pythia version to test compatibility. If the current Pythia version is 
not found in the list then an error is given when loading the 
library. Additionally, the version of Pythia that the plugin library 
was compiled against is checked.  If the versions between Pythia and 
the plugin library do not match a warning is given. This is because in 
principle the application binary interface between Pythia versions is 
expected to be stable. It is possible that a plugin library compiled 
against a different version of Pythia than the version loading the 
library might still function correctly. However, this behaviour may be 
changed to an error in the future.