#!/bin/sh
#
# burstareas - calculate area under curve for bursts in run
#
# Usage:  burstareas [-c wfnum] [-d cols] [-a] [-f c] [-h] runfile ...
#
# where:  -c wfnum	specifies the waveform number for the marked up bursts
#			or a list of waveform numbers separated by commas
#			(default is 0)
#	  -d cols	specifies the data columns to be included in the output,
#			by letter name for each column: S=start, E=end, B=burst
#			duration, C=cycle duration, M=mean amplitude, A=area,
#			P=peak amplitude, L=LDP amplitude
#			(default is SEMA, for start, end, mean, area)
#	  -a		specifies that peak or LDP amplitude should be measured
#			in the active phase only, ignoring samples between the
#			end of one burst and the start of the next one
#	  -f c		specifies an alternate field separator "c" to be used
#			instead of the default comma ","
#	  -h		specifies that headings should appear above the columns
#			and run file names appear above those column headings
#			(default is to output only the numbers)
#	  -m		specifies that multiple runs should be merged into
#			multiple output columns
#	  runfile	specifies one or more run file names to be measured
#			(no default, runfile must be specified)
#
# Output will, by default, be of the form:
#  Start,End,Mean-ampl.,Area
# but other columns can be specified using the -d option as shown above.
#
# The start and end times indicate where each burst occurred in the run.
# The cycle and burst durations are calculated from the start and end values,
# with burst duration as end-start, and cycle duration as next-current start.
# For the last burst, the cycle duration is given as the burst duration, as
# there is no next start time to use for this calculation.  The time units are
# as selected in the analysis parameters for the run (typically seconds or ms,
# which is the default).  The mean-amplitude will be as calibrated or as
# selected in the analysis parameters (typically mV), and the area will be as
# a product of the time and amplitude units (typically mV x s or mV x ms).
#
# The peak amplitude is determined as a peak to peak value within the entire
# cycle for each burst, i.e. maximum - minumum level from the start of the
# burst to the start of the next burst (or end of the last burst).  Because
# the cycle duration and peak amplitude measurements depend on whole cycles,
# you may want to ignore the value given for these at the last burst in any
# given waveform, unless you're only using the active phase with the -a option.
#
# E.g.:  burstareas -c 7,8 -d CBPA aojedro4damp02
#
# Copyright (c) 2005-2019, Gilles Detillieux, Spinal Cord Research Centre,
# University of Manitoba.  All Rights Reserved.
#

cwfnum=0
datacols=SEMA
sep=,
headings=0
multirun=0
activeonly=0
T=/tmp/baf$$
while :
do
	case "$1" in
	-\?|-help|--help)	sed -n '3,/^# Univ/s/^#/ /p' "$0"; exit ;;
	-debug|--debug)	shift; T=baf.out. ;;
	-c)	shift; cwfnum="$1"; shift ;;
	-c[0-9]*)	cwfnum=`expr "x$1" : 'x-c\(.*\)'`; shift ;;
	-d)	shift; datacols="$1"; shift ;;
	-d[A-Za-z]*)	datacols=`expr "x$1" : 'x-d\(.*\)'`; shift ;;
	-f)	shift; sep="$1"; shift ;;
	-f?*)	sep=`expr "x$1" : 'x-f\(.*\)'`; shift ;;
	-h)	headings=1; shift ;;
	-m)	multirun=1; shift ;;
	-a)	activeonly=1; shift ;;
	-*)	set --; break ;;
	*)	break ;;
	esac
done
ascript=${T}a
diags=${T}b
anafile=${T}c
csvfile1=${T}d
csvfile2=${T}e
resfile=${T}f

case "$#" in
0)	echo "Usage:  burstareas [-c wfnum] [-d cols] [-a] [-f c] [-h] runfile ...
	or burstareas --help	for detailed usage information" >&2; exit 1 ;;
esac

case "$cwfnum" in
[0-9]*)	;;
*)	echo "$0: Invalid number for cycle waveform (with marked bursts): -c $cwfnum" >&2
	exit 1
	;;
esac

case "$datacols" in
*[^SEBCMAPLsebcmapl]*)
	echo "$0: Invalid letter for data column (must be one of SEBCMAPL): -d $datacols" >&2
	exit 1
	;;
esac

sedsep=`echo "$sep" | sed 's/&/\\&/g'`
datavars=`echo "$datacols" | sed 's/[A-Za-z]/\$&,/g;
				  s/\<[Ss],/start,/; s/\<[Ee],/end,/;
				  s/\<[Bb],/bdur,/; s/\<[Cc],/cdur,/;
				  s/\<[Mm],/mean,/; s/\<[Aa],/area,/;
				  s/\<[Pp],/peak,/; s/\<[Ll],/ldp,/; s/,$//;'"
				  s/,/$sedsep/g"`
hdrseps=`echo "$datacols" | sed "s/[A-Za-z]/,/g; s/^,//; s/,/$sedsep/g"`

case "${T}" in
/tmp/*)	trap "rm -f ${T}[a-f]" 0		# cleanup on exit
	trap "exit 1" 1 2 3 15			# exit, & cleanup, if killed
	;;
esac

IFS="$IFS,"
results=0
numruns=$#
test $multirun -gt 0 && multirun=$numruns
numwfs=`echo "$cwfnum" | tr ',' ' ' | wc -w`
test $multirun -gt 1 && numwfs=`expr $numwfs \* $multirun`
#test $numwfs -le 1 && hdrseps=

alldatavars="$datavars"
test $numwfs -gt 1 && alldatavars="\$lineno$sep$datavars"
test $numwfs -eq 1 -a -w /dev/stdout && csvfile2=/dev/stdout

mrgdatavars="$alldatavars"
test $multirun -gt 1 -a $numwfs -gt 1 && : > "$csvfile1"

#echo "multirun=$multirun, numwfs=$numwfs, numruns=$numruns, csvfile1=$csvfile1, csvfile2=$csvfile2, datacols='$datacols', datavars='$datavars', hdrseps='$hdrseps'" >&2

for run
do
    test $# -gt 1 && echo "Analysing $run..." >&2
    case "$headings" in
    1)	
	rfile=`echo "$run" | sed 's/\.frm$//'`
	tdesc=`head -1 "$rfile.txt" 2>/dev/null`
	test -n "$tdesc" && tdesc=": $tdesc"
#	echo "\"$run$tdesc\""
	fln=
	test $numwfs -gt 1 && fln="-1$sep"
	;;
    esac
    test $multirun -le 1 && mrgdatavars="$alldatavars"
    test $multirun -le 1 -a $numwfs -gt 1 && : > "$csvfile1"
    for wfnum in $cwfnum
    do
	#echo "$run:"
	sysvecho "w$wfnum\nec/dev/stdout\nyqqqyn" |
	    TERM=dumb DISPLAY= analysis "$run" 2>/dev/null |
#	    sed -n 's/^\([-0-9.e+]*\), *\([-0-9.e+]*\) *$/\1 \2/p' |
	    awk -F, '
		/^[-0-9.e+]*, *[-0-9.e+]* *$/ {
			if (s != "")
				printf("%d %s %s %g %g\n", ++n, s, e, e-s, $1-s)
			s = $1
			e = $2
		}
		END {
			if (s != "")
				printf("%d %s %s %g %g\n", ++n, s, e, e-s, e-s)
		}
	    ' |
	    (fresults=0
	     case "$headings" in
	     1)	starthdr="\"Start $wfnum\""
		endhdr="\"End $wfnum\""
		bdurhdr="\"BurstDur $wfnum\""
		cdurhdr="\"CycleDur $wfnum\""
		meanhdr="\"MeanAmpl $wfnum\""
		areahdr="\"Area $wfnum\""
		peakhdr="\"PeakAmpl $wfnum\""
		ldphdr="\"LdpAmpl $wfnum\""
		linenohdr="0"
		echo "$fln\"$rfile$tdesc\"$hdrseps"
		datahdrs=`echo "$alldatavars$sep" | sed "s/$sep/hdr$sedsep/g; s/$sep\$//"`
		eval "echo \"$datahdrs\""
		;;
	     esac
	     while read lineno start end bdur cdur
	     do
#		sysvecho "$start,$end,\c"
		cat <<! > $ascript
agwva srs$start
e$end
qcw-1
qgnn r0
b1
qlwn$wfnum
rlmin
umax
qqqdsay qtay sn qqq g sdsan yl0
qqnmean ampl: y
qq gb
qyn
!

		if TERM=dumb DISPLAY= analysis "$run" < $ascript > $anafile 2> $diags
		then
			mean=`sed -n 's/^.*mean ampl: *//p' $anafile`
			[ -z "$mean" ] && mean=0
			area=`sed -n 's/^Area under mean curve: *//p' $anafile`
			if [ -z "$area" ]
			then
				area=0
			else
				results=`expr $results + 1`
			fi
		else
			mean=0
			area=`sed -n -e 's/FATAL ERROR: *\(.*\)/"analysis: \1"/p' $diags`
			case "$datavars" in
			*area*)	;;
			*)	mean="$area" ;;	# get message out there...
			esac
			#sed -n -e 's/FATAL ERROR: /analysis: /p' $diags >&2
			#echo "$0: analysis failed!" >&2
			#echo
		fi
		peak=0
		case "$datavars" in
		*peak*)
		    setdur="$cdur"
		    test "$setdur" = "0" && setdur="$bdur"
		    test "$activeonly" = "1" && setdur="$bdur"
		    # repeat with full cycle & lots of bins for effectively
		    # raw peak-to-peak amplitude calculation
		    cat <<! > $ascript
agwva srs$start
rl$setdur
qqcw-1
qgnn r0
b10000
qlwn$wfnum
rlmin
umax
qqqdsay qtay sn qqq g sdsan yl0
qqnmean ampl: y
qq gb
qyn
!
		    if TERM=dumb DISPLAY= analysis "$run" < $ascript > $anafile 2> $diags
		    then
			peak=`sed -n 's/^.*Amplitude: *\([-0-9e.+]*\) *[A-Za-z\/]*/\1/p' $anafile`
			[ -z "$peak" ] && peak=0
		    else
			peak=`sed -n -e 's/FATAL ERROR: *\(.*\)/"analysis: \1"/p' $diags`
		    fi
		    ;;
		esac
		ldp=0
		case "$datavars" in
		*ldp*)
		    setdur="$cdur"
		    test "$setdur" = "0" && setdur="$bdur"
		    test "$activeonly" = "1" && setdur="$bdur"
		    # repeat with full cycle for raw LDP amplitude calculation
		    cat <<! > $ascript
agwl srs$start
rl$setdur
qqcw-1
qgnn r0
b1
qlwn$wfnum
w30ms
rlmin
umax
qqqdsay qtay sn qqapn qq g sdsan yl0
qqnldp ampl: y
qq gb
qyn
!
		    if TERM=dumb DISPLAY= analysis "$run" < $ascript > $anafile 2> $diags
		    then
			ldp=`sed -n 's/^.*ldp ampl: *\([-0-9e.+]*\) */\1/p' $anafile`
			[ -z "$ldp" ] && ldp=0
		    else
			ldp=`sed -n -e 's/FATAL ERROR: *\(.*\)/"analysis: \1"/p' $diags`
		    fi
		    ;;
		esac
#		echo "$start,$end,$mean,$area"
		eval "echo \"$alldatavars\""
		fresults=`expr $fresults + 1`
	     done
	     echo "$results" > "$resfile"
	     test "$fresults" -gt 0 ||
		echo "No bursts found on W.F. $wfnum in $run" >&2
	    ) > "$csvfile2"
	rfile= tdesc=
#	if [ $numwfs -gt 1 -a -s "$csvfile2" ]
	if [ $numwfs -gt 1 ]
	then
	    if [ -e "$csvfile1" -a -s "$csvfile1" ]
	    then
		#echo "merging $csvfile1 and $csvfile2..." >&2
		#head -4 $csvfile1 $csvfile2 >&2
		start= end= bdur= cdur= mean= area= peak= ldp=
		nl1=`sed -n '$s/[^0-9].*//p' < "$csvfile1"`
		test -z "$nl1" -a $headings -gt 0 && nl1=-2
		test -z "$nl1" && nl1=0
		nl2=`sed -n '$s/[^0-9].*//p' < "$csvfile2"`
		test -z "$nl2" -a $headings -gt 0 && nl2=-2
		test -z "$nl2" && nl2=0
		#echo "$csvfile1 has $nl1 lines and $csvfile2 has $nl2 lines..." >&2
		while [ $nl1 -lt $nl2 ]
		do
		    nl1=`expr $nl1 + 1`
		    lineno=$nl1
		    eval "echo \"$mrgdatavars\"" >> "$csvfile1"
		done
		while [ $nl1 -gt $nl2 ]
		do
		    nl2=`expr $nl2 + 1`
		    lineno=$nl2
		    eval "echo \"$alldatavars\"" >> "$csvfile2"
		done
		join -j 1 -t "$sep" "$csvfile1" "$csvfile2" > "$anafile"
		cat "$anafile" > "$csvfile1"
		mrgdatavars="$mrgdatavars$sep$datavars"
	    else
		#echo "empty $csvfile1 replaced by $csvfile2..." >&2
		mv "$csvfile2" "$csvfile1"
	    fi
	elif [ $numwfs -eq 1 -a "$csvfile2" != /dev/stdout ]
	then
	    # handle rare case where /dev/stdout not writable, e.g. using "su"
	    cat "$csvfile2"
	fi
	results=`cat "$resfile" 2>/dev/null`
    done
    test $multirun -le 1 -a $numwfs -gt 1 -a -s "$csvfile1" &&
	sed "s/^-*[0-9]*$sep *//" "$csvfile1"
    numruns=`expr $numruns - 1`
    test $numruns -gt 0 && echo ""
done

test $multirun -gt 1 -a $numwfs -gt 1 -a -s "$csvfile1" &&
	sed "s/^-*[0-9]*$sep *//" "$csvfile1"

results=`cat "$resfile" 2>/dev/null`
test -n "$results" || exit 2
test "$results" -gt 0 || exit 2
