## Plugins

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, the `include/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):

1. A user creates a standalone plugin library, which implements derived classes from Pythia. This plugin library can be linked against external libraries.
2. At runtime, a `Pythia` object loads this plugin library.
3. 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 `MyPDF` class which derives from the Pythia `PDF` class. The plugin system will then return a shared pointer of type `PDF` which allows access to a `MyPDF` object.

This type of system has a number of advantages over the header interface style of plugins.

1. 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.
2. 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.
3. 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.
4. 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 is an option to either `set` the pointer, overwriting any previous pointer, or `add` the pointer to a list of pointers that will all be used. To specify whether the plugin should be set 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) or `add`. 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:

1. `PDF` set via `Pythia::setPDFPtr`
2. `LHAup` set via `Pythia::setLHAupPtr`
3. `DecayHandler` set via `Pythia::setDecayPtr`
4. `RndmEngine` set via `Pythia::setRndmEnginePtr`
5. `UserHooks` set via `Pythia::set/addUserHooksPtr`
6. `Merging` set via `Pythia::setMergingPtr`
7. `MergingHooks` set via `Pythia::setMergingHooksPtr`
8. `BeamShape` set via `Pythia::setBeamShapePtr`
9. `SigmaProcess` set via `Pythia::set/addSigmaPtr` with a null argument for the `PhaseSpace` pointer
10. `PhaseSpace` set via the second argument of `Pythia::set/addSigmaPtr`; the previous plugin must be the `SigmaProcess` which uses this phase-space generator
11. `ResonanceWidths` set via `Pythia::set/addResonancePtr`
12. `ShowerModel` set via `Pythia::setShowerModelPtr`
13. `HeavyIons` set via `Pythia::setHeavyIonsPtr`
14. `HIUserHooks` set via `Pythia::setHIHooks`

The second method for loading a plugin can be used directly in user code, with or without a `Pythia` 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.