How to rename files with snakemake with a dictionary in config file?

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

我目前有在配置文件中的字典帮助下基于模式匹配使用 snakemake 重命名某些文件的问题。

input
通配符之后不再与
output
通配符匹配。数据遵循以下结构:

.
├── pool1
│   ├── name_A.txt
│   ├── name_B.txt
│   ├── name_C.txt
│   └── name_D.txt
└── pool2
    ├── name_E.txt
    ├── name_F.txt
    ├── name_G.txt
    └── name_H.txt

我想将它们重命名为基于文件名的子模式。在这种情况下,大写字母应替换为数字,而不同的池可以“编码”相同的数字。

.
├── pool1
│   ├── name_1.txt
│   ├── name_2.txt
│   ├── name_3.txt
│   └── name_4.txt
└── pool2
    ├── name_2.txt
    ├── name_3.txt
    ├── name_5.txt
    └── name_6.txt

每个池的替换存储在配置文件中,如下所示:

pools=['pool1','pool2']

c2n : [{'A':'1',
        'B':'2',
        'C':'3',
        'D':'4'},
       {'E':'2',
        'F':'3',
        'G':'5',
        'H':'6'}]

不幸的是 rule all from snakemake 没有找到重命名的输出文件。这些列表是在

rule all
之前根据配置文件使用嵌套 for 循环创建的。

rename_in=['pool1/name_A','pool1/name_B','pool1/name_C','pool1/name_D','pool2/name_E','pool2/name_F','pool2/name_G','pool2/name_H']
rename_out=['pool1/name_1','pool1/name_2','pool1/name_3','pool1/name_4','pool2/name_2','pool2/name_3','pool2/name_5','pool2/name_6']

rule all:
    input:
        # rename.smk
        expand("{pattern}.txt", pattern=rename_out)
  1. 到目前为止,我尝试使用 for 循环在遍历列表时创建多个规则:
for l, n in zip(rename_in, rename_out):
    rule:
        input:
            f"{l}.txt"
        output:
            f"{n}.txt"
        shell:
            "mv {input} {output}"

  1. 我还尝试在配置文件中对单个池 (pool1) 进行编码,然后为所有池制定规则:
rule rename:
    input:
        "pool1/name_{l}.txt"
    output:
        "pool1/name_{config[c2n][l]}.txt"
    shell:
        "mv {input} {output}"
  1. 在我的第三次尝试中,我编写了自己的 Python 包装器,其中包含一个调用
    mv
    命令的子进程,但是
    rule all
    仍然无法正确识别输出。

Snakemake 有没有聪明又简单的重命名文件的方法?在最佳世界中,这将基于池动态发生,但在这一点上我很好地让它以某种方式工作。 到目前为止,我一直在尝试绕过检查点,因为一开始这对我来说似乎是一个简单的问题。 我发现了一些与我类似的问题,但都没有更改输入和输出中的通配符。 提前致谢 (:

python configuration workflow snakemake
1个回答
0
投票

关于
rule all

您说,“这些列表是在根据配置文件全部规则之前使用嵌套 for 循环创建的。”使用下面的示例代码,您只需将

input
更改为
rule all
即可成为列表
rename_out
.

rule all:
    input:
        rename_out

关于重命名的主要规则

我认为你的 zip 想法是正确的。我将它嵌入到规则中。
这是一个在您提供的情况下有效的示例,将它们放在一起:

from shutil import move
import os
import glob

rename_in=['pool1/name_A','pool1/name_B','pool1/name_C','pool1/name_D','pool2/name_E','pool2/name_F','pool2/name_G','pool2/name_H']
rename_out=['pool1/name_1','pool1/name_2','pool1/name_3','pool1/name_4','pool2/name_2','pool2/name_3','pool2/name_5','pool2/name_6']


rule all:
    input:
        rename_out
        
        
rule rename_files:
    input: 
        [path for path in rename_in if os.path.exists(path)]
    output: 
        [rename_out[indx] for indx,path in enumerate(rename_in) if os.path.exists(path)]
    run:
        for f_in,f_out in zip(rename_in, rename_out):
            if f_in in glob.glob(f"{f_in.split('/')[0]}/*"):
               move(f_in, f_out)

注意,为了让 snakemake 稍后处理文件状态的微小变化,整个列表不会用作执行繁重工作的规则的输入和输出。当使用整个列表作为主要规则的输入和输出时,在从第一个方块开始时有效。如果在那种情况下你将一个文件恢复为原始名称,它会破坏工作流程,因为 snakemake 评估事情并说整个输出列表已过时并擦除所有涉及的文件以准备重新制作它们。 (事实上 ,如果该目录完全变空,它甚至会清除这些文件所在的目录。)。
Bu加上只涉及尚未重命名为

input
的文件和
output
中的
rename_files
规则中的相应文件,你会看到你可以将原始名称恢复为一个或几个并重新- 运行工作流程,snakemake 将只处理重命名这些文件,而保留在第一轮中重命名的其他文件不变。 snakemake 的一大优势在于它可以跟踪工作流程中必须完成的所有工作,因此您不想失去这种能力。因为否则你可以直接使用 Python。


这充分利用了 Snakemake 作为 Python 超集的优势。将

rename_files
中使用的一些代码放在上下文中以获得更多解释:

© www.soinside.com 2019 - 2024. All rights reserved.