如何使用Snakemake将多个输入文件分别拆分为多个子片段?
问题根因
你当前的写法将所有输入文件绑定到同一个规则实例的输入参数中,Snakemake只会执行一次shell命令,将所有输入文件拼接后传给seqkit split。你需要让Snakemake为每个输入文件单独生成拆分任务,核心是通过通配符建立单个输入文件和对应拆分后输出文件的映射关系。
解决方案
以下是修改后的完整可运行代码,同时修复了你原有代码中扩展名硬编码、拆分份数少1的问题:
import os # 配置参数 my_files = ["path/to/file_1.fasta", "other/path/to/file_2.fasta"] split_parts = 10 # 每份文件拆分的份数 split_output_dir = "splited_fasta" # 解析每个文件的前缀、扩展名 file_info = {} all_split_files = [] for file_path in my_files: # 提取不带路径的文件名 base_name = os.path.basename(file_path) # 拆分文件名和扩展名,支持fna/fa/fasta prefix, ext = os.path.splitext(base_name) if ext not in ['.fna', '.fa', '.fasta']: # 可按需补充其他支持的扩展名逻辑 raise ValueError(f"不支持的文件扩展名: {ext}") file_info[prefix] = { "path": file_path, "ext": ext } # 生成该文件对应的所有拆分后文件名 for i in range(1, split_parts + 1): all_split_files.append(f"{split_output_dir}/{prefix}.part_{i:03d}{ext}") # 总规则,放在最前面,作为默认执行目标 rule all: input: all_split_files # 拆分单个fasta文件的规则 rule split_fasta: input: lambda wildcards: file_info[wildcards.prefix]["path"] output: expand(f"{split_output_dir}/{{prefix}}.part_{{i:03d}}{ext}", i=range(1, split_parts + 1), ext=lambda wildcards: file_info[wildcards.prefix]["ext"]) params: num_parts = split_parts, out_dir = split_output_dir shell: "seqkit split --out-dir {params.out_dir} --by-part {params.num_parts} {input}"
改动说明
- 用
os.path模块替代正则解析文件名,兼容性更强,也解决了原代码中扩展名硬编码为.fna的问题 - 新增顶层
rule all,将所有需要生成的拆分后文件作为输入,Snakemake会自动推导需要执行的任务 - 拆分规则使用通配符
prefix匹配文件名前缀,Snakemake会自动为每个输入文件生成独立的拆分任务,分别执行seqkit split命令 - 修正了原代码中
range(1,10)只能生成9份拆分文件的问题,改为range(1, split_parts + 1)生成完整的10份文件
内容的提问来源于stack exchange,提问作者Alexandre.S
相关产品推荐
相关产品推荐

