2013-12-23 2 views
1

Я получил этот скрипт ниже с этого сайта.
Расчет расстояния между атомами по атомам Координаты

use strict; 
use warnings; 

open(OUTPUT,">/home/guest/Desktop/test.txt") or die ("couldn't write the file"); 
my @line; 
for (<>) { 
    push @line, $_;    
    next if (@line)<2; 
    print OUTPUT distance(@line), "\n"; 
} 
sub distance { 
    my @a = split ' ',shift; 
    my @b = split ' ',; 
    my $x = ($a[6]-$b[6]);  
    my $y = ($a[7]-$b[7]); 
    my $z = ($a[8]-$b[8]); 
    my $dist = sprintf "%.1f",sqrt($x**2+$y**2+$z**2); 
    return "$a[1] to $b[1] |$a[11]-$b[11]| Distance-\t$dist"; 
} 

Я использую этот сценарий, чтобы определить расстояние между атомами. Я могу достичь только с одним атомом.

INPUT 

HETATM 1 N MSE A 1  16.272 16.789 53.256 1.00 31.95   N 
HETATM 2 CA MSE A 1  15.408 15.939 52.384 1.00 30.64   C 
HETATM 3 C MSE A 1  13.919 16.266 52.544 1.00 27.80   C 
HETATM 4 O MSE A 1  13.393 16.321 53.659 1.00 26.16   O 

OUTPUT 

1 to 2 |N-C| Distance- 1.5 
1 to 3 |N-C| Distance- 2.5 
1 to 4 |N-O| Distance- 2.9 

ВЫХОД

DESIRED

1 до 2 | N-C | Расстояние - 1,5
От 1 до 3 | N-C | Расстояние - 2,5
От 1 до 4 | N-O | Расстояние - 2.9
От 2 до 1 | N-C | Расстояние - 1,5
От 2 до 3 | N-C | Расстояние - 2,5
От 2 до 4 | N-O | Расстояние - 2.9
3 до 1 | N-C | Расстояние - 1,5
3 до 2 | N-C | Расстояние - 2,5
От 3 до 4 | N-O | Расстояние - 2.9
4 до 1 | N-C | Расстояние - 1,5
От 4 до 2 | N-C | Дистанция - 2,5
От 4 до 3 | N-O | Distance- 2,9

Пожалуйста, помогите мне

ответ

3

Линия

my @b = split ' ',; 

$_ разбивает переменную в массиве @b, когда то, что вы хотите в верхней части @_ массива.

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

Если вы пишете подпрограмму с именем distance, то лучше всего, если она возвращает расстояния, а не какая-то произвольная строки, что вызывающий код случается хотеть.

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

use strict; 
use warnings; 

open my $out, '>', '/home/guest/Desktop/test.txt' or die "Couldn't open output file: $!"; 
my @data = map [ split ], grep /\S/, <>; 

for my $i (0 .. $#data) { 
    for my $j (0 .. $#data) { 

    next if $i == $j; 

    my @coords_i = @{$data[$i]}[6,7,8]; 
    my @coords_j = @{$data[$j]}[6,7,8]; 

    printf $out "%s to %s |%s-%s| Distance-%.3f\n", 
     $data[$i][1], $data[$j][1], 
     $data[$i][11], $data[$j][11], 
     distance(\@coords_i, \@coords_j); 
    } 
} 

sub distance { 
    my ($aa, $bb) = @_; 
    my ($x, $y, $z) = map { $aa->[$_] - $bb->[$_] } 0 .. $#$aa; 
    return sqrt($x * $x + $y * $y + $z * $z); 
} 

выход

1 to 2 |N-C| Distance-1.493 
1 to 3 |N-C| Distance-2.513 
1 to 4 |N-O| Distance-2.944 
2 to 1 |C-N| Distance-1.493 
2 to 3 |C-C| Distance-1.533 
2 to 4 |C-O| Distance-2.415 
3 to 1 |C-N| Distance-2.513 
3 to 2 |C-C| Distance-1.533 
3 to 4 |C-O| Distance-1.234 
4 to 1 |O-N| Distance-2.944 
4 to 2 |O-C| Distance-2.415 
4 to 3 |O-C| Distance-1.234 
+0

Большое спасибо! – user3032425

1

У вас есть 4 строки в файле, так что ваш цикл будет иметь 4 итерации (и будет пропускать первый, так как список по-прежнему имеет размер 1).

Если вы хотите совместить каждый 2 элемента, вам нужен вложенный цикл, который будет запускать n^2 итераций, данных n строк ввода. Просто включите ваш главный цикл в этом

for (<>) { 
    push @line, $_;    
} 
for $a (@line) { 
    for $b (@line) { 
      next if ($a eq $b); 
      print OUTPUT distance(@line), "\n"; 
    } 
} 
+0

К сожалению Его ошибка показывает .. – user3032425

+0

@ user3032425, уход сказать, какая ошибка? Отлично работает для меня – Leeor

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