I am attempting to create an iterative rule in snakemake. I have an empty text file in data/ called basic_0. I am hoping to apply a rule to it "x" times (where "x" is an integer) by calling $ snakemake data/basic_<x>.txt --cores 1
, where the snakefile is as follows:
rule iterative_addHi:
input:
"data/basic_{iter}.txt"
output:
"data/basic_{iter+1}.txt"
shell:
"python addHi.py {input} {output}"
The addHi.py file just adds a new line with "Hi" to the text file (just toy code), so if I call $ snakemake data/basic_5.txt --cores 1
I would hope to find a file called data/basic_5.txt that has five new lines with "Hi". However I'm only getting
MissingRuleException: No rule to produce data/basic_5.txt (if you use input functions make sure that they don't raise unexpected exceptions).
Is there a way to do what I'm thinking? I've tried converting the wildcard into an integer using int()
, then adding 1, then converting this back to a string using str()
.
Thanks
Snakemake allows expressing inputs as a function of wildcards. This applies to inputs directive, so the arithmetic should be moved from output
to input
and lambda used to delay the computation/evaluation of inputs:
rule iterative_addHi:
input:
lambda wildcards: f"data/basic_{int(wildcards.iter)-1}.txt"
output:
"data/basic_{iter}.txt"
shell:
"python addHi.py {input} {output}"
As @dariober noted in a comment: the wildcards are stored as strings, so for arithmetic, we need to convert them to an integer representation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With