Snakemake 公式 | Snakemake GitHub
Snakemake は、GNU Make のようなタスクランナーの一つです。ファイルの依存関係をシンプルに書きつつ、Python で好きな処理がかけるのが魅力です。
ルールの書き方
rule all:
input: "output-A.txt"
rule hoge:
input: "input-{sample}.txt"
output: "output-{sample}.txt"
shell: "myscript.sh {input} > {output}"
パラメータ | 説明 |
---|---|
input: | 入力ファイルの指定。{sample} 等でワイルドカードを指定できる。 |
output: | 出力ファイルの指定。input: の指定したワイルドカードを使うことができる。 |
shell: | 実行するコマンド。{input} , {output} などを利用可。 |
run: | 実行するPythonコード。shell: と run: は同時に指定できない。 |
その他のパラメータ: params:
, log:
, benchmark:
, message:
, threads:
, resources:
, version:
,
リファレンス
定義済み変数
input:
以外のパラメータでは {input}
, {output}
などとして定義済み変数にアクセスできる。トップレベルのコード部や run:
パラメータでは、通常の変数としてアクセス可。
変数 | 説明 |
---|---|
{input} |
input: に対応するファイル、またはファイル群(スペース区切り) |
{output} |
output: に対応するファイル、またはファイル群(スペース区切り) |
{wildcards.*} |
input: , output: で指定したワイルドカードの集まり。 |
{params.*} |
params: で設定した文字列の集まり。 |
{rules.*} | 定義された rule: の集まり。 |
{checkpoints.*} | 定義された checkpoint: の集まり。 |
{config} |
configfile: で読み込んだファイルの設定。 |
{rule} | ( shell: , run: のみアクセス可。)現在のルール名(str) |
{.*}
となっている箇所は、{wildcards.sample}
等、属性に個々のアイテム名を指定する。
input:
では {hoge}
とした部分はすべてワイルドカード定義として扱われる。
定義済みトップレベル要素
rule:
以外にも、下記の要素を定義することができます。その他、通常の Python コードを記述することが可能です。
要素 | 説明 |
---|---|
rule: | ルール指定(前述) |
checkpoint: | 特殊なルール指定(使い方は後述) |
configfile: | YAML 形式の外部変数定義を読み込む。 |
include: | 他の Snakefile を取り込む |
workdir: | カレントディレクトリを指定 |
subworkflow: | (未調査) |
定義済み関数(抜粋)
関数 | 説明 |
---|---|
expand | wildcard を展開した結果の str のリストを返す。最終成果物のリストの生成などで頻繁に使うことになる(はず)。 |
glob_wildcards | ファイル名探索をする glob のワイルドカード版。得られるのが、ファイル名ではなく、ワイルドカードであることに注意。(普通にファイル名の一覧が必要であれば標準ライブラリ(`glob.glob`等)を普通に使える) |
touch | output: セクションで使用。処理完了後に touch で指定されたファイルの更新時刻を更新する。 |
directory | output: セクションで使用。出力先としてディレクトリを指定するときに使用。参考 |
temp | output: セクションで使用。引数で指定されたファイルは、ジョブ成功時でも削除される。 |
protected | output: セクションで使用。引数で指定されたファイルは、ジョブ失敗時にも削除されない。 |
remote | input:, output: セクションで使用。詳細は別ページで説明予定 |
ワイルドカードの書式
書式 | 説明 |
---|---|
{sample} | デフォルト。正規表現としては .+ が指定されたのと同じ |
{sample,[A-Z]+} |
, の後ろにワイルドカードがマッチする正規表現を指定可能 |
{sample:02d} | Python標準のフォーマット指定も利用可 |
{sample:q} | 文字列をクォートする |
コマンドラインオプション
オプション | 説明 |
---|---|
-n, --dryrun | dryrun |
-p, --printshellcmds | 実行したコマンドを標準出力に出す(デフォルトでは出ない) |
-f, --force | 依存関係を無視して強制実行する |
-R [TARGET, TARGET, ...], --forcerun [TARGET, TARGET, ...] |
TARGET 以降のルール(TARGET と、TARGET に依存しているルール)を再実行する |
-U TARGET[, TARGET, ...], --until TARGET[, TARGET, ...] |
TARGET 以前のルール (TARGET が依存しているルール) を再実行する |
-s filename, --snakefile filename | Snakefile を指定 |
-d, --directory | ワーキングディレクトリを指定 |
-l, --list | Snakefile の rule 一覧を出力する |
--lt, --list-target-files | rule のうち、snakemake RULE として指定可能なルール (=ルールにwildcardを含まないもの) を出力する。なお、-lt とすると、-l , -t(--touch) と解釈され、--lt とはならないので注意。 |
-t, --touch |
output のファイルの更新時間だけを更新し、コマンドを実行しない。output のファイルがない場合には何も起こらないことに注意(空ファイルが作成されたりはしない) |
-k, --keep-going | 途中でエラーが発生しても、実行可能なジョブは実行する(デフォルトはエラー発生次第、即座に止まる) |
定番の書き方
default ターゲット
ターゲット指定が省略された場合、Make と同じく一番上の rule がターゲットとして指定された扱いになる。
input:
に、最終的に生成されるファイルを指定することで、必要な依存関係をたどって生成に必要な rule:
群が実行される。
rule all:
input: "final-result.txt"
分析の途中から再実行
ワイルドカード付きのルールを再実行したい場合、-R (--forcerun)
オプションを使います。
% snakemake -R step2 all
最終的にワイルドカードを展開しているルールを指定しつつ、 -R
オプションで再実行するターゲットを指定します。
単に -f
オプションで指定すると、ワイルドカードの展開ができずエラーになります。
% snakemake -f step2
Building DAG of jobs...
WorkflowError:
Target rules may not contain wildcards. Please specify concrete files or a rule without wildcards.
参考 Can SnakeMake be forced to rerun rules when files are missing - Stack Overflow
分析の特定ステップだけを再実行
先程の例は step2 以降を再実行でしたが、step2 だけを再実行したい場合はどうでしょうか。その場合は -U
オプションを利用します。
% snakemake -R step2 -U step2 all
ちょうど -R
で指定したターゲットから、-U
で指定したターゲットまでが実行されます。両方に同じターゲットを指定すると、そのターゲットだけが実行されるようになります。
.env の読み込み
Snakefile
には通常の Python スクリプトを書けますので1、たとえば pip install python-dotenv
を実行しておいて、Snakefile
に
from dotenv import load_dotenv
load_dotenv()
# 以後、通常のルール記述
rule all:
input: ...
などと書けばOKです。
(逆にいえば、snakemake 標準では .env の読み込み機能は提供されていない模様。)
input:
パラメータに変数の値を指定する
var_a = 'some_text'
rule hoge:
input: "{var_a}"
などと書いても、{var_a}
というワイルドカードを定義したことになり、変数の値は入りません。変数の値をいれるためには、例えば下記の方法があります。
-
input: f'{var_a}'
とする。(ワイルドカードを使う場合はf'{var_a}-{{wc_a}}'
とワイルドカード側を{{}}
とする。) -
input: expand('{var_a}', var_a=var_a)
として、ワイルドカード展開を利用する
-
正確には「ルール記述が通常の Python 関数に置き換えられて、Python スクリプトとして実行される」 ↩