在 Snakemake 中使用多个文件名作为通配符

Using multiple filenames as wildcards in Snakemake

我正在尝试创建一个规则来在 snakemake 中实施 bedtools,这将 closest 一个包含一堆文件的文件在另一个目录中。

我有的是,在/home/bedfiles目录下,20个bed文件:

1A.bed , 2B_83.bed , 3f_33.bed ...

我要的是,在/home/bedfiles目录下,20个修改床文件:

1A_modified,  2B_83_modified , 3f_33_modified ...

所以 bash 命令将是:

filelist='/home/bedfiles/*.bed'
for mfile in $filelist;
do
bedtools closest -a /home/other/merged.txt -b ${mfile} > ${mfile}_modified

因此此命令会在 /home/bedfiles 目录中生成扩展名为 _modified 的文件。

我想用 Snakemake 实现它,但是我一直有语法错误,我不知道如何修复。我的试用是:

第一步:获取目录下bed文件的第一部分

FIRSTPART = [f.split(".")[0] for f in os.listdir("/home/bedfiles") if f.endswith('.bed')]

第二步:定义输出名称和文件夹

MODIFIED = expand("/home/bedfiles/{first}_modified", first=FIRSTPART)

第三步:在rule all中写入:

rule all:
   input: MODIFIED

Step4:制定具体规则实施'bedtools closest'

rule closest:

    input:
        input1 = "/home/other/merged.txt" , \
        input2 = expand("/home/bedfiles/{first}.bed", first=FIRSTPART) 

    output:
        expand("/home/bedfiles/{first}_modified", first=FIRSTPART)  

    shell:
        """ bedtools closest -a {input.input1} -b {input.input2} > {output} """

它在规则所有行向我抛出错误,输入:

invalid syntax

你知道如何克服这个错误或任何其他实现它的方法吗?

PS : 一个一个写文件名是不可能的。

简单的:无效语法指的是 input1 = "/home/other/merged.txt" 之后缺少 , 希望能帮助到你 马克

inputclosest 中的 output 定义中删除对 expand 的调用。您目前正在传递一个包含 20 个文件名的矢量作为 input.input2 和一个包含 20 个文件名的矢量作为 output.

也就是说,您的规则 closest 当前正在尝试 运行 一次并创建 20 个文件;而它应该 运行 20 次并且每次创建一个文件。

closest 中,您希望 input.input2 成为单个文件,而 output 成为单个文件,每次规则为 运行:

FIRSTPART = [f.split(".")[0] for f in os.listdir("/home/bedfiles") if f.endswith('.bed')]

print("These are the input files:")
print([f + ".bed" for f in FIRSTPART])

MODIFIED = expand("/home/bedfiles/{first}_modified", first=FIRSTPART)
print("These will be created")
print(MODIFIED)

rule all:
   input: MODIFIED

rule closest:
    message: """
        Converts /home/other/merged.txt and /some/dir/xyz.bed
        into /some/dir/xyz_modified
        """

    input:
        input1 = "/home/other/merged.txt",
        input2 = "{prefix}.bed" 

    output:    "{prefix}_modified"  

    shell:
        """ 
        bedtools closest -a {input.input1} -b {input.input2} > {output}
        """

这是一个实验:

将自己移动到一个临时目录并在该目录中执行以下操作:

mkdir bedfiles                                                                  
touch bedfiles/{a,b,c,d}.bed

然后将名为 Snakefile 的文件添加到包含以下代码的当前目录中

import os                                                                         
import os.path
import re

input_dir = "bedfiles"
input_files = [os.path.join(input_dir, f) for f in os.listdir(input_dir)]

print(input_files)                                                                

output_files = [re.sub(".bed$", "_modified", f) for f in input_files]             

print(output_files)                                                               

rule all:                                                                         
    input: output_files                                                           

rule mover:                                                                       
    input: "{prefix}.bed"                                                         
    output: "{prefix}_modified"                                                   
    shell:                                                                        
       """ cp {input} {output} """

然后 运行 它在命令行中使用 snakemake。 Snakemake 以目标为导向;它会计算出如何根据现有文件制作您想要的输出。