Search code examples
nextflow

Writing values from a channel to a file


What is the best way to write values from a channel to a file?

Consider the following example:

nextflow.enable.dsl=2

workflow {

    ch = Channel.of('a', 'b', 'c')

    file('test.txt').withWriter {out -> 
        out.println "My values are:"
        ch.subscribe {
            out.println "$it"
            println "$it"
        }
    }
}

This will correctly output a, b, c to stdout, but test.txt will only contain My values are: and nothing else. Clearly, .subscribe{} is iterating over the values (otherwise it wouldn't display them to stdout) and writing to the file is working (otherwise the file would not have My values are:), but why would it not write the values to the file?


Solution

  • The usual way is to use the collectFile operator: https://nextflow-io.github.io/patterns/collect-into-file/

    If you don't need sorted output and would like the entries appended as they're emitted, you could also use sort: false to disable content sorting and the concat operator to prepend the header:

    workflow {
    
        my_header = Channel.value( "My values are:" )
        my_values = Channel.of( 'foo', 'bar', 'baz' )
        
        my_header
            .concat( my_values )
            .collectFile( name: 'test.txt', newLine: true, sort: false )
            .view()
    
    }
    

    Results:

    $ nextflow run main.nf 
    N E X T F L O W  ~  version 23.04.1
    Launching `main.nf` [marvelous_marconi] DSL2 - revision: c9242fbc73
    /path/to/work/tmp/ea/d8ec4488443faf816cb6a213f3bad7/test.txt
    

    Contents of /path/to/work/tmp/ea/d8ec4488443faf816cb6a213f3bad7/test.txt:

    My values are:
    foo
    bar
    baz
    

    Note that you could also use a closure to write to the file, for example:

    workflow {
    
        def test_file = new File( 'test.txt' )
        def write_value = { value ->
            test_file << value + "\n"
        }
    
        my_values = Channel.of( 'foo', 'bar', 'baz' )
    
        Channel
            .value( "My values are:" )
            .concat( my_values )
            .subscribe { write_value(it) }
    }
    
    $ cat test.txt 
    My values are:
    foo
    bar
    baz