プログラム中で、NCBIの管理するデータベースに登録された配列ファイルをダウンロードしたいことがたまにあります。手作業は何かと煩雑なので。
そこで、Biopythonを利用して指定したアクセッション番号の配列データを自動でダウンロードするプログラムを作ったので、そのまとめです。完成したコードはこのページの一番下に載せてあります。
Entrezについて
プログラムによるダウンロードの需要は広く全世界であるようで、NCBIはEntrez(アントレと読むらしいです)と呼ばれるデータベースを用意しアクセスを受け付けています。
ただし、Entrezの使用に関しては色々と注意事項があるようです。詳しくはNCBIのガイドラインをご覧ください。個人的に重要だと感じたのは以下の3点です。
- アクセス元の身元が分かるようにメールアドレスをスクリプト中で明示する。
- Entrezへのアクセスは1秒間に3回までとする。ただし、Biopythonなら自動で調整してくれます。
- ヒトの全ゲノム配列など、巨大なデータについてはFTPを利用するなど別の方法を検討する。
1.の補足
連絡先を伝えることで、過度なアクセスをしてしまった場合などの問題発生時に、メールで連絡を受け取れるようにします。アクセス禁止は絶対に避けたいはずですので、記載することをおすすめします。
Biopythonならメールアドレスの指定も簡単です。関数ごとに引数で指定しても良いのですが、煩雑な上に忘れそうなので、スクリプトのトップでグローバルに指定します。
from Bio import Entrez Entrez.email = "your email address"
コードの補足
今回は、以下のようにアクセッション番号が記載されたファイルを渡すと、各番号に対応したGenbankファイルを自動でダウンロードしてくれるPythonスクリプトを作成しました。なお、ダウンロードするデータはバクテリアの全ゲノム情報を想定しています。
Num1 Num2 Num3
アクセッション番号を利用して、Entrezからファイルをダウンロードするには、Biopythonのefetch関数を使うと簡単です。以下はBiopythonの公式チュートリアルに載っている使用例です。
>>> from Bio import Entrez >>> Entrez.email = "A.N.Other@example.com" # Always tell NCBI who you are >>> handle = Entrez.efetch(db="nucleotide", id="EU490707", rettype="gb", retmode="text") >>> print(handle.read())
db引数で利用するデータベースの種類を、id引数でダウンロードするファイルのアクセッション番号を指定しています。rettypeとretmodeについては理解が不十分なのですが、ダウンロードしたいファイルの形式に合わせて適宜変更する必要があるようです。例えばFASTAファイルをダウンロードする場合はrettype="fasta"と指定します。
今回はCDS情報まで記載されたGenbankファイルをダウンロードしたいので、dbに"nucleotide"を、retmodeに"gbwithparts"を、retmodeに"text"を指定しました。Biostarsのこちらの回答を参考にしましたが、NCBIのサイトにも一応記載があります。ダウンロードするファイルの種類に応じて適宜引数を変更する必要があります。
更に詳しい情報を知りたい方は、Biopythonの公式チュートリアルが分かりやすいのでおすすめです。
コード
#!/usr/bin/python3 import os import sys from time import sleep from Bio import Entrez # 自分のeメールアドレスを指定する Entrez.email = def fetch(search_id, d, f, r): sleep(1) handle = Entrez.efetch(id=search_id, db=d, rettype=f, retmode=r) gbk = handle.read() return gbk def download_from_acc(acc_list, outdir): if not os.path.isdir(outdir): os.makedirs(outdir, exist_ok=True) search_db = "nucleotide" filetype = "gbwithparts" datatype = "text" suffix = ".gbk" with open(acc_list, "r") as f: for acc in f: acc = acc.rstrip() contents = fetch(acc, search_db, filetype, datatype) outfile = acc + suffix outfile = os.path.join(outdir, outfile) with open(outfile, "w") as out: print(contents, end="", file=out) if __name__ == '__main__': infile = sys.argv[1] outdir = sys.argv[2] download_from_acc(infile, outdir)