Perl: создание и манипулирование хешем массивов для оценки лог-шансов последовательностей ДНК - PullRequest
1 голос
/ 27 марта 2019

это снова я.У меня проблемы с созданием хэша массивов даже после просмотра документации.Я хочу, чтобы HoA содержал логарифмическую оценку мотива (меньшая последовательность) в последовательности ДНК.Я хочу, чтобы структура выглядела следующим образом:

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

Где $id - это идентификатор последовательности, а $pos - это позиция в последовательности, с которой начинается мотив.Я ввожу .txt файл, содержащий последовательности ДНК, отформатированный следующим образом:

>Sequence_1
TCAGAACCAGTTATAAATTTATCATTTCCTTCTCCACTCCT
>Sequence_2
CCCACGCAGCCGCCCTCCTCCCCGGTCACTGACTGGTCCTG
>Sequence_3
TCGACCCTCTGGAACCTATCAGGGACCACAGTCAGCCAGGCAAG

Например: мотив в позиции 2 для последовательности 1 будет «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.

Пример оценки log-odds с этими данными, которые мне нужны:

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

Итак, оценка log-odds мотива 'AGA'который начинается с позиции 2 в последовательности 1 0,6.Я ценю все ваше терпение и помощь!Дайте мне знать, если мне нужно что-то уточнить.

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

Я думаю, что это решает проблему: замените

$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;
        }
    }

Дайте мне знать, если у вас есть что добавить.

0 голосов
/ 27 марта 2019

Я вижу несколько проблем в вашем коде. Рассмотрим эти строки:

$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)

Согласно вашим комментариям, вы хотите инициализировать записи %loscore и %maxscore с 0 и -30. Однако вместо использования старого доброго знака = вы используете оператор .= (который добавляет строки). Я не думаю, что это то, что вы хотите, поэтому подумайте об изменении .= на =.

(Или, может быть, вы намеревались использовать //= вместо этого. Таким образом, если %loscore и %maxscore уже имеют запись $id, она не будет перезаписана. Но только вы можете сказать наверняка, если вы предназначен для использования оператора //=.)

Итак, теперь давайте посмотрим на $loscore{$id} = 0. Это говорит нам о том, что %loscore - это хеш (или «связанный массив»), который для каждой записи принимает $ id для ключа и число в качестве значения.

Тем не менее, ниже в вашем коде у вас есть это:

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

Тот факт, что $loscore{$id} заключен в ${ ... }, говорит нам, что значения в %loscore являются ссылками на массив. Но мы уже установили выше, что его значения являются числами!

И поскольку вы рассматриваете число как ссылку на массив, Perl видит в этом ошибку.

То, что вы возможно хотели написать вместо этого, было:

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

Поскольку значения в хэше %HoA содержат ссылки на массивы, имеет смысл отменить ссылку на как на массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...