Skip to content

Commit

Permalink
feat: link nrexcl of reactive moleculetype to toplevel topology (#451)
Browse files Browse the repository at this point in the history
and other workflow patches 

fix: properly compare to empty dicts

refactor(config): rename recursive_dict argument to opts

to reflect its function for a user, not the mode of operation

feat: add xtc option to config

refactor: format json

feat: always setup tasks on init of RunManager

feat: configure logger from init of Config

(since this the only time we do it is after initializing the config,
using the config)

refactor(runmanager): rename step to task_name for consistency

docs: update quarto version

fix: resolve all non-relative paths in config relative to config.cwd

refactor(runmanager): rename crr_tasks to priority_tasks

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
jmbuhr and github-actions[bot] committed Jul 11, 2024
1 parent 4199d72 commit b100117
Show file tree
Hide file tree
Showing 85 changed files with 12,686 additions and 4,264 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ jobs:
python-version: "3.10"
- uses: quarto-dev/quarto-actions/setup@v2
with:
version: "1.4.176"
version: "1.5.53"
- name: Install dependencies
run: |
python -m pip install .[dev]
- name: Build docs
run: |
make setup-docs
make docs
- name: Commit rendered docs
uses: stefanzweifel/git-auto-commit-action@v5
with:
Expand Down
12 changes: 0 additions & 12 deletions .github/workflows/lint.yml~

This file was deleted.

1,930 changes: 1,930 additions & 0 deletions CHANGELOG.html

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"hash": "8b7d5e6853eed471e2b02d436272c182",
"hash": "c37867e44d2001357c31925f8f4884e3",
"result": {
"engine": "jupyter",
"markdown": "---\ntitle: Write a Reaction Plugin\ndescription: In this tutorial, you will learn how to create your own reaction plugin in a GitHub repository.\nexecute:\n eval: false\ncode-fold: true\nauthor: Eric Hartmann\ncategories:\n - developer\n---\n\n## Creating a GitHub repository\n\nBy creating a GitHub repository, you have version control for your plugin and can share it with others. To set it up, follow [these instructions](https://docs.github.com/en/get-started/quickstart/create-a-repo).\n\n## Adding the functionality of the plugin\n\n### Main code\n\nA 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`. \n\nThe `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 `Recipe`s with predefined `RecipeStep`s 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.\n\n::: {#2641ff7c .cell execution_count=1}\n``` {.python .cell-code code-fold=\"true\" code-summary=\"Plugin main code (reaction.py)\"}\nfrom kimmdy.recipe import (\n Bind,\n Recipe,\n RecipeCollection,\n)\nfrom kimmdy.plugins import ReactionPlugin\nfrom kimmdy.tasks import TaskFiles\nfrom kimmdy.utils import (\n get_atomnrs_from_plumedid,\n)\nfrom kimmdy.parsing import (\n read_plumed,\n read_distances_dat,\n)\n\n\nclass BindReaction(ReactionPlugin):\n \"\"\"Reaction to bind two particles if they are in proximity\n \"\"\"\n\n def get_recipe_collection(self, files: TaskFiles):\n logger = files.logger\n logger.debug(\"Getting recipe for reaction: Bind\")\n\n # get cutoff distance from config, unit is [nm]\n cutoff = self.config.distance\n\n # Initialization of objects from files\n distances = read_distances_dat(files.input[\"plumed_out\"])\n plumed = read_plumed(files.input[\"plumed\"])\n\n recipes = []\n # check distances file for values lower than the cutoff\n for plumedid, dists in distances.items():\n if plumedid == \"time\":\n continue\n # checks only last frame\n if dists[-1] < cutoff:\n # get atomnrs from plumedid \n atomnrs = get_atomnrs_from_plumedid(plumedid, plumed)\n recipes.append(\n Recipe(\n recipe_steps=[\n Bind(atom_id_1=atomnrs[0], atom_id_2=atomnrs[1]),\n ],\n rates=[1],\n timespans=[(distances[\"time\"][0], distances[\"time\"][-1])],\n )\n )\n\n return RecipeCollection(recipes)\n```\n:::\n\n\n### Configuration file schema\n\nA 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.\n\n\n<details>\n <summary>Plugin schema (kimmdy-yaml-schema.json)</summary>\n\n\n```{.json filename='kimmdy-yaml-schema.json'}\n{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"type\": \"object\",\n \"$id\": \"bind-config\",\n \"description\": \"Settings for bind reactions\",\n \"additionalProperties\": false,\n \"properties\": {\n \"distance\": {\n \"description\": \"Cutoff distance for two particles to bind [nm]\",\n \"type\": \"float\",\n \"pytype\": \"float\"\n },\n \"kmc\": {\n \"description\": \"KMC algorithm for this reaction.\",\n \"type\": \"string\",\n \"pytype\": \"str\",\n \"enum\": [\"rfkmc\", \"frm\", \"extrande\"],\n \"default\": \"rfkmc\"\n }\n },\n \"required\": [\"distance\"]\n}\n```\n\n</details>\n\n## Making a python package\n\nIt 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.\n\n::: {#e96ba74b .cell execution_count=2}\n``` {.python .cell-code code-fold=\"true\" code-summary=\"setup.py\"}\nfrom setuptools import setup\n\nsetup()\n```\n:::\n\n\n<details>\n <summary>setup.cfg</summary>\n\n```{.ini filename='setup.cfg'}\n[metadata]\nname = kimmdy-reactions\nversion = 0.1\nlicense = GPL-3.0 \ndescription = Reaction template for KIMMDY\nlong_description = file: README.md\nauthor = Eric Hartmann\nauthor_email = eric.Hartmann@h-its.org\nclassifiers=\n Programming Language :: Python :: 3\n License :: OSI Approved :: MIT License\n Operating System :: OS Independent\n\n[options]\npackages = find:\npackage_dir =\n =src\ninclude_package_data = True\ninstall_requires =\n MDAnalysis\n\npython_requires = >= 3.9\n\n[options.packages.find]\nwhere=src\n\n[options.entry_points]\nkimmdy.reaction_plugins =\n bind = bind.reaction:BindReaction\n```\n\n</details>\n\nThe 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>/`. \n\n:::callout-tip\nBy adding the `kimmdy` tag on GitHub you can make your plugin discoverable by other users.\nIt will show up in [this list](https://github.com/topics/kimmdy)\n:::\n\n## Improving code quality and reproducibility\n\nAdding tests will help in ensuring the plugin is working as expected. An example would help users to understand what your plugin does.\n\n",
"markdown": "---\ntitle: Write a Reaction Plugin\ndescription: In this tutorial, you will learn how to create your own reaction plugin in a GitHub repository.\nexecute:\n eval: false\ncode-fold: true\nauthor: Eric Hartmann\ncategories:\n - developer\n---\n\n\n\n\n## Creating a GitHub repository\n\nBy creating a GitHub repository, you have version control for your plugin and can share it with others. To set it up, follow [these instructions](https://docs.github.com/en/get-started/quickstart/create-a-repo).\n\n## Adding the functionality of the plugin\n\n### Main code\n\nA 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`. \n\nThe `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 `Recipe`s with predefined `RecipeStep`s 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.\n\n::: {#71789652 .cell execution_count=1}\n``` {.python .cell-code code-fold=\"true\" code-summary=\"Plugin main code (reaction.py)\"}\nfrom kimmdy.recipe import (\n Bind,\n Recipe,\n RecipeCollection,\n)\nfrom kimmdy.plugins import ReactionPlugin\nfrom kimmdy.tasks import TaskFiles\nfrom kimmdy.utils import (\n get_atomnrs_from_plumedid,\n)\nimport logging\nfrom kimmdy.parsing import (\n read_plumed,\n read_distances_dat,\n)\n\n# start the name of your logger with kimmdy.<plugin name>\n# such that it ends up in the kimmdy log file\nlogger = logging.getLogger(\"kimmdy.hydrolysis\")\n\nclass BindReaction(ReactionPlugin):\n \"\"\"Reaction to bind two particles if they are in proximity\n \"\"\"\n\n def get_recipe_collection(self, files: TaskFiles):\n logger = files.logger\n logger.debug(\"Getting recipe for reaction: Bind\")\n\n # get cutoff distance from config, unit is [nm]\n cutoff = self.config.distance\n\n # Initialization of objects from files\n distances = read_distances_dat(files.input[\"plumed_out\"])\n plumed = read_plumed(files.input[\"plumed\"])\n\n recipes = []\n # check distances file for values lower than the cutoff\n for plumedid, dists in distances.items():\n if plumedid == \"time\":\n continue\n # checks only last frame\n if dists[-1] < cutoff:\n # get atomnrs from plumedid \n atomnrs = get_atomnrs_from_plumedid(plumedid, plumed)\n recipes.append(\n Recipe(\n recipe_steps=[\n Bind(atom_id_1=atomnrs[0], atom_id_2=atomnrs[1]),\n ],\n rates=[1],\n timespans=[(distances[\"time\"][0], distances[\"time\"][-1])],\n )\n )\n\n return RecipeCollection(recipes)\n```\n:::\n\n\n### Configuration file schema\n\nA 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.\n\n\n<details>\n <summary>Plugin schema (kimmdy-yaml-schema.json)</summary>\n\n\n```{.json filename='kimmdy-yaml-schema.json'}\n{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"type\": \"object\",\n \"$id\": \"bind-config\",\n \"description\": \"Settings for bind reactions\",\n \"additionalProperties\": false,\n \"properties\": {\n \"distance\": {\n \"description\": \"Cutoff distance for two particles to bind [nm]\",\n \"type\": \"float\",\n \"pytype\": \"float\"\n },\n \"kmc\": {\n \"description\": \"KMC algorithm for this reaction.\",\n \"type\": \"string\",\n \"pytype\": \"str\",\n \"enum\": [\"rfkmc\", \"frm\", \"extrande\"],\n \"default\": \"rfkmc\"\n }\n },\n \"required\": [\"distance\"]\n}\n```\n\n</details>\n\n## Making a python package\n\nIt 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.\n\n::: {#9dceb279 .cell execution_count=2}\n``` {.python .cell-code code-fold=\"true\" code-summary=\"setup.py\"}\nfrom setuptools import setup\n\nsetup()\n```\n:::\n\n\n<details>\n <summary>setup.cfg</summary>\n\n```{.ini filename='setup.cfg'}\n[metadata]\nname = kimmdy-reactions\nversion = 0.1\nlicense = GPL-3.0 \ndescription = Reaction template for KIMMDY\nlong_description = file: README.md\nauthor = Eric Hartmann\nauthor_email = eric.Hartmann@h-its.org\nclassifiers=\n Programming Language :: Python :: 3\n License :: OSI Approved :: MIT License\n Operating System :: OS Independent\n\n[options]\npackages = find:\npackage_dir =\n =src\ninclude_package_data = True\ninstall_requires =\n MDAnalysis\n\npython_requires = >= 3.9\n\n[options.packages.find]\nwhere=src\n\n[options.entry_points]\nkimmdy.reaction_plugins =\n bind = bind.reaction:BindReaction\n```\n\n</details>\n\nThe 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>/`. \n\n:::callout-tip\nBy adding the `kimmdy` tag on GitHub you can make your plugin discoverable by other users.\nIt will show up in [this list](https://github.com/topics/kimmdy)\n:::\n\n## Improving code quality and reproducibility\n\nAdding tests will help in ensuring the plugin is working as expected. An example would help users to understand what your plugin does.\n\n",
"supporting": [
"write-plugin_files"
"write-plugin_files/figure-html"
],
"filters": [],
"includes": {}
Expand Down
2 changes: 1 addition & 1 deletion _freeze/site_libs/quarto-listing/list.min.js

Large diffs are not rendered by default.

13 changes: 0 additions & 13 deletions _reference/cmd.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,10 @@ Other entry points such as `kimmdy-analysis` also live here.

| Name | Description |
| --- | --- |
| [configure_logger](#kimmdy.cmd.configure_logger) | Configure logging. |
| [entry_point_kimmdy](#kimmdy.cmd.entry_point_kimmdy) | Run KIMMDY from the command line. |
| [get_cmdline_args](#kimmdy.cmd.get_cmdline_args) | Parse command line arguments. |
| [kimmdy_run](#kimmdy.cmd.kimmdy_run) | Run KIMMDY from python. |

### configure_logger { #kimmdy.cmd.configure_logger }

`cmd.configure_logger(config)`

Configure logging.

#### Parameters

| Name | Type | Description | Default |
|----------|----------------------------------|----------------------------------------------------|------------|
| `config` | [Config](`kimmdy.config.Config`) | configuration that contains log.level and log.file | _required_ |

### entry_point_kimmdy { #kimmdy.cmd.entry_point_kimmdy }

`cmd.entry_point_kimmdy()`
Expand Down
24 changes: 21 additions & 3 deletions _reference/config.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ and package into a parsed format for internal use.

### Config { #kimmdy.config.Config }

`config.Config(self, input_file=None, recursive_dict=None, scheme=None, section='config', logfile=None, loglevel=None)`
`config.Config(self, input_file=None, opts=None, scheme=None, section='config', logfile=None, loglevel=None)`

Internal representation of the configuration generated
from the input file, which enables validation before running
Expand All @@ -24,7 +24,7 @@ and computationally expensive operations.
| Name | Type | Description | Default |
|------------------|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|------------|
| `input_file` | [Path](`pathlib.Path`) \| None | Path to the config yaml file. | `None` |
| `recursive_dict` | [dict](`dict`) \| None | For internal use only, used in reading settings in recursively. | `None` |
| `recursive_dict` | | For internal use only, used in reading settings in recursively. | _required_ |
| `scheme` | [dict](`dict`) \| None | dict containing types and defaults for casting and validating settings. | `None` |
| `section` | [str](`str`) | current section e.g. to determine the level of recursion in nested configs e.g. "config", "config.mds" or "config.reactions.homolysis" | `'config'` |

Expand All @@ -46,4 +46,22 @@ Alias for self.__getattribute__

`config.Config.get_attributes()`

Get a list of all attributes without hidden ones (_<...>).
Get a list of all attributes without hidden ones (_<...>).

## Functions

| Name | Description |
| --- | --- |
| [configure_logger](#kimmdy.config.configure_logger) | Configure logging. |

### configure_logger { #kimmdy.config.configure_logger }

`config.configure_logger(config)`

Configure logging.

#### Parameters

| Name | Type | Description | Default |
|----------|----------------------------------|----------------------------------------------------|------------|
| `config` | [Config](`kimmdy.config.Config`) | configuration that contains log.level and log.file | _required_ |
2 changes: 1 addition & 1 deletion _reference/runmanager.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ rest of the program and keeps track of global state.
|-------------------|-----------------------------------------------------------------------------------------|------------------------------------------------------------|
| config | [Config](`kimmdy.config.Config`) | The configuration object. |
| tasks | [queue](`queue`).[Queue](`queue.Queue`)\[[Task](`kimmdy.tasks.Task`)\] | Tasks from config. |
| crr_tasks | [queue](`queue`).[Queue](`queue.Queue`)\[[Task](`kimmdy.tasks.Task`)\] | Current tasks. |
| slotted_tasks | [queue](`queue`).[Queue](`queue.Queue`)\[[Task](`kimmdy.tasks.Task`)\] | Additional tasks added during the run by other tasks. |
| iteration | [int](`int`) | Current iteration. |
| state | [State](`kimmdy.runmanager.State`) | Current state of the system. |
| recipe_collection | [RecipeCollection](`kimmdy.recipe.RecipeCollection`) | Collection of recipes. |
Expand Down
Loading

0 comments on commit b100117

Please sign in to comment.