我正在尝试在循环中使用 Snakemake 规则,以便该规则将前一次迭代的输出作为输入。那可能吗?如果可以,我该怎么做?
这是我的例子
- 设置测试数据
mkdir -p test
echo "SampleA" > test/SampleA.txt
echo "SampleB" > test/SampleB.txt
- 蛇形
SAMPLES = ["SampleA", "SampleB"]
rule all:
input:
# Output of the final loop
expand("loop3/{sample}.txt", sample = SAMPLES)
#### LOOP ####
for i in list(range(1, 4)):
# Setup prefix for input
if i == 1:
prefix = "test"
else:
prefix = "loop%s" % str(i-1)
# Setup prefix for output
opref = "loop%s" % str(i)
# Rule
rule loop_rule:
input:
prefix+"/{sample}.txt"
output:
prefix+"/{sample}.txt"
#expand("loop{i}/{sample}.txt", i = i, sample = wildcards.sample)
params:
add=prefix
shell:
"awk '{{print $0, {params.add}}}' {input} > {output}"
尝试运行示例会在/Users/fabiangrammes/Desktop/Projects/snake_loop/Snakefile 的第 26 行产生错误 CreateRuleException:
名称 loop_rule 已被另一个规则使用
。如果有人发现一个选项可以让那个东西工作,那就太好了!
谢谢!
最佳答案
我认为这是使用递归编程的好机会。与其为每次迭代显式地包含条件,不如编写一条从迭代 (n-1)
过渡到 n
的规则。所以,按照这些思路:
SAMPLES = ["SampleA", "SampleB"]
rule all:
input:
expand("loop3/{sample}.txt", sample=SAMPLES)
def recurse_sample(wcs):
n = int(wcs.n)
if n == 1:
return "test/%s.txt" % wcs.sample
elif n > 1:
return "loop%d/%s.txt" % (n-1, wcs.sample)
else:
raise ValueError("loop numbers must be 1 or greater: received %s" % wcs.n)
rule loop_n:
input: recurse_sample
output: "loop{n}/{sample}.txt"
wildcard_constraints:
sample="[^/]+",
n="[0-9]+"
shell:
"""
awk -v loop='loop{wildcards.n}' '{{print $0, loop}}' {input} > {output}
"""
正如@RussHyde 所说,您需要主动确保不会触发无限循环。为此,我们确保所有情况都包含在 recurse_sample
中,并使用 wildcard_constraints
来确保匹配的精确性。
关于python - Snakemake 在循环中使用规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56274065/