CWLを学ぶ part 2
以前のエントリでCWL (Common Workflow Language) について簡単にまとめたが、マニュアルやgithubを見ていると、いくつか知らない機能があることがわかったので、改めてメモを残しておこうと思う。
BioContainer
CWLとは直接は関係がないが、BioContainerには、多種多様なバイオインフォ系のツールをすぐに実行可能なDocker/Singularityイメージが登録されている。マイナーなツールもかなり見つかるので、まずはここを検索してみることを推奨する。
Scatter
複数のサンプルのFASTQファイルを同じリファレンスゲノムにマッピングする場合など、同一作業を繰り返す場合に使われる。*1
ここでは複数のgzipファイルを一つずつ解凍するワークフローを考える。以下のyamlを書くと変数gzに複数ファイルを配列として格納することができる。
# scatter_example.yaml gz: - class: File location: test_data_16s_light/ERR3668533_15_L001_R1_001.fastq.gz - class: File location: test_data_16s_light/ERR3668533_15_L001_R2_001.fastq.gz - class: File location: test_data_16s_light/ERR3668534_15_L001_R1_001.fastq.gz - class: File location: test_data_16s_light/ERR3668534_15_L001_R2_001.fastq.gz
stepsの中でscatter
を使うことで、複数の入力に対して同一のステップを繰り返し実行することができる。以下の例では、配列gzに含まれる各ファイルに対して、ステップgunzip
を繰り返している。この場合、ステップgunzip
の出力も配列となるため、このワークフローの出力gunzipped
の型にはファイルの配列 (File[]) を指定している。requirementsにScatterFeatureRequirementをつけないとエラーとなるので注意。
# scatter_example.cwl cwlVersion: v1.2 class: Workflow doc: scatter test requirements: ScatterFeatureRequirement: {} # これが必要 inputs: gz: label: gzipped files type: File[] steps: gunzip: run: components/gunzip.cwl scatter: gz # ここ in: gz: gz out: [gunzipped] outputs: gunzipped: type: File[] outputSource: gunzip/gunzipped
when
CWL version 1.2から追加された機能。これを使うことでif/else的な条件分岐が可能となる。
入力seq_type
がse
(single-end)とpe
(paired-end)の場合でデータ処理のパイプラインを変える場合を想定する。この場合はstepにwhenを以下のように挟むことで条件分岐を実現することができる。この場合注意すべきは、ステップpipeline_se
とpipeline_pe
がseq_type
を入力として受け取る必要がない場合でも、whenを使う場合にはinputにseq_type
を入れなければエラーが出る仕様になっているので注意。*2
# when_example.cwl cwlVersion: v1.2 class: Workflow doc: scatter test requirements: InlineJavascriptRequirement: {} MultipleInputFeatureRequirement: {} inputs: input_file_dir: label: input directory type: Directory seq_type: label: sequencing type ("pe" or "se") default: "se" type: string steps: pipeline_se: in: seq_type: seq_type input_file_dir: input_file_dir when: $(inputs.seq_type == "se") run: components/pipeline_se.cwl out: [out] pipeline_pe: in: seq_type: seq_type input_file_dir: input_file_dir when: $(inputs.seq_type == "pe") run: components/pipeline_pe.cwl out: [out] outputs: result: type: File outputSource: - pipeline_se/out - pipeline_pe/out pickValue: first_non_null
ファイルを一箇所にまとめる
ワークフローでたくさんのファイルが出力される場合は、それを特定の名前のディレクトリに集約できるとありがたい。その方法が紹介されているページ*3があったのでメモ。以下のようにExpressionToolで実現できる。
cwlVersion: v1.0 class: ExpressionTool requirements: InlineJavascriptRequirement: {} inputs: file1: type: File file2: type: File file3: type: File file4: type: File outputs: dirs: type: Directory[] expression: |- ${ var dirs = []; dirs.push({ "class": "Directory", "basename": inputs.file1.nameroot + "_1", "listing": [inputs.file1, inputs.file2] }); dirs.push({ "class": "Directory", "basename": inputs.file1.nameroot + "_2", "listing": [inputs.file3, inputs.file4] }); return {"dirs": dirs}; }