Snakemake中如何结合通配符实现自定义函数?
问题:Snakemake expand函数嵌套lambda调用自定义函数时的通配符错误
场景说明
需要生成不同channel、mass、norm组合的输出文件,其中每个{channel, mass}对应一组特定的norm值。通过expand结合lambda调用get_norms函数获取norm列表时,触发如下错误:
InputFunctionException in rule all in file /home/egenton/upgrade_solar_WIMP/scripts/Snakefile, line 45: Error: AttributeError: 'Wildcards' object has no attribute 'channel' Wildcards:
错误原因
Snakemake的expand函数处理通配符是逐步填充的:先遍历channel,再针对每个channel遍历mass,最后处理norm。但嵌套的lambda函数在执行时,wildcards对象尚未完成channel和mass的绑定,导致无法访问wildcards.channel属性。
解决方案
方案一:嵌套expand,直接传递具体参数给get_norms
将expand拆分为两层,先遍历channel和mass,再针对每个具体的(channel, mass)组合调用get_norms,避免依赖未完全初始化的wildcards:
rule all: input: expand( expand( f"{DATA_LOC}/signal/channel_{channel}/trial_distributions/{mass}_trial_distrib_{{norm}}.h5", norm=get_norms({"mass": mass, "channel": channel}) ), channel=channels, mass=lambda wildcards: masked_mass_dict[wildcards.channel] )
方案二:手动生成所有输出路径(更直观)
编写函数遍历所有channel、mass、norm组合,直接生成完整的输出路径列表,完全绕过expand的lambda限制:
def generate_all_outputs(): outputs = [] # 遍历所有channel for channel in channels: # 遍历当前channel对应的mass值 for mass in masked_mass_dict[channel]: # 获取当前(channel, mass)对应的norm列表 norms = get_norms({"channel": channel, "mass": mass}) # 生成每个norm对应的输出路径 for norm in norms: outputs.append( f"{DATA_LOC}/signal/channel_{channel}/trial_distributions/{mass}_trial_distrib_{norm}.h5" ) return outputs rule all: input: generate_all_outputs()
额外注意事项
get_norms函数中dictionary_file = "path/"应为具体文件路径(如"path/sensitivities.pkl"),否则open会尝试打开目录而非文件,触发错误。- 函数中
norms = np.array([0])会覆盖之前生成的linspace和insert结果,若需保留多组norm值,需删除该行。
内容的提问来源于stack exchange,提问作者ma_boi
相关产品推荐
相关产品推荐

