10

大きなfastaファイルを解析しようとしていますが、メモリ不足エラーが発生しています。データ処理を改善するためのいくつかの提案をいただければ幸いです。現在、プログラムは名前を正しく出力しますが、ファイルを部分的に介してMemoryErrorが発生します

これがジェネレーターです

def readFastaEntry( fp ):
    name = ""
    seq = ""
    for line in fp:
        if line.startswith( ">" ):
            tmp = []
            tmp.append( name )
            tmp.append( seq )
            name = line
            seq = ""
            yield tmp
        else:
            seq = seq.join( line )

これが発信者のスタブです。この部分が機能した後、さらに追加されます

fp = open( sys.argv[1], 'r' )

for seq in readFastaEntry( fp ) :
    print seq[0]

fasta形式に慣れていない人のためにここに例があります

>1 (PB2)
AATATATTCAATATGGAGAGAATAAAAGAACTAAGAGATCTAATGTCACAGTCTCGCACTCGCGAGATAC
TCACCAAAACCACTGTGGACCACATGGCCATAATCAAAAAGTACACATCAGGAAGGCAAGAGAAGAACCC
TGCACTCAGGATGAAGTGGATGATG
>2 (PB1)
AACCATTTGAATGGATGTCAATCCGACTTTACTTTTCTTGAAAGTTCCAGCGCAAAATGCCATAAGCACC
ACATTTCCCTATACTGGAGACCCTCC

各エントリは、名前などを示す ">"で始まり、次のN行はデータです。先頭に「>」が付いている次の行以外に、データの終了は定義されていません。

4

4 に答える 4

15

BioPythonの使用を検討しましたか。fastaファイルを読み取ることができるシーケンス リーダーがあります。また、自分でコーディングすることに興味がある場合は、BioPython のコードをご覧ください。

編集:コードが追加されました

def read_fasta(fp):
    name, seq = None, []
    for line in fp:
        line = line.rstrip()
        if line.startswith(">"):
            if name: yield (name, ''.join(seq))
            name, seq = line, []
        else:
            seq.append(line)
    if name: yield (name, ''.join(seq))

with open('f.fasta') as fp:
    for name, seq in read_fasta(fp):
        print(name, seq)
于 2011-10-04T23:09:50.483 に答える
7

この形式の pyparsing パーサーは、わずか数行の長さです。次のコードの注釈を参照してください。

data = """>1 (PB2) 
AATATATTCAATATGGAGAGAATAAAAGAACTAAGAGATCTAATGTCACAGTCTCGCACTCGCGAGATAC 
TCACCAAAACCACTGTGGACCACATGGCCATAATCAAAAAGTACACATCAGGAAGGCAAGAGAAGAACCC 
TGCACTCAGGATGAAGTGGATGATG 
>2 (PB1) 
AACCATTTGAATGGATGTCAATCCGACTTTACTTTTCTTGAAAGTTCCAGCGCAAAATGCCATAAGCACC 
ACATTTCCCTATACTGGAGACCCTCC"""

from pyparsing import Word, nums, QuotedString, Combine, OneOrMore

# define some basic forms
integer = Word(nums)
key = QuotedString("(", endQuoteChar=")")

# sequences are "words" made up of the characters A, G, C, and T
# we want to match one or more of them, and have the parser combine
# them into a single string (Combine by default requires all of its
# elements to be adjacent within the input string, but we want to allow
# for the intervening end of lines, so we add adjacent=False)
sequence = Combine(OneOrMore(Word("AGCT")), adjacent=False)

# define the overall pattern to scan for - attach results names
# to each matched element
seqEntry = ">" + integer("index") + key("key") + sequence("sequence")

for seq,s,e in seqEntry.scanString(data):
    # just dump out the matched data
    print seq.dump()
    # could also access fields as seq.index, seq.key and seq.sequence

版画:

['>', '1', 'PB2', 'AATATATTCAATATGGAGAGAATAAAAGAACTAAGAGATCTAATGTCACAGTCTCGCACTCGCGAGATACTCACCAAAACCACTGTGGACCACATGGCCATAATCAAAAAGTACACATCAGGAAGGCAAGAGAAGAACCCTGCACTCAGGATGAAGTGGATGATG']
- index: 1
- key: PB2
- sequence: AATATATTCAATATGGAGAGAATAAAAGAACTAAGAGATCTAATGTCACAGTCTCGCACTCGCGAGATACTCACCAAAACCACTGTGGACCACATGGCCATAATCAAAAAGTACACATCAGGAAGGCAAGAGAAGAACCCTGCACTCAGGATGAAGTGGATGATG
['>', '2', 'PB1', 'AACCATTTGAATGGATGTCAATCCGACTTTACTTTTCTTGAAAGTTCCAGCGCAAAATGCCATAAGCACCACATTTCCCTATACTGGAGACCCTCC']
- index: 2
- key: PB1
- sequence: AACCATTTGAATGGATGTCAATCCGACTTTACTTTTCTTGAAAGTTCCAGCGCAAAATGCCATAAGCACCACATTTCCCTATACTGGAGACCCTCC
于 2011-10-05T10:11:06.650 に答える
0
def read_fasta(filename):
    name = None
    with open(filename) as file:
        for line in file:
            if line[0] == ">":
                if name:
                    yield (name, seq)
                name = line[1:-1].split("|")[0]
                seq = ""
            else:
                seq += line[:-1]
        yield (name, seq)
于 2013-12-23T08:10:27.373 に答える
0

あなたが何をしているのかをよく理解していなければ、私は次のようなコードを書いていただろう:

def readFastaEntry( fp ):
    name = ""
    while True:
        line = name or f.readline()
        if not line:
            break
        seq = []
        while True:
            name = f.readline()
            if not name or name.startswith(">"):
                break
            else:
                seq.append(name)
        yield (line, "".join(seq))

これにより、開始ラインから次の開始ラインまでのデータが収集されます。配列を作成seqするということは、可能な限り最後の瞬間まで文字列の結合を最小限に抑えることを意味します。タプルを生成することは、リストよりも理にかなっています。

于 2011-10-05T02:32:50.807 に答える