从mol2文件计算欧氏距离

时间:2014-03-20 05:47:07

标签: regex perl

这是我的程序,我想在不同的时间计算两个原子之间的欧氏距离。所以我可以修改这个程序使它成为可能。我的输入是

  1 I          -6.2528   -0.8879    0.3208 I       1  LIG1       -0.0425
  2 O          -0.1927    0.3708   -0.4256 O.3     1  LIG1       -0.4750
  3 N           2.7475    3.2931    0.6111 N.3     1  LIG1       -0.2164
  4 C           0.6554    0.0834    0.6881 C.3     1  LIG1        0.1896
  5 C           1.3107    1.3881    1.1695 C.3     1  LIG1        0.0670
  6 C           1.6435   -0.9764    0.2598 C.ar    1  LIG1        0.0172
  7 C           2.1448    2.0726    0.0863 C.3     1  LIG1        0.0928
  8 C          -1.5245    0.1089   -0.2623 C.ar    1  LIG1        0.1349
  9 C           2.1274   -1.8960    1.1905 C.ar    1  LIG1       -0.0008
 10 C           2.0723   -1.0350   -1.0663 C.ar    1  LIG1       -0.0008
 11 C          -2.4708    1.1273   -0.3768 C.ar    1  LIG1        0.0125
 12 C           3.0398   -2.8742    0.7949 C.ar    1  LIG1       -0.0002
 13 C           2.9846   -2.0133   -1.4618 C.ar    1  LIG1       -0.0002
 14 C          -1.9331   -1.1945    0.0206 C.ar    1  LIG1        0.0370
 15 C           3.4684   -2.9327   -0.5314 C.ar    1  LIG1       -0.0000
 16 C           3.5783    3.9360   -0.3969 C.3     1  LIG1        0.1075

这是我的程序

#!/usr/bin/perl -w
use strict;

my $num = 0;

my @arrayx;
my @arrayy;
my @arrayz;

while (<>) {
    # remove new line char
    chomp;

    # Find x, y, z coordinates and store in separate arrays
    if (/^ATOM/) {
        my @line = $_ =~ m/^(.....).(.....).(....).(...)..(....)....(........)(........)               (........)/;

        my $x = $line[5];
        $arrayx[$num] = $x;

        my $y = $line[6];
        $arrayy[$num] = $y;

        my $z = $line[7];
        $arrayz[$num] = $z;

        ++$num;
    }
}

# Calculate distance between all atom coordinates
for my $i ( 0 .. $num ) {
    for my $j ( $i + 1 .. $num ) {

        # skip if j array element does not exist
        unless ( defined( $arrayx[$j] )
            && defined( $arrayy[$j] )
            && defined( $arrayz[$j] ) )
        {
            print "Skipping i:$i j:$j\n";
            sleep(1);
            next;
        }

        my $dist =
          sqrt( ( $arrayx[$i] - $arrayx[$j] )**2 +
              ( $arrayy[$i] - $arrayy[$j] )**2 +
              ( $arrayz[$i] - $arrayz[$j] )**2 );
        print "$dist\n";
    }
}

2 个答案:

答案 0 :(得分:1)

您发布了一些示例数据,但实际上并没有告诉我们它的含义。我怀疑第2,第3和第4列分别是指x,y和z,但你应该确认这一点。

如果是这种情况,那么以下是您的代码的清理版本。也许它会对你有所帮助:

#!/usr/bin/perl -w
use strict;

my @data;

while (<DATA>) {
    chomp;

    # Find x, y, z coordinates and store in separate arrays
    my @line = split;

    push @data, {
        x => $line[2],
        y => $line[3],
        z => $line[4],
        name => $line[5],
    };
}

# Calculate distance between all atom coordinates
for my $i ( 0 .. $#data ) {
    for my $j ( $i + 1 .. $#data ) {

        my $dist =
          sqrt( ( $data[$i]{x} - $data[$j]{x} )**2 +
              ( $data[$i]{y} - $data[$j]{y} )**2 +
              ( $data[$i]{z} - $data[$j]{z} )**2 );

        printf "%-6s %-6s %f\n", $data[$i]{name}, $data[$j]{name}, $dist;
    }
}

__DATA__
  1 I          -6.2528   -0.8879    0.3208 I       1  LIG1       -0.0425
  2 O          -0.1927    0.3708   -0.4256 O.3     1  LIG1       -0.4750
  3 N           2.7475    3.2931    0.6111 N.3     1  LIG1       -0.2164
  4 C           0.6554    0.0834    0.6881 C.3     1  LIG1        0.1896
  5 C           1.3107    1.3881    1.1695 C.3     1  LIG1        0.0670
  6 C           1.6435   -0.9764    0.2598 C.ar    1  LIG1        0.0172
  7 C           2.1448    2.0726    0.0863 C.3     1  LIG1        0.0928
  8 C          -1.5245    0.1089   -0.2623 C.ar    1  LIG1        0.1349
  9 C           2.1274   -1.8960    1.1905 C.ar    1  LIG1       -0.0008
 10 C           2.0723   -1.0350   -1.0663 C.ar    1  LIG1       -0.0008
 11 C          -2.4708    1.1273   -0.3768 C.ar    1  LIG1        0.0125
 12 C           3.0398   -2.8742    0.7949 C.ar    1  LIG1       -0.0002
 13 C           2.9846   -2.0133   -1.4618 C.ar    1  LIG1       -0.0002
 14 C          -1.9331   -1.1945    0.0206 C.ar    1  LIG1        0.0370
 15 C           3.4684   -2.9327   -0.5314 C.ar    1  LIG1       -0.0000
 16 C           3.5783    3.9360   -0.3969 C.3     1  LIG1        0.1075

输出:

I        O.3      6.234280
I        N.3      9.928264
I        C.3      6.985811
I        C.3      7.943991
I        C.ar     7.897032
I        C.3      8.907258
I        C.ar     4.867282
I        C.ar     8.485305
I        C.ar     8.441148
I        C.ar     4.341797
I        C.ar     9.514335
I        C.ar     9.474901
I        C.ar     4.340960
I        C.ar     9.970415
I        C.3      10.974317
O.3      N.3      4.273097
O.3      C.3      1.429056
O.3      C.3      2.416496
O.3      C.ar     2.378309
....

答案 1 :(得分:0)

你不清楚问题是什么。目前尚不清楚会发生什么以及应该发生什么。尤其应该发生什么。我不知道mol2格式,甚至更少知道如何在不同时间计算欧氏距离。

但是:您的评论意味着问题在于

my @line = $_ =~ m/^(.....).(.....).(....).(...)..(....)....(........ (........)               (........)/;

我不完全确定你在这里尝试做什么。您是否尝试将粘贴文本文件的一行(mol2?)的字段放入数组@line?如果是这样,请尝试

my @line = split ' ', $_;

代替。这将删除任何前导空格,然后将字符串拆分为任意数量的空格。因此,如果您以这种方式拆分第一个示例行,最后将以$line[2] == -6.2528,$line[3] == -0.8879,$line[4] == 0.3208结束 假设这些是您追求的数字。