Perl序列比对分数计算错误

时间:2016-04-27 01:01:11

标签: perl

您好我正在为我的Bioinformatics类编写这个程序,在那里我从文本文件中获取序列,然后改变序列。之后,我想通过比较碱基对进行比较以得分。我编写了所有代码,但我不明白为什么我一直得到0的分数。我假设我的代码部分处理这个是错误的,因为我初始化了$sum = 0;我想知道是否我可以帮助解决这个问题,以便我的代码正常工作。这是我正在使用的序列。

AGGGCACCTCTCAGTTCTCATTCTAACACCACATAATTTTTATTTGTATTATTCAGATTTTTCATGAACTTTTCCACAT
AGAATGAAGTTGACATTGTTATTTCTCAGGGTCTCGGTTCACCAGTATTTGACAAACTTGAAGCTGAACTAGCTAAAGC

use strict;

my $sum = 0;
my @seq;
my $seqString;
my $seqShuf;
my $line;

unless(open FILE, "test_seq.txt")
{
    print "Cannot open file!";
    exit; 
}

while (chomp($line = <FILE>))
{
    next if (/^>/);
    @seq = <FILE>;
}

$seqString = join("",@seq);
chomp($seqShuf = shuffle_string($seqString));
$seqShuf =~ s/\s+//g;
#print "Original sequence is:\n";
#print "$seqString\n";
#print "Mutated Sequence is:\n";
#print "$seqShuf\n";

my @shufSeq = split("", $seqShuf, length($seqShuf));

my %test = (
            AA => 0,
            AG => -1,
            AT => -2,
            AC => -2,
            GA => -1,
            GG => 0,
            GT => -2,
            GC => -2,
            TA => -2,
            TG => -2,
            TT => 0,
            TC => -1,
            CA => -2,
            CG => -2,
            CT => -1,
            CC => 0
            );

my @base_pairs = make_base_pairs(@seq, @shufSeq);
foreach my $bp (@base_pairs)
{
    $sum += $test{$bp};
}

print "@base_pairs\n";
print "The score is ", $sum, "\n";

# Shuffles original sequence
sub shuffle_string
{
    my ($string) = @_;
    my $length = length $string;
    for (my $i = 0; $i < $length-1; $i++)
    {
        my $j = random_int ($i, $length-1);
        my $tmp = substr($string, $i, 1);
        substr($string, $i, 1) = substr($string, $j, 1);
        substr($string, $j, 1) = $tmp;
    }
    return $string;
}

# created random int between two parameters
sub random_int
{
    (my $par1, my $par2) = @_;
    my $num = (1+$par1) +  int(rand($par2 - $par1));
}

# aligns base pairs based on index location
sub make_base_pairs
{
    (my @orig, my @shuf) = @_;
    my $idx = 0;
    my @bps;
    foreach my $base (@orig)
    {
        push @bps, $base , $shuf[$idx];
        $idx++;
    }
    return @bps;
}

1 个答案:

答案 0 :(得分:2)

不幸的是,简单的perl错误的数量,更不用说一些算法错误,无法列出。只需研究并比较下面的代码。

这是清理过的代码。它可能仍然有一些错误,但至少它打印非零[请原谅无偿的风格清理]:

#!/usr/bin/perl

use strict;

my $sum = 0;
my @seq;
my $seqString;
my $seqShuf;
my $line;

open(FILE, "test_seq.txt") or
    die("unable to open file -- $!\n");

while ($line = <FILE>) {
    chomp($line);
    push(@seq,split(//,$line));
}

close(FILE);

my @shufSeq = shuffle_string(@seq);
#print "Original sequence is:\n";
#print "$seqString\n";
#print "Mutated Sequence is:\n";
#print "$seqShuf\n";

my %test = (
AA => 0,
    AG => -1,
    AT => -2,
    AC => -2,
    GA => -1,
    GG => 0,
    GT => -2,
    GC => -2,
    TA => -2,
    TG => -2,
    TT => 0,
    TC => -1,
    CA => -2,
    CG => -2,
    CT => -1,
    CC => 0
);

my @base_pairs = make_base_pairs(\@seq, \@shufSeq);
foreach my $bp (@base_pairs)
{
    ###printf("DEBUG bp='%s'\n",$bp);
    $sum += $test{$bp};
}

print("base_pairs: ",join(" ",@base_pairs),"\n");
print "The score is ", $sum, "\n";

# Shuffles original sequence
sub shuffle_string
{
    my (@string) = @_;
    my $length = @string;

    for (my $i = 0; $i < $length-1; $i++) {
        my $j = random_int ($i, $length-1);

        my $tmp = $string[$i];
        $string[$i] = $string[$j];
        $string[$j] = $tmp;
    }

    @string;
}

# created random int between two parameters
sub random_int
{
    my($par1,$par2) = @_;
    my $num = (1+$par1) +  int(rand($par2 - $par1));
    $num;
}

# aligns base pairs based on index location
sub make_base_pairs
{
    my($orig,$shuf) = @_;
    my $idx = 0;
    my @bps;

    foreach my $base (@$orig) {
        push(@bps,$base . $shuf->[$idx]);
        $idx++;
    }

    return @bps;
}

<强>更新

  

非常感谢你们。这是我的第一个编程课程,它在整个学期里一直在杀我。我将继续查看代码和编辑,以摆脱一些额外的错误。

以下是一些其他注释,可能有助于理解我所做的更改的机制。

现在该程序基本上正常工作,您可以检查您的随机化和随机码是否在算法上足够(即足够随机和随机播放)。

例如,我认为shuffle的最后一个元素总是是原始元素的最后一个元素,因为i循环是< $length-1而不是{{1 }}。我试图通过再循环一次来解决这个问题,但是在阵列上遇到了一个越​​界。

文件I / O:

读取文件数据和拆分单个字符的代码非常惯用。

在您的代码中,< $length只会为您提供一个包含最后一行文本的数组[因为第一行是由@seq = <FILE>提取的。)

循环$line = <FILE>值不是循环的最佳标准。它[也许,有点]有效,但我从来没有这样做过。

chomp无效,因为它会在next if上运行而不是$_ [为什么要这样做?]。

所以,最后,$line将有一个元素是最后一行[没有一个换行符],而不是每个文件的所有字符分成一个字符@seq元素。

由于@seq仍然有换行符,这可能是您之后有第二个@seq的原因

<强>随机

chomp的主要更改是通过索引到数组而不是使用shuffle_seq在标量内交换来操作。在您的代码中,您在substr上执行了join只是为了致电@seq,然后对结果做了shuffle_seq。通过让split处理数组,事情就更简单了。

<强>语法:

我之前从未见过shuffle_seq语法[它可能有效 - 我没有检查]。我只使用(my $par1, my $par2) = @_;

<强> make_base_pair:

在您的my($par1,$par2) = @_; make_base_pairs@seq所有元素中,最终会出现在make_base_pair的@shufSeq中其@orig将为空。

我将序列更改为@shuf [在函数内部进行了相应的更改]。这会将标量引用传递给每个数组,而不是传递数组值。

请注意,对于引用,在函数内部,访问的语法更改为make_base_pair(\@seq,\@shufSeq)@$orig

通过这些更改,算法结果更可能是正确的。

如果没有它们,$shuf->[$idx]仍然可以运行,但它有一个最终的错误就是节目制作者:

您的make_base_pairs会在每个循环中添加两个元素:push [记住X,""为空]。因此,最终结果是一个单个char元素[或empty]和 not 数组元素的数组,它们是你想要的两个字符。

我对推送的更改:@shuf使用perl的字符串连接运算符:push(@bps,$base . $shuf->[$idx]);来连接.base [这是一个单一的每个字符]产生两个字符输出元素。

主要的错误是shuf返回的数组中有 no 两个字符元素,因此对它们求和的循环可能从不产生非零