【问题标题】:Perl program to look for k-mer with specific sequencePerl 程序查找具有特定序列的 k-mer
【发布时间】:2016-11-04 01:39:30
【问题描述】:

我正在尝试增强我之前编写的 perl 程序,以便它识别以 GG 结尾的前 1000 个长度为 23 k-mers 并打印出仅在顺序。但是,无论我在哪里添加 reg exp,我都无法获得预期的结果。

我的代码:

#!/usr/bin/perl
use strict;
use warnings;

my $k           = 23;
my $input       = 'Fasta.fasta';
my $output      = 'Fasta2.fasta';
my $match_count = 0;

#Open File
unless ( open( FASTA, "<", $input ) ) {
    die "Unable to open fasta file", $!;
}

#Unwraps the FASTA format file
$/ = ">";

#Separate header and sequence
#Remove spaces
unless ( open( OUTPUT, ">", $output ) ) {
    die "Unable to open file", $!;
}

<FASTA>;    # discard 'first' 'empty' record

my %seen;
while ( my $line = <FASTA> ) {
    chomp $line;
    my ( $header, @seq ) = split( /\n/, $line );
    my $sequence = join '', @seq;

    for ( length($sequence) >= $k ) {
        $sequence =~ m/([ACTG]{21}[G]{2})/g;

        for my $i ( 0 .. length($sequence) - $k ) {
            my $kmer = substr( $sequence, $i, $k );

            ##while ($kmer =~ m/([ACTG]{21}[G]{2})/g){
            $match_count = $match_count + 1;
            print OUTPUT ">crispr_$match_count", "\n", "$kmer", "\n" unless $seen{$kmer}++;
        }
    }
}

输入的 fasta 文件如下所示:

> >2L type=chromosome_arm; loc=2L:1..23011544; ID=2L;  dbxref=REFSEQ:NT_033779,GB:AE014134; MD5=bfdfb99d39fa5174dae1e2ecd8a231cd; length=23011544; release=r5.54; species=Dmel;
CGACAATGCACGACAGAGGAAGCAGAACAGATATTTAGATTGCCTCTCAT
TTTCTCTCCCATATTATAGGGAGAAATATGATCGCGTATGCGAGAGTAGT
GCCAACATATTGTGCTCTTTGATTTTTTGGCAACCCAAAATGGTGGCGGA
TGAACGAGATGATAATATATTCAAGTTGCCGCTAATCAGAAATAAATTCA
TTGCAACGTTAAATACAGCACAATATATGATCGCGTATGCGAGAGTAGTG
CCAACATATTGTGCTAATGAGTGCCTCTCGTTCTCTGTCTTATATTACCG
CAAACCCAAAAAGACAATACACGACAGAGAGAGAGAGCAGCGGAGATATT
TAGATTGCCTATTAAATATGATCGCGTATGCGAGAGTAGTGCCAACATAT
TGTGCTCTCTATATAATGACTGCCTCTCATTCTGTCTTATTTTACCGCAA
ACCCAAATCGACAATGCACGACAGAGGAAGCAGAACAGATATTTAGATTG
CCTCTCATTTTCTCTCCCATATTATAGGGAGAAATATGATCGCGTATGCG
AGAGTAGTGCCAACATATTGTGCTCTTTGATTTTTTGGCAACCCAAAATG
GTGGCGGATGAACGAGATGATAATATATTCAAGTTGCCGCTAATCAGAAA
TAAATTCATTGCAACGTTAAATACAGCACAATATATGATCGCGTATGCGA
GAGTAGTGCCAACATATTGTGCTAATGAGTGCCTCTCGTTCTCTGTCTTA
TATTACCGCAAACCCAAAAAGACAATACACGACAGAGAGAGAGAGCAGCG
GAGATATTTAGATTGCCTATTAAATATGATCGCGTATGCGAGAGTAGTGC
CAACATATTGTGCTCTCTATATAATGACTGCCTCTCATTCTGTCTTATTT
TACCGCAAACCCAAATCGACAATGCACGACAGAGGAAGCAGAACAGATAT

等等……

我希望得到的预期结果(打印出 GG 结尾的 23k-mer,仅在序列中出现 一次):

>crispr_1
GGGTGGAGCTCCCGAAATGCAGG
>crispr_2
TTAATAAATATTGACACAGCGGG
>crispr_3
ATCGTGGGGCGTTTTGTGAAAGG
>crispr_4
AGTTTTTCACATAATCAGACAGG
>crispr_5
GTGTTGGATGAGTGTCCTCTGGG
>crispr_6
ATAGGTTGGTTGTTTTAAAAGGG
>crispr_7
AAATTTTTGTTGCCACTGAATGG
>crispr_8
AAGTTTCGAACTACGATGGTTGG
>crispr_9
CATGCTTTGTGGAAATAAGTCGG
>crispr_10
CACAGTGGGTGTTTGCACCTCGG
.... and so on

我创建了一个fasta文件的当前代码如下:

>crispr_1
CGACAATGCACGACAGAGGAAGC
>crispr_2
GACAATGCACGACAGAGGAAGCA
>crispr_3
ACAATGCACGACAGAGGAAGCAG
>crispr_4
CAATGCACGACAGAGGAAGCAGA
>crispr_5
AATGCACGACAGAGGAAGCAGAA
>crispr_6
ATGCACGACAGAGGAAGCAGAAC
>crispr_7
TGCACGACAGAGGAAGCAGAACA
>crispr_8
GCACGACAGAGGAAGCAGAACAG
>crispr_9
CACGACAGAGGAAGCAGAACAGA
>crispr_10
ACGACAGAGGAAGCAGAACAGAT
.... and so on

如果我删除了

for (length($sequence) >=$k){
$sequence =~m/([ACTG]{21}[G]{2})/g;

并添加##while ($kmer =~ m/([ACTG]{21}[G]{2})/g){

 while ($kmer =~ m/([ACTG]{21}[G]{2})/g){

我正在获取 fasta 文件(结果编号不正确且无法区分重复序列和唯一序列):

>crispr_1
CATTTTCTCTCCCATATTATAGG
>crispr_2
ATTTTCTCTCCCATATTATAGGG
>crispr_3
TATTGTGCTCTTTGATTTTTTGG
>crispr_4
GATTTTTTGGCAACCCAAAATGG
>crispr_5
TTTTTGGCAACCCAAAATGGTGG
>crispr_6
TTGGCAACCCAAAATGGTGGCGG
>crispr_7
ACGACAGAGAGAGAGAGCAGCGG
>crispr_8
AAATCGACAATGCACGACAGAGG
>crispr_91
TATTGTGATCTTCGATTTTTTGG
>crispr_93
TTTTTGGCAACCCAAAATGGAGG
.... and so on

我试图在我的代码周围移动正则表达式,但它们都没有产生预期的结果。我不知道我在这里做错了什么。当计数达到 1000 时,我还没有在代码中添加退出程序。

提前致谢!

【问题讨论】:

  • 您能否向我们提供一些(必要时减少)输入以及您希望从该输入中获得的输出。当您看不到正在处理的数据时,很难提供帮助。
  • @DaveCross 我已经提供了输入文件;它只是一个包含基因序列的通用 fasta 文件。谢谢。
  • 我很困惑:预期的第一行(crispr_1 的行)是:CATTTTCTCTCCCATATTATAGG,但您显示的输入文件中没有连续的序列与之匹配。您是如何得出这个特定顺序的?
  • @HåkonHægland 那边不错。我没有尝试将序列直接与文件匹配;所以我没有注意到。具体的序列就像给我的提示,要知道我期望的前几个序列是什么。
  • 您的“预期结果”完全不清楚,另一方面,返回 CATTTTCTCTCCCATATTATAGGATTTTCTCTCCCATATTATAGGGTATTGTGCTCTTTGATTTTTTGG 的最后一次尝试似乎是正确的。

标签: perl


【解决方案1】:

我不确定我是否完全理解您的问题,但您需要以下内容吗?

<FASTA>; # discard 'first' 'empty' record

my %data;
while (my $line = <FASTA>){
    chomp $line;
    my($header, @seq) = split(/\n/, $line);
    my $sequence = join '', @seq;

    for my $i (0 .. length($sequence) - $k) {
        my $kmer = substr($sequence, $i, $k);

        $data{$kmer}++ if $kmer =~ /GG$/;
    }
}
my $i = 0;
for my $kmer (sort {$data{$b} <=> $data{$a}} keys %data) {
    printf "crispr_%d\n%s appears %d times\n", ++$i, $kmer, $data{$kmer};
    last if $i == 1000; 
}

我拥有的文件的一些输出是:

crispr_1
ggttttccggcacccgggcctgg appears 4 times
crispr_2
ccgagctgggcgagaagtagggg appears 4 times
crispr_3
gccgagctgggcgagaagtaggg appears 4 times
crispr_4
gcacccgggcctgggtggcaggg appears 4 times
crispr_5
agcagcgggatcgggttttccgg appears 4 times
crispr_6
gctgggcgagaagtaggggaggg appears 4 times
crispr_7
cccttctgcttcagtgtgaaagg appears 4 times
crispr_8
gtggcagggaagaatgtgccggg appears 4 times
crispr_9
gatcgggttttccggcacccggg appears 4 times
crispr_10
tgagggaaagtgctgctgctggg appears 4 times
crispr_11
agctgggcgagaagtaggggagg appears 4 times

. . . .

ggcacccgggcctgggtggcagg appears 4 times
crispr_50
gaatctctttactgcctggctgg appears 4 times
crispr_51
accacaacattgacagttggtgg appears 2 times
crispr_52
caacattgacagttggtggaggg appears 2 times
crispr_53
catgctcatcgtatctgtgttgg appears 2 times
crispr_54
gattaatgaagtggttattttgg appears 2 times
crispr_55
gaaaccacaacattgacagttgg appears 2 times
crispr_56
aacattgacagttggtggagggg appears 2 times
crispr_57
gacttgatcgattaatgaagtgg appears 2 times
crispr_58
acaacattgacagttggtggagg appears 2 times
crispr_59
gaaccatatattgttatcactgg appears 2 times
crispr_60
ccacagcgcccacttcaaggtgg appears 1 times
crispr_61
ctgctcctgggtgtgagcagagg appears 1 times
crispr_62
ccatatattatctgtggtttcgg appears 1 times

. . . .

更新 要获得您在评论中提到的结果(如下),请将输出代码替换为:

my $i = 1;

while (my ($kmer, $count) = each %data) {
    next unless $count == 1;
    print "crispr_$i\n$kmer\n";
    last if $i++ == 1000;
}

回答我自己的评论以获得第一 1000。

<FASTA>; # discard 'first' 'empty' record

my %seen;
my @kmers;
while (my $line = <FASTA>){
    chomp $line;
    my($header, @seq) = split(/\n/, $line);
    my $sequence = join '', @seq;

    for my $i (0 .. length($sequence) - $k) {
        my $kmer = substr($sequence, $i, $k);

        if ($kmer =~ /GG$/) {
            push @kmers, $kmer unless $seen{$kmer}++;
        }
    }
}

my $i = 1;
for my $kmer (@kmers) {
    next unless $seen{$kmer} == 1;
    print "crispr_$i\n$kmer\n";
    last if $i++ == 1000;
}

答案为了检查以 GG 结尾的最后 12 个字符的唯一性,下面的代码实现了这一点。

        if ($kmer =~ /(.{10}GG)$/) {
            my $substr = $1;
            push @kmers, $kmer unless $seen{$substr}++;
        }

my $i = 1;
for my $kmer (@kmers) {
    my $substr = substr $kmer, -12;
    next unless $seen{$substr} == 1;
    print "crispr_$i\n$kmer\n";
    last if $i++ == 1000;
}

【讨论】:

  • 我想要实现的是打印出前 1000 个 23kmer 序列,以 GG 结尾,只出现 1 次。谢谢!
  • @Sunny 我已经考虑过了,我的解决方案不会打印以 GG 结尾的 first kmers。它以随机顺序打印文件中出现一次的任何 kmers。如果您需要 first 1000,则需要使用不同的解决方案。
  • 我检查了更新代码的结果输出,头部 -100 和尾部 -100 确实与预期的输出结果匹配。而且它似乎也不是以随机顺序产生的。所以我认为这个解决方案没有问题。非常感谢您的检查!
  • 我使用了 diff 命令并确保预期输出与此代码产生的输出之间没有区别。谢谢!
  • 仅供参考,如果我只想打印出具有唯一 12 个核苷酸结尾的 23-kmers,我是否只需将正则表达式更改为 ($kmer =~ /.{10}GG $/) ?谢谢。
【解决方案2】:

其实就是这行代码

$sequence =~m/([ACTG]{21}[G]{2})/g;

此行仅用于正则匹配,如果您尝试打印此$sequence,它肯定会打印出原始结果。

请像这样添加代码段

if($sequence =~/([ACTG]{21}[G]{2}$)/g) 
{


}#please remember to match the end with $.

顺便说一句,看起来多次for循环解析这个数据不是很合理,解析速度不是最好的。

【讨论】:

  • Eric 这个方法不起作用,它会打印出空白的 fasta 文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多