输出带有混合通配符的文件

时间:2018-03-16 18:19:29

标签: output wildcard snakemake

我一直坚持如何用Snakemake做到这一点。

首先,说我的“所有”规则是:

rule all:
    input: "SA.txt", "SA_T1.txt", "SA_T2.txt",
        "SB.txt", "SB_T1.txt", "SB_T2.txt", "SB_T3.txt"

请注意,SA有两个_T#个文件,而SB有三个这样的文件,这是其中的一个重要元素。

现在我想写一个这样的规则来生成这些文件:

rule X:
    output: N="S{X}.txt", T="S{X}_T{Y}.txt"
    (etc.)

但SnakeMake要求两个输出模板都具有相同的通配符,而这些通配符不是。此外,即使SnakeMake可以处理多个通配符,也可能希望找到S{X}_T{Y}.txt模板的单个文件名匹配,但我希望它匹配{X}匹配第一个模板{{}的所有文件。 1}},即我希望{X}成为列表,而不是单个文件。所以看起来这样做的方法是:

output.T

但是我不能这样做,因为lambda函数不能在输出节中使用。

我该怎么做?

在我看来,这支持在输出语句上支持lambda函数,提供一个通配符字典,其中填充了输出语句的已解析部分的值。

回复评论的补充:

需要使用通配符Y的值,因为其他规则对具有通配符Y的文件具有输入。

我的规则知道从数据库读取到python词典的数据需要处理的Y(和X)的不同值。

X的值很多,X的每个值都有2到6个Y值。我认为对X的每个值使用单独的规则是不合理的。但是,我可能错了,因为我最近了解到,可以将规则放在循环中,并创建多个规则。

关于工作流程的更多信息:我将来自一个人的几个肿瘤样本的体细胞变异VCF文件组合到一个VCF文件中,并且这样做对于任何一个肿瘤中的每个被调用的变体,所有肿瘤都没有调用该变体分析以确定变量的读取深度,该深度包含在合并的VCF文件中。

整个过程涉及大约14个步骤,可能多达14个规则。我实际上不想使用14条规则,但更喜欢在一条规则中完成所有操作。

然而,我现在认为解决方案确实使用了许多单独的规则。我之所以避免这种情况,部分原因是因为大量不必要的中间文件,但实际上,这些都是暂时存在的,在一个大规则内。有了多个规则,我可以将它们标记为temp(),这样Snakemake会在最后删除它们。

为了充实这个我认为合法的讨论,让我们假设一个可能出现的简单情况。比如对于每个人来说,你有N(> = 2)肿瘤VCF文件,就像我一样,并且你想编写一个规则,产生N + 1个输出文件,每个肿瘤加一个输出文件加还有一个与此人关联的文件。使用通配符X作为人员ID,使用通配符Y作为人X内的肿瘤ID。假设该操作是将所有肿瘤VCF文件中存在的所有变体放入人员输出VCF文件中,并将所有其他变体放入相应的肿瘤输出文件中它们出现的肿瘤。 假设一个程序从N个输入文件生成所有N + 1个文件。你怎么写这条规则?

你想要这个:

def myExpand(T, wildcards):
    T = T.replace("{X}", wildcards.X)
    T = [T.replace("{Y}", S) for S in theXYs[wildcards.X]]
    return T

rule X:
    output: N="S{X}.txt", T=lambda wildcards: myExpand("S{X}_T{Y}.txt", wildcards)
    (etc.)

但这违反了输出通配符的规则。

我这样做的方式不太令人满意,但是很有效,就是使用两个规则,第一个规则的输出模板包含更多通配符,第二个模板包含更少的通配符通配符,并使用第二个规则创建临时输出文件,这些文件由第一个规则重命名为最终名称:

rule:
    output: COMMON="{X}.common.vcf", INDIV="{X}.{Y}.indiv.vcf"
    input: "{X}.{Y}.vcf"
    shell: """
        getCommonAndIndividualVariants --inputs {input} \
        --common {output.COMMON} --indiv {output.INDIV}
        """

2 个答案:

答案 0 :(得分:0)

我不知道您的工作流程的其余部分是什么样的,最佳解决方案是依赖于上下文。

1

如何将规则拆分为两个,一个创建"SA.txt", "SA_T1.txt", "SA_T2.txt"另一个"SB.txt", "SB_T1.txt", "SB_T2.txt", "SB_T3.txt"

2

另一种可能性是只在output-directive中包含{X}文件,但是让规则创建其他文件,即使它们不在output-directive中。如果{Y}文件是DAG的一部分,则不起作用。

3(最佳解决方案?)

第三种也可能是最佳解决方案可能是在X规则中使用聚合通配符以及需要X输出的规则。

然后解决方案是

rule X:
    output: N="S{X_prime}.txt", T="S{Y_prime}.txt"

需要这些文件的规则可能如下所示:

rule all:
    input:
        expand("S{X_prime}", X_prime="A_T1 A_T2".split()),
        expand("S{Y_prime}", Y_prime="B_T1 B_T2 B_T3".split())

如果这不符合您的要求,我们可以进一步讨论:)

聚苯乙烯。您可能需要使用wildcard_constraints来消除规​​则X的输出歧义。

list_of_all_valid_X_prime_values = "A_T1 A_T2".split()
list_of_all_valid_Y_prime_values = "B_T1 B_T2 B_T3".split()

wildcard_constraints:
    X_prime = "({})".format("|".join(list_of_all_valid_X_prime_values))
    Y_prime = "({})".format("|".join(list_of_all_valid_Y_prime_values))

rule all:
    ...

答案 1 :(得分:0)

我的理解是,snakemake的工作方式如下:

  • 查看要求生成的文件的名称。
  • 查找输出中具有匹配模式的规则。
  • 从上面的匹配中推断通配符的值。
  • 使用通配符确定所选规则的输入名称。

您的规则可以在不需要输入的情况下生成其输出,因此推断通配符Y的值的问题并不明显。

您的规则如何知道需要使用的Y有多少不同的值?

如果你找到一种方法来确定Y的值,只知道X和预定义的“python-level”函数和变量的值,那么可能有办法{{1作为规则的内部变量,而不是通配符。

在这种情况下,工作流程只能由文件Y驱动。 S{X}.txt只是执行规则的副产品,而不是其显式输出。