Snakemake是否有内置参数可容忍缺失输入?
在Snakemake中处理动态生成的输入文件(容忍缺失输入)
Snakemake没有直接“容忍缺失输入”的内置参数,但可以通过Checkpoint机制处理这种“先动态生成部分文件,再基于实际存在的文件进行下游分析”的场景——这是官方推荐的处理动态输出/输入的标准方案。
你的核心问题在于:初始定义的CHR列表是固定的,但实际运行中只会生成部分染色体的文件;而Snakemake在初始化阶段就会解析所有规则的目标文件,所以在规则内部修改全局CHR变量无法改变后续规则的执行逻辑。
解决方案:用Checkpoint捕获动态生成的文件
下面是修改后的完整代码,核心思路是:
- 用Checkpoint替代原来的
get_CHR规则,动态生成染色体对应的文件,并以目录作为Checkpoint的输出(标记这是一个动态生成的文件集合) - 编写一个函数,在运行时收集Checkpoint生成的所有文件,动态生成下游规则的目标列表
- 下游规则基于实际存在的动态文件执行,不会因“预期但未生成的文件”报错
import os import pandas as pd import glob CHR = [1,2,3,4,5] # 初始值仅作为占位,实际会被动态覆盖 rule all: input: # 动态获取实际需要生成的my_file_{chr}.txt文件列表 lambda wildcards: get_chr_files() rule one: input: config["Inputfile"] output: config["outdir"] + "/rslts/rule_1/rule_1.csv" shell: """ # 这里写你的rule1逻辑,生成包含染色体信息的csv文件 whatever """ # 用Checkpoint替代原get_CHR规则,处理动态输出 checkpoint get_CHR: input: config["outdir"] + "/rslts/rule_1/rule_1.csv" params: outdir = config["outdir"] + "/rslts/update_CHR/" output: directory(params.outdir) # 以目录作为输出,标记动态生成的文件集合 run: # 创建输出目录(如果不存在) os.makedirs(params.outdir, exist_ok=True) # 读取rule1生成的csv,提取实际存在的染色体 chr_df = pd.read_csv(input[0], sep=",") actual_chrs = chr_df["chromosome_name"].tolist() # 生成每个染色体对应的update_*.txt文件 for chr in actual_chrs: # 这里替换为你实际的文件生成逻辑,示例中假设取csv第二列的值写入文件 chr_value = chr_df[chr_df["chromosome_name"] == chr].iloc[0, 1] with open(f"{params.outdir}/update_{chr}.txt", "w") as f: f.write(f"{chr_value}\n") # 收集Checkpoint生成的所有update_*.txt文件,生成下游目标文件列表 def get_chr_files(): # 获取Checkpoint的输出目录 checkpoint_dir = checkpoints.get_CHR.get_output()[0] # 遍历目录下的所有update_*.txt文件 chr_files = glob.glob(os.path.join(checkpoint_dir, "update_*.txt")) # 提取染色体编号,生成对应的my_file_{chr}.txt路径 actual_chrs = [os.path.basename(f).replace("update_", "").replace(".txt", "") for f in chr_files] return expand("my_file_{chr}.txt", chr=actual_chrs) rule three: input: # 根据wildcard动态匹配对应的输入文件 lambda wildcards: os.path.join(config["outdir"], f"rslts/update_CHR/update_{wildcards.chr}.txt") output: "my_file_{chr}.txt" shell: """ # 这里写你的下游处理逻辑 whatever """
关键说明
- Checkpoint的作用:Checkpoint会暂停Snakemake的DAG解析,先执行该规则生成动态文件,之后再重新解析后续规则的依赖关系,确保后续规则只处理实际存在的文件。
- 动态目标列表:
get_chr_files函数在运行时读取Checkpoint生成的文件,动态生成rule all的目标,避免了初始固定CHR列表带来的“缺失输入”问题。 - 为什么原来的方法无效:Snakemake在启动时会一次性解析所有规则的依赖和目标文件,规则内部修改全局变量
CHR的操作发生在运行阶段,无法影响初始化阶段已经确定的DAG结构。
替代方案(仅适用于预先生成文件的场景)
如果你的染色体文件是在Snakemake运行前就已经存在的,可以用glob_wildcards在初始化阶段直接匹配现有文件:
# 直接匹配目录下已有的update_*.txt文件 chr_wildcards = glob_wildcards(config["outdir"] + "/rslts/update_CHR/update_{chr}.txt") actual_chrs = chr_wildcards.chr rule all: input: expand("my_file_{chr}.txt", chr=actual_chrs)
但这种方法不适用于文件是由Snakemake动态生成的场景,因为初始化阶段文件还未生成。
内容的提问来源于stack exchange,提问作者Toffi
相关产品推荐
相关产品推荐

