#!/usr/bin/perl # # varf [] # # # Read command line parameters # $iopt=0; $Deriv = 0; $NoSort = 0; # # Parse options -s, -dn # while (substr($ARGV[$iopt],0,1) eq "-" && $iopt<=$#ARGV) { if (substr($ARGV[$iopt],1,1) eq "d") { $Deriv = substr($ARGV[0],2); } elsif (substr($ARGV[$iopt],1,1) eq "s") { $NoSort = 1; } $iopt++; } # if (substr($ARGV[0],0,1) eq "-") # { # $Deriv = substr($ARGV[0],2); # $iopt++; # } # Number of variables $NumVar = $#ARGV+1-$iopt-1; # # Test for no input # if ($NumVar<1) { print "\n"; print "varf -s -d [ ..]\n"; print "\n"; print "Scans input file for lines of the form\n"; print "\n"; print " value\n"; print "\n"; print "All values are collected into an array and then printed.\n"; print "The first variable is taken to be the independent variable,\n"; print "the remaining variables are considered dependent. The\n"; print "independent variable need not be in ascending order, this\n"; print "program will automatically sort them. (This is suppressed\n"; print "by the -s option).\n"; print "\n"; print "If is 1 or greater, then the n'th derivative\n"; print "is taken for the all variables with respect to the first.\n"; print "If only one variable is used, then n'th difference of that\n"; print "variable is used instead.\n"; print "\n"; print "This program is useful for getting data from text files for\n"; print "use with gnuplot. From gnuplot, you can use this command\n"; print "for example.\n"; print "\n"; print " plot '< varf -d1 compress.xmo A0 ENERGY' with lines\n"; print "\n"; exit; } $InputFileName = $ARGV[$iopt]; for ($ivar=0; $ivar<$NumVar; $ivar++) { $VarName[$ivar] = $ARGV[$iopt+$ivar+1]; $VarList{$VarName[$ivar]} = $ivar+1; } # # Sanity check # if ($Deriv<0) { $Deriv=0; } # # Open file # open (InputFile, "<" . $InputFileName); # # Read and store values # $NumNameReadOnce = 0; $NumList = 0; # # Scan each line in file # while ($line = ) { # # Remove trailing \n character # chop $line; # # Break line into "tokens" # @Token = split(/[ \t\n]+/,$line); # # if first token is blank, throw it away # if ($Token[0] eq "") { shift(@Token); } # # Is first token a requested name? # $ivar = $VarList{$Token[0]}; if ($ivar>0) { # # Store value associated with this name (the 2nd token) # $VarValue[$ivar-1] = $Token[1]; # # If this name read for first time, increment names found # if ($VarRead[$ivar-1]==0) { $NumNameReadOnce++; } # # Mark this name as read # $VarRead [$ivar-1] = 1; } # # If all names have been read at least once, # and last name of list has been read, # add values to list # print out values on one line # if ($NumNameReadOnce==$NumVar && $ivar==$NumVar) { $ilist = $NumVar * $NumList; for ($ivar=0; $ivar<$NumVar; $ivar++) { $Value[$ilist+$ivar] = $VarValue[$ivar]; } $NumList++; } } # # Close file # close InputFile; # # Sort data # for ($i=0; $i<$NumList; $i++) { $Index[$i] = $i*$NumVar; } if ($NoSort) { @SortIndex = @Index; } else { @SortIndex = sort {$Value[$a] <=> $Value[$b]} @Index; } # # Take derivative of 2nd, 3rd, n'th value wrt 1st value # for ($iderv=0; $iderv<$Deriv; $iderv++) { if ($NumVar==1) { &Deriv1(); } else { &DerivN(); } $NumList--; } # # Print values array # for ($ilist=0; $ilist<$NumList; $ilist++) { $i = $SortIndex[$ilist]; for ($ivar=0; $ivar<$NumVar; $ivar++) { print " ", $Value[$i+$ivar]; } printf "\n"; } #---------------------------------------------------------- #---------------------------------------------------------- sub Deriv1 { local ($i,$j,$ilist,$ivar); # # Loop through all data points # for ($ilist=0; $ilist<$NumList-1; $ilist++) { # # Calculate derivatives of dependent variables # $i = $SortIndex[$ilist]; $j = $SortIndex[$ilist+1]; $Value[$i] = ($Value[$j+1]-$Value[$i]); } } sub DerivN { local ($i,$j,$ilist,$ivar); # # Loop through all data points # for ($ilist=0; $ilist<$NumList-1; $ilist++) { $i = $SortIndex[$ilist]; $j = $SortIndex[$ilist+1]; # # Calculate span of independent variable # $Del = $Value[$j] - $Value[$i]; # # Reset independent value between neighboring points # $Value[$i] += $Del/2; # # Calculate derivatives of dependent variables # for ($ivar=1; $ivar<$NumVar; $ivar++) { if ($Del==0) { $Value[$i+$ivar] = 0; } else { $Value[$i+$ivar] = ($Value[$j+$ivar]-$Value[$i+$ivar])/$Del; } } } }