我想了解snakemake如何处理以下情况,以及避免碰撞/损坏的最佳实践是什么。
rule something:
input:
expand("/path/to/out-{asd}.txt", asd=LIST)
output:
"/path/to/merged.txt"
shell:
"cat {input} >> {output}"
使用snakemake -j10
,该命令将尝试同时附加到同一个文件,但我无法确定这是否会导致可能的损坏或是否已处理。
此外,如何处理更复杂的案件,例如它不仅是 cat
,而且是另一个基于附加到同一文件的输入值的进程的返回值?最佳实践是首先将它们写入单独的文件,然后 cat
将它们组合在一起吗?
rule get_merged_total_distinct:
input:
expand("{dataset_id}/merge_libraries/{tomerge}_merged_rmd.bam",dataset_id=config["dataset_id"],tomerge=list(TOMERGE.keys())),
output:
"{dataset_id}/merge_libraries/merged_total_distinct.csv"
params:
with_dups="{dataset_id}/merge_libraries/{tomerge}_merged.bam"
shell:
"""
RCT=$(samtools view -@4 -c -F1 -F4 -q 30 {params.with_dups})
RCD=$(samtools view -@4 -c -F1 -F4 -q 30 {input})
printf "{wildcards.tomerge},${{RCT}},${{RCD}}\n" >> {output}
"""
或者调用外部脚本将结果打印到单个输出文件的情况?
input:
expand("infile/{x}",...) # expanded as above
output:
"results/all.txt"
shell:
"""
bash script.sh {params.x} {input} {params.y} >> {output}
"""
最佳答案
根据您的示例,shell 指令将扩展为
cat /path/to/out-SAMPLE1.txt /path/to/out-SAMPLE2.txt [...] >> /path/to/merged.txt
其中SAMPLE1
等来自LIST。在这种情况下,不存在冲突、损坏或竞争条件。一个线程将运行该命令,就像您在 shell 上键入该命令一样,并且所有输入都将被 cat
编辑到输出中。由于snakemake是基于pull的,一旦输出存在,只有当输入发生变化时,该规则才会再次运行,此时由于使用>>
,新输入将添加到旧输入中>。因此,我建议使用 >
以便删除旧内容;规则应尽可能具有确定性。
现在,如果你做了类似的事情
rule something:
input:
"/path/to/out-{asd}.txt"
output:
touch("/path/to/merged-{asd}.txt")
params:
output="/path/to/merged.txt"
shell:
"cat {input} >> {params.output}"
# then invoke
snakemake -j10 /path/to/merged-{a..z}.txt
事情变得更加困惑。 Snakemake 将启动所有 10 个作业并输出到单个 merged.txt。请注意,文件现在是一个参数,我们的目标是一些虚拟文件。这将表现得好像您有 10 个不同的 shell 并执行了命令
cat /path/to/out-a.txt >> /path/to/merged.txt
# ...
cat /path/to/out-z.txt >> /path/to/merged.txt
一下子就全部完成了。输出将具有随机顺序,并且行可能会交错或中断。
作为一些指导
- 尝试使输出具有确定性。给定相同的输入,您应该始终产生相同的输出。如果可能,设置随机种子并强制输入排序。在第二个示例中,您不知道输出是什么。
- 不要使用追加运算符。这是从第一点开始的。如果输出已经存在并且需要更新,请从头开始。
- 如果您需要附加一堆输出(例如日志文件或创建摘要),请在单独的规则中执行此操作。这又是从第一点得出的,但这是我能想到使用追加的唯一原因。
希望有帮助。否则,您可以用更现实的示例来评论或编辑您所担心的问题。
关于snakemake - Snakemake 如何处理由于并行运行的规则同时附加到单个文件而可能发生的损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71939707/