Snakemake 具有 3 个不同的程序、2 个输入目录和一个具有所需输出的预定义 .txt 文件

Snakemake with 3 different programs, 2 input-directorys and one pre-defined .txt file with desired outputs

这将是一个有点苛刻的问题,但到目前为止,由 sankemake doku 主演的死亡还没有产生预期的结果,我希望更有经验的人可以指导我。

让我描述一下我有什么:

1:Shell上的三个程序,执行方式如下:

./program_1 $(cat file/from/dir_1/foo.fa) $(cat file/from/dir_2/bar.fa) > output.txt
./program_2 $(cat file/from/dir_1/foo.fa) $(cat file/from/dir_2/bar.fa) > output.txt
./program_3 $(cat file/from/dir_1/foo.fa) $(cat file/from/dir_2/bar.fa) > output.txt

是的,猫是必需的,他们使用文件中的字符串,而不是文件本身。


2:两个看起来像这样的目录:

hsa-let-7f-5p.fa
hsa-let-7g-5p.fa
hsa-miR-100-3p.fa
hsa-miR-100-5p.fa
hsa-miR-101-2-5p.fa

...(更多)

NM_000044.fa
NM_000059.fa
NM_000075.fa
NM_000088.fa
NM_000103.fa

...(更多)


3:包含所有所需输出组合的 .txt 文件:

hsa-miR-29b-3p__NM_138473_programm_1.txt
hsa-miR-29b-3p__NM_138473_programm_2.txt
hsa-miR-29b-3p__NM_138473_programm_3.txt
hsa-miR-545-3p__NM_002332_programm_1.txt
hsa-miR-545-3p__NM_002332_programm_2.txt
hsa-miR-545-3p__NM_002332_programm_3.txt

...(更多)


这两个目录的文件并不是全部都用到,有些文件用了多次,我不要全部组合,只需要指定一次。输出文件应该是单独的,并根据上面指定的 .txt 命名。最终的 sankefile 应该在集群上很好地并行化。


工作流程用文字来说非常简单:

1.Read 输出文件名。
2.Retrieve 来自两个目录的组合所需的输入。
3.Run 它们在所有 3 个程序上并输出预定义的 txt。通过将程序标准输出管道传输到文件中。

完成


但是好吧...如何告诉 Snakemake?有人告诉我这是可能的,但到目前为止还不是运气。如果有问题请问。提前致谢 (:



我根据我对情况的了解调整了下面的代码。我现在正在从文件中读出,顶部的“程序”和“规则一”中的“目录”有它们的完整路径。我还把 shell 命令中的两个输入调换了,因为我很困惑,他们就这样走了。是的,我知道文件名不是最理想的。

out = []
f = open("snakemake_output_small.txt", "r")
for line in f:
    out.append(line.replace('\n', ''))   

# Get distinct filenames
hsa = set([x.split('__')[0] for x in out])
nm = [x.split('__')[1] for x in out]
nm = set([re.sub('_program_.*', '', x) for x in nm])
program = ['full/path/to/program_1', 'full/path/to/program_2', 'full/path/to/program_3']

# Force snakemake to use exactly these wildcard values
# i.e. do not match by regex
wildcard_constraints:
    hsa= '|'.join([re.escape(x) for x in hsa]),
    nm= '|'.join([re.escape(x) for x in nm]),
    program= '|'.join([re.escape(x) for x in program]),


rule all:
    input:
        out,


rule one:
    input:
        hsa= 'full/path/to/dir1/{hsa}.fa',
        nm= 'full/path/to/dir2/{nm}.fa',
    output:
        '{hsa}__{nm}_{program}.txt',
    shell:
        r"""
        {wildcards.program} {input.nm} {input.hsa} > {output}
        """

现在它告诉我:

Building DAG of jobs...
MissingInputException in line 21 of Snakefile:
Missing input files for rule all:
hsa-miR-545-3p__NM_002332_program_3.txt
hsa-miR-29b-3p__NM_138473_program_1.txt
hsa-miR-29b-3p__NM_138473_program_1.txt
hsa-miR-545-3p__NM_002332_program_2.txt
hsa-miR-29b-3p__NM_138473_program_3.txt
hsa-miR-545-3p__NM_002332_program_2.txt

这 100% 是用户错误,但我错过了什么。如果我不是完全瞎了,输入的目录是正确的。


我还忘了提,其中两个程序有自己的参数,必须包含在内。程序 2 的 -d 和程序 3 的 -P here/a/parameter/file,因此 shell 命令可能需要分开。对不起,这一切都非常混乱。

如前所述,有问题请追问。

我更愿意将输出文件名与输入和程序的组合放在一个 csv 文件中,使用 pandas 读取它并使用数据框来指导工作流程。相反,我在这里解析输出文件名以提取相关输入,这在我看来是模糊的。

为了容纳传递给每个程序的选项,请使用字典,或者更好的是,使用 yaml 配置文件并使用 program 通配符查询此字典:

# Read this list from file:
out= ['hsa-miR-29b-3p__NM_138473_program_1.txt',
    'hsa-miR-29b-3p__NM_138473_program_2.txt',
    'hsa-miR-29b-3p__NM_138473_program_3.txt',
    'hsa-miR-545-3p__NM_002332_program_1.txt',
    'hsa-miR-545-3p__NM_002332_program_2.txt',
    'hsa-miR-545-3p__NM_002332_program_3.txt']

hsa = set([x.split('__')[0] for x in out])
nm = [x.split('__')[1] for x in out]
nm = set([re.sub('_program_.*', '', x) for x in nm])

# Better to put this in a yaml file and read it with `--configfile progs.yaml`
programs = {'program_1': 
                {'path': '/path/to/program_1', 'opts': '-d foo -P bar'}, 
           'program_2': 
                {'path': '/path/to/program_2', 'opts': '-P spam eggs'}, 
           'program_3': 
                {'path': '/path/to/program_3', 'opts': ''}
           }

wildcard_constraints:
    hsa= '|'.join([re.escape(x) for x in hsa]),
    nm= '|'.join([re.escape(x) for x in nm]),
    program= '|'.join([re.escape(x) for x in programs.keys()]),


rule all:
    input:
        out,


rule one:
    input:
        hsa= 'dir1/{hsa}.fa',
        nm= 'dir2/{nm}.fa',
    output:
        '{hsa}__{nm}_{program}.txt',
    params:
        path= lambda wc: programs[wc.program]['path'],
        opts= lambda wc: programs[wc.program]['opts'],
    shell:
        r"""
        {params.path} {params.opts} {input.hsa} {input.nm} > {output}
        """