【问题标题】:How to read multiple lines at once? (practice script) [duplicate]如何一次读取多行? (练习脚本)[重复]
【发布时间】: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


【解决方案1】:

这里是一个获取fasta文件逆补的例子。也许您可以从中借鉴一些想法。

import re

file = """\
>Sequence_1  
ATG
TATA
>Sequence_2 
TATA
GACT
ATG""".splitlines()

s = ''
for line in file:
    line = line.rstrip()
    if line.startswith('>'):
        if len(s):
            # complement the sequence of fasta 'TAGC' to 'ATCG'
            # T to A, A to T, G to C, C to G
            s = s.translate(str.maketrans('TAGC', 'ATCG'))
            # reverse the string, 's[::-1]'
            # Also, print up to 50 fasta per line to the end of the sequence
            s = re.sub(r'(.{1,50})', r'\1\n', s[::-1])
            print(s, end='')
            s = ''
        print(line)
    else:
        s += line

# print last sequence
s = s.translate(str.maketrans('TAGC', 'ATCG'))
s = re.sub(r'(.{1,50})', r'\1\n', s[::-1])
print(s, end='')

打印:

>Sequence_1  
TATACAT
>Sequence_2 
CATAGTCTATA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-05
    • 2015-11-12
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 2011-02-26
    • 2017-11-10
    • 1970-01-01
    相关资源
    最近更新 更多