在一条规则中处理文件列表的最佳方法是什么?
工作流程的主要目标是选择原始数据并输出所选数据。工作流程的目录结构如下。
.
├── data
│ ├── 000_raw
│ │ ├── 15_a.csv
│ │ ├── 15_b.csv
│ │ ├── 15_c.csv
│ │ ├── 16_a.csv
│ │ ├── 16_b.csv
│ │ └── 16_c.csv
│ └── 010_sel
│ ├── 15_a.csv
│ ├── 15_b.csv
│ ├── 15_c.csv
│ ├── 16_a.csv
│ ├── 16_b.csv
│ └── 16_c.csv
├── scripts
│ └── 010_sel.py
└── Snakefile
选择脚本
010_sel.py
每次读取并生成一个文件,即常见的运行方式是
python scripts/010_sel.py data/000_raw/15_a.csv data/010_sel/15_a.csv
我在snakemake文件中使用
expand
和run
方法。
ls_year_type = [15_a,15_b,15_c,16_a,16_b,16_c]
rule sel_010:
input:
expand("data/000_raw/{year_type}.csv",year_mag=ls_year_type)
output:
expand("data/010_sel/{year_type}.csv",year_mag=ls_year_type)
run:
for ifile in range(len(output)):
os.system("python scripts/010_sel.py {} {}".format(input[ifile],output[ifile]))
这个方法有两个问题。
expand
命令生成一个列表。如果仅修改列表中的一个文件,例如,rm data/010_sel/15_b.csv
,snakemake 将在列表中的每个文件上重新运行脚本。很费时间。010_sel.py
被修改,snakemake将不知道。需要手动重新运行蛇文件。一种可选方法是重写
010_sel.py
以包含 Snakemake 命令,而不是使用 sys.argv
for i in range(len(snakemake.input)):
input_file = snakemake.input[i]
output_file = snakemake.output[i]
在snakemake文件中将
run
更改为script
script:
"scripts/010_sel.py"
这将解决第二个问题,但第一个问题仍然存在。
预先感谢您的帮助。
Snakemake 是一个工作流管理器,具有许多功能,包括并行化、错误恢复和代码更改感知。它允许定义流程的逻辑并使用通配符将其应用到许多样本,并根据需要进行扩展。
通过在规则内定义 for 循环,您基本上会失去上述所有功能。
您(可能)应该这样做:
ls_year_type = [15_a,15_b,15_c,16_a,16_b,16_c]
rule all:
expand("data/010_sel/{year_type}.csv",year_mag=ls_year_type)
rule sel_010:
input:
"data/000_raw/{year_type}.csv"
output:
"data/010_sel/{year_type}.csv"
shell:
"python scripts/010_sel.py {input} {output}"
并运行snakemake:
$ snakemake --jobs 5
根据需要调整并行作业的数量,具体取决于您的计算机或 HPC。
您还可以按照您的说明使用
script
标签。 Snakemake 将创建一个包含命令行参数的 python 对象,您可以在脚本中处理这些参数:
rule sel_010:
input:
"data/000_raw/{year_type}.csv"
output:
"data/010_sel/{year_type}.csv"
script:
"scripts/010_sel.py"
通过这样做,你可以让snakemake 负责缩放。如果输入文件之一发生更改,snakemake 将仅在更改的文件上重新运行规则。如果脚本的代码发生更改,snakemake 将重新运行所有文件。您还可以使用 Snakemake 选项来更改此行为
--cleanup-metadata