5

假设我有以下文件,我想使用 snakemake 自动对其进行一些处理:

test_input_C_1.txt
test_input_B_2.txt
test_input_A_2.txt
test_input_A_1.txt

以下蛇形expand文件用于确定所有潜在的最终结果文件:

rule all:
    input: expand("test_output_{text}_{num}.txt", text=["A", "B", "C"], num=[1, 2])

rule make_output:
    input: "test_input_{text}_{num}.txt"
    output: "test_output_{text}_{num}.txt"
    shell:
        """
        md5sum {input} > {output}
        """

执行上面的snakefile会导致如下错误:

MissingInputException in line 4 of /tmp/Snakefile:
Missing input files for rule make_output:
test_input_B_1.txt

该错误的原因是在后台expand使用itertools.product生成通配符组合,其中一些恰好对应于丢失的文件。

如何过滤掉不需要的通配符组合?

4

1 回答 1

10

expand函数接受第二个可选的非关键字参数,以使用与默认函数不同的函数来组合通配符值。

itertools.product可以通过将其包装在一个高阶生成器中来创建过滤版本,该生成器检查生成的通配符组合是否不在预先建立的黑名单中:

from itertools import product

def filter_combinator(combinator, blacklist):
    def filtered_combinator(*args, **kwargs):
        for wc_comb in combinator(*args, **kwargs):
            # Use frozenset instead of tuple
            # in order to accomodate
            # unpredictable wildcard order
            if frozenset(wc_comb) not in blacklist:
                yield wc_comb
    return filtered_combinator

# "B_1" and "C_2" are undesired
forbidden = {
    frozenset({("text", "B"), ("num", 1)}),
    frozenset({("text", "C"), ("num", 2)})}

filtered_product = filter_combinator(product, forbidden)

rule all:
    input:
        # Override default combination generator
        expand("test_output_{text}_{num}.txt", filtered_product, text=["A", "B", "C"], num=[1, 2])

rule make_output:
    input: "test_input_{text}_{num}.txt"
    output: "test_output_{text}_{num}.txt"
    shell:
        """
        md5sum {input} > {output}
        """

可以从配置文件中读取缺少的通配符组合。

下面是一个 json 格式的例子:

{
    "missing" :
    [
        {
            "text" : "B",
            "num" : 1
        },
        {
            "text" : "C",
            "num" : 2
        }
    ]
}

forbidden集合将在蛇文件中读取如下:

forbidden = {frozenset(wc_comb.items()) for wc_comb in config["missing"]}
于 2016-12-16T13:31:10.263 回答