-
Notifications
You must be signed in to change notification settings - Fork 9
CWL Start Guide JP
このドキュメントは、Common Workflow Language (以下、CWL) について興味を持っている人に、CWLとはどんなもので、何を目的とした道具であるかを、15分で説明するためのドキュメントです。CWLの仕様の解説や、チュートリアルの提供を目的としたものではありません。
Pitagora Project のメンバーである、科学データ解析に携わる研究者と開発者です。このドキュメントについてのご意見ご感想や、CWLについて分からないことがあれば、Google フォーム から送ってください。もしくは、 Twitter でハッシュタグ #CommonWLjp を付けてつぶやいてください。
- 業務や研究でデータ解析ワークフローを使う、もしくは作る人
- ワークフローを実行するためのソフトウェア (実行エンジン) を設計する人
ソフトウェアを組み合わせて構成される一連の作業手順 (ワークフロー) を記述するための仕組みや言語、GUI ソフトウェアは既に多く存在します。しかし、それらは特定の実行環境 (ハードウェア、ソフトウェア) に依存したものであり、異なる環境の間でワークフローを共有、再実行することは困難です。この問題を解決するために、異なるワークフロー実行ソフトウェア (実行エンジン) の間で共通してインポート/エクスポートできるフォーマットを目指して、Common Workflow Language (CWL) の開発が始まりました。
CWL は Bioinformatics Open Source Conference (BOSC) 2014 Codefest の参加者によって立ち上げられた、特定の企業や大学、研究室、グラントに依存しない、オープンソースプロジェクトです。現在も、主に生命科学系の企業や大学の研究者の貢献によって GitHub, gitter などでコミュニケーション、議論、開発が進行しています。CWL自体は、生命科学系に限定されることなく、どの分野でも利用できる汎用的なものです。
以下に、CWL を使ってどのようにワークフローを記述するかを紹介します。
CWL では、ソフトウェア (コマンドラインツール) とワークフローの内容を YAML もしくは JSON の形式で記述し、.cwl という拡張子でファイルに保存します。実行時には、この CWL ファイルと、必要に応じて実行時パラメータを、CWL をサポートしている実行エンジンに入力すると、ワークフローが実行されます。
(このパートは http://www.commonwl.org/user_guide/02-1st-example/ の内容を反映しています)
Hello World を表示するツールを CWLで記述します。bash であれば、以下のコマンドです。
$ echo "Hello World"
Hello World
この処理を CWL で記述してみます。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: echo
inputs:
message:
type: string
inputBinding:
position: 0
outputs:
hello_output:
type: stdout
stdout: hello-out.txt
このファイル hello.cwl を CWL に対応している実行エンジンに入力すると、ツールが実行されます。CWL の標準実装である、cwltool の場合には以下のようになります。
$ cwltool helloworld.cwl --message 'Hello World'
以下、実行結果です。
$ cwltool helloworld.cwl --message 'Hello World'
/usr/local/bin/cwltool 1.0.20171107133715
Resolved 'helloworld.cwl' to 'file:///home/vagrant/hajimete/helloworld.cwl'
[job helloworld.cwl] /tmp/tmpPNAUDo$ echo \
'Hello World' > /tmp/tmpPNAUDo/hello-out.txt
[job helloworld.cwl] completed success
{
"hello_output": {
"checksum": "sha1$648a6a6ffffdaa0badb23b8baf90b6168dd16b3a",
"basename": "hello-out.txt",
"location": "file:///home/vagrant/hajimete/hello-out.txt",
"path": "/home/vagrant/hajimete/hello-out.txt",
"class": "File",
"size": 12
}
}
Final process status is success
出力結果を確認します。
$ cat hello-out.txt
Hello World
以下に、CWL ファイルを各パートごとに解説します。
cwlVersion: v1.0
cwlVersion
キーワードで、準拠しているCWLのバージョンを記述します。
class: CommandLineTool
class
キーワードで、これが単独のツールを実行する (ワークフローではない) コマンドラインツールであることを示す CommandLineTool
を指定します。
baseCommand: echo
baseCommand
で 実行されるコマンドを指定します。この場合は echo コマンドです。
inputs:
message:
type: string
inputBinding:
position: 0
inputs
キーワードで、コマンドに与える入力について記述します。ここでは message
という名前をつけて1つのコマンド入力を定義しています。message
には echo
コマンドに与える文字列が入るので、 type
キーワードで入力データの型 string
を指定します。inputBinding
キーワードを使って、 baseCommand
に message
がどのように渡されるかを指定します。ここでは、position
キーワードを使って、コマンドライン上の echo
コマンドの直後 (0番目) に message
が渡されるように定義します。
outputs:
hello_output:
type: stdout
outputs
キーワードで、コマンドから得る出力について記述します。ここでは hello_output
という名前をつけて、1つの出力を得ます。hello_output
は標準出力に書き込まれる文字列を得たいので type
キーワードで stdout
を指定します。
stdout: hello-out.txt
stdout
キーワードで、標準出力を取得します。stdout: hello-out.txt
によって、標準出力に出た文字列を hello-out.txt
というファイルに書き込みます。
下図の処理を実行するワークフローを CWL で記述します。この処理では入力ファイル(file_to_search
) から特定のパターン (pattern
) を含む行数を grep
コマンドで抽出し、その出現回数を wc
コマンドでカウントします。wc
の結果 (counts
) がワークフローの出力です。
例として、以下のテキストを保存した mock.txt から、パターン one が含まれる行の出現回数を調べます。
one
two
one
three
bash では以下のように行います。
$ grep one mock.txt > grepout.txt
$ wc -l grepout.txt > wcout.txt
$ cat wcout.txt
2
このワークフローを CWL として記述する前に、以下のように grep と wc を実行する CWL をそれぞれ記述します。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: grep
inputs:
pattern:
type: string
inputBinding:
position: 0
file_to_search:
type: File
inputBinding:
position: 1
outputs:
results: stdout
stdout: grepout.txt
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [wc, -l]
inputs:
file:
type: File
inputBinding:
position: 0
outputs:
counts: stdout
stdout: wcout.txt
次に、この2つのコマンドラインツールを使い、grep をして wc をするワークフローを作成します。
cwlVersion: v1.0
class: Workflow
inputs:
grep_pattern:
type: string
target_file:
type: File
outputs:
counts:
type: File
outputSource: wc/counts
steps:
grep:
run: grep.cwl
in:
pattern: grep_pattern
file_to_search: target_file
out: [results]
wc:
run: wc.cwl
in:
file: grep/results
out: [counts]
このワークフローを、cwltool を使って実行してみます。
$ cwltool grep-and-count.cwl --target_file mock.txt --grep_pattern one
実行するとこのようになります。
$ cwltool grep-and-count.cwl --target_file mock.txt --grep_pattern one
/usr/local/bin/cwltool 1.0.20171107133715
Resolved 'grep-and-count.cwl' to 'file:///home/vagrant/cwl-samples/grep-and-count.cwl'
[workflow grep-and-count.cwl] start
[step grep] start
[job grep] /tmp/tmpH0lrD9$ grep \
one \
/tmp/tmplmLMRE/stga2fed2a1-73d3-4739-8a71-a3bff07a210b/mock.txt > /tmp/tmpH0lrD9/grepout.txt
[job grep] completed success
[step grep] completed success
[step wc] start
[job wc] /tmp/tmpsV7RZO$ wc \
-l \
/tmp/tmp74O9fg/stg92157e74-dce3-4ea2-beaf-725d6390249e/grepout.txt > /tmp/tmpsV7RZO/wcout.txt
[job wc] completed success
[step wc] completed success
[workflow grep-and-count.cwl] completed success
{
"counts": {
"checksum": "sha1$3d069f5c2f47dd7b91490991378518c18ec84e86",
"basename": "wcout.txt",
"location": "file:///home/vagrant/cwl-samples/wcout.txt",
"path": "/home/vagrant/cwl-samples/wcout.txt",
"class": "File",
"size": 69
}
}
Final process status is success
実行結果を確認します。
$ cat wcout.txt
2 /tmp/tmpYg7Goq/stg73ea3c6a-5ac1-4a63-94ad-4eaed213ab82/grepout.txt
mock.txtの中にある。 'one' という文字列が含まれている行数が、 2
であることが確認できます。
以下、ワークフロー記述を各パートごとに解説します。
cwlVersion: v1.0
CommandLineTool と同じく、 cwlVersion
キーワードで準拠している CWL ツールのバージョンを記述します。
class: Workflow
class
キーワードで、ツールを組み合わせた Workflow
であることを記述します。
inputs:
grep_pattern:
type: string
target_file:
type: File
inputs
キーワードで、ワークフロー全体の入力を記述します。ここでは、 pattern
, file_to_search
と名前をつけた 2つの入力があることを示します。それぞれ、string
, File
と型を指定します。
outputs:
counts:
type: File
outputSource: wc/counts
outputs
キーワードで、ワークフロー全体の出力を記述します。counts
と名前をつけて、wcコマンドの出力を得るよう指定します。 type
は File
です。 outputSource
キーワードを使って、後述の steps
内の wc
における出力 counts
を取得するよう、 wc/counts
と記述します。
steps:
grep:
run: grep.cwl
in:
pattern: grep_pattern
file_to_search: target_file
out: [results]
wc:
run: wc.cwl
in:
file: grep/results
out: [counts]
(stepは、ワークフローとしての識別子と、ツールとしての識別子がでてきており、頭の中でマッピングしながら理解する必要があり、大変です。これを書いた人たちもつらかったです。しかし、CWLの肝なので、落ち着いてゆっくりと何度も大きく声に出して読んでください。図も見ながら読むと理解の手助けになります。)
steps
キーワードで、ワークフローの各ステップを記述します。各 step は自由に名前をつけられますが、ここでは grep
と wc
としました。各 step では、 run
キーワードで、それぞれの CommandLineTool を記述した CWL ファイルのファイル名を指定します。また、in
と out
のキーワードを使って、各ステップの入力、出力を指定します。
最初に実行される grep
の入力は、ワークフロー全体の入力を受け取るため、前述の grep_pattern
と target_file
を指定します。pattern: grep_pattern
において、grep.cwl
内で定義された入力 pattern
に、grep-and-count.cwl
における入力 grep_pattern
を与えることを示しています。file_to_search: target_file
も同様です。out
では、 grep.cwl 内で定義された results
を指定します。この場合のみ、[]
で囲む必要があります。
次に実行される wc
の入力は、grep
の出力 results
を受け取るため、grep/results
と記述します。ここでも同じく、 wc.cwl で定義された counts
を取得するため [counts]
と記述します。
ツール定義は主に、実行コマンド定義、入力定義、出力定義および動作要件定義(オプション)から構成されます。実行コマンド定義では実行するプログラム名や Docker のイメージ名を指定することができます。入力定義では各入力の型や引数として与える順序を指定できます。出力定義ではツールの出力として、標準出力や出力ファイル名を指定します。動作要件指定では、搭載メモリ量の下限など、コマンドを実行するために必要な条件を指定できます。
ワークフロー定義は主に、ツール定義と同様の入出力定義および各ステップの定義から構成されます。各ステップの入力として他のステップの出力を指定することで、ステップ間の依存関係を記述します。
CWL v1.0 では、ループや条件分岐の記述をサポートしていません。ただし CWL への機能追加は現在も議論されており、将来的にサポートされる可能性はあります。また各ステップの並列処理や、使用するジョブスケジューラの指定等も CWL ではサポートしていません。実行エンジンによっては、別途サポートしていることがあります。
http://www.commonwl.org/#Repositories_of_CWL_Tools_and_Workflows に、GitHub などで公開されている CWL 記述へのリンクがあります。
CWL の仕様を満たす標準実装として、cwltool というワークフロー実行エンジンが CWL と合わせて開発されています (https://github.com/common-workflow-language/cwltool)。高機能ではありませんが、CWL を入力としてワークフローの実行ができます。頻繁に更新されるため、実運用には注意が必要です。
http://www.commonwl.org/#Implementations に、CWL のインポート・エクスポートに対応している実行エンジンのリストがあります。
http://www.commonwl.org/#Software_for_working_with_CWL に、CWL の可視化、エディタのサポート、各種プログラミング言語のバインディングなどのリストがあります。
公式のユーザーガイド http://www.commonwl.org/user_guide/ があるので、そちらをやってみるとよいでしょう。3時間位あれば一通りのことができます。
- 公式サイト
- ツール定義仕様
- ワークフロー定義仕様
- 仕様書の Github
- cwltool (標準実装)
- schema-salad (CWL のバリデータ)
- CWL YouTube channel