FASTA文件是整个生物信息学,基因组学和进化生物学中使用的最常见的序列格式之一。主要用于存储核酸序列,但是FASTA文件的扩展名差异很大,有时可能是.fasta,有时也可能是.fas或.fna。

        在解析FASTA文件之前,我们首先需要了解FASTA文件的基本特征:

(1)标识符:以“>”开头,后跟唯一的字符串(如gene_id加一些其他注释的信息)

(2)顺序:从标识符后的一行开始。该序列由多个符号(核酸或氨基酸)组成,它们可能显示在一行,也可能包含在多行上。

1.open()函数打开文件

f = open('test.txt', 'r')
#readlines()函数是指按行读取文件,并且按每一行为列表一个元素,最后得到的lines就是一个列表
lines = f.readlines()
#for循环以读取每一行
for line in lines:
    print(line)
f.close()
print(lines)


#===========================运行结果====================
1.4

2.1

3.5
['1.4\n', '2.1\n', '3.5']

       

python fastapi 支持 stream python处理fasta文件_换行符

 

        结合test.txt文件和上述运行结果我们发现,test.txt文件中的1.4,2.1和3.5之间并没有空行,而python的运行结果却都空了一些,这主要是由于1.4后面的换行符“\n”导致的,我们在处理序列时并不希望看到换行符的存在,因此还需要用strip()函数将换行符删除。

PS:对于strip()函数可以理解对字符串进行操作,以删除所有前导和尾随空格以及特殊字符,如这里的换行符“\n”。加上strip()函数的代码如下:

f = open('test.txt', 'r')
#readlines()函数是指按行读取文件,并且按每一行为列表一个元素,最后得到的lines就是一个列表
lines = f.readlines()
#for循环以读取每一行
for line in lines:
    #strip()函数删除换行符
    print(line.strip())
f.close()
print(lines)


=========================运行结果====================
1.4
2.1
3.5
['1.4\n', '2.1\n', '3.5']

2.自制FASTA解析器时的兼容性

        在第一步中,我们已经成功的读取了.txt格式的文件,想要读取.fasta文件,只需要改变open()函数中的第一个参数就可以进行FASTA文件的读取,然而,魔鬼在细节中。由于FASTA格式非常松散,例如FASTA文件允许序列之间有空行,如果直接按行进行读取,那么我们会把空行也读进序列,因此为使我们的解析器具有很好的兼容性,我们要添加一些代码来应对这些格式上的细微变化。代码如下:

f = open('sample.fasta', 'r')
lines = f.readlines()
#创建空字典,用于存储基因ID和响应的序列
seq_dict = {}
#seq_name在这里就是处理之前说的存在空前的情况,先定义为空字符串
seq_name = ''
for line in lines:
    #line[0]表示每行的第一个字符,若为‘>’,则表示这一行是基因ID,则我们取除了“>”后的字符line[1:]
    if line[0] == '>':
        #line[1:]表示基因ID,然后strip()函数除去基因ID后面的换行符
        seq_name = line[1:].strip()
        #将基因ID作为key存入字典seq_dict,同时对应的value先定义为空字符串,以便else:后面加上响应的序列
        seq_dict[seq_name] = ''
    else:
        #if seq_name表示只有在seq_name为空时,不执行if右面的内容,若seq_name 不为空,
        # 而是前面seq_name = line[1:].strip()这一句定义的ID,这执行else:下的if后的内容,将序列添加到value里面
        if seq_name:
            #注意,等号左边的seq_dict[seq_name]将相应的基因ID对应的序列加入到字典,
            #而等号右边的seq_dict[seq_name]是提取相应的基因ID的value,然后与下一行的DNA序列进行拼接,
            # 这样写的主要目的就是为了在一个基因的序列存在多行的情况下也能顺利读取
            seq_dict[seq_name] = seq_dict[seq_name] + line.strip()
print(seq_dict)
#关闭文件
f.close()

===============================运行结果===============================
{'lcl|NC_016838.1': 'ATGCTGTCAGCGGTAAACGATATGCTGTCAGCGGTACGGTATATGCTGCCAACGGTTTTGTGTATGCTATCAGCGGTAATTGACGTATGCTGTCAGCGGTTAGAACCAAAAGGTATCCACATGTCCACAAAAAATAAAAAAGAGAGTGAAATCAAAGAAATACCTGAGGATAACGAAATTCTTGAGGAAGATGCTCTCAATTTGTACACAGGTGACTTAGTTCCTAACAGCAACAATACGGTGCAGCCAATCGCTTTAATGCGCCTTGGCCTCTTTGTTC', 'lcl|NC_016838.2': 'ATGGCTCTCACAATGACTGGTCTTGAGATTGAGAAAACAAGCGGCTACTGGAGAGCGAAAGGCTTCAGAAAACCGGACATGCTGGAGCGTCTGGAACGTGAAGACGGTTACATCATCCACCAGCGTCGGGAATGGCGCATGTTTGATCCTGAAACCGGGAAACTCACATCGAAAGCACAAACGCTTTGGGGTTTGCTCAAGCAGATTCACTAA', 'lcl|NC_016838.3': 'ATGGTGAATGGCTCTGGACTGGCCATCTTTAGGGAGTTCCAGGCCTTAGCGCTCTTCCGGAGCCATTTACAGCTCAAAATAGATAAGTTAGTATTTACCTATTATGAAGATATACATAGATATCCTGTTACTCATCTTTTTTAA', 'lcl|NC_016838.4': 'GTGAAGAGGCTCTGGGATGCGGCCAATGCCGCGCTCGATGTTATCGACGCAGAAATCGCCCAAGGCTTACCTGAGCCTGAATGGGCCGCTCAGCTGCGCGAGGTCATTGCTCTAATAGATGAGCCATCACCTGAACAGGACGATTGCTCCCCTTATCTCGATCTGAATAATAAGTAA', 'lcl|NC_016838.5': 'ATGACGAGATCCAAAAAGGTTTCACACTGGATTGATTCCGGCTTCCCTCCGCTGAATAAAGCCATCTCCGGGCGCTATGACGGCGGTTTCCCAAGCGGACGTATCGTTGAGATCTTTGGGCCGCCAAGTGCTGGTAAAACCTTCCTGGCGACGGCCGCCATGGTCTCCGCTCAGAAACAGGAGGGTCTGGCTGTATTCCTCGACCACGAAAACAGCTTTGACGTTGGTCTGGCGGTGGCAAACGGGCTGAATGCGGATGAGGATGACGGCCAGTGGGTCT'}

        至此,我们的FASTA解析器已经步入正轨,而且我们创建的sample.fasta(如下图所示)不仅是一个标准的FASTA文件,而且还特异包含了一些小的错误(如在首行和序列之间有许多的空行,如下图的箭头所示)。

python fastapi 支持 stream python处理fasta文件_python_02

          请注意,该程序已经像冠军一样可以处理大部分的“魔鬼细节”,对于序列本身都是ATGC的文件进行读取不成问题,但若序列本身含有除ATGC以外的字母,那么还需另外的代码以应对这些“魔鬼细节”!

 PS:文章中的测试文件可以到百度网盘下载:

链接: https://pan.baidu.com/s/1gIQLBXvhhOlyNPBXwSJgUg

提取码: j3ie