Nextflow 入門 Hello World ワークフローの実行内容を解説

2023.05.20

Nextflow に入門しました。Workflow の独自言語でワークフローを定義することになるわけですが、初見で自由に書けるほど甘くはなく相応の学習コストが必要でした。そこで定番の Helo World を例に基本的な説明と、書き方の参考になったドキュメントを紹介します。

実行環境

Name Version
Nextflow 23.04.1
DSL 2

DSL のバージョンに注意

Nextflow 独自のワークフロー記述言語(Domain Specific Language)には2バージョンあります。旧世代のDSLと現行世代のDSL2です。

DSLのバージョン違いで注意しないといけないのは完全な後方互換性はないことです。

Nextflow の書き方を学ぶために検索すると旧世代のDSLで記述されたワークフローがヒットすることもあります。そのまま実行するには「旧世代のDSLを使ったワークフローですと明示」しないと現行の Nextflow のバージョンだと実行できません。

DSLからDSL2への移行ガイドはあるのですが Nextflow の記述方法がわからない段階では難易度が高く感じます。私は Nextflow の記述方法がわかってない状態で書き換えは無理だなと諦めました。

DSL 2 — Nextflow 23.04.1 documentation

参考になったドキュメント類

これから紹介するmain.nfの内容を理解するためには Nextflow の Basic Training で説明されている内容が有用でした。

最初に公式ドキュメントを参考にされるなら上記リンクがよろしいかと思います。

Hello World を紐解く

Nextflow のセットアップをした後は動作確認のためにnextflow run helloコマンドを一度は実行した経験があるのではないでしょうか?

$ nextflow run hello
N E X T F L O W  ~  version 23.04.1
Launching `https://github.com/nextflow-io/hello` [serene_yalow] DSL2 - revision: 1d71f857bb [master]
executor >  local (4)
[b0/6ca63b] process > sayHello (1) [100%] 4 of 4 ✔
Hola world!

Hello world!

Ciao world!

Bonjour world!

nextflow runを実行するとこの場合はhelloというファイル名のファイルをカレントディレクトリから探し、なければ同じ名前の GitHub のリポジトリを探し、実行スクリプトを取得してきてローカルで実行した結果が表示されたことになります。

When you launch a script execution with Nextflow, it will look for a file with the pipeline name you’ve specified. If that file does not exist, it will look for a public repository with the same name on GitHub (unless otherwise specified). If it is found, the repository is automatically downloaded to your computer and executed.

Pipeline sharing — Nextflow 23.04.1 documentation

つまり、今回はこちらのnextflow-io/helloリポジトリからmain.nfファイルを取得し実行していたわけです。

main.nf

#!/usr/bin/env nextflow
nextflow.enable.dsl=2

process sayHello {
  input:
    val x
  output:
    stdout
  script:
    """
    echo '$x world!'
    """
}

workflow {
  Channel.of('Bonjour', 'Ciao', 'Hello', 'Hola') | sayHello | view
}

Hello World のスクリプト(main.nf)の内容を解説します。

main.nf はなにをしているのか?

わかりやすくコメントを追記しました。気になって調べた点は別途後述しています。

main.nf

#!/usr/bin/env nextflow // シェバンで nextflow を指定
nextflow.enable.dsl=2 // DSL2 を利用すると明示的に宣言

process sayHello { // プロセスはいわゆる関数みたいなもの
  input:
    val x // Channel.of() の引数で渡している文字列(Bonjor)を変数 x に格納
  output:
    stdout // 出力先を標準出力に指定 ※標準出力へ内容を返すにはオペレーターの view が必要
  script:
    """
    echo '$x world!' // $変数名で変数を展開
    """
}

workflow { // プロセスの実行順番やプロセスへ渡す引数など全体の処理の流れを定義
  Channel.of('Bonjour', 'Ciao', 'Hello', 'Hola') | sayHello | view // 後述
}

DSL2 の利用を明示について

Nextflow 23.04.1 ではデフォルトで DSL2 が利用されます。そのため、現行バージョンで実行する分にはnextflow.enable.dsl=2の記述を省略しても動作します。

DSL 2 — Nextflow 23.04.1 documentation

プロセス名の命名規則について

プロセス名はsayHelloとキャメルケース(ローワーキャメルケース)で書かれていますが、Nextflow ではすべて大文字で書くアッパケースが一般的とドキュメントに記述がありました。

The process name is commonly written in upper case by convention.

Processes - training.nextflow.io

workflow 内の指示について

workflow で記述した process の実行順番の指示や、引数を渡したり全体の流れの指示を行います。

指示内容がワンライナー(実行コマンドをパイプで繋いで1行にまとめてある)のため逆に理解に苦しみました。

workflow {
  Channel.of('Bonjour', 'Ciao', 'Hello', 'Hola') | sayHello | view
}

理解しづらかったのでパイプを分解して同じ動作する様に書き換えたものが以下です。

workflow {
  input_ch = Channel.of('Bonjour', 'Ciao', 'Hello', 'Hola')
  results = sayHello(input_ch)
  results.view()
}

Channel.of()の動作は与えられた引数に対応する引数毎の個別のチャネルが生成されます。Channelにはofメソッドがあり、その説明が以下です。

The of method allows you to create a channel that emits the arguments provided to it, for example:

Channels — Nextflow 23.04.1 documentation

つまり、引数毎のキューが生成され、個別のキュー内にはそれぞれメッセージとして引数の値が入っています。その状態をinput_chに格納しています。

次にsayHelloプロセスにinput_chを引数にして渡します。チャンネル毎に並列でsayHelloが実行されます。sayHelloプロセスは引数に指定したBonjorを変数xに格納しechoコマンドで変数の内容を展開して実行しています。その出力結果は標準出力(stdout)を指定しています。実行結果を workflow の定義内でresultsに格納しています。

process sayHello {
  input:
    val x
  output:
    stdout
  script:
    """
    echo '$x world!'
    """
}

そして、view がないと標準出力へ結果を返せないです。

最後にresults.view()sayHelloの実行結果を表示しています。これでコンソール画面に文字列が表示されることになります。

viewというオペレーターの存在を知らずstdoutを指定しているのにもかかわらず画面に表示されなくハマりました。

The view operator prints the items emitted by a channel to the console standard output, appending a new line character to each item. For example:

Operators - training.nextflow.io

Hello World の実行内容の解説は以上です。

おわりに

RNA-Seq解析パイプラインを作成したかったので[nf-core/rnaseq: RNA sequencing analysis pipeline using STAR, RSEM, HISAT2 or Salmon with gene/isoform counts and extensive quality control.]をベースにして学ぼうかと思ったのですがあまりにも重厚なワークフローで記述方法がわかって初学者が読み解くのは難しかったです。基本的な Nextflow のお作法を学んで最小限のワークフローをゼロから生み出す方法でやっていく方法としました。手始めに Hello World のワークフローの実行内容を調べたときのまとめでした。