#!/bin/sh
#
# avgspfrq - calculate average spike frequencies for last n spikes
#
# Usage:  avgspfrq [-n num] [-c wfnum] [-ct thresh] [-s wfnum] [-t thresh] [-h hyst] [-d] [-r st,en] runfile ...
#
# where:  -n num	specifies the number of spike intervals to average
#			at the end of a burst
#			(default is 3)
#	  -c wfnum	specifies waveform number for current injected
#			(default is 0)
#	  -ct thresh	specifies current threshold for burst detection
#			(default is automatic detection using mean level,
#			 or value previously set in waveform parameters)
#	  -s wfnum	specifies waveform number for spikes to measure
#			(default is 1)
#	  -t thresh	specifies spike threshold, as a differential
#			(default is 500)
#	  -h hyst	specifies spike hysteresis, as a 2nd differential
#			i.e. relative to threshold above
#			(default is 0 for no hysteresis)
#	  -d		specifies that spike triggering will not be on a
#			differential waveform, and threshold above will be
#			an actual waveform level
#	  -r st,en	specifies the start and end of the analysis range,
#			overriding the range determined from the injected
#			current waveform
#	  -r mult	specifies that multiple bursts of current will be
#			looked at on the injected current waveform, and each
#			burst will be processed and reported
#	  -r st,en,mult	specifies the start and end of the analysis range,
#			and specifies that multiple bursts in that range will
#			be analysed
#	  runfile	specifies one or more run file names to be measured
#			(no default, runfile must be specified)
#
# avgspfrq first looks at the injected current waveform, to determine the
# range of samples to be analyzed.  It then backs off the end point (when
# current is turned off) by 0.2 ms, to avoid spikes that are artifacts of
# the current being switched off.  It then analyses the intervals of the
# last n spikes on the spike waveform, and calculates the average.
#
# Output will be of the form:
# FF1450551.frm:  Average spike frequency (last 3 spikes from 30 to 555.6 ms):     29.6666    1894.624
# where the name before the first colon is the file name, and the two numbers
# after the second colon are the spike frequency in Hz and the injected current
# (if it can be measured).  The current is output in whatever units that
# waveform has been calibrated for.
#
# Copyright (c) 2005, Gilles Detillieux, Spinal Cord Research Centre,
# University of Manitoba.  All Rights Reserved.
#

nspikes=3 cwfnum=0 cthresh= swfnum=1 sthresh=500 hyst=0 diff=y range=
T=/tmp/asf$$
while :
do
	case "$1" in
	-\?|-help|--help)	sed -n '3,/^# Univ/s/^#/ /p' "$0"; exit ;;
	-debug|--debug)	shift; T=asf.out. ;;
	-n)	shift; nspikes="$1"; shift ;;
	-c)	shift; cwfnum="$1"; shift ;;
	-ct)	shift; cthresh="$1"; shift ;;
	-s)	shift; swfnum="$1"; shift ;;
	-t)	shift; sthresh="$1"; shift ;;
	-st)	shift; sthresh="$1"; shift ;;
	-h)	shift; hyst="$1"; shift ;;
	-d)	shift; diff=n ;;
	-r)	shift; range="$1"; shift ;;
	-*)	set --; break ;;
	*)	break ;;
	esac
done
ascript=${T}a
diags=${T}b
anafile=${T}c
rfile=${T}d

case "$#" in
0)	echo "Usage:  avgspfrq [-n num] [-c wfnum] [-ct thresh] [-s wfnum] [-t thresh] [-h hyst] [-d] [-r st,en] runfile ...
	or avgspfrq --help	for detailed usage information" >&2; exit 1 ;;
esac

case "$nspikes" in
[1-9]*)	;;
*)	echo "$0: Invalid number of spikes: -n $nspikes" >&2
	exit 1
	;;
esac

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

case "$swfnum" in
[0-9]*)	;;
*)	echo "$0: Invalid number for spike waveform: -s $swfnum" >&2
	exit 1
	;;
esac

case "$cthresh" in
"")	;;
[0-9]*|-[0-9]*)	cthresh="s$cthresh\n" ;;
*)	echo "$0: Invalid number for current threshold: -ct $cthresh" >&2
	exit 1
	;;
esac

case "$sthresh" in
[0-9]*|-[0-9]*)	;;
*)	echo "$0: Invalid number for spike threshold: -t $sthresh" >&2
	exit 1
	;;
esac

case "$hyst" in
[0-9]*|-[0-9]*)	;;
*)	echo "$0: Invalid number for spike hysteresis: -h $hyst" >&2
	exit 1
	;;
esac

start=0 end=max
range=`echo "$range" | tr -d ' '`
case "$range" in
""|[Mm][Uu][Ll]*|[Aa][Ll][Ll])
	;;
[0-9]*\,[0-9]* | [0-9]*\,[Mm][Aa][Xx]*)
	start=`echo "$range" | sed 's/^\([-0-9.e+]*\),.*/\1/'`
	end=`echo "$range" | sed 's/^[^,]*, *\([-0-9.e+MmAaXx]*\).*$/\1/'`
	case "$start,$end" in
	[0-9]*\,[0-9Mm]*)	;;
	*)	echo "$0: Invalid range specified: -r $range" >&2
		exit 1
		;;
	esac
	;;
*)	echo "$0: Invalid range specified: -r $range" >&2
	exit 1
	;;
esac

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

results=0
for run
do
    nbursts=1
    refstart=0
    prevcend=0
    case "$range" in
    ""|*[Mm][Uu][Ll]*)
	bursts=`sysvecho "w$cwfnum\nsas$start\ne$end\nqc${cthresh}vadqqqec/dev/stdout\nyqqnqyn" |
		TERM=dumb DISPLAY= analysis "$run" 2>/dev/null`
	nbursts=`echo "$bursts" | sed -n '2s/n = //p'`
	bindex=4
	crange=`echo "$bursts" | sed -n "${bindex}p"`
	start=`echo "$crange" | sed 's/^\([-0-9.e+]*\),.*/\1/'`
	cend=`echo "$crange" | sed 's/^[^,]*, *\([-0-9.e+]*\) *$/\1/'`
	case "$cend" in
	[0-9]*)	end=`sysvecho "scale=4\n$cend - 0.2" | bc 2>/dev/null` ;;
	*)	echo "$run:	No single current burst on W.F. $cwfnum"
		continue
		;;
	esac
	;;
    esac
    rm -f "$rfile".???
    copyrun "$run" "$rfile"
    # find first available W.F., preferably w/o having to erase one
    fwf=
    for dwfnum in 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 9999
    do
	if [ $dwfnum -ne $cwfnum -a $dwfnum -ne $swfnum ]
	then
		if [ ! -r "$rfile.w$dwfnum" ]
		then
			break
		fi
		if [ -z "$fwf" ]
		then
			fwf=$dwfnum
		fi
	fi
    done
    if [ $dwfnum -eq 9999 ]
    then
	dwfnum=$fwf
    fi
    while [ "$nbursts" -gt 0 ]
    do
	case "$range" in
	*[Mm][Uu][Ll]*)
		crange=`echo "$bursts" | sed -n "${bindex}p"`
		start=`echo "$crange" | sed 's/^\([-0-9.e+]*\),.*/\1/'`
		cend=`echo "$crange" | sed 's/^[^,]*, *\([-0-9.e+]*\) *$/\1/'`
		end=`sysvecho "scale=4\n$cend - 0.2" | bc 2>/dev/null`
		refstart=$prevcend
		prevcend=$cend
		if [ "$refstart" = 0 ]
		then
			# avoid incomplete first burst
			refstart=`sysvecho "scale=4\nh=($end-$start)/2\nr=0\nif($start>250 && $start>h)r=$start-h\nr" | bc 2>/dev/null`
		fi
		bindex=`expr "$bindex" + 1`
		nbursts=`expr "$nbursts" - 1`
		rm -f "$rfile".p$dwfnum
		;;
	*)
		nbursts=0
		;;
	esac
	: > $ascript
	if [ -r "$rfile.w$dwfnum" ]
	then
		sysvecho "me$dwfnum\nq\c" >> $ascript
	fi
	nlzdwfnum=`expr $dwfnum + 0`	# remove leading 0
	cat <<! >> $ascript
agasfrsrs$start
e$end
qcw-1
qswn$nlzdwfnum
ryqqmianqqgb$nspikes
qdn+ y\n
qqw$nlzdwfnum
sv$swfnum
${diff}ss$sthresh
e$hyst
qqqy
b
agwvaslwn$cwfnum
qqgb1
qdnPEAK y\n
qqb
srs$refstart
e$start
qdnREF y\n
qqb
qyn
!

	sysvecho "$run:\t\c"
	if TERM=dumb DISPLAY= analysis "$rfile" < $ascript > $anafile 2> $diags
	then
		frqs=`grep '^ *+ *[-0-9.e+]* *$' $anafile | tr -d '\012'`
		nfrqs=`grep '^ *+ *[-0-9.e+]* *$' $anafile | wc -l | tr -d ' '`
		if [ -z "$frqs" -o $nfrqs -le 0 ]
		then
			echo "No spike frequencies found for W.F. $swfnum from $start to $end ms"
			continue
		fi
		avg=`sysvecho "scale=4\n(0 $frqs ) / $nfrqs" | bc 2>/dev/null`
		pcurr=`sed -n -e 's/^ *PEAK *\([-0-9.e+]*\) *$/\1/p' $anafile | tr -d '\012'`
		rcurr=`sed -n -e 's/^ *REF *\([-0-9.e+]*\) *$/\1/p' $anafile | tr -d '\012'`
		if [ ! -z "$pcurr" -a ! -z "$rcurr" ]
		then
			curr=`sysvecho "scale=4\n$pcurr - $rcurr" | bc 2>/dev/null`
			curr="    $curr"
		fi
		echo "Average spike frequency (last $nfrqs spikes from $start to $end ms):     $avg$curr"
		if [ $nfrqs -ne "$nspikes" ]
		then
			echo "Warning: got only $nfrqs of $nspikes spikes"
		fi
		if [ -z "$pcurr" -o -z "$rcurr" ]
		then
			echo "Warning: Couldn't get current value from W.F. $cwfnum"
		fi
		results=`expr $results + 1`
	else
		sed -n -e "s/Spike W\.F\. # $nlzdwfnum/Spike W.F. # $swfnum/" \
			-e 's/FATAL ERROR: *//p' $diags
		#sed -n -e 's/FATAL ERROR: /analysis: /p' $diags >&2
		#echo "$0: analysis failed!" >&2
		#echo
	fi
    done
done

test "$results" -gt 0 || exit 2
