2016-04-27 2 views
1

Здравствуйте, я пишу эту программу для своего класса Bioinformatics, где получаю последовательность из текстового файла и затем мутирую последовательность. После этого я должен сделать сравнение, чтобы сделать оценку, сравнив пары оснований. У меня есть весь написанный код, но я не понимаю, почему я продолжаю получать оценку 0. Я предполагаю, что часть моего кода, которая имеет дело с этим, неверна, потому что я инициализировал $sum = 0;. Мне было интересно, могу ли я получить некоторые помогите устранить эту проблему, чтобы мой код работал правильно. Вот последовательность, которую я использую.Ошибка вычисления оценки выравнивания последовательности Perl

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; 
} 
+0

Что вы сделали для отладки вашей программы? – Mort

+0

'использование предупреждений;' еще важнее, чем строгий. – ysth

ответ

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

UPDATE:

Это помогает тонну спасибо так много. Это мой первый класс программирования, и он убил меня весь семестр. Я буду продолжать смотреть код и редактировать, чтобы избавиться от некоторых дополнительных ошибок.

Ниже приведены некоторые дополнительные примечания, которые могут помочь в понимании механики изменений, которые я сделал.

Теперь, когда программа в основном работает, вы можете проверить, является ли ваша рандомизация и случайный код алгоритмически адекватной (то есть достаточно случайной и работает в случайном порядке).

Например, я думаю, что последний элемент перетасовки будет всегда быть последним элементом оригинала, потому что петля i является < $length-1 вместо < $length. Я попытался исправить это, зациклив еще один, но получив вне границ в массиве.


File I/O:

Код для чтения в файл данных и разделение на отдельных символов довольно идиоматическое.

В вашем коде @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) = @_; синтаксис перед тем [это может быть действительно - я не проверял]. Я просто использовать my($par1,$par2) = @_;


make_base_pair:

В ваших make_base_pairs, всех элементов как@seq и @shufSeq бы в конечном итоге в make_base_pair-х @orig и его @shuf будет пустым.

Я изменил последовательность на make_base_pair(\@seq,\@shufSeq) [с соответствующим изменением внутри функции]. Это передает скаляр ссылку на каждый массив, а не на передачу значений массива.

Обратите внимание, что при ссылках внутри функции, синтаксис для доступа изменения @$orig и $shuf->[$idx]

С этими изменениями, алгоритмические результаты, скорее всего, будет правильным.

Без них make_base_pairs бы еще работать, но это был один последний баг, который был шоу стоппер:

Ваш push бы добавить два элементов на каждом цикле: X,"" [помните, что @shuf было пусто]. Таким образом, конечным результатом был массив одиночных элементов char [или empty] и не элементов массива, которые были два символов по вашему желанию.

Мои изменения в толчке: push(@bps,$base . $shuf->[$idx]); использует строку конкатенации оператор в Perl: . конкатенировать base и shuf [которые один символ каждый] для получения двух выходных символов элементов.

Основная ошибка в том, что make_base_pairs возвращается массив, который не имел ни одного два элемента символов, поэтому цикл суммировать их могли никогда не производить не нуль.

+0

Это очень помогает вам. Это мой первый класс программирования, и он убил меня весь семестр. Я буду продолжать смотреть код и редактировать, чтобы избавиться от некоторых дополнительных ошибок. –

Смежные вопросы