Search code examples
groovynextflow

Nextflow: transform a list of tuples into a channel of tuples?


My process returns a list of tuples. How to create a channel that yields each tuple separately?

Indeed, I want to use the tuple's item as input of another process (here the multiply process). I would want the calls to multiply (i.e. one for each tuple in my_list_of_tuple) to be able to run in parallel.

However, if I use:

  • my_process.out.my_returned_list: I get only one element ([[1, 2], [3, 4], [5, 6]]);
  • my_process.out.my_returned_list.flatten(): I also flatten the tuples and get 6 elements (1, 2, 3, 4, 5, 6).

Question: How to define a channel that will get 3 elements: [1, 2], [3, 4], [5, 6]?

nextflow.enable.dsl=2

process my_process {
  output:
    val myList, emit: my_returned_list

  exec:
    myList = []
    myList.add(tuple(1, 2))
    myList.add(tuple(3, 4))
    myList.add(tuple(5, 6))
}

process multiply {
    input:
        val left
        val right

    output:
        val left_times_right

    exec:
        left_times_rigth = left * right
}

workflow {
    my_process()
    my_process.out.my_returned_list.view()
    my_process.out.my_returned_list.flatten().view()

    // <channel_to_be_defined>.map { i, j ->
    //    multiply(i, j)
    // }
}

Solution

  • You can just use the flatMap operator for this, for example:

    process my_process {
        
        output:
        val myList, emit: my_returned_list
    
        exec:
        myList = []
        myList.add(tuple(1, 2))
        myList.add(tuple(3, 4))
        myList.add(tuple(5, 6, 7))
    }
    
    process multiply {
        
        input:
        val factors
    
        output:
        tuple val(factors), val(the_product)
    
        exec:
        the_product = factors.inject { acc, num -> acc *= num }
    }
    
    workflow {
    
        my_process()
    
        my_factors = my_process.out.flatMap()
        my_products = multiply( my_factors )
    
        my_products.view { factors, product ->
            "The product of ${factors.join(',')} is: ${product}"
        }
    }
    

    Results:

    $ nextflow run main.nf 
    N E X T F L O W  ~  version 23.04.1
    Launching `main.nf` [admiring_hilbert] DSL2 - revision: 0bafefce32
    executor >  local (4)
    [9d/292489] process > my_process   [100%] 1 of 1 ✔
    [ec/94643b] process > multiply (1) [100%] 3 of 3 ✔
    The product of 3,4 is: 12
    The product of 5,6,7 is: 210
    The product of 1,2 is: 2