zoukankan      html  css  js  c++  java
  • Bioinfo:学习Python,做生信PartII 学习笔记

    在学习了生信大神孟浩巍的知乎Live “学习Python, 做生信”之后,对第二部分的文件信息处理部分整理了如下的笔记。

    一、fasta与fastq格式的转换

    1、首先需要了解FASTA和FASTQ格式的详解

    1)具体的详解看知乎专栏的这篇文章,写的很详细。

    https://zhuanlan.zhihu.com/p/20714540

    2)关于FASTA

    • 主要分为两部分:第一行是“>”开始的储运存的序列描述信息;接下来是序列部分。序列部分可以有空格,按照一般70~80bp。用python进行操作的过程中,需要去掉空格和换行符,把序列读成一行再处理。(.strip()可以除去空格)
    • 即使是mRNA的序列,为了保证数据的统一性,序列中的U依然是用T来表示。核苷酸序列信息对应列表如下所示。
    A  adenosine          C  cytidine             G  guanine
    T  thymidine          N  A/G/C/T (any)        U  uridine 
    K  G/T (keto)         S  G/C (strong)         Y  T/C (pyrimidine) 
    M  A/C (amino)        W  A/T (weak)           R  G/A (purine)        
    B  G/T/C              D  G/A/T                H  A/C/T      
    V  G/C/A              -  gap of indeterminate length

    3)关于FASTQ

    • 刚刚测到的测序数据一般用FASTQ格式进行储存,因为其中包含了测序质量信息。
    • 四行依次为:信息头,序列信息,注释信息,质量信息。质量值的计算方法见上面链接里的文章。
    • 序列符号为 ATCGN,N表示无法确定。

    2、读取fastq文件并进行相应的格式转化

    1)主要流程如下:

    • 读取fastq文件,1header作为fastaheader 
    • 读取fastq文件,2seq作为fasta格式的seq
    • 第3/4行直接忽略
    • 格式化输出fasta文件

    2)以下是没有设置输出并储存为.fa文件的代码

     1 #-*- coding: UTF-8 -*-
     2 with open( 'E:genome_file\test.fastq','r') as input_fastq:
     3     for index, line in enumerate (input_fastq):  
     4         if index % 4 == 0:
     5             print ">" + line.strip()[1:]
     6         elif index % 4 == 1:
     7             for i in range (0,len(line.strip()),40):
     8                 print line.strip()[i:i+40]
     9         elif index % 4 == 2:
    10             pass
    11         elif index % 4 == 3:
    12             pass

    3)以下是设置了输出fasta文件的代码:

     1 out_file = open(E:genome_file\test.fa)
     2 
     3 with open( 'E:genome_file\test.fastq','r') as input_fastq:
     4 
     5     for index, line in enumerate (input_fastq):
     6 
     7         if index % 4 == 0:
     8             out_file.write(">" + line.strip()[1:]+"
    " )
     9 
    10         elif index % 4 == 1:
    11             for i in range (0,len(line.strip()),40):
    12                 out_file.write(line.strip()[i:i + 40] +"
    ")
    13 
    14         elif index % 4 == 2:
    15             pass
    16 
    17         elif index % 4 == 3:
    18             pass

    4)有几点注意的地方这里提一下:

    • 2)和3)中代码的主要区别就是在3)在一开始创建了一个output_file,这就是用来输出用的。所以可以看到2)中的输出直接用的是print,而3)中则是通过.write写入到 output_file当中。
    • 读取第一行的时候要特别注意:去掉原先FASTQ文件中的“@”字符,并加上一个“>”字符。
    • enumarate是个遍历函数,能够输出相应的索引和对应的值。
    • print能够自动换行,但是write不行。所以在写入的时候需要切片+ ,切多少呢一般?前面在关于fasta格式文件介绍中有提到。

    二、读取fasta格式文件

    1、分析过程

    • 当有>的时候,就为标题行;
    • 当不是>的时候,就是序列信息;
    • 当是序列信息的时候,需要进行序列的拼接;
    • 最终返回序列的headerseq

    2、简化版的主要代码如下:

    input_file = open( 'E:genome_file\test.fa','r')
    seq = ""
    header = input_file.readline().strip()[1:]
    
    for line in input_file:
        line = line.strip()
        if line[0] != ">":
            seq = seq + line
        else:
            print header
            print seq
            header = line[1:]
            seq = ""
    #打印最后一行
    print header
    print seq
    input_file.close()

    3、值得注意的几个地方:

    • 整体思路就是通过for循环进行序列信息的累加;
    • 一开始先读一行header(虽然暂时也还没搞太明白为什么,反正就是如果不读的话出来结果是乱七八糟的)
    • 按照上面那个情况,循环中是无法打印最后一行的,所以要在最外面打印一下。
    • readline和readlines的区别:readline只读一行,readlines则是一下子读整个文件。永远不要用readlines!!

    4、下面的代码是汇总了上面的功能,直接通过函数形式fastq-->fasta格式文件的转换

     1 def read_fasta(file_path=""):
     2     """
     3     Loading FASTA file and return a iterative object
     4     """
     5 
     6     line = ""
     7 
     8     try:
     9         fasta_handle = open(file_path,"r")
    10     except:
    11         raise IOError("Your input FASTA file is not right!")
    12 
    13     # make sure the file is not empty
    14     while True:
    15         line = fasta_handle.readline()
    16         if line == "":
    17             return
    18         if line[0] == ">":
    19             break
    20 
    21     # when the file is not empty, we try to load FASTA file
    22     while True:
    23         if line[0] != ">":
    24             raise ValueError("Records in Fasta files should start with '>' character")
    25         title = line[1:].rstrip()
    26         lines = []
    27         line = fasta_handle.readline()#这里是读第二行了
    28         while True:#循环只用来加载序列行
    29             if not line:
    30                 break
    31             if line[0] == ">":
    32                 break
    33             lines.append(line.rstrip())
    34             line = fasta_handle.readline()
    35 
    36         yield title,"".join(lines).replace(" ","").replace("
    ","")
    37 
    38         if not line:
    39             return
    40 
    41     fasta_handle.close()
    42     assert False, "Your input FASTA file have format problem."
    43 
    44 for header,seq in read_fasta(file_path=r"D:data_file	est.fa"):
    45     print header
    46     print seq
    47 #下面是后边的练习中以hg19为例进行操作
    48 hg19_genome = {}
    49 for chr_name , chr_seq in read_fasta(file_path=r"D:/data_file/hg19_only_chromosome.fa"):
    50     hg19_genome[chr_name] = chr_seq

    其实不太明白的是这里边最终是返回两个head和seq两个值了吗?为什么后边直接来两个参数就能开始for循环?

    三、计算人类基因组长度信息

    1、下载人类参考基因组信息(UCSC网站)

    • http://hgdownload.soe.ucsc.edu/downloads.html#human
    • 下载对象为hg19全基因组信息

    2、利用读取fasta的代码读取基因组序列

    1)代码如下:

    1 #前面已经定义过的read_fasta函数这里不再重复写。
    2 hg19_genome = {}
    3 
    4 for chr_name , chr_seq in read_fasta(file_path=r"D:/data_file/hg19_only_chromosome.fa"):
    5     hg19_genome[chr_name] = chr_seq

    2)注意几点

    • 程序中把下载的.fa文件中的信息输入到hg19_genome的列表当中
    • 读取一个全基因组数据需要耗费一定量的时间和内存,如果再pycharm或者通过powershell进行运行,调试的时候每调试一次就要运行一次,很费事。这个时候jupyter就方便多了。使用方法:1、终端输入conda,回车;2、输入jupyter notebook,回车;3、在弹出的中选择计算机上相应的Python程序,hello world。

    3、统计每条序列的长度,并输出 ;

    1)下面这个是一个乱序的输出

    1 for chr_name in sorted(hg19_genome.keys()):
    2     print chr_name, len(hg19_genome.get(chr_name))

    2)下面的代码能够做到按顺序输出

     1 hg19_total_len = 0
     2 for index in range (1,26):
     3     if index <=22:
     4         chr_name = "chr%s" %index
     5     elif index == 23:
     6         chr_name = "chrX"
     7     elif index == 24:
     8         chr_name = "chrY"
     9     elif index == 25:
    10         chr_name = "chrM"
    11     print chr_name, len(hg19_genome.get(chr_name))
    12     hg19_total_len = hg19_total_len + len(hg19_genome.get(chr_name))
    13     
    14 print "Total chromosome length is %s" %hg19_total_len

    注意一点:一般从字典里边根据Key来获取内容,用.get(),这样子在对象不存在的时候就不会报错。

    3、统计人类参考基因组的总长度,并输出

    在上面已经输出,往回看。

    4、统计每条染色体N的长度,并输出(GC含量同理)

    以N为例,其他同理。使用.count指令。

    1 hg19_genome['chr22'].count("N")

    5、提取基因组特定区域的序列,并输出(支持+/-链)

    1)思路分析

    • 通过切片可以截取特定区域的序列
    • 需要进行转移来过得互补序列
    • [::-1]能够实现序列反向的功能

    2)上代码

     1 chr_name = "chr1"
     2 chr_start = 10000
     3 chr_end = 10100
     4 #特定区域截取
     5 hg19_genome[chr_name][chr_start-1:chr_end-1].upper()
     6 #互补链
     7 import string
     8 translate_table = string.maketrans("ATCG","TAGC")
     9 a = hg19_genome[chr_name][chr_start-1:chr_end-1].upper()
    10 a.translate(translate_table)
    11 
    12 #反向链
    13 a.translate(translate_table)[::-1]#反向
    • 这里导入string模块,设定一个转译表
    • .upper是用来把小写字母全部转换成大写
    • 注意要“-1”

    3)定义成函数方便使用

    1 def con_rev(input_seq):
    2     translate_table = string.maketrans("ATCG","TAGC")
    3     output_seq = input_seq.upper().translate(translate_table)[::-1]
    4     return output_seq
    5 
    6 con_rev("aaTTCCGG")

    四、计算人类基因组外显子的长度(CDS区域同理)

    1、下载人类参考转录组(UCSC table browser)

    • 一般在track一栏均选择RefSeq Genes

    2、整体思路

    • 从转录组抓取关键信息:exon_count, gene_id, exon_start,exon_end
    • 最后输出一个字典:{‘基因名,外显子长度’}
    • 同一基因存在不同转录本,本例中按照最长计算,所以需要进行比较

    3、上代码

     1 gene_exon_len_dict = {}
     2 with open(r"E:genome_filehg19_refseq_gene_table","r") as input_file:
     3     header = input_file.readline()
     4     for line in input_file:
     5         line = line.strip().split("	")
     6         
     7         exon_count = int(line[8])
     8         exon_start = line[9].split(",")#还有更好的方法进行index
     9         exon_end = line[10].split(",")
    10         exon_total_len = 0
    11         gene_id = line[12]
    12         for index in range (exon_count):
    13             exon_total_len = exon_total_len + int(exon_end[index]) - int(exon_start[index])
    14             
    15         if gene_exon_len_dict.get(gene_id) is None:#注意:如果直接用dict[gene_id]是会出现key error的
    16             gene_exon_len_dict[gene_id] = exon_total_len
    17             
    18         elif gene_exon_len_dict[gene_id] < exon_total_len:
    19             gene_exon_len_dict[gene_id] = exon_total_len
    20             
    21         else:
    22             pass
    23             
    24         #注意啊调试的时候要加break,这是很重要的!!
    25         
    26     print gene_exon_len_dict
    27        
    • .split()能够根据括号中的内容把相应的字符串拆分成为列表
    • exon_start和exon_end都要以整型的格式才能进行相减。除了上面代码中的处理方法,还可以通过如下方法来实现:
    1     exon_start = map(int,line[9].strip(",").split(","))
    2     exon_end = map(int,line[10].strip(",").split(","))
    • 特别重要!!数据量大的运算,调试的时候,在后边加个 break啊!!不然卡的你怀疑人生~~~
  • 相关阅读:
    SpringBoot入门学习(二)
    SpringBoot入门学习(一)
    eclipse调试程序界面简单介绍使用
    利用URLConnection来发送POST和GET请求
    查看用户所属的组
    linux下创建用户,给用户设置密码,给用户授权
    新linux系统上rz 与sz命令不可用
    pom.xml文件报错:web.xml is missing and <failOnMissingWebXml> is set to true
    MySql采用GROUP_CONCAT合并多条数据显示的方法
    Mysql计算时间差
  • 原文地址:https://www.cnblogs.com/dingtou00/p/8167986.html
Copyright © 2011-2022 走看看