Snakemake含merge规则时,如何过滤无效通配符组合?
我明白你碰到的麻烦了:明明已经写了过滤逻辑只处理存在的FASTQ文件,但Snakemake还是硬要去找那些不存在的输入文件。核心问题出在你的aggReadLength规则里——它的expand调用直接用了全量的SIZEFRACS,完全没用到你之前做的过滤逻辑,导致Snakemake默认认为每个techname/capDesign组合都需要覆盖所有sizeFrac的依赖,哪怕对应的原始FASTQ根本不存在。
下面是适配Snakemake 4.4.0版本的修复方案:
第一步:重构授权组合的数据结构
先把授权组合改成按(techname, capDesign)分组的字典,这样能快速查到每个技术+捕获设计组合对应的有效size分数:
# 替换原来的AUTHORIZEDCOMBINATIONS生成代码 AUTHORIZED_BY_TC = {} for tech, cap, size in product(TECHNAMES, CAPDESIGNS, SIZEFRACS): fname = f"{tech}_{cap}_{size}.fastq" if os.path.isfile(fname): key = (tech, cap) if key not in AUTHORIZED_BY_TC: AUTHORIZED_BY_TC[key] = [] AUTHORIZED_BY_TC[key].append(size) # 整理出rule all需要生成的所有目标组合 ALL_TARGET_COMBOS = [(tech, cap) for tech, cap in AUTHORIZED_BY_TC.keys()]
第二步:修改rule all的输入生成
现在可以直接用分组后的组合生成目标文件,不用再依赖复杂的过滤函数:
rule all: input: expand("{techname}_{capDesign}_all.readlength.tsv", techname=[tc[0] for tc in ALL_TARGET_COMBOS], capDesign=[tc[1] for tc in ALL_TARGET_COMBOS])
第三步:让aggReadLength只请求存在的依赖
添加一个自定义函数,根据当前的techname和capDesign通配符,返回对应的有效sizeFrac列表,这样Snakemake只会去寻找真实存在的文件:
def get_valid_sizes(wildcards): key = (wildcards.techname, wildcards.capDesign) return AUTHORIZED_BY_TC.get(key, []) rule aggReadLength: input: expand("{techname}_{capDesign}_{sizeFrac}.readlength.tsv", sizeFrac=get_valid_sizes) output: "{techname}_{capDesign}_all.readlength.tsv" shell: "cat {input} > {output}"
第四步:保留原getReadLength规则即可
这个规则本身不需要修改,因为现在aggReadLength只会请求存在的sizeFrac组合对应的文件,Snakemake只会在需要的时候才触发getReadLength,自然不会去碰不存在的FASTQ。
为什么原来的方法失效?
你之前的filtered_product只在rule all的expand里生效,但aggReadLength的依赖生成完全没用到过滤逻辑,还是遍历了所有SIZEFRACS,导致Snakemake错误地认为每个techname/capDesign组合都需要覆盖所有sizeFrac的文件。通过按技术+捕获设计分组,我们确保每个规则只请求实际存在的文件依赖,从根源上解决了找不到文件的问题。
内容的提问来源于stack exchange,提问作者JulienLag

