我有一个 Nextflow 流程,如下所示:
process my_app {
publishDir "${outdir}/my_app", mode: params.publish_dir_mode
input:
path input_bam
path input_bai
val output_bam
val max_mem
val threads
val container_home
val outdir
output:
tuple env(output_prefix), path("${output_bam}"), path("${output_bam}.bai"), emit: tuple_ch
shell:
'''
my_script.sh \
!{input_bam} \
!{output_bam} \
!{max_mem} \
!{threads}
output_prefix=$(echo !{output_bam} | sed "s#.bam##")
'''
}
此过程仅创建两个
.bam .bai
文件,但 my_script.sh
还创建其他未在输出目录中发布的 .vcf
。
我尝试这样做是为了检索脚本创建的文件,但没有成功:
output:
tuple env(output_prefix), path("${output_bam}"), path("${output_bam}.bai"), path("${output_prefix}.*.vcf"), emit: mt_validation_simulation_tuple_ch
但在日志中我可以看到:
Error executing process caused by:
Missing output file(s) `null.*.vcf` expected by process `my_app_wf:my_app`
我缺少什么?你能帮我吗?预先感谢您!
问题在于 output_prefix 仅在 shell 块内部定义。如果输出前缀所需的只是文件的基本名称(不带扩展名),则可以使用常规的 script 块来 检查文件属性。请注意,脚本块中定义的变量(但在命令字符串之外)是全局变量(在进程范围内),除非使用
def
关键字定义:
process my_app {
...
output:
tuple val(output_prefix), path("${output_bam}{,.bai}"), path("${output_prefix}.*.vcf")
script:
output_prefix = output_bam.baseName
"""
my_script.sh \\
"${input_bam}" \\
"${output_bam}" \\
"${max_mem}" \\
"${threads}"
"""
}
如果该过程创建了 BAM(和索引),如果可以预先提供输出前缀,甚至可以重构多个输入通道。通常这更有意义,但我没有足够的细节来说明其中一种方式。以下内容可能足以作为示例;您可能需要/更喜欢组合/更改输出声明以适应,但希望您明白:
params.publish_dir = './results'
params.publish_mode = 'copy'
process my_app {
publishDir "${params.publish_dir}/my_app", mode: params.publish_mode
cpus 1
memory 1.GB
input:
tuple val(prefix), path(indexed_bam)
output:
tuple val(prefix), path("${prefix}.bam{,.bai}"), emit: bam_files
tuple val(prefix), path("${prefix}.*.vcf"), emit: vcf_files
"""
my_script.sh \\
"${indexed_bam.first()}" \\
"${prefix}.bam" \\
"${task.memory.toGiga()}G" \\
"${task.cpus}"
"""
}
请注意,indexed_bam需要以下形式的元组:
tuple(bam, bai)
我同意史蒂夫所说的,但是
path("${prefix}.bam{,.bai}")
可能有问题,据我了解,如果索引部分失败并且bai文件丢失,输出仍然会执行而不会出现错误。