Расстояние между одной точкой и всеми остальными в файле PDB

У меня есть файл PDB. Теперь он состоит из двух частей, разделенных TER. Перед TER я называю это частью 1. Я хочу взять x, y, z атома 1 первой части, то есть до TER, и найти расстояние до всех координат x, y, z после TER, а затем второго ATOM части 1 ко всем атомам. части второй. Это необходимо повторить для всех АТОМОВ первой части = для всех АТОМОВ второй части. Я должен автоматизировать его для 20 файлов. имена моих файлов начинаются с 1_0.pdb, 2_0.pdb .... 20_0.pdb. Это расчет расстояния. Я пробовал что-то на PERL, но это очень грубо. Может кто-нибудь немного поможет. Файл выглядит так:

---- длинный файл (я его обрезал) ----

ATOM   1279 C    ALA    81      -1.925 -11.270   1.404
ATOM   1280 O    ALA    81      -0.279   9.355  15.557
ATOM   1281 OXT  ALA    81      -2.188  10.341  15.346
TER   
ATOM   1282 N    THR    82      29.632   5.205   5.525
ATOM   1283 H1   THR    82      30.175   4.389   5.768
ATOM   1284 H2   THR    82      28.816   4.910   5.008

Код такой: В конце концов, он находит максимальное расстояние и его координаты.

my @points = (); 
open(IN, @ARGV[0]) or die "$!"; 
while (my $line = <IN>) { 

  chomp($line); 
  my @array = (split (/\s+/, $line))[5, 6, 7]; 
  print "@array\n"; 
  push @points, [ @array ]; 
} 
close(IN); 


 $max=0;
 for my $i1 ( 0 .. $#points  )

{ 
    my ( $x1, $y1, $z1 ) = @{ $points[$i1] };  
    my $dist = sqrt( ($x1+1.925)**2 + ($y1+11.270)**2 + ($z1-1.404)**2 ); 
    print "distance from (-1.925 -11.270 1.404) to ( $x1, $y1, $z1 ) is $dist\n"; 

    if ( $dist > $max )
     { $max = $dist;
       $x=$x1;
       $y=$y1;
       $z=$z1; 
      }}
    print "maximum value is : $max\n";
print "co ordinates are : $x $y $z\n";        

person kanika    schedule 06.03.2012    source источник
comment
Сделайте часть цикла for + результирующую печать в подпрограмме, в которую вы можете передать одну ссылку на массив со значениями part1 и всю ссылку на массив для значений part2. Затем вы можете просто просмотреть значения part1 и сравнить. Используйте регулярное выражение внутри вашего начального цикла while, чтобы разделить part1 и part2, например last if /^TER$/.   -  person TLP    schedule 06.03.2012
comment
это 3vc8 .. но я использую его свернутые файлы   -  person kanika    schedule 06.03.2012


Ответы (3)


Не уверен, что я четко понимаю, что вы хотите, но как насчет:

#!/usr/local/bin/perl 
use strict;
use warnings;

my (@refer, @points);
my $part = 0;
while (my $line = <DATA>) { 
    chomp($line);
    if ($line =~ /^TER/) {
        $part++;
        next;
    }
    my @array = (split (/\s+/, $line))[5, 6, 7]; 
    if ($part == 0) {
        push @refer, [ @array ]; 
    } else {
        push @points, [ @array ]; 
    }
} 
my %max = (val=>0, x=>0, y=>0, z=>0);
foreach my $ref(@refer) {
    my ($x1, $y1, $z1) = @{$ref};
    foreach my $atom(@points) {
        my ($x, $y, $z) = @{$atom};
        my $dist = sqrt( ($x-$x1)**2 + ($y-$y1)**2 + ($z-$z1)**2 );
        if ($dist > $max{val}) {
            $max{val} = $dist;
            $max{x} = $x;
            $max{y} = $y;
            $max{z} = $z;
        }
    }
}
print "max is $max{val}; coord: x=$max{x}, y=$max{y}, z=$max{z}\n";

__DATA__
ATOM   1279 C    ALA    81      -1.925 -11.270   1.404
ATOM   1280 O    ALA    81      -0.279   9.355  15.557
ATOM   1281 OXT  ALA    81      -2.188  10.341  15.346
TER   
ATOM   1282 N    THR    82      29.632   5.205   5.525
ATOM   1283 H1   THR    82      30.175   4.389   5.768
ATOM   1284 H2   THR    82      28.816   4.910   5.008

вывод:

max is 35.9813670807545; coord: x=30.175, y=4.389, z=5.768
person Toto    schedule 06.03.2012
comment
Спасибо за помощь, но почему код не запускается, если я отдаю свой файл. имя моего файла 40_0.pdb.i запустить код как perl code.pl 40_0.pdb - person kanika; 06.03.2012
comment
@kanika: Просто замените <DATA> на <FILE_HANDLER> в цикле while. - person Toto; 06.03.2012
comment
я сделал это .. есть некоторая ошибка как Использование неинициализированного значения при вычитании (-) в tlp.pl строке 26, ‹FILE› строке 2619. Я не знаю, что это значит. - person kanika; 06.03.2012
comment
@kanika: Какая строка 2619 во входном файле? Разве это не пусто? - person Toto; 06.03.2012
comment
нет, это не пусто. это ATOM 2617 OXT THR 85 40,474 20,274 3,412 означает, что он имеет значение - person kanika; 06.03.2012
comment
@kanika: Попытайтесь создать какое-нибудь print, в сообщении указано значение undefined, это одно из $x,$y,$z,$x1,$y1,$z1, какое именно вам решать. - person Toto; 06.03.2012

Основная проблема здесь - чтение данных. Во-первых, обратите внимание, что нельзя использовать разделение с текстовыми файлами PDB, поскольку поля определяются по положению, а не по разделителям. См. Описание файла координат (формат PDB).

Чтобы разделить запись ATOM для различных цепочек полимеров, вы можете начать с упрощенной версии, например

my $iblock = 0;
my @atoms = ();
while (my $line = <IN>) { 
   chomp($line);

   # Switch blocks at TER lines
   if ($line =~ /^TER/) {
      $iblock++;

   # Read ATOM lines
   } elsif ($line =~ m/^ATOM/) {
      my @xyz = (substr($line,7-1,9),substr($line,16-1,9),substr($line,25-1,9)); 
      printf "Block %d: atom at (%s)\n",$iblock,join (",",@xyz); 
      push @{$atoms[$iblock]},\@xyz; 

   # Parse additional line types (if needed)
   } else {
      ...
   }
} 

Затем следует цикл по всем парам координат из разных блоков, структурированный следующим образом:

# 1st block
for my $iblock1 (0..$#atoms) {

   # 2nd block
   for my $iblock2 ($iblock1+1..$#atoms) {

      # Compare all pairs of atoms
      ... 
      my $xyz1 (@{$atoms[$iblock1]}) {
         for my $xyz2 (@{$atoms[$iblock2]}) {
            # Calculate distance and compare with $max_dist
            ...
         }
      }
      # Print the maximal distance between these two blocks
      ...
   }
}

Конечно, код может быть более общим, если используется более сложная структура данных или один из доступных парсеров PDB, например Bioperl.

person Itamar    schedule 06.03.2012

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

ETA: добавлено решение с фиксированной шириной, которое у меня было под рукой. Вероятно, было бы лучше прочитать все поля вместо того, чтобы отбрасывать первые 31 символ, а затем вернуть их все в хеш-ссылке. Таким образом, вы можете обрабатывать все строки с помощью одной и той же подпрограммы и просто переключаться между частями, когда первое поле оказывается TER. Вам должно быть легко экстраполировать это из данного кода.

Вы заметите, что ссылочные значения считываются с помощью цикла, потому что нам нужно прервать цикл в точке останова. Остальные значения записываются с помощью оператора map. Затем мы просто передаем данные подпрограмме, которую создали из вашего исходного кода (с некоторыми улучшениями). Я использовал те же имена для лексических переменных, чтобы облегчить чтение кода.

use strict;
use warnings;

my @points;
while (<DATA>) {
    last if /^TER$/;
    push @points, getpoints($_);
}
my @ref = map getpoints($_), <DATA>;

for my $p (@points) {
    getcoords($p, \@ref);
}

sub getpoints {
    my $line = shift;
    my @data = unpack "A31 A8 A8 A8", $line;
    shift @data;
    return \@data;
}
sub getcoords {
    my ($p, $ref) = @_;
    my ($p1,$p2,$p3) = @$p;
    my $max=0;
    my ($x,$y,$z);
    for my $aref ( @$ref ) {
        my ( $x1, $y1, $z1 ) = @$aref;  
        my $dist = sqrt(
            ($x1-$p1)**2 +
            ($y1-$p2)**2 +
            ($z1-$p3)**2
        ); 
        print "distance from ($p1 $p2 $p3) to ( $x1, $y1, $z1 ) is $dist\n"; 

        if ( $dist > $max ) {
            $max = $dist;
            $x=$x1;
            $y=$y1;
            $z=$z1; 
        }
    }
    print "maximum value is : $max\n";
    print "co ordinates are : $x $y $z\n";
}

__DATA__
ATOM   1279 C    ALA    81      -1.925 -11.270   1.404
ATOM   1280 O    ALA    81      -0.279   9.355  15.557
ATOM   1281 OXT  ALA    81      -2.188  10.341  15.346
TER
ATOM   1282 N    THR    82      29.632   5.205   5.525
ATOM   1283 H1   THR    82      30.175   4.389   5.768
ATOM   1284 H2   THR    82      28.816   4.910   5.008
person TLP    schedule 06.03.2012
comment
вроде бы какая-то ошибка. прога не берет координаты после TER. держит их (0,0,0) - person kanika; 06.03.2012
comment
@kanika Это рабочий код с моей стороны. Если это не работает с вашей стороны, значит проблема на вашей стороне. - person TLP; 06.03.2012
comment
Я думаю, это потому, что некоторые строки в файле похожи на ATOM 2597 HG22THR 84 44,438 16,785 1,083 ATOM 2598 HG23THR 84 45,228 18,247 1,394 - person kanika; 06.03.2012
comment
@kanika Итак, вместо этого вы выбираете решение с фиксированной шириной. Так получилось, что я сделал и эту версию, просто для удовольствия. Это довольно просто, но вам может потребоваться настроить числа смещения. - person TLP; 06.03.2012