【发布时间】:2016-09-25 04:24:23
【问题描述】:
我正在尝试编写一个脚本来计算几个碳氢键的顺序参数并输出这些值。数学是微不足道的,但是当我尝试对最后的值进行平均时,我得到了“另外使用未初始化的值”错误。 我很清楚这个错误是多么常见和容易修复,但我检查了所有给定的值,所有 9212 个值都有一个值(我通过打印每个值进行检查,将其放入 excel 文档并搜索空单元格)。我很茫然,我不知道如何进一步调试。
我的脚本接受一个输入文件,逐行执行,如果存在某些字符串,则采用 x、y、z 坐标,对这些坐标进行数学运算(找到两个向量与 z 轴之间的角度),应该是将每个 $integer 部分平均在一起(因此所有 2 的平均值等)。它对 3 个段(2-8、9-10 和 11-18)执行此操作,将它们保存到两个数组(@theta_values 和 @theta2_values),最后它应该将每个“整数”平均在一起以找到矢量和 z 轴。 总共应该有 34 个值输出,这确实发生了,但每个值都有一个“在 angle_checker_v3.pl 第 334 行,第 34303 行使用未初始化的值(+)”。误差,并且除第一个以外的所有平均值都太小了。
作为参考,第 334 行是我平均的位置,第 34303 行是文件的最后一行。
一些示例数据是:
ATOM 2199 C22 POPC 1 -9.427 11.863 11.706 1.00 0.00 MEMB
ATOM 2200 H2R POPC 1 -10.347 11.662 12.293 1.00 0.00 MEMB
ATOM 2201 H2S POPC 1 -8.968 10.895 11.443 1.00 0.00 MEMB
ATOM 2211 C23 POPC 1 -9.801 12.641 10.423 1.00 0.00 MEMB
ATOM 2212 H3R POPC 1 -10.136 13.667 10.696 1.00 0.00 MEMB
ATOM 2213 H3S POPC 1 -10.658 12.124 9.934 1.00 0.00 MEMB
ATOM 2214 C24 POPC 1 -8.663 12.751 9.396 1.00 0.00 MEMB
ATOM 2215 H4R POPC 1 -7.763 13.166 9.894 1.00 0.00 MEMB
ATOM 2216 H4S POPC 1 -8.961 13.479 8.607 1.00 0.00 MEMB
*我故意跳过上面的 10 个无关紧要的原子
按列表示的顺序:物质(不相关)、原子编号、原子类型、残基编号/分子类型、残基编号、x 坐标、y 坐标、z 坐标、α 编号(不相关)、 beta 列(不相关)和整体分子类型。
TLDR; 我的平均脚本:
#Averaging theta values
for (my $t=2; ($t <= 18); $t++) {
for (my $j=1; ($j <= $lipid_num); $j++) {
$sum[$t]= $theta_values[$t][$j] + $sum[$t];
}
$average[$t]= $sum[$t] / $lipid_num;
print "Average theta for carbon $t is $average[$t]\n";
}
#Averaging Theta2 values
for (my $q=2; ($q <= 18); $q++) {
for (my $b=1; ($b <= $lipid_num); $b++) {
$sum2[$q]= $theta2_values[$q][$b] + $sum2[$q];
}
$average2[$q]= $sum2[$q] / $lipid_num;
print "Average theta2 for carbon $q is $average2[$q]\n";
}
即使我已验证所有位置都有值,但在所有位置都没有找到值。
这是完整的脚本,我知道它有多大。
#Usage: #
# perl angle_checker.pl [granuphilin_prot-memb_system].pdb
#!/usr/bin/perl
use strict;
use warnings;
use Math::Trig;
my $inputfile = $ARGV[0];
open (INPUTFILE, "<", $inputfile) or die $!;
my @data = <INPUTFILE>;
#Quick Change Variables
my $lipid_num = 256;
#Library
my @sum;
my @average;
my @sum2;
my @average2;
my @x1;
my @y1;
my @z1;
my $R = 'R';
my $S = 'S';
my $one = '1';
my @theta_values;
my @theta2_values;
my @vectorCtoHR;
my @vectorCtoHS;
my @normal;
#Start for lipid count
for (my $lipid=1; ($lipid <= $lipid_num); $lipid++) {
# First Carbon/Integer counter
for (my $integer= 2; ($integer <= 8); $integer++) {
#Split line 1
for (my $line = 0; $line <= $#data; ++$line) {
#Search 1.1
if(($data[$line] =~ m/\s+C2$integer\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
chomp $data[$line];
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[0]= $splitline[5];
$y1[0]= $splitline[6];
$z1[0]= $splitline[7];
}
}
#Search 1.2
if(($data[$line] =~ m/\s+H$integer$R\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[1]= $splitline[5];
$y1[1]= $splitline[6];
$z1[1]= $splitline[7];
}
}
#Search 1.3
if(($data[$line] =~ m/\s+H$integer$S\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[2]= $splitline[5];
$y1[2]= $splitline[6];
$z1[2]= $splitline[7];
}
}
}
#Z-axis
$normal[0]= 0;
$normal[1]= 0;
$normal[2]= 100;
#Vector 1
$vectorCtoHR[0]=($x1[0] - ($x1[1]));
$vectorCtoHR[1]=($y1[0] - ($y1[1]));
$vectorCtoHR[2]=($z1[0] - ($z1[1]));
#Vector 2
$vectorCtoHS[0]=($x1[0] - ($x1[2]));
$vectorCtoHS[1]=($y1[0] - ($y1[2]));
$vectorCtoHS[2]=($z1[0] - ($z1[2]));
#First Angle
my $x1mag = sqrt(($vectorCtoHS[0]**2)+($vectorCtoHS[1]**2)+($vectorCtoHS[2]**2));
my $x2mag = sqrt(($normal[0]**2)+($normal[1]**2)+($normal[2]**2));
#Dot product
my $dotproduct = (($vectorCtoHS[0]*$normal[0])+($vectorCtoHS[1]*$normal[1])+($vectorCtoHS[2]*$normal[2]));
my $theta = acos($dotproduct/($x1mag*$x2mag));
$theta_values[$integer][$lipid]= $theta;
# Second Angle
my $x3mag = sqrt(($vectorCtoHR[0]**2)+($vectorCtoHR[1]**2)+($vectorCtoHR[2]**2));
my $dotproduct2 = (($vectorCtoHR[0]*$normal[0])+($vectorCtoHR[1]*$normal[1])+($vectorCtoHR[2]*$normal[2]));
my $theta2 = acos($dotproduct2/($x3mag*$x2mag));
$theta2_values[$integer][$lipid]= $theta2;
}
#Section 2 Search These only have one hydrogen to search for, hence 1 less search
for (my $integer = 9; ($integer <= 10); $integer++) {
for (my $line = 0; $line <= $#data; ++$line) {
if(($data[$line] =~ m/\s+C2$integer\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
chomp $data[$line];
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[0]= $splitline[5];
$y1[0]= $splitline[6];
$z1[0]= $splitline[7];
}
}
if(($data[$line] =~ m/\s+H$integer$one\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[1]= $splitline[5];
$y1[1]= $splitline[6];
$z1[1]= $splitline[7];
}
}
}
$normal[0]= 0;
$normal[1]= 0;
$normal[2]= 100;
$vectorCtoHR[0]=($x1[0] - ($x1[1]));
$vectorCtoHR[1]=($y1[0] - ($y1[1]));
$vectorCtoHR[2]=($z1[0] - ($z1[1]));
my $x1mag = sqrt(($vectorCtoHR[0]**2)+($vectorCtoHR[1]**2)+($vectorCtoHR[2]**2));
my $x2mag = sqrt(($normal[0]**2)+($normal[1]**2)+($normal[2]**2));
#Dot product
my $dotproduct = (($vectorCtoHR[0]*$normal[0])+($vectorCtoHR[1]*$normal[1])+($vectorCtoHR[2]*$normal[2]));
my $theta = acos($dotproduct/($x1mag*$x2mag));
$theta_values[$integer][$lipid]= $theta;
$theta2_values[$integer][$lipid]= $theta;
}
#Effectively the same as section 1
for (my $integer= 11; ($integer <= 18); $integer++) {
for (my $line = 0; $line <= $#data; ++$line) {
if(($data[$line] =~ m/\s+C2$integer\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
chomp $data[$line];
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[0]= $splitline[5];
$y1[0]= $splitline[6];
$z1[0]= $splitline[7];
}
}
if(($data[$line] =~ m/\s+H$integer$R\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[1]= $splitline[5];
$y1[1]= $splitline[6];
$z1[1]= $splitline[7];
}
}
if(($data[$line] =~ m/\s+H$integer$S\s+/)&&($data[$line] =~ m/\s+$lipid\s+/)&&($data[$line] =~ m/\s+POPC\s+/)) {
my @splitline = (split /\s+/, $data[$line]);
foreach (@splitline) {
$x1[2]= $splitline[5];
$y1[2]= $splitline[6];
$z1[2]= $splitline[7];
}
}
}
$normal[0]= 0;
$normal[1]= 0;
$normal[2]= 100;
$vectorCtoHR[0]=($x1[0] - ($x1[1]));
$vectorCtoHR[1]=($y1[0] - ($y1[1]));
$vectorCtoHR[2]=($z1[0] - ($z1[1]));
$vectorCtoHS[0]=($x1[0] - ($x1[2]));
$vectorCtoHS[1]=($y1[0] - ($y1[2]));
$vectorCtoHS[2]=($z1[0] - ($z1[2]));
#First Angle
my $x1mag = sqrt(($vectorCtoHS[0]**2)+($vectorCtoHS[1]**2)+($vectorCtoHS[2]**2));
my $x2mag = sqrt(($normal[0]**2)+($normal[1]**2)+($normal[2]**2));
#Dot product
my $dotproduct = (($vectorCtoHS[0]*$normal[0])+($vectorCtoHS[1]*$normal[1])+($vectorCtoHS[2]*$normal[2]));
my $theta = acos($dotproduct/($x1mag*$x2mag));
$theta_values[$integer][$lipid]= $theta;
}
print "done with $lipid\n";
#End of lipid search
}
#Averaging starts now
#Averaging theta values
for (my $t=2; ($t <= 18); $t++) {
for (my $j=1; ($j <= $lipid_num); $j++) {
$sum[$t]= $theta_values[$t][$j] + $sum[$t];
}
$average[$t]= $sum[$t] / $lipid_num;
print "Average theta for carbon $t is $average[$t]\n";
}
#Averaging Theta2 values
for (my $q=2; ($q <= 18); $q++) {
for (my $b=1; ($b <= $lipid_num); $b++) {
$sum2[$q]= $theta2_values[$q][$b] + $sum2[$q];
}
$average2[$q]= $sum2[$q] / $lipid_num;
print "Average theta2 for carbon $q is $average2[$q]\n";
}
【问题讨论】:
-
是否可以在某处发布输入数据文件?没有它,问题就无法在本地重现,从而使调试变得困难一个数量级。
-
尝试先将
@sum和@sum2数组初始化为零? -
另外,您将
$q从 2 迭代到 18。您的意思是跳过@sum和@sum2数组的 0 和 1 位置吗?除非您对此采取措施,否则这些将不会被初始化。 -
您的代码也将受益于将您几乎重复的代码部分重构为子例程。
$integer的任意索引也应转换为常量,并为其值提供一些理由。在你的代码的 cmets 中输入格式的一个例子也会为其他试图理解你的代码的人创造奇迹。 -
第一个观察:这是太多的直接代码。它应该分成子程序。然后您可以实际检查该过程的各个部分。此外,它会允许并迫使您对问题进行分区和结构化,几乎可以肯定会产生更好的代码。
标签: perl