为什么条件通道源导致下游进程不为不同通道中的每个值执行实例?

Why is a conditional channel source causing a downstream process to not execute an instance for each value in a different channel?

我有一个 Nextflow DSL2 管道,其中早期过程通常需要很长时间(~24 小时)并且中间产品占用大量存储空间(~1 TB)。由于此过程所需的长度和资源,希望能够设置“检查点”,即将(相对较小的)最终输出保存到安全位置,并在后续管道执行中从该位置检索输出.这意味着可以安全地删除中间数据,而不会阻止稍后恢复管道。

但是,我发现当我实现它并使用检查点时,下游的一个进程应该 运行 列表中每个值的实例仅 运行 一个实例。最小工作示例和示例输出如下:

// foobarbaz.nf
nextflow.enable.dsl=2

params.publish_dir = "$baseDir/output"
params.nofoo = false

xy = ['x', 'y']
xy_chan = Channel.fromList(xy)

process foo {
    publishDir "${params.publish_dir}/", mode: "copy"

    output:
        path "foo.out"
    
    """
    touch foo.out
    """
}

process bar {
    input:
        path foo_out

    output:
        path "bar.out"

    script:
        """
        touch bar.out
        """    
}

process baz {
    input:
        path bar_out
        val xy

    output:
        tuple val(xy), path("baz_${xy}.out")

    script:
        """
        touch baz_${xy}.out
        """
}

workflow {
    main:
        if( params.nofoo ) {
            foo_out = Channel.fromPath("${params.publish_dir}/foo.out")
        }
        else {
            foo_out = foo() // generally takes a long time and uses lots of storage
        }

        bar_out = bar(foo_out)
        baz_out = baz(bar_out, xy_chan)

        // ... continue to do things with baz_out ...
}

第一次执行 foo:

$ nextflow foobarbaz.nf 
N E X T F L O W  ~  version 21.10.6
Launching `foobarbaz.nf` [soggy_gautier] - revision: f4e70a5cd2
executor >  local (4)
[77/c65a9a] process > foo     [100%] 1 of 1 ✔
[23/846929] process > bar     [100%] 1 of 1 ✔
[18/1c4bb1] process > baz (2) [100%] 2 of 2 ✔

(注意 baz 成功执行了两个实例:一个 xy==x 和一个 xy==y

稍后使用检查点执行:

$ nextflow foobarbaz.nf --nofoo
N E X T F L O W  ~  version 21.10.6
Launching `foobarbaz.nf` [infallible_babbage] - revision: f4e70a5cd2
executor >  local (2)
[40/b42ed3] process > bar (1) [100%] 1 of 1 ✔
[d9/76888e] process > baz (1) [100%] 1 of 1 ✔

检查点成功(bar不需要foo执行),但现在baz只执行一个实例,其中xy==x.

为什么会这样,我怎样才能得到预期的行为?我看不出 foo_out 是来自 foo 还是直接从文件中检索会对 baz.[=25= 解释 xy 通道的方式产生任何影响]

根据我的经验,一个过程是根据具有最低 N 排放量的输入通道执行的(在您的情况下,这是来自 bar 的一条路径排放量)。 所以在这种情况下,奇怪的行为实际上是我脑海中没有 --nofoo 的例子。 如果您希望它执行 2 次,您可以尝试使用 baz_input_ch=bar.out.combine(xy_chan)

之类的组合来组合通道

问题是 Channel.fromPath factory method creates a queue channel to provide a single value, whereas the output of process 'foo' implicitly produces a value channel:

A value channel is implicitly created by a process when an input specifies a simple value in the from clause. Moreover, a value channel is also implicitly created as output for a process whose inputs are only value channels.

所以没有--nofoo,'foo_out'和'bar_out'都是价值渠道。由于 'xy_chan' 是一个提供两个值的队列通道,进程 'bar' 被执行了两次。对于 --nofoo,'foo_out' 和 'bar_out' 都是提供单个值的队列通道。由于只有一个完整的输入配置(即来自每个输入通道的一个值),进程 'bar' 只执行一次。另见:Understand how multiple input channels work.

解决方案是确保 'foo_out' 始终是队列通道或始终是值通道。鉴于您的 'foo' 流程声明,您可能需要后者:

if( params.nofoo ) {
    foo_out = file( "${params.publish_dir}/foo.out" )
}
else {
    foo_out = foo()
}