07-Nextflow operators(3)
Operators
Nextflow操作符是一些方法,允许您将信道相互连接,或转换应用用户提供的某些规则的信道发出的值。
操作符可分为七组:
- Filtering operators
- Transforming operators
- Splitting operators
- Combining operators
- Forking operators
- Maths operators
- Other operators
Note
操作符set和subscribe是最终操作符,因此,如果使用它们,它们必须是组合操作符链中的最后一个操作符。
Forking operators
分支操作符有:
branch
Note
需要Nextflow版本19.08.0-edge或更高版本。
branch操作符允许您将源信道发出的项转发到一个或多个输出信道,每次选择一个输出信道。
选择标准是通过指定一个闭包来定义的,该闭包提供一个或多个布尔表达式,每个布尔表达式都由一个唯一的标签标识。在第一个计算结果为真值的表达式上,当前项作为标签标识符绑定到一个命名信道。例如:
Channel
.from(1,2,3,40,50)
.branch {
small: it < 10
large: it > 10
}
.set { result }
result.small.view { "$it is small" }
result.large.view { "$it is large" }
1 is small
2 is small
3 is small
40 is large
50 is large
Note
由于view操作符的异步执行,上面的大小字符串可能会交错打印。
Tip
可以使用true作为最后一个分支条件来指定默认的回退条件。参见下面的示例。
Channel
.from(1,2,3,40,50)
.branch {
small: it < 10
large: it < 50
other: true
}
每个分支条件返回的值可以通过在条件表达式后面指定一个可选的表达式语句来定制。例如:
Channel
.from(1,2,3,40,50)
.branch {
foo: it < 10
return it+2
bar: it < 50
return it-2
other: true
return 0
}
Tip
当省略return关键字时,将隐式返回最后一个表达式语句的值。
Warning
分支计算闭包必须内联指定,例如。它不能被赋值给一个变量,并作为参数传递给操作符,而其他操作符可以这样做。
要创建一个可以作为参数传递给多个branch操作符的分支标准,可以使用branchCriteria内置方法,如下所示:
def criteria = branchCriteria {
small: it < 10
large: it > 10
}
Channel.from(1,2,30).branch(criteria).set { ch1 }
Channel.from(10,20,1).branch(criteria).set { ch2 }
multiMap
Note
需要Nextflow 19.11.0-edge版本或更高版本。
multiMap操作符允许您将源信道发出的项转发到两个或多个输出信道,这些输出信道将每个输入值映射为一个单独的元素。
映射条件是通过指定一个闭包来定义的,闭包指定目标信道,该信道由一个惟一标识符标记,后面跟着一个表达式语句,该表达式语句计算要分配给该信道的值。
Channel
.from(1,2,3,4)
.multiMap { it ->
foo: it + 1
bar: it * it
}
.set { result }
result.foo.view { "foo $it" }
result.bar.view { "bar $it" }
foo 2
foo 3
foo 4
foo 5
bar 1
bar 4
bar 9
bar 16
Tip
如果要发出的值与下面的值相同,则可以省略语句表达式。如果您只需要将相同的值转发到多个通道,您可以使用下面所示的简写符号。
Channel
.from(1,2,3)
.multiMap { it -> foo: bar: it }
.set { result }
与之前一样,这将创建两个通道,但现在这两个通道都接收相同的源项。
Warning
multi-map评估闭包必须内联指定,即。它不能被赋值给一个变量,并作为参数传递给操作符,而其他操作符可以这样做。
要创建一个可以作为参数传递给多个multiMap操作符的多map标准变量,可以使用multiMapCriteria内置方法,如下所示:
def criteria = multiMapCriteria {
small: it < 10
large: it > 10
}
Channel.from(1,2,30).multiMap(criteria).set { ch1 }
Channel.from(10,20,1).multiMap(criteria).set { ch2 }
into
Warning
在使用Nextflow DSL2语法时,into操作符不可用。
into操作符将源信道连接到两个或多个目标信道,这样源信道发出的值就会复制到目标信道。例如:
Channel
.from( 'a', 'b', 'c' )
.into{ foo; bar }
foo.view{ "Foo emit: " + it }
bar.view{ "Bar emit: " + it }
Foo emit: a
Foo emit: b
Foo emit: c
Bar emit: a
Bar emit: b
Bar emit: c
Note
注意,在这个例子中使用了花括号和;作为通道名称分隔符。这是必要的,因为into的实际参数是一个闭包,它定义了源连接到的目标通道。
第二个版本的into操作符接受一个整数n作为参数,并返回一个包含n个通道的列表,每个通道发出源通道发出的项的副本。例如:
(foo, bar) = Channel.from( 'a','b','c').into(2)
foo.view{ "Foo emit: " + it }
bar.view{ "Bar emit: " + it }
Note
上面的例子利用了多重赋值语法,使用into操作符返回的信道列表一次赋值两个变量。
See also tap and separate operators.
tap
tap操作符结合into和separate操作符的功能,连接两个信道,将源的值复制到tapped的信道中。同时,它将源信道分割为一个由操作符本身返回的新创建的信道。
tap在某些需要串联多个操作的场景中很有用,如下面的示例:
log1 = Channel.create()
log2 = Channel.create()
Channel
.of ( 'a', 'b', 'c' )
.tap ( log1 )
.map { it * 2 }
.tap ( log2 )
.map { it.toUpperCase() }
.view { "Result: $it" }
log1.view { "Log 1: $it" }
log2.view { "Log 2: $it" }
Result: AA
Result: BB
Result: CC
Log 1: a
Log 1: b
Log 1: c
Log 2: aa
Log 2: bb
Log 2: cc
// 可能出现的运行情况
N E X T F L O W ~ version 21.04.3
Launching `08-test_tap.nf` [clever_minsky] - revision: 67c4c1ac4f
Result: AA
Log 1: a
Result: BB
Log 1: b
Log 1: c
Result: CC
Log 2: aa
Log 2: bb
Log 2: cc
N E X T F L O W ~ version 21.04.3
Launching `08-test_tap.nf` [pensive_bhaskara] - revision: 67c4c1ac4f
Result: AA
Result: BB
Result: CC
Log 1: a
Log 1: b
Log 1: c
Log 2: aa
Log 2: bb
Log 2: cc
// 第一遍出现乱序的情况,值得注意
tap操作符还允许使用闭包指定目标信道。这种语法的优点是,您不需要先前创建目标信道,因为它是由操作符本身隐式创建的。
使用闭包语法,上面的例子可以被改写,如下所示:
Channel
.of ( 'a', 'b', 'c' )
.tap { log1 }
.map { it * 2 }
.tap { log2 }
.map { it.toUpperCase() }
.view { "Result: $it" }
log1.view { "Log 1: $it" }
log2.view { "Log 2: $it" }
Result: AA
Result: BB
Result: CC
Log 1: a
Log 1: b
Log 1: c
Log 2: aa
Log 2: bb
Log 2: cc
separate
Warning
separate操作符已经启用。使用multiMap代替。