#!/usr/bin/perl

# MDAVG is a Perl script to compute averages and block average
# standard deviations from a Tinker dynamics trajectory log file
#
# Original version written by Pengyu Ren, Ponder Lab, July 2000
# Modified to give std dev of block averages, Jay Ponder, Oct 2011

if ($#ARGV > 2 or $#ARGV < 0) {die "$0: logfile start(in frame) end\n";}
if ($#ARGV == 0) {$ARGV[1]=1;$ARGV[2]=1000000000;}
if ($#ARGV == 1) {$ARGV[2]=1000000000;} 
#In perl, $ARG[0] is the first argument, $0 is the name of prog
$start=88+$ARGV[1]*14;
@tot=();
@totrms=();
@totrms2=();
@pot=();
@potrms=();
@potrms2=();
@kin=();
@kinrms=();
@kinrms2=();
@inter=();
@interms=();
@interms2=();
@ele=();
@elerms=();
@elerms2=();
@vdw=();
@vdwrms=();
@vdwrms2=();
@pol=();
@polrms=();
@polrms2=();
@temp=();
@temprms=();
@temprms2=();
@press=();
@pressrms=();
@pressrms2=();
@den=();
@denrms=();
@denrms2=();
$i=0;
$count=0;

open(LOG,"$ARGV[0]")||die "can't open log file\n";

while(<LOG>){

    if (substr($_,1,12) eq "Total Energy") {
        $i++;
        $etot=substr($_,23,13);
        $etotrms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            $count++;
            push(@tot, $etot);
            push(@totrms, $etot);
            push(@totrms2, $etotrms);
        }
    }
    if (substr($_,1,9) eq "Potential") {
        $epot=substr($_,23,13);
        $epotrms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@pot, $epot);
            push(@potrms, $epot);
            push(@potrms2, $epotrms);
        }
    }
    if (substr($_,1,7) eq "Kinetic") {
        $ekin=substr($_,23,13);
        $ekinrms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@kin, $ekin);
            push(@kinrms, $ekin);
            push(@kinrms2, $ekinrms);
        }
    }
    if (substr($_,1,14) eq "Intermolecular") {   
        $ei=substr($_,23,13);
        $eirms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@inter, $ei);
            push(@interms, $ei);
            push(@interms2, $eirms);
        }
    }
    if (substr($_,1,13) eq "Electrostatic") {
        $ee=substr($_,23,13);
        $eerms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@ele, $ee);
            push(@elerms, $ee);
            push(@elerms2, $eerms);
        }
    }
    if (substr($_,1,13) eq "van der Waals") {
        $ev=substr($_,23,13);
        $evrms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@vdw, $ev);
            push(@vdwrms, $ev);
            push(@vdwrms2, $evrms);
        }
    }
    if (substr($_,1,12) eq "Polarization") {
        $ep=substr($_,23,13);
        $eprms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@pol, $ep);
            push(@polrms, $ep);
            push(@polrms2, $eprms);
        }
    } 
    if (substr($_,1,11) eq "Temperature") {
        $tm=substr($_,23,13);
        $tmrms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@temp, $tm);
            push(@temprms, $tm);
            push(@temprms2, $tmrms);
        }
    }
    if (substr($_,1,8) eq "Pressure") {
        $pre=substr($_,23,13);
        $prerms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@press, $pre);
            push(@pressrms, $pre);
            push(@pressrms2, $prerms);
        }
      }
    if (substr($_,1,7) eq "Density") {
        $d=substr($_,23,13);
        $drms=substr($_,53,7);
        if ($i>=$ARGV[1] && $i<=$ARGV[2]) {
            push(@den, $d);
            push(@denrms, $d);
            push(@denrms2, $drms);
        }
      }
}

if ($#tot != -1) {
    $avgtot=&AVG(@tot);
    $stdtot=&STD(@totrms);
    $stdtot2=&STD2(@totrms2);
}
if ($#pot != -1) {
    $avgpot=&AVG(@pot);
    $stdpot=&STD(@potrms);
    $stdpot2=&STD2(@potrms2);
}
if ($#kin != -1) {
    $avgkin=&AVG(@kin);
    $stdkin=&STD(@kinrms);
    $stdkin2=&STD2(@kinrms2);
}
if ($#inter != -1) {
    $avgi=&AVG(@inter);
    $stdi=&STD(@interms);
    $stdi2=&STD2(@interms2);
}
if ($#ele != -1) {
    $avge=&AVG(@ele);
    $stde=&STD(@elerms);
    $stde2=&STD2(@elerms2);
}
if ($#vdw != -1) {
    $avgv=&AVG(@vdw);
    $stdv=&STD(@vdwrms);
    $stdv2=&STD2(@vdwrms2);
}
if ($#pol != -1) {
    $avgp=&AVG(@pol);
    $stdp=&STD(@polrms);
    $stdp2=&STD2(@polrms2);
}
if ($#temp != -1) {
    $avgt=&AVG(@temp);
    $stdt=&STD(@temprms);
    $stdt2=&STD2(@temprms2);
}
if ($#press != -1) {
    $avgpr=&AVG(@press);
    $stdpr=&STD(@pressrms);
    $stdpr2=&STD2(@pressrms2);
}
if ($#den != -1)  {
    $avgd=&AVG(@den);
    $stdd=&STD(@denrms);
    $stdd2=&STD2(@denrms2);
}

sub AVG{
    $sum=0.0;
    $cnt=0;
    foreach $ii (@_) { 
        $sum=$ii+$sum;
        $cnt=$cnt+1;
    }
    $avg=$sum/$cnt;
}

sub STD{
    $sum2=0.0;
    $sum1=0.0;
    $cnt=0;
    foreach $ii (@_) { 
        $sum1=$ii+$sum1;
        $cnt=$cnt+1;
    }
    $avg=$sum/$cnt;
   
    foreach $ii (@_) {
        $sum2=($avg-$ii)*($avg-$ii)+$sum2;
    }             
    $std=sqrt($sum2/($cnt-1));
}

sub STD2{
    $sum2=0.0;
    $sum1=0.0;
    $cnt=0;
    for($i=0;$i<$#_;$i=$i+2){
        $cnt=$cnt+100;
        $sum1=$_[$i]*100.0+$sum1;
        $sum2=$sum2+($_[$i+1]**2+$_[$i]**2)*100.0;
        $std2=$sum2/$cnt-($sum1/$cnt)**2;
    }
    if ($std2 > -0.0001 && $std2 < 0) { $std2=0.0; }
    $std2=sqrt($std2);
}

if ($count > -1) {
   printf " Total MD Blocks     %15d Blocks\n", "$count";
}
if ($#tot > -1) {
   printf " Total Energy        %15.4f Kcal/mole   (+/-%9.4f)\n", "$avgtot","$stdtot";
}
if ($#pot > -1) {
   printf " Potential Energy    %15.4f Kcal/mole   (+/-%9.4f)\n", "$avgpot","$stdpot";
}
if ($#kin > -1) {
   printf " Kinetic Energy      %15.4f Kcal/mole   (+/-%9.4f)\n", "$avgkin","$stdkin";
}
if ($#inter > -1) {
   printf " Intermolecular      %15.4f Kcal/mole   (+/-%9.4f)\n", "$avgi","$stdi";
}
if ($#ele > -1) {
   printf " Electrostatic       %15.4f Kcal/mole   (+/-%9.4f)\n", "$avge","$stde";
}
if ($#vdw > -1) {
   printf " van der Waals       %15.4f Kcal/mole   (+/-%9.4f)\n", "$avgv","$stdv";
}
if ($#pol > -1) {
   printf " Polarization        %15.4f Kcal/mole   (+/-%9.4f)\n", "$avgp","$stdp";
}
if ($#temp > -1) {
   printf " Temperature         %15.2f Kelvin      (+/-%9.2f)\n", "$avgt","$stdt";
}
if ($#press > -1) {
   printf " Pressure            %15.2f Atomsphere  (+/-%9.2f)\n", "$avgpr","$stdpr";
}
if ($#den > -1) {
   printf " Density             %15.4f Grams/cc    (+/-%9.4f)\n", "$avgd","$stdd";
}
