はじめに
真面目に CWL を書いてみたい場合には、公式で提供している User Guide や、日本の CWL コミュニティが公開している CWL ファイルが参考になると思います。
この記事ではそうではなく、「CWL の細かい文法とかどうでもいい。とりあえず今動いてるツールをそれっぽく CWL 化して CWL のワークフローから使えるようにしたい」という方向けに、できるだけ細かい文法要素に踏み込まずにツールの定義ファイルを CWL で書く例を示します。
注意
- 本記事では、ツールのオプションをうまいこと扱う方法については書きません。様々なオプションを入力パラメータとして与えたい場合には、まじめに CWL を書きましょう。
CWL 化したいツール
以下のツールの定義ファイルを CWL で書くことを考えます。
このコマンドは、引数で与えられたファイルの先頭数行を、標準出力に表示します。
出力する行数は -n
で与えられます。
$ head -n5 foobar.txt
-
-n5
の5
と、foobar.txt
を入力パラメータとして与えたい。 -
head
コマンドの標準出力を、ツールの出力オブジェクトとして取得できるようにしたい。 - 他のオプションは知らぬ。
ツール自体の動作サンプル
$ man head > manhead.txt
$ head -n5 manhead.txt
HEAD(1) BSD General Commands Manual HEAD(1)
NAME
head -- display first lines of a file
作成
- まず以下を
head.cwl
としてコピーします。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: []
arguments: []
inputs: []
outputs: []
-
baseCommand
に、先程のコマンドの先頭部分、それ以降をarguments
に追加します。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [head]
arguments: [-n5, foobar.txt]
inputs: []
outputs: []
- 入力パラメータを
inputs
に追加します。今回は表示したいファイルであるsource
、先頭n
行を表すnlines
を導入します。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [head]
arguments: [-n5, foobar.txt]
inputs:
- id: source
- id: nlines
outputs: []
- 各入力パラメータに型を追加します。
source
はファイルなのでFile
、nlines
は整数値を取るのでint
です。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [head]
arguments: [-n5, foobar.txt]
inputs:
- id: source
type: File
- id: nlines
type: int
outputs: []
-
arguments
に5
やfoobar.txt
が残ったままなので、それぞれnlines
とsource
の値に置き換えるようにします。これは$(inputs.idフィールド名)
という記法で実現できます。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [head]
arguments: [-n$(inputs.nlines), $(inputs.source)]
inputs:
- id: source
type: File
- id: nlines
type: int
outputs: []
- 出力パラメータを追加します。今回はとりあえず
out
という名前をつけます。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [head]
arguments: [-n$(inputs.nlines), $(inputs.source)]
inputs:
- id: source
type: File
- id: nlines
type: int
outputs:
- id: out
- 入力パラメータの時と同様に、出力パラメータに型を付けます。標準出力を取得したい場合には
stdout
型を使えばいいです。
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [head]
arguments: [-n$(inputs.nlines), $(inputs.source)]
inputs:
- id: source
type: File
- id: nlines
type: int
outputs:
- id: out
type: stdout
- できあがり!
動かしてみる
試しに source
が manhead.txt
、nlines
が 5
の場合を試してみます。
$ man head > manhead.txt
$ cwltool head.cwl --source manhead.txt --nlines 5
...
[job head.cwl] completed success
{
"out": {
"location": "file:///Users/tom-tan/147d6ad946430f35c2aafbff6c5604d43b30aa14",
"basename": "147d6ad946430f35c2aafbff6c5604d43b30aa14",
"class": "File",
"checksum": "sha1$30c2a20de147871db76e237705ac274277504428",
"size": 145,
"path": "/Users/tom-tan/147d6ad946430f35c2aafbff6c5604d43b30aa14"
}
}
Final process status is success
$ cat 147d6ad946430f35c2aafbff6c5604d43b30aa14
HEAD(1) BSD General Commands Manual HEAD(1)
NAME
head -- display first lines of a file
-
[job head.cwl] completed success
以下に、出力オブジェクトが表示されます。- 今回の場合、
out
として147d6ad9464...
という名前のファイルオブジェクトがあるのがわかります。
- 今回の場合、
- 実際に
cat
コマンドで確認すると、ツール自体の動作サンプルと同様の内容が得られたことがわかります。
次のステップ
出力ファイル名がひどい
stdout
フィールドで標準出力を保存するファイル名を指定できます。
...
outputs:
- id: out
type: stdout
stdout: output.txt # この行を追加
source
のファイル名が manhead.txt
の時には、出力ファイル名を manhead-head.txt
にしたい
$()
記法を活用すればいいです。File
オブジェクトの nameroot
フィールドを使うことで、manhead.txt
から manhead
のみを取り出すことができます。
...
outputs:
- id: out
type: stdout
stdout: $(inputs.source.nameroot)-head.txt # この行を変更
Docker で動かしたい
DockerRequirement
というものを使います。またdockerPull
で、利用したい docker イメージ名を指定します。
...
outputs:
- id: out
type: stdout
stdout: $(inputs.source.nameroot)-head.txt
# 以下を追記
requirements:
- class: DockerRequirement
dockerPull: debian:latest
volume mount などの細かい部分は、CWL の処理系がうまいことやってくれます。
おわり
今回はツール定義を CWL で書く方法を示しました。
これで CWL 書き放題ですね!!!
おまけ
続編書きました。