Reputation: 1246
Is there a way to reuse a rule in snakemake changing only the params
?
For instance:
rule job1:
...
params:
reference = "path/to/ref1"
...
rule job2:
input: rules.job1.output
...
params:
reference = "path/to/ref2"
job1
and job2
rules are doing the same stuff, but I need to call them successively and the reference
parameter has to be modified. It generates lot's of code for a very similar task.
I tried to make a sub-workflow for this step, and the main Snakefile is more readable. However, the sub-workflow code still repeated.
Any idea or suggestion? Did I miss something?
EDIT
To be more specific, job2 has to be executed after job1, using the output of the latter.
Upvotes: 5
Views: 2255
Reputation: 23455
In case someone finds this 6 years later like I did: Snakemake version 6 and above supports rule inheritence, which makes the solution to the OP quite simple:
use rule job1 as job2 with:
input: rules.job1.output
...
params:
reference = "path/to/ref2"
Upvotes: 5
Reputation: 968
If the rule is the same, you could just use wildcards in the naming of the output files. This way, the same rule will be executed twice:
references = ["ref1", "ref2"]
rule all:
input: expand("my_output_{ref}", ref=references)
rule job:
input: "my_input"
output: "my_output_{ref}"
params: ref = "path/to/{ref}"
shell: "... {params.ref} {output}"
Hope this helps, if not could you maybe make your question more specific?
Edit
Okay, there's the possibility of defining custom inputs for a rule, by using a python function. Maybe you could into this direction. See this working example:
references = ["ref1", "ref2"]
rule all:
input: expand("my_output_{ref}", ref=references)
def rule_input(wildcards):
if (wildcards.ref == "ref1"):
input = "my_first_input"
elif (wildcards.ref == "ref2"):
input = "my_output_ref1"
return(input)
rule job:
input: rule_input
output: "my_output_{ref}"
params: ref = "path/to/{ref}"
shell: "echo input: {input} ; echo output: {output} ; touch {output}"
Upvotes: 3
Reputation: 1947
Snakemake does not support inheritance between rules. So, if you cannot use wildcards for your case, one option is to use delegation. You predefine the constant parts of the two rules into variables, and then refer to these from the rule bodies. Another option might be input/params functions (see docs and tutorial) and only one rule definition. This way, you can have completely different input files, following some logic based on the value of e.g. a wildcard.
Upvotes: 1