【发布时间】:2020-07-10 19:50:09
【问题描述】:
我正在制作一个 .fasta 解析器脚本。 (我知道 .fasta 文件已经存在一些解析器,但我需要练习处理大文件,并认为这是一个好的开始)。
程序的目标:获取一个包含多个序列的非常大的.fasta 文件,并在一个新文件中返回每个序列的反向补码。
我有一个脚本,一次读取一行,但在常规 .fasta 文件中,每行只有大约 50 个字节。所以一次只缓冲一行是没有必要的。有没有办法可以设置一次缓冲的行数?
对于不知道什么是 fasta 的人:.fasta 文件是一个文本文件,其中包含 DNA 序列,每个序列在 DNA/RNA/蛋白质序列之前都有一个标题行,由“>”标记。示例:
>Sequence_1
ATG
TATA
>Sequence_2
TATA
GACT
ATG
我的代码概览:
读取每行的第一个字节,通过查找“>”来映射文件中序列的位置。
使用此映射逐行向后读取每个序列(这是我想要更改的内容)
- 反向
- 恭维字符串中的碱基对 (I.E. G->C)
- 将此行写入新文件
以下是所有相关代码,以便您可以看到我试图更改的行正在调用的函数:(可以跳过)
def get_fasta_seqs(BIGFILE): #Returns returns an object containing all of seq locations
f = open(BIGFILE)
cnt = 0
seq_name = []
seq_start = []
seq_end = []
seqcount = 0
#print(line)
#for loop skips first line check for seq name
if f.readline(1) == '>':
seq_name.append(cnt)
seq_start.append(cnt+1)
seqcount =+ 1
for line in f:
cnt += 1
if f.readline(1) == '>':
seq_name.append(cnt)
seq_start.append(cnt+1)
seqcount += 1
if seqcount > 1:
seq_end.append(cnt-1)
seq_end.append(cnt-1) #add location of final line
seqs = fileseq(seq_name,seq_start,seq_end,seqcount) #This class only has a __init__ function for these lists
return seqs
def fasta_rev_compliment(fasta_read,fasta_write = "default",NTtype = "DNA"):
if fasta_write == 'default':
fasta_write = fasta_read[:-6] + "_RC.fasta"
seq_map = get_fasta_seqs(fasta_read)
print(seq_map.seq_name)
f = open(fasta_write,'a')
for i in range(seq_map.seqcount): #THIS IS WHAT I WANT TO CHANGE
line = getline(fasta_read,seq_map.seq_name[i]+1) #getline is reading it as 1 indexed?
f.write(line)
my_fasta_seqs = get_fasta_seqs(fasta_read)
for seqline in reversed(range(seq_map.seq_start[i],seq_map.seq_end[i]+1)):
seq = getline(fasta_read,seqline+1)
seq = seq.replace('\n','')
seq = reverse_compliment(seq,NTtype = NTtype) #this function just returns the reverse compliment for that line.
seq = seq + '\n'
f.write(seq)
f.close()
fasta_rev_compliment('BIGFILE.fasta')
我要修改的主要代码在这里:
for i in range(seq_map.seqcount): #THIS IS WHAT I WANT TO CHANGE
line = getline(fasta_read,seq_map.seq_name[i]+1) #getline is reading it as 1 indexed?
f.write(line)
my_fasta_seqs = get_fasta_seqs(fasta_read)
for seqline in reversed(range(seq_map.seq_start[i],seq_map.seq_end[i]+1)):
seq = getline(fasta_read,seqline+1)
我想要这样的东西:
def fasta_rev_compliment(fasta_read,fasta_write = "default",NTtype = "DNA",lines_to_record_before_flushing = 5):
###MORE CODE###
#i want something like this
for i in range(seq_map.seqcount): #THIS IS WHAT I WANT TO CHANGE
#is their a way to load
line = getline(fasta_read,seq_map.seq_name[i]+1) #getline is reading it as 1 indexed?
f.write(line)
my_fasta_seqs = get_fasta_seqs(fasta_read)
for seqline in reversed(range(seq_map.seq_start[i],seq_map.seq_end[i]+1)):
seq = getline(fasta_read,seqline+1)
#Repeat n = 5 (or other specified number) times until flushing ram.
我遇到的问题是我需要向后读取文件。当您尝试将其应用于向后读取文件时,我能找到的所有方法都无法正常工作。有没有东西可以分块读取文件但向后?
或者:任何其他可以使低内存设置更有效的方法。现在它几乎不使用任何内存,但是对于一个大约 12,000 行的 100kB 文件需要 21 秒,但使用 file.readlines() 方法会立即处理该文件。
【问题讨论】:
-
请显示您想要的输出。
-
对于这个问题,如果您可以提供输入文件的更大部分,将会很有帮助。什么是“低内存”设置,有多少内存可用? “大”文件有多大?一次性读入内存是绝对不可能的吗?
-
可能不是您正在寻找的完整解决方案,但它可能会让您走上正轨:How to read a file in reverse order。你想看看第二个答案,它不会先将完整的文件读入内存。
-
@Ronald 这取决于文件。我处理的许多都超过 20GB。对于较小的,我有另一个很好用的脚本
标签: python bioinformatics fasta