This page collects some recurring implementation patterns used in Nextflow applications. Feel free to contribute by opening a pull request in the GitHub repository at this link.
1. Basic patterns
1.1. Channel duplication
1.1.1. Problem
You need to you use the same channel as input in two or more processes.
1.1.2. Solution
In DSL2, you can just do it! The into operator is no longer needed.
1.1.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
process foo {
input: path x
script:
"""
echo your_command --input $x
"""
}
process bar {
input: path x
script:
"""
echo your_command --input $x
"""
}
workflow {
input_ch = Channel.fromPath("$baseDir/data/prots/*_?.fa")
foo(input_ch)
bar(input_ch)
}
1.1.4. Run it
Use the the following command to execute the example:
nextflow run patterns/channel-duplication.nf
2. Scatter executions
2.1. Process per file path
2.1.1. Problem
You need to execute a task for each file that matches a glob pattern.
2.1.2. Solution
Use the Channel.fromPath method to create a channel emitting all files matching the glob pattern. Then, use the channel as input of the process implementing your task.
2.1.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
process foo {
debug true
input:
path x
script:
"""
echo your_command --input $x
"""
}
workflow {
foo("$baseDir/data/reads/*_1.fq.gz")
}
2.1.4. Run it
Use the the following command to execute the example:
nextflow run patterns/process-per-file-path.nf
2.2. Process per file chunk
2.2.1. Problem
You need to split one or more input files into chunks and execute a task for each of them.
2.2.2. Solution
Use the splitText operator to split a file into chunks of a given size. Then use the resulting channel as input for the process implementing your task.
Chunks are kept in memory by default. When splitting big files, specify the parameter file: true to save the chunks into files. See the documentation for details.
|
Splitter for specific file formats are available, e.g. splitFasta and splitFastq.
2.2.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
params.infile = "$baseDir/data/poem.txt"
params.size = 5
process foo {
debug true
input:
file x
script:
"""
rev $x | rev
"""
}
workflow {
Channel.fromPath(params.infile) \
| splitText(by: params.size) \
| foo
}
2.2.4. Run it
Use the the following command to execute the example:
nextflow run patterns/process-per-file-chunk.nf
2.3. Process per file pairs
2.3.1. Problem
You need to process the files in a directory, grouping them by pairs.
2.3.2. Solution
Use the Channel.fromFilePairs method to create a channel that emits file pairs matching a glob pattern. The pattern must match a common prefix in the paired file names.
The matching files are emitted as tuples in which the first element is the grouping key of the matching files and the second element is the file pair itself.
2.3.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
process foo {
debug true
input:
tuple val(sampleId), file(reads)
script:
"""
echo your_command --sample $sampleId --reads $reads
"""
}
workflow {
Channel.fromFilePairs("$baseDir/data/reads/*_{1,2}.fq.gz", checkIfExists:true) \
| foo
}
2.3.4. Run it
nextflow run patterns/process-per-file-pairs.nf
2.3.5. Custom grouping strategy
When necessary, it is possible to define a custom grouping strategy. A common use case is for alignment BAM files (sample1.bam
) that come along with their index file. The difficulty is that the index is sometimes called sample1.bai
and sometimes sample1.bam.bai
depending on the software used. The following example can accommodate both cases.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
process foo {
debug true
tag "$sampleId"
input:
tuple val(sampleId), file(bam)
script:
"""
echo your_command --sample ${sampleId} --bam ${sampleId}.bam
"""
}
workflow {
Channel.fromFilePairs("$baseDir/data/alignment/*.{bam,bai}", checkIfExists:true) { file -> file.name.replaceAll(/.bam|.bai$/,'') } \
| foo
}
2.3.6. Run it
nextflow run patterns/process-per-file-pairs-custom.nf
2.4. Process per file range
2.4.1. Problem
You need to execute a task over two or more series of files having a common index range.
2.4.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
process foo {
debug true
tag "$sampleId"
input:
tuple val(sampleId), file(indels), file(snps)
"""
echo foo_command --this $indels --that $snps
"""
}
workflow {
Channel.from(1..23) \
| map { chr -> ["sample${chr}", file("/some/path/foo.${chr}.indels.vcf"), file("/other/path/foo.snvs.${chr}.vcf")] } \
| foo
}
2.4.4. Run it
nextflow run patterns/process-per-file-range.nf
2.5. Process per CSV record
2.5.1. Problem
You need to execute a task for each record in one or more CSV files.
2.5.3. Code
Given the file index.csv
with the following content:
sampleId | read1 | read2 |
---|---|---|
FC816RLABXX |
reads/110101_I315_FC816RLABXX_L1_HUMrutRGXDIAAPE_1.fq.gz |
reads/110101_I315_FC816RLABXX_L1_HUMrutRGXDIAAPE_2.fq.gz |
FC812MWABXX |
reads/110105_I186_FC812MWABXX_L8_HUMrutRGVDIABPE_1.fq.gz |
reads/110105_I186_FC812MWABXX_L8_HUMrutRGVDIABPE_2.fq.gz |
FC81DE8ABXX |
reads/110121_I288_FC81DE8ABXX_L3_HUMrutRGXDIAAPE_1.fq.gz |
reads/110121_I288_FC81DE8ABXX_L3_HUMrutRGXDIAAPE_2.fq.gz |
FC81DB5ABXX |
reads/110122_I329_FC81DB5ABXX_L6_HUMrutRGVDIAAPE_1.fq.gz |
reads/110122_I329_FC81DB5ABXX_L6_HUMrutRGVDIAAPE_2.fq.gz |
FC819P0ABXX |
reads/110128_I481_FC819P0ABXX_L5_HUMrutRGWDIAAPE_1.fq.gz |
reads/110128_I481_FC819P0ABXX_L5_HUMrutRGWDIAAPE_2.fq.gz |
This workflow parses the file and executes a process for each line:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
params.index = "$baseDir/data/index.csv"
process foo {
debug true
input:
tuple val(sampleId), file(read1), file(read2)
script:
"""
echo your_command --sample $sampleId --reads $read1 $read2
"""
}
workflow {
Channel.fromPath(params.index) \
| splitCsv(header:true) \
| map { row-> tuple(row.sampleId, file(row.read1), file(row.read2)) } \
| foo
}
Relative paths are resolved by the file function against the execution directory.
In practice, it is preferable to use absolute file paths.
|
2.5.4. Run it
Use the the following command to execute the example:
nextflow run patterns/process-per-csv-record.nf
2.6. Process per file output
2.6.1. Problem
A task in your workflow produces two or more files at time. A downstream task needs to process each of these files independently.
2.6.2. Solution
Use the flatten operator to transform the outputs of the upstream process to a channel that emits each file separately. Then use this channel as input for the downstream process.
2.6.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
process foo {
output:
path '*.txt'
script:
'''
echo Hello there! > file1.txt
echo What a beautiful day > file2.txt
echo I hope you are having fun! > file3.txt
'''
}
process bar {
debug true
input:
path x
script:
"""
cat $x
"""
}
workflow {
foo | flatten | bar
}
2.6.4. Run it
Use the the following command to execute the example:
nextflow run patterns/process-per-file-output.nf
3. Gather results
3.1. Process all outputs altogether
3.1.1. Problem
You need to process all the outputs of an upstream task altogether.
3.1.2. Solution
Use the collect operator to gather all the outputs produced by the upstream task and emit them as a single output. Then use the resulting channel as input for the downstream task.
3.1.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
process foo {
input:
path x
output:
path 'file.fq'
script:
"""
< $x zcat > file.fq
"""
}
process bar {
debug true
input:
path '*.fq'
script:
"""
cat *.fq | head -n 50
"""
}
workflow {
Channel.fromPath("$baseDir/data/reads/*_1.fq.gz", checkIfExists: true) \
| foo \
| collect \
| bar
}
3.1.4. Run it
Use the the following command to execute the example:
nextflow run patterns/process-collect.nf
3.2. Process outputs into groups
3.2.1. Problem
You need to process in the same batch all files that have a matching key in the file name.
3.2.2. Solution
Use the map operator to associate each file with a key extracted from the file name. Then chain the resulting channel with the groupTuple operator to group together all files that have a matching key. Finally, use the resulting channel as input for the process.
3.2.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
params.reads = "$baseDir/data/reads/*"
process foo {
debug true
input:
tuple val(key), file(samples)
script:
"""
echo your_command --batch $key --input $samples
"""
}
workflow {
Channel.fromPath(params.reads, checkIfExists:true) \
| map { file ->
def key = file.name.toString().tokenize('_').get(0)
return tuple(key, file)
} \
| groupTuple() \
| foo
}
3.2.4. Run it
nextflow run patterns/process-into-groups.nf
3.3. Collect outputs into a file
3.3.1. Problem
You need to concatenate into a single file all output files produced by an upstream process.
3.3.2. Solution
Use the collectFile operator to merge all the output files into a single file.
3.3.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
process foo {
input:
path x
output:
path 'file.fq'
script:
"""
< $x zcat > file.fq
"""
}
workflow {
Channel.fromPath("$baseDir/data/reads/*_1.fq.gz", checkIfExists: true) \
| foo \
| collectFile \
| view
}
3.3.4. Run it
Use the the following command to execute the example:
nextflow run patterns/collect-into-file.nf
4. Organize outputs
4.1. Store process outputs
4.1.1. Problem
You need to store the outputs of one or more processes into a directory structure of your choice.
4.1.2. Solution
Use the publishDir directive to define a custom directory where the process outputs should be saved.
4.1.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
params.reads = "$baseDir/data/reads/*{1,2}.fq.gz"
params.outdir = 'my-results'
process foo {
publishDir "$params.outdir/$sampleId"
input:
tuple val(sampleId), file(samples)
output:
path '*.fq'
script:
"""
< ${samples[0]} zcat > sample_1.fq
< ${samples[1]} zcat > sample_2.fq
"""
}
workflow {
Channel.fromFilePairs(params.reads, checkIfExists: true) \
| foo
}
4.1.4. Run it
Run the script with the following command:
nextflow run patterns/publish-process-outputs.nf
4.2. Store outputs matching a glob pattern
4.2.1. Problem
A task in your workflow creates many output files that are required by a downstream task. You want to store some of those files into separate directories depending on the file name.
4.2.2. Solution
Use two or more publishDir directives
to publish the output files into separate paths. For each directive specify a different glob pattern
using the option pattern
to store into each directory only the files that match the provided pattern.
4.2.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
params.reads = "$baseDir/data/reads/*_{1,2}.fq.gz"
params.outdir = 'my-results'
process foo {
publishDir "$params.outdir/$sampleId/counts", pattern: "*_counts.txt"
publishDir "$params.outdir/$sampleId/outlooks", pattern: '*_outlook.txt'
publishDir "$params.outdir/$sampleId/", pattern: '*.fq'
input:
tuple val(sampleId), file('sample1.fq.gz'), file('sample2.fq.gz')
output:
path "*"
script:
"""
< sample1.fq.gz zcat > sample1.fq
< sample2.fq.gz zcat > sample2.fq
awk '{s++}END{print s/4}' sample1.fq > sample1_counts.txt
awk '{s++}END{print s/4}' sample2.fq > sample2_counts.txt
head -n 50 sample1.fq > sample1_outlook.txt
head -n 50 sample2.fq > sample2_outlook.txt
"""
}
workflow {
Channel.fromFilePairs(params.reads, checkIfExists: true, flat: true) \
| foo
}
4.2.4. Run it
Run the script with the following command:
nextflow run patterns/publish-matching-glob.nf
4.3. Rename process outputs
4.3.1. Problem
You need to save the outputs of a process to a directory, giving each file a name of your choice.
4.3.2. Solution
The publishDir allows you to save the process outputs in a directory of your choice.
Specify the saveAs
parameter to give each file a name of your choice, providing
a custom rule as a closure.
4.3.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
process foo {
publishDir 'results', saveAs: { filename -> "foo_$filename" }
output:
path '*.txt'
'''
touch this.txt
touch that.txt
'''
}
workflow {
foo()
}
4.3.4. Run it
nextflow run patterns/publish-rename-outputs.nf
4.3.5. Save outputs in a sub-directory
The same pattern can be used to store specific files in separate directories depending on the actual name.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
process foo {
publishDir 'results', saveAs: { filename -> filename.endsWith(".zip") ? "zips/$filename" : filename }
output:
path '*'
'''
touch this.txt
touch that.zip
'''
}
workflow {
foo()
}
Relative paths are resolved against the publishDir store path. Use an absolute path
to store files in a directory outside the publishDir store path.
|
4.3.6. Run it
nextflow run patterns/publish-rename-outputs-subdirs.nf
5. Other
5.1. Get process work directory
5.1.1. Problem
A tool needs the explicit path of the current task work directory.
5.1.2. Solution
Use the $PWD
Bash variable or the pwd
command to retrieve the task working directory path.
Make sure to escape the $ variable placeholder when the command script is enclosed in double quote characters.
|
5.1.3. Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
process foo {
debug true
script:
"""
echo foo task path: \$PWD
"""
}
process bar {
debug true
script:
'''
echo bar task path: $PWD
'''
}
workflow {
foo()
bar()
}
5.1.4. Run it
The command run the script with an empty channel:
nextflow run patterns/process-get-workdir.nf
Use the following command to provide the same script some input files, that prevents the process from being executed:
nextflow run patterns/process-get-workdir.nf --inputs ../data/prots/\*
5.2. Ignore failing process
5.2.1. Problem
A task is expected to fail in some cases. You want to ignore the failure and continue the execution of the remaining tasks in the workflow.
5.2.2. Solution
Use the process directive errorStrategy 'ignore'
to ignore the error condition.
5.2.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
process foo {
errorStrategy 'ignore'
script:
'''
echo This is going to fail!
exit 1
'''
}
process bar {
script:
'''
echo OK
'''
}
workflow {
foo()
bar()
}
5.2.4. Run it
Run the script with the following command:
nextflow run patterns/ignore-failing-process.nf
5.3. State dependency
5.3.1. Problem
You need to synchronize the execution of two processes for which there isn’t a data dependency, so that process bar
is executed after the completion of process foo
.
5.3.2. Solution
Add an output channel to process foo
that produces a ready signal. Then pass this channel as input to process bar
in order to trigger its execution when foo
completes.
5.3.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
process foo {
output:
val true
script:
"""
echo your_command_here
"""
}
process bar {
input:
val ready
path fq
script:
"""
echo other_commad_here --reads $fq
"""
}
workflow {
reads_ch = Channel.fromPath("$baseDir/data/reads/11010*.fq.gz", checkIfExists:true)
foo()
bar(foo.out, reads_ch)
}
6. Advanced patterns
6.1. Conditional resources definition
6.1.1. Problem
A task in your workflow needs to use some amount of computing resources (e.g. memory) that depends on the size or the name of one or more input files.
6.1.2. Solution
Declare the resource requirements (memory
, cpus
, etc.)
in a dynamic manner using a closure.
The closure computes the required amount of resources using the file
attributes (e.g. size
) of the inputs declared in the process
definition.
6.1.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
process foo {
memory { reads.size() < 70.KB ? 1.GB : 5.GB }
input:
path reads
"""
echo your_command_here --in ${reads} --mem=${task.memory.giga}
"""
}
workflow {
Channel.fromPath("$baseDir/data/reads/*_1.fq.gz", checkIfExists:true) \
| foo
}
6.1.4. Run it
nextflow run patterns/conditional-resources.nf
6.2. Conditional process executions
6.2.1. Problem
One of two different tasks should be executed based on some condition, and a third task should process the results of the selected task.
6.2.2. Solution
Simply execute either process using if/else
statements on the condition.
Define a channel, e.g. omega_ch
, which emits the output of the selected process
in each case. Then, execute the third process with this output channel.
Or, use a ternary expression and a pipe to keep things short and sweet.
6.2.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
params.flag = false
process foo {
output:
path 'x.txt'
script:
'''
echo foo > x.txt
'''
}
process bar {
output:
path 'x.txt'
script:
'''
echo bar > x.txt
'''
}
process omega {
debug true
input:
path x
script:
"""
cat $x
"""
}
workflow {
// the long way
if ( params.flag ) {
bar()
omega_ch = bar.out
}
else {
foo()
omega_ch = foo.out
}
omega(omega_ch)
// the short way
(params.flag ? bar : foo) | omega
}
6.2.4. Run it
Use the the following command to execute the example:
nextflow run patterns/conditional-process.nf
The processes foo
and omega
are executed. Run the same command
with the --flag
command line option.
nextflow run patterns/conditional-process.nf --flag
This time the processes bar
and omega
are executed.
6.2.5. Alternative solution
Create an input channel for each process that is either populated with data or an empty channel. Each process will execute only if its input channel has data.
Then use the mix operator to create a new channel that emits the outputs produced by the two processes, and use it as the input for the third process.
6.2.6. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
params.flag = false
process foo {
input:
val x
output:
path 'x.txt'
script:
"""
echo $x > x.txt
"""
}
process bar {
input:
val(b)
output:
path 'x.txt'
script:
"""
echo $b > x.txt
"""
}
process omega {
debug true
input:
path x
script:
"""
cat $x
"""
}
workflow {
(foo_ch, bar_ch) = params.flag
? [ Channel.empty(), Channel.from(1,2,3) ]
: [ Channel.from(4,5,6), Channel.empty() ]
foo(foo_ch)
bar(bar_ch)
foo.out | mix(bar.out) | omega
}
6.2.7. Run it
nextflow run patterns/conditional-process2.nf
6.3. Skip process execution
6.3.1. Problem
You have two sequential tasks in your workflow. When an optional flag is specified, the first task should be skipped and its input(s) should be processed by the second task.
6.3.2. Solution
Use an empty channel, created in a conditional expression, to skip the first process execution when an optional parameter is specified.
Then, define the second process input as a mix of the first process output (when executed) and the input channel.
6.3.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
params.skip = false
params.input = "$baseDir/data/reads/sample.fq.gz"
process foo {
input:
path x
output:
file('*.fastq')
script:
"""
< $x zcat > ${x.simpleName}.fastq
"""
}
process bar {
debug true
input:
path x
script:
"""
echo your_command --input $x
"""
}
workflow {
input_ch = Channel.fromPath(params.input)
(foo_ch, bar_ch) = params.skip
? [Channel.empty(), input_ch]
: [input_ch, Channel.empty()]
foo_ch | foo | mix(bar_ch) | bar
}
6.3.4. Run it
Use the the following command to execute the example:
nextflow run patterns/skip-process-execution.nf
The processes foo
and bar
are executed. Run the same command
with the --skip
command line option:
nextflow run patterns/skip-process-execution.nf --skip
This time only the bar
process is executed.
= Feedback loop
6.3.5. Problem
You need to repeat a process or workflow multiple times, using the output from the previous iteration as the input to the next iteration.
6.3.6. Solution
This feature is experimental and may change in the future. |
Use the recurse
method on a process or workflow to execute it iteratively.
In order to use this feature, the process or workflow must have identical input
and output definitions, and any initial values must be Groovy values or
value channels — queue channels are not supported (yet).
You can use the times
operator to perform a fixed number of iterations, or the
until operator to iterate until
some condition is satisfied.
6.3.7. Code
For an iterative process:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
nextflow.preview.recursion=true
params.data = "$baseDir/data/hello.txt"
process foo {
input:
path 'input.txt'
output:
path 'result.txt'
script:
"""
cat input.txt > result.txt
echo "Task ${task.index} was here" >> result.txt
"""
}
workflow {
// perform a fixed number of iterations
foo
.recurse(file(params.data))
.times(10)
// iterate until some condition is satisfied
foo
.recurse(file(params.data))
.until { it -> it.size() > 100 }
foo
.out
.view(it -> it.text)
}
For an iterative workflow:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
nextflow.preview.recursion=true
params.input = "$baseDir/data/hello.txt"
process tick {
input:
path 'input.txt'
output:
path 'result.txt'
script:
"""
cat input.txt > result.txt
echo "Task ${task.index} : tick" >> result.txt
"""
}
process tock {
input:
path 'input.txt'
output:
path 'result.txt'
script:
"""
cat input.txt > result.txt
echo "Task ${task.index} : tock" >> result.txt
"""
}
workflow clock {
take: infile
main:
infile | tick | tock
emit:
tock.out
}
workflow {
clock
.recurse(file(params.input))
.until { it -> it.size() > 100 }
clock
.out
.view(it -> it.text)
}
6.3.8. Run it
Use the the following command to execute the example:
# iterative process
nextflow run patterns/feedback-loop-process.nf
# iterative workflow
nextflow run patterns/feedback-loop-workflow.nf
6.4. Optional input
6.4.1. Problem
One or more processes have an optional input file.
6.4.2. Solution
Use a special file name to mark the absence of the file parameter.
6.4.3. Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
params.inputs = "$baseDir/data/prots/*{1,2,3}.fa"
params.filter = 'NO_FILE'
process foo {
debug true
input:
path seq
path opt
script:
def filter = opt.name != 'NO_FILE' ? "--filter $opt" : ''
"""
echo your_commad --input $seq $filter
"""
}
workflow {
prots_ch = Channel.fromPath(params.inputs, checkIfExists:true)
opt_file = file(params.filter)
foo(prots_ch, opt_file)
}
6.4.4. Run it
Run the script with the following command:
nextflow run patterns/optional-input.nf
Run the same script providing an optional file input:
nextflow run patterns/optional-input.nf --filter foo.txt
6.5. Optional output
6.5.1. Problem
A task in your workflow is expected to not create an output file in some circumstances.
6.5.2. Solution
Declare such output as an optional
file.
6.5.3. Code
1
2
3
4
5
6
7
8
9
process foo {
output:
path 'foo.txt', optional: true
script:
'''
your_command
'''
}
6.5.4. Run it
Use the the following command to execute the example:
nextflow run patterns/optional-output.nf
6.6. Execute when empty
6.6.1. Problem
You need to execute a process if a channel is empty.
6.6.2. Solution
Use the ifEmpty operator to emit a marker value to trigger the execution of the process.
6.6.3. Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
params.inputs = ''
process foo {
debug true
input:
val x
when:
x == 'EMPTY'
script:
'''
echo hello
'''
}
workflow {
reads_ch = params.inputs
? Channel.fromPath(params.inputs, checkIfExists:true)
: Channel.empty()
reads_ch \
| ifEmpty { 'EMPTY' } \
| foo
}
6.6.4. Run it
Use the following command to run the script with an empty channel:
nextflow run patterns/process-when-empty.nf
Use the following command to provide the same script some input files, which prevents the process from being executed:
nextflow run patterns/process-when-empty.nf --inputs ../data/prots/\*