#!/bin/ksh
#set -x
#
##############################################################################
#                                                                            #
#  RCS Filename : plot_pfs,v
#  RCS Date     : 1996/08/12 09:29:32
#  RCS Revision : 1.8
#  RCS Author   : lamberts
#  RCS State    : V2_0_B
#                                                                            #
#  Authors: Stefan Lamberts                                                  #
#                                                                            #
##############################################################################

#
# Inputfile format
# OP MA NS ND C  I  O  M  EI II  BYTES MIN MAX AVG STD
# $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11   $12 $13 $14 $15
#

######################################################################
# Defaults
######################################################################


GNUPLOT="gnuplot"
GETDATA="gd"
GPPLOT="plot"

TYPE="avg"
WHAT="lat"
TITLE=""
OTERM="X11"
GPPAUSE="pause 1000 'Hit <Return> to continue'"
SCALE="log"
DATADIR="DATA"
INFILE=$DATADIR"/RESULTS"
OFILE="plot_pfs.output"
MINY="UNSET"
MAXY="UNSET"
MINX="UNSET"
MAXX="UNSET"

# Part of the range used for the graph
RANGEUSED=0.95
# X position of the key and the label in fraction of the X range
LABXPOS=0.3
# Y position of the label in fraction of the Y range
LABYPOS=0.95
# Y position of the key in fraction of the Y range
KEYYPOS=0.90

USAGE='Usage: \n'$0'\n
\t[-t {avg|min|max|erb}]\t# Default: '$TYPE'\n
\t[-w {lat|bdw}]\t\t# Latency | Bandwidth; Default: '$WHAT'\n
\t[-d <data directory>]\t# Default: '$DATADIR'\n
\t[-i <input>]\t\t# Inputfile; Default: '$INFILE'\n
\t[-n]\t\t\t# -n: Do not extract but use existing cache files\n
\t[-o <output>]\t\t# Outputfile\n
\t[-m {X11|eps|ps|fig}]\t# Output device; Default: '$OTERM'\n
\t[-s {log|lin|logx|logy}]\t# Scale of Axes; Default: '$SCALE'\n
\t[-p <plotfile>]\t# Append plot commands to <plotfile>
\t[-T <Title>]\t\t# Title header\n
\t[-x <Min x value>]\t# Minimal x value\n
\t[-X <Max x value>]\t# Maximal x value\n
\t[-y <Min y value>]\t# Minimal y value\n
\t[-Y <Max y value>]\t# Maximal y value\n
\t<DESCRIPTION>+\n\n
\tDESCRIPTION :== <OPERATION>:<CLNTSYNC>:<IODSYNC>:<O_SYNC>:<MODE>:<CLIENTS>:<NODE>:<MACHINES>\n
\tOPERATION   :== {CWR|CRD|IWRW|IRDW|IWRIOW|IRDIOW}\n
\tCLNTSYNC    :== {A|S}\t# Client asynchronous(A),synchronous(S)\n
\tIODSYNC     :== {A|S}\t# Iod asynchronous(A),synchronous(S)\n
\tO_SYNC      :== {T|F}\t# O_SYNC flag set(T), not set(F)\n
\tMODE        :== {U|L|R|S|G}\t# M_UNIX,M_LOG,M_RECORD,M_SYNC,M_GLOBAL\n
\tCLIENTS     :== <Number>\t# Number of Clients\n
\tNODE        :== <Number>|N|C\t# Nodenumber\n
\t\t\t\t\t\t\t# N : Average over all nodes per measurement\n
\t\t\t\t\t\t\t# C : Collective of all nodes\n
\tMACHINES    :== <Number>\t# Number of Machines used'

####################################################################
#
#	GET COMANDLINE-OPTIONS
#
####################################################################

while getopts "t:w:d:i:no:m:p:T:s:x:X:y:Y:" opt
do
	case $opt in
	t)	TYPE=$OPTARG;;
	w)	WHAT=$OPTARG;;
	d)	DATADIR=$OPTARG;;
	i)	INFILE=$OPTARG;;
	n)	DONTEXTRACT=T;;
	o)	OFILE=$OPTARG;;
	m)	OTERM=$OPTARG;;
	p)	PFILE=$OPTARG;;
	T)	TITLE=$OPTARG;;
	s)	SCALE=$OPTARG;;
	y)	MINY=$OPTARG;;
	Y)	MAXY=$OPTARG;;
	x)	MINX=$OPTARG;;
	X)	MAXX=$OPTARG;;
	*)	echo $USAGE; exit 1;;
	esac
done

shift `expr $OPTIND - 1`

if [[ $# -lt 1 ]]
then
	echo $USAGE; exit 1
fi

case $TYPE in
avg|min|max|erb);;
*)		echo $USAGE; exit 1;;
esac

case $WHAT in
bdw|lat);;
*)		echo $USAGE; exit 1;;
esac			

case $OTERM in
eps|fig|ps|X11);;
*)		echo $USAGE; exit 1;;
esac

case $SCALE in
log|lin|logx|logy);;
*)	echo $USAGE; exit 1;;
esac

if [[ ! -r "$INFILE" ]]
then
	echo "$0: Cannot read input file '$INFILE'."
	exit 1
fi

######################################################################
# Titles
######################################################################
unset OP CS IS OS MD CC ND MA
unset OPDIF CSDIF ISDIF OSDIF MDDIF CCDIF NDDIF MANECC MADIF

checkcommon () # OP CS IS OS MD CC ND MA
{	if [[ -z $OP ]];	then OP=$1
	elif [[ $OP != $1 ]];	then OPDIF=T
	fi

	if [[ -z $CS ]];	then CS=$2
	elif [[ $CS != $2 ]];	then CSDIF=T
	fi

	if [[ -z $IS ]];	then IS=$3
	elif [[ $IS != $3 ]];	then ISDIF=T
	fi

	if [[ -z $OS ]];	then OS=$4
	elif [[ $OS != $4 ]];	then OSDIF=T
	fi

	if [[ -z $MD ]];	then MD=$5
	elif [[ $MD != $5 ]];	then MDDIF=T
	fi

	if [[ -z $CC ]];	then CC=$6
	elif [[ $CC != $6 ]];	then CCDIF=T
	fi

	if [[ -z $ND ]];	then ND=$7
	elif [[ $ND != $7 ]];	then NDDIF=T
	fi

	if [[ $6 -ne $8 ]];	then MANECC=T; fi
	if [[ -z $MA ]];	then MA=$8
	elif [[ $MA != $8 ]];	then MADIF=T
	fi
}

ctitlehead ()
{	CTITLEHEAD=""
	if [[ -n $OPDIF ]];	then CTITLEHEAD="$CTITLEHEAD""Operation "; fi
	if [[ -n $CSDIF ]];	then CTITLEHEAD="$CTITLEHEAD""Clt "; fi
	if [[ -n $ISDIF ]];	then CTITLEHEAD="$CTITLEHEAD""Iod "; fi
	if [[ -n $OSDIF ]];	then CTITLEHEAD="$CTITLEHEAD""O_S "; fi
	if [[ -n $MDDIF ]];	then CTITLEHEAD="$CTITLEHEAD""Mode "; fi
	if [[ -n $CCDIF ]];	then CTITLEHEAD="$CTITLEHEAD""#Clt "; fi
	if [[ -n $NDDIF ]];	then CTITLEHEAD="$CTITLEHEAD""Node "; fi
	if [[ -n $MANECC && -n $MADIF ]]
	then	CTITLEHEAD="$CTITLEHEAD""#Mch"
	fi
}

ctitle () # OP CS IS OS MD CC ND MA 
{
	CTITLE=""
	if [[ -n $OPDIF ]]
	then	typeset -L9 CTE=$1
		CTITLE="$CTITLE$CTE "
	fi
	if [[ -n $CSDIF ]]
	then	case $2 in
		A)	CTITLE="$CTITLE""ASY ";;
		S)	CTITLE="$CTITLE""SYN ";;
		*)	CTITLE="$CTITLE""ERR ";;
		esac
	fi
	if [[ -n $ISDIF ]]
	then	case $3 in
		A)	CTITLE="$CTITLE""ASY ";;
		S)	CTITLE="$CTITLE""SYN ";;
		*)	CTITLE="$CTITLE""ERR ";;
		esac
	fi
	if [[ -n $OSDIF ]]
	then	case $4 in
		T)	CTITLE="$CTITLE""Yes ";;
		F)	CTITLE="$CTITLE""No  ";;
		*)	CTITLE="$CTITLE""ERR ";;
		esac
	fi
	if [[ -n $MDDIF ]]
	then	case $5 in
		G)	CTITLE="$CTITLE""GLOB ";;
		L)	CTITLE="$CTITLE""LOG  ";;
		R)	CTITLE="$CTITLE""REC  ";;
		S)	CTITLE="$CTITLE""SYNC ";;
		U)	CTITLE="$CTITLE""UNIX ";;
		*)	CTITLE="$CTITLE""ERR  ";;
		esac
	fi
	if [[ -n $CCDIF ]]
	then	typeset -R4 CTE=$6
		CTITLE="$CTITLE$CTE "
	fi
	if [[ -n $NDDIF ]]
	then	case $7 in
		C)	CTITLE="$CTITLE KUMU ";;
		N)	CTITLE="$CTITLE MITL ";;
		*)	typeset -R4 CTE=$7
			CTITLE="$CTITLE$CTE ";;
		esac
	fi
	if [[ -n $MANECC && -n $MADIF ]]
	then	typeset -R3 CTE=$8
		CTITLE="$CTITLE$CTE"
	fi
}

title ()
{
	TITLE=""
	case $TYPE in
	min)	TITLE="$TITLE Min.";;
	max)	TITLE="$TITLE Max.";;
	avg)	TITLE="$TITLE Mittl.";;
	erb)	TITLE="$TITLE Min./Mittl./Max.";;
	esac

	case $WHAT in
	bdw)	TITLE="$TITLE Bandbreite";;
	lat)	TITLE="$TITLE Dauer";;
	esac

	if [[ -z $NDDIF ]]
	then	case $ND in
		C)	TITLE="$TITLE(kumuliert)";;
		N)	TITLE="$TITLE(durchschn)";;
		*)	TITLE="$TITLE Node: $ND";;
		esac
	fi

	if [[ -z $OPDIF ]];	then TITLE="$TITLE $OP"; fi
	if [[ -z $CSDIF ]]
	then	case $CS in
		A)	TITLE="$TITLE; Clt: ASY";;
		S)	TITLE="$TITLE; Clt: SYN";;
		esac
	fi
	if [[ -z $ISDIF ]]
	then	case $IS in
		A)	TITLE="$TITLE; Iod: ASY";;
		S)	TITLE="$TITLE; Iod: SYN";;
		esac
	fi
	if [[ -z $OSDIF ]]
	then	case $OS in
		T)	TITLE="$TITLE; O_SYNC";;
#		F)	TITLE="$TITLE; O_SYNC: No";;
		esac
	fi
	if [[ -z $MDDIF ]]
	then	case $MD in
		G)	TITLE="$TITLE; Mode: G";;
		L)	TITLE="$TITLE; Mode: L";;
		R)	TITLE="$TITLE; Mode: R";;
		S)	TITLE="$TITLE; Mode: S";;
		U)	TITLE="$TITLE; Mode: U";;
		esac
	fi
	if [[ -z $CCDIF ]]
	then	TITLE="$TITLE; #Clt: $CC"
	fi
	if [[ -n $MANECC && -z $MADIF ]]
	then	TITLE="$TITLE; #Mch: $MA"
	fi

}	

######################################################################
# Generate Filename
######################################################################
fname () # OP CS IS OS MD CC ND MA
{
	typeset -Z2 MAFN=$8
	typeset -Z2 CCFN=$6
	
	echo $1:$2:$3:$4:$5:$CCFN:$7:$MAFN
}

######################################################################
# Generate data files and make plot command
######################################################################

if [[ "$DONTEXTRACT" != "T" ]]
then	$GETDATA -w $WHAT -d $DATADIR $* < $INFILE
fi


######################################################################
# Initialize and set title
######################################################################
for arg in $*
do	ARG=`echo $arg | sed -e 's/:/ /g'`
	FN="$DATADIR/$WHAT:"`fname $ARG`
	
	if [[ -r "$FN" ]]
	then	checkcommon $ARG
	fi
done

if [[ -z "$TITLE" ]]
then
	title
fi

ctitlehead

######################################################################
# Make plot command
######################################################################

FILES=""
FIRST="T"
for arg in $*
do	ARG=`echo $arg | sed -e 's/:/ /g'`
	FN="$DATADIR/$WHAT:"`fname $ARG`

	if [[ -r "$FN" ]]
	then	FILES="$FILES $FN"
		if [[ $FIRST = "T" ]]
		then	FIRST="F"
		else	GPPLOT=$GPPLOT","
		fi
		ctitle $ARG
		case $TYPE in
		avg) GPPLOT=$GPPLOT" '$FN' using 1:2 title '$CTITLE'";;
		min) GPPLOT=$GPPLOT" '$FN' using 1:3 title '$CTITLE'";;
		max) GPPLOT=$GPPLOT" '$FN' using 1:4 title '$CTITLE'";;
		erb) GPPLOT=$GPPLOT" '$FN' title '$CTITLE'";;
		esac
	else	echo "No data for $arg; Skipping"
	fi
	
done

if [[ -z "$FILES" ]]
then	echo "Nothing to plot"
	exit 0
fi


######################################################################
# Set min and max
######################################################################

if [[ $MINY = "UNSET" ]]
then MINY=`awk	'BEGIN{min = -1.0}
		{ if (("'$TYPE'" == "erb")||("'$TYPE'" == "min")) val = $3
		  else if ("'$TYPE'" == "max") val = $4
		  else val = $2
		  if ((min < 0.0)||(min > val)) min = val }
		END{print min}' $FILES`
fi

if [[ $MAXY = "UNSET" ]]
then MAXY=`awk	'BEGIN{max = -1.0}
		{ if (("'$TYPE'" == "erb")||("'$TYPE'" == "max")) val = $4
		  else if ("'$TYPE'" == "min") val = $3
		  else val = $2
		  if (max < val) max = val }
		END{print max}' $FILES`
fi

if [[ $MINX = "UNSET" ]]
then MINX=`awk	'BEGIN{min = -1.0}
		{ if ((min == -1.0)||(min > $1)) min = $1 }
		END{print min}' $FILES`
fi

if [[ $MAXX = "UNSET" ]]
then MAXX=` awk	'BEGIN{max = -1.0}
		{ if (max < $1) max = $1; }
		END{print max}' $FILES`
fi

######################################################################
# calculates ranges 
######################################################################
rangelin () # min max
{
	RMIN=`bc <<EOF
		scale=6
		$1-(((1-$RANGEUSED)/(2*$RANGEUSED))*($2-$1))
EOF`
	RMAX=`bc <<EOF
		scale=6
		(($2-$1)/$RANGEUSED)+$RMIN
EOF`
}

rangelog () # min max
{
	case $1 in
	0|-*)	echo "Logarithmic scale must be greater 0; Min is $1"; exit 1;;
	esac

	case $2 in
	0|-*)	echo "Logarithmic scale must be greater 0; Max is $2"; exit 1;;
	esac

	RMIN=`bc -l <<EOF
		scale=6
		e(l($1)-(((1-$RANGEUSED)/(2*$RANGEUSED))*(l($2)-l($1))))
EOF`
	RMAX=`bc -l <<EOF
		scale=6
		e(((l($2)-l($1))/$RANGEUSED)+l($RMIN))
EOF`
}

####################################################################
#
#	DEFAULT-SETTINGS FOR GNUPLOT
#
####################################################################

case $OTERM in
eps)	GPTERM="set term postscript eps"
	GPPAUSE="";;
fig)	GPTERM="set term fig"
	GPPAUSE="";;
ps)	GPTERM="set term postscript landscape"
	GPPAUSE="";;
X11)	GPTERM=""
	GPPAUSE="pause -1 'Hit <Return> to continue'";;
esac

case $OTERM in
eps|fig|ps)	GPOUTPUT="set output '$OFILE.$OTERM'";;
esac

case $TYPE in
avg|min|max)	GPSTYLE="set data style linespoints";;
erb)		GPSTYLE="set data style errorbars";;
esac

case $SCALE in
log)	XAXE=log
	YAXE=log;;
logx)	XAXE=log
	YAXE=lin;;
logy)	XAXE=lin
	YAXE=log;;
lin)	XAXE=lin
	YAXE=lin;;
esac

case $XAXE in
log)	rangelog $MINX $MAXX
	MINX=$RMIN
	MAXX=$RMAX
	GPSCALEX="set logscale x"
	LABX=`echo "scale=6;e(($MINX)+((l($MAXX)-l($MINX))*($LABXPOS)))"|bc -l`
	KEYX=$LABX;;
lin)	rangelin $MINX $MAXX
	MINX=$RMIN
	MAXX=$RMAX
	GPSCALEX="set nologscale x"
	LABX=`echo "scale=6;($MINX)+((($MAXX)-($MINX))*($LABXPOS))"|bc -l`
	KEYX=$LABX;;
esac

case $YAXE in
log)	rangelog $MINY $MAXY
	MINY=$RMIN
	MAXY=$RMAX
	GPSCALEY="set logscale y"
	LABY=`echo "scale=6;e(l($MINY)+((l($MAXY)-l($MINY))*($LABYPOS)))"|bc -l`
	KEYY=`echo "scale=6;e(l($MINY)+((l($MAXY)-l($MINY))*($KEYYPOS)))"|bc -l`
	;;
lin)	rangelin $MINY $MAXY
	MINY=$RMIN
	MAXY=$RMAX
	GPSCALEY="set nologscale y"
	LABY=`echo "scale=6;($MINY)+((($MAXY)-($MINY))*($LABYPOS))"|bc -l`
	KEYY=`echo "scale=6;($MINY)+((($MAXY)-($MINY))*($KEYYPOS))"|bc -l`
	;;
esac

GPYRANGE="set yrange [$MINY:$MAXY]"
GPXRANGE="set xrange [$MINX:$MAXX]"

GPGRID="set grid";

case $WHAT in
lat)	GPYLABEL="set ylabel '[s]'"
	GPYTICS="";;
bdw)	GPYLABEL="set ylabel '[Byte/s]'"
	case $YAXE in
	lin)	((trange = MAXY - MINY))
		((tics = 1))
		while [[ trange -gt 12 ]]
		do	((tics *= 2))
			((trange /= 2))
		done
		((tic = 0))
		while [[ $tic -lt $MINY ]]
		do	((tic += tics))
		done
		GPYTICS="set ytics ("
		firsttic=T
		while [[ $tic -lt $MAXY ]]
		do	if [[ $firsttic = T ]]
			then firsttic=F
			else GPYTICS="$GPYTICS, "
			fi
			if [[ $tic -lt 1024 ]]
			then	tlab=$tic
				tmag=""
			elif [[ $tic -lt 1048576 ]]
			then	tlab=`echo "scale=2; $tic/1024"|bc`
				tmag=k
			elif [[ $tic -lt 1073741824 ]]
			then	tlab=`echo "scale=2; $tic/1048576"|bc`
				tmag=M
			else	tlab=`echo "scale=2; $tic/1073741824"|bc`
				tmag=G
			fi
			tlab=`echo $tlab|sed -e 's/[.]00//' -e '/[.]/s/0*$//'`
			GPYTICS="$GPYTICS'$tlab$tmag' $tic"
			((tic += tics))
		done
		GPYTICS="$GPYTICS)";;
	log)	GPYTICS="set ytics ('1' 1,'4' 4,'16' 16,'64' 64,'256' 256,'1k' 1024,'4k' 4096,'16k' 16384,'64k' 65536,'256k' 262144,'1M' 1048576,'4M' 4194304,'16M' 16777216,'64M' 67108864,'256M' 268435456,'1G' 1073741824)";;
	esac;;
esac

GPXLABEL="set xlabel 'Datenmenge [Byte]'"
case $XAXE in
lin)	((trange = MAXX - MINX))
	((tics = 1))
	while [[ trange -gt 12 ]]
	do	((tics *= 2))
		((trange /= 2))
	done
	((tic = 0))
	while [[ $tic -lt $MINX ]]
	do	((tic += tics))
	done
	GPXTICS="set xtics ("
	firsttic=T
	while [[ $tic -lt $MAXX ]]
	do	if [[ $firsttic = T ]]
		then firsttic=F
		else GPXTICS="$GPXTICS, "
		fi
		if [[ $tic -lt 1024 ]]
		then	tlab=$tic
			tmag=""
		elif [[ $tic -lt 1048576 ]]
		then	tlab=`echo "scale=2; $tic/1024"|bc`
			tmag=k
		elif [[ $tic -lt 1073741824 ]]
		then	tlab=`echo "scale=2; $tic/1048576"|bc`
			tmag=M
		else	tlab=`echo "scale=2; $tic/1073741824"|bc`
			tmag=G
		fi
		tlab=`echo $tlab | sed -e 's/[.]00//' -e '/[.]/s/0*$//'`
		GPXTICS="$GPXTICS'$tlab$tmag' $tic"
		((tic += tics))
	done
	GPXTICS="$GPXTICS)";;
log)	GPXTICS="set xtics ('1' 1,'4' 4,'16' 16,'64' 64,'256' 256,'1k' 1024,'4k' 4096,'16k' 16384,'64k' 65536,'256k' 262144,'1M' 1048576,'2M' 2097152,'4M' 4194304)";;
esac

GPLABEL="set label 1 '$CTITLEHEAD' at $LABX,$LABY right"
GPKEY="set key $KEYX,$KEYY"

######################################################################
# Run gnuplot
######################################################################

cat > plot_pfs.plot <<EOF
$GPTERM
$GPOUTPUT
$GPSCALEX
$GPSCALEY
set title "$TITLE"
$GPSTYLE
$GPGRID
$GPLABEL
$GPXLABEL
$GPXTICS
$GPXRANGE
$GPYLABEL
$GPYTICS
$GPYRANGE
$GPKEY	
$GPPLOT
$GPPAUSE
EOF

######################################################################
# Wait for gnuplot to terminate
######################################################################

if [[ -z "$PFILE" ]]
then	$GNUPLOT plot_pfs.plot
else	cat plot_pfs.plot >> $PFILE
fi

exit 0
