Create and register a Method

Create and register a Method#

A method accepts some combination of QIIME 2 artifacts and parameters as input, and produces one or more QIIME 2 artifacts as output. These output artifacts could subsequently be used as input to other QIIME 2 methods or visualizers.

Create a function to register as a Method#

A function that can be registered as a Method will have a Python 3 API, and the inputs and outputs for that function will be annotated with their data types using mypy syntax. mypy annotation does not impact functionality (though the syntax is new to Python 3), so these can be added to existing functions in your Python 3 software project. An example is q2_diversity.pcoa, which takes an skbio.DistanceMatrix and an int as input, and produces an skbio.OrdinationResults as output. The signature for this function is:

def pcoa(distance_matrix: skbio.DistanceMatrix,
         number_of_dimensions: int = None) -> skbio.OrdinationResults:

As far as QIIME is concerned, it doesn’t matter what happens inside this function (as long as it adheres to the contract defined by the signature regarding the input and output types). For example, q2_diversity.pcoa is making some calls to the skbio API, but it could be doing anything, including making system calls (if your plugin is wrapping a command line application), executing an R library, etc.

Register the Method#

Once you have a function that you’d like to register as a Method, and you’ve instantiated your Plugin object, you are ready to register that function as a Method. This will likely be done in the file where the Plugin object was instantiated, as it will use that instance (which will be referred to as plugin in the following examples).

We register a Method by calling plugin.methods.register_function as follows (see the original source here).

from q2_types import DistanceMatrix, PCoAResults
from qiime2.plugin import Int, Citations

import q2_diversity

citations = Citations.load('citations.bib', package='q2_diversity')

    inputs={'distance_matrix': DistanceMatrix},
        'number_of_dimensions': Int % Range(1, None)
    outputs=[('pcoa', PCoAResults)],
        'distance_matrix': ('The distance matrix on which PCoA should be '
        'number_of_dimensions': "Dimensions to reduce the distance matrix to. "
                                "This number determines how many "
                                "eigenvectors and eigenvalues are returned,"
                                "and influences the choice of algorithm used "
                                "to compute them. "
                                "By default, uses the default "
                                "eigendecomposition method, SciPy's eigh, "
                                "which computes all eigenvectors "
                                "and eigenvalues in an exact manner. For very "
                                "large matrices, this is expected to be slow. "
                                "If a value is specified for this parameter, "
                                "then the fast, heuristic "
                                "eigendecomposition algorithm fsvd "
                                "is used, which only computes and returns the "
                                "number of dimensions specified, but suffers "
                                "some degree of accuracy loss, the magnitude "
                                "of which varies across different datasets."
    output_descriptions={'pcoa': 'The resulting PCoA matrix.'},
    name='Principal Coordinate Analysis',
    description=("Apply principal coordinate analysis."),

The values being provided are:

  • function: The function to be registered as a method.

  • inputs: A dictionary indicating the parameter name and its artifact class, for each input Artifact. These artifact classes differ from the data types that you provided in your mypy_ annotation of the input, as artifact classes describe the data, where the data types indicate the structure of the data. (See Semantic types, data types, file formats, and artifact classes for more detail on the difference between data types, semantic types, and artifact classes.) In the example above we’re indicating that the table parameter must be a FeatureTable of Frequency (i.e. counts), and that the phylogeny parameter must be a Phylogeny that is Rooted. Notice that the keys in inputs map directly to the parameter names in q2_diversity.beta_phylogenetic.

  • parameters: A dictionary indicating the parameter name and its type, for each input Parameter. These parameters are primitive values (i.e., non-Artifacts). In the example above, we’re indicating that the metric should be a string from a specific set (in this case, the set of known phylogenetic beta diversity metrics).

  • outputs: A list of tuples indicating each output name and its artifact class.

  • input_descriptions: A dictionary containing input artifact names and their corresponding descriptions. This information is used by interfaces to instruct users how to use each specific input artifact.

  • parameter_descriptions: A dictionary containing parameter names and their corresponding descriptions. This information is used by interfaces to instruct users how to use each specific input parameter. You should not include any default parameter values in these descriptions, as these will generally be added automatically by an interface.

  • output_descriptions: A dictionary containing output artifact names and their corresponding descriptions. This information is used by interfaces to inform users what each specific output artifact will be.

  • name: A human-readable name for the Method. This may be presented to users in interfaces.

  • description: A human-readable description of the Method. This may be presented to users in interfaces.

  • citations: A list of bibtex-formatted citations. These are provided in a separate citations.bib file, loaded via the Citations API, and accessed here by using their bibtex indices as keys.