相信大家在上一文中下載fasta的時(shí)候還沒有感覺到下載是多么復(fù)雜,但是對(duì)于分析比對(duì)多個(gè)序列文件時(shí),這個(gè)工作量說多了都是淚。比如,老板讓你比對(duì)自己測(cè)定序列與 NCBI 庫(kù)中序列,并構(gòu)建相應(yīng)的進(jìn)化樹,而這個(gè)序列需要大于100條。我想你的心情不會(huì)和下載一條序列時(shí)那么平靜,那么,接下來通過BioPython提供的接口來實(shí)現(xiàn)快速的自動(dòng)化序列下載。
一、Entrez 庫(kù)
1.1 Entrez 介紹
Entrez 在線資源檢索器是一組服務(wù)器端程序,為國(guó)家生物技術(shù)信息中心(NCBI)的Entrez查詢和數(shù)據(jù)庫(kù)系統(tǒng)提供穩(wěn)定的接口。使用固定的URL語法,將一組標(biāo)準(zhǔn)輸入?yún)?shù)轉(zhuǎn)換為各種NCBI軟件組件搜索和檢索所請(qǐng)求數(shù)據(jù)所需的值。目前包括38個(gè)數(shù)據(jù)庫(kù),涵蓋各種生物醫(yī)學(xué)數(shù)據(jù),包括核苷酸和蛋白質(zhì)序列,基因記錄,三維分子結(jié)構(gòu)和生物醫(yī)學(xué)文獻(xiàn)。該在線資源檢索器可以使用任何計(jì)算機(jī)語言(Perl,Python,Java和C ++等)將URL發(fā)送到應(yīng)用程序服務(wù)器并解析響應(yīng)。
1.2 注意事項(xiàng)
-
最小化請(qǐng)求數(shù)
- 如果任務(wù)需要搜索和/或下載大量記錄,則使用Entrez歷史記錄批量上載和/或檢索這些記錄而不是對(duì)每條記錄使用單獨(dú)的請(qǐng)求會(huì)更有效
- 可以使用單個(gè)EPost請(qǐng)求上載數(shù)千個(gè)ID
- 可以使用一個(gè)EFetch請(qǐng)求下載數(shù)百個(gè)記錄
-
訪問限制
- 為了不使服務(wù)器過載,NCBI建議用戶每秒發(fā)布不超過三個(gè)URL請(qǐng)求
- 將大型作業(yè)限制在工作日的周末或東部時(shí)間晚上9:00到凌晨5:00之間
-
設(shè)置郵箱
- 使用email參數(shù),這樣如果遇到什么問題,NCBI可以通過郵件聯(lián)系到你
- 郵件的參數(shù)從2010年6月1日是強(qiáng)制的參數(shù),所以每次必須告訴 NCBI 是誰在訪問
-
URL字符處理
- 所有參數(shù)使用小寫字符
- 參數(shù)沒有必需的順序,通常會(huì)忽略空值或不適當(dāng)?shù)膮?shù)
- 避免在URL中放置空格,尤其是在查詢中。如果需要空格,請(qǐng)使用加號(hào)(+)代替空格
- 其他特殊字符(例如引號(hào)(“)或用于引用歷史記錄服務(wù)器上的查詢鍵的#符號(hào))應(yīng)由其URL編碼表示(%22表示”;%23表示#)
二、基本操作
2.1 參數(shù)設(shè)置
# =====一般參數(shù)設(shè)置=====
# 設(shè)置 email 參數(shù),為了方便 NCBI 的工作人員可以聯(lián)系到你
# 郵件的參數(shù)從2010年6月1日是強(qiáng)制的參數(shù),所以每次必須告訴 NCBI 是誰在訪問
Entrez.email = "example@163.com"
# 如果你是通過其他腳本調(diào)用,可以設(shè)定 tool 的名字,默認(rèn)為 `Biopython`
Entrez.tool = "exampleScript"
# 可選參數(shù),使用代理,一般在無法正常訪問時(shí)設(shè)置
os.environ["http_proxy"] = "http://proxyhost.example.com:8080"
2.2 查看概況
2.2.1 查看目前 NCBI 所有數(shù)據(jù)庫(kù)
from Bio import Entrez
# =====查看數(shù)據(jù)庫(kù)概況=====
# 獲取 Entrez 所有數(shù)據(jù)庫(kù)的句柄
hd_info = Entrez.einfo()
# 獲取所有數(shù)據(jù)庫(kù)列表
read_info = Entrez.read(hd_info)
for db in read_info['DbList']:
print (db)
2.2.2 查看單個(gè)數(shù)據(jù)庫(kù)概況
from Bio import Entrez
# 獲取 Entrez 的 gene 數(shù)據(jù)庫(kù)句柄
hd_info_gene = Entrez.einfo(db="gene")
read_info_gene = Entrez.read(hd_info_gene)
# 數(shù)據(jù)庫(kù)名
print ("DbName : ", read_info_gene["DbInfo"]["DbName"])
# 在 NCBI 首頁(yè)頂部下拉菜單欄中的命名
print ("MenuName : ", read_info_gene["DbInfo"]["MenuName"])
# 數(shù)據(jù)庫(kù)描述
print ("Description: ", read_info_gene["DbInfo"]["Description"])
# 數(shù)據(jù)庫(kù)收錄總數(shù)
print ("Count : ", read_info_gene["DbInfo"]["Count"])
# 最新更新時(shí)間
print ("LastUpdate : ", read_info_gene["DbInfo"]["LastUpdate"])
# Gene 數(shù)據(jù)庫(kù)中可用的搜索關(guān)鍵字列表
print ("FieldList : ", read_info_gene["DbInfo"]["FieldList"])
# 我們把它遍歷下
for field in read_info_gene["DbInfo"]["FieldList"]:
print("%(Name)s\t %(FullName)s\t %(Description)s" % field)
2.3 查詢
2.3.1 全局搜索 | EGQuery
EGQuery:https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.ESummary
這里只關(guān)注搜索關(guān)鍵字在數(shù)據(jù)庫(kù)中所有的個(gè)數(shù),而不關(guān)注它的具體內(nèi)容
在實(shí)際使用中我們可以通過在這里得到的數(shù)字來確定下載策略
from Bio import Entrez
# =====全局搜索=====
hd_egquery = Entrez.egquery(term="oct4")
read_egquery = Entrez.read(hd_egquery)
print(read_egquery)
for ele in read_egquery["eGQueryResult"]:
print (ele["DbName"], ele["Count"], ele["Status"])
2.3.2 查詢單個(gè)數(shù)據(jù)庫(kù)中的基因 | ESearch
關(guān)于 ESearch 的官方文檔 https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.ESearch
from Bio import Entrez
# =====在數(shù)據(jù)庫(kù)搜索基因=====
# 搜索 Xenopus laevis 物種中名為 oct4 的基因
handle = Entrez.esearch(db="gene", term="oct4[Gene] AND Xenopus laevis[ORGN]")
read_gene = Entrez.read(handle)
print(read_gene)
2.3.3 查詢基因詳細(xì)描述信息 | Esummary
ESummary :https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.ESummary
from Bio import Entrez
# =====獲取摘要=====
# 通過 id 來獲取 item 的詳細(xì)信息
hd_esummary = Entrez.esummary(db="gene", id="397784")
read_esummary = Entrez.read(hd_esummary)
# 獲取該基因的詳細(xì)描述
for key, value in read_esummary['DocumentSummarySet']['DocumentSummary'][0].items():
print(key, value)
2.3.4 查詢交叉引用條目 | Elink
Elink:https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.ELink
from Bio import Entrez
# =====搜索交叉引用條目=====
# 接下來我們看看 id 為 5460 的基因相關(guān)的文獻(xiàn)資料
read_elink = Entrez.read(Entrez.elink(dbfrom="gene", db="pubmed", id="5460"))
print ("LinkSetDb: ", read_elink[0]["LinkSetDb"])
# 查看所有相關(guān)的目標(biāo)庫(kù)
for lsd in read_elink[0]["LinkSetDb"]:
print (lsd["DbTo"], lsd["LinkName"], len(lsd["Link"]))
# 查看相關(guān)的所有文獻(xiàn) Id
for link in read_elink[0]["LinkSetDb"][0]["Link"]:
print (link["Id"])
2.4 其他操作
2.4.1 上傳id列表到服務(wù)器 | EPost
EPost :https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.EPost
為什么要上傳列表到服務(wù)器?
你要上傳的 id 的列表會(huì)以 url 的形式上傳到服務(wù)器,這里有一個(gè)問題,如果 id 很多,就會(huì)導(dǎo)致url很長(zhǎng)。但是在 HTTP 的協(xié)議中,上傳一般以 GET 形式,這種方式會(huì)限制 url 的長(zhǎng)度,也就是說如果用戶上傳的 URL 太長(zhǎng)就會(huì)只能局限在一定的長(zhǎng)度內(nèi),而不能完整的上傳到服務(wù)器。 為了解決這個(gè)問題,只能使用 POST 方式上傳,它沒有限制文本長(zhǎng)度,隨后以 HTTP 頭文件的形式上傳服務(wù)器,并以歷史記錄的形式存儲(chǔ)在服務(wù)器
from Bio import Entrez
# =====上傳歷史記錄=====
# EPost :https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.EPost
#
id_list = ['379522', '397784', '398336']
hd_epost = Entrez.epost("gene", id=",".join(id_list))
read_epost = Entrez.read(hd_epost)
print ("web_env: ", read_epost["WebEnv"])
print ("query_key: ", read_epost["QueryKey"])
2.4.2 拼寫建議與糾正 | Espell
這個(gè)模塊用來糾正輸入的查詢?cè)~條
from Bio import Entrez
# =====拼寫建議=====
hd_espell = Entrez.espell(term="steem cell")
read_espell = Entrez.read(hd_espell)
print ("Query: ", read_espell["Query"])
print ("CorrectedQuery: ", read_espell["CorrectedQuery"])
2.4.3 下載 | EFetch
EFetch:https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.EFetch
所有參數(shù)組合:https://www.ncbi.nlm.nih.gov/books/NBK25499/table/chapter4.T._valid_values_of__retmode_and/?report=objectonly
from Bio import Entrez
# =====下載=====
hd_efetch_gb = Entrez.efetch(db='nucleotide', id="397784", rettype='gb', retmode='text')
hd_efetch_fa = Entrez.efetch(db='nucleotide', id="397784", rettype='fasta')
print (hd_efetch_gb.read())
print (hd_efetch_fa.read())
with open("res/397784.txt", "w") as file:
hd_efetch_ml = Entrez.efetch(db='pubmed', id="397784", rettype='medline', retmode='text')
file.write(hd_efetch_ml.read())
with open("res/397784.txt") as file:
read_medline = Medline.read(file)
print ("PMID", read_medline["PMID"])
print ("TI", read_medline["TI"])
2.4.4 解析大文件| parse
一般在 NCBI 中的資源會(huì)有較大的內(nèi)存占用,
這里的parse使用迭代器的方式,而不是像列表全部加載,因此了避免了大文件讀取時(shí)占滿內(nèi)存
- Linux 系統(tǒng)下準(zhǔn)備工作
下載實(shí)例文件:ftp://ftp.ncbi.nlm.nih.gov/gene/DATA/ASN_BINARY/Mammalia/Homo_sapiens.ags.gz
下載格式轉(zhuǎn)換工具:ftp://ftp.ncbi.nlm.nih.gov/toolbox/ncbi_tools/converters/by_program/gene2xml/linux64.gene2xml.gz
- 在終端依次運(yùn)行下列命令
mkdir ncbi
cd ncbi
mkdir ags
mkdir tool
cd tool
wget ftp://ftp.ncbi.nlm.nih.gov/toolbox/ncbi_tools/converters/by_program/gene2xml/linux64.gene2xml.gz
gunzip linux64.gene2xml.gz
mv linux64.gene2xml gene2xml
cd ../ags
wget ftp://ftp.ncbi.nlm.nih.gov/gene/DATA/ASN_BINARY/Mammalia/Homo_sapiens.ags.gz
gunzip Homo_sapiens.ags.gz
../tool/gene2xml -b T -i Homo_sapiens.ags -o Homo_sapiens.xml
- 下載你的目錄結(jié)構(gòu)類似這樣,這里的Homo_sapiens.xml 大約有15G(2018.09)
- 使用 BioPython 解析
from Bio import Entrez
# =====解析大文件=====
hd_parse = open("Homo_sapiens.xml")
res_parse = Entrez.parse(hd_parse)
for record in res_parse:
status = record['Entrezgene_track-info']['Gene-track']['Gene-track_status']
if status.attributes['value']=='discontinued':
continue
geneid = record['Entrezgene_track-info']['Gene-track']['Gene-track_geneid']
genename = record['Entrezgene_gene']['Gene-ref']['Gene-ref_locus']
print (geneid, genename)