Skip to content

2. Basic concepts

Nextflow is a workflow orchestration engine and domain-specific language (DSL) that makes it easy to write data-intensive computational workflows.

It is designed around the idea that the Linux platform is the lingua franca of data science. Linux provides many simple but powerful command-line and scripting tools that, when chained together, facilitate complex data manipulations.

Nextflow extends this approach, adding the ability to define complex program interactions and a high-level parallel computational environment, based on the dataflow programming model. Nextflow’s core features are:

  • Workflow portability and reproducibility
  • Scalability of parallelization and deployment
  • Integration of existing tools, systems, and industry standards

2.1 Processes and Channels

In practice, a Nextflow workflow is made by joining together different processes. Each process can be written in any scripting language that can be executed by the Linux platform (Bash, Perl, Ruby, Python, etc.).

Processes are executed independently and are isolated from each other, i.e., they do not share a common (writable) state. The only way they can communicate is via asynchronous first-in, first-out (FIFO) queues, called channels. In other words, every input and output of a process is represented as a channel. The interaction between these processes, and ultimately the workflow execution flow itself, is implicitly defined by these input and output declarations.

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1daVNcIslcdTAwMTb93r/CcL6ONbkvXHUwMDEz8eJcdTAwMDWotKjYbrTii1x0o4BCSpZCKESc6P/+bqJSXHUwMDA1VLGjpdHMRKu1ZGVl3nPuuTdcdTAwMTf+/ba1te33W87231vbzlPJrrvltt3b/tNcdTAwMWN/dNpcdTAwMWTXa8IpMvi743XbpcGVVd9vdf7+66+G3a45fqtul1x1MDAxY+vR7XTtesfvll3PKnmNv1xc32l0/mv+PbFcdTAwMWLOf1peo+y3reAhO07Z9b32y7OcutNwmn5cdTAwMDdK/1x1MDAxZvy9tfXv4N9Q7ex223up2OBwUDmO1fjRXHUwMDEzrzmoKJOaUi4lXHUwMDFlXuB29uBRvlOGs1x1MDAxNaiuXHUwMDEznDGHtq/9Vv7azaRcdTAwMWZaT9+ru9fnd1x1MDAxOFeywVMrbr1+4ffrL61gl6rdtlx1MDAxM5zt+G2v5lxcuWW/alx1MDAxZT52fHhfx4NcdTAwMDZcYu5qe927atPpmHdcdTAwMGYq6rXskuv3zTGEhkft5t2gjODIk+lcdTAwMWWiLY2pQlxiY8TgjenwtCmAIWppLVx1MDAxOVeUaim0XHUwMDFlq9iuV4dugIr9wTRHXFxcdTAwMDZVK9ql2lx1MDAxZNSvWVx1MDAxZV7jt+1mp2W3obOC63qvryyVRTRVUFx1MDAxNyo5XHUwMDExjFxmr6g67l3VNzW3kKZcdTAwMDL+Z0xQwjVjoXZyXHUwMDA2/YIloVx1MDAxOEtBgtYwlWhly1x1MDAwM/P4J9xyzfJry73ZS2Ax5PXIr+B1zPX7IUtcdTAwMGKK6rbK9otVYCE5XHUwMDEziiGJRNDMdbdZg5PNbr1cdTAwMWVcdTAwMWPzSrVcYkPq+HbbT7vNstu8XHUwMDFiv8VploMzoSq/mn92YIP7JOs37eec+717dn5fdi55bjfoXHUwMDE0Y4VeqWvqv1x1MDAwM42JmUBCcUVcYmLQuUHXm1azW+aFsIU5llhRuFSZXHUwMDFmXHUwMDEzXHJTtzv+rtdouD60wannNv3xilx1MDAwZl4qZSBYdexyxGuFz41jtWVKXGagbT7Bb1uBMVx1MDAwZv5cdTAwMTj+/s+fkVfH2pj57ESYV1Dgt/DP17ef4Fx1MDAxOaded1tcdTAwMWQnimmoXHUwMDE0cUyDXHUwMDExUVgqqNfcVDO9m1x1MDAxN6JcdTAwMWE8dnxzVEOxtihXSCuMOFx1MDAxN4hcdTAwMDQt0lx1MDAxZrRcdTAwMTC2KFFKMaJcdDfXxHJcclx1MDAxYXyW51x1MDAxYcIsRVx1MDAxMMUkeMSQZFx1MDAwNFx1MDAwM5NcdTAwMTehM6/MQiSDftI8OLEhYlx1MDAxOd7zb8g453IxI7b4gqPhmV9vXHUwMDA2vEbamopcdTAwMDW4PVx1MDAxYVxilMVcdTAwMDFBXCLGXHUwMDAwlXp+l3vVPtM/2q1cdTAwMWK1+8x2z/3bhj6zfyRcdTAwMWVcdTAwMDeUWlRwjaG1I3FALKo11kJuXHUwMDFhXHUwMDA3VJhHUfCX0PtcdTAwMTIjySbxgMaBgInWSisp6Vx1MDAwMkhcdTAwMTixooT50tHC1uvORs6t1ZfF993Y7XN5rji0MlwiY91cdTAwMTbmSDBB5vdaondzW7HtvYKXrfTb/cL3g/x1I/loJZZSQmmkXHUwMDE4M7+MopVRbjFAs9CSXHUwMDEyzClcdTAwMWaX7utEq7Cw1kJDKVKRkFKPXHUwMDA3q1JcdTAwMWFIRi6ihn9Ddf1Qjem4sbtXQipEPWj88Fx1MDAxYlRB8WpNJJ3fseb6vStW+X7vX+5cdTAwMTae7GNkp1jaSTpUXHUwMDE5l1x1MDAxNsCVSzB4XG5+NaCuXHUwMDE3v8pcdTAwMDCpXHUwMDE0ioGYXHUwMDE3fGt8KLsqUCFq0lx1MDAwNFSuYJxcdTAwMDNcdTAwMDC1XGYqMkQq11x1MDAxNsGKUIFcdTAwMDVcdTAwMTHGKCbcLNVGXCKEo4IvXHUwMDE5yX5OSEtLXGJCKFwiIOIoXHQ5QfPB4JnB/MDQpFx1MDAxMlxiS8JmXHUwMDE1XHUwMDE3bzHmQ7QlpcBcdTAwMTJcIiTCmKZ8ZnHIMpkrocAlXHUwMDAx48Bv4eJcdTAwMThcdTAwMTSHmYFcdTAwMDBcdTAwMDS7IC/VrOIgXCLSoEqZXHUwMDA0+GiCwDTCxU1Y8rpcYo3h2EiBmmxcdTAwMTSXaH5CO053XHUwMDFh6rJWuHJTp0LtOKXr3Ekv6YQmtLAk1WBEikutaJCsfCM0yoSxL+hFTehYvVx1MDAxMkZohs9cdTAwMDTDZJGw4Tef/eazra/CZ4Tr8cPDWEphiOQglpg/lmqre13id72rQuGkg09w8Vx1MDAwN/aSzmdcXFx1MDAxOVx0Rlx1MDAwNPBcdTAwMTlcdTAwMDHiYuNcdTAwMDKNQsdAMyhpXHUwMDAyS8RcdTAwMTJOaFpqsDtMf1x1MDAxM9pvQvvKhOY7T35kJlx1MDAxN8XnhqhUXGKqouYnNHrmfL/t1S6bXVxiVr/jg0e7ktdJJzRcdTAwMTPZU5NcdTAwMTjCXHUwMDA0xChVQSlcdTAwMDNC09gyY8hgNlx1MDAwNML/zWWGQvmdIX2RibFRXHUwMDAyjMpcdTAwMTFcdTAwMGV7mURmgype079wn1x1MDAwN+SIRo5m7IZbXHUwMDFmtOzw8MA4oX3g6fbWc7hcdDvOwFx1MDAxM49cdTAwMTRirk7V3bvmwFE7lVG79t2SXVx1MDAxZp5uuOVyPWRjJaiAXHIltrNcdTAwMTPM5bXdO7dp1y9HK7NcdTAwMWOqWGzUY1x1MDAwNlxuKdGLyIRsMX14cnCGVC3VaWqPXHUwMDFjK7uQeJnAtFx1MDAwMj5lXHUwMDE0WFx1MDAwNFx1MDAwM6OGRiXeUFx1MDAwNdFcdTAwMTBlREHcXHUwMDEzdr9cdTAwMWZcdTAwMDMrYGpMXHUwMDA1pyjhSdblYdVPXHUwMDEyrPpLwkrEOyvOzZxcdTAwMTEwpblhlU7t3V5Xfj572XxKcsIumWzVklx1MDAwZSuBuVx1MDAwNWJDgFBcdTAwMDBvJEMskkhYSSa5XHUwMDE2XHUwMDE0f1lv9ZQkWD0tXHQrOiWm5Vx1MDAxMmSnYvPDaicnd3f2XG7n9Sd6WPLat/lWQ54nXHUwMDFkVpQyS1x1MDAxMDMwyCCiYEiPwlxuXCJcdTAwMDdcYjFGZ5SsO5pcctVxiCgqJlx1MDAxMYVcdTAwMDVcdTAwMDBfLDKg8MGAUtGAwlx1MDAxM4DardrNplOPRlx1MDAxNH9vRL3VZiqk2k7Jf7GoXGJcXLFQpSdiK6Ew2JueXHUwMDFmV0dN1cxcdTAwMTVcdTAwMGZ4zW92/cPeXrH7fHe1XHUwMDFjrshcdTAwMTK4XCJL4UpKcFdcYlxiRFxuXHUwMDE0Rk//xcgsKoXmI3O41j7gTpVcdTAwMDWWrCFcdTAwMTRcdTAwMTdcdTAwMDIqoiOyRExMjtwppakyczNcdTAwMTZcdTAwMDDaZGKIvlx1MDAxZVkhMYRcdTAwMTfA31L0T0KPXHUwMDE4N1PJodUkW0BV9dK5LL9OZ4/zvYr/47abvW09nCSd/qXiXHUwMDE2RqbJ5ZiNgtxcIpIyKjfJ/Fx1MDAxMSZcdTAwMTnB/EgrLSBQeTfmX8TyVmP+07ZXMjVOXHUwMDA287/VZiqaYpcjUFx1MDAxMlx1MDAxYvtDjELNpIX5Q/9C7oFcdTAwMTR3s4eMXHUwMDFlVqvlw7NcdTAwMDfhPq97jnDZ7lSd9cJcdGtLXHUwMDFha1VmuVx1MDAwMdWjQ1x1MDAwNFxmMThLXHUwMDE4Q4hcdTAwMDJwqN4gtDCypKCEgGpcdTAwMDL5hqOmW2FcIixMoVNcdTAwMDQoKzODm04gXHUwMDBmqklcdTAwMTDDXHUwMDFmvlx1MDAxY2EpQK68XHUwMDFj4dTOXFyKokJcdTAwMDdcdTAwMGbVZ0FPczc/MuVm1HJcdTAwMDRkQTW5lsCkklOBUCiD/bpcdTAwMTZBWlpcdTAwMTOsJFx1MDAwNK/wUUpMNMpnWopcdTAwMTBvXuazM2lZQYHfwj+XUpcyPmgjhClJXHUwMDE0mX9mxfQ+XHUwMDFl5Zkx7/tRPlx1MDAxYtrT4pxBq1xuqjjCo2l7wrFcdTAwMDWaXHUwMDBmISnIwNpW4Zg/MLftYiWCX5i0gMBGpG0w9kgtqtmYun1hXHUwMDE0SZVCXCLMfFx1MDAxYlx1MDAxMpfDe0bWIUQqwpA1nFdZyj09l/gpL9ntzb3q1+7Dy1x1MDAxMP6MLnZcdTAwMWWXNfL88eVcclPLLaZP9jNcdTAwMTepvCw+XaTZkU2encf8WpdNbF5pxy5UxFx1MDAxNFx1MDAxOIRcdTAwMDFtzi9ccqI7KeFCXHUwMDFi4kCLS6oxUypcdTAwMDK0XHUwMDEwXHUwMDExYlx1MDAwNoClhJNVQbt4+nLC8UO8XGJcdTAwMWFGvONY28qSe1x1MDAxZNlLrEeuXHUwMDFlSupcdTAwMTK8hdNeWnPPcjLLpDTjXHUwMDE3XHUwMDA189iJ1Fx1MDAwMlx1MDAwNFxuXHUwMDAy45NzQ2069SRVhWvNLCqwXHUwMDFjXHUwMDA0tlxiYTKKNVx1MDAwNe6JcVx1MDAwMSjDXG7zXHJiXHLEiMVcdTAwMTkjlHOulWBcdTAwMTHQm1xcn1x1MDAwNJrJTKVCXHUwMDFmPnF6XHUwMDFkmntccspcdTAwMWFLs8aMY2g+qFx1MDAxNeiKXHRprUCKKlwiIKySXHUwMDFj+ovziXd/t1x1MDAxOUFcdTAwMWJcdTAwMTXdseY0dvfqXG6byvjEmEZmQlI4dTaLREpPj376x5X/WFx1MDAxMo1y515mLm5cdTAwMGX3ki2xzcpcdTAwMDWLUVxiXTRHQFx1MDAxNmx02Vx1MDAxNOFcdTAwMTDfYPDlaMWBkT8qdlx1MDAxMSx2ffpcdTAwMWHoQ1x1MDAxYSSEVo8kSmDfXHUwMDE3z3L0MOPenFT2XHUwMDFhmcu6WzrbTSdQsNKQJlx1MDAxYV+OJJngXFwsMDBcdTAwMTj90lx0XHUwMDE3rFx1MDAxOFx0ZoEwp1x1MDAxMmg1XHUwMDAyXHUwMDAyZr07kPKqXGKY6kB1hPFPilWjU1x0xLrvN4Pl/cSq1/VbXf+d5epcZsJcdTAwMWWXq8M6LidYmYqd26LNrlx1MDAwNZTL+aHW8J+v8jdcdTAwMTdPe6Xuz/ZZQZ5cdTAwMWT3cuteUr+BtDFBXHUwMDE2ldrkXHUwMDBlseJMjU5cdTAwMTljiJt1NPBcdTAwMWZcdTAwMDNpqLnYbNpcdTAwMTgrXHUwMDAyXCKDY605iVx1MDAxOJ9cdTAwMTlklyThIMtcdTAwMTBcdTAwMDU5XHUwMDEy6r3hXHUwMDEye1xmhFx1MDAwMbX+8KnlXHUwMDFmkza+f+xcdTAwMWV0XG43pL9XuSZXdPdcblx1MDAxNY6PosUtXCJArmZ1K9hcYlJcdTAwMTSzSXX7ljieVLWfSbvGXHUwMDFh1uDkhEmtU8xcdTAwMTJcdTAwMTTvyplGRC+wSdb0rk2klJ2eLYbDXHUwMDE2wlx1MDAxY9qeXHTQk2S8Xlx1MDAxZpstXHUwMDA2hc2UmX2eTDHby1Vyl1wi9fSjl1x1MDAxNsfPrKpvKlx1MDAxN3TerO50TzXy/IWyxXamkleZ3uGhzVx1MDAwZUlVPGevj9o3nytbjHls+Fx01MExkXz+XHUwMDE0VnQnJVxcfE/PXHUwMDE2U60sXHUwMDAycCFcdTAwMTQptSpo15AtNrlcdTAwMTlpKOZcdTAwMTPN0FjHXHUwMDFj8k3p71x1MDAxOV5mmYnlsepbTJlZjrHZ1o2J+cE2nXySKr9NvphcdTAwMTPEmUSaXHUwMDAwv4xtXCKJ4SxcdTAwMDP3JEz+UW1OfIM6siQhXG7ozyx3XHUwMDBiT2KPz1x1MDAxN3OIz5kmcrVcdTAwMDHVhGjtNShqrFx1MDAxMERKXHUwMDFhdJ2AXHUwMDFmUqjQVW/pYmguMFxuXHJNZ1x1MDAxNpThiXf/KuniOHNcdTAwMWG7fXWJXHJcdTAwMDZcdTAwMThLXCJKmGBwgaWUqJlLnVSOOnXl+163WGyJhnxKtsaekS6mSoLElUaCK2TW9a60lnL9OWNBXHUwMDExOG+OXHUwMDEzmjPuNHo51D88yPiV1M8uxjftXFw9k0DZylj8rHdcctWQXHUwMDE04fm3m4t+64Tr1lx1MDAxOUljhojFQVAwTVx1MDAxMV9cdTAwMTlcYmtIXHUwMDFkY41cdTAwMDW4/HCK4Oso19e87Ptq11x1MDAxOexcdTAwMWSTO15WvYbXrI9vslx1MDAwNEpO6lx1MDAwNVLH6oE9Vr3bXFxqJ7+j3MN9IVxuR+tcdTAwMDbcJlLH1Fx1MDAwMqWjXHUwMDA2XHUwMDBijrlcdTAwMTCjkaLRrlhKqZFWVDK2yV3jqCU5XHUwMDE3kkipzLKTyFx0x9wy+1x0SIbMllx1MDAwM1x1MDAxMNpO4NHsMchcdTAwMTThi4zlJFbOLp467udSfbvaK/bc63Yh11JlnVx1MDAxMTxK6O4gaG1QVYZizY8gQzDUuWbzc1x1MDAwNZJcdTAwMDOuIFx1MDAxY6FPP+M4zr5cdTAwMDZnJyxrnfJcdTAwMTZPWSdkJvtrpeanmeldnEh5Oz2FzIFjXHUwMDEwRFx1MDAxOUhcdTAwMTJDQ6vte7T2XHUwMDE0Mlx1MDAxNsRse6NXnE+1MXF7e9M4TD3VhPT287VuSu1cdTAwMWWV+1x1MDAwZvPmeqe7rJHnL5RDVrXe7cO+aNzcZ5o3V9f8PJty2SfLIcdv76OJokxBuDY3ZqM7KeFafHpcdTAwMGWZXHUwMDEzbVx1MDAwMVFKXHUwMDAwLaGronZccjlkoFx1MDAxN5DhSC/i+D+LXHUwMDEwn7K7z6Zk+FxmL7PMlj/xKWRcdTAwMWVcdTAwMWL3Slx1MDAxMKRYi5DtzVThU6knqSpcdTAwMWOuwFx1MDAxNqeUK1x1MDAxZTXlXHUwMDE4jllcYmQtsI400/M2hjXCXHUwMDEwhN9CYsaVXHUwMDA0b1x1MDAxZPk9RFx1MDAxMaJcdTAwMWJwgbj6XHUwMDEyontlaY0sXGZhI2hIpszmOCi0NCXQ1tzSXGZhXHUwMDEwXHUwMDFkX37OcZxBjd2+uspmLH4kSmhMoSpcdTAwMGKs68Npr8uz+WbJa93ca/dcdTAwMWNd1k7LyZbZM7LIXHUwMDFjK1x1MDAwYrBidkGkgoRbK1x1MDAxMUlkXHUwMDA0YaZCcvPbRiyns7v3dydcdTAwMGZcdTAwMDJ38qyQ2T8p1P1uXHUwMDFml1x1MDAxMqhbWchMJjbQw2aNcWh/zJkoiH7rhFx1MDAwYtdcdTAwMTlJZHCzllnkq82o1qo4WENcdTAwMGXZbHVcbuREXHUwMDE3XHUwMDE5PfksyvU1Pfu+2nVcdTAwMDZ1x6SQl9ywXHUwMDEy49jV5Fx1MDAwNFFidkXV81x1MDAwN4q12vlZqrrvelx1MDAxN7xCXHUwMDFh9Z8/z45zcVuALed11q9dXHUwMDE1laB4OPhcdTAwMTSEmWZj21pDXHUwMDBiWGZ3XHUwMDE4rYX5lk222vyH2PSOiFx1MDAxMKpcdTAwMTGrxyGKxZzhzz/PaHInXHUwMDE43+7UtnA00FQ00GZsXHUwMDA043utOIxN3Vx1MDAwNea1JsvBKX5AhoOgplxmLbBuRudcdTAwMWaubHRRqd2dsd1cIjvUd7dkvTNcdTAwMDHeXHUwMDFiTeDNLPNlXHUwMDE3ilx1MDAxMFx1MDAwMVx1MDAwZU6tNlx1MDAxMSBcdTAwMGVMoa9Smlx1MDAwMibA8mD/93fc+fWd0URcdTAwMTKDJrJcdTAwMWOaXGKaMq+GY7CyhfbRy+5cdTAwMDCQLk6L+1x1MDAwNd5vXHUwMDExXa3cnVx1MDAxY3xcdTAwMDI4ISo4MTYk9Fx1MDAxOJyY1JY03+NHJOVmg/BcdTAwMGbFXHUwMDEzRtp87cNcdTAwMTdYh1x1MDAxNoMnmlx1MDAxODy9zrI3UdugjbbtVuvCh1x1MDAxNtp+XHUwMDBiKqHt3fLra1x1MDAwNuVtP7pOL1x1MDAxZFx1MDAxNVx1MDAwZVx1MDAwZj6m1Fx1MDAwMUZcclx1MDAxOJxBhPrr26//XHUwMDAzdpOZKyJ9 data zdata ydata xChannelProcessdata xoutput xdata youtput ydata zoutput ztask 1task 2task 3

2.2 Execution abstraction

While a process defines what command or script has to be executed, the executor determines how that script is run in the target platform.

If not otherwise specified, processes are executed on the local computer. The local executor is very useful for workflow development and testing purposes, however, for real-world computational workflows a high-performance computing (HPC) or cloud platform is often required.

In other words, Nextflow provides an abstraction between the workflow’s functional logic and the underlying execution system (or runtime). Thus, it is possible to write a workflow that runs seamlessly on your computer, a cluster, or the cloud, without being modified. You simply define the target execution platform in the configuration file.

Execution abstraction

2.3 Scripting language

Nextflow implements a declarative DSL that simplifies the writing of complex data analysis workflows as an extension of a general-purpose programming language.

This approach makes Nextflow flexible — it provides the benefits of a concise DSL for the handling of recurrent use cases with ease and the flexibility and power of a general-purpose programming language to handle corner cases in the same computing environment. This would be difficult to implement using a purely declarative approach.

In practical terms, Nextflow scripting is an extension of the Groovy programming language which, in turn, is a super-set of the Java programming language. Groovy can be thought of as "Python for Java", in that it simplifies the writing of code and is more approachable.

2.4 Your first script

Here you will execute your first Nextflow script (hello.nf), which we will go through line-by-line.

In this toy example, the script takes an input string (provided with a parameter called params.greeting) and splits it into chunks of six characters in the first process. The second process then converts the characters to upper case. The result is finally displayed on-screen.

2.4.1 Nextflow code

Info

Click the icons in the code for explanations.

nf-training/hello.nf
#!/usr/bin/env nextflow
// (1)!
params.greeting = 'Hello world!' // (2)!
greeting_ch = Channel.of(params.greeting) // (3)!

process SPLITLETTERS { // (4)!
    input: // (5)!
    val x // (6)!

    output: // (7)!
    path 'chunk_*' // (8)!

    script: // (9)!
    """
    printf '$x' | split -b 6 - chunk_
    """
} // (10)!

process CONVERTTOUPPER { // (11)!
    input: // (12)!
    path y // (13)!

    output: // (14)!
    stdout // (15)!

    script: // (16)!
    """
    cat $y | tr '[a-z]' '[A-Z]'
    """
} // (17)!

workflow { // (18)!
    letters_ch = SPLITLETTERS(greeting_ch) // (19)!
    results_ch = CONVERTTOUPPER(letters_ch.flatten()) // (20)!
    results_ch.view { it } // (21)!
} // (22)!
  1. The code begins with a shebang, which declares Nextflow as the interpreter. This is optional, but recommended.
  2. Declares a parameter greeting that is initialized with the value 'Hello world!'.
  3. Initializes a channel labeled greeting_ch, which contains the value from params.greeting. Channels are the input type for processes in Nextflow.
  4. Begins the first process block, defined as SPLITLETTERS.
  5. Input declaration for the SPLITLETTERS process. Inputs can be values (val), files or paths (path), or other qualifiers (see here).
  6. Tells the process to expect an input value (val), that we assign to the variable 'x'.
  7. Output declaration for the SPLITLETTERS process.
  8. Tells the process to expect an output file(s) (path), with a filename starting with 'chunk_', as output from the script. The process sends the output as a channel.
  9. Three double quotes start and end the code block to execute this process. Inside is the code to execute — printing the input value 'x' (called using the dollar symbol [$] prefix), splitting the string into chunks with a length of 6 characters ("Hello " and "world!"), and saving each to a separate file (chunk_aa and chunk_ab).
  10. End of the first process block.
  11. Beginning of the second process block, defined as CONVERTTOUPPER.
  12. Input declaration for the CONVERTTOUPPER process.
  13. Tells the process to expect an input file (path; e.g. chunk_aa), that we assign to the variable 'y'.
  14. Output declaration for the CONVERTTOUPPER process.
  15. Tells the process to expect output as standard output (stdout) and sends this output as a channel.
  16. Three double quotes start and end the code block to execute this process. Within the block there is a script to read files (cat) using the '$y' input variable, then pipe to uppercase conversion, outputting to standard output.
  17. End of second process block.
  18. Start of the workflow scope where each process can be called.
  19. Execute the process SPLITLETTERS on the greeting_ch (aka greeting channel), and store the output in the channel letters_ch.
  20. Execute the process CONVERTTOUPPER on the letters channel letters_ch, which is flattened using the operator .flatten(). This transforms the input channel in such a way that every item is a separate element. We store the output in the channel results_ch.
  21. The final output (in the results_ch channel) is printed to screen using the view operator (appended onto the channel name).
  22. End of the workflow scope.

This pipeline takes params.greeting, which defaults to the string Hello world!, and splits it into individual words in the SPLITLETTERS process. Each word is written to a separate file, named chunk_aa, chunk_ab, chunk_acand so on. These files are picked up as the process output.

The second process CONVERTTOUPPER takes the output channel from the first process as its input. The use of the operator .flatten() here is to split the SPLITLETTERS output channel element that contains two files into two separate elements to be put through the CONVERTTOUPPERprocess, else they would be treated as a single element. The CONVERTTOUPPER process thus launches two tasks, one for each element. The bash script uses cat to print the file contents and tr to convert to upper-case. It takes the resulting standard-out as the process output channel.

2.4.2 Python instead of bash

If you're not completely comfortable with the bash code used in the example, don't worry! You can use whatever programming language you like within Nextflow script blocks. For example, the hello_py.nf file contains the same example but using Python code:

nf-training/hello_py.nf
    """
    #!/usr/bin/env python
    x="$x"
    for i, word in enumerate(x.split()):
        with open(f"chunk_{i}", "w") as f:
nf-training/hello_py.nf
    script:
    """
    #!/usr/bin/env python

Note that the $x and $y variables are interpolated by Nextflow, so the resulting Python scripts will have fixed strings here (x="Hello world!"). Check the hello_py.nf file for the full workflow script code.

2.4.3 In practice

Now copy the above example into your favorite text editor and save it to a file named hello.nf.

Warning

For the Gitpod tutorial, make sure you are in the folder called nf-training

Execute the script by entering the following command in your terminal:

nextflow run hello.nf

The output will look similar to the text shown below:

Output
N E X T F L O W  ~  version 23.10.1
Launching hello.nf [cheeky_keller] DSL2 - revision: 197a0e289a
executor >  local (3)
[31/52c31e] process > SPLITLETTERS (1)   [100%] 1 of 1 ✔
[37/b9332f] process > CONVERTTOUPPER (2) [100%] 2 of 2 ✔
HELLO
WORLD!
  1. The version of Nextflow that was executed.
  2. The script and version names.
  3. The executor used (in the above case: local).
  4. The first process is executed once, which means there is one task. The line starts with a unique hexadecimal value (see TIP below), and ends with the percentage and other task completion information.
  5. The second process is executed twice (once for chunk_aa and once for chunk_ab), which means two tasks.
  6. The result string from stdout is printed.

Info

The hexadecimal numbers, like 31/52c31e, identify the unique process execution, that we call a task. These numbers are also the prefix of the directories where each task is executed. You can inspect the files produced by changing to the directory $PWD/work and using these numbers to find the task-specific execution path.

Tip

The second process runs twice, executing in two different work directories for each input file. The ANSI log output from Nextflow dynamically refreshes as the workflow runs; in the previous example the work directory [37/b9332f] is the second of the two directories that were processed (overwriting the log with the first). To print all the relevant paths to the screen, disable the ANSI log output using the -ansi-log flag (e.g., nextflow run hello.nf -ansi-log false).

It’s worth noting that the process CONVERTTOUPPER is executed in parallel, so there’s no guarantee that the instance processing the first split (the chunk Hello ) will be executed before the one processing the second split (the chunk world!).

Thus, it could be that your final result will be printed out in a different order:

Output
WORLD!
HELLO

2.5 Modify and resume

Nextflow keeps track of all the processes executed in your workflow. If you modify some parts of your script, only the processes that are changed will be re-executed. The execution of the processes that are not changed will be skipped and the cached result will be used instead.

This allows for testing or modifying part of your workflow without having to re-execute it from scratch.

For the sake of this tutorial, modify the CONVERTTOUPPER process in the previous example, replacing the process script with the string rev $y, so that the process looks like this:

nf-training/hello.nf
process CONVERTTOUPPER {
    input:
    path y

    output:
    stdout

    script:
    """
    rev $y
    """
}

Then save the file with the same name, and execute it by adding the -resume option to the command line:

$ nextflow run hello.nf -resume
Output
N E X T F L O W  ~  version 23.10.1
Launching `hello.nf` [zen_colden] DSL2 - revision: 0676c711e8
executor >  local (2)
[31/52c31e] process > SPLITLETTERS (1)   [100%] 1 of 1, cached: 1 ✔
[0f/8175a7] process > CONVERTTOUPPER (1) [100%] 2 of 2 ✔
!dlrow
 olleH

You will see that the execution of the process SPLITLETTERS is skipped (the task ID is the same as in the first output) — its results are retrieved from the cache. The second process is executed as expected, printing the reversed strings.

Info

The workflow results are cached by default in the directory $PWD/work. Depending on your script, this folder can take up a lot of disk space. If you are sure you won’t need to resume your workflow execution, clean this folder periodically.

2.6 Workflow parameters

Workflow parameters are simply declared by prepending the prefix params to a variable name, separated by a dot character. Their value can be specified on the command line by prefixing the parameter name with a double dash character, i.e. --paramName.

Now, let’s try to execute the previous example specifying a different input string parameter, as shown below:

nextflow run hello.nf --greeting 'Bonjour le monde!'

The string specified on the command line will override the default value of the parameter. The output will look like this:

Output
N E X T F L O W  ~  version 23.10.1
Launching `hello.nf` [goofy_kare] DSL2 - revision: 0676c711e8
executor >  local (4)
[8b/7c7d13] process > SPLITLETTERS (1)   [100%] 1 of 1 ✔
[58/3b2df0] process > CONVERTTOUPPER (3) [100%] 3 of 3 ✔
uojnoB
m el r
!edno

2.7 In DAG-like format

To better understand how Nextflow is dealing with the data in this workflow, below is a DAG-like figure to visualize all the inputs, outputs, channels and processes:

Hello world diagram