NextFlow:如果通道为空( .ifEmpty() )如何失败

NextFlow: How to fail if channel is empty ( .ifEmpty() )

如果特定的 channel 为空,我希望我的 NextFlow 管道失败,因为按照原样,管道将继续运行,就好像没有任何问题一样,但过程取决于频道永远不会开始。 声明我们通常不应该检查 channel 是否为空,但我不确定如何处理这个问题。

我在下面的示例中遇到的问题是它总是失败,但是如果我注释掉 .ifEmpty() 语句,就会调用该过程。

这是一个基本示例:

/*
 * There are .cram files in this folder
 */
params.input_sample_folder = 'path/to/folder/*' 
samples = Channel.fromPath(params.input_sample_folder, checkIfExists: true)
                 .filter( ~/.*(\.sam|\.bam|\.cram)/ )
                 .ifEmpty( exit 1,
                  "ERROR: Did not find any samples in ${params.input_sample_folder})

workflow{
    PROCESS_SAMPLES( samples )
}

终极问题:

  1. 我的猜测是 channel 不会立即填充。真的吗?如果有,什么时候填满?
  2. 我该如何处理这种情况?如果频道没有被填充,我想失败。例如,如果我只提供没有 glob/wildcard 字符的文件夹路径(/path/to/folder/;没有 **.cram 等),我惊讶地发现频道仍然是空的。 .我认为我无法在进程本身中处理它,因为如果 channel 合法为空,则永远不会调用该进程。

非常感谢您的帮助。

设置checkIfExists: true实际上会在你的文件系统中不存在指定的文件时为你抛出一个异常。诀窍是在创建通道时指定您需要的文件,而不是在下游过滤它们。例如,您只需要:

params.input_sample_folder = 'path/to/folder'

samples = Channel.fromPath(
    "${params.input_sample_folder}/*.{sam,bam,cram}",
    checkIfExists: true,
)

或者可以说更好;因为这使用户可以完全控制输入文件:

params.input_sample_files = 'path/to/folder/*.{sam,bam,cram}'

samples = Channel.fromPath( params.input_sample_files, checkIfExists: true )

无论哪种方式,当不存在匹配文件时,两者都会使您的管道失败,退出状态为 1 并显示以下红色消息:

No files match pattern `*.{sam,bam,cram}` at path: path/to/folder/

根据文档,ifEmpty 运算符实际上只是为了在通道变空时发出默认值。为了避免必须检查通道是否为空,一般的解决方案是首先避免创建空通道。有很多方法可以做到这一点,但其中一种方法可能如下所示:

import org.apache.log4j.Logger

nextflow.enable.dsl=2


def find_sample_files( input_dir ) {

    def pattern = ~/.*(\.sam|\.bam|\.cram)/
    def results = []

    input_dir.eachFileMatch(pattern) { item ->
        results.add( item )
    }

    return results
}


params.input_sample_folder = 'path/to/folder'

workflow {

    input_sample_folder = file( params.input_sample_folder )
    input_sample_files = find_sample_files( input_sample_folder )

    if ( !input_sample_files ) {
        log.error("ERROR: Did not find any samples in ${params.input_sample_folder}")
        System.exit(1)
    }

    sample_files = Channel.of( input_sample_files )
    sample_files.view()
}