Python3 提取CDS

根据物种基因组和注释文件,可以编写脚本,提取特殊的序列结构,完成个性化的分析。本文利用Python3提取拟南芥的最长编码序列,并转化为氨基酸序列输出到文件中。

基因结构

参考链接:WIKIVERSITY

  • 真核生物和原核生物具有不同的基因结构,首先我们认识一下真核生物的基因结构。接下来我们根据基因结构,提取分析不同结构。


    真核生物的基因结构
简并碱基

个别物种的参考基因组中存在特殊的简并碱基,即在基因组某个位置上存在多种碱基类型,一般可以用单个碱基表示。

  • 类型
R:  A/G
Y:  C/T
M:  A/C
K:  G/T
S:  G/C
W:  A/T
H:  A/T/C
B:  G/T/C
V:  G/A/C
D:  G/A/T
N:  A/T/C/G
  • 简并碱基的原因
    基因组测序样品为多倍体,在同一位点检测到多种碱基信号;测序样品为混合样品,在同一位点检测到多种碱基信号;测序错误;
  • 如何处理
    在拟南芥的基因组中存在的简并碱基,在翻译的时候统一翻译成氨基酸X(参考NCBI的注释文件)。
提取基因组基因最长蛋白编码序列脚本
#------------------------------------------------------------------
#------------------------------------------------------------------
#作者:香波地海
#时间:2019/09/12
#脚本名称:TAIR10.1_sub_longest_cds.py
#脚本功能:根据拟南芥注释文件的features,提取最长编码蛋白序列
#运行模式:python Script.py genome.fasta genome.gff
#返回结果格式:
#   >geneid1
#   ATGTTTGGGAAACCCTGCGATGCTACGCT
#   >geneid2
#   ATGCCCGTAGCTAGCGATCGTAGCTAGCTAGCT
#---------------------------------------------------------------------------------------------------

#---------------------------------------------------------------------------------------------------
#举例说明提取过程
#---------------------------------------------------------------------------------------------------

# cds = {}
#如果不是第一个gene信息的话,则处理上个基因里面的多个编码蛋白序列,计算长度提取最长的编码序列;

# cds['gene1'] = {}
# cds['gene1']['pro1'] = [('chr1','+',1,100)]
# cds['gene1']['pro1'] = [('chr1','+',1,100),('chr1','+',150,200),('chr1','+',250,300),('chr1','+',350,400),('chr1','+',450,500),]

# cds['gene1']['pro2'] = [('chr1','+',1,100)]
# cds['gene1']['pro2'] = [('chr1','+',1,100),('chr1','+',120,200),('chr1','+',220,300),('chr1','+',320,400),('chr1','+',420,500),]

# cds['gene2'] = {}
# cds['gene2']['pro3'] = [('chr1','+',1,100)]
# cds['gene2']['pro3'] = [('chr1','+',1,100),('chr1','+',110,200),('chr1','+',210,300),('chr1','+',310,400),('chr1','+',410,500),]

# cds['gene2']['pro4'] = [('chr1','+',1,100)]
# cds['gene2']['pro4'] = [('chr1','+',1,100),('chr1','+',100,200),('chr1','+',200,300),('chr1','+',300,400),('chr1','+',400,500),]

#处理最后一个基因的多个编码蛋白序列,提取最长的蛋白编码序列

#---------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
import sys
import re
from Bio import SeqIO


#---------------------------------------------------------------------------------------------------
#写一个函数readgff(),读取基因组注释文件,返回gene、mrna、exon、cds、longest_cds的字典
#---------------------------------------------------------------------------------------------------
def readgff(gff_file):
    '''

    ''' 
    g_id = ''
    gene = {}
    mrna = {}
    exon = {}
    cds = {}
    longest_cds = {}

    with open(gff_file) as gff:
        for line in gff:
            if line.startswith('#'):
                continue
            else:
                line = line.strip()
                (chrs,ref,features,start,end,dot,strand,start_point,note)= line.split('\t')

                if features == 'gene' :
                #-----------------------------------------------------------------------------------
                #在读取下一个基因之前,筛选上一个基因的转录本,构建每个基因对应的最长转录本字典
                #-----------------------------------------------------------------------------------
                    if g_id != '':
                        if cds.get(g_id,None):
                            temp = {}
                            for pro, pos in cds[g_id].items():
                                sum = 0
                                for i in pos:
                                    sum += int(i[-1]) - int(i[-2]) + 1
                                temp[pro] = sum
                            longest_pro = max(temp,key=temp.get)
                            longest_cds[g_id] = cds[g_id][longest_pro]
                    #-------------------------------------------------------------------------------
                    #如果g_id为空值,说明这是注释的第一个基因,那么读取基因ig,构建新的基因字典;如果g_id不是空值,
                    #那么找到上一个基因的最长转录本之后,记录和存储下一个基因的各种信息
                    #-------------------------------------------------------------------------------
                    g_id = note.split(';')[0].replace('ID=','')
                    gene[g_id] = (chrs,strand,start,end)
                    cds[g_id] = {}
                    exon[g_id] = {}
                    mrna[g_id] = {}
    
                if features == 'mRNA':
                    r_id = note.split(';')[0].replace('ID=','')
                    mrna[g_id][r_id] = (chrs,strand,start,end)

                if features == 'exon':
                    r_id = note.split(';')[1].replace('Parent=','')
                    if exon[g_id].get(r_id,None):
                        exon[g_id][r_id].append((chrs,strand,start,end))
                    else:
                        exon[g_id][r_id] = [(chrs,strand,start,end)]

                if features == 'CDS':   
                    c_id = note.split(';')[0].replace('ID=cds-','')
                    if cds[g_id].get(c_id,None):
                        cds[g_id][c_id].append((chrs,strand,start,end))
                    else:
                        cds[g_id][c_id] = [(chrs,strand,start,end)]
                else:
                    continue
    #-----------------------------------------------------------------------------------------------
    #分析最后一个基因的最长转录本
    #-----------------------------------------------------------------------------------------------
    if cds.get(g_id,None):
        temp = {}
        for pro, pos in cds[g_id].items():
            sum = 0
            for i in pos:
                sum += int(i[-1]) - int(i[-2]) + 1
            temp[pro] = sum
        longest_pro = max(temp,key=temp.get)
        longest_cds[g_id] = cds[g_id][longest_pro]
    return gene,mrna,exon,cds,longest_cds

#---------------------------------------------------------------------------------------------------
#定义一个函数用于根据基因位置列表,提取并拼接得到orf的函数sequence(postion)
# longest_cds['gene2'] = [('chr1','+',1,100),('chr1','+',100,200),('chr1','+',200,300),
#                                                       ('chr1','+',300,400),('chr1','+',400,500),]
#---------------------------------------------------------------------------------------------------

def sequence(position):
    '''
    根据函数参数元组position提供的位置参数,提取基因的碱基序列,"+"正链的按照起始位置切片提取,"-"负链的转换成反向互补序列提取,
    最后输出dna字符串
    5'----ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAGCAT----3'
    3'----TACCGGTAACATTACCCGGCGACTTTCCCACGGGCTATCGTA----5'

    '''
    hash = {'A':'T','T':'A','C':'G','G':'C','N':'N'}
    scaffold,strand,start,end = position
    if strand == '+':
        dna = Fa[str(scaffold)][int(start)-1:int(end)].upper()
    if strand == '-':
        dna1 = Fa[str(scaffold)][int(start)-1:int(end)][::-1].upper()
        dna = ''.join([hash[i] for i in dna1])
    return dna
#---------------------------------------------------------------------------------------------------
#定义一个函数dna_to_aa(),将核苷酸序列转变成氨基酸序列。输入为dna序列,输出为aa序列。
#---------------------------------------------------------------------------------------------------

def dna_to_aa(dna_seq):
    '''
    定义密码子与氨基酸对应的字典,其中终止密码子用*表示

    '''
    aa_dict = {
    'TTT':'F', 'TTC':'F', 'TTA':'L', 'TTG':'L', 'CTT':'L', 'CTC':'L', 'CTA':'L', 'CTG':'L', 'ATT':'I', 'ATC':'I','ATA':'I', 
    'ATG':'M', 'GTT':'V', 'GTC':'V', 'GTA':'V', 'GTG':'V', 'TCT':'S', 'TCC':'S', 'TCA':'S', 'TCG':'S', 'CCT':'P', 'CCC':'P',
    'CCA':'P', 'CCG':'P', 'ACT':'T', 'ACC':'T', 'ACA':'T', 'ACG':'T', 'GCT':'A', 'GCC':'A', 'GCA':'A', 'GCG':'A','TAT':'Y',
    'TAC':'Y',  'CAT':'H', 'CAC':'H', 'CAA':'Q', 'CAG':'Q', 'AAT':'N', 'AAC':'N', 'AAA':'K', 'AAG':'K', 'GAT':'D', 'GAC':'D', 
    'GAA':'E', 'GAG':'E', 'TGT':'C', 'TGC':'C', 'TGG':'W', 'CGT':'R', 'CGC':'R','CGA':'R','CGG':'R', 'AGT':'S', 'AGC':'S', 
    'AGA':'R', 'AGG':'R', 'GGT':'G', 'GGC':'G', 'GGA':'G', 'GGG':'G', 'TGA':'*', 'TAA':'*', 'TAG':'*',
    }

    
    #定一个空列表,用来存储翻译完成的氨基酸序列
    aa_seq = []
    for i in range(0,len(dna_seq)-2,3):
        codons = dna_seq[i:i+3]
        if aa_dict.get(codons):
            aa_seq.append(aa_dict[codons])
        else:
            aa_seq.append('@')
    aa = "".join(aa_seq)
    return aa
#---------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------


try:
    genome = sys.argv[1]
    gff = sys.argv[2]
    gene,mrna,exon,cds,longest_cds = readgff(gff)
    Fa = {rec.id:rec.seq for rec in SeqIO.parse(genome,"fasta")}
    print('There are {} genes in the genome.'.format(len(gene)))
    print('There are {} genes transcripted mRNA.'.format(len(mrna)))
    print('There are {} genes transcripted cds.'.format(len(exon)))
    print('There are {} longest proteins produced.'.format(len(longest_cds)))
#---------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
#输出最长转录本
# longest_cds['gene2'] = [('chr1','+',1,100),('chr1','+',100,200),('chr1','+',200,300),('chr1','+',300,400),('chr1','+',400,500),]
except IndexError:
    print('please input an gff and fasta file!')
finally:
    #---------------------------------------------------------------------------------------------------
    #---------------------------------------------------------------------------------------------------
    with open("out1.fa",'w') as W:
        for name,positions in longest_cds.items():
            seq = ''
            for p in positions:
                seq += sequence(p)
            aa = dna_to_aa(seq)
            W.write(">" + name + "\n")
            W.write(aa + "\n")

    print('The programs of {} have completed!'.format(sys.argv[0]))

#------------------------------------------------------------------#------------------------------------------------------------------
#结束了!
#------------------------------------------------------------------#------------------------------------------------------------------

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

推荐阅读更多精彩内容