Nextflow执行bbduk报错No such variable: id问题求助
问题复现
首次编写Nextflow流程处理双端测序reads,调用bbduk工具时出现如下错误:
ERROR ~ Error executing process > 'BBduk (1)'
Caused by:
No such variable: id -- Check script 'Workflow_Clean_Human_DNA.nf' at line: 34Source block:
def prefix = file("${meta.id}")
def raw = "in1=${reads[0]} in2=${reads[1]}"
def trimmed = "out1=${prefix}_1.fastq.gz out2=${prefix}_2.fastq.gz"
"""
echo(${prefix})
echo(${raw})
echo(${trimmed})
bbduk.sh \
$raw \
$trimmed \
qtrim=r trimq=10 minlen=100 \
&> ${prefix}.bbduk.log
"""
原因分析
核心问题在于Channel.fromFilePairs()的默认输出结构:该方法返回的是**(样本前缀字符串, [read1文件路径, read2文件路径])**的元组,而你的process输入定义为tuple val(meta), path(reads),错误地将第一个元素当作包含id字段的Map对象来使用,导致meta.id找不到对应变量。
解决方案
提供两种可行方案,按需选择:
方案1:直接使用样本前缀字符串(最简单)
修改process的输入定义和后续引用,将meta替换为sample_id(即fromFilePairs返回的前缀字符串):
process BBduk { input: tuple val(sample_id), path(reads) tag {sample_id} output: tuple val(sample_id), path('*.fq.gz'), emit: reads tuple val(sample_id), path('*.log'), emit: log script: def prefix = sample_id def raw = "in1=${reads[0]} in2=${reads[1]}" def trimmed = "out1=${prefix}_1.fastq.gz out2=${prefix}_2.fastq.gz" """ echo ${prefix} echo ${raw} echo ${trimmed} bbduk.sh \\ ${raw} \\ ${trimmed} \\ qtrim=r trimq=10 minlen=100 \\ &> ${prefix}.bbduk.log """ }
Workflow部分无需修改,原sequences通道的结构完全适配。
方案2:封装为带id的元数据Map(便于后续扩展)
如果后续流程需要更复杂的元数据,可以将fromFilePairs的输出转换为包含id字段的Map对象:
workflow { sequences = Channel.fromFilePairs( [params.fq1,params.fq2] ) // 将样本前缀封装为带id的Map .map { sample_id, reads -> [ id: sample_id ], reads } println "Performing Quality control and trimming from $sequences" BBduk(sequences) }
此方案下,原process的代码无需修改(仅建议将echo(${prefix})改为echo ${prefix},避免Shell语法解析问题)。
额外优化建议
- 参数定义中
params.fq2 = "$HOME/..//*{2}.fq.gz"多了一个冗余斜杠,建议改为params.fq2 = "$HOME/../*{2}.fq.gz" - script块中无需用
file()包装${meta.id},直接使用字符串作为前缀即可
内容的提问来源于stack exchange,提问作者Adría Cruells

