从多个目录复制Snakemake

问题描述 投票:0回答:1

Snakemake让我超级困惑。我有一些格式的文件。

indir/type/name_1/run_1/name_1_processed.out
indir/type/name_1/run_2/name_1_processed.out
indir/type/name_2/run_1/name_2_processed.out
indir/type/name_2/run_2/name_2_processed.out

哪儿 type, name而这些数字是可变的。我想把所有名字相同的文件都集中到一个目录下。

outdir/type/name/name_1-1.out
outdir/type/name/name_1-2.out
outdir/type/name/name_2-1.out
outdir/type/name/name_2-2.out

我如何写一个Snakemake规则来实现这个目标?我首先尝试了下面的方法

rule rename:
    input:
        "indir/{type}/{name}_{nameno}/run_{runno}/{name}_{nameno}_processed.out"
    output:
        "outdir/{type}/{name}/{name}_{nameno}-{runno}.out"
    shell:
        "cp {input} {output}"

# example command: snakemake --cores 1 outdir/type/name/name_1-1.out

这样做是可行的,但这样做并不省力,因为我必须提前知道输出文件是什么,所以基本上我必须把所有的输出文件作为一个参数列表传给 snakemake,需要使用一些shell技巧来获取变量。

于是我尝试使用 directory (以及放弃保存 runno).

rule rename2:
    input:
        "indir/{type}/{name}_{nameno}"
    output:
        directory("outdir/{type}/{name}")
    shell:
        """
        for d in {input}/run_*; do
          i=0
          for f in ${{d}}/*processed.out; do
            cp ${{f}} {output}/{wildcards.name}_{wildcards.nameno}-${{i}}.out
          done
          let ++i
        done
        """

这给我带来了错误。Wildcards in input files cannot be determined from output files: 'nameno'. 我明白了。{nameno} 不存在于 output. 但我不希望它出现在目录名中,只希望它出现在被复制的文件名中。

另外,如果我删除 {nameno}然后它就会因为找不到正确的输入文件而抱怨。

对于我想做的事情,最好的做法是什么?另外,如何理解在 snakemake 中,你指定的是输出,而不是输入?我想这后一个事实才是让人困惑的地方。

snakemake
1个回答
1
投票

我想你需要的是 expand 职能。

rule all:
    input: expand("outdir/{type}/{name}/{name}_{nameno}-{runno}.out",
                  type=TYPES,
                  name=NAMES,
                  nameno=NAME_NUMBERS,
                  runno=RUN_NUMBERS)

职能: TYPES, NAMES, NAME_NUMBERSRUN_NUMBERS 是这些参数的所有可能值的列表。您需要硬编码或使用 glob_wildcards 函数来收集这些数据。

TYPES, NAMES, NAME_NUMBERS, RUN_NUMBERS, = glob_wildcards("indir/{type}/{name}_{nameno}/run_{runno}/{name}_{nameno}_processed.out")

但这样会产生重复的数据 如果不希望这样,请删除重复的数据。

TYPES, NAMES, NAME_NUMBERS, RUN_NUMBERS, = map(set, glob_wildcards("indir/{type}/{name}_{nameno}/run_{runno}/{name}_{nameno}_processed.out"))
© www.soinside.com 2019 - 2024. All rights reserved.