我一直坚持如何用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}
"""
答案 0 :(得分:0)
我不知道您的工作流程的其余部分是什么样的,最佳解决方案是依赖于上下文。
如何将规则拆分为两个,一个创建"SA.txt", "SA_T1.txt", "SA_T2.txt"
另一个"SB.txt", "SB_T1.txt", "SB_T2.txt", "SB_T3.txt"
?
另一种可能性是只在output-directive中包含{X}文件,但是让规则创建其他文件,即使它们不在output-directive中。如果{Y}文件是DAG的一部分,则不起作用。
第三种也可能是最佳解决方案可能是在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
只是执行规则的副产品,而不是其显式输出。