如何在 snakemake 输出中执行简单的字符串操作

How to perform simple string operations in snakemake output

我正在创建我的第一个 snakemake 文件,我需要对 output 的值执行简单的字符串操作,这样我的 shell 命令就可以作为预期:

rule sketch:
  input:
    'out/genomes.txt'
  output:
    'out/genomes.msh'
  shell:
    'mash sketch -l {input} -k 31 -s 100000 -o {output}'

我需要将 split 函数应用到 {output} 以便只使用扩展名之前的文件名。我在文档或相关问题中找不到任何内容。

您可以使用参数字段:

rule sketch:
  input:
    'out/genomes.txt'
  output:
    'out/genomes.msh'
  params:
    dir = 'out/genomes'
  shell:
    'mash sketch -l {input} -k 31 -s 100000 -o {params.dir}'

避免重复文本。除非您将 input/outputs 转换为通配符 + 扩展名,否则不要使用参数。否则,您将面临难以维护的规则。

input:
    "{pathDIR}/{genome}.txt"
output:
    "{pathDIR}/{genome}.msh"
params:
    dir: '{pathDIR}/{genome}'

否则,use Python's slice notation

我似乎无法使用输出通配符在参数中使用切片符号。这是在 运行 指令中。

from subprocess import call

rule sketch:
  input:
    'out/genomes.txt'
  output:
    'out/genomes.msh'
  run:
    callString="mash sketch -l " + str(input) + " -k 31 -s 100000 -o " + str(output)[:-4]
    print(callString)
    call(callString, shell=True)

Python 是 Snakemake 的基础。我更喜欢 "run" 指令而不是 "shell" 指令,因为我发现它确实解锁了很多漂亮的 Python 功能。参数和各种事物的访问与 "shell" 指令略有不同。

例如

callString=config["mpileup_samtoolsProg"] + ' view -bh -F ' + str(config["bitFlag"]) + ' ' + str(input.inputBAM) + ' ' + wildcards.chrB2M[1:] 

A bit of a snippet of J.K. using the run directive.

All of the rules in my modules pretty much use the run directive

您可以在 shell 命令中删除扩展程序

rule sketch:
  input:
    'out/genomes.txt'
  output:
    'out/genomes.msh'
  shell:
    'mash sketch -l {input} -k 31 -s 100000 -o $(echo "{output}" | sed -e "s/.msh//")'

使用通配符的替代解决方案:

rule all:
  input: 'out/genomes.msh'

rule sketch:
  input:
    '{file}.txt'
  output:
    '{file}.msh'
  shell:
    'mash sketch -l {input} -k 31 -s 100000 -o {wildcards.file}'

未经测试,但我认为这应该可行。

params 解决方案相比的优势在于它的泛化能力更好。

最好使用 params:

rule sketch:
    input:
        'out/genomes.txt'
    output:
        'out/genomes.msh'
    params:
        prefix=lambda wildcards, output: os.path.splitext(output[0])[0]
    shell:
        'mash sketch -l {input} -k 31 -s 100000 -o {params.prefix}'

最好使用 params 而不是 run 指令,因为 run 指令不能与 conda 环境结合使用。