In this tutorial, you will learn how to create your own reaction plugin in a GitHub repository.
Author
Eric Hartmann
Creating a GitHub repository
By creating a GitHub repository, you have version control for your plugin and can share it with others. To set it up, follow these instructions.
Adding the functionality of the plugin
Main code
A reaction plugin has to be a derived class from the ReactionPlugin base class. Such a class has the attributes name, runmng and config and the method get_recipe_collection, which takes a TaskFiles object as argument and returns a RecipeCollection.
The name is a simple string and may be useful for logging. runmng is the central RunManager of a kimmdy run and has plenty of useful attributes for your plugin, especially the system Topology, which can be accessed via self.runmg.top. config contains the reaction plugin configuration as specified in the kimmdy configuration file (typically named kimmdy.yml). A RecipeCollection contains Recipes with predefined RecipeSteps that can be used to define the modification to the system for the reaction. A Recipe also contains the rates of the specified reaction and the timespans during which the corresponding rates are valid. An example plugin can be seen below.
Plugin main code (reaction.py)
from kimmdy.recipe import ( Bind, Recipe, RecipeCollection,)from kimmdy.plugins import ReactionPluginfrom kimmdy.tasks import TaskFilesfrom kimmdy.utils import ( get_atomnrs_from_plumedid,)import loggingfrom kimmdy.parsing import ( read_plumed, read_distances_dat,)# start the name of your logger with kimmdy.<plugin name># such that it ends up in the kimmdy log filelogger = logging.getLogger("kimmdy.hydrolysis")class BindReaction(ReactionPlugin):"""Reaction to bind two particles if they are in proximity """def get_recipe_collection(self, files: TaskFiles): logger = files.logger logger.debug("Getting recipe for reaction: Bind")# get cutoff distance from config, unit is [nm] cutoff =self.config.distance# Initialization of objects from files distances = read_distances_dat(files.input["plumed_out"]) plumed = read_plumed(files.input["plumed"]) recipes = []# check distances file for values lower than the cutofffor plumedid, dists in distances.items():if plumedid =="time":continue# checks only last frameif dists[-1] < cutoff:# get atomnrs from plumedid atomnrs = get_atomnrs_from_plumedid(plumedid, plumed) recipes.append( Recipe( recipe_steps=[ Bind(atom_id_1=atomnrs[0], atom_id_2=atomnrs[1]), ], rates=[1], timespans=[(distances["time"][0], distances["time"][-1])], ) )return RecipeCollection(recipes)
Configuration file schema
A plugin defines which variables it needs in a schema. The schema can contain default values and types of these variables. For a Kimmdy run, reaction plugin variables are defined in the configuration file (kimmdy.yml). An example schema can be seen below.
Plugin schema (kimmdy-yaml-schema.json)
kimmdy-yaml-schema.json
{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","$id":"bind-config","description":"Settings for bind reactions","additionalProperties":false,"properties":{"distance":{"description":"Cutoff distance for two particles to bind [nm]","type":"float","pytype":"float"},"kmc":{"description":"KMC algorithm for this reaction.","type":"string","pytype":"str","enum":["rfkmc","frm","extrande"],"default":"rfkmc"}},"required":["distance"]}
Making a python package
It is necessary to make the plugin a python package to interface with Kimmdy. For this, package setup configuration files are necessary, for example setup.py and setup.cfg. In setup.cfg dependencies can be specified, which will be installed alongside the plugin. The interface with kimmdy is specified in the [options.entry_points] section. This section needs to refer to the class we created in the plugin main code and assign it to kimmdy.reaction_plugins, i.e. kimmdy.reaction_plugins = bind = <path>.<to>.<main file>:<ClassName>. Also, the directory containing the source code (typically src) is defined in [options.packages.find]. An example for setup.py and setup.cfg can be found below.
setup.py
from setuptools import setupsetup()
setup.cfg
setup.cfg
[metadata]name = kimmdy-reactionsversion =0.1license = GPL-3.0 description = Reaction template for KIMMDYlong_description = file: README.mdauthor = Eric Hartmannauthor_email = eric.Hartmann@h-its.orgclassifiers= Programming Language :: Python :: 3 License :: OSI Approved :: MIT License Operating System :: OS Independent[options]packages = find:package_dir ==srcinclude_package_data =Trueinstall_requires = MDAnalysispython_requires = >= 3.9[options.packages.find]where=src[options.entry_points]kimmdy.reaction_plugins = bind = bind.reaction:BindReaction
The main code and configuration schema file should then be moved to the specified source directory in a directory that has the name of the reaction plugin, i.e. src/<plugin name>/.
Tip
By adding the kimmdy tag on GitHub you can make your plugin discoverable by other users. It will show up in this list
Improving code quality and reproducibility
Adding tests will help in ensuring the plugin is working as expected. An example would help users to understand what your plugin does.