如何计算 pdb 文件中的每个元素

How to count each element from a pdb file

我在尝试计算 pdb 文件中提供的每个元素的数量时遇到问题。到目前为止,代码已经实现了从以 ATOM 开头的文件中获取行。我也已经到了可以打印每个元素的地步。但是现在我想统计每个元素如C、O、N等,并按字母顺序列出。 数据如下所示:

 ATOM   4851  O   PRO A 715      89.164  76.083  75.292  1.00 99.41           O  
 ATOM   4852  CB  PRO A 715      88.324  78.267  73.865  1.00 95.88           C  
 ATOM   4853  CG  PRO A 715      88.836  78.838  72.540  1.00 95.93           C  
 ATOM   4854  CD  PRO A 715      90.288  78.546  72.593  1.00 94.99           C  
 ATOM   4855  N   PHE A 716      90.009  77.320  76.994  1.00100.00           N  
 ATOM   4856  CA  PHE A 716      90.100  76.203  77.966  1.00 99.66           C  
 ATOM   4857  C   PHE A 716      89.942  76.667  79.419  1.00 99.17           C  
 ATOM   4858  O   PHE A 716      88.895  76.334  80.027  1.00100.00           O  
 ATOM   4859  CB  PHE A 716      91.409  75.402  77.819  1.00 97.04           C  
 ATOM   4860  CG  PHE A 716      91.290  74.219  76.899  1.00 96.00           C  
 ATOM   4861  CD1 PHE A 716      90.323  73.236  77.133  1.00 94.17           C  
 ATOM   4862  CD2 PHE A 716      92.112  74.107  75.774  1.00 94.87           C  
 ATOM   4863  CE1 PHE A 716      90.170  72.157  76.260  1.00 93.04           C  
 ATOM   4864  CE2 PHE A 716      91.971  73.037  74.894  1.00 93.41           C  
 ATOM   4865  CZ  PHE A 716      90.996  72.057  75.137  1.00 95.29           C  

我的代码是:

open (FILE, $ARGV[0])
    or die "Could not open file\n";

my @newlines;
while ( my $line = <FILE> ) {
    if ($line =~ m/^ATOM.*/) {
    push @newlines, $line;
    }
}

##############################################################
#This function will take out the element from each line
#The element is from column 77 and contains one or two letters
#The function will also sort each element alphabetically and count them
sub atomfreq {
    foreach my $record1(@newlines) {
      my @element = substr($record1, 76, 2);
      my @sortelement = sort(@element);
      print "@sortelement\n";
    }
}

谢谢。

为了计算元素 CON(以及其他)的出现次数,hash 是正确的数据结构. 使用 元素 作为键并增加相应的值。 循环之后,您可以打印按其键排序的散列:

sub atomfreq {
    my %count;
    foreach my $record1(@newlines) {
        my $element = substr($record1, 76, 2);
        $count{$element} += 1;
    }
    foreach my $element ( sort keys %count ) {
        print "element=$element, count=$count{$element}\n";
    }
}

无需 open 将文件作为参数传递到命令行:您可以使用 <> 从中读取文件。使用 grep 而不是读取循环、测试和 push

也更加简洁

我也不明白你为什么需要一个子程序

此代码将执行您的要求

use strict;
use warnings 'all';

my @lines = grep /^ATOM/, <>;

my %counts;
++$counts{ unpack '@77 A2' } for @lines;
printf "%-4s%4d\n", $_, $counts{$_} for sort keys %counts;

输出

C     12
N      1
O      2