цикл for выполняется только один раз в PERL, аргумент "" не является числовым в substr - PullRequest
0 голосов
/ 16 марта 2019

У меня есть цикл for с вложенными операторами if, else и elsif внутри. Цикл for работает правильно, но по какой-то причине он запускается только один раз. Я хочу посчитать A, C, G и T в последовательности, но я хочу посчитать их в двух группах - группе мотивов и фоновой группе. Количество групп мотивов должно быть определенным для позиции, в то время как количество фонов - нет.

Вот что содержится в моем файле .dna (отлично подойдет .txt): AGGCT

Вот что у меня есть:

use strict;
use warnings;

#Upload sequence
print "Please enter the filename of the first sequence data: ";
my $filename1 = <STDIN>;

#Remove newline from file
chomp $filename1;

#Open the file and ignore comment lines
open (FILE, '<', $filename1) or die "Cannot open $filename1.",$!;
my $dna;
for (<FILE>)
{
    next if /^#/;
    next if /^>/;
    $dna .= $_;
}
close FILE;

#Remove white spaces 
$dna =~ s/[\s\d]//g;
$dna =~ /./g;

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

#Remove newline from file
chomp $width;
#Omitting code for non-negative widths to keep this shorter

#Initialize counts and arrays for motif positions
my @motA;
my @motC;
my @motG;
my @motT;

#Define length of motif arrays per width
for(0..($width-1))
{
    $motA[$_] = 0;
    $motC[$_] = 0;
    $motG[$_] = 0;
    $motT[$_] = 0;
}

#Initialize background counts
my $bgA = 0;
my $bgC = 0;
my $bgG = 0;
my $bgT = 0;

#Generate random start site in the sequence
#for motif to start from
my $ms = int(rand(((length($dna)+1)-$width)));

#Within a motif, count the bases at the positions
for (my $pos = 0..(length($dna)-1))
{
    my $base = substr($dna, $pos, 1);

    if ($pos = $ms..($ms + $width))
    {
        #Add to motif counts    
        if($base eq 'A')
        {
            $motA[$pos-$ms] = $motA[$pos-$ms] + 1;
        }
        elsif($base eq 'C')
        {
            $motC[$pos-$ms] = $motC[$pos-$ms] + 1;
        }
        elsif($base eq 'G')
        {
            $motG[$pos-$ms] = $motG[$pos-$ms] + 1;
        }
        elsif($base eq 'T')
        {
            $motT[$pos-$ms] = $motT[$pos-$ms] + 1;
        }
    }
    else
    {
        #Create background counts
        if ($base eq 'A')
        {
            $bgA = $bgA + 1;
        }
        elsif ($base eq 'C')
        {
            $bgC = $bgC + 1;
        }
        elsif ($base eq 'G')
        {
            $bgG = $bgG + 1;
        }
        elsif ($base eq 'T')
        {
            $bgT = $bgT + 1;
        }
    }
}
print "A @motA\nC @motC\nG @motG\nT @motT\n\n";

print "bgA = $bgA\n
bgC = $bgC\n
bgG = $bgG\n
bgT = $bgT";

Вывод выглядит так:

Please enter the filename of the first sequence data: sample.dna
Please enter the motif width:
3
Argument "" isn't numeric in substr at line 62, <STDIN> line2.
A 0 1 0
C 0 0 0
G 0 0 0
T 0 0 0

bgA = 0
bgC = 0
bgG = 0
bgT = 0

Я знаю, что это наиболее вероятно, потому что мои $ dna или $ pos в строке с substr содержат "" (пустая строка?), Но я не уверен, как решить эту проблему. Я думал, что инициализация $ pos позаботилась об этом, но поэтому я хочу попросить мастеров посмотреть, что делать. Я думаю, что это решит проблему цикла. Как всегда, любая помощь полезна. Я ценю это заранее!

1 Ответ

3 голосов
/ 16 марта 2019

Это:

for (my $pos = 0..length($dna))
{
    my $base = substr($dna, $pos, 1);

, вероятно, вместо этого будет 0..length($dna)-1?

Когда $ pos - длина, подстрока будет пустой строкой.

И это неправильный синтаксис цикла for для итерации по диапазону.Это должно быть

for my $pos (0..length($dna)-1)

Это:

if ($pos = $ms..($ms + $width))

, если я правильно понимаю, должно быть

if ($pos >= $ms && $pos < $ms + $width)

То, что у вас есть, присваивает $ pos результатоперация триггера, которая не будет ничего полезного.

Это выглядит так:

my $ms = int(rand(((length($dna)+1)-$width)));

должно быть

my $ms = int(rand(((length($dna))-$width)));

Например, если длина $ dna равна10 и width = 3, вы хотите, чтобы возможные начальные смещения были от 0 до 7, а не от 0 до 8.

И похоже, что ваш подсчет в мотиве должен использовать позицию внутри мотива, а не $ pos;это:

            $motA[$pos] = $motA[$pos] + 1;

должно быть

            $motA[$pos-$ms] = $motA[$pos-$ms] + 1;
...