生物信息必备技能 -- 查找 SNP 突变后的氨基酸

生信虐我系列之--几个必备小程序:
这个程序可以根据提供的 SNP位点信息,以及参考注释信息对 SNP 位点突变前后的 氨基酸 进行比较。

** 修改了部分代码,重新设计了 SNP 突变位点落在反向转录本上的情况**
** 重新设计了结果的输出格式**
** 欢迎积极提出设计上的不足**

输入文件格式:
1. 参考注释的 GTF 文件;
2. 参考注释的基因组 fasta 文件;
3. 输入的 SNP 列表文件:
  1       49527   A       G       Exon:Zm00001d027230;
  1       51053   A       T       Exon:Zm00001d027231;
  1       53013   A       G       Exon:Zm00001d027231;
  1       53109   C       T       Exon:Zm00001d027231;
第一列: 染色体
第二列:突变位置
第三列:SNP 参考的碱基
第四列:SNP 位点突变后的碱基
第五列:[可选],SNP 的信息

使用方法:

perl script.pl zma.gtf zma.fa in.txt >result.txt

程序源码如下:(遵循 GPL v3 Licenses

#!/usr/bin/perl -w
use strict;
die "Usage: perl $0 <zma.GTF> <zma.FA> <in.TXT> >Result.txt \n" if @ARGV < 3;

&timing("start")
my (%tr, %cds, %seq);

open IN, $ARGV[0] or die $!;
while (<IN>){
    chomp;
    next if /^#/;
    my @a = split /\t/,$_;
    if ($a[2] eq "transcript"){
#        (my $gene) = $a[8] =~ /gene_id\s"(\S+)";/;
        (my $id) = $a[8] =~ /transcript_id\s"(\S+)";/;

#        $tr{$a[0]}{$gene}{$id} = [@a[3,4,6]];
        $tr{$a[0]}{$id} = [@a[3,4,6]];
    }
    if ($a[2] eq "CDS"){
#        (my $gene) = $a[8] =~ /gene_id\s"(\S+)";/;
        (my $id) = $a[8] =~ /transcript_id\s"(\S+)";/;
        next unless exists $tr{$a[0]}{$id};
        push @{$cds{$a[0]}{$id}},[@a[3,4,7]];
    }
}
close IN;

# make fasta hash

open FA,$ARGV[1] or die $!;
$/ = ">"; <FA>;
while(<FA>){
    chomp;
    my ($info,$fa) = split /\n/,$_,2;
    my ($chr,$tmp) = split /\s/,$info,2;
    $fa =~ s/\n+//g;
    $seq{$chr} = $fa;
}
$/ = "\n";
close FA;

# deal with input 
open IN,$ARGV[2] or die $!;
print "# Chrom:Loci:Ref->Alt\tTranscript\tStrand\tCDS(Ref->Alt)\tRef_Codon\tAlt_Codon\tRef_aa\tAlt_aa\tAlt_Pos\tCDS_Pos\n";
while (<IN>){
    chomp;
    my ($chr,$loci,$ref,$alt,$tmp) = split /\t/,$_;
    my ($strand,$j,$tr_id);
    my @arr;
    my $flag = 0;

    if ( exists $tr{$chr} ){
        foreach my $k (sort keys $tr{$chr}){
            if ($loci >= $tr{$chr}{$k}->[0] && $loci <= $tr{$chr}{$k}->[1]){
                $flag = 1;
                $strand = $tr{$chr}{$k}->[2];
                @arr = sort{$a->[0] <=> $b->[0] || $a->[1] <=> $b->[1]} @{$cds{$chr}{$k}};
                for (my $i=0;$i<@arr;$i++){
                    if ($loci >= $arr[$i]->[0] && $loci <= $arr[$i]->[1]){
                        $flag = 2;
                        $j = $i;
                        $tr_id = $k;
                        last;
                    }
                }
            }
        }
    }
if ($flag == 2 ){
        my ($pos, $seq, $site, $ref_codon, $alt_codon, $ref_aa, $alt_aa);
        my ($ref_nucl, $alt_nucl, $alt_pos);
        my $c = &code();

        if ($strand eq "+"){
            foreach (0..($j-1)){
                $pos += $arr[$_]->[1] - $arr[$_]->[0] + 1;
            }
            $pos += $loci - $arr[$j]->[0] + 1;
            foreach my $v (@arr){
                my ($x,$y) = @$v[0,1];
                $seq .= uc(substr($seq{$chr},$x-1,$y-$x+1));
            }
            $ref_nucl = substr($seq,$pos-1,1);
            $alt_nucl = $alt;

            $site = $pos % 3 ;
            if($site == 1){
                $ref_codon = uc(substr($seq,$pos - 1,3));
                $alt_codon = &ref2alt($ref_codon,1,$alt_nucl);
                $alt_pos = 1;
            }elsif($site == 2){
                $ref_codon = uc(substr($seq,$pos - 2,3));
                $alt_codon = &ref2alt($ref_codon,2,$alt_nucl);
                $alt_pos = 2;
            }elsif($site == 0){
                $ref_codon = uc(substr($seq,$pos - 3,3));
                $alt_codon = &ref2alt($ref_codon,3,$alt_nucl);
                $alt_pos = 3;
            }
        }
        if ($strand eq "-"){
            my $pos1;
            foreach (0..($j-1)){
                $pos1 += $arr[$_]->[1] - $arr[$_]->[0] + 1;
            }
            $pos1 += $loci - $arr[$j]->[0] + 1;
            foreach my $v (@arr){
                my ($x,$y) = @$v[0,1];
                $seq .= uc(substr($seq{$chr},$x-1,$y-$x+1));
            }
            my $len = length $seq;
            $pos = $len - $pos1 + 1;
            $seq = reverse $seq;
            $seq =~ tr/AaGgCcTt/TtCcGgAa/;
 
            $ref_nucl = substr($seq,$pos-1,1);
            $alt_nucl = $alt;
            $alt_nucl =~ tr/AaGgCcTt/TtCcGgAa/;
            
            $site = $pos % 3;
            if($site == 1){
                $ref_codon = uc(substr($seq,$pos - 1,3));
                $alt_codon = &ref2alt($ref_codon,1,$alt_nucl);
                $alt_pos = 1;
            }elsif($site == 2){
                $ref_codon = uc(substr($seq,$pos - 2,3));
                $alt_codon = &ref2alt($ref_codon,2,$alt_nucl);
                $alt_pos = 2;
            }elsif($site == 0){
                $ref_codon = uc(substr($seq,$pos - 3,3));
                $alt_codon = &ref2alt($ref_codon,3,$alt_nucl);
                $alt_pos = 3;
            }
        }
        $ref_aa = exists $c->{"standard"}{$ref_codon} ? $c->{"standard"}{$ref_codon} : "-";
        $alt_aa = exists $c->{"standard"}{$alt_codon} ? $c->{"standard"}{$alt_codon} : "-";
        print "$chr:$loci:$ref->$alt\t$tr_id\t$strand\t$ref_nucl->$alt_nucl\t$ref_codon\t$alt_codon\t$ref_aa\t$alt_aa\t$alt_pos\tcds_$pos\n"; 
    }
}
close IN;

&timing("end");

# time
sub timing{
    my $state=shift;
    my $time=strftime("%Y-%m-%d.%H:%M:%S",localtime);
    print STDOUT "## ==== >> Start at $time\n" if $state eq "start";
    print STDOUT "## ==== >> End at $time\n" if $state eq "end";
}
# ref2alt
sub ref2alt{
    my ($codon, $pos, $alt) = @_;
    my ($c1, $c2, $c3) = split //,$codon;
    my $out;
    
    if ($pos == 1){
        $out = join ("",$alt,$c2,$c3);
    }elsif ($pos == 2){
        $out = join ("",$c1,$alt,$c3);
    }else{
        $out = join ("",$c1,$c2,$alt);
    }
    return $out;
}

# code
sub code{
    my $p = {
        "standard" =>
        {       
            'GCA' => 'A', 'GCC' => 'A', 'GCG' => 'A', 'GCT' => 'A',                               # Alanine
            'TGC' => 'C', 'TGT' => 'C',                                                           # Cysteine
            'GAC' => 'D', 'GAT' => 'D',                                                           # Aspartic Aci
            'GAA' => 'E', 'GAG' => 'E',                                                           # Glutamic Aci
            'TTC' => 'F', 'TTT' => 'F',                                                           # Phenylalanin
            'GGA' => 'G', 'GGC' => 'G', 'GGG' => 'G', 'GGT' => 'G',                               # Glycine
            'CAC' => 'H', 'CAT' => 'H',                                                           # Histidine
            'ATA' => 'I', 'ATC' => 'I', 'ATT' => 'I',                                             # Isoleucine
            'AAA' => 'K', 'AAG' => 'K',                                                           # Lysine
            'CTA' => 'L', 'CTC' => 'L', 'CTG' => 'L', 'CTT' => 'L', 'TTA' => 'L', 'TTG' => 'L',   # Leucine
            'ATG' => 'M',                                                                         # Methionine
            'AAC' => 'N', 'AAT' => 'N',                                                           # Asparagine
            'CCA' => 'P', 'CCC' => 'P', 'CCG' => 'P', 'CCT' => 'P',                               # Proline
            'CAA' => 'Q', 'CAG' => 'Q',                                                           # Glutamine
            'CGA' => 'R', 'CGC' => 'R', 'CGG' => 'R', 'CGT' => 'R', 'AGA' => 'R', 'AGG' => 'R',   # Arginine
            'TCA' => 'S', 'TCC' => 'S', 'TCG' => 'S', 'TCT' => 'S', 'AGC' => 'S', 'AGT' => 'S',   # Serine
            'ACA' => 'T', 'ACC' => 'T', 'ACG' => 'T', 'ACT' => 'T',                               # Threonine
            'GTA' => 'V', 'GTC' => 'V', 'GTG' => 'V', 'GTT' => 'V',                               # Valine
            'TGG' => 'W',                                                                         # Tryptophan
            'TAC' => 'Y', 'TAT' => 'Y',                                                           # Tyrosine
            'TAA' => 'U', 'TAG' => 'U', 'TGA' => 'U'                                              # Stop
        }
    }
}


__END__

1       49527   A       G       Exon:Zm00001d027230;
1       51053   A       T       Exon:Zm00001d027231;
1       53013   A       G       Exon:Zm00001d027231;
1       53109   C       T       Exon:Zm00001d027231;
1       53826   T       C       Exon:Zm00001d027231;
1       53885   T       C       Exon:Zm00001d027231;

本文原创,转载请注明出处!
欢迎留言讨论!

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

推荐阅读更多精彩内容