Plugins#
Plugins are a feature in Snakebids that enables you to add custom functionality to your Snakebids application after parsing CLI arguments but before invoking Snakemake. For example, you can use a plugin to perform BIDS validation of your Snakebids app’s input, which ensures your app is only executed if the input dataset is valid. You can either use those that are distributed with Snakebids (see Using plugins) or create your own plugins (see Creating plugins).
Note
For a full list of plugins distributed with Snakebids, see the Plugins reference page.
Using plugins#
To add one or more plugins to your SnakeBidsApp
, pass them to the SnakeBidsApp
constructor via the plugins
parameter. Your plugin will have access to CLI parameters (after they’ve been parsed) via their names in SnakeBidsApp.config
. Any modifications to that config dictionary made by the plugin will be carried forward into the workflow.
As an example, the distributed BidsValidator
plugin can be used to run the BIDS Validator on the input directory like so:
import subprocess
from snakebids.app import SnakeBidsApp
from snakebids.plugins.validator import BidsValidator
SnakeBidsApp(
"path/to/snakebids/app",
plugins=[BidsValidator]
).run_snakemake()
Creating plugins#
A plugin is a function or callable class that accepts a SnakeBidsApp
as input and returns a modified SnakeBidsApp
or None
.
As an example, a simplified version of the bids-validator plugin that runs the BIDS Validator could be defined as follows:
import subprocess
from snakebids.app import SnakeBidsApp
from snakebids.exceptions import SnakeBidsPluginError
class BidsValidator:
"""Perform BIDS validation of dataset
Parameters
-----------
app
Snakebids application to be run
"""
def __call__(self, app: SnakeBidsApp) -> None:
# Skip bids validation
if app.config["plugins.validator.skip"]:
return
try:
subprocess.run(["bids-validator", app.config["bids_dir"]], check=True)
except subprocess.CalledProcessError as err:
raise InvalidBidsError from err
class InvalidBidsError(SnakebidsPluginError):
"""Error raised if input BIDS dataset is invalid,
inheriting from SnakebidsPluginError.
"""
Note
When adding plugin-specific parameters to the config dictionary, it is recommended to use namespaced keys (e.g. plugins.validator.skip
). This will help ensure plugin-specific parameters do not conflict with other parameters already defined in the dictionary or by other plugins.
A plugin can be used to implement any logic that can be handled by a Python function. In the above example, you may also want to add some logic to check if the BIDS Validator is installed and pass along a custom error message if it is not. Created plugins can then be used within a Snakebids workflow, similar to the example provided in Using plugins section. Prospective plugin developers can take a look at the source of the snakebids.plugins
module for examples.
Note
When creating a custom error for your Snakebids plugin, it is recommended to inherit from SnakebidsPluginError
such that errors will be recognized as a plugin error.