【问题标题】:Find and print all overlapping k-mers查找并打印所有重叠的 k-mer
【发布时间】:2016-10-24 22:18:56
【问题描述】:

我正在尝试编写一个 perl 程序,它读取一个 fasta 文件并打印出一个文本文件,其中包含来自序列 (fasta) 文件的所有可用(重叠)长度为 15 k-mers 的文本文件。当我搜索不重叠的 k-mer 时,该程序运行得非常好,但是当我对其进行编码以找到重叠的 k-mer 时,它需要永远执行,并且 Cygwin 最终在 12 小时后终止了程序。 (我将 match_count 留在那里计算总数,请随意忽略该行)

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

my $k = 15;
my $input = 'fasta.fasta';
my $output = 'text.txt';
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", $!;
}

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

    while (length($sequence) >= $k){
        $sequence =~ m/(.{$k})/;
        print OUTPUT "$1\n";
        $sequence = substr($sequence, 1, length($sequence)-1);
    }
}

我要找的结果是:

A total of 20938309 k-mers printed in the text file when I use the wc -l command.

提前致谢!

【问题讨论】:

  • 您是在寻找总 kmer 数还是需要包含所有 kmer 的文件?
  • 生成大约 20M 的子字符串不应该花费 那么 长,即使该循环不是很有效。您的输入文件有多大(字节和记录)?您可以在最后一个 while 循环中使用以下内容,以避免大量字符串修改:for my $i (0..length($sequence)-$k) { print OUTPUT substr($sequence, $i, $k), "\n"; }
  • @ChrisCharley 我需要一个包含所有 kmers 的文件。我只需要使用 wc -l 命令来确保我总共有 20m kmers。
  • @mbethke 我不确定输入文件的大小。但我假设大小应该大于 20mb。我尝试了您的修改,但执行代码仍然需要很长时间。
  • 在我计算机上的一个 20,000 大小的 fasta 文件中,我生成了近 20,000 个重叠的 kmers。

标签: perl


【解决方案1】:

不知道为什么你没有得到你想要的结果。

我想我会按照您的问题描述发布我使用过的 2 个程序。

第一个仅计算我用于测试的文件中的 kmers (fasta_dat.txt)。它不会将它们打印出来,而只是检查有多少 kmer。

#!/usr/bin/perl
use strict;
use warnings;
use Bio::SeqIO;

my $in  = Bio::SeqIO->new( -file   => "fasta_dat.txt" ,
                           -format => 'fasta');

my $count_kmers;
my $k = 15;
while ( my $seq = $in->next_seq) {
    $count_kmers += $seq->length - $k + 1;
}

print $count_kmers;

__END__
C:\Old_Data\perlp>perl t9.pl
18657

您可以看到计数(在__END__ 令牌之后),18657。当我使用您的代码打印出来时,这个计数与 kmers 的计数一致。

#!/usr/bin/perl
use strict;
use warnings;
use 5.014;
use Devel::Size 'total_size';

my $k = 15;
my $input = 'fasta_dat.txt';
my $output = 'kmers.txt';
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 my $i (0 .. length($sequence) - $k) {
        my $kmer = substr($sequence, $i, $k);
        print OUTPUT $kmer, "\n" unless $seen{$kmer}++;
    }
}
print total_size(\%seen);

更新 我运行的测试显示,哈希大小的内存增加了大约 100 倍。在我的测试中,kmers 的数量约为 18500。这导致哈希大小为 1.8MB。

对于您的数据,kmers 为 22M,将导致哈希大小约为 2.2GB。不知道这会不会超出你的记忆容量。

【讨论】:

  • 我测试了你的代码,它也给了我的 23m k-mers,和我写的完全一样。我假设额外的 2m k-mers 来自“重复”k-mers(完全相同序列的 k-mers)。
  • 有没有办法让它只打印出不同的 k-mers?谢谢。
  • @Sunny,我编辑了我的代码以消除重复的 kmers,结果显示 kmers 减少了大约 10%(没有重复项)。
  • 我这里没有 Devel::Size 模块。有标准的 perl 方法吗?谢谢。
  • @Sunny 您的程序不需要该模块。我把它放在那里,这样我就可以测量%seen 哈希的大小。 (最后一行包含在上面的代码中)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 2020-05-08
  • 1970-01-01
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
相关资源
最近更新 更多