#! /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.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}" $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.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.rr done rm -f foo.dat foo.rr foo.n? foo.exc foo.next