В среде Linux Вы могли читать из/proc файловой системы.
~$ cat /proc/meminfo
MemTotal: 2076816 kB
MemFree: 130284 kB
Buffers: 192664 kB
Cached: 1482760 kB
SwapCached: 0 kB
Active: 206584 kB
Inactive: 1528608 kB
HighTotal: 1179484 kB
HighFree: 120768 kB
LowTotal: 897332 kB
LowFree: 9516 kB
SwapTotal: 2650684 kB
SwapFree: 2650632 kB
Dirty: 64 kB
Writeback: 12 kB
AnonPages: 59668 kB
Mapped: 22008 kB
Slab: 200744 kB
PageTables: 1220 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 3689092 kB
Committed_AS: 263892 kB
VmallocTotal: 114680 kB
VmallocUsed: 3604 kB
VmallocChunk: 110752 kB
У меня есть и другие комментарии, но вот первое наблюдение:
my $num_of_rows = length($self->{seq1}) + 1;
my $num_of_columns = length($self->{seq2}) + 1;
Итак $ self -> {seq1}
и $ self -> {seq2}
- это строки, и вы продолжаете обращаться к отдельным элементам с помощью substr
. Я бы предпочел хранить их как массивы символов:
$self->{seq1} = [ split //, $seq1 ];
Вот как я бы написал это:
sub create_matrix {
my $self = shift;
my $matrix = $self->{score_matrix};
my $path_matrix = $self->{path_matrix};
my $rows = @{ $self->{seq1} };
my $cols = @{ $self->{seq2} };
for my $row (0 .. $rows) {
$matrix->[$row]->[0] = $row * $self->{gap_cost};
$path_matrix->[$row]->[0] = 1;
}
my $gap_cost = $self->{gap_cost};
$matrix->[0] = [ map { $_ * $gap_cost } 0 .. $cols ];
$path_matrix->[0] = [ (-1) x ($cols + 1) ];
$path_matrix->[0]->[0] = 2;
for my $row (1 .. $rows) {
for my $col (1 .. $cols) {
my $gap1 = $matrix->[$row - 1]->[$col] + $gap_cost;
my $gap2 = $matrix->[$row]->[$col - 1] + $gap_cost;
my $match_mismatch =
$matrix->[$row - 1]->[$col - 1] +
$self->get_match_score(
$self->{seq1}->[$row - 1],
$self->{seq2}->[$col - 1]
);
my $max = $matrix->[$row]->[$col] =
max($gap1, $gap2, $match_mismatch);
$path_matrix->[$row]->[$col] = $max == $gap1
? -1
: $max == $gap2
? 1
: 0;
}
}
}
Одно простое изменение - использовать для
такие циклы:
for my $i (0 .. $num_of_rows){
# Do stuff.
}
Для получения дополнительной информации см. документацию Perl по циклам foreach и оператору диапазона .
Вместо того, чтобы разыменовать ваши двумерные массивы следующим образом:
$$path_matrix[0][0] = 2;
сделайте это:
$path_matrix->[0][0] = 2;
Кроме того, вы делаете много операторов if / then / else для сопоставления с конкретными подпоследовательностями: это могло бы быть лучше записывается как с учетом
операторов (эквивалент perl5.10 переключателя C
). Прочтите об этом на perldoc perlsyn :
given ($matrix->[$row][$column])
{
when ($seq1_gap) { $path_matrix->[$row][$column] = -1; }
when ($match_mismatch) { $path_matrix->[$row][$column] = 0; }
when ($seq2_gap) { $path_matrix->[$row][$column] = 1; }
}
Большая часть вашего кода манипулирует 2D-массивами. Я думаю, что самым большим улучшением будет переход на использование PDL , если вы хотите много чего делать с массивами, особенно если эффективность является проблемой. Это модуль Perl, обеспечивающий отличную поддержку массивов. Базовые процедуры реализованы на C для повышения эффективности, так что это тоже быстро.
sa Perl-модуль, обеспечивающий отличную поддержку массивов. Базовые процедуры реализованы на C для повышения эффективности, так что это тоже быстро. sa Perl-модуль, обеспечивающий отличную поддержку массивов. Базовые процедуры реализованы на C для повышения эффективности, так что это тоже быстро.Я всегда советую смотреть на CPAN , чтобы найти предыдущие решения или примеры того, как что-то делать на Perl. Вы смотрели на Algorithm :: NeedlemanWunsch ?
Документация к этому модулю включает пример сопоставления последовательностей ДНК. Вот пример использования матрицы сходства из википедии .
#!/usr/bin/perl -w
use strict;
use warnings;
use Inline::Files; #multiple virtual files inside code
use Algorithm::NeedlemanWunsch; # refer CPAN - good style guide
# Read DNA sequences
my @a = read_DNA_seq("DNA_SEQ_A");
my @b = read_DNA_seq("DNA_SEQ_B");
# Read Similarity Matrix (held as a Hash of Hashes)
my %SM = read_Sim_Matrix();
# Define scoring based on "Similarity Matrix" %SM
sub score_sub {
if ( !@_ ) {
return -3; # gap penalty same as wikipedia)
}
return $SM{ $_[0] }{ $_[1] }; # Similarity Value matrix
}
my $matcher = Algorithm::NeedlemanWunsch->new( \&score_sub, -3 );
my $score = $matcher->align( \@a, \@b, { align => \&check_align, } );
print "\nThe maximum score is $score\n";
sub check_align {
my ( $i, $j ) = @_; # @a[i], @b[j]
print "seqA pos: $i, seqB pos: $j\t base \'$a[$i]\'\n";
}
sub read_DNA_seq {
my $source = shift;
my @data;
while (<$source>) {
push @data, /[ACGT-]{1}/g;
}
return @data;
}
sub read_Sim_Matrix {
#Read DNA similarity matrix (scores per Wikipedia)
my ( @AoA, %HoH );
while (<SIMILARITY_MATRIX>) {
push @AoA, [/(\S+)+/g];
}
for ( my $row = 1 ; $row < 5 ; $row++ ) {
for ( my $col = 1 ; $col < 5 ; $col++ ) {
$HoH{ $AoA[0][$col] }{ $AoA[$row][0] } = $AoA[$row][$col];
}
}
return %HoH;
}
__DNA_SEQ_A__
A T G T A G T G T A T A G T
A C A T G C A
__DNA_SEQ_B__
A T G T A G T A C A T G C A
__SIMILARITY_MATRIX__
- A G C T
A 10 -1 -3 -4
G -1 7 -5 -3
C -3 -5 9 0
T -4 -3 0 8
И вот некоторые примеры вывода:
seqA pos: 7, seqB pos: 2 base 'G'
seqA pos: 6, seqB pos: 1 base 'T'
seqA pos: 4, seqB pos: 0 base 'A'
The maximum score is 100
Вы получаете несколько предложений относительно синтаксиса, но я бы также предложил более модульный подход, хотя бы по той причине, что код удобочитаем. Намного легче разобраться в коде, если вы сможете увидеть общую картину, прежде чем беспокоиться о низкоуровневых деталях.
Ваш основной метод может выглядеть так.
sub create_matrix {
my $self = shift;
$self->create_2d_array_of_scores;
$self->fill_out_first_row;
$self->fill_out_other_rows;
}
И у вас также будет несколько более мелких методов, например:
n_of_rows
n_of_cols
create_2d_array_of_scores
fill_out_first_row
fill_out_other_rows
И вы можете пойти еще дальше, определив еще более мелкие методы - геттеры, сеттеры и так далее. В этот момент ваши методы среднего уровня, такие как create_2d_array_of_scores
, вообще не будут напрямую касаться базовой структуры данных.
sub matrix { shift->{score_matrix} }
sub gap_cost { shift->{gap_cost} }
sub set_matrix_value {
my ($self, $r, $c, $val) = @_;
$self->matrix->[$r][$c] = $val;
}
# Etc.