8 Operators

Operators

我们可以使用operators修改channel的内容。例如前面就使用了view来查看channel的内容。operators大概可以分为以下几类:

  • Filtering:根据给定的规则过滤出想要的元素;
  • Transforming:转换channel中的值;
  • Splitting:将channel中的元素分成块;
  • Combining:合并多个channel;
  • Forking:可以将一个channel分割成多个channel;
  • Maths:在channel上使用数学函数;
  • Other:不在上述类别的操作,如view;

使用Operators

使用operator方式为:channel_obj.<operator>()

view作用是打印channel中的每一项到控制台:

ch = channel.of('1', '2', '3')
ch.view()

也可以传递一个闭包{}来格式化打印:

ch = channel
  .of('1', '2', '3')
  .view({ "chr$it" })

Filtering operators

filter可以过滤出满足某个条件的项,过滤条件可以为:

  • 正则表达式
  • 字面值
  • 数据类型限定符,如:Number,String,Boolean
  • 布尔语句

数据类型限定符

例如可以使用Number来过滤出数字项:

chr_ch = channel.of( 1..22, 'X', 'Y' )
autosomes_ch =chr_ch.filter( Number )
autosomes_ch.view()

正则表达式

例如匹配以1打头的所有项:

chr_ch = channel
  .of( 1..22, 'X', 'Y' )
  .filter(~/^1.*/)
  .view()

布尔语句

例如找到小于5的数字:

channel
  .of( 1..22, 'X', 'Y' )
  .filter(Number)
  .filter { it < 5 }
  .view()

上面的例子省略了括号,因为操作符的参数是一个闭包。完整写法:filter({ it<5})

字面值

如果我们只想要特定值的元素,我们可以指定一个字面值:

channel
  .of( 1..22, 'X', 'Y' )
  .filter('X')
  .view()

Transforming operators

map

map操作符可以为channel中的每一项应用传入的映射函数,并且将其返回作为一个新的channel。例如:

chr = channel
  .of( 'chr1', 'chr2' )
  .map ({ it.replaceAll("chr","") })

chr.view()

我们也可以使用map来将每个元素转为tuple:

fq_ch = channel
    .fromPath( 'data/yeast/reads/*.fq.gz' )
    .map ({ file -> [file, file.countFastq()] })
    .view ({ file, numreads -> "file $file contains $numreads reads" })

flatten

flatten操作符能将listtuple中的项展开:

list1 = [1,2,3]
ch = channel
  .of(list1)
  .view()
// [1, 2, 3]

ch =channel
    .of(list1)
    .flatten()
    .view()
/*
1
2
3
*/

效果等同于Channel.fromList

collect

flatten操作的逆向就是collect,它能将channel中的所有项当作一个list返回。当组合多个进程的输出或单个进程多次运行的结果时,这非常有用。

ch = channel
    .of( 1, 2, 3, 4 )
    .collect()
    .view()
// [1,2,3,4]

collect返回结果是一个value channel,能被多次使用。

groupTuple

groupTuple能将list或tuple中的元素按照key来分组:

ch = channel
     .of( ['wt','wt_1.fq'], ['wt','wt_2.fq'], ["mut",'mut_1.fq'], ['mut', 'mut_2.fq'] )
     .groupTuple()
     .view()
 /*
 [wt, [wt_1.fq, wt_1.fq]]
[mut, [mut_1.fq, mut_2.fq]]
 */

如果我们知道要分组的项目数,可以使用size参数。

ch = channel
     .of( ['wt','wt_1.fq'], ['wt','wt_1.fq'], ["mut",'mut_1.fq'])
     .groupTuple(size:2)
     .view()
// [wt, [wt_1.fq, wt_1.fq]]

Combining operators

合并操作符能将通道合并在一起。

mix

mix操作符将两个(或多个)通道发出的项组合到一个通道中。

ch1 = channel.of( 1,2,3 )
ch2 = channel.of( 'X','Y' )
ch3 = channel.of( 'mt' )

ch4 = ch1.mix(ch2,ch3).view()

结果中元素的顺序可能以任何顺序出现,不管通道的先后顺序。

join

join操作符按照匹配的键将两个通道中的项连接在一起。默认情况下,键为每一项的第一个元素。

reads1_ch = channel
  .of(['wt', 'wt_1.fq'], ['mut','mut_1.fq'])
reads2_ch= channel
  .of(['wt', 'wt_2.fq'], ['mut','mut_2.fq'])
reads_ch = reads1_ch
  .join(reads2_ch)
  .view()
  /*
  [wt, wt_1.fq, wt_2.fq]
[mut, mut_1.fq, mut_2.fq]
  */

Forking operators

分叉操作符将单个通道拆分为多个通道。

MultiMap

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
*/

若要创建一个multiMap的映射作为一个变量,该变量可以作为参数传递给多个 multiMap 操作符,可以使用 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 }

Maths operators

数学操作符允许使用简单的数学函数在通道上。例如:

  • count
  • min
  • max
  • sum
  • toInterger

count

count操作符会返回源通道中的所有项目数:

ch = channel
    .of(1..22,'X','Y')
    .count()
    .view()
// 24

Splitting operators

有时需要将通道中单个项(如文件或字符串)的内容分割成更小的块,这些块可以由下游操作符或进程处理,例如存储在 CSV 文件中的条目。
nextflow有以下此类操作符:

  • splitCsv:splitCsv 操作符允许您解析通道发出的,并使用 CSV 格式进行格式化的文本项,并将它们分割为记录或将它们分组为具有指定长度的记录列表。
  • splitFasta:splitFasta 操作符允许分割通道发出的条目,这些条目使用 FASTA 格式进行格式化。
  • splitFastq:splitFastq操作符可以分割FASTQ格式的条目。
  • splitText:splitText操作符可以将源通道发出的多行字符串或文本文件先拆分为包含n行的块。

splitCsv

splitCsv操作符可以解析具有CSV格式的文本文件。例如:

/*  data/yeast/samples.csv
sample_id,fastq_1,fastq_2
ref1,data/yeast/reads/ref1_1.fq.gz,data/yeast/reads/ref1_2.fq.gz
ref2,data/yeast/reads/ref2_1.fq.gz,data/yeast/reads/ref2_2.fq.gz
*/

csv_ch=channel
    .fromPath('data/yeast/samples.csv')
    .splitCsv()
csv_ch.view()

/*  output
[sample_id, fastq_1, fastq_2]
[ref1, data/yeast/reads/ref1_1.fq.gz, data/yeast/reads/ref1_2.fq.gz]
[ref2, data/yeast/reads/ref2_1.fq.gz, data/yeast/reads/ref2_2.fq.gz]
*/

可以通过位置索引来访问值,例如访问第一列可以使用[0]:

csv_ch=channel
    .fromPath('data/yeast/samples.csv')
    .splitCsv()
csv_ch
  .view({it[0]})

/*
sample_id
ref1
ref2
*/

当csv文件有列头时,可以使用参数header: true,这样可以通过列名来索引:

csv_ch=channel
    .fromPath('data/yeast/samples.csv')
    .splitCsv(header:true)
csv_ch.view({it.fastq_1})

/*
data/yeast/reads/ref1_1.fq.gz
data/yeast/reads/ref2_1.fq.gz
*/

如果想要分割以tab分界的文件,可以使用sep参数。例如:

Channel.of("val1\tval2\tval3\nval4\tval5\tval6\n")
  .splitCsv(sep: "\t")
  .view()
  /*
  [val1, val2, val3]
  [val4, val5, val6]
  */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值