遺伝研スパコンで Singularity とか CWL を使う上での tips

# はじめに
2019年3月のスパコンリプレイスに伴い、遺伝研スパコンで Singularity コンテナが利用できるようになりました。スパコンウェブサイトに Singularity の[簡単な使い方](https://sc.ddbj.nig.ac.jp/ja/guide/software/singularity)が書かれていますが、実際に使ってみると意外なところに落とし穴があってハマります。Singularity とは？Docker コンテナとの違いは？といった説明は @mkt3 氏の[記事](https://qiita.com/mkt3/items/b9f86f5ddf9eb0f43608)に詳しいので省略しますが、ここでは主に初心者を対象として、Singularity を使う上での trouble shoot や tips を紹介します。  
~~また、関連してCommon Workflow Language (CWL)で書かれたワークフローを実行する方法も紹介します。~~分量が増えたので CWL に関しては[別ページ](https://qiita.com/nigyta/items/e62e8a307918f42baed2)に分けました。

追記）Singularity を使って BUSCO を動かすまでの過程を記録しました。この記事の内容のより実践的な位置付けです。[→こちら](https://qiita.com/nigyta/items/bf37787be6153bdbaed1)

# どうやって使う？
スパコンの /usr/local/biotools/ 以下にアルファベットごとに分かれてSingularityコンテナイメージが格納されています。

```
$ ls /usr/local/biotools/
a/            c/            f/            i/            l/            o/            r/            u/            x/
b/            d/            g/            j/            m/            p/            s/            v/            y/
bioconductor/ e/            h/            k/            n/            q/            t/            w/            z/
```
たとえばsamtoolsなら

```
$ ls /usr/local/biotools/s/samtools*
/usr/local/biotools/s/samtools:0.1.12--0  /usr/local/biotools/s/samtools:1.3--2  /usr/local/biotools/s/samtools:1.5--0
/usr/local/biotools/s/samtools:0.1.13--0  /usr/local/biotools/s/samtools:1.3.1--2  /usr/local/biotools/s/samtools:1.5--1
/usr/local/biotools/s/samtools:0.1.14--0  /usr/local/biotools/s/samtools:1.3.1--3  /usr/local/biotools/s/samtools:1.5--2
/usr/local/biotools/s/samtools:0.1.15--0  /usr/local/biotools/s/samtools:1.3.1--4  /usr/local/biotools/s/samtools:1.6--0
/usr/local/biotools/s/samtools:0.1.19--2  /usr/local/biotools/s/samtools:1.3.1--5  /usr/local/biotools/s/samtools:latest
/usr/local/biotools/s/samtools:1.0--0     /usr/local/biotools/s/samtools:1.4--0
/usr/local/biotools/s/samtools:1.3--1     /usr/local/biotools/s/samtools:1.4.1--0
```

に各バージョンごとのイメージがあります。`:`の後はバージョン番号で、`--`の後はビルド番号を示します。ビルド番号は基本的に新しいものを使った方が良いでしょう。
使用するには、

```
$ singularity exec コンテナイメージファイルパス 実行したいコマンド
```

と実行します。具体的には、

```
$ singularity exec /usr/local/biotools/s/samtools:1.6--0 samtools view alignment.bam
```
といった感じです。毎回絶対パスで指定するのが面倒だという場合には、次のようにエイリアスを設定しておくと通常のコマンドと同じように呼び出せます。


```
$ alias samtools='singularity exec /usr/local/biotools/s/samtools:1.6--0 samtools'
$ samtools view alignment.bam > alignment.sam
# パイプも使える
$ samtools view -b alignment.sam | samtools sort > alignment.sort.bam
```

このように、Singularity を使えば自分でインストールする手間をかけることなく手軽にツールを実行することが可能です。ただし、スパコンで提供されているイメージファイルは　[BioContainers](https://biocontainers.pro/) で提供されている　Docker イメージを定期的に取り込み　Singularity に変換したものなので、必ずしも　Singularity での動作が保証されているわけではありません。そのような場合には、次に紹介するようにコンテナに入って原因解明を行うこともあります。**（Singularityで動かすことにこだわらず、自分でインストールしてしまった方が早いことも多々あり）**


# コンテナに入る
`singularity shell`でコンテナ内に入ってコマンドを実行できます。

```
$ singularity shell /usr/local/biotools/s/samtools:1.6--0
```
Singularity では $HOME はコンテナ内の環境に自動的にマウントされるため、自分のホームディレクトリ内のファイルは自由に読み書きできます。ただし、それ以外の /usr/local などはコンテナ内のものが見えていて、コンテナ外（ホスト側）のものは見えなくなっています（コンテナ内の実行環境はコンテナ外とは独立しているので当然といえば当然）。コマンドがうまく動かないときなどには原因解明のためコンテナ内のディレクトリ構造やどこにツールがインストールされているかを調べましょう。
コンテナから抜けるには`exit`と打つか、ctrl-Dを押します。

# ディレクトリのマウント
$HOME 以外の場所にあるファイルを参照したい場合には、実行時にディレクトリをマウントする必要があります。例えば遺伝研スパコンには`/usr/local/seq`以下に BLAST の参照 DB が格納されていますが、そのままでは使用できません。以下の方法でディレクトリをマウントすることで参照可能になります。

- `--bind (または-B)`オプションを使用する方法 

    ```
    singularity exec --bind /usr/local/seq /usr/local/biotools/b/blast:2.7.1--boost1.64_1 blastp -query query.fa -db /usr/local/seq/blast/ncbi/swissprot
    ```
    `--bind`オプションは複数回指定することも可能です。


- 環境変数 `SINGULARITY_BINDPATH` を指定する方法

    ```
$ export SINGULARITY_BINDPATH=/usr/local/seq
$ singularity exec /usr/local/biotools/b/blast:2.7.1--boost1.64_1 blastp -query query.fa -db /usr/local/seq/blast/ncbi/swissprot
    ```

 
# 環境変数について
ほとんどの環境変数はコンテナ実行時に引き継がれますが、`$PATH`は引き継がれません（コンテナ内の実行環境はコンテナ外とは独立しているのでこれも当然）。`printenv`でコンテナ内の環境変数を確認できます。

```
$ singularity exec /usr/local/biotools/s/samtools:1.6--0 printenv
```

実行前に環境変数を設定しておくことで、エラーや警告を回避できることがあります。

- localeに関するエラー・警告の回避  
`export LANG=C`や`export LC_ALL=C`を実行前に設定しておく  
`--bind /usr/lib/locale/locale-archive`オプションをつけて実行する方法もある

    ```
 $ singularity exec --bind /usr/lib/locale/locale-archive /usr/local/biotools/t/trimmomatic:0.36--5 trimmomatic
     ```

# 共有ライブラリの追加
OrthoFinder というオルソロググループを推定するソフトでは内部的に BLAST を使用しています。OrthoFinder の Singularity イメージには BLAST が同梱されていますが、イメージ内にライブラリが欠けているためか実行することができません（将来的に fix される可能性はあります）。

```
$ singularity exec  /usr/local/biotools/o/orthofinder:1.1.8--py27_0 blastp -h
blastp: error while loading shared libraries: libbz2.so.1: cannot open shared object file: No such file or directory
```
このような場合には、環境変数`SINGULARITY_CONTAINLIBS`を設定してスパコンの`/lib64`や`/usr/lib64`内に存在する`libbz2.so.1`をコンテナ内のライブラリに追加することでエラー回避ができます。

```
$ export SINGULARITY_CONTAINLIBS=/lib64/libbz2.so.1.0.6,/lib64/libbz2.so.1
$ singularity exec  /usr/local/biotools/o/orthofinder:1.1.8--py27_0 blastp -h
USAGE
  blastp [-h] [-help] [-import_search_strategy filename] ...
```
なお、`libbz2.so.1`は`libbz2.so.1.0.6`へのリンクになっているので、ライブラリ本体である`libbz2.so.1.0.6`も同時に追加しています。

また、ちょっと乱暴な手ですが

```
singularity exec --bind /lib64/ /usr/local/biotools/o/orthofinder:1.1.8--py27_0 blastp -h
```

というように`/lib64`をコンテナにマウントしてしまうという方法もあります。ただし、これはコンテナ内の`/lib64`を上書きしてしまうことになるので、BLASTが動くようになったとしても他のツールを実行する際にエラーが生じる可能性はあります。

ここで挙げた例のようにコンテナ内のライブラリの依存関係が壊れていてツールが動作しないというケースは十分に考えられます。その際には異なるビルド番号のものを試すか、コンテナを使用せずに自分でインストールを行ってしまった方が早いケースがあります。


# 自前のコンテナを使いたい
`/usr/local/biotools/`に用意されていないコンテナを使用したい場合には、自前でコンテナを用意することができます。簡単なのは[Singularity Hub](https://singularity-hub.org)で公開されているものを利用するか、[Docker Hub](https://hub.docker.com) で公開されている Docker コンテナイメージを Singularity に変換する方法です。いずれも`singularity pull`で取得してコンテナをビルドできます。
以下の例は、BioContainers から[wtdbg2](https://quay.io/repository/biocontainers/wtdbg) (別名 Redbean、2019/10現在で /usr/local/biotools/ からは利用できない) というゲノムアセンブラーのコンテナをビルドする方法です。    

```
singularity pull docker://quay.io/biocontainers/wtdbg:2.5--h8b12597_0
```

また、下記は SingularityHub の DDBJ レポジトリから MySQL のイメージを"mysql.simg"という名称で取得するものです。（スパコン上でユーザー権限で MySQL を動かす具体的な手順は[こちら](https://github.com/ddbj/singularity_mysql)へ）

```
singularity pull --name mysql.simg shub://ddbj/singularity_mysql:5.6
```

なお、得られたコンテナは基本的に read only なので変更ができません。コンテナをカスタマイズしたい場合や、scratch でコンテナを作成したい場合には、@HoriThe3rd 氏の[こちらの記事](https://qiita.com/HoriThe3rd/items/6982247ac0f612d0474a)が役に立つでしょう。



# JAVAで動くプログラムについて
JAVAで書かれたアダプタートリミングツール Trimmomatic は、[公式サイト](http://www.usadellab.org/cms/?page=trimmomatic)によると `java -jar trimmomatic.jar PE ...` というコマンドで動かすように書かれています。しかし、これにならって実行しようしてもエラーになります。

```
$ singularity exec /usr/local/biotools/t/trimmomatic:0.36--5 java -jar trimmomatic.jar PE ...(以下省略)
Error: Unable to access jarfile trimmomatic.jar
```

これはコンテナ内では`/usr/local/share/trimmomatic-0.36-5/trimmomatic.jar`に jar ファイルが存在しているためです。(jar ファイルのパスを正しく指定すれば動かすことは可能ですが、遺伝研スパコンの場合、JAVA のメモリ関連のエラーが生じるという別の問題が発生する可能性があります --> 補足を参照)

コンテナ内に入って jar ファイルのパスを確認するのは手間なので、BioContainers で提供されているコンテナでは、jar ファイルと同名のラッパーが用意されています。これを利用すると以下のように実行することができます。

```
singularity exec /usr/local/biotools/t/trimmomatic:0.36--5 trimmomatic PE ...(以下省略)
```

### [補足] 遺伝研スパコンで JAVA を利用するときの注意点  
 遺伝研スパコンで JAVA で書かれたプログラムを実行するには、`java -Xmx1g`というように最大ヒープサイズをオプションで指定するか、実行前に環境変数で`export _JAVA_OPTIONS="-Xmx1g"`のように指定しておく必要があります。ラッパーを利用した場合、デフォルトでメモリ廻りのオプション設定がされているのでこれらの指定は不要です。設定を変更する必要がある場合には次のように実行時にオプションとして与えることも可能です。

```
singularity exec /usr/local/biotools/t/trimmomatic:0.36--5 trimmomatic -Xmx2g PE ...(以下省略
```

なお、`_JAVA_OPTIONS`を設定した場合には Singularity 実行時に引き継がれます。

# Singularityで動かすのに向かないもの
真核生物のゲノムアノテーションパイプライン Maker は、内部的に RepeatMasker を使用しています。通常は Maker をインストールするときにRepeatMasker の参照ライブラリとして RepBase のデータを追加するように促されますが、ライセンスの関係上、コンテナイメージには RepBase のデータは同梱されていません。RepBase のデータを含めたコンテナを自前で作成することはもちろん可能ですが、普通に Maker をインストールしてしまった方が早いでしょう。
前述の通り　Singularity コンテナは基本的に変更不可なので、Maker のようにインストールディレクトリ以下に設定ファイルや参照データを追加して使用するようなプログラムは Singularity コンテナの利用は難しいのではないかと思います。


# その他
### Singularityのバージョンについて  
デフォルトでは 2.6.1 が利用可能です。
次のようにすると 3.2.0 が利用可能です。

```
$ module load singularity/3.2.0
$ singularity --version
singularity version 3.2.0
```

### GPUを使いたい
`--nv`オプションを使いましょう。詳しくはスパコンの[使い方ページ](https://sc.ddbj.nig.ac.jp/ja/guide/software/singularity)で。

```
$ singularity shell --nv ./tensorflow-latest-gpu-py3.simg
```