雑に始めるCWL！をもっと雑に始めたい

# 注意

この記事は、すでに[雑に始める CWL！](https://qiita.com/tm_tn/items/4956f5ca523f7f49f386)や[続・雑に始める CWL！](https://qiita.com/tm_tn/items/83ce4c826135d78ba98f)を読んで、自分である程度動く CWL を書けるようになった人、つまり中級者以上を対象にしています。
まだ記事を読んでいない人は、まずは上の記事を読みつつ自分で CWL を書けるようになりましょう！

# はじめに

昨年の [CWL Advent Calendar](https://qiita.com/advent-calendar/2018/cwl) で、[雑に始める CWL！](https://qiita.com/tm_tn/items/4956f5ca523f7f49f386)という記事を書きました。
この記事では、既存のツールを CWL のツール定義として記述(以下、CWL 化と呼びます)する方法がわからない人向けに、とにかく動く CWL のツール定義を記述する方法を紹介しました。以下では、上記記事での CWL 化の方法を**雑方式**と呼ぶことにします。
[コミュニティ活動中](https://github.com/manabuishii/workflow-meetup/wiki/20190813-16)に行われた、[雑方式に基づく Live Coding](https://www.youtube.com/watch?v=sOAnIe8Mu-s&t=3689s)での状況を見ると、この方法は思っていたよりも幅広い人やツールに対して適用できそうだと感じました(が、この記事の主題はこちらではありません)。

また同時に、雑方式を使うと、ある程度作業的にツールの CWL 化を行えることがわかってきました。
物事を作業的にできるようになった次のステップ…**そう！自動化ですね！**

この記事では、雑方式に基づいて(そして通常の意味で雑な方法でも)ツールを CWL 化する [zatsu-cwl-generator](https://github.com/tom-tan/zatsu-cwl-generator) を紹介します。

# zatsu-cwl-generator とは

## コマンドを

```console
$ cat aaa.txt bbb.txt > output.txt
```

## 投げ込むと

```console
$ zatsu-cwl-generator "cat aaa.txt bbb.txt > output.txt"
```

## 対応する CWL 定義が出てくる

```console
$ zatsu-cwl-generator "cat aaa.txt bbb.txt > output.txt"
#!/usr/bin/env cwl-runner
# Generated from: cat aaa.txt bbb.txt > output.txt
class: CommandLineTool
cwlVersion: v1.0
baseCommand: cat
arguments:
  - $(inputs.aaa_txt)
  - $(inputs.bbb_txt)
inputs:
  - id: aaa_txt
    type: File
  - id: bbb_txt
    type: File
outputs:
  - id: all-for-debugging
    type:
      type: array
      items: [File, Directory]
    outputBinding:
      glob: "*"
  - id: out
    type: stdout
stdout: output.txt
```

# 機能いろいろ

- Docker コンテナが提供されているので実質インストール不要

```console
$ docker run --rm ttanjo/zatsu-cwl-generator:latest "cat aaa.txt bbb.txt > output.txt"
...
```

- コンテナを使う CWL 定義も出力できる

```console
$ zatsu-cwl-generator "cat aaa.txt bbb.txt > output.txt" --container alpine:latest
#!/usr/bin/env cwl-runner
# Generated from: cat aaa.txt bbb.txt > output.txt
class: CommandLineTool
cwlVersion: v1.0
baseCommand: cat
...
hints:
  - class: DockerRequirement # それっぽく DockerRequirement を追加してくれる
    dockerPull: alpine:latest
```

- オプション名からそれらしく出力オブジェクトの型を類推してくれる
  - あくまで「それらしく」なので過信は禁物

```console
$ zatsu-cwl-generator "gcc -o sample sample.c"
#!/usr/bin/env cwl-runner
# Generated from: gcc -o sample sample.c
class: CommandLineTool
cwlVersion: v1.0
baseCommand: gcc
arguments:
  - -o
  - $(inputs.o_name)
  - $(inputs.sample_c)
inputs:
  - id: o_name
    type: string # ちゃんと `-o sample` の sample を文字列扱いしている
  - id: sample_c
    type: File
outputs:
  - id: all-for-debugging
    type:
      type: array
      items: [File, Directory]
    outputBinding:
      glob: "*"
#  - id: o # 出力オブジェクトの候補に -o の引数を追加してくれる
#    type: Any
#    outputBinding:
#      glob: "$(inputs.o_name)"
```

# zatsu-cwl-generator が提供しないこと
このツールは、CWL をある程度わかっている人がボイラープレートコードを書く手間を省くためのツールです。
そのため、以下のことは現在行っていません。

- オプションや引数の完璧な解析
  - 多様なツールのオプションの型(`int` を受け取るとか `File` を受け取るとか)を完璧に当てるのは不可能です
  - `zatsu-cwl-generator` の出力が間違っていたら自分で修正しましょう

- 出力オブジェクトの完璧な補足
  - 例えば「引数のどこにも出てきてないけど、このツールは `hogehoge-analyze` というディレクトリを生成する」などを事前に知るのは不可能です
  - その代わり `zatsu-cwl-generator` では、出力ファイルやディレクトリを全てまとめて補足する `all-for-debugging` オブジェクトを定義します。まずはこれでどのようなファイルやディレクトリが生成されるか確認してから、各自の必要に応じた出力オブジェクトを定義していくのがいいでしょう

- コマンド名からの適切な使用コンテナの推測
  - [biocontainers](https://biocontainers.pro) などで様々なツールのコンテナが提供されていますが、あるコマンドを含むコンテナを検索する機能は提供されていません
  - この機能の実装は、与えられたコマンドからツール定義を出力するという `zatsu-cwl-generator` の機能から大幅に逸脱するため実装しません
  - 将来的に、うまく適切なコンテナを推測してくれるツールが現れれば、それを使って `zatsu-cwl-generator` の拡張を行うことはあるかもしれません

# そのうちやりたい

- コマンド列から CWL のワークフロー定義を生成したい

# おわり
みなさんもガンガン CWL を書いていきましょうね！