• 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()
    
    • 1
    • 2

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

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

    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
    • 2
    • 3

    正则表达式

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

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

    布尔语句

    例如找到小于5的数字:

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

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

    字面值

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

    channel
      .of( 1..22, 'X', 'Y' )
      .filter('X')
      .view()
    
    • 1
    • 2
    • 3
    • 4

    Transforming operators

    map

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

    chr = channel
      .of( 'chr1', 'chr2' )
      .map ({ it.replaceAll("chr","") })
    
    chr.view()
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

    flatten

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

    list1 = [1,2,3]
    ch = channel
      .of(list1)
      .view()
    // [1, 2, 3]
    
    ch =channel
        .of(list1)
        .flatten()
        .view()
    /*
    1
    2
    3
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    效果等同于Channel.fromList

    collect

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

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

    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]]
     */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果我们知道要分组的项目数,可以使用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]]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    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]
      */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    若要创建一个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 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Maths operators

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

    • count
    • min
    • max
    • sum
    • toInterger

    count

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

    ch = channel
        .of(1..22,'X','Y')
        .count()
        .view()
    // 24
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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]
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

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

    csv_ch=channel
        .fromPath('data/yeast/samples.csv')
        .splitCsv()
    csv_ch
      .view({it[0]})
    
    /*
    sample_id
    ref1
    ref2
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    当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
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    Channel.of("val1\tval2\tval3\nval4\tval5\tval6\n")
      .splitCsv(sep: "\t")
      .view()
      /*
      [val1, val2, val3]
      [val4, val5, val6]
      */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    十一、对象的新增方法
    复旦微开发过程中遇到的问题总结(三)
    软件测试概念介绍 -- 小白入门必看
    数据治理:元数据及元数据管理策略、方法和技术
    HTML期末学生大作业-节日网页作业html+css+javascript
    Spring 多数据源配置详解
    【计算机网络笔记】DNS报文格式
    栈和队列相关的一些问题
    Flink DataStream API 介绍
    万字长文总结与剖析C语言关键字 -- <<C语言深度解剖>>
  • 原文地址:https://blog.csdn.net/sinat_20791575/article/details/125516759