Functions as input and output for rules - RomainFeron/workshop-snakemake-sibdays2020 GitHub Wiki

We have already seen multiple ways to define inputs and outputs that cover a wide range of situations: single file, multiple files (named or unnamed), using wildcards, the expand syntax ... However, in some cases, inputs and outputs can depend on wildcard values in a non-trivial ways that is not covered by these definitions. In this case, we can specify inputs and outputs using special functions. These functions take the wildcards global object as single argument, and return either a single or a list of inputs / outputs.

These functions should be implemented in the Snakefile above the rule that uses them. Alternatively, they can be implemented as lambda expression within the rule. The syntax to use a defined function as input in a rule is input: <function_name> without brackets and arguments. The following example implements an input function that conditionally returns an input file based on the value of the wildcard sample:

def first_step_input(wildcards):
    sample = wildcards.sample
    if sample == 'sample1':
        return 'data/data1.txt'
    else:
        return 'data/data2.txt'


rule first_step:
    input:
        first_step_input
    output:
        'results/first_step.txt'
    shell:
        'cp {input} > {output}'

The syntax would be the same for an output function in the output directive.

Input and output functions can return a list of files, which will then be automatically handled like multiple inputs or outputs by Snakemake. These functions can also return a dictionary; in this case, the function should be called with the syntax input: unpack(<function_name>). The dictionary's keys will be interpreted as input / output names and the dictionary's values will be interpreted as input / output values.

Note: functions are evaluated before the workflow is executed. As a consequence, they cannot be used to list the content of an output directory, since the directory does not exist before the workflow is executed !