Perl期望最大化DNA序列的对数分数

时间:2019-03-20 14:48:23

标签: perl hash hashmap dna-sequence expectation-maximization

此代码的总体目标是在每个DNA序列中找到基序(较小序列),该基序将基于对数奇数评分矩阵报告最大对数奇数分数。我正在搜索的.txt文件如下所示:

>Sequence 1
TCGACGATCAGACAG
>Sequence 2
TGGGACTTGCACG

....依此类推。

目前,我正在代码的最大化步骤上,我正在努力计算DNA序列中基序的对数比分。我有创建对数得分矩阵的代码-参见以下内容:

#!/usr/bin/perl -w
#Above line used in Unix and Linux
#Grome Programming Assignment 2
#E-M
use strict;
use warnings;

# usage: script.pl {motif_width} {dnafile}
#USER SPECIFICATIONS
print "Please enter the filename of the fasta sequence data: ";
my $filename1 = <STDIN>;

#Remove newline from file
chomp $filename1;

#Open the file and store each dna seq in hash
my %id2seq = ();
my $id = '';
open (FILE, '<', $filename1) or die "Cannot open $filename1.",$!;
my $dna;
while (<FILE>)
{
    if($_ =~ /^>(.+)/)
    {
        $id = $1;
    }
    else
    {
        $id2seq{$id} .= $_;
    }
}
close FILE;
foreach $id (keys %id2seq)
{
    print "$id2seq{$id}\n\n";
}

#User specifies motif width
print "Please enter the motif width:\n";
my $width = <STDIN>;

#Remove newline from file
chomp $width;

#Default width is 3 (arbitrary number chosen)
if ($width eq '')
{
    $width = 3;
}
elsif ($width <=0)
{
    print "Please enter a number greater than zero:\n";
    $width = <STDIN>;
    chomp $width;
}

#User specifies number of initial random
#starting alignments
print "Please enter the number of initial random
starting alignments:\n";
my $start = <STDIN>;

#Remove newline from file
chomp $start;

#Default start is 50
if ($start eq '')
{
    $start = 50;
}
elsif ($start <=0)
{
    print "Please enter a number greater than zero:\n";
    $start = <STDIN>;
    chomp $start;
}

#User specifies number of iterations to
#perform expectation-maximization
print "Please enter the number of iterations for 
expectation-maximization:\n";
my $iteration = <STDIN>;

#Remove newline from file
chomp $iteration;

#Default iteration = 500
if($iteration eq '') 
{
    $iteration = 500;
}
elsif ($iteration <=0)
{
    print "Please enter a number greater than zero:\n";
    $iteration = <STDIN>;
    chomp $iteration;
}

#EXPECTATION
#Initialize counts for motif positions
#Incorporate pseudocounts initially
my %mot = map { $_ => [ (1) x $width ] } qw( A C G T );

# Initialize background counts
my %bg = map { $_ => 0 } qw( A C G T );

#Fill background and motif counts
foreach $id (keys %id2seq)
{
    #Generate random start site in the sequence
    #for motif to start from
    my $ms = int(rand(length($id2seq{$id})-$width));

    # Within a motif, count the bases at the positions
    for my $pos (0..length($id2seq{$id})-1)
    {
        my $base = substr($id2seq{$id}, $pos, 1);
        if ($pos >= $ms && $pos < $ms + $width) 
        {
            ++$mot{$base}[$pos-$ms]
                if exists($mot{$base});
        } 
        else 
        {
            ++$bg{$base}
            if exists($bg{$base});
        }
    }
}
#Print the background and motif counts
for my $base (qw( A C G T )) 
{
   print "$base @{$mot{$base}}\n";
}

print "\n";

for my $base (qw( A C G T )) 
{
   print "bg$base = $bg{$base}\n";
}

#Create frequency table of the motifs
#Get sum of the background
my $bgsum = 0;
for my $base (qw( A C G T))
{
    $bgsum = $bgsum + $bg{$base};
}
print "\n$bgsum\n\n";

#Create background frequency table
my %bgfreq = map { $_ => 0 } qw( A C G T );
for my $base (qw( A C G T))
{
    $bgfreq{$base} = $bg{$base} / $bgsum;
    print "bgfreq$base = $bgfreq{$base}\n";
}

#Get sum of each motif position
my @motsum = ( (0) x $width );
for my $base (qw( A C G T))
{
    for my $arrpos (0.. ($width-1))
    {
        $motsum[$arrpos] = $motsum[$arrpos] + @{$mot{$base}}[$arrpos];
    }
}

#Create motif frequency table
my %motfreq = map { $_ => [ (0) x $width ]} qw( A C G T );
for my $base (qw( A C G T))
{
    for my $arrpos (0.. ($width-1))
    {
        $motfreq{$base}[$arrpos] = $mot{$base}[$arrpos] / $motsum[$arrpos];
    }
    print "motfreq$base @{$motfreq{$base}}\n";
}

#Create odds table of motifs
my %odds = map { $_ => [ (0) x ($width) ]} qw( A C G T );

for my $base (qw( A C G T))
{
    for my $arrpos (0.. ($width-1))
    {
        $odds{$base}[$arrpos] = $motfreq{$base}[$arrpos] / $bgfreq{$base};
    }
    print "odds$base @{$odds{$base}}\n";
}

#Create log-odds table of motifs
my %logodds = map { $_ => [ (0) x ($width) ]} qw( A C G T );
for my $base (qw( A C G T))
{
    for my $arrpos (0.. ($width-1))
    {
        $logodds{$base}[$arrpos] = log2($odds{$base}[$arrpos]);
    }
    print "logodds$base @{$logodds{$base}}\n";
}
#####################################################
sub log2
{
    my $n = shift;
    return log($n)/log(2);
}

现在,我需要计算每个DNA序列中基序的对数比分。然后,我将遍历序列中所有可能的位置,并找到每个序列的最高分。未来的工作需要我回忆起具有最高分的主题,但是我还没有尝试过(只是想给这些最高分提供范围)。

策略:我将创建一个对数分数和最高分数的哈希值,以保留迭代时每个序列的最高分数。为了计算对数得分,我将看到对数得分矩阵中的哪个元素与主题中的元素匹配。

#MAXIMIZATION
#Determine location for each sequence that maximally
#aligns to the motif pattern
#Calculate logodds for the motif

#Create hash of logodds scores and hash of maxscores
#so each id has a logodds score and max score
 my %loscore = map { $_ => [ (0) x (length($id2seq{$id})-$width) ]} qw( $id ); #Not sure if $id is correct, but I want a loscore for each $id
 my %maxscore = map { $_ => [ (0) x (length($id2seq{$id})-$width) ]} qw( $id ); #Not sure if $id is correct, but I want a maxscore for each $id
 foreach $id (keys %loscore, %maxscore, %id2seq)
 {
 my $len = length($id2seq{$id});
 for my $base (qw( A C G T ))
 {
     for my $pos (0..$len-1)
     {
         if ($id2seq{$id}[$pos] = $mot{$base})
         {
             for my $motpos (0..$width-1)
             {
                 $loscore{$id} = $loscore{$id} + $logodds{$base}[$motpos];
                 if ($loscore{$id} > $maxscore{$id})
                 {
                     $maxscore{$id} = $loscore{$id};
                 }
             }
         }
     }
 }
 print "$id2seq{$id} logodds score: $maxscore{$id}\n";
 }

#####################################################
sub log2
{
    my $n = shift;
    return log($n)/log(2);
}

当我从运行中取消注释最大化步骤时,没有显示任何内容。我没有收到任何错误,但是没有新的打印。我知道可以简化我的期望步骤(在工作完成后,我会清理所有内容),但是我首先关注此最大化步骤。我知道最大化代码中存在很多缺陷,尤其是在尝试创建对数得分和最大得分哈希值时。任何输入都可以帮助您!预先感谢您的耐心和建议。让我知道您是否需要任何澄清。

1 个答案:

答案 0 :(得分:0)

foreach $id (keys %loscore, %maxscore, %id2seq)不会遍历所有三个哈希。您可能是说foreach $id (keys %loscore, keys %maxscore, keys %id2seq)

if ($id2seq{$id}[$pos] = $mot{$base})将该值分配给$id2seq{$id}[$pos]。要检查是否相等,您需要if ($id2seq{$id}[$pos] eq $mot{$base})。但这也可能是错误的,因为$id2seq{$id}应该是字符串,而$mot{$base}是数组。

尚不清楚代码应如何工作,很难在如此长的代码示例中发现错误。