#!/usr/bin/perl

# MDAVG is a Perl script to compute property average values and 
# 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
# Patched to agree with Tinker MDAVG program, Jay Ponder, Oct 2025

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

if ($#tot != -1) {
    $avgtot=&AVG(@tot);
    $stdtot=&STD(@totrms);
}
if ($#pot != -1) {
    $avgpot=&AVG(@pot);
    $stdpot=&STD(@potrms);
}
if ($#kin != -1) {
    $avgkin=&AVG(@kin);
    $stdkin=&STD(@kinrms);
}
if ($#inter != -1) {
    $avgi=&AVG(@inter);
    $stdi=&STD(@interms);
}
if ($#ele != -1) {
    $avge=&AVG(@ele);
    $stde=&STD(@elerms);
}
if ($#vdw != -1) {
    $avgv=&AVG(@vdw);
    $stdv=&STD(@vdwrms);
}
if ($#pol != -1) {
    $avgp=&AVG(@pol);
    $stdp=&STD(@polrms);
}
if ($#temp != -1) {
    $avgt=&AVG(@temp);
    $stdt=&STD(@temprms);
}
if ($#press != -1) {
    $avgpr=&AVG(@press);
    $stdpr=&STD(@pressrms);
}
if ($#den != -1)  {
    $avgd=&AVG(@den);
    $stdd=&STD(@denrms);
}

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

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

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";
}
