我想跳过中间规则,如果他们的输出文件已经存在。
例如,我想跳过第二条规则,如果它在这个基本的 Snakefile 之前运行:
rule third:
input:
"b",
"c"
output: "d"
shell: "touch {output}"
rule second:
input: ancient("b")
output: "c"
shell: "touch {output}"
rule first:
input: "a"
output: "b"
shell: "touch {output}"
触摸a
后,此管道工作正常。
当我再次触摸a
时,我希望第二个规则将被跳过,因为输入被标记为ancient
。
将第三规则中的c
而不是第二规则中的b
标记为古代也没有效果。
更新:使用建议,我更新了 Snakefile 以跳过第二条规则,如果它在之前运行(并且不是强制的):
ruleorder: cached_c > second
rule third:
input:
"b",
"c"
output: "d"
shell: "touch {output}"
rule second:
input: "b"
output:
c = "c"
shell: '''
touch {output.c}
cp {output.c} cache
'''
rule cached_c:
input: "cache"
output: "c"
shell: "cp {input} {output}"
rule first:
input: "a"
output: "b"
shell: "touch {output}"
如果输入被更改,远古确实会阻止规则运行,但是不是在 snakemake 执行更改时。您可以运行snakemake -nr
以查看运行规则的原因,并且在您提供规则的情况下,第二个将运行,因为Input files updated by another job: b
。我遇到了类似的情况,但我认为这是在 temp 和远古之间的相互作用,而不是
虽然缓存会工作,但它会向磁盘添加另一个文件,在实际示例中可能不太理想。此外,在规则第三只依赖于 c 的情况下,它仍然会重新运行,因为 c 的修改时间随着复制而更新。我去是一个输入函数,当输出文件已经存在时,它将返回一个空字符串 (或 dict 如果使用 unpack)。
import os
rule third:
input:
"b",
"c"
output: "d"
shell: "touch {output}"
def second_input(wildcards):
if os.path.exists("c"):
return ""
else:
return "b"
rule second:
input: second_input
output: "c"
shell: "touch {output}"
rule first:
input: "a"
output: "b"
shell: "touch {output}"
现在触摸 a 只会导致规则第一和第三运行,因为 a 被更新,然后 b 被更新。
为什么你假设第二条规则将被跳过?ancient
修饰符相反:
为了确定是否必须重新创建输出文件,Snakemake 检查同一作业的任何输入文件的文件修改日期(即时间戳)是否比输出文件的时间戳新。可以通过将输入文件标记为古老来覆盖此行为。此类文件的时间戳将被忽略,并始终假定为比任何输出文件都旧
因此,而不是总是跳过规则,你总是运行它,即使没有任何变化。
规则具有依赖关系这一事实意味着,每当更改输入时,您都希望重新评估此规则的输出。您可以通过创建从cache获取其输入的单独规则来手动打破此依赖关系。缓存版本必须没有依赖关系(因此永远不会被重新评估),并且您可以在确定文件足够好以进行缓存时手动复制它们。
一种替代方法是在每次成功运行后(或在每次运行之前,如果您找到工件)自动将文件复制到缓存目录中:s://snakemake.readthedocs.io/en/stable/snakefiles/rules.html#onstart-onsuccess-and-onerror-handlers
onsuccess:
# Copy your files here
更新:我在消息中提供的 Snakemake 引用的引用是模棱两可的,可以通过两种方式理解。但是,它没有说 Snakemake 如何处理古代输入的时间戳,将它们链接到可能影响此文件的其他规则。
关于缓存版本,我个人没有接触到Between workflow caching,但这不是我的意思。Snakemake 不知道更改的源是否会影响缓存的文件,除非它重新评估文件并比较哈希。如果您希望避免这种情况(并且您非常确定源的更改不会影响管道的其余部分),则可以创建两个单独的分支来创建目标。例如,
本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处
评论列表(16条)