美文网首页生物信息学习
生信必备技能 -- 不可描述

生信必备技能 -- 不可描述

作者: 正踪大米饭儿 | 来源:发表于2017-03-04 11:09 被阅读49次

    在做 Small RNA 分析的过程中时遇到了一个有意思的事情,前期比对到不同的数据库后需要将不同的短 tags 注释到不同的类别上,这个地方有点意思的事情是同一条 tags 可能被注释到不同的类别上,这里就需要对不同的类别进行优先级排序了。
    一般按照惯例我们会根据 已知 miRNA -> rRNA -> tRNA -> ncRNA (snRNA, snoRNA) 的顺序进行优先级注释。

    在写程序的时候基本上有以下的思路:
    首先我获得了每个数据库的比对结果,知道了哪些 tags 比对到了相应的数据库中,使用最基本的思路是从 总的 tags 中先剔除比对到相应物种的成熟 miRNA,然后剔除比对到物种相应的总的 hairpin ( miRNA 前体数据库),然后剔除比对到 GeneBank 数据库中的 rRNA 以及 tRNA , 如果有 snRNA 或者 snoRNA 等 tags 的话依次提取出来。

    思路很简单,但是真正动手写脚本的时候才发现,这个过程苏是多么的冗余。因为,这样思路下我们如果要比对7个数据库的话,最少就应该用同样的脚本过滤六次。好麻烦,还好我比较喜欢偷懒,写脚本的时候应用了另一种思路:
    直接处理所有的 tags 然后对不同的数据库比对结果信息分别建立一个文件,通过不同的文件标签进行 tags 分类标记,这样就省事多了:
    附上源代码:( 遵循 GLP v3 开源协议 )

    #!/usr/bin/perl -w
    use strict;
    
    die "Usage: perl $0 <list> <prefix> <indir> \n" if @ARGV < 3;
    
    my $info_dir = $ARGV[2];
    my $sample = $ARGV[1];
    
    my ( %list, %out );
    
    # deal with all tags
    open IN,$ARGV[0] or die $!;
    while (<IN>){
        chomp;
        next if /^#/;
        my ($id, $cnt) = split /\t/,$_;
        $list{$id}{"count"} = $cnt;
    }
    close IN;
    
    # indir must contain files like: $sample.m2mature.info 
    # t0023555        xxx_tRNA_AM087200_6:80:-        1       20      +
    # t0031916        xxx_tRNA_AM087200_6:80:-        1       21      +
    
    opendir DIR, $info_dir or die $!;
    foreach my $file (sort grep(/$sample\.\S+\.info$/,readdir(DIR))){
        (my $type) = $file =~ /$sample\.(\S+)\.info/;
        if ($type eq "m2ncgb"){
            open IN,$file or die $!;
            while (<IN>)  {
                chomp;
                next if /^#/;
                next if /^$/;
                my @b = split /\t/,$_;
                my @c = split /_/,$b[1];
                push @{$out{$b[0]}},$c[1];
            }
            close IN;
        } else {
            open IN,$file or die $!;
            while (<IN>)  {
                chomp;
                next if /^#/;
                next if /^$/;
                my @b = split /\t/,$_;
                push @{$out{$b[0]}},$type;
            }
            close IN;
        }
    }
    close DIR;
    
    foreach my $k (sort keys %list){
        if (exists $out{$k}){
            my $t = @{$out{$k}}==1 ? $out{$k}->[0] :join ",",@{$out{$k}};
            print "$k\t$t\n";
        }else {
            print "$k\t-\n";
        }
    }
    

    附上大牛的代码:行使同样的功能,代码量只有我的一半!

    #! /usr/bin/perl -w
    use strict;
    die "perl $0  input.txt prefix  dir\n"  unless @ARGV == 3;
    
    chomp(my @file = glob "$ARGV[2]/$ARGV[1].*info");
    my %ha;
    foreach(@file){
       my $flag = (split/\./,$_)[-2];
       ding($_,\%ha,$flag);
    }
    open IN,$ARGV[0]||die;
    while(<IN>){
        chomp;
        my $id = (split/\t/,$_)[0];
        $ha{$id} ||= "NA,";
        chop $ha{$id};
        print "$id\t$ha{$id}\n";
    }
    close IN;
    
    ############################################
    sub ding{
        my ($p,$q,$f) = @_;
        open IN,$p||die;
        while(<IN>){
            chomp;
            next if /^#|^$/;
            my $a = (split/\t/,$_)[0];
            $q->{$a} .="$f,";
        }
    }
    

    perl 真是一门强大的脚本们语言。同样的功能有多种多样的方法可以将它演绎出来!

    ** 这里值得重点划线的地方是 这一句代码:**

    my $t = @{$out{$k}}==1 ? $out{$k}->[0] :join ",",@{$out{$k}};
    

    这里使用了 ?:的判断方式,问号前面代表判断的条件,问号后面冒号前面代表条件判断如果为真则执行,否则就执行冒号后面的语句。

    欢迎大家留言讨论!

    相关文章

      网友评论

        本文标题:生信必备技能 -- 不可描述

        本文链接:https://www.haomeiwen.com/subject/ffmdgttx.html