/* file: plotstm.c G. Moody 24 March 1992 Last revised: 10 June 2005 ------------------------------------------------------------------------------- plotstm: Make a PostScript scatter plot of ST measurements from `epic' output Copyright (C) 1992-2005 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . You may contact the author by e-mail (wfdb@physionet.org) or postal mail (MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, please visit PhysioNet (http://www.physionet.org/). _______________________________________________________________________________ */ #include #include #ifdef __STDC__ #include #else extern void exit(); #endif #ifndef BSD # include #else /* for Berkeley UNIX only */ # include # define strchr index #endif /* The PostScript code below is the prolog for the scatter plot. Portions of this code were extracted from the output of `plt', a 2-D plotting package written by Paul Albrecht at MIT. */ char *prolog[] = { "%!", "save 100 dict begin /plotstm exch def", "/M {newpath PMTX transform moveto} def", "/N {PMTX dtransform rlineto} def", "/L {N currentpoint stroke moveto} def", "/T {/ang exch def /pos exch def M ang rotate /str exch def str stringwidth", " pop XOFF pos get mul YOFF pos get PS mul XYM 0.85 mul add rmoveto str show", " /XYM 0 def DMTX setmatrix} def", "/XT {/XYM XM neg def 3 0 T /XM 0 def} def", "/YT {/XYM YM def 7 90 T /YM 0 def} def", "/XN {/XM PS def 3 0 T} def", "/YN {-1 1 0 6 3 roll M /str exch def str stringwidth pop add /len exch def", " len mul .2 PS mul add mul PS -.37 mul rmoveto str show /YM len .2 PS mul", " add YM 2 copy lt {exch pop} {pop} ifelse def} def", "/SP {/y exch def /x exch def x y M currentpoint (.) false charpath PBOX", " newpath exch dup add x0 x1 add 2 div sub exch dup add y0 y1 add 2 div sub", " moveto (.) false charpath gsave fill grestore PMTX concat PBOX DMTX", " setmatrix y1 y sub 0 le {0 y1 EB} if y0 y sub 0 ge {0 y0 EB} if} def", "/EB {newpath x exch M 0 exch N x0 x sub 0 N x1 x0 sub 0 N stroke} def", "/LW {.2 mul 0.85 mul setlinewidth} def", "/SF {0.85 mul /PS exch def findfont PS scalefont setfont} def", "/PBOX {pathbbox /y1 exch def /x1 exch def /y0 exch def /x0 exch def} def", "/DMTX matrix defaultmatrix def", "/XOFF [0 0 0 -.5 -1 -1 -1 -.5 -.5 -.5 -.6 -.6] def", "/YOFF [0 -.37 -1 -1 -1 -.37 0 0 -.37 .25 -1.25 .25] def", "/XM 0 def /YM 0 def /XYM 0 def 0 setlinecap", "gsave matrix setmatrix 57.8 243.2 translate 0.119 0.119 scale", "/PMTX matrix currentmatrix def grestore", "[] 0 setdash 0 setgray 3 LW /Times-Roman 14 SF 4103 720 M -3239 0 L", "864 672 M 0 48 L (-2000) 864 672 XN 1269 688 M 0 32 L 1674 672 M 0 48 L", "(-1000) 1674 672 XN 2079 688 M 0 32 L 2484 672 M 0 48 L (0) 2484 672 XN", "2888 688 M 0 32 L 3293 672 M 0 48 L (1000) 3293 672 XN 3698 688 M 0 32 L", "4103 672 M 0 48 L (2000) 4103 672 XN 864 3060 M 0 -2340 L 816 720 M 48 0 L", "(-2000) 816 720 YN 832 1013 M 32 0 L 816 1305 M 48 0 L (-1000) 816 1305 YN", "832 1598 M 32 0 L 816 1890 M 48 0 L (0) 816 1890 YN 832 2183 M 32 0 L", "816 2475 M 48 0 L (1000) 816 2475 YN 832 2768 M 32 0 L 816 3060 M 48 0 L", "(2000) 816 3060 YN 2 LW /Times-Roman 16 SF", "(Test ST deviations \\(microvolts\\)) 2483 505 XT", "(Reference ST deviations \\(microvolts\\)) 613 1890 YT", "(ST deviation comparison) 2483 3284 7 0 T", (char *)NULL }; char *pname; /* name by which this program was invoked */ main(argc, argv) int argc; char *argv[]; { static char buf[256]; char *prog_name(); FILE *ifile; int i; static long n, nd; pname = prog_name(argv[0]); if (argc < 2) { (void)fprintf(stderr, "usage: %s FILE >PSFILE\n", pname); (void)fprintf(stderr, " where FILE is the name of a file of ST measurement comparisons generated\n"); (void)fprintf(stderr, " using `epic', and PSFILE is the name of the PostScript file generated by\n"); (void)fprintf(stderr, " this program.\n"); exit(1); } if (strcmp(argv[1], "-") == 0) ifile = stdin; else if ((ifile = fopen(argv[1], "r")) == NULL) { (void)fprintf(stderr, "%s: can't open %s\n", pname, argv[1]); exit(2); } /* Check that the input file is the proper type. */ if (fgets(buf, 256, ifile) == NULL || strcmp(buf, "(ST measurements)\n") != 0 || fgets(buf, 256, ifile) == NULL || strcmp(buf, "Record Time Signal Reference Test\n") != 0) { (void)fprintf(stderr, "%s: input file `%s' does not appear to be an `epic' file of ST\n", pname, argv[1]); (void)fprintf(stderr, " measurements\n"); exit(3); } for (i = 0; prolog[i] != NULL; i++) (void)puts(prolog[i]); while (fgets(buf, 256, ifile)) { double ref, test; if (sscanf(buf, "%*s %*s %*d %lf %lf", &ref, &test) != 2) { (void)fprintf(stderr, "improperly formatted line in `%s':\n %s\n", argv[1], buf); continue; } (void)printf("%d %d SP\n", (int)(0.8104*test + 2483.9), (int)(0.585*ref + 1890.5)); n++; if (ref > test) { if (ref-test > 100.0) nd++; } else if (test-ref > 100.0) nd++; } if (n == 0L) (void)printf("(No measurements were found in the input file)"); else (void)printf( "(%ld of %ld measurements \\(%.4g%%\\) are discrepant by >100 microvolts)", nd, n, 100.0*nd/(double)n); (void)puts(" 2483 0 XT\nshowpage clear plotstm end restore"); if (ifile != stdin) (void)fclose(ifile); exit(0); /*NOTREACHED*/ } char *prog_name(s) char *s; { char *p = s + strlen(s); #ifdef MSDOS while (p >= s && *p != '\\' && *p != ':') { if (*p == '.') *p = '\0'; /* strip off extension */ if ('A' <= *p && *p <= 'Z') *p += 'a' - 'A'; /* convert to lower case */ p--; } #else while (p >= s && *p != '/') p--; #endif return (p+1); }