0

FASTQ 形式の 2 つのファイル A と B があります。これらは基本的に、次のように @ で始まる 4 行のグループに編成された数億行のテキストです。

@120412_SN549_0058_BD0UMKACXX:5:1101:1156:2031#0/1
GCCAATGGCATGGTTTCATGGATGTTAGCAGAAGACATGAGACTTCTGGGACAGGAGCAAAACACTTCATGATGGCAAAAGATCGGAAGAGCACACGTCTGAACTCN
+120412_SN549_0058_BD0UMKACXX:5:1101:1156:2031#0/1
bbbeee_[_ccdccegeeghhiiehghifhfhhhiiihhfhghigbeffeefddd]aegggdffhfhhihbghhdfffgdb^beeabcccabbcb`ccacacbbccB

私は比較する必要があります

5:1101:1156:2031#0/

ファイル A と B の間を分割し、新しいファイルに一致するファイル B に 4 行のグループを書き込みます。それを行うPythonのコードを取得しましたが、ファイルAのすべての@行に対してファイルBの@行全体を解析し、両方のファイルに数億行が含まれているため、小さなファイルに対してのみ機能します。

ファイル B のインデックスを作成する必要があると誰かが提案しました。私は成功せずにグーグルで検索しましたが、誰かがこれを行う方法を指摘したり、チュートリアルを教えてくれたりして、学ぶことができれば非常に感謝しています. ありがとう。

==編集== 理論的には、4 行の各グループは各ファイルに 1 回だけ存在する必要があります。各試合の後に解析を中断すると、速度が十分に向上しますか、それともまったく別のアルゴリズムが必要ですか?

4

2 に答える 2

1

インデックスは、作業中の情報の短縮版です。この場合、「キー」 (@ 行の最初のコロン (':') と末尾近くの最後のスラッシュ ('/') の間のテキスト) と、何らかの値が必要になります。

この場合の「値」は 4 行のブロックの内容全体であり、インデックスはブロックごとに個別のエントリを格納するため、実際の値を使用するとファイル全体がメモリに格納されます。インデックス。

代わりに、4 行ブロックの先頭のファイル位置を使用しましょう。そうすれば、そのファイルの位置に移動し、4 行印刷して停止することができます。総コストは、実際のゲノムデータのバイト数ではなく、整数ファイル位置を格納するのに必要な 4 または 8 または何バイトでもかまいません。

これは、ジョブを実行するコードですが、多くの検証とチェックも実行します。使わないものは捨てたほうがいいかもしれません。

import sys

def build_index(path):
    index = {}
    for key, pos, data in parse_fastq(path):
        if key not in index:
            # Don't overwrite duplicates- use first occurrence.
            index[key] = pos

    return index

def error(s):
    sys.stderr.write(s + "\n")

def extract_key(s):
    # This much is fairly constant:
    assert(s.startswith('@'))
    (machine_name, rest) = s.split(':', 1)
    # Per wikipedia, this changes in different variants of FASTQ format:
    (key, rest) = rest.split('/', 1)
    return key

def parse_fastq(path):
    """
    Parse the 4-line FASTQ groups in path.
    Validate the contents, somewhat.
    """
    f = open(path)
    i = 0
    # Note: iterating a file is incompatible with fh.tell(). Fake it.
    pos = offset = 0
    for line in f:
        offset += len(line)
        lx = i % 4
        i += 1
        if lx == 0:     # @machine: key
            key = extract_key(line)
            len1 = len2 = 0
            data = [ line ]
        elif lx == 1:
            data.append(line)
            len1 = len(line)
        elif lx == 2:   # +machine: key or something
            assert(line.startswith('+'))
            data.append(line)
        else:           # lx == 3 : quality data
            data.append(line)
            len2 = len(line)

            if len2 != len1:
                error("Data length mismatch at line "
                        + str(i-2)
                        + " (len: " + str(len1) + ") and line "
                        + str(i)
                        + " (len: " + str(len2) + ")\n")
            #print "Yielding @%i: %s" % (pos, key)
            yield key, pos, data
            pos = offset

    if i % 4 != 0:
        error("EOF encountered in mid-record at line " + str(i));

def match_records(path, index):
    results = []
    for key, pos, d in parse_fastq(path):
        if key in index:
            # found a match!
            results.append(key)

    return results

def write_matches(inpath, matches, outpath):
    rf = open(inpath)
    wf = open(outpath, 'w')

    for m in matches:
        rf.seek(m)
        wf.write(rf.readline())
        wf.write(rf.readline())
        wf.write(rf.readline())
        wf.write(rf.readline())

    rf.close()
    wf.close()

#import pdb; pdb.set_trace()
index = build_index('afile.fastq')
matches = match_records('bfile.fastq', index)
posns = [ index[k] for k in matches ]
write_matches('afile.fastq', posns, 'outfile.fastq')

このコードは、データのブロックを取得するために最初のファイルに戻ることに注意してください。ファイル間でデータが同一で​​ある場合、一致が発生したときに 2 番目のファイルからブロックをコピーできます。

また、抽出しようとしているものによっては、出力ブロックの順序を変更したり、キーが一意であることを確認したり、キーが一意ではなく、それらが一致する順序。それはあなた次第です - 私はあなたがデータで何をしているのか分かりません.

于 2014-01-14T06:26:41.593 に答える
1

これらの人は、専用ライブラリを使用しながらいくつかのギグ ファイルを解析すると主張しています

fastq_parser = SeqIO.parse(fastq_filename, "fastq") 
wanted = (rec for rec in fastq_parser if ...)
SeqIO.write(wanted, output_file, "fastq")

IMOのより良いアプローチは、それを一度解析し、その代わりにデータベースoutput_file(つまりmysql)にデータをロードし、後でそこでクエリを実行することです

于 2014-01-13T23:58:50.563 に答える