groovyexitnextflow

How to print (using view) and then exit with multiple workflows in nextflow?


I am debugging a workflow, and cannot quickly find a way to execute view (to print the diagnostic output) and then exit (quit) the workflow. The actual workflow is complex, and I reduced it to a minimal example below:

#!/usr/bin/env nextflow

nextflow.enable.dsl=2

params.run_step = true

workflow {
    input_ch = Channel.from("a", "b", "c")
    foo(input_ch)                             // <-- line 9
    if (params.run_step) {
        // Do not run this code and below:
        bar(foo.out.foo_out)
    }
}

workflow foo {
    take:
    input_data

    main:
    input_data.view { it -> "foo: input_data: ${it}" }

    return

    // Do not run this code and below:
    input_data.view { it -> "foo2: input_data: ${it}" }

    emit:
    foo_out = input_data.map{it -> "foo_out: ${it}"}
}

workflow bar {
    take:
    input_data

    main:
    input_data.view { it -> "bar: input_data: ${it}" }

    emit:
    bar_out = input_data.map{it -> "bar_out: ${it}"}
}

I am executing the code using either of these 2 commands below:

nextflow -quiet run example.nf --run_step true

or

nextflow -quiet run example.nf --run_step false

In both cases, the output is:

Missing workflow output parameter: foo_out

 -- Check script 'example.nf' at line: 9 or see '.nextflow.log' file for more details

If return is commented out like so:

    // return

then the output is as expected for that case:

$ nextflow -quiet run example.nf --run_step true
foo: input_data: a
foo2: input_data: a
bar: input_data: foo_out: a
foo: input_data: b
foo2: input_data: b
bar: input_data: foo_out: b
foo: input_data: c
foo2: input_data: c
bar: input_data: foo_out: c

or

nextflow -quiet run example.nf --run_step false
foo: input_data: a
foo2: input_data: a
foo2: input_data: b
foo: input_data: b
foo2: input_data: c
foo: input_data: c

But in both of these cases, of course, input_data.view { it -> "foo2: input_data: ${it}" } is executed, which is not what I want.

I want input_data.view { it -> "foo2: input_data: ${it}" } to not be executed, and also bar(foo.out.foo_out) to not be executed. This is the desired output:

nextflow -quiet run example.nf --run_step false
foo: input_data: a
foo: input_data: b
foo: input_data: c

My current workaround is to use control+c to stop Nextflow from the command line. I am looking for a programmatic way to do this.

Related:


Solution

  • If I follow correctly, you're looking to use a diagnostics flag to only emit inputs and not actually run anything. There are a few options to this approach:

    1. Using your example, I've changed the name of the run_step variable as I think something like diagnostics sounds like a more intuitive flag.
    #!/usr/bin/env nextflow
    nextflow.enable.dsl=2
    params.diagnostics = true
    
    workflow {
        input_ch = Channel.from("a", "b", "c")
        foo(input_ch)
        if (!params.diagnostics) {
            // Do not run this code and below:
            bar(foo.out.foo_out)
        }
    }
    
    workflow foo {
        take:
        input_data
    
        main:
        input_data.view { it -> "foo: input_data: ${it}" }
        
        if (params.diagnostics) {
          foo_out = channel.empty()
          return  
        }
    
        // Do not run this code and below:
        input_data.view { it -> "foo2: input_data: ${it}" }
    
        emit:
        foo_out = input_data.map{it -> "foo_out: ${it}"}
    }
    
    workflow bar {
        take:
        input_data
    
        main:
        input_data.view { it -> "bar: input_data: ${it}" }
    
        emit:
        bar_out = input_data.map{it -> "bar_out: ${it}"}
    }
    

    In this example, the return is only executed when the diagnostics flag is run. One of the errors was likely coming from when nextflow first checks if process input/outputs will exist before running. This was fixed by adding an empty channel when foo_out wasn't being created.

    Here is the output for the two options:

    āžœ  testing_nf nextflow -quiet run example.nf --diagnostics true
    foo: input_data: a
    foo: input_data: b
    foo: input_data: c
    āžœ  testing_nf nextflow -quiet run example.nf --diagnostics false
    foo: input_data: a
    foo2: input_data: a
    foo2: input_data: b
    foo: input_data: b
    foo: input_data: c
    foo2: input_data: c
    bar: input_data: foo_out: a
    bar: input_data: foo_out: b
    bar: input_data: foo_out: c
    
    1. Use when to only activate processes not in debug mode (docs here). To my knowledge this can only be used in processes and not workflow declarations. Unsure how easy this would be to implement on an existing workflow as I think you'd have to generate a lot of dummy empty channels within if statements like the above example.

    2. Use -stub flag (docs here). Meant for prototyping, but I've seen it used to emit environment and software versions rather than running the actual which I liked.