C C C $STORAGE:2 C C C C======================================================================= C C These routine are from the PRO-350 library, and include C all necessary to create screen plots C C======================================================================= C C C SUBROUTINE PLTSCR(UNIT,TITLE,TLEN,TATTR,SUBT1,SUBT2) CC CC CC Created on : June 16, 1987 CC Last Updated: July 29, 1987 CC Written by : Bruce W. Roeckel CC CC Description : This routine will draw a bar chart, using the VT100 CC graphic character set. The screen is cleared from CC line six and the plot is drawn using the rest of the CC screen space. The cursor is left at 'home' after CC everything is done. CC CC UNIT is the unit# of an opened file were the data CC resides. If an error occurs during processing, CC this variable will be set to -99. The format the CC data in the file should be in is: CC CC Format of data is: F12,F12,1X,A1,A1 CC ^ ^ ^ ^ CC | | | | CC Data Point 1 ' | | | CC Data Point 2 ----' | | CC Horiz Axis Char's ------'--' CC CC TITLE is a 40 character variable that defines the CC plots title. CC CC TLEN is the number of characters that make up the CC titles actual length passed. CC CC TATTR is a code indicating the character attributes CC to use when drawing the title. CC CC CC 0 = Normal Characters CC 1 = inverse video CC 2 = bold CC 3 = blink CC 4 = inverse video, bold CC 5 = inverse video, blink CC 6 = bold, blink CC 7 = inverse video, bold, blink CC CC CC SUBT1 is the subtitle, or description, of data point CC number 1. It is 8 characters max. CC CC SUBT2 is the subtitle, or description, of data point CC number 2. It is 8 characters max. CC CC CC Update # Name Date Comments CC -------- --------- -------- ---------------------------------- CC 001 Roeckel 07/29/87 Added Average Line to Plot CC CC IMPLICIT INTEGER (A-Z) CHARACTER*1 TLC,TRC,VLINE(80),BLNK(80) CHARACTER RELOC*11,FMT1*40,TITLE*40,SUBT1*8,SUBT2*8 REAL PDATA(68),MIN,MAX,AVE,INC CHARACTER*1 H1(34),H2(34) C C READ DATA FROM FILE, CHECK FOR ERROR CONDITION C CALL PLTDAT(UNIT,PDATA,H1,H2,IDATA,MIN,MAX,AVE,INC,OLAY) IF(UNIT.LE.0) GOTO 900 C C ALL DATA READ IN O.K., SO GO AHEAD AND C MOVE LINE DRAWING CHARACTER SET INTO "G1", AND PRELOAD DATA C LUN=0 CALL GCHAR(LUN) DO 50 K=1,80 BLNK(K)=' ' VLINE(K)='q' 50 CONTINUE C C BASED ON HOW MUCH DATA WAS READ IN, FIQURE OUT HOW WIDE THE C BARS SHOULD BE, AS WELL AS HOW FAR APART FROM ONE ANOTHER C IF(IDATA.GT.22) THEN IWIDE=1 ISKIP=2 ITICK=0 ELSEIF(IDATA.GT.11) THEN IWIDE=2 ISKIP=3 ITICK=1 ELSE IWIDE=3 ISKIP=6 ITICK=1 ENDIF C C LETS SHOW SOME SCREEN ACTIVITY AND DRAW GRAPH BOUNDARY C HEIGHT=17 WIDTH=72 HORZ=6 VERT=6 BXATTR=0 IF(TATTR.LT.0 .OR. TATTR.GT.7) THEN TATT2=10 ELSE TATT2=TATTR+10 ENDIF CALL BOLD CALL BOX(HEIGHT,WIDTH,HORZ,VERT,TITLE,TLEN,TATT2,BXATTR) CALL UPTOP(1,6) C C ADD THE VERTICAL SCALE NUMBERS AND VERTICAL REFERENCE LINES C I=INT(MIN) CALL GPHON(LUN) CALL BOLD DO 100 IV=20,8,-2 CALL LOCATE(1,IV,RELOC) WRITE(*,'(A11,I4,1X,A1)') RELOC,I,117 I = I + INT(INC*2.0) 100 CONTINUE CALL OFF DO 150 IV=20,8,-2 CALL LOCATE(7,IV,RELOC) WRITE(*,'(A11,70A1)') RELOC,(VLINE(L),L=1,70) 150 CONTINUE IV=22-NINT(AVE) CALL LOCATE(7,IV,RELOC) CALL BOLD WRITE(*,'(A11,69A1,A3)') RELOC,(VLINE(L),L=1,69),'AVE' CALL OFF CALL GPHOFF(LUN) C C BASED UPON HOW MUCH DATA WAS ENTERED AND HOW WIDE EACH BAR C WILL BE, CENTER THE GRAPH IN THE MIDDLE OF THE BOX. C HORZ = 8 + ((68 - (ISKIP*IDATA))/2) C C START DISPLAYING EACH DATA POINT ............................ C THE FIRST 34 ENTRIES IN THE ARRAY 'PDATA' ARE THE OVERLAY C DATAPOINTS AND WILL BE DISPLAYED USING A HOLLOW BAR. C THE REMAINING 34 ENTRIES (35-68) ARE THE BASE POINTS C AND THEY WILL BE DISPLAYED AS A SOLID BAR. C C IF OVERLAY DATA WAS FOUND, THEN DRAW THAT STUFF FIRST C IF(OLAY.EQ.1) THEN IH=HORZ-1 CALL BOLD CALL GPHON(LUN) WRITE(FMT1,'(A8,I2.2,A5)') '(A11,A1,',IWIDE,'X,A1)' DO 600 K=1,IDATA HEIGHT=NINT(PDATA(K)) IF(HEIGHT.LE.0) THEN OLDTOP=0 IH=IH+ISKIP GOTO 600 ENDIF IV=22-HEIGHT C C ... BASED UPON THE WIDTH AND SEPERATION OF EACH BAR, C DEFINE THE GRAPHICS CHARACTERS TO BE USED C IF(ISKIP.LT.4 .AND. K.GT.1) THEN IF(NINT(PDATA(K-1)).EQ.NINT(PDATA(K))) THEN TLC='w' ELSEIF(NINT(PDATA(K-1)).GT.NINT(PDATA(K))) THEN TLC='t' ELSE TLC='l' ENDIF ELSE TLC='l' ENDIF IF(ISKIP.LT.4 .AND. K.LT.IDATA) THEN IF(NINT(PDATA(K+1)).EQ.NINT(PDATA(K))) THEN TRC='w' ELSEIF(NINT(PDATA(K+1)).GT.NINT(PDATA(K))) THEN TRC='u' ELSE TRC='k' ENDIF ELSE TRC='k' ENDIF C C ... STARTING AT THE LEFT HAND CORNER, DRAW THE TOP C CALL LOCATE(IH,IV,RELOC) WRITE(*,300) RELOC,TLC,(VLINE(L),L=1,IWIDE),TRC 300 FORMAT(A11,80A1,$) C C ... NOW START DOWN THE SIDES C DO 400 I=1,HEIGHT-1 CALL LOCATE(IH,IV+I,RELOC) IF(ISKIP.LT.4 .AND. K.GT.1) THEN IF(NINT(PDATA(K-1)).LT.NINT(PDATA(K)) A .AND. (IV+I).EQ.OLDTOP) THEN WRITE(*,FMT1) RELOC,'u','x' ELSE WRITE(*,FMT1) RELOC,'x','x' ENDIF ELSE WRITE(*,FMT1) RELOC,'x','x' ENDIF 400 CONTINUE C C .... AND FINALLY DRAW THE BOTTOM C CALL LOCATE(IH,IV+HEIGHT,RELOC) WRITE(*,300) RELOC,'v',(VLINE(L),L=1,IWIDE),'v' OLDTOP=IV IH=IH+ISKIP 600 CONTINUE CALL GPHOFF(LUN) CALL OFF ENDIF C C NOW GO AHEAD AND DRAW THE SOLID BAR INFO C CALL UPTOP(1,6) IV=0 IH=HORZ WRITE(FMT1,'(A11,I2.2,A9)') '(A11,A1,A4,',IWIDE,'A1,A1,A2)' DO 750 K=35,IDATA+34 HEIGHT=NINT(PDATA(K)) IF(HEIGHT.LE.0) THEN IH=IH+ISKIP GOTO 750 ENDIF IV=22-HEIGHT DO 700 I=1,HEIGHT CALL LOCATE(IH,IV+I-1,RELOC) WRITE(*,FMT1) RELOC,155,'1;7m',(BLNK(L),L=1,IWIDE),155,'0m' 700 CONTINUE IH=IH+ISKIP 750 CONTINUE CALL UPTOP(1,6) C C NOW DRAW THE HORIZONTAL LABELS C IH=HORZ+ITICK CALL GPHON(LUN) CALL BOLD DO 800 I=1,IDATA CALL LOCATE(IH,22,RELOC) WRITE(*,'(A11,A1)') RELOC,'w' IH=IH+ISKIP 800 CONTINUE CALL GPHOFF(LUN) IH=HORZ+ITICK DO 850 I=1,IDATA CALL LOCATE(IH-1,23,RELOC) WRITE(*,'(A11,2A1)') RELOC,H1(I),H2(I) IH=IH+ISKIP 850 CONTINUE CALL OFF C C NOW DRAW THE REFERENCE KEY, USING THE POINT SUBTITLES. C CALL PLTKEY(PDATA,IDATA,HORZ,OLAY,ISKIP,SUBT1,SUBT2) CALL UPTOP(1,6) 900 CONTINUE RETURN END C C C SUBROUTINE PLTKEY(PDATA,IDATA,FIRST,OLAY,SKIP,SUBT1,SUBT2) CC CC Plotting Subroutine CC CC This routine will locate a clear spot in the CC plot area and draw the reference 'key' CC CC IMPLICIT INTEGER (A-Z) REAL PDATA(68),PONE,PTWO CHARACTER TITLE*40,RELOC*11 CHARACTER*8 SUBT1,SUBT2 C C FIND A 4X16 AREA OF THE PLOT TO DRAW THE KEY SO C AS NOT TO DISTURB ANY DATA C C .... FIRST, LOAD VARIABLES BASED ON WERE FIRST BAR WAS PLOTTED C I=1 HORZ=8 VERT=9 LNUM=FIRST-8 C C .... IF THE BARS ARE LESS THEN HALF WAY UP THE SCALE C THEN WE COULD PLACE THE KEY ABOVE THEM C 100 CONTINUE PONE=PDATA(I) PTWO=PDATA(I+34) IF(OLAY.EQ.0) PONE=PTWO IF(PONE.LT.7.0 .AND. PTWO.LT.7.0) THEN IF(LNUM.LE.0) HORZ=FIRST + (I-1)*SKIP LNUM=LNUM+SKIP IF(LNUM.GE.16) GOTO 200 ELSE LNUM=0 ENDIF I=I+1 IF(I.LE.IDATA) GOTO 100 C C .... IF WE HAVENT FOUND A SPOT AFTER SEARCHING ALL POINTS C THEN LETS FIND A SPOT TO DRAW OVER THE BARS C I=1 HORZ=8 VERT=17 LNUM=FIRST-8 C C .... IF THE DATA IS MORE THAN HALF WAY UP THE PLOT, C THEN WE CAN DRAW THE KEY OVER THE BOTTOM OF THE BARS C 150 CONTINUE PONE=PDATA(I) PTWO=PDATA(I+34) IF(OLAY.EQ.0) PONE=PTWO IF(PONE.GT.7.0 .AND. PTWO.GT.7.0) THEN IF(LNUM.LE.0) HORZ=FIRST + (I-1)*SKIP LNUM=LNUM+SKIP IF(LNUM.GE.16) GOTO 200 ELSE LNUM=0 ENDIF I=I+1 IF(I.LE.IDATA) GOTO 150 C C IF WE FELL THROUGH TO THIS SPOT, THAT MEANS WE COULD NOT C FIND A GOOD PLACE. DEFAULT TO THE LOWER RIGHT CORNER C HORZ=60 VERT=17 C C NOW DRAW THE BOX FOR THE KEY C 200 CONTINUE IF(HORZ.GT.60 .OR. HORZ.LT.8) HORZ=60 IF(VERT.GT.17 .OR. VERT.LT.8) VERT=17 HEIGHT=4 WIDTH=16 TITLE='Key' TLEN=5 TATTR=2 BATTR=0 CALL BOLD CALL BOX(HEIGHT,WIDTH,HORZ,VERT,TITLE,TLEN,TATTR,BATTR) C C CLEAR OUT THE CENTER OF THE BOX C LUN=0 CALL LOCATE(HORZ+1,VERT+1,RELOC) WRITE(LUN,'(A11,A14)') RELOC,' ' CALL LOCATE(HORZ+1,VERT+2,RELOC) WRITE(LUN,'(A11,A14)') RELOC,' ' C C DRAW THE GRAPH SYMBOLS AND LABELS INSIDE THE BOX C IF(OLAY.EQ.1) THEN CALL LOCATE(HORZ+2,VERT+1,RELOC) CALL BOLD CALL GPHON(LUN) WRITE(LUN,'(A11,A3,\)') RELOC,'lqk' CALL GPHOFF(LUN) CALL OFF CALL LOCATE(HORZ+6,VERT+1,RELOC) WRITE(LUN,'(A11,A8,\)') RELOC,SUBT1 ENDIF CALL LOCATE(HORZ+3,VERT+2,RELOC) WRITE(LUN,500) RELOC,155,'1;7m',' ',155,'0m',SUBT2 500 FORMAT(A11,A1,A4,A1,A1,A2,2X,A8,\) RETURN END C C C SUBROUTINE PLTDAT(UNIT,PDATA,H1,H2,IDATA,MIN,MAX,AVE,INC,OLAY) CC CC Ploting Subroutine CC CC This routine reads in the data from the file and CC determines the minimum, maximum and average values. CC In addition, the scale increment is also calculated. CC CC UNIT ---- Unit # of opened file CC PDATA --- Array (real, dim of 68) of data read in CC H1,H2 --- Horizontal Scale Labels (char*1, DIM 34) CC IDATA --- # of data points read in CC MIN ----- Minimum value of all data points CC MAX ----- Maximum value of all data points CC AVE ----- Average of all data points CC INC ----- Vertical Scale increment CC OLAY ---- Switch indicating if overlay data was found CC IMPLICIT INTEGER (A-Z) CHARACTER*1 H1(34),H2(34) REAL PDATA(68),MIN,MAX,AVE,INC,TTL,VALINC(20) DATA VALINC/1.0,2.0,5.0,10.0,15.0,20.0,25.0,50.0,75.0,100.0, A 150.0,200.0,250.0,300.0,350.0,400.0,450.0,500.0, A 550.0,600.0/ C ************************* START PROCESSING ******************** C C READ IN DATA, ABORT IF ERROR OCCURS C I=0 OLAY=0 REWIND UNIT 100 CONTINUE I=I+1 IF(I.GT.34) GOTO 200 READ(UNIT,150,END=200,ERR=175) PDATA(I),PDATA(I+34), A H1(I),H2(I) 150 FORMAT(F12.0,F12.0,1X,A1,A1) IF(PDATA(I).GT.0.0) OLAY=1 GOTO 100 C C IF READ ERROR OCCURS, RETURN WITH FLAG SET C 175 CONTINUE UNIT=-99 GOTO 900 C C IF NO READ ERROR THEN CHECK FOR DATA BOUNDS, RETURN IF ERROR C 200 CONTINUE IDATA=I-1 IF(IDATA.LE.0) THEN UNIT=-99 GOTO 900 ENDIF C C FIND THE AVERAGE, MINIMUM AND MAXIMUM VALUES OF THE DATA C TTL=0.0 AVE=0.0 MAX=0.0 MIN=9999.0 DO 300 I=1,IDATA TTL=TTL+PDATA(I)+PDATA(I+34) IF(PDATA(I).GT.MAX) MAX=PDATA(I) IF(PDATA(I+34).GT.MAX) MAX=PDATA(I+34) IF(PDATA(I).NE.0.0 .AND. PDATA(I).LT.MIN) MIN=PDATA(I) IF(PDATA(I+34).NE.0.0 .AND. PDATA(I+34).LT.MIN) MIN=PDATA(I+34) 300 CONTINUE IF(OLAY.EQ.1) THEN AVE=TTL/REAL(IDATA*2) ELSE AVE=TTL/REAL(IDATA) ENDIF C C CHECK FOR DATA VALIDITY C IF((MAX.LE.0.0) .OR. (MIN.GE.9999.0)) THEN UNIT=-99 GOTO 900 ENDIF C C CALCULATE THE VERTICAL INCREMENTS BY DIVIDING THE MAXIMUM VALUE C BY 12 (THE NUMBER OF AVAILABLE TICKS) AND THEN MOVING TO THE NEXT C HIGHEST WHOLE NUMBER (I.E. CHECK FOR REMAINDER) I KNOW THERE MUST C BE A SIMPLER WAY TO DO THIS, BUT THIS WORKS. C INC = (MAX-MIN) / 12.0 TTL = INC - INT(INC) IF(TTL.GT.0) THEN INC = INT(INC) + 1.0 ELSE INC = INT(INC) ENDIF C C FIND THE CLOSEST 'VALID' INCREMENT IN TABLE C IF VALID INCREMENTS ARE NOT BIG ENOUGH, CALCULATE ONE C DO 400 I=1,20 IF(INC.LE.VALINC(I)) THEN INC = VALINC(I) GOTO 500 ENDIF 400 CONTINUE 450 CONTINUE IF(MAX.GT.(12.0*INC)) THEN INC = INC + 50.0 GOTO 450 ENDIF C C SCALE DOWN THE DATA TO FIT THE BOUNDS OF THE SCREEN C SINCE I WILL MAKE THE MINIMUM VALUE BE THE FIRST C VERTICAL TICK MARK, ADD TWO TO ALL VALUES C 500 CONTINUE MAX=((MAX-MIN)/INC) + 2.0 AVE=((AVE-MIN)/INC) + 2.0 C DO 600 J=1,IDATA IF(PDATA(J).GE.MIN) THEN PDATA(J) = ((PDATA(J)-MIN) / INC) + 2.0 ELSE PDATA(J)=0.0 ENDIF IF(PDATA(J+34).GE.MIN) THEN PDATA(J+34) = ((PDATA(J+34)-MIN) / INC) + 2.0 ELSE PDATA(J+34)=0.0 ENDIF 600 CONTINUE C C THAT ALL FOR NOW FOLKS !!! C 900 CONTINUE RETURN END