蛇妈能否在文件丢失时强制重新运行规则?

12

当管道中早期创建的文件被删除时,SnakeMake似乎并不认为这是一个问题,只要后面的文件存在:

rule All:
    input: "testC1.txt", "testC2.txt"

rule A:
    input: "{X}{Y}.txt"
    output: "{X}A{Y}.txt"
    shell: "cp {input} {output}"

rule B:
    input: "{X}A{Y}.txt"
    output: "{X}B{Y}.txt"
    shell: "cp {input} {output}"

rule C:
    input: "{X}B{Y}.txt"
    output: "{X}C{Y}.txt"
    shell: "cp {input} {output}"

将此SnakeFile保存为test.sf并执行以下操作:

rm testA*.txt testB*.txt testC*.txt
echo "test1" >test1.txt
echo "test2" >test2.txt
snakemake -s test.sf
# Rerun:
snakemake -s test.sf
# SnakeMake says all is up to date, which it is.
# Remove intermediate results:
rm testA1.txt
# Rerun:
snakemake -s test.sf

SnakeMake表示一切都是最新的,它没有检测到缺失的testA1.txt文件。

我记得在线SnakeMake手册中有相关内容,但现在找不到了。

我认为这是SnakeMake的预期行为。有时这可能是期望的行为,但有时您可能希望它检测并重建丢失的文件。如何实现?


1
我认为这确实是Snakemake的预期行为。如果您真的需要testA1.txt,我建议您将其添加到您的All规则中。 - rioualen
4
将所有可能需要保留的中间文件添加到规则 "All" 中是不切实际的。Snakemake 应该有不同的工作方式,以提供针对这种情况的解决方案。 - tedtoal
3个回答

12
另一个回答所述,-R参数可以帮助,但还有更多选项:

强制重新构建整个工作流程

当您调用时

snakemake -F

这将触发整个流水线的重建。基本上意味着忘记所有中间文件并重新开始。这肯定会在路上(重新)生成所有中间文件。缺点是:可能需要一些时间。

强制执行特定规则

这是-R <rule>参数的领域。这将重新运行给定规则和所有依赖于它的规则。因此,在您的情况下

snakemake -R A -s test.sf

如果重新运行规则A(使用test.txt创建testA1.txt),还有规则B、C和All需要运行,因为它们依赖于A。请注意,这将运行所有所需的规则A的副本,因此在您的示例中,testA2.txt及其后续文件也将被重新构建。

如果在您的示例中,您删除了testB1.txt,那么只会重新运行规则BC

为什么会这样?

如果我没记错的话,snakemake通过utime检测文件是否需要重新构建。因此,如果testA1.txt的版本比testB1.txt年轻(即最近创建的),则必须使用规则B重新构建testB1.txt,以确保一切都是最新的。因此,除非您以某种方式更改文件的utime,否则不能轻松地仅重新构建testA1.txt而不重新构建所有后续文件。

我没有尝试过这个方法,但可以使用snakemakes的--touch参数来实现。如果您设法仅运行规则A,然后运行snakemake -R B -t,这会触及规则B和其后续文件的所有输出文件,您可以获得一个有效的工作流状态,而无需重新运行所有中间步骤。


3

我前段时间发现了这个关于 --forcerun/-R 参数的讨论帖,其中有很多有用的信息。

如果你想在不单独为中间文件创建规则或将其作为所有目标的一部分的情况下重新生成该文件,那么最终,snakemake会强制执行整个流程。


2

确实,如果Snakemake有一个标志可以查找缺失的中间结果并在缺失时重新生成它们(以及所有依赖项),那将是很好的(但目前没有这样的选项)。

注意,m00am和Jon Chung建议使用-R选项会重新生成所有其他文件,而不管中间文件是否缺失。因此这并不理想。

解决方法1:强制重新创建文件

使用-R-f标志强制重新创建中间文件(下面是帮助信息)。关键在于明确地指定目标文件,而不是规则。

snakemake -s test.sf testA1.txt # only works if testA1.txt was deleted
# or
snakemake -s test.sf -R testA1.txt # testA1.txt can be present or absent
# or
snakemake -s test.sf -f testA1.txt
# or
snakemake -s test.sf -F testA1.txt

请注意,对于后两个,需要重新运行管道以更新依赖项:

snakemake -s test.sf 

防止更新相关文件(通过触碰文件)

如果您不希望更新相关文件(即testB1.txt,testC1.txt),也有选项可用。

您可以重新生成testA1.txt,然后“重置”其修改时间,例如设置为源文件的修改时间,这将防止管道更新任何内容:

snakemake -s test.sf -f testA1.txt
touch testA1.txt -r test1.txt

snakemake -s test.sf现在不会执行任何操作,因为testB1.txttestA1.txt新。

或者您可以使用--touch标记依赖文件(即testB1.txt,testC1.txt)为“较新”:

snakemake -s test.sf -f testA1.txt
snakemake -s test.sf --touch

解决方法2:创建新规则

可以通过创建新规则来扩展snakefile:

rule A_all:
    input: "testA1.txt", "testA2.txt"

然后可以像这样调用:

snakemake A_all -s test.sf

这将只生成testA1.txt,类似于上面的工作流中的-f,因此需要重新运行管道或更改修改时间。一个技巧是使用--touch“更新”中间文件。
snakemake -s test.sf --touch testA1.txt -n

这将“更新”testA1.txt。重新创建依赖文件需要之后正常运行snakemake:

snakemake -s test.sf

请注意,如果删除了testA1.txt,这将无法起作用,需要执行以下操作代替删除。

相关参数的帮助信息:

  --touch, -t           Touch output files (mark them up to date without
                        really changing them) instead of running their
                        commands. This is used to pretend that the rules were
                        executed, in order to fool future invocations of
                        snakemake. Fails if a file does not yet exist.

  --force, -f           Force the execution of the selected target or the
                        first rule regardless of already created output.
  --forceall, -F        Force the execution of the selected (or the first)
                        rule and all rules it is dependent on regardless of
                        already created output.
  --forcerun [TARGET [TARGET ...]], -R [TARGET [TARGET ...]]
                        Force the re-execution or creation of the given rules
                        or files. Use this option if you changed a rule and
                        want to have all its output in your workflow updated.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接