Perl:为DNA序列的log-odds得分创建和操作数组的散列

问题描述 投票:1回答:2

又是我。即使在查看文档之后,我也无法创建数组哈希。我希望HoA包含DNA序列中基序(较小序列)的对数 - 得分。我希望结构看起来像:

$HoA{$id}[$pos] = #score based on the position

其中$id是序列ID,而$pos是图案开始的序列内的位置。我输入一个包含DNA序列的.txt文件,格式如下:

>Sequence_1
TCAGAACCAGTTATAAATTTATCATTTCCTTCTCCACTCCT
>Sequence_2
CCCACGCAGCCGCCCTCCTCCCCGGTCACTGACTGGTCCTG
>Sequence_3
TCGACCCTCTGGAACCTATCAGGGACCACAGTCAGCCAGGCAAG

例如:序列1的位置2处的主题将是“AGA”。下面是我到目前为止的代码(简化了一点):

use strict;
use warnings;
use Data::Dumper; 

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 %HoA = ();
my %loscore = ();
my $id = '';
open (FILE, '<', $filename1) or die "Cannot open $filename1.",$!;
my $dna;
while (<FILE>)
{
    if($_ =~ /^>(.+)/)
    {
        $id = $1; #Stores 'Sequence 1' as the first $id, etc.
    }
    else
    {
        $HoA{$id} = [ split(//) ]; #Splits the contents to allow for position reference later
        $loscore{$id} .= 0; #Creates a hash with each id number to have a log-odds score (initial score 0)
        $maxscore{$id} .= -30; #Creates a hash with each id number to have a maxscore (initial score -30)
    }
}
close FILE;

my $width = 3;

my %logodds;  #I know there is a better way to do this - this is just for simplicity
$logodds{'A'}[0] = 0.1;
$logodds{'A'}[1] = 0.2;
$logodds{'A'}[2] = 0.3;
$logodds{'C'}[0] = 0.2;
$logodds{'C'}[1] = 0.5;
$logodds{'C'}[2] = 0.2;
$logodds{'G'}[0] = 0.3;
$logodds{'G'}[1] = 0.2;
$logodds{'G'}[2] = 0.4;
$logodds{'T'}[0] = 0.4;
$logodds{'T'}[1] = 0.1;
$logodds{'T'}[2] = 0.1;

print Dumper (\%logodds);
print "\n\n";
for my $base (qw( A C G T))
{
    print "logodds$base @{$logodds{$base}}\n";
}

my @arr;

foreach $id (keys %HoA)
{   
    for my $pos1 (0..length($HoA{$id})-$width-1)    #Look through all positions the motif can start at
    {
        for my $pos2 ($pos1..$pos1+($width-1)) #look through the positions at a specific motif starting point
        {
            for my $base (qw( A C G T))
            {
                if ($HoA{$id}[$pos2] eq $base)  #If the character matches a base:
                {
                    for my $pos3 (0..$width-1) #for the length of the motif:
                    {
                        $arr[$pos1] += $logodds{$base}[$pos3]; 
                        @{ $loscore{$id}} = @arr; #Throws error here
                    }
                }   
            }   
        }
    }
}
print Dumper(\%loscore);

我一直收到错误:不能使用字符串(“0”)作为ARRAY引用,而第75行使用“strict refs”。

我希望这个数据的对数赔率得分的一个例子是:

$HoA{'Sequence 1'}[2] = 0.1 + 0.2 + 0.3 = 0.6

因此,在序列1中从位置2开始的基序'AGA'的对数概率得分为0.6。感谢您的耐心和帮助!如果我需要澄清任何事情,请告诉我。

arrays perl hash
2个回答
0
投票

我在你的代码中看到了一些问题。考虑以下几点:

$HoA{$id} = [ split(//) ];  # Splits the contents to allow for position reference later
$loscore{$id} .= 0;  # Creates a hash with each id number to have a log-odds score (initial score 0)
$maxscore{$id} .= -30;  # Creates a hash with each id number to have a maxscore (initial score -30)

根据你的评论,你似乎想用0和-30初始化%loscore%maxscore的条目。但是,您使用的是=运算符(附加字符串),而不是使用旧的.=符号。我不认为这是你想要的,所以考虑将.=改为=

(或者你的意思是使用//=代替。这样,如果%loscore%maxscore已经有一个$id条目,它将不会被覆盖。但只有你可以肯定地说你是否打算使用//=算子。)

现在让我们来看看$loscore{$id} = 0。这告诉我们%loscore是一个哈希(或“关联数组”),对于每个条目,它为密钥获取$ id,并将数字作为值。

但是,您的代码中还有以下内容:

@{ $loscore{$id} } = @arr;

$loscore{$id}${ ... }包裹的事实告诉我们%loscore中的值是数组引用。但我们已经在上面建立了它的数值!

并且因为您将数字视为数组引用,Perl将其视为错误。

你可能打算写的是:

@{ $HoA{$id} } = @arr;

由于%HoA哈希值包含数组引用,因此您需要将其作为数组去引用。


0
投票

我认为这解决了问题:替换

$loscore{$id} .= 0; $maxscore{$id} .= -30;

foreach $id (keys %HoA)
    {
        for my $len (0..(length($HoA{$id})-$width-1))
        {
            push @{ $loscore{$id} }, 0;
            push @{ $maxscore{$id} }, -30;
        }
    }

如果您有任何补充,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.