nsSNPs致病性分析(一): 自己写脚本分析蛋白质保守性

——仅以此纪念自己半路夭折的工具开发计划

初衷:

SNV有很多类型,其中落在编码区域的非同义突变 (nsSNPs) 会带来氨基酸序列的改变,很可能带来不良的影响,但是其影响程度与其所处的位置以及氨基酸的理化性质有关

若非同义替换的发生位置是蛋白质的功能或结构的核心区域则更可能带来不良的影响,但是也不尽然,若突变前后的氨基酸的理化性质是否相近,比如分子大小相近,极性也很相似,那么也很可能是一个良性的变异

因此氨基酸位置的保守性能很大程度上反映其所处位置的重要性

想法:

目的:分析目的基因编码蛋白质序列各个氨基酸位点的保守性

实现方法:(1)获取与目的蛋白同源的蛋白质序列集合——从NCBI的Homogene数据库中获得某个基因(蛋白质)的同源基因(蛋白质);(2)基于这些序列之间的多序列比对结果,推算出各个位点的保守性评分(计算方法在下文中说明)——分值在0-1之间,分值越低保守性越低;

  1. 获取同源蛋白质序列及多序列比对结果

    从NCBI的Homogene数据库中获得某个基因(蛋白质)的同源基因(蛋白质),获取这些同源蛋白的多序列比对结果,直接将网页上的多序列比对结果复制黏贴成纯文本homogene.msa

    HomoloGene中的同源蛋白序列以及多序列比对

    homogene.msa转换成FASTA格式:

    # 读入上一步复制黏贴直接得到的原始多序列比对结果文件,除了空行之外,
    #   每行都由四列组成(以任意空字符为分隔符),其中第一列为序列Id,
    #   第三列为序列组成,则将这些序列读入并保存成哈希,以序列Id为key,
    #   以序列组成为value
    # 文件读取结束后,即将每条序列以fasta格式输出
    
    $ perl -ne \
    'chomp;
    next if(/^$/);  # 跳过空行
    @F=split /\s+/;
    $Seq{$F[0]}.=$F[2];
    END{
        foreach $key (keys(%Seq)){
            print ">$key\n$Seq{$key}\n"
        }
    }' \
    homogene.msa >homogene.msa.fasta
    
  2. 计算保守性分值

    用python脚本ConservativeAnalysis.py基于homogene.msa.fasta计算目标蛋白质序列各个位点的保守性,保守性的计算公式如下:

    这个公式其实用到了信息熵的思想,本质上是将总信息熵(或称最大信息熵)log2N,减去观测到的信息熵-∑Plog2P,若某一个位点的氨基酸组成多样性高,则保守性低,其观测信息熵就大,算出来的R值就小

    还可以用以下两种方式表示保守性:

    • 相对保守性:
    • 保守性分位数:


    Python脚本代码如下(脚本对上面提到的3中保守性分值都进行了计算):

    from Bio import SeqIO
    import sys
    import numpy as np
    import math
    
    # 用Biopython读入fasta序列
    def loadAASeq(infile):
        seq = {}
        for i in SeqIO.parse(infile,'fasta'):
            seq[i.id] = list(i.seq)
        return seq
    
    # 构建20种氨基酸和“-”gap占位符的字典,value为这些符号的编号
    def AAHash():
        AARow = {"A":0,
        "R":1,
        "N":2,
        "D":3,
        "C":4,
        "Q":5,
        "E":6,
        "G":7,
        "H":8,
        "I":9,
        "L":10,
        "K":11,
        "M":12,
        "F":13,
        "P":14,
        "S":15,
        "T":16,
        "W":17,
        "Y":18,
        "V":19,
        "-":20}
        return AARow
    
    # 对目标序列某一个位点的氨基酸组成进行频数统计
    def countFreq(seq,gaps,posi):
        '''
        seq:    [char] 目标序列名
        gaps:   [int] posi位置之前,目标序列存在的gap数
        posi:   [int] 当前位置,0-base
        '''
        if Seq[seq][posi] == '-':
            gaps += 1
        else:
            for key in Seq.keys():
                aa = Seq[key][posi]
                row = int(AA[aa])
                col = posi-gaps
                Count[row,col] += 1
        return gaps
    
    # 计算保守性分位数
    def Quantile(Vec):
        Vlen = len(Vec)
        SortIndex = Vec.argsort()
        
        # 计算每个数的秩序,当有多个数的值相等时,则用它们的最大秩序表示,如[1,2,2,5],其中的两个2并列第3
        #   主要思路为:若当前位置的值与上一个位置的值相同,说明存在数值并列情况,记下这个位置;
        #       若当前位置的值与上一个位置的值不相同,对之前的位置生成它们的秩序
        #   注意考虑第一个位置和最后一个位置的特殊情况:第一个位置没有更前的位置,最后一个位置没有更后的位置
        VRank = np.zeros(Vlen)
        forwardIndex = list()
        forwardValue = 0
        for i in range(0,Vlen):
            if Vec[SortIndex[i]] == forwardValue:
                forwardIndex.append(SortIndex[i])
                # 考虑最后一个位置的情况
                if i == Vlen-1:
                    for j in forwardIndex:
                        VRank[j] = i+1
            else:
                if len(forwardIndex) >= 2:
                    for j in forwardIndex:
                        VRank[j] = i
                else:
                    # 考虑第一个位置的情况
                    if i > 0:
                        VRank[SortIndex[i-1]] = i
                # 考虑最后一个位置的情况
                if i == Vlen-1:
                    VRank[SortIndex[i]] = i+1
                forwardIndex = [SortIndex[i]]
                forwardValue = Vec[SortIndex[i]]
        
        # 计算分位数
        PercValue = VRank*100/Vlen
        return PercValue
    
    if __name__ == '__main__':
        '''
        脚本共有两个输入参数:
        1. fasta格式的多序列比对结果
        2. 目标序列的id
        '''
        in_msa = sys.argv[1]
        nseq = sys.argv[2]
        Seq = loadAASeq(in_msa)
        AA = AAHash()
        seqlenAll = len(Seq[nseq]) # 多序列比对得到的比对整体的长度
        seqlenInt = seqlenAll - Seq[nseq].count('-') # 目标序列的氨基酸序列长度
        Count = np.zeros((21,seqlenInt),dtype = float) + 0.000001 # 加上一个很小的数是为了防止后面在执行对数计算时报错
        gaps = 0
        # 对每个位点进行频数统计,统计目标序列每个氨基酸位点的氨基酸组成频数分布,得到一个矩阵,行为20中氨基酸加“-”gap占位符,列为各个氨基酸位点   
        for i in range(0,seqlenAll):
            gaps = countFreq(nseq,gaps,i)
        colSum = sum(Count[...,0])
        # 每个位点氨基酸组成的频率
        CountRate = Count/colSum
        # 计算每个位点的保守性
        Shannon = -(CountRate*np.log2(CountRate)).sum(axis=0)
        Rindex = math.log2(21)-Shannon
        # 相对保守性
        Rrelat = (Rindex - Rindex.min())/(Rindex.max()-Rindex.min())
        # 保守性分位数,使用自定义的Quantile函数
        Rquant = Quantile(Rindex)
    

    由于脚本中添加了详细的注释,这里就不展开讲解了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容