2011-10-26 48 views
2

我希望能夠加入這兩個「字典」存儲在「INDATA」和「pairdata」,但是這個代碼,如何加入由Bio.SeqIO.index創建的兩個或更多詞典?

indata = SeqIO.index(infile, infmt) 
pairdata = SeqIO.index(pairfile, infmt) 
indata.update(pairdata) 

產生以下錯誤:

indata.update(pairdata) 
TypeError: update() takes exactly 1 argument (2 given) 

我有使用,

indata = SeqIO.to_dict(SeqIO.parse(infile, infmt)) 
pairdata = SeqIO.to_dict(SeqIO.parse(pairfile, infmt)) 
indata.update(pairdata) 

它不工作嘗試,但由此產生的字典佔用太多的內存是因爲我有INFILE和pairfile的大小實用。

我已經探索了最後的選擇就是:

indata = SeqIO.index_db(indexfile, [infile, pairfile], infmt) 

這完美的作品,但速度很慢。有誰知道我是否可以成功地加入上述第一個示例中的兩個索引?

回答

2

SeqIO.indexSeqIO.index返回一個類似於只讀字典的對象,因此update將無法​​正常工作(對於令人困惑的錯誤消息致歉;我剛剛檢查了Biopython主存儲庫的修復)。

最好的辦法是要麼使用index_db,這會慢一些,但 只需要索引文件一次,或定義一個更高層次的對象 它就像一本字典在你的多個文件。這裏是一個 簡單的例子:

from Bio import SeqIO 

class MultiIndexDict: 
    def __init__(self, *indexes): 
     self._indexes = indexes 
    def __getitem__(self, key): 
     for idx in self._indexes: 
      try: 
       return idx[key] 
      except KeyError: 
       pass 
     raise KeyError("{0} not found".format(key)) 

indata = SeqIO.index("f001", "fasta") 
pairdata = SeqIO.index("f002", "fasta") 
combo = MultiIndexDict(indata, pairdata) 

print combo['gi|3318709|pdb|1A91|'].description 
print combo['gi|1348917|gb|G26685|G26685'].description 
print combo["key_failure"] 
+0

我很新的類和繼承。我希望能夠遍歷MultiIndexDict,是否有可能繼承SeqIO.index中的方法,例如, 'keys()'或'iterkeys()'迭代器?我可以只做'class MultiIndexDict(SeqIO.index):'? – benjsmith

+1

你需要定義一個iterkeys方法,它返回所有兒童字典中的所有鍵。 – peterjc

1

在你不打算再次使用該索引和內存並不是限制(兩者似乎是在你的情況如此),你可以告訴Bio.SeqIO .index_db(...)以在存儲器SQLite3的索引與該特殊索引名稱使用一個「:存儲器:」,例如:

indata = SeqIO.index_db(":memory:", [infile, pairfile], infmt) 

這裏的infile和pairfile是文件名,並且infmt限定如他們的格式類型Bio.SeqIO(例如「fasta」)。

這實際上是Python的SQLite3庫的一般技巧。對於一小組文件,這應該比在磁盤上構建SQLite索引快得多。

+0

謝謝,這是非常有用的,並提供了一個解決方案,我面臨的更一般的問題。 SQLite3數據庫似乎佔用了輸入序列文件大約一半的空間,而SeqIO.to_dict似乎使用了序列輸入文件大小的6倍以上(我使用的節點在從20GB填充126GB RAM後崩潰輸入)。比較這個解決方案和@Brad下面的內存之間的速度折衷會很有趣。 – benjsmith

+0

'indata = index_db(「:memory:」,existing_indexfile)'是否將現有的SQLite3序列數據庫讀入內存?它會比從頭開始使用上面的示例在內存中構建數據庫更快嗎? – benjsmith

+0

不可以。如果你想加載一個現有的SQLite3數據庫,只需提供SQLite3數據庫的文件名。重新加載現有的數據庫應該比重新建立索引要快得多。這是正常的用法 - 將索引建立一次到SQLite數據庫(可能很慢),但將來會重新加載(這很快)。 – peterjc