.COMMENT C C This is a set of Fortran callable routines for drawing C scaled x-y graphs with labels, etc. C See the separate writeup in GRAF.DOC for an explanation. C C C David Villeneuve C Division of Physics M23A C National Research Council C Ottawa Ont. K1A 0R6 C 613-993-9975 C SUBROUTINE GRAF1 (X, Y, NPTS) C C [AUTOSCALED GRAPH OF SINGLE FUNCTION] C C GIVEN A SET OF POINTS DEFINED BY THE VECTORS (X, Y), A GRAPH IS DISPLAYED C ON THE PLOTTING DEVICE, USING A SUITABLE SCALE. C THE AXES ARE LABELLED IN THE UNITS OF X AND Y. THE ELEMENTS OF X AND Y C FROM 1 TO NPTS ARE USED. C IF NPTS < 0, THE GRID WILL BE DRAWN USING SCALES DETERMINED FROM THE C IABS(NPTS) VALUES IN X AND Y, BUT NO DATA POINTS WILL BE DRAWN. C NOTE THAT THERE ARE A NUMBER OF PARAMETER SETTING ROUTINES WHICH MAY C MODIFY THE ACTION OF THIS ROUTINE. C REAL X(1), Y(1) COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) DATA NOHASH /1/, NOTICK /1/, NSYMBO /1/ DATA XPLOTL, XPLOTR, YPLOTB, YPLOTT / 1.95, 11.5, 1.0, 8.75 / C C PEN COLOURS AND HEIGHTS DEFAULTS HERE C C M-ttl S-ttl nums syms date maj-tk min-tk frame curve spare DATA IPEN / 1 2, 2, 3, 1, 2, 4, 4, 4, 1, 0/ DATA HITE / 1 0.2, 0.2, 0.15, 0.15, 0.1, 0.25, 0.1, 0.022, 0.0, 0.0/ C C DEFINE PLOTTING LIMITS OF PLOTTER IN INCHES C IFF (NOSIZE .EQ. 0) THEN { XPLOTL = 1.95 XPLOTR = 11.3 YPLOTB = 1.00 YPLOTT = 8.75 } NOSIZE = 0 C C INITIALIZE THE PLOTTING DEVICE C IF (NOGRID .EQ. 0) CALL PLOTS C C CALCULATE THE SCALE IF REQUIRED C IF (NUSCAL .EQ. 0) 1 CALL GRSCAL (X, Y, IABS(NPTS), XLSAVE, 2 XRSAVE, DXSAVE, YBSAVE, YTSAVE, DYSAVE, NDECX, NDECY) XSCALE = (XPLOTR-XPLOTL) / (XRSAVE-XLSAVE) YSCALE = (YPLOTT-YPLOTB) / (YTSAVE-YBSAVE) C C PUT IN THE GRID C IF (NOGRID .EQ. 0) 1 CALL GRAXIL (XLSAVE, XRSAVE, DXSAVE, YBSAVE, YTSAVE, DYSAVE) C C PLOT THE GRAPH C CALL GRFIXL (X, Y, NPTS, 1, XLSAVE, XRSAVE, YBSAVE, YTSAVE) C C WRITE IN THE SCALES C IFF (NOGRID .EQ. 0) THEN { XLMOST = XPLOTL !GRNUML WILL MOVE THIS LEFT CALL GRNUML (1, LOGARX, XLSAVE, XRSAVE, DXSAVE, 2 XLSAVE, XSCALE, XPLOTL, NDECX) CALL GRNUML (2, LOGARY, YBSAVE, YTSAVE, DYSAVE, 2 YBSAVE, YSCALE, YPLOTB, NDECY) } C C RELEASE THE PLOTTER, RESET SWITCHES C CALL PLOTF NOGRID = 0 NUSCAL = 0 RETURN END SUBROUTINE GRAF2 (X, Y, NPTS, MX, MY, ILOG, IOPT, 1 TITLE, XLABEL, YLABEL) C C [AUTOSCALED GRAPH OF SINGLE FUNCTION, MULTIPLE PLOTS PER PAGE] C C THIS IS SIMILAR TO GRAF1, IN THAT IT PLOTS A GRAPH OF X VERSUS Y C WITH THE OPTION OF AUTOSCALING. IT DRAWS THE GRID AND LABELS IT. C IN ADDITION, HOWEVER, IT MAY PLOT FROM 1 TO 6 GRAPHS ON THE SAME C PAGE IN VARIOUS LOCATIONS, DEPENDING ON THE CHOICE OF MX,MY. C GRNOTK,GRNOHA MAY BE CALLED BEFOREHAND, GRLOC MAY BE CALLED AFTERWARDS, C AND THE SCALES MAY BE RETRIEVED AFTERWARDS BY GRGSCA, GRLSCA. C THE LOG/LINEAR STATE IS SET AS IF A CALL TO GRLOG WERE MADE, C AND THIS STAYS IN EFFECT WHEN A CALL TO GRAF1 IS MADE. C ALL OTHER PARAMETER SETTING SUBROUTINES FOR GRAF1 HAVE NO EFFECT C ON GRAF2. C C X,Y = REAL ARRAYS, DIMENSIONED AT LEAST X(NPTS), Y(NPTS), C CONTAINING THE VALUES TO BE GRAPHED. IF SOLID LINES C ARE USED, ONE OF THE ARRAYS SHOULD BE MONOTONIC. C NPTS = NUMBER OF POINTS TO BE PLOTTED. IF IS NEGATIVE, C THE NUMBER OF POINTS IS TAKEN TO BE THE ABSOLUTE VALUE, C AND THE POINTS ARE PLOTTED ON TOP OF THE EXISTING GRAPH, C USING THE SCALE VALUES OF THE LAST CALL TO GRAF2, WITHOUT C DRAWING THE GRID. C MX,MY = LOCATION ON THE PLOTTING PAGE WHERE THE GRAPH IS TO GO. C CAN BE IN THE RANGE 1-3. IF MX=1, IT FILLS THE WIDTH C OF THE PAGE; IF MX=2, IT FILLS HALF THE WIDTH ON THE C LEFT SIDE; IF MX=3, IT FILLS HALF THE WIDTH ON THE C RIGHT SIDE. SIMILARLY FOR MY. A NEW PAGE IS BEGUN C ONLY WHEN THE TOP LEFT GRAPH IS PLOTTED, SO ALWAYS C BEGIN AT THE TOP LEFT. C ILOG = LOGARITHMIC/LINEAR MODE OF GRAPH, AS FOLLOWS: C ILOG=1 FOR LIN/LIN, C ILOG=2 FOR LIN X, LOG Y, C ILOG=3 FOR LOG X, LIN Y, C ILOG=4 FOR LOG/LOG. C IOPT = PLOTTING SYMBOL OPTIONS WHICH CONTROL HOW THE DATA CURVE C IS DRAWN. THIS PARAMETER IS CODED AS A DECIMAL INTEGER AS C , WHERE EACH LETTER REPRESENTS A DIGIT, AND IS C THE PEN COLOUR, IS THE PLOTTING SYMBOL, AND IS THE C INCREMENT FOR PLOTTING A SYMBOL AT EVERY TH POINT. C C=1-4 FOR THE COLOURS. SS=00 FOR NO SYMBOL, 01 FOR DOTS C OF COLOUR C, 65-72 FOR SPECIAL SYMBOLS IN BLACK (SEE GRSYM). C I IS 0 FOR PLOTTING THE SYMBOL ONLY, >0 FOR PLOTTING THE C SYMBOL ON TOP OF THE CONNECTED CURVE AT EVERY I-TH POINT. C SPECIAL CASE IS IOPT=1-4, WHICH DRAWS A CONNECTED CURVE C OF COLOUR IOPT. C IF IOPT IS NEGATIVE, NO DATA POINTS ARE PLOTTED, BUT THE C GRID IS DRAWN AND LABELED, AND THE SCALE IS CHOSEN FROM C THE VALUES IN X,Y. THIS WAY ONE CAN FORCE THE SCALE. C TITLE = CHARACTER STRING TO BE WRITTEN AT THE TOP OF THE GRAPH. C THIS MAY BE EITHER A QUOTED STRING, OR A BYTE ARRAY WITH C A ZERO BYTE TO MARK THE END OF IT. C XLABEL = CHARACTER STRING TO BE WRITTEN UNDER THE X-AXIS, SAME C TYPE AS TITLE. C YLABEL = CHARACTER STRING TO BE WRITTEN UNDER THE Y-AXIS, SAME C TYPE AS TITLE. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) REAL X(1), Y(1), XPLOT0(3), XPLOT1(3), YPLOT0(3), YPLOT1(3) BYTE TITLE(1), XLABEL(1), YLABEL(1) DATA NOHASH /1/, NOTICK /1/, NSYMBO /1/ DATA XPLOT0 / 1.95, 1.95, 7.9 / DATA XPLOT1 / 11.9, 5.75, 11.9 / DATA YPLOT0 / 1.00, 5.50, 1.00 / DATA YPLOT1 / 8.75, 8.75, 4.0 / C C PEN COLOURS AND HEIGHTS DEFAULTS HERE C C M-ttl S-ttl nums syms date maj-tk min-tk frame curve spare DATA IPEN / 1 2, 2, 3, 1, 2, 4, 4, 4, 1, 0/ DATA HITE / 1 0.2, 0.2, 0.15, 0.15, 0.1, 0.25, 0.1, 0.022, 0.0, 0.0/ IF (NPTS .EQ. 0 .OR. MX .LE. 0 .OR. MX .GT. 3 1 .OR. MY .LE. 0 .OR. MY .GT. 3) RETURN C C SAVE PARAMETERS FOR GRAF1 WHICH WE MIGHT CHANGE HERE C NSYMSV = NSYMBO C C CHOOSE SIZE OF GRAPH C XPLOTL = XPLOT0(MX) XPLOTR = XPLOT1(MX) YPLOTB = YPLOT0(MY) YPLOTT = YPLOT1(MY) C C SET LOG/LINEAR OPTIONS C LOGARX = 0 LOGARY = 0 IF (ILOG .EQ. 3 .OR. ILOG .EQ. 4) LOGARX = 1 IF (ILOG .EQ. 2 .OR. ILOG .EQ. 4) LOGARY = 1 C C CALCULATE SCALE UNLESS USING PREVIOUS SCALE C IF (NPTS .GT. 0) CALL GRSCAL (X, Y, NPTS, 1 XLSAVE, XRSAVE, DXSAVE, YBSAVE, YTSAVE, DYSAVE, NDECX, NDECY) XSCALE = (XPLOTR-XPLOTL) / (XRSAVE-XLSAVE) YSCALE = (YPLOTT-YPLOTB) / (YTSAVE-YBSAVE) C C INITIALIZE PLOTTER FOR TOP LEFT GRAPH ONLY C IF (NPTS .GT. 0 .AND. MX .LT. 3 .AND. MY .LT. 3) CALL PLOTS C C PLOT THE DATA CURVE IF IOPT IS POSITIVE. C THIS MAY BE DONE TWICE IF OVERPLOTTING REQUESTED. C IFF (IOPT .GE. 0) THEN { ISYM = MOD( IOPT/10, 100 ) !SYMBOL CODE ICOL = MOD( IOPT, 10 ) !COLOUR CODE INC = IOPT / 1000 !INCREMENT NSYMBO = MAX0( 1, ICOL ) !ASSUME SOLID COLOUR IF (INC .GT. 0 .OR. IOPT .LT. 10) 1 CALL GRFIXL (X, Y, IABS(NPTS), 1, XLSAVE, XRSAVE, YBSAVE, YTSAVE) INC = MAX0( INC, 1 ) NSYMBO = -NSYMBO !TRY DOTS IF (ISYM .GT. 64) NSYMBO = -ISYM !SPECIAL SYMBOL IF (ISYM .NE. 0) 1 CALL GRFIXL (X, Y, IABS(NPTS), INC, XLSAVE, XRSAVE, YBSAVE, YTSAVE) } C C DRAW THE GRID UNLESS WE ARE PLOTTING ON TOP OF LAST ONE C IF (NPTS .GT. 0) 1 CALL GRAXIL (XLSAVE, XRSAVE, DXSAVE, YBSAVE, YTSAVE, DYSAVE) C C WRITE ON SCALES C IFF (NPTS .GT. 0) THEN { XLMOST = XPLOTL !GRNUML WILL MOVE THIS LEFT CALL GRNUML (1, LOGARX, XLSAVE, XRSAVE, DXSAVE, 2 XLSAVE, XSCALE, XPLOTL, NDECX) CALL GRNUML (2, LOGARY, YBSAVE, YTSAVE, DYSAVE, 2 YBSAVE, YSCALE, YPLOTB, NDECY) } C C WRITE IN TITLES C IF (NPTS .GT. 0) 1 CALL GRTITL (TITLE, 100, XLABEL, 80, YLABEL, 50) C C RESET PARAMETERS SO GRAF1 IS UNAFFECTED C CALL PLOTF NSYMBO = NSYMSV RETURN END SUBROUTINE GRSYM (ISYM) C C DEFINES THE TYPE OF SYMBOLS TO BE USED FOR PLOTTING THE DATA POINTS C IN SUBSEQUENT CALLS TO GRAF1. C C ISYM = 1:64 USE THE PEN COLOUR AND CONNECT THE POINTS WITH LINES. C ONLY PEN COLOURS 1-4 WORK FOR THE HP PLOTTER, SO ISYM>4 WILL C USE PEN 4. FOR THE NORPAK, THE LOOKUP TABLE MUST BE SET BY C THE USER FOR COLOURS HIGHER THAN 4. C C ISYM = -1:-64 USE PEN COLOUR ABS TO PUT A DOT AT EACH POINT. IN THIS C CASE THE X-Y PAIRS IN THE CALL TO GRAF1 DO NOT NEED TO BE IN C ANY ORDER. C C ISYM < -64 USE THE SPECIAL SYMBOLS WHOSE CODE IS ABS TO MARK C EACH POINT. THESE SYMBOLS ARE DRAWN BY SYMBOS. C C ISYM > 64 USE SPECIAL SYMBOLS AS ABOVE, PLUS DRAW BLACK LINE C BETWEEN POINTS. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) NSYMBO = ISYM IF (ISYM .LT. -127) NSYMBO = -65 RETURN END SUBROUTINE GRLSCA C C CAUSES THE NEXT CALL TO GRAF1 TO USE THE SCALE VALUES WHICH C WERE USED ON THE LAST CALL TO GRAF1, RATHER THAN CHOOSING C NEW ONES. THIS ONLY HOLDS FOR THE NEXT CALL TO GRAF1. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) NUSCAL = 1 RETURN END SUBROUTINE GRGSCA (X0, X1, DX, Y0, Y1, DY) C C RETURNS THE RANGE OF VALUES USED TO PLOT THE PREVIOUS GRAPH BY GRAF1. C THE X AXIS WENT FROM X0 TO X1, THE Y AXIS FROM Y0 TO Y1, AND GRID C LINE SPACING OF DX AND DY WERE USED. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) X0 = XLSAVE X1 = XRSAVE Y0 = YBSAVE Y1 = YTSAVE DX = DXSAVE DY = DYSAVE RETURN END SUBROUTINE GRSSCA (X0, X1, DX, Y0, Y1, DY) C C CAUSES THE NEXT CALL TO GRAF1 TO USE THESE VALUES FOR THE SCALE, C RATHER THAN CHOOSING ITS OWN. THE X AXIS WILL RUN FROM X0 TO X1, C THE Y AXIS FROM Y0 TO Y1, AND GRID SPACING OF DX AND DY WILL BE USED. C THIS ONLY HOLDS FOR THE NEXT CALL TO GRAF1. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) C C CHECK RANGE OF SCALE FACTORS C IF (X0 .GE. X1) RETURN IF (Y0 .GE. Y1) RETURN IF (DX .LE. 0.0 .OR. DY .LE. 0.0) RETURN C C COPY THE FACTORS C NUSCAL = 1 XLSAVE = X0 XRSAVE = X1 YBSAVE = Y0 YTSAVE = Y1 DXSAVE = DX DYSAVE = DY RETURN END SUBROUTINE GRNOGR C C CAUSES THE NEXT CALL TO GRAF1 TO PLOT THE DATA ONLY, WITHOUT C PRODUCING A GRID. THIS HOLDS FOR THE NEXT CALL TO GRAF1 ONLY. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) NOGRID = 1 RETURN END SUBROUTINE GRSSIZ (X0, X1, Y0, Y1) C C CAUSES THE NEXT CALL TO GRAF1 ONLY TO USE THE GIVEN SIZE OF C THE PLOTTING AREA, IN INCHES. SEE GRAF1 FOR THE DEFAULTS. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) XPLOTL = X0 XPLOTR = X1 YPLOTB = Y0 YPLOTT = Y1 NOSIZE = 1 RETURN END SUBROUTINE GRGSIZ (X0, X1, Y0, Y1) C C RETURNS THE LAST USED SIZE OF THE PLOTTING AREA, SET EITHER BY C GRAF1 OR GRAF2, IN INCHES. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) X0 = XPLOTL X1 = XPLOTR Y0 = YPLOTB Y1 = YPLOTT RETURN END SUBROUTINE GRNOHA C C CAUSES THE SUBSEQUENT CALLS TO GRAF1 TO USE TICK MARKS TO MARK EACH VALUE ALONG C THE AXES, RATHER THAN HASH MARKS RIGHT ACROSS THE GRAPH. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) NOHASH = 1 RETURN END SUBROUTINE GRYEHA C C CAUSES SUBSEQUENT CALLS TO GRAF1 TO PLOT THE AXES WITH LINES RUNNING C RIGHT ACROSS THE GRAPH TO MARK THE VALUES. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) NOHASH = 0 RETURN END SUBROUTINE GRNOTK C C [NO TICKS] C PREVENTS THE DRAWING OF SUBDIVISION TICK MARKS AROUND THE GRAPH. C IN EFFECT FOR THE NEXT GRAPH ONLY, THEN IS TURNED BACK ON. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) NOTICK = 1 RETURN END SUBROUTINE GRYETK C C [TICKS] C TURNS ON THE DRAWING OF SUBDIVISION TICK MARKS AROUND THE GRAPH. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) NOTICK = 0 RETURN END SUBROUTINE GRLOG (IX, IY) C C [CHOOSE LOG SCALES] C DETERMINES WHETHER SUBSEQUENT CALLS TO GRAF1 WILL USE C LINEAR OR LOGARITHMIC SCALES. IF IX,IY = 0, THE C CORRESPONDING SCALES ARE LINEAR, OTHERWISE LOGARITHMIC. C THESE SETTINGS REMAIN IN EFFECT FOR ALL SUBSEQUENT C GRAPHS, UNLESS RESET BY ANOTHER CALL TO GRLOG. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) LOGARX = IX LOGARY = IY RETURN END SUBROUTINE GRGPAR (IPENS, HITES) C C RETRIEVES THE CURRENTLY USED HEIGHT AND PEN PARAMETERS FOR C THE VARIOUS COMPONENTS OF THIS GRAPHING SYSTEM, AND RETURNS C THEM IN THE TWO ARRAYS AND , WHICH MUST BE C DIMENSIONED AS 10 EACH. C THE ENTRIES CORRESPOND TO THE FOLLOWING SETTINGS: C (1) Main title C (2) Axis titles C (3) Numbers on the axes C (4) Symbols, ie. triangles and diamonds C (5) Date C (6) Major tick or hash lines (HITE is actually length) C (7) Minor tick (HITE is actually length) C (8) Frame (HITE is width of line using three strokes) C (9) Curves (HITE is ignored, overridden by GRSYM and GRAF2) C DIMENSION IPENS(10), HITES(10) COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) FOR J=1,10 { IPENS(J) = IPEN(J) HITES(J) = HITE(J) } RETURN END SUBROUTINE GRSPAR (IPENS, HITES) C C SETS THE ENTIRE SET OF PEN AND HEIGHT PARAMETERS USED BY THIS C GRAPHING SYSTEM FROM THE USER SUPPLIED ARRAYS AND C WHICH MUST BE DIMENSIONED AS 10 EACH. C THE ENTRIES CORRESPOND TO THE FOLLOWING SETTINGS: C (1) Main title C (2) Axis titles C (3) Numbers on the axes C (4) Symbols, ie. triangles and diamonds C (5) Date C (6) Major tick or hash lines (HITE is actually length) C (7) Minor tick (HITE is actually length) C (8) Frame (HITE is width of line using three strokes) C (9) Curves (HITE is ignored, overridden by GRSYM and GRAF2) C DIMENSION IPENS(10), HITES(10) COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) FOR J=1,10 { IPEN(J) = IPENS(J) HITE(J) = HITES(J) } RETURN END SUBROUTINE GRTITL (TTEXT, NT, XTEXT, NX, YTEXT, NY) C C ANNOTATES THE GRAPH WITH UP TO THREE CHARACTER STRINGS. C THE FIRST STRING, , IS PLACED ABOVE THE GRAPH. C THE SECOND STRING, , IS PLACED BELOW THE X AXIS. C THE THIRD STRING, , IS PLACED TO THE LEFT OF THE Y AXIS. C EACH STRING IS FOLLOWED BY ITS LENGTH. THE STRING MAY ALSO BE C TERMINATED BY A ZERO BYTE, IN WHICH CASE THE LENGTH IS SET TO A C LARGE NUMBER. IF A PARTICULAR LABEL IS NOT C DESIRED, SET ITS STRING TO EMPTY QUOTES, AND ITS LENGTH TO ZERO. C NOTE THAT THE POSITION OF THE Y AXIS LABEL DEPENDS ON THE VALUE C OF XLMOST WHICH IS SET BY GRNUML TO THE LEFTMOST POSITION OF C THE Y AXIS NUMBERS, SO IF THE NUMBERS ARE SHORT THE LABEL COMES C IN CLOSER TO THE AXIS. C BYTE TTEXT(1), XTEXT(1), YTEXT(1) COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) CALL NEWPEN (IPEN(1)) XSTART = (XPLOTR-XPLOTL) / 2.0 + XPLOTL CALL SYMBOC (XSTART, YPLOTT+0.25, HITE(1), TTEXT, 0.0, NT, 0) CALL NEWPEN (IPEN(2)) YSTART = AMAX1( 0.0, YPLOTB - 1.66*HITE(3) - 2.2*HITE(2) ) CALL SYMBOC (XSTART, YSTART, HITE(2), XTEXT, 0.0, NX, 0) IF (XLMOST .LE. HITE(2)) XLMOST = 2.0*HITE(2) !ALWAYS LEAVE ROOM XSTART = XLMOST - HITE(2) YSTART = (YPLOTT-YPLOTB) / 2.0 + YPLOTB CALL SYMBOC (XSTART, YSTART, HITE(2), YTEXT, 90.0, NY, 0) CALL PLOTF RETURN END SUBROUTINE GRDATE C C PLACES THE TIME AND DATE IN THE LOWER RIGHT HAND CORNER OF THE GRAPH C JUST DRAWN. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) BYTE STRING (20) CALL TIME (STRING) CALL DATE (STRING(10)) STRING (9) = "40 CALL NEWPEN (IPEN(5)) CALL SYMBOC (XPLOTR, 0.125, HITE(5), STRING, 0.0, 18, 1) CALL PLOTF RETURN END SUBROUTINE GRSCAL (X, Y, N, XLEFT, XRIGHT, DX, YBOT, YTOP, DY, 1 NDECX, NDECY) C C FINDS THE RANGE OF VALUES IN X(N) AND Y(N), AND CHOOSES NICE ROUNDED C SCALE VALUES AND GRID SPACINGS. C C X(N),Y(N) = VECTORS OF VALUES TO BE EVENTUALLY PLOTTED. C (X0, X1) = RETURNED RANGE OF X WHICH CONTAINS ALL ELEMENTS OF X(N). C (Y0, Y1) = RETURNED RANGE OF Y WHICH CONTAINS ALL ELEMENTS OF Y(N). C DX, DY = GRID SPACING FOR THE X AND Y AXES RESPECTIVELY. C THE VALUE IS CHOSEN SO THAT THE ARE NICE NUMBERS, AND C SO THAT APPROXIMATELY 4 TO 8 GRID LINES WILL APPEAR. C NDECX,NDECY = NUMBER OF DECIMAL POINTS REQUIRED FOR EACH SCALE. C C FOR LOG SCALES, X0,X1,Y0,Y1 ARE SET TO THE LOG BASE 10 OF C THE LIMITS OF THE GRAPH, AND DX,DY ARE SET TO 1. C REAL X(1), Y(1) COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) C C FIND THE RANGE OF X AND Y C XMIN = 1E37 XMAX = -1E37 YMIN = 1E37 YMAX = -1E37 FOR J=1,N { IF (X(J) .LT. XMIN) XMIN = X(J) IF (X(J) .GT. XMAX) XMAX = X(J) IF (Y(J) .LT. YMIN) YMIN = Y(J) IF (Y(J) .GT. YMAX) YMAX = Y(J) } C C CHOOSE NICE INTERVALS FOR THE SCALE C IF (LOGARX .EQ. 0) CALL GRINTN (XMIN, XMAX, XLEFT, XRIGHT, DX, NDECX) IF (LOGARX .NE. 0) CALL GRINTL (XMIN, XMAX, XLEFT, XRIGHT, DX, NDECX) IF (LOGARY .EQ. 0) CALL GRINTN (YMIN, YMAX, YBOT, YTOP, DY, NDECY) IF (LOGARY .NE. 0) CALL GRINTL (YMIN, YMAX, YBOT, YTOP, DY, NDECY) RETURN END SUBROUTINE GRINTN (XL, XR, PL, PR, PDX, NDEC) C C [AUTOSCALING INTERVALS] C C THE INTERVAL [XL, XR] IS EXAMINED, AND A LARGER INTERVAL [PL, PR] IS CHOSEN C SUCH THAT PL AND PR ARE "NICE" NUMBERS FOR A GRAPHICAL SCALE. THE INTERVAL C BETWEEN MARKERS IS PDX, WHICH IS ALSO A NICE NUMBER. C NDEC IS RETURNED AS THE NUMBER OF DIGITS REQUIRED TO THE RIGHT OF THE C DECIMAL POINT. C REAL XMULT(7) DATA XMULT / 1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0/ DX = XR - XL IFF (DX .LE. 0.0) THEN { !RANGE IS TOO NARROW 20 PL = XL-1.0 PR = XL+1.0 PDX = 1.0 NDEC = 1 RETURN } ALOGDX = ALOG10(DX) LOGDX = INT(ALOGDX) IF (ALOGDX .LT. 0.0) LOGDX = INT (ALOGDX - 1.0) C C CALCULATE A NICE INCREMENT, FOR SPACING BETWEEN MARKERS C PDXS = 10.0**(LOGDX-1) PDX = PDXS J = 1 WHILE (DX/PDX .GT. 5.0) { J = J+1 PDX = XMULT(J)*PDXS } NDEC = MAX0( 1 - LOGDX - (J-1)/3, 0 ) !NUMBER OF DECIMAL PLACES C C SEE IF ZERO LIES EITHER IN THE INTERVAL [XL,XR] OR WITHIN 25% OF IT. C IFF ((XL*XR .LE. 0.0) 1 .OR. (XR .LT. 0.0 .AND. XR+0.25*DX .GT. 0.0) 2 .OR. (XL .GT. 0.0 .AND. XL-0.25*DX .LT. 0.0)) THEN { !ZERO IS IN INTERVAL PNICE = 0.0 !ZERO IS A VERY NICE NUMBER GO TO 200 } IFF (XL .LT. 0.0) THEN { !EXCHANGE XL AND XR IF BOTH NEGATIVE TEMP = XR XR = XL XL = TEMP } ALOGXL = ALOG10(ABS(XL)) LOGXL = INT(ALOGXL) IF (ALOGXL .LT. 0.0) LOGXL = INT (ALOGXL - 1.0) C C TRY 1-2-5 MULTIPLES OF POWERS OF TEN FOR A NICE NUMBER C J = 1 PNICE = 10.0**LOGXL WHILE (XMULT(J)*PNICE .LE. ABS(XL)) J = J+1 PNICE = PNICE * XMULT(J) IF (PNICE .LE. ABS(XR)) GO TO 200 C C TRY INTEGRAL MULTIPLES OF TEN FOR A NICE NUMBER C PLS = 10.0**LOGXL J = 1 REPEAT { PNICE = PLS WHILE (J*PNICE .LE. ABS(XL)) J = J+1 PNICE = J*PNICE IF (PNICE .LE. ABS(XR)) GO TO 200 PLS = PLS/10.0 !TRY SMALLER FRACTIONS OF INTEGERS } C C WE NOW HAVE A "NICE" NUMBER PNICE WHICH LIES IN OR NEAR OUR INTERVAL. C COUNT BACK TO THE LEFT MARGIN C 200 X = PNICE IF (XR .LT. 0.0) X = -X WHILE (X .GT. AMIN1(XL,XR)) X = X-PDX PL = X C C NOW COUNT AHEAD TO THE RIGHT MARGIN, AND RETURN C WHILE (X .LT. AMAX1(XL, XR)) X = X + PDX PR = X C C REVISE NUMBER OF DECIMAL PLACES FOR VERY LARGE OR SMALL NUMBERS C BIGEST = AMAX1( ABS(PL), ABS(PR) ) IF (BIGEST .GE. 1.0E7 .OR. BIGEST .LE. 1.0E-4) 1 NDEC = -( ALOG10( BIGEST/PDX ) + 1.0 ) RETURN END SUBROUTINE GRINTL (XMIN, XMAX, XLEFT, XRIGHT, DX, NDEC) C C [CHOOSE LOGARITHMIC INTERVALS] C GIVEN THE RANGE OF DATA [XMIN,XMAX], THIS CHOOSES NICE GRAPH C LIMITS XLEFT, XRIGHT, SUCH THAT THE DATA IS CONTAINED IN THE C INTERVAL, AND XLEFT AND XRIGHT ARE MULTIPLES OF TEN. C XLEFT AND XRIGHT ARE THE LOG BASE 10 OF THE LIMITS, DX IS 1. C THUS FOR LOG SCALES, THE AXES ARE THOUGHT OF IN TERMS OF THE C LOG OF THE VALUES, RESULTING IN A LINEAR SCALE FOR MOST OF C THE SUBROUTINES. THE ONLY DIFFERENCE IF FOR LOG TICK MARKS. C NDEC = 0 SINCE WE WANT WHOLE NUMBERS FOR EXPONENTS. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) DX = 1.0 NDEC = 0 IFF (XMIN*XMAX .LT. 0.0) THEN { !VALUES STRADDLE ZERO XLEFT = -20 XRIGHT = CEIL( ALOG9(XMAX) ) IF (XRIGHT .LT. XLEFT) XLEFT = XRIGHT-2 RETURN } XLEFT = FLOOR( ALOG9(XMIN) ) XRIGHT = CEIL( ALOG9(XMAX) ) RETURN END SUBROUTINE GRFIXL (X, Y, NX, INC, XSC0, XSC1, YSC0, YSC1) C C [PLOT FIXED SCALES] C THE POINTS IN (X,Y) ARE PLOTTED ON THE PLOTTER, ACCORDING TO THE LEFT, RIGHT, C BOTTOM AND TOP EDGES DEFINED BY THE LAST FOUR ARGUMENTS. ANY POINTS OUTSIDE C THIS RANGE ARE TRUNCATED. C C X(NX), Y(NX) = POINT PAIRS WHICH DEFINE GRAPH. C INC = NUMBER TO INCREMENT BETWEEN PTS. INC=1 MEANS PLOT C EVERY POINT, INC=2 MEANS PLOT EVERY OTHER POINT, ETC. C XSC0, XSC1 = LOWER AND UPPER RANGE OF X-VALUES. THESE WILL CORRESPOND C TO THE LEFT AND RIGHT EDGES OF THE GRAPH. C YSC0, YSC1 = LOWER AND UPPER RNAGE OF Y-VALUES. THESE WILL CORRESPOND C TO THE LOWER AND UPPER EDGES OF THE GRAPH. C REAL X(1), Y(1) COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) IF (NX .LE. 0) RETURN IF (NSYMBO .EQ. 0) RETURN !INVISIBLE LINE IFF (NSYMBO .LT. 65 .AND. NSYMBO .GT. -65) THEN CALL NEWPEN (IABS(NSYMBO)) !SPECIFIED PEN COLOUR ELSE CALL NEWPEN (IPEN(4)) !DEFAULT FOR SYMBOLS IPENUP = 3 FOR J=1,NX,INC { X1 = X(J) IF (LOGARX .NE. 0) X1 = ALOG9(X1) Y1 = Y(J) IF (LOGARY .NE. 0) Y1 = ALOG9(Y1) XP = XSCALE*(X1-XSC0) + XPLOTL YP = YSCALE*(Y1-YSC0) + YPLOTB XP = AMAX1(XPLOTL, AMIN1(XP, XPLOTR)) YP = AMAX1(YPLOTB, AMIN1(YP, YPLOTT)) IFF (NSYMBO .GE. 0 .AND. NSYMBO .LE. 64) THEN { !CONNECTED LINES BETWEEN POINTS CALL PLOT (XP, YP, IPENUP) } IFF (NSYMBO .LT. 0 .AND. NSYMBO .GT. -65) THEN { !POINTS ONLY CALL PLOT (XP, YP, 3) CALL PLOT (XP+0.01, YP, 2) } IF (NSYMBO .LT. -64) 1 CALL SYMBOL (XP, YP, HITE(4), NSYMBO, 0.0, -1) IFF (NSYMBO .GT. 64) THEN { !SYMBOLS AND LINES IF (IPENUP .EQ. 3) CALL PLOT (XP, YP, 3) CALL SYMBOL (XP, YP, HITE(4), NSYMBO, 0.0, -2) } IPENUP = 2 } RETURN END SUBROUTINE GRLOC (XPLOT, YPLOT, XUSER, YUSER) C C CONVERTS FROM USER COORDINATES TO PLOTTING COORDINATES. C (XUSER,YUSER) IS THE COORDINATE OF A POINT USING THE USER'S UNITS C FROM THE LAST CALL TO GRAF1 OR GRAF2. THIS IS CONVERTED TO C PLOTTING UNITS (XPLOT,YPLOT). THIS IS USEFUL IF ONE WISHES C TO PUT MORE DATA ON THE GRAPH OR TO LABEL INDIVIDUAL POINTS. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) X1 = XUSER IF (LOGARX .NE. 0) X1 = ALOG9(X1) XPLOT = XSCALE * (X1-XLSAVE) + XPLOTL XPLOT = AMAX1( XPLOTL, AMIN1( XPLOT, XPLOTR ) ) Y1 = YUSER IF (LOGARY .NE. 0) Y1 = ALOG9(Y1) YPLOT = YSCALE * (Y1-YBSAVE) + YPLOTB YPLOT = AMAX1( YPLOTB, AMIN1( YPLOT, YPLOTT ) ) RETURN END SUBROUTINE GRAXIL (XSC0, XSC1, DX, YSC0, YSC1, DY) C C [PLOT AXES] C INSERTS A GRID ON THE SCREEN, WITH SPACING GIVEN BY DX AND DY. C C XSC0, XSC1 = RANGE OF X VALUES, FROM LEFT TO RIGHT. FIRST LINE WILL C START AT XSC0. C YSC0, YSC1 = RANGE OF Y VALUES, FROM BOTTOM TO TOP. FIRST LINE WILL C START AT YSC0. C DX, DY = SPACING BETWEEN SUCCESSIVE GRID LINES. C C NOTE THAT THESE VALUES SHOULD BE WITHIN THE RANGE DEFINED BY C XLSAVE, XRSAVE, YBSAVE, YTSAVE PREVIOUSLY. THEY DO NOT HAVE C TO CORRESPOND EXACTLY TO THE LIMITS, BUT MAY SPAN A SUBSET. C C If you define the symbol PLOTTER below, the ticks will all be drawn C counterclockwise to minimize pen motion on the plotter. This has C the drawback of uneven lines on the left and top when the starting C tick mark does not lie on the edge of the graph, which only occurs C with DRAW. If you comment out the next line, it always draws tick C marks in ascending direction. C.DEFINE PLOTTER C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) CALL NEWPEN (IPEN(6)) !COLOUR FOR MAJOR TICKS DX1 = DX / 10.0 DY1 = DY / 10.0 C C DRAW MAJOR TICKS C IFF (NOHASH .EQ. 0) THEN { CALL GRAXXY (2, 0, YPLOTB, YPLOTT, XSC1, XSC0, -DX, 1 XSCALE, XLSAVE, XPLOTL) !VERTICALS CALL GRAXXY (1, 0, XPLOTL, XPLOTR, YSC1, YSC0, -DY, 1 YSCALE, YBSAVE, YPLOTB) !HORIZONTALS } ELSE { .IFDF PLOTTER CALL GRAXXY (1, 0, XPLOTR, XPLOTR-HITE(6), YSC0, YSC1, DY, 1 YSCALE, YBSAVE, YPLOTB) !RIGHT CALL GRAXXY (2, 0, YPLOTT, YPLOTT-HITE(6), XSC1, XSC0, -DX, 1 XSCALE, XLSAVE, XPLOTL) !TOP CALL GRAXXY (1, 0, XPLOTL, XPLOTL+HITE(6), YSC1, YSC0, -DY, 1 YSCALE, YBSAVE, YPLOTB) !LEFT CALL GRAXXY (2, 0, YPLOTB, YPLOTB+HITE(6), XSC0, XSC1, DX, 1 XSCALE, XLSAVE, XPLOTL) !BOTTOM .ENDC .IFNDF PLOTTER CALL GRAXXY (2, 0, YPLOTB, YPLOTB+HITE(6), XSC0, XSC1, DX, 1 XSCALE, XLSAVE, XPLOTL) !BOTTOM CALL GRAXXY (1, 0, XPLOTR, XPLOTR-HITE(6), YSC0, YSC1, DY, 1 YSCALE, YBSAVE, YPLOTB) !RIGHT CALL GRAXXY (2, 0, YPLOTT, YPLOTT-HITE(6), XSC0, XSC1, DX, 1 XSCALE, XLSAVE, XPLOTL) !TOP CALL GRAXXY (1, 0, XPLOTL, XPLOTL+HITE(6), YSC0, YSC1, DY, 1 YSCALE, YBSAVE, YPLOTB) !LEFT .ENDC } C C DRAW MINOR TICKS C IFF (NOTICK .EQ. 0) THEN { CALL NEWPEN (IPEN(7)) .IFDF PLOTTER CALL GRAXXY (1, LOGARY, XPLOTR, XPLOTR-HITE(7), YSC0, YSC1, DY1, 1 YSCALE, YBSAVE, YPLOTB) !RIGHT CALL GRAXXY (2, LOGARX, YPLOTT, YPLOTT-HITE(7), XSC1, XSC0, -DX1, 1 XSCALE, XLSAVE, XPLOTL) !TOP CALL GRAXXY (1, LOGARY, XPLOTL, XPLOTL+HITE(7), YSC1, YSC0, -DY1, 1 YSCALE, YBSAVE, YPLOTB) !LEFT CALL GRAXXY (2, LOGARX, YPLOTB, YPLOTB+HITE(7), XSC0, XSC1, DX1, 1 XSCALE, XLSAVE, XPLOTL) !BOTTOM .ENDC .IFNDF PLOTTER CALL GRAXXY (2, LOGARX, YPLOTB, YPLOTB+HITE(7), XSC0, XSC1, DX1, 1 XSCALE, XLSAVE, XPLOTL) !BOTTOM CALL GRAXXY (1, LOGARY, XPLOTR, XPLOTR-HITE(7), YSC0, YSC1, DY1, 1 YSCALE, YBSAVE, YPLOTB) !RIGHT CALL GRAXXY (2, LOGARX, YPLOTT, YPLOTT-HITE(7), XSC0, XSC1, DX1, 1 XSCALE, XLSAVE, XPLOTL) !TOP CALL GRAXXY (1, LOGARY, XPLOTL, XPLOTL+HITE(7), YSC0, YSC1, DY1, 1 YSCALE, YBSAVE, YPLOTB) !LEFT .ENDC } C C FRAME THE PLOT WITH THREE STROKES C CALL NEWPEN (IPEN(8)) DELTA = HITE(8) IP = 3 FOR J=1,3 { CALL PLOT (XPLOTR+DELTA, YPLOTB-DELTA, IP) IP = 2 CALL PLOT (XPLOTR+DELTA, YPLOTT+DELTA, IP) CALL PLOT (XPLOTL-DELTA, YPLOTT+DELTA, IP) CALL PLOT (XPLOTL-DELTA, YPLOTB-DELTA, IP) CALL PLOT (XPLOTR+DELTA, YPLOTB-DELTA, IP) DELTA = DELTA - HITE(8)/2.0 } RETURN END SUBROUTINE GRAXXY (IDIR, LOGAR, X0, X1, Y0, Y1, DY, 1 SCALE, SC0, PLOTB) C C INTERNAL SUBROUTINE USED BY GRAXIL TO GENERATE SETS OF HORIZONTAL C OR VERTICAL LINES. THE DIRECTION IS DETERMINED BY IDIR: C IDIR = 1 => HORIZONTAL LINES C IDIR = 2 => VERTICAL LINES C FOR HORIZONTAL LINES, ALL LINES GO FROM X0 TO X1 (IN INCHES). C THEY START AT Y0 AND EVERY DY UNTIL Y1 (IN USER UNITS). C FOR VERTICAL LINES, ALL LINES GO FROM Y0 TO Y1 (IN INCHES). C ALL SETS OF LINES CAN BE DRAWN IN EITHER DIRECTION, I.E. UP OR DOWN. C LOG SCALES ARE HANDLED EXACTLY THE SAME AS LINEAR SCALES SINCE C THE LIMITS ARE IN TERMS OF THE LOGS OF THE ACTUAL LIMITS AND DX=1. C THE EXCEPTION IS FOR THE MINOR TICK MARKS BETWEEN MAJOR TICKS: C FOR LOG SCALES, SET LOGAR TO 1 AND DY TO 0.1, AND IT WILL PUT C MINOR LOG TICKS IN EVERY DECADE, EITHER DIRECTION. C SCALE IS THE SCALE FACTOR CORRESPONDING TO THE DIRECTION OF Y, C SC0 IS THE BOTTOM USER UNIT CORRESPONDING TO Y, AND PLOTB IS C THE COORDINATE IN INCHES OF THE BOTTOM OF THE GRAPH (LEFT FOR C IDIR=1). C THIS PROGRAM HAS BEEN WRITTEN WITH X/Y VARIABLES LABELED SUCH C THAT IT SEEMS TO BE PLOTTING A SCALE ALONG THE Y-AXIS, WHEN C IDIR=1. WHEN IDIR=2, THIS X/Y CONVENTION SHOULD MENTALLY BE C REVERSED. C Y = Y0 YMAX = Y1 + 0.05*DY N = 1 TERM = 0.0 IFF (LOGAR .NE. 0) THEN { !LOG TICK MARKS YMAX = Y1 - 0.5*DY N = 9 IF (DY .LT. 0.0) TERM = 10.0*DY } WHILE ( (DY .GT. 0.0 .AND. Y .LT. YMAX) 1 .OR. (DY .LT. 0.0 .AND. Y .GT. YMAX) ) { FOR J=1,N { YP = ( Y + ALOG10( FLOAT(J) ) + TERM - SC0) * SCALE + PLOTB IFF (IDIR .EQ. 1) THEN { CALL PLOT (X0, YP, 3) CALL PLOT (X1, YP, 2) } ELSE { CALL PLOT (YP, X0, 3) CALL PLOT (YP, X1, 2) } } IF (LOGAR .EQ. 0) Y = Y + DY IF (LOGAR .NE. 0) Y = Y + 10.0*DY } RETURN END SUBROUTINE GRNUML (IDIR, LOGAR, XL, XR, DX, XLS, SCALE, PLOTL, NDEC) C C [PLACE NUMBERS ON GRID] C C THIS WRITES IN THE SCALE VALUES OPPOSITE THE MARKERS WHICH ARE THERE NOW. C XL, XR AND DX ARE IN USER'S UNITS. C THE SCALE RUNS FROM XL TO XR IN STEPS OF DX. THE AXIS TO BE LABELLED C IS SELECTED BY IDIR=1 FOR X, AND IDIR=2 FOR Y. LOGAR IS SET TO 0 C FOR LINEAR AXIS, 1 FOR LOG AXIS, IN WHICH CASE THE NUMBERS ARE WRITTEN C AS 10**X. THE NUMBERS MUST BE INCREASING. C SCALE IS THE SCALE FACTOR, XLS IS THE LEFT EDGE IN USER UNITS, C AND PLOTL IS THE LEFT GRAPH LIMIT IN INCHES. C IT SETS XLMOST TO THE POSITION OF THE LEFTMOST LABEL FOR USE BY GRTITL. C NDEC IS THE NUMBER OF DIGITS TO THE RIGHT OF THE DECIMAL POINT REQUIRED C TO PRINT THE SCALE NUMBERS; -1 MEANS NO DECIMAL POINT. C COMMON /GRAFCX/ XPLOTL, XPLOTR, YPLOTB, YPLOTT, DXSAVE, DYSAVE, 1 XLSAVE, XRSAVE, YBSAVE, YTSAVE, NUSCAL, NOGRID, NSYMBO, 2 NOHASH, NOTICK, LOGARX, LOGARY, XSCALE, YSCALE, XLMOST, 3 NOSIZE, IPEN(10), HITE(10) CALL NEWPEN (IPEN(3)) X = XL DX1 = 0.05*DX WHILE (X .LE. XR+DX1) { XP = (X-XLS) * SCALE + PLOTL IF (ABS(X) .LT. DX1) X = 0.0 !ACCOUNT FOR ROUNDOFF NEAR 0 IFF (IDIR .EQ. 1) THEN { !X AXIS LABEL XC = XP YC = YPLOTB - 1.66*HITE(3) JUSTIF = 0 !CENTER NUMBERS ON X AXIS } ELSE { XC = XPLOTL - AMIN1( 1.3*HITE(3), 0.12 ) YC = AMAX1( XP - 0.5*HITE(3), YPLOTB ) JUSTIF = 1 !RIGHT JUSTIFY NUMBERS ON Y AXIS } H = HITE(3) IF (LOGAR .NE. 0) H = 0.85 * H CALL GRNUMB (XC, YC, H, X, NDEC, JUSTIF, XA, YA) IF (IDIR .EQ. 2) XLMOST = AMIN1( XLMOST, XA ) !LEFTMOST LABEL C C FOR LOG SCALE, WE ADD THE BASE 10 HERE. IF WE WERE SURE WE C WOULDN'T USE THE HARDWARE CHARACTER SETS, WE COULD USE THE C SOFTWARE SET'S 10{N} STYLE. C IFF (LOGAR .NE. 0) THEN { !ADD 10 TO LOWER LEFT FOR LOG SCALES XE = XA - 0.2*HITE(3) YE = YA - 0.6*HITE(3) XLM = XA - 2.2*HITE(3) CALL SYMBOC (XE, YE, HITE(3), '10', 0.0, 2, 1) IF (IDIR .EQ. 2) XLMOST = AMIN1( XLMOST, XLM ) } X = X+DX } RETURN END SUBROUTINE GRNUMB (X, Y, HEIGHT, FNUM, NDEC, JUSTIF, XP, YP) C C DRAWS A DECIMAL NUMBER AT LOCATION X,Y. C C X,Y = POSITION IN INCHES FROM THE CURRENT ORIGIN WHERE LOWER C LEFT CORNER OF FIRST CHARACTER WILL GO. C HEIGHT = HEIGHT IN INCHES OF CHARACTER. C FNUM = REAL NUMBER TO BE WRITTEN. C NDEC = NUMBER OF DECIMAL PLACES AFTER DECIMAL POINT [0:8]. C FOR NDEC >= 0, USE F FORMAT, FOR NDEC < 0, USE E FORMAT. C JUSTIF = -1 FOR LEFT-JUSTIFY NUMBER, C 1 FOR RIGHT-JUSTIFY NUMBER, C 0 FOR CENTER NUMBER AT X,Y. C XP, YP = LOCATION OF LOWER LEFT POINT WHERE PLOTTING OF STRING BEGINS. C BYTE TEXT(15), FMT1(9), FMT2(7) LOGICAL FFMT DATA FMT1 / '(', '1', 'P', 'E', '1', '5', '.', '2', ')' / DATA FMT2 / '(', 'F', '1', '5', '.', '2', ')' / C C THINK ABOUT WHAT FORMAT TO USE, DEPENDING ON NUMBER OF DIGITS C NDECM = MAX0( 0, MIN0( IABS(NDEC), 8 ) ) ALGNUM = ALOG10( AMAX1( ABS(FNUM), 1E-37) ) + 1.0!NUMBER OF DIGITS TO LEFT NDIGIT = FLOAT(NDEC) + AMAX1( 0.0, ALGNUM ) !NUMBER OF DIGITS IN ALL C C CAN USE F FORMAT WHEN NDEC <= 0, WHEN THE NUMBER IS ZERO, C AND WHEN THERE ARE NEITHER TOO FEW NOR TOO MANY DIGITS. C IFF (NDEC .GE. 0 .AND. ( FNUM .EQ. 0.0 .OR. ( NDIGIT .LT. 7 .AND. 1 (ALGNUM .GE. 0.0 .OR. 1.0-FLOAT(NDECM) .LE. ALGNUM ) ) ) ) THEN { !F FORMAT FMT2(6) = "60 + NDECM !FORMAT (F15.N) IF (FNUM .EQ. 0.0) FMT2(6) = "60 !NO DECIMALS AFTER ZERO ENCODE (15, FMT2, TEXT) FNUM FFMT = .TRUE. } ELSE { !E FORMAT FMT1(8) = "60 + NDECM !FORMAT (1PE15.N) ENCODE (15, FMT1, TEXT) FNUM !ENCODE NUMBER INTO TEXT FFMT = .FALSE. } C C DROP LEADING BLANKS C FOR J=1,15 IF (TEXT(J) .NE. "40 .AND. TEXT(J) .NE. "44) GO TO 300 C C DROP DECIMAL POINT FOR WHOLE NUMBER C 300 L = 15 IF (FFMT .AND. (NDEC .EQ. 0 .OR. FNUM .EQ. 0.0) ) L = 14 !DROP DECIMAL POINT C C PLOT THE NUMBER, IN TEXT(J:L) C NCHAR = L-J+1 !NUMBER OF CHARACTERS CALL SYMBOC (X, Y, HEIGHT, TEXT(J), 0.0, NCHAR, JUSTIF) C C ESTIMATE LOWER LEFT COORDINATE OF STRING JUST PLOTTED. C NOTE THAT THIS IS JUST AN ESTIMATE, SINCE WE REALLY DON'T KNOW C AT THIS TIME WHETHER A HARDWARE OR SOFTWARE CHARACTER SET IS IN USE. C XP = X - 0.95 * HEIGHT * FLOAT(NCHAR) * (FLOAT(JUSTIF)+1.0) / 2.0 YP = Y RETURN END FUNCTION ALOG9 (X) C C [FOLDED LOGARITHM] C RETURNS THE LOG BASE 10 OF X IF X>0, ELSE RETURNS C LOG10 -X IF X<0. C THIS SAVES ERROR MESSAGES WHEN SOMEONE TRIES TO PLOT NEGATIVE C VALUES ON A LOG SCALE, AS THEY WILL TRY TO DO SOMETIME. C ALOG9 = -39.0 IF (X .EQ. 0.0) RETURN ALOG9 = ALOG10( ABS(X) ) RETURN END