diff --git a/.devcontainer/codespaces-dev/devcontainer.json b/.devcontainer/codespaces-dev/devcontainer.json index d8a3a3bc9a..5474a4cc1b 100644 --- a/.devcontainer/codespaces-dev/devcontainer.json +++ b/.devcontainer/codespaces-dev/devcontainer.json @@ -32,7 +32,7 @@ // Nextflow installation version "NXF_HOME": "/workspaces/.nextflow", "NXF_EDGE": "0", - "NXF_VER": "25.04.3", + "NXF_VER": "25.10.0", // Other env vars "HOST_PROJECT_PATH": "/workspaces/training", "SHELL": "/bin/bash" // Ush bash diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index be11210961..d291aa6184 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,7 +12,7 @@ // Nextflow installation version "NXF_HOME": "/workspaces/.nextflow", "NXF_EDGE": "0", - "NXF_VER": "25.04.3", + "NXF_VER": "25.10.0", // Other env vars "HOST_PROJECT_PATH": "/workspaces/training", "SHELL": "/bin/bash" // Ush bash diff --git a/.devcontainer/local-dev/devcontainer.json b/.devcontainer/local-dev/devcontainer.json index 750dbfb341..c967ee7179 100644 --- a/.devcontainer/local-dev/devcontainer.json +++ b/.devcontainer/local-dev/devcontainer.json @@ -33,7 +33,7 @@ // Nextflow installation version "NXF_HOME": "/workspaces/training/.nextflow", "NXF_EDGE": "0", - "NXF_VER": "25.04.3", + "NXF_VER": "25.10.0", // Other env vars "HOST_PROJECT_PATH": "/workspaces/training", "SHELL": "/bin/bash" // Ush bash diff --git a/docs/hello_nextflow/01_hello_world.md b/docs/hello_nextflow/01_hello_world.md index a9403ceea0..f7aefaeeaf 100644 --- a/docs/hello_nextflow/01_hello_world.md +++ b/docs/hello_nextflow/01_hello_world.md @@ -212,7 +212,7 @@ nextflow run hello-world.nf You console output should look something like this: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-world.nf` [goofy_torvalds] DSL2 - revision: c33d41f479 @@ -305,7 +305,7 @@ Learn how to manage your workflow executions conveniently. Knowing how to launch workflows and retrieve outputs is great, but you'll quickly find there are a few other aspects of workflow management that will make your life easier, especially if you're developing your own workflows. -Here we show you how to use the `publishDir` directive to store in an output folder all the main results from your pipeline run, the `resume` feature for when you need to re-launch the same workflow, and how to delete older work directories with `nextflow clean`. +Here we show you how to use workflow outputs to store in an output folder all the main results from your pipeline run, the `resume` feature for when you need to re-launch the same workflow, and how to delete older work directories with `nextflow clean`. ### 3.1. Publish outputs @@ -314,34 +314,76 @@ This is done on purpose; Nextflow is in control of this directory and we are not However, that makes it inconvenient to retrieve outputs that we care about. -Fortunately, Nextflow provides a way to manage this more conveniently, called the `publishDir` directive, which acts at the process level. -This directive tells Nextflow to publish the output(s) of the process to a designated output directory. By default, the outputs are published as symbolic links from the `work` directory. -It allows us to retrieve the desired output file without having to dig down into the work directory. +Fortunately, Nextflow provides a way to manage this more conveniently using **workflow outputs**. +Workflow outputs allow you to declare which outputs from your workflow should be published to a designated output directory. +This approach centralizes output publishing at the workflow level rather than at individual processes. -#### 3.1.1. Add a `publishDir` directive to the `sayHello` process +#### 3.1.1. Add workflow outputs to publish results -In the workflow script file `hello-world.nf`, make the following code modification: +In the workflow script file `hello-world.nf`, make the following code modification to add a `publish:` section to the workflow and an `output` block: === "After" - ```groovy title="hello-world.nf" linenums="6" hl_lines="3" - process sayHello { + ```groovy title="hello-world.nf" linenums="1" hl_lines="16-28" + #!/usr/bin/env nextflow - publishDir 'results', mode: 'copy' + process sayHello { output: path 'output.txt' + + script: + """ + echo 'Hello World!' > output.txt + """ + } + + workflow { + + main: + // emit a greeting + sayHello() + + publish: + greetings = sayHello.out + } + + output { + greetings { + path '.' + } + } ``` === "Before" - ```groovy title="hello-world.nf" linenums="6" + ```groovy title="hello-world.nf" linenums="1" hl_lines="17-18" + #!/usr/bin/env nextflow + process sayHello { output: path 'output.txt' + + script: + """ + echo 'Hello World!' > output.txt + """ + } + + workflow { + + // emit a greeting + sayHello() + } ``` +Let's break down what we added: + +1. **`main:` section in the workflow**: When using `publish:`, we need to explicitly mark the main workflow logic with `main:` +2. **`publish:` section in the workflow**: This assigns the output channel from `sayHello()` to a named output called `greetings` +3. **`output` block**: This declares how the `greetings` output should be published. The `path '.'` means files will be published to the root of the output directory (which defaults to `results`) + #### 3.1.2. Run the workflow again Now run the modified workflow script: @@ -353,7 +395,7 @@ nextflow run hello-world.nf The log output should look very familiar: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-world.nf` [jovial_mayer] DSL2 - revision: 35bd3425e5 @@ -366,14 +408,50 @@ Our `output.txt` file is in this directory. If you check the contents it should match the output in the work subdirectory. This is how we publish results files outside of the working directories conveniently. -When you're dealing with very large files that you don't need to retain for long, you may prefer to set the `publishDir` directive to make a symbolic link to the file instead of copying it. -However, if you delete the work directory as part of a cleanup operation, you will lose access to the file, so always make sure you have actual copies of everything you care about before deleting anything. +By default, Nextflow creates symbolic links from the output directory to files in the work directory. +This is efficient because it doesn't duplicate files, but it means if you delete the work directory, you'll lose access to the outputs. -!!! note +In this training environment, we've configured Nextflow to copy files instead of creating symlinks, which is safer for learning purposes. +You can configure this behavior in your own pipelines using the `workflow.output.mode` setting (covered later in this training). + +!!! tip + + You can change the output directory name by using the `-output-dir` command-line option: + ```bash + nextflow run hello-world.nf -output-dir my-results + ``` + +!!! note "Understanding workflow outputs vs. publishDir (legacy syntax)" + + Before workflow outputs were introduced, Nextflow used a different approach to publishing results called the `publishDir` directive. + This directive was applied at the process level and looked like this: + + ```groovy + process sayHello { - A newer syntax option documented [here](https://www.nextflow.io/docs/latest/workflow.html#publishing-outputs) has been proposed to make it possible to declare and publish workflow-level outputs. - This will eventually make using `publishDir` at the process level redundant for completed pipelines. - However, we expect that `publishDir` will still remain very useful during pipeline development. + publishDir 'results', mode: 'copy' + + output: + path 'output.txt' + + script: + """ + echo 'Hello World!' > output.txt + """ + } + ``` + + The `publishDir` directive tells Nextflow to copy (or symlink) the process outputs to the specified directory. + You can set options like `mode: 'copy'` to control how files are published. + + The modern **workflow outputs** approach you just learned provides several advantages over `publishDir`: + + - **Centralized**: All publishing logic is in one place at the workflow level, rather than scattered across individual process definitions + - **Flexible**: You can easily control what gets published from the workflow level without modifying process code + - **Cleaner modules**: Processes don't need to know where their outputs should be published, making them more reusable + + The `publishDir` directive is still supported but is being phased out in favor of workflow outputs. + You will encounter `publishDir` frequently when reading existing Nextflow pipelines and working with nf-core modules, so it's important to understand both approaches. ### 3.2. Re-launch a workflow with `-resume` @@ -397,7 +475,7 @@ nextflow run hello-world.nf -resume The console output should look similar. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-world.nf` [golden_cantor] DSL2 - revision: 35bd3425e5 @@ -411,7 +489,7 @@ Nextflow is literally pointing you to the previous execution and saying "I alrea !!! note - When your re-run a pipeline with `resume`, Nextflow does not overwrite any files written to a `publishDir` directory by any process call that was previously run successfully. + When you re-run a pipeline with `resume`, Nextflow does not overwrite any files written to the output directory by any process call that was previously run successfully. ### 3.3. Delete older work directories @@ -454,7 +532,8 @@ Removed /workspaces/training/hello-nextflow/work/a3/7be2fad5e71e5f49998f795677fd Deleting work subdirectories from past runs removes them from Nextflow's cache and deletes any outputs that were stored in those directories. That means it breaks Nextflow's ability to resume execution without re-running the corresponding processes. - You are responsible for saving any outputs that you care about or plan to rely on! If you're using the `publishDir` directive for that purpose, make sure to use the `copy` mode, not the `symlink` mode. + You are responsible for saving any outputs that you care about or plan to rely on by publishing them to the output directory! + Make sure your workflow outputs use the `copy` mode (the default), not the `symlink` mode. ### Takeaway @@ -489,11 +568,9 @@ In the process block, make the following code change: === "After" - ```groovy title="hello-world.nf" linenums="6" hl_lines="5 6" + ```groovy title="hello-world.nf" linenums="3" hl_lines="3 4" process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -503,11 +580,9 @@ In the process block, make the following code change: === "Before" - ```groovy title="hello-world.nf" linenums="6" + ```groovy title="hello-world.nf" linenums="3" process sayHello { - publishDir 'results', mode: 'copy' - output: path 'output.txt' ``` @@ -586,7 +661,7 @@ nextflow run hello-world.nf --greeting 'Bonjour le monde!' If you made all three edits correctly, you should get another successful execution: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-world.nf` [elated_lavoisier] DSL2 - revision: 7c031b42ea @@ -639,7 +714,7 @@ nextflow run hello-world.nf The console output should look the same. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-world.nf` [determined_edison] DSL2 - revision: 3539118582 @@ -668,7 +743,7 @@ nextflow run hello-world.nf --greeting 'Konnichiwa!' The console output should look the same. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-world.nf` [elegant_faraday] DSL2 - revision: 3539118582 diff --git a/docs/hello_nextflow/02_hello_channels.md b/docs/hello_nextflow/02_hello_channels.md index c8c5e179bf..63c5417aca 100644 --- a/docs/hello_nextflow/02_hello_channels.md +++ b/docs/hello_nextflow/02_hello_channels.md @@ -37,7 +37,7 @@ nextflow run hello-channels.nf --greeting 'Hello Channels!' ``` ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [insane_lichterman] DSL2 - revision: c33d41f479 @@ -45,7 +45,7 @@ executor > local (1) [86/9efa08] sayHello | 1 of 1 ✔ ``` -As previously, you will find the output file named `output.txt` in the `results` directory (specified by the `publishDir` directive). +As previously, you will find the output file named `output.txt` in the `results` directory (specified by the workflow outputs). ```console title="results/output.txt" linenums="1" Hello Channels! @@ -81,9 +81,11 @@ In the workflow block, add the channel factory code: === "After" - ```groovy title="hello-channels.nf" linenums="27" hl_lines="3 4" + ```groovy title="hello-channels.nf" linenums="27" hl_lines="5 6" workflow { + main: + // create a channel for inputs greeting_ch = Channel.of('Hello Channels!') @@ -97,9 +99,9 @@ In the workflow block, add the channel factory code: ```groovy title="hello-channels.nf" linenums="27" workflow { + main: // emit a greeting sayHello(params.greeting) - } ``` This is not yet functional since we haven't yet switched the input to the process call. @@ -112,14 +114,19 @@ In the workflow block, make the following code change: === "After" - ```groovy title="hello-channels.nf" linenums="27" hl_lines="7" + ```groovy title="hello-channels.nf" linenums="27" hl_lines="9" workflow { + main: + // create a channel for inputs greeting_ch = Channel.of('Hello Channels!') // emit a greeting sayHello(greeting_ch) + + publish: + greetings = sayHello.out } ``` @@ -128,11 +135,16 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="27" workflow { + main: + // create a channel for inputs greeting_ch = Channel.of('Hello Channels!') // emit a greeting sayHello(params.greeting) + + publish: + greetings = sayHello.out } ``` @@ -151,7 +163,7 @@ nextflow run hello-channels.nf If you made both edits correctly, you should get another successful execution: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [nice_heisenberg] DSL2 - revision: 41b4aeb7e9 @@ -221,7 +233,7 @@ nextflow run hello-channels.nf It certainly seems to run just fine: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [suspicious_lamport] DSL2 - revision: 778deadaea @@ -246,7 +258,7 @@ nextflow run hello-channels.nf -ansi-log false This time we see all three process runs and their associated work subdirectories listed in the output: ```console title="Output" linenums="1" -N E X T F L O W ~ version 25.04.3 +N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [pensive_poitras] DSL2 - revision: 778deadaea [76/f61695] Submitted process > sayHello (1) [6e/d12e35] Submitted process > sayHello (3) @@ -282,7 +294,7 @@ You may recall that we hardcoded the output file name for the `sayHello` process You can check the work subdirectories for each of the three processes; each of them contains a file called `output.txt` as expected. As long as the output files stay there, isolated from the other processes, that is okay. -But when the `publishDir` directive copies each of them to the same `results` directory, whichever got copied there first gets overwritten by the next one, and so on. +But when the workflow outputs publish each of them to the same `results` directory, whichever got published there first gets overwritten by the next one, and so on. ### 2.2. Ensure the output file names will be unique @@ -299,11 +311,9 @@ In the process block, make the following code changes: === "After" - ```groovy title="hello-channels.nf" linenums="6" hl_lines="9 13" + ```groovy title="hello-channels.nf" linenums="6" hl_lines="7 11" process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -322,8 +332,6 @@ In the process block, make the following code changes: ```groovy title="hello-channels.nf" linenums="6" process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -356,7 +364,7 @@ nextflow run hello-channels.nf Reverting back to the summary view, the output looks like this again: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [astonishing_bell] DSL2 - revision: f57ff44a69 @@ -480,7 +488,7 @@ nextflow run hello-channels.nf Oh no! Nextflow throws an error that starts like this: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [friendly_koch] DSL2 - revision: 97256837a7 @@ -518,7 +526,7 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="31" hl_lines="3" // create a channel for inputs greeting_ch = Channel.of(greetings_array) - .flatten() + .flatten() ``` === "Before" @@ -543,9 +551,9 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="31" hl_lines="3-5" // create a channel for inputs greeting_ch = Channel.of(greetings_array) - .view { greeting -> "Before flatten: $greeting" } - .flatten() - .view { greeting -> "After flatten: $greeting" } + .view { greeting -> "Before flatten: $greeting" } + .flatten() + .view { greeting -> "After flatten: $greeting" } ``` === "Before" @@ -553,7 +561,7 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="31" // create a channel for inputs greeting_ch = Channel.of(greetings_array) - .flatten() + .flatten() ``` We are using an operator _closure_ here - the curly brackets. @@ -582,7 +590,7 @@ nextflow run hello-channels.nf This time it works AND gives us the additional insight into what the contents of the channel look like before and after we run the `flatten()` operator: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [tiny_elion] DSL2 - revision: 1d834f23d2 @@ -606,7 +614,7 @@ Importantly, this means each item can now be processed separately by the workflo ```groovy title="hello-channels.nf" linenums="31" // create a channel for inputs greeting_ch = Channel.of(greetings_array) - .flatten() + .flatten() ``` We left them in the `hello-channels-3.nf` solution file for reference purposes. @@ -685,7 +693,7 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="31" // create a channel for inputs greeting_ch = Channel.of(greetings_array) - .flatten() + .flatten() ``` #### 4.1.3. Run the workflow @@ -699,7 +707,7 @@ nextflow run hello-channels.nf Oh no, it doesn't work. Here's the start of the console output and error message: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [adoring_bhabha] DSL2 - revision: 8ce25edc39 @@ -740,9 +748,9 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="31" hl_lines="3-5" // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) - .view { csv -> "Before splitCsv: $csv" } - .splitCsv() - .view { csv -> "After splitCsv: $csv" } + .view { csv -> "Before splitCsv: $csv" } + .splitCsv() + .view { csv -> "After splitCsv: $csv" } ``` === "Before" @@ -766,7 +774,7 @@ nextflow run hello-channels.nf Interestingly, this fails too, but with a different error. The console output and error starts like this: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [stoic_ride] DSL2 - revision: a0e5de507e @@ -823,11 +831,11 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="31" hl_lines="6-8" // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) - .view { csv -> "Before splitCsv: $csv" } - .splitCsv() - .view { csv -> "After splitCsv: $csv" } - .map { item -> item[0] } - .view { csv -> "After map: $csv" } + .view { csv -> "Before splitCsv: $csv" } + .splitCsv() + .view { csv -> "After splitCsv: $csv" } + .map { item -> item[0] } + .view { csv -> "After map: $csv" } ``` === "Before" @@ -835,9 +843,9 @@ In the workflow block, make the following code change: ```groovy title="hello-channels.nf" linenums="31" // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) - .view { csv -> "Before splitCsv: $csv" } - .splitCsv() - .view { csv -> "After splitCsv: $csv" } + .view { csv -> "Before splitCsv: $csv" } + .splitCsv() + .view { csv -> "After splitCsv: $csv" } ``` @@ -854,7 +862,7 @@ nextflow run hello-channels.nf This time it should run without error. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-channels.nf` [tiny_heisenberg] DSL2 - revision: 845b471427 diff --git a/docs/hello_nextflow/03_hello_workflow.md b/docs/hello_nextflow/03_hello_workflow.md index d5bcd340cd..8efa51564b 100644 --- a/docs/hello_nextflow/03_hello_workflow.md +++ b/docs/hello_nextflow/03_hello_workflow.md @@ -42,7 +42,7 @@ nextflow run hello-workflow.nf ``` ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-workflow.nf` [stupefied_sammet] DSL2 - revision: b9e466930b @@ -50,7 +50,7 @@ executor > local (3) [2a/324ce6] sayHello (3) | 3 of 3 ✔ ``` -As previously, you will find the output files in the `results` directory (specified by the `publishDir` directive). +As previously, you will find the output files in the `results` directory (specified by the workflow outputs). ```console title="Directory contents" results @@ -112,8 +112,6 @@ Add the following process definition to the workflow script: */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -142,21 +140,25 @@ In the workflow block, make the following code change: === "After" - ```groovy title="hello-workflow.nf" linenums="53" hl_lines="4 5" + ```groovy title="hello-workflow.nf" linenums="58" hl_lines="4 5" // emit a greeting sayHello(greeting_ch) // convert the greeting to uppercase convertToUpper() - } + + publish: + greetings = sayHello.out ``` === "Before" - ```groovy title="hello-workflow.nf" linenums="53" + ```groovy title="hello-workflow.nf" linenums="58" // emit a greeting sayHello(greeting_ch) - } + + publish: + greetings = sayHello.out ``` This is not yet functional because we have not specified what should be input to the `convertToUpper()` process. @@ -172,18 +174,28 @@ In the workflow block, make the following code change: === "After" - ```groovy title="hello-workflow.nf" linenums="56" hl_lines="2" + ```groovy title="hello-workflow.nf" linenums="58" hl_lines="5" + // emit a greeting + sayHello(greeting_ch) + // convert the greeting to uppercase convertToUpper(sayHello.out) - } + + publish: + greetings = sayHello.out ``` === "Before" - ```groovy title="hello-workflow.nf" linenums="56" + ```groovy title="hello-workflow.nf" linenums="58" hl_lines="5" + // emit a greeting + sayHello(greeting_ch) + // convert the greeting to uppercase convertToUpper() - } + + publish: + greetings = sayHello.out ``` For a simple case like this (one output to one input), that's all we need to do to connect two processes! @@ -199,7 +211,7 @@ nextflow run hello-workflow.nf -resume You should see the following output: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-workflow.nf` [disturbed_darwin] DSL2 - revision: 4e252c048f @@ -224,7 +236,7 @@ The output of the first process is in there because Nextflow staged it there in However, it is actually a symbolic link pointing to the the original file in the subdirectory of the first process call. By default, when running on a single machine as we're doing here, Nextflow uses symbolic links rather than copies to stage input and intermediate files. -You'll also find the final outputs in the `results` directory since we used the `publishDir` directive in the second process too. +You'll also find the final outputs in the `results` directory, as we'll configure next. ```console title="Directory contents" results @@ -241,6 +253,63 @@ Nextflow did the hard work of handling individual input and output files and pas This is one of the reasons Nextflow channels are so powerful: they take care of the busywork involved in connecting workflow steps together. +### 1.6. Update workflow outputs to publish both processes + +Now let's update our workflow outputs to publish the results from both processes. + +In the workflow and output blocks, make the following code change: + +=== "After" + + ```groovy title="hello-workflow.nf" linenums="53" hl_lines="5 9 16-18" + // emit a greeting + sayHello(greeting_ch) + + // convert the greeting to uppercase + convertToUpper(sayHello.out) + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + } + + output { + greetings { + path '.' + } + uppercase { + path '.' + } + } + ``` + +=== "Before" + + ```groovy title="hello-workflow.nf" linenums="53" hl_lines="5" + // emit a greeting + sayHello(greeting_ch) + + // convert the greeting to uppercase + convertToUpper(sayHello.out) + + publish: + greetings = sayHello.out + } + + output { + greetings { + path '.' + } + } + ``` + +Here we made several changes: + +1. **Added the second process output to the `publish:` section**: Added `uppercase = convertToUpper.out` to publish the uppercase greetings alongside the original greetings. +2. **Declared both outputs in the `output` block**: Added an `uppercase` section to specify that the uppercase files should also be published to the root of the output directory. + +Now when you run the workflow, both the original greetings and the uppercase versions will be published to the `results` directory. + ### Takeaway You know how to add a second step that takes the output of the first step as input. @@ -297,8 +366,6 @@ Add the following process definition to the workflow script: */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: ??? @@ -398,7 +465,10 @@ In the workflow block, make the following code change: // collect all the greetings into one file collectGreetings(convertToUpper.out) - } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` === "Before" @@ -406,7 +476,10 @@ In the workflow block, make the following code change: ```groovy title="hello-workflow.nf" linenums="75" // convert the greeting to uppercase convertToUpper(sayHello.out) - } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` This connects the output of `convertToUpper()` to the input of `collectGreetings()`. @@ -422,7 +495,7 @@ nextflow run hello-workflow.nf -resume It runs successfully, including the third step: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-workflow.nf` [mad_gilbert] DSL2 - revision: 6acfd5e28d @@ -465,7 +538,10 @@ In the workflow block, make the following code change: ```groovy title="hello-workflow.nf" linenums="78" hl_lines="2" // collect all the greetings into one file collectGreetings(convertToUpper.out.collect()) - } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` === "Before" @@ -473,7 +549,10 @@ In the workflow block, make the following code change: ```groovy title="hello-workflow.nf" linenums="78" // collect all the greetings into one file collectGreetings(convertToUpper.out) - } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` #### 2.4.2. Add some `view()` statements @@ -489,7 +568,10 @@ Let's also include a couple of `view()` statements to visualize the before and a // optional view statements convertToUpper.out.view { greeting -> "Before collect: $greeting" } convertToUpper.out.collect().view { greeting -> "After collect: $greeting" } - } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` === "Before" @@ -497,7 +579,10 @@ Let's also include a couple of `view()` statements to visualize the before and a ```groovy title="hello-workflow.nf" linenums="78" // collect all the greetings into one file collectGreetings(convertToUpper.out.collect()) - } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` The `view()` statements can go anywhere you want; we put them after the call for readability. @@ -513,7 +598,7 @@ nextflow run hello-workflow.nf -resume It runs successfully, although the log output may look a little messier than this (we cleaned it up for readability). ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-workflow.nf` [soggy_franklin] DSL2 - revision: bc8e1b2726 @@ -669,6 +754,10 @@ In the workflow block, make the following code change: ```groovy title="hello-workflow.nf" linenums="80" hl_lines="2" // collect all the greetings into one file collectGreetings(convertToUpper.out.collect(), params.batch) + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` === "Before" @@ -676,6 +765,10 @@ In the workflow block, make the following code change: ```groovy title="hello-workflow.nf" linenums="80" // collect all the greetings into one file collectGreetings(convertToUpper.out.collect()) + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` !!! warning @@ -693,7 +786,7 @@ nextflow run hello-workflow.nf -resume --batch trio It runs successfully: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-workflow.nf` [confident_rutherford] DSL2 - revision: bc58af409c @@ -801,25 +894,32 @@ In the process block, make the following code change: The `emit:` tags are optional, and we could have added a tag to only one of the outputs. But as the saying goes, why not both? -### 4.2. Report the output at the end of the workflow +### 4.2. Report the output and update publishing Now that we have two outputs coming out of the `collectGreetings` process, the `collectGreetings.out` output contains two channels: - `collectGreetings.out.outfile` contains the final output file - `collectGreetings.out.count` contains the count of greetings -We could send either or both of these to another process for further work. However, in the interest of wrapping this up, we're just going to use `view()` to demonstrate that we can access and report the count of greetings. +We could send either or both of these to another process for further work. Here, we're going to use `view()` to demonstrate that we can access and report the count of greetings. + +We also need to update the `publish:` block to publish the collected output file. Since `collectGreetings` now has multiple outputs, we must use the named output `collectGreetings.out.outfile` to specify which output we want to publish. In the workflow block, make the following code change: === "After" - ```groovy title="hello-workflow.nf" linenums="82" hl_lines="4 5" + ```groovy title="hello-workflow.nf" linenums="82" hl_lines="4 5 10" // collect all the greetings into one file collectGreetings(convertToUpper.out.collect(), params.batch) // emit a message about the size of the batch collectGreetings.out.count.view { num_greetings -> "There were $num_greetings greetings in this batch" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out.outfile ``` === "Before" @@ -827,6 +927,10 @@ In the workflow block, make the following code change: ```groovy title="hello-workflow.nf" linenums="82" // collect all the greetings into one file collectGreetings(convertToUpper.out.collect(), params.batch) + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out ``` !!! note @@ -844,7 +948,7 @@ nextflow run hello-workflow.nf -resume --batch trio This runs successfully: ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-workflow.nf` [evil_sinoussi] DSL2 - revision: eeca64cdb1 diff --git a/docs/hello_nextflow/04_hello_modules.md b/docs/hello_nextflow/04_hello_modules.md index cc2476a6b4..d6af375fc4 100644 --- a/docs/hello_nextflow/04_hello_modules.md +++ b/docs/hello_nextflow/04_hello_modules.md @@ -39,7 +39,7 @@ nextflow run hello-modules.nf ``` ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-modules.nf` [festering_nobel] DSL2 - revision: eeca64cdb1 @@ -50,7 +50,7 @@ executor > local (7) There were 3 greetings in this batch ``` -As previously, you will find the output files in the `results` directory (specified by the `publishDir` directive). +As previously, you will find the output files in the `results` directory (specified by the workflow outputs). ```console title="Directory contents" results @@ -117,8 +117,6 @@ Copy the whole process definition over from the workflow file to the module file */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -170,7 +168,7 @@ nextflow run hello-modules.nf -resume This runs quickly very quickly because everything is cached. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-modules.nf` [romantic_poisson] DSL2 - revision: 96edfa9ad3 @@ -216,8 +214,6 @@ Copy the whole process definition over from the workflow file to the module file */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -267,7 +263,7 @@ nextflow run hello-modules.nf -resume This should still produce the same output as previously. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-modules.nf` [nauseous_heisenberg] DSL2 - revision: a04a9f2da0 @@ -303,8 +299,6 @@ Copy the whole process definition over from the workflow file to the module file */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files val batch_name @@ -359,7 +353,7 @@ nextflow run hello-modules.nf -resume This should still produce the same output as previously. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-modules.nf` [friendly_coulomb] DSL2 - revision: 7aa2b9bc0f diff --git a/docs/hello_nextflow/05_hello_containers.md b/docs/hello_nextflow/05_hello_containers.md index eaaade723a..cd4e1f5227 100644 --- a/docs/hello_nextflow/05_hello_containers.md +++ b/docs/hello_nextflow/05_hello_containers.md @@ -40,7 +40,7 @@ nextflow run hello-containers.nf This should produce the following output: ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-containers.nf` [tender_becquerel] DSL2 - revision: f7cat8e223 @@ -50,7 +50,7 @@ executor > local (7) [7d/f7961c] collectGreetings [100%] 1 of 1 ✔ ``` -As previously, you will find the output files in the `results` directory (specified by the `publishDir` directive). +As previously, you will find the output files in the `results` directory (specified by the workflow outputs). ```console title="Directory contents" results @@ -378,8 +378,6 @@ We can model our `cowpy` process on the other processes we've written previously // Generate ASCII art with cowpy process cowpy { - publishDir 'results', mode: 'copy' - input: path input_file val character @@ -500,7 +498,7 @@ nextflow run hello-containers.nf -resume Oh no, there's an error! ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-containers.nf` [special_lovelace] DSL2 - revision: 028a841db1 @@ -545,10 +543,9 @@ Edit the `cowpy.nf` module to add the `container` directive to the process defin === "After" - ```groovy title="modules/cowpy.nf" linenums="4" hl_lines="4" + ```groovy title="modules/cowpy.nf" linenums="4" hl_lines="3" process cowpy { - publishDir 'containers/results', mode: 'copy' container 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' ``` @@ -556,8 +553,6 @@ Edit the `cowpy.nf` module to add the `container` directive to the process defin ```groovy title="modules/cowpy.nf" linenums="4" process cowpy { - - publishDir 'containers/results', mode: 'copy' ``` This tells Nextflow that if the use of Docker is enabled, it should use the container image specified here to execute the process. @@ -601,7 +596,7 @@ nextflow run hello-containers.nf -resume This time it does indeed work. ```console title="Output" linenums="1" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-containers.nf` [elegant_brattain] DSL2 - revision: 028a841db1 diff --git a/docs/hello_nextflow/06_hello_config.md b/docs/hello_nextflow/06_hello_config.md index a8c7225811..6d5bad8fb9 100644 --- a/docs/hello_nextflow/06_hello_config.md +++ b/docs/hello_nextflow/06_hello_config.md @@ -27,14 +27,29 @@ By learning to utilize these configuration options effectively, you can enhance ## 0. Warmup: Check that Docker is enabled and run the Hello Config workflow -First, a quick check. There is a `nextflow.config` file in the current directory that contains the line `docker.enabled = `, where `` is either `true` or `false` depending on whether or not you've worked through Part 5 of this course in the same environment. +First, a quick check. There is a `nextflow.config` file in the current directory that should contain basic configuration settings from earlier parts of the training. -If it is set to `true`, you don't need to do anything. +You can view the current config file: -If it is set to `false`, switch it to `true` now. +```bash +cat nextflow.config +``` + +It should look something like this: + +```groovy title="nextflow.config" linenums="1" +docker.enabled = false +workflow.output.mode = 'copy' +``` -```console title="nextflow.config" linenums="1" +The `docker.enabled` setting controls whether Docker containers are used (covered in Part 5). +The `workflow.output.mode` setting controls how output files are published - `'copy'` means files are copied to the output directory, while the default `'symlink'` creates symbolic links instead. + +For this part of the training, make sure `docker.enabled` is set to `true`: + +```groovy title="nextflow.config" linenums="1" docker.enabled = true +workflow.output.mode = 'copy' ``` Once you've done that, verify that the initial workflow runs properly: @@ -44,7 +59,7 @@ nextflow run hello-config.nf ``` ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-config.nf` [reverent_heisenberg] DSL2 - revision: 028a841db1 @@ -90,13 +105,14 @@ To do so, we switch the value of `docker.enabled` to `false`, and add a directiv ```groovy title="nextflow.config" linenums="1" hl_lines="1-2" docker.enabled = false conda.enabled = true + workflow.output.mode = 'copy' ``` === "Before" ```groovy title="nextflow.config" linenums="1" - docker.enabled = true + workflow.output.mode = 'copy' ``` This will allow Nextflow to create and utilize Conda environments for processes that have Conda packages specified. @@ -115,13 +131,11 @@ Now we add the URI to the `cowpy` process definition using the `conda` directive === "After" - ```console title="modules/cowpy.nf" linenums="4" hl_lines="4" + ```console title="modules/cowpy.nf" linenums="4" hl_lines="3" process cowpy { container 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' conda 'conda-forge::cowpy==1.1.5' - - publishDir 'results', mode: 'copy' ``` === "Before" @@ -130,8 +144,6 @@ Now we add the URI to the `cowpy` process definition using the `conda` directive process cowpy { container 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' - - publishDir 'results', mode: 'copy' ``` To be clear, we're not _replacing_ the `docker` directive, we're _adding_ an alternative option. @@ -147,7 +159,7 @@ nextflow run hello-config.nf This should work without issue. ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-config.nf` [trusting_lovelace] DSL2 - revision: 028a841db1 @@ -362,7 +374,7 @@ nextflow run hello-config.nf -params-file test-params.json It works! And as expected, this produces the same outputs as previously. ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-config.nf` [disturbed_sammet] DSL2 - revision: ede9037d02 @@ -511,7 +523,7 @@ nextflow run hello-config.nf -profile my_laptop This still produces the following output: ``` - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-config.nf` [gigantic_brazil] DSL2 - revision: ede9037d02 @@ -593,7 +605,7 @@ nextflow run hello-config.nf -profile my_laptop,test This should produce the following: ```console title="Output" - N E X T F L O W ~ version 25.04.3 + N E X T F L O W ~ version 25.10.0 Launching `hello-config.nf` [gigantic_brazil] DSL2 - revision: ede9037d02 diff --git a/hello-nextflow/hello-channels.nf b/hello-nextflow/hello-channels.nf index 6236eea21e..280b7ad138 100644 --- a/hello-nextflow/hello-channels.nf +++ b/hello-nextflow/hello-channels.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -26,6 +24,16 @@ params.greeting = 'Holà mundo!' workflow { + main: // emit a greeting sayHello(params.greeting) + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/hello-modules.nf b/hello-nextflow/hello-modules.nf index ccf29abd63..780f8c04b7 100644 --- a/hello-nextflow/hello-modules.nf +++ b/hello-nextflow/hello-modules.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -24,8 +22,6 @@ process sayHello { */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -43,8 +39,6 @@ process convertToUpper { */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files val batch_name @@ -68,6 +62,7 @@ params.batch = 'test-batch' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -84,4 +79,21 @@ workflow { // emit a message about the size of the batch collectGreetings.out.count.view { "There were $it greetings in this batch" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out.outfile +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } } diff --git a/hello-nextflow/hello-workflow.nf b/hello-nextflow/hello-workflow.nf index 0f54be80ce..e1c2ec5793 100644 --- a/hello-nextflow/hello-workflow.nf +++ b/hello-nextflow/hello-workflow.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -26,11 +24,21 @@ params.greeting = 'greetings.csv' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) - .splitCsv() - .map { line -> line[0] } + .splitCsv() + .map { line -> line[0] } // emit a greeting sayHello(greeting_ch) + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/nextflow.config b/hello-nextflow/nextflow.config index 0a5fd46b9a..a8a6c05192 100644 --- a/hello-nextflow/nextflow.config +++ b/hello-nextflow/nextflow.config @@ -1 +1,2 @@ docker.enabled = false +workflow.output.mode = 'copy' diff --git a/hello-nextflow/solutions/1-hello-world/hello-world-3.nf b/hello-nextflow/solutions/1-hello-world/hello-world-3.nf index f2e4b33448..e7a8c4a22e 100644 --- a/hello-nextflow/solutions/1-hello-world/hello-world-3.nf +++ b/hello-nextflow/solutions/1-hello-world/hello-world-3.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - output: path 'output.txt' @@ -18,6 +16,16 @@ process sayHello { workflow { + main: // emit a greeting sayHello() + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/solutions/1-hello-world/hello-world-4.nf b/hello-nextflow/solutions/1-hello-world/hello-world-4.nf index 6236eea21e..280b7ad138 100644 --- a/hello-nextflow/solutions/1-hello-world/hello-world-4.nf +++ b/hello-nextflow/solutions/1-hello-world/hello-world-4.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -26,6 +24,16 @@ params.greeting = 'Holà mundo!' workflow { + main: // emit a greeting sayHello(params.greeting) + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/solutions/2-hello-channels/hello-channels-1.nf b/hello-nextflow/solutions/2-hello-channels/hello-channels-1.nf index 6190b616ae..d391ed0991 100644 --- a/hello-nextflow/solutions/2-hello-channels/hello-channels-1.nf +++ b/hello-nextflow/solutions/2-hello-channels/hello-channels-1.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -26,9 +24,19 @@ params.greeting = 'Holà mundo!' workflow { + main: // create a channel for inputs greeting_ch = Channel.of('Hello Channels!') // emit a greeting sayHello(greeting_ch) + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/solutions/2-hello-channels/hello-channels-2.nf b/hello-nextflow/solutions/2-hello-channels/hello-channels-2.nf index 5e7a2d50fc..a63d59661f 100644 --- a/hello-nextflow/solutions/2-hello-channels/hello-channels-2.nf +++ b/hello-nextflow/solutions/2-hello-channels/hello-channels-2.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -26,9 +24,19 @@ params.greeting = 'Holà mundo!' workflow { + main: // create a channel for inputs greeting_ch = Channel.of('Hello','Bonjour','Holà') // emit a greeting sayHello(greeting_ch) + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/solutions/2-hello-channels/hello-channels-3.nf b/hello-nextflow/solutions/2-hello-channels/hello-channels-3.nf index 49de2cb657..273a743a58 100644 --- a/hello-nextflow/solutions/2-hello-channels/hello-channels-3.nf +++ b/hello-nextflow/solutions/2-hello-channels/hello-channels-3.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -26,14 +24,24 @@ params.greeting = 'Holà mundo' workflow { + main: greetings_array = ['Hello','Bonjour','Holà'] // create a channel for inputs greeting_ch = Channel.of(greetings_array) - .view { "Before flatten: $it" } + .view { greeting -> "Before flatten: $greeting" } .flatten() - .view { "After flatten: $it" } + .view { greeting -> "After flatten: $greeting" } // emit a greeting sayHello(greeting_ch) + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/solutions/2-hello-channels/hello-channels-4.nf b/hello-nextflow/solutions/2-hello-channels/hello-channels-4.nf index 449366b810..3b4ee8af65 100644 --- a/hello-nextflow/solutions/2-hello-channels/hello-channels-4.nf +++ b/hello-nextflow/solutions/2-hello-channels/hello-channels-4.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -26,16 +24,24 @@ params.greeting = 'greetings.csv' workflow { - greetings_array = ['Hello','Bonjour','Holà'] - + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) - .view { "Before splitCsv: $it" } + .view { csv -> "Before splitCsv: $csv" } .splitCsv() - .view { "After splitCsv: $it" } + .view { csv -> "After splitCsv: $csv" } .map { line -> line[0] } - .view { "After map: $it" } + .view { csv -> "After map: $csv" } // emit a greeting sayHello(greeting_ch) + + publish: + greetings = sayHello.out +} + +output { + greetings { + path '.' + } } diff --git a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-1.nf b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-1.nf index 9516d600f7..4161d1d345 100644 --- a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-1.nf +++ b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-1.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -24,8 +22,6 @@ process sayHello { */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -45,6 +41,7 @@ params.greeting = 'greetings.csv' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -55,4 +52,17 @@ workflow { // convert the greeting to uppercase convertToUpper(sayHello.out) + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } } diff --git a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-2.nf b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-2.nf index f517924175..71f2cd0582 100644 --- a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-2.nf +++ b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-2.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -24,8 +22,6 @@ process sayHello { */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -43,8 +39,6 @@ process convertToUpper { */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files @@ -64,6 +58,7 @@ params.greeting = 'greetings.csv' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -81,4 +76,21 @@ workflow { // optional view statements convertToUpper.out.view { "Before collect: $it" } convertToUpper.out.collect().view { "After collect: $it" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } } diff --git a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-3.nf b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-3.nf index 65ac85ce0d..d579264504 100644 --- a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-3.nf +++ b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-3.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -24,8 +22,6 @@ process sayHello { */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -43,8 +39,6 @@ process convertToUpper { */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files val batch_name @@ -66,6 +60,7 @@ params.batch = 'test-batch' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -83,4 +78,21 @@ workflow { // optional view statements convertToUpper.out.view { "Before collect: $it" } convertToUpper.out.collect().view { "After collect: $it" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } } diff --git a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-4.nf b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-4.nf index 92af832e72..b97bf1126d 100644 --- a/hello-nextflow/solutions/3-hello-workflow/hello-workflow-4.nf +++ b/hello-nextflow/solutions/3-hello-workflow/hello-workflow-4.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting @@ -24,8 +22,6 @@ process sayHello { */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -43,8 +39,6 @@ process convertToUpper { */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files val batch_name @@ -68,6 +62,7 @@ params.batch = 'test-batch' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -88,4 +83,21 @@ workflow { // optional view statements //convertToUpper.out.view { "Before collect: $it" } //convertToUpper.out.collect().view { "After collect: $it" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out.outfile +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } } diff --git a/hello-nextflow/solutions/4-hello-modules/hello-modules-2.nf b/hello-nextflow/solutions/4-hello-modules/hello-modules-2.nf index 0d384c4796..7ef2976910 100644 --- a/hello-nextflow/solutions/4-hello-modules/hello-modules-2.nf +++ b/hello-nextflow/solutions/4-hello-modules/hello-modules-2.nf @@ -5,8 +5,6 @@ */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file @@ -24,8 +22,6 @@ process convertToUpper { */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files val batch_name @@ -52,6 +48,7 @@ include { sayHello } from './modules/sayHello.nf' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -68,4 +65,21 @@ workflow { // emit a message about the size of the batch collectGreetings.out.count.view { "There were $it greetings in this batch" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out.outfile +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } } diff --git a/hello-nextflow/solutions/4-hello-modules/hello-modules-3.nf b/hello-nextflow/solutions/4-hello-modules/hello-modules-3.nf index e34edebed0..bf5cb28b11 100644 --- a/hello-nextflow/solutions/4-hello-modules/hello-modules-3.nf +++ b/hello-nextflow/solutions/4-hello-modules/hello-modules-3.nf @@ -5,8 +5,6 @@ */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files val batch_name @@ -34,6 +32,7 @@ include { convertToUpper } from './modules/convertToUpper.nf' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -50,4 +49,21 @@ workflow { // emit a message about the size of the batch collectGreetings.out.count.view { "There were $it greetings in this batch" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out.outfile +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } } diff --git a/hello-nextflow/solutions/4-hello-modules/hello-modules-4.nf b/hello-nextflow/solutions/4-hello-modules/hello-modules-4.nf index 8764606bf7..cffa5bcc8b 100644 --- a/hello-nextflow/solutions/4-hello-modules/hello-modules-4.nf +++ b/hello-nextflow/solutions/4-hello-modules/hello-modules-4.nf @@ -13,6 +13,7 @@ include { collectGreetings } from './modules/collectGreetings.nf' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -29,4 +30,21 @@ workflow { // emit a message about the size of the batch collectGreetings.out.count.view { "There were $it greetings in this batch" } + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out.outfile +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } } diff --git a/hello-nextflow/solutions/4-hello-modules/modules/collectGreetings.nf b/hello-nextflow/solutions/4-hello-modules/modules/collectGreetings.nf index 849bba4b6e..09b8fa1fce 100644 --- a/hello-nextflow/solutions/4-hello-modules/modules/collectGreetings.nf +++ b/hello-nextflow/solutions/4-hello-modules/modules/collectGreetings.nf @@ -3,8 +3,6 @@ */ process collectGreetings { - publishDir 'results', mode: 'copy' - input: path input_files val batch_name diff --git a/hello-nextflow/solutions/4-hello-modules/modules/convertToUpper.nf b/hello-nextflow/solutions/4-hello-modules/modules/convertToUpper.nf index b2689e8e9c..20d0b0885a 100644 --- a/hello-nextflow/solutions/4-hello-modules/modules/convertToUpper.nf +++ b/hello-nextflow/solutions/4-hello-modules/modules/convertToUpper.nf @@ -5,8 +5,6 @@ */ process convertToUpper { - publishDir 'results', mode: 'copy' - input: path input_file diff --git a/hello-nextflow/solutions/4-hello-modules/modules/sayHello.nf b/hello-nextflow/solutions/4-hello-modules/modules/sayHello.nf index 6005ad54c9..e2cd73ae85 100644 --- a/hello-nextflow/solutions/4-hello-modules/modules/sayHello.nf +++ b/hello-nextflow/solutions/4-hello-modules/modules/sayHello.nf @@ -5,8 +5,6 @@ */ process sayHello { - publishDir 'results', mode: 'copy' - input: val greeting diff --git a/hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf b/hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf index f187831d1c..975249b836 100644 --- a/hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf +++ b/hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf @@ -15,6 +15,7 @@ include { cowpy } from './modules/cowpy.nf' workflow { + main: // create a channel for inputs from a CSV file greeting_ch = Channel.fromPath(params.greeting) .splitCsv() @@ -34,4 +35,25 @@ workflow { // generate ASCII art of the greetings with cowpy cowpy(collectGreetings.out.outfile, params.character) + + publish: + greetings = sayHello.out + uppercase = convertToUpper.out + collected = collectGreetings.out.outfile + ascii_art = cowpy.out +} + +output { + greetings { + path '.' + } + uppercase { + path '.' + } + collected { + path '.' + } + ascii_art { + path '.' + } } diff --git a/hello-nextflow/solutions/5-hello-containers/modules/cowpy.nf b/hello-nextflow/solutions/5-hello-containers/modules/cowpy.nf index 60b739b625..07a06c70f8 100644 --- a/hello-nextflow/solutions/5-hello-containers/modules/cowpy.nf +++ b/hello-nextflow/solutions/5-hello-containers/modules/cowpy.nf @@ -3,8 +3,6 @@ // Generate ASCII art with cowpy (https://github.com/jeffbuttars/cowpy) process cowpy { - publishDir 'results', mode: 'copy' - container 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' input: diff --git a/hello-nextflow/solutions/6-hello-config/modules/cowpy.nf b/hello-nextflow/solutions/6-hello-config/modules/cowpy.nf index 2bc7ed612b..7c850fbd4c 100644 --- a/hello-nextflow/solutions/6-hello-config/modules/cowpy.nf +++ b/hello-nextflow/solutions/6-hello-config/modules/cowpy.nf @@ -3,8 +3,6 @@ // Generate ASCII art with cowpy (https://github.com/jeffbuttars/cowpy) process cowpy { - publishDir 'results', mode: 'copy' - container 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273' conda 'conda-forge::cowpy==1.1.5'