593 lines (527 with data), 13.9 kB
#! /bin/sh
# plt_rrs Joe Mietus Oct 7 2008
# plt_rrs
USAGE="$0 [options] -R rrfile | record annotator [start [end]]
Plot RR intervals or RR interval heart rates
options :
[-P 2|4|8|16|24|32] : plot 2, 4, 8, 16, 24 or 32 hours per page
(default: scale page length to data length)
[-R rrfile] : RR interval file : time (sec), interval
[-N] : plot NN intervals instead of RR intervals
[-H] : plot RR/NN interval heart rate
[-F \"filt hwin\"] : filter intervals, plot filtered data
[-f \"filt hwin\"] : filter intervals
[-p] : plot points
[-I c|h|m] : input time format: hh::mm:ss, hours, minutes (default: seconds)
[-m] : RR intervals in msec
[-y \"ymin ymax\"] : y axis limits
[-o] : output postscript
"
DATA=Intervals
YLABEL="RR (sec)"
while getopts P:R:NHF:f:pI:my:o c
do
case $c in
P) PAGELEN=$OPTARG ;;
R) RRFILE=$OPTARG ;;
N) NFLAG='-a N -r'
YLABEL="NN (sec)" ;;
H) HRFLAG=1
DATA="Interval Heart Rate"
YLABEL="HR (bpm)" ;;
F) FILT=$OPTARG
PLTFILT=1 ;;
f) FILT=$OPTARG ;;
p) PPLT=1 ;;
I) TIME=$OPTARG ;;
m) MFLAG=1 ;;
y) YLIMS=$OPTARG ;;
o) PS=-ps ;;
\?) echo "$USAGE"
exit 1;;
esac
done
shift `expr $OPTIND - 1`
if test "$RRFILE"
then
if test ! -r "$RRFILE"
then
echo "$0 : Can't open $RRFILE"
exit 1
fi
FORM=`head -1 $RRFILE |
awk 'NF>3 {printf "bad"}
NF==3 || NF==2 || NF==1 \
{if($1~/[0-9:.]+/) \
{{if($1~/[^0-9:.]+/) printf "bad"}; printf "N1 "}
else printf "A1 "}
NF==3 || NF==2 \
{if($2~/[0-9:.]+/) \
{{if($2~/[^0-9:.]+/) printf "bad"}; printf "N2 "}
else printf "A2 "}
NF==3 \
{if($3~/[0-9\.]+/) \
{{if($3~/[^0-9:.]+/) printf "bad"}; printf "N3 "}
else printf "A3 "}
{printf "\n"}'` >/dev/null
NF=`echo $FORM | wc -w`
F1=`echo $FORM | awk '{print $1}'`
F2=`echo $FORM | awk '{print $2}'`
F3=`echo $FORM | awk '{print $3}'`
if test $NF -eq 3 -a "$F1" = N1 -a "$F2" = N2 -a "$F3" = A3
then :
elif test $NF -eq 2 -a "$F1" = N1 -a "$F2" = N2
then
NOANN=1
elif test $NF -eq 2 -a "$F1" = N1 -a "$F2" = A2
then
TFLAG=1
elif test $NF -eq 1 -a "$F1" = N1
then
NOANN=1
TFLAG=1
else
echo "$RRFILE : bad input format"
exit 1
fi
if test "$NOANN"
then
echo "$0 : No beat labels"
unset NFLAG
fi
else
if test $# -lt 2
then
echo "$USAGE"
exit 1
fi
REC=$1
ANN=$2
if test ! "`wfdbwhich $REC.$ANN 2>/dev/null`"
then
echo "$0 : can't read annotator $ANN for record $REC"
exit 1
fi
shift 2
fi
START=$1
END=$2
if test "$PS"
then
PTERM=lw
export PTERM
else
xpltwin -g 720x940
fi
if test ! "$START" -o "$START" = "-"
then
START=00:00:00
fi
STARTSEC=`seconds $START`
if test "$STARTSEC" -eq -1
then
echo "$0 : bad start time : $START"
exit 1
fi
START=`hours $STARTSEC`
if test "$END"
then
ENDSEC=`seconds $END`
if test $STARTSEC -gt $ENDSEC
then
echo "$0: start time greater than end time"
exit 1
fi
fi
if test "$PAGELEN" != 2 -a "$PAGELEN" != 4 -a "$PAGELEN" != 8 -a \
"$PAGELEN" != 16 -a "$PAGELEN" != 24 -a "$PAGELEN" != 32
then PAGELEN=s
fi
if test ! "$YLIMS"
then
if test "$HRFLAG"
then YLIMS="0 150"
else YLIMS="0 2.0"
fi
elif test `echo $YLIMS | wc -w` -ne 2
then
echo "$0 : [-y \"ymin ymax\"]"
exit 1
fi
(
if test "$RRFILE"
then
cat $RRFILE |
(
if test "$TFLAG"
then awk '{T+=$1}; {printf "%.3f %s\n", T, $0}'
else cat
fi
) |
(
if test "$MFLAG" -a "$TFLAG"
then awk '{$1/=1000; $2/=1000; print}'
elif test "$MFLAG"
then awk '{$2/=1000; print}'
else cat
fi
) |
(
if test "$TIME" = c
then
sed 's/[0-9:.][0-9:.]* /&: /' |
awk -F: 'NF==2 {print $1, $2}
NF==3 {print $1*60+$2, $3}
NF==4 {print $1*3600+$2*60+$3, $4}'
elif test "$TIME" = h
then
awk '{$1*=3600; print}'
elif test "$TIME" = m
then
awk '{$1*=60; print}'
else
cat
fi
) |
(
if test "$END"
then
awk "\$1 >= $STARTSEC && \$1 <= $ENDSEC && \$2!=0 {print}
\$1 > $ENDSEC {exit}"
else
awk "\$1 >= $STARTSEC && \$2!=0 {print}"
fi
) |
(
if test "$NFLAG"
then
awk '{RCNT++}
LAST=="N" && $3=="N" {print; NCNT++}
{LAST = $3}
END {printf "NN : RR = %d : %d = %.3f\n", \
NCNT, RCNT, NCNT/RCNT > "foo.n0"}'
else
cat
fi
)
else
rrlist $ANN $REC -f $START ${END:+-t} $END $NFLAG -s 2>foo.n0
fi
) | awk "{print \$1, \$2}" |
(
if test "$HRFLAG"
then awk '{$2 = 60/$2; print}'
else cat
fi
) |
(
if test "$FILT"
then filt $FILT -p foo.exc -n 2>foo.n1
else cat
fi
) |
awk '{print $1/3600, $2}' >foo.dat
if test $PAGELEN = s
then
DATSTART=`head -1 foo.dat | awk '{print $1}'`
DATEND=`tail -1 foo.dat | awk '{print $1}'`
PAGELEN=`echo $DATSTART $DATEND |
awk '{LEN=$2-$1}
LEN<=2 {print 2; exit}
LEN<=4 {print 4; exit}
LEN<=4 {print 4; exit}
LEN<=8 {print 8; exit}
LEN<=16 {print 16; exit}
LEN<=24 {print 24; exit}
LEN<=32 {print 32; exit}'`
fi
LINELEN=`echo "scale=2; $PAGELEN / 8" | bc`
if test $PAGELEN -eq 2
then
XTIC=`echo "1 / 60" | bc -l`
XMIN0=`echo $START |
sed 's/^.:..$/0&/
s/^..:..$/0:&/
s/:/ /g' |
awk '{if($2<15) $2=0;
if($2>=15 && $2<30) $2=0.25;
if($2>=30 && $2<45) $2=0.5;
if($2>=45) $2=0.75;
print $1+$2}'`
elif test $PAGELEN -eq 4
then
XTIC=`echo "5 / 60" | bc -l`
XMIN0=`echo $START |
sed 's/^.:..$/0&/
s/^..:..$/0:&/
s/:/ /g' |
awk '{if($2<30) $2=0; if($2>=30) $2=0.5; print $1+$2}'`
elif test $PAGELEN -eq 8
then
XTIC=`echo "5 / 60" | bc -l`
XMIN0=`echo $START |
sed 's/^.:..$/0&/
s/^..:..$/0:&/
s/:.*//'`
elif test $PAGELEN -eq 16 -o $PAGELEN -eq 24 -o $PAGELEN -eq 32
then
XTIC=`echo "15 / 60" | bc -l`
XMIN0=`echo $START |
sed 's/^.:..$/0&/
s/^..:..$/0:&/
s/:.*//'`
fi
XMAX7=`echo "scale=2; $XMIN0 + $PAGELEN" | bc`
X0=0.065
X1=0.965
YMIN=`echo $YLIMS | awk '{print $1}'`
YMAX=`echo $YLIMS | awk '{print $2}'`
if test "$NFLAG"
then
DATA="NN $DATA"
NRR0=`awk '{print $7}' foo.n0`
NRR1=`awk '{print $5}' foo.n0`
else
DATA="RR $DATA"
fi
if test "$FILT"
then
NRR1=`awk '{print $7}' foo.n1`
NRR2=`awk '{print $5}' foo.n1`
NFILT=`cat foo.exc | wc -l`
fi
if test "$NFLAG" -a "$FILT"
then
RATIO=`echo "$NRR2 $NRR1 $NRR0" |
awk '{printf "Filt : NN : RR = %d : %d : %d = %.3f : %.3f = %.3f\n", \
$1, $2, $3, $1/$2, $2/$3, $1/$3}'`
EXCLUDED=`echo "$NFILT $NRR1 $NRR0" |
awk '{printf "[%d Filtered, %d non-NN]\n", $1, $3-$2}'`
elif test "$NFLAG" -a ! "$FILT"
then
RATIO=`echo "$NRR1 $NRR0" |
awk '{printf "NN : RR = %d : %d = %.3f\n", $1, $2, $1/$2}'`
EXCLUDED=`echo "$NRR1 $NRR0" |
awk '{printf "[%d non-NN]\n", $2-$1}'`
elif test "$FILT" -a ! "$NFLAG"
then
RATIO=`echo "$NRR2 $NRR1" |
awk '{printf "Filt : RR = %d : %d = %.3f\n", $1, $2, $1/$2}'`
EXCLUDED=`echo "$NFILT" |
awk '{printf "[%d Filtered]\n", $1}'`
fi
if test "$FILT"
then PROG="filt $FILT"
fi
if test "$PROG"
then PROG="($PROG)"
fi
if test "$PPLT"
then
P1='p 0,1S5(P2)'
P2='p 0,1S0(P5)'
else
P1='p (W0)'
P2='p 0,1S5(P5)'
fi
awk "\$1>=$XMIN0 && \$1<=$XMAX7 {print}
\$1>$XMAX7 {print \$1 >\"foo.next\"; exit}" <foo.dat >foo.rr
PAGE=0
while test -s foo.rr -o -s foo.next
do
PAGE=`expr $PAGE + 1`
XMAX0=`echo "scale=2; $XMIN0 + $LINELEN" | bc`
XMIN1=$XMAX0
XMAX1=`echo "scale=2; $XMIN1 + $LINELEN" | bc`
XMIN2=$XMAX1
XMAX2=`echo "scale=2; $XMIN2 + $LINELEN" | bc`
XMIN3=$XMAX2
XMAX3=`echo "scale=2; $XMIN3 + $LINELEN" | bc`
XMIN4=$XMAX3
XMAX4=`echo "scale=2; $XMIN4 + $LINELEN" | bc`
XMIN5=$XMAX4
XMAX5=`echo "scale=2; $XMIN5 + $LINELEN" | bc`
XMIN6=$XMAX5
XMAX6=`echo "scale=2; $XMIN6 + $LINELEN" | bc`
XMIN7=$XMAX6
XMIN=$XMIN0
XMAX=$XMAX0
awk "{if(\$2<$YMIN) \$2=$YMIN; if(\$2>$YMAX) \$2=$YMAX}
\$1>=$XMIN0 && \$1<=$XMAX0 {print >\"foo.rr0\"}
\$1>=$XMIN1 && \$1<=$XMAX1 {print >\"foo.rr1\"}
\$1>=$XMIN2 && \$1<=$XMAX2 {print >\"foo.rr2\"}
\$1>=$XMIN3 && \$1<=$XMAX3 {print >\"foo.rr3\"}
\$1>=$XMIN4 && \$1<=$XMAX4 {print >\"foo.rr4\"}
\$1>=$XMIN5 && \$1<=$XMAX5 {print >\"foo.rr5\"}
\$1>=$XMIN6 && \$1<=$XMAX6 {print >\"foo.rr6\"}
\$1>=$XMIN7 && \$1<=$XMAX7 {print >\"foo.rr7\"}
\$1>=$XMAX7 {exit}" <foo.rr
if test "$PLTFILT"
then
awk "{\$1/=3600}
{if(\$2<$YMIN) \$2=$YMIN; if(\$2>$YMAX) \$2=$YMAX}
\$1>=$XMIN0 && \$1<=$XMAX0 {print >\"foo.exc0\"}
\$1>=$XMIN1 && \$1<=$XMAX1 {print >\"foo.exc1\"}
\$1>=$XMIN2 && \$1<=$XMAX2 {print >\"foo.exc2\"}
\$1>=$XMIN3 && \$1<=$XMAX3 {print >\"foo.exc3\"}
\$1>=$XMIN4 && \$1<=$XMAX4 {print >\"foo.exc4\"}
\$1>=$XMIN5 && \$1<=$XMAX5 {print >\"foo.exc5\"}
\$1>=$XMIN6 && \$1<=$XMAX6 {print >\"foo.exc6\"}
\$1>=$XMIN7 && \$1<=$XMAX7 {print >\"foo.exc7\"}
\$1>=$XMAX7 {exit}" <foo.exc
fi
TITLE1="${RRFILE:-$REC $ANN} ($START) : $DATA"
if test "$PAGE" -eq 1
then
if test "$PROG"
then
TITLE2="$PROG"
TITLE3="$RATIO $EXCLUDED"
else
TITLE2="$RATIO $EXCLUDED"
fi
else
TITLE2="$PROG"
TITLE3=""
fi
( plt -wm 0 -F"
t
L (P14) .5 1.005 CT $TITLE1
L (P11) .5 0.980 CT $TITLE2
L (P11) .5 0.955 CT $TITLE3
s f"
for i in 0 1 2 3 4 5 6 7
do
if test -s foo.rr$i
then
Y0=`echo "scale=4; 0.845 - ($i * 0.114)" | bc`
Y1=`echo "scale=4; 0.925 - ($i * 0.114)" | bc`
if test $PAGELEN -eq 2
then
echo $XMIN |
sed 's/^[0-9][0-9]*$/&.00/
s/^\./0&/
s/\./ &/' |
awk '$2==.00 {printf("xt %f %d:00:00\n", $1+$2, $1);
printf("xt %f %d:05:00\n", $1+$2+5/60, $1);
printf("xt %f %d:10:00\n", $1+$2+10/60, $1);
printf("xt %f %d:15:00\n", $1+$2+0.25, $1);
printf("xts %f\n", $1+1/60)}
$2==.25 {printf("xt %f %d:15:00\n", $1+$2, $1);
printf("xt %f %d:20:00\n", $1+$2+5/60, $1);
printf("xt %f %d:25:00\n", $1+$2+10/60, $1);
printf("xt %f %d:30:00\n", $1+$2+0.25, $1);
printf("xts %f\n", $1+16/60)}
$2==.50 {printf("xt %f %d:30:00\n", $1+$2, $1);
printf("xt %f %d:35:00\n", $1+$2+5/60, $1);
printf("xt %f %d:40:00\n", $1+$2+10/60, $1);
printf("xt %f %d:45:00\n", $1+$2+0.25, $1);
printf("xts %f\n", $1+31/60)}
$2==.75 {printf("xt %f %d:45:00\n", $1+$2, $1);
printf("xt %f %d:50:00\n", $1+$2+5/60, $1);
printf("xt %f %d:55:00\n", $1+$2+10/60, $1);
printf("xt %f %d:00:00\n", $1+$2+0.25, $1+1);
printf("xts %f\n", $1+46/60)}' >foo.xlabels
elif test $PAGELEN -eq 4
then
echo $XMIN |
sed 's/^[0-9][0-9]*$/&.00/
s/^\./0&/
s/\./ &/' |
awk '$2==.00 {printf("xt %f %d:00:00\n", $1+$2, $1);
printf("xt %f %d:15:00\n", $1+$2+0.25, $1);
printf("xt %f %d:30:00\n", $1+$2+0.50, $1)}
$2==.50 {printf("xt %f %d:30:00\n", $1+$2, $1);
printf("xt %f %d:45:00\n", $1+$2+0.25, $1);
printf("xt %f %d:00:00\n", $1+$2+0.50, $1+1)}' >foo.xlabels
elif test $PAGELEN -eq 8
then
echo $XMIN |
awk '{printf("xt %f %d:00:00\n", $1, $1);
printf("xt %f %d:15:00\n", $1+0.25, $1);
printf("xt %f %d:30:00\n", $1+0.50, $1);
printf("xt %f %d:45:00\n", $1+0.75, $1);
printf("xt %f %d:00:00\n", $1+1.00, $1+1)}' >foo.xlabels
elif test $PAGELEN -eq 16
then
echo $XMIN |
awk '{printf("xt %f %d:00:00\n", $1, $1);
printf("xt %f %d:30:00\n", $1+0.50, $1);
printf("xt %f %d:00:00\n", $1+1.00, $1+1);
printf("xt %f %d:30:00\n", $1+1.50, $1+1);
printf("xt %f %d:00:00\n", $1+2.00, $1+2)}' >foo.xlabels
elif test $PAGELEN -eq 24
then
echo $XMIN |
awk '{printf("xt %f %d:00:00\n", $1, $1);
printf("xt %f %d:00:00\n", $1+1, $1+1);
printf("xt %f %d:00:00\n", $1+2, $1+2);
printf("xt %f %d:00:00\n", $1+3, $1+3)}' >foo.xlabels
elif test $PAGELEN -eq 32
then
echo $XMIN |
awk '{printf("xt %f %d:00:00\n", $1, $1);
printf("xt %f %d:00:00\n", $1+1, $1+1);
printf("xt %f %d:00:00\n", $1+2, $1+2);
printf("xt %f %d:00:00\n", $1+3, $1+3);
printf("xt %f %d:00:00\n", $1+4, $1+4)}' >foo.xlabels
fi
plt foo.rr$i % -wms 1 -F"
W $X0 $Y0 $X1 $Y1
sf all P10
t
x
y
vl -.06 .5 - 1
$YLABEL
s X
s n
xa $XMIN $XMAX $XTIC
`cat foo.xlabels`
ya $YMIN $YMAX
$P1"
if test -s foo.exc$i
then
plt foo.exc$i -wms 1 -F"
W $X0 $Y0 $X1 $Y1
sf all P10
s t
s x
s y
xa $XMIN $XMAX
ya $YMIN $YMAX
$P2"
fi
fi
XMIN=$XMAX
XMAX=`echo "scale=2; $XMIN + $LINELEN" | bc`
done
if test -s foo.rr
then
plt : -wms 1 -F"
W $X0 $Y0 $X1 $Y1
sf all P10
s t
s x
s y
hl 0.5 -0.5 - 1
TIME (hours)
xa $XMIN $XMAX
ya $YMIN $YMAX"
fi
) |
(
if test "$PTERM"
then cat | lwcat -full $PS
else cat
fi
)
rm -f foo.rr? foo.exc? foo.xlabels foo.next
XMIN0=$XMAX7
XMAX7=`echo "scale=2; $XMAX7 + $PAGELEN" | bc`
STARTSEC=`echo "$XMIN0" | awk '{printf "%.0f\n", $1*3600}'`
START=`hours $STARTSEC`
awk "\$1>$XMIN0 && \$1<=$XMAX7 {print}
\$1>$XMAX7 {print \$1 >\"foo.next\"; exit}" <foo.dat >foo.rr
done
rm -f foo.dat foo.rr foo.n? foo.exc foo.next