knytshade
knytshade

Reputation: 31

Pushing to an array while in a loop

I am attempting to make a script that calculates the centroid of two amino acids then finds the distance between the two centroids. Obviously to do this I need all of the x,y,z coordinates which I have and can get at just fine. However, when I attempt to find the average of each of these I am simply getting the last value. Right now I have a fairly lengthy bit of code but the part that is giving me trouble is:

for (my $line = 1; $line <= $#data; ++$line) {
   if (($data[$line] =~ m/\s+$resid1\s+P/)&&($data[$line] =~ m/P\s+$resnum1\s+/)) {
    chomp $data[$line];
    my @splitline = (split /\s+/, $data[$line]);
    #print "$splitline[1] $splitline[3] $splitline[5] $splitline[6] $splitline[7] $splitline[8]\n";
            #atom#         #residue       #resid        #x-coor        #y-coor        #z-coor

    #calculate the average x coordinate
    my @xcoordinate_array;
    push @xcoordinate_array, $splitline[6];
    $xsum =sum(@xcoordinate_array);
    $xaverage=($xsum/$#xcoordinate_array);
    print "@xcoordinate_array \n";

    #calculate the average y coordinate
    my @ycoordinate_array;
    push @ycoordinate_array, $splitline[7];
    $ysum =sum(@ycoordinate_array);
    $yaverage =($xsum/$#ycoordinate_array);

    #calculate the average z coordinate
    my @zcoordinate_array;
    push @zcoordinate_array, $splitline[8];
    $zsum =sum(@zcoordinate_array);
    $zaverage=($zsum/$#zcoordinate_array);
    }

  }

Basically what this is supposed to do is search for some residue name (resid1), then some residue number (resnum1), read that line into an array (@splitline) (whose important contents are explained on line 5), then it is supposed to put each type of value into its individual array and use a subroutine (sum) to add the whole array and then divide by the number of things in the array.

However, when I print any of the averages it is only the last value. I understand why this is happening, however I cannot calculate the average outside of the loop since perl throws a fit saying that I cannot access the @xcoordinate_array outside of the loop. I understand that it is just overriding the array every time it goes the loop however I was hoping that it would add each value onto the array and at the end give the correct value.

So what I am asking is, how do I fix it so that I can get the array "full" with each value?

Upvotes: 0

Views: 975

Answers (1)

Paul Roub
Paul Roub

Reputation: 36448

You're re-creating the arrays, and calculating an average of a single element, for each matching line. Declare the arrays outside, and print their values after you're done with the file:

my (@xcoordinate_array, @ycoordinate_array, @zcoordinate_array);

for (my $line = 1; $line <= $#data; ++$line) {
   if (($data[$line] =~ m/\s+$resid1\s+P/) && ($data[$line] =~ m/P\s+$resnum1\s+/)) {
    chomp $data[$line];
    my @splitline = (split /\s+/, $data[$line]);

    push @xcoordinate_array, $splitline[6];
    push @ycoordinate_array, $splitline[7];
    push @zcoordinate_array, $splitline[8];
  }
}

#calculate the average x coordinate
if (@xcoordinate_array > 0) {
  $xsum     = sum(@xcoordinate_array);
  $xaverage = $xsum / @xcoordinate_array;
}

#calculate the average y coordinate
if (@ycoordinate_array > 0) {
  $ysum     = sum(@ycoordinate_array);
  $yaverage = $ysum / @ycoordinate_array;
}

#calculate the average z coordinate
if (@zcoordinate_array > 0) {
  $zsum     = sum(@zcoordinate_array);
  $zaverage = $zsum / @zcoordinate_array;
}

Upvotes: 2

Related Questions