为什么条件通道源导致下游进程不为不同通道中的每个值执行实例?
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()
}
我有一个 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()
}