home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Science
/
Science.zip
/
ABCPLOT.ZIP
/
ABCPLOT.FOR
< prev
next >
Wrap
Text File
|
1991-04-02
|
20KB
|
523 lines
C======================================================================
SUBROUTINE ABCPLT(FILNAM,NCURV,IX,IY,ICAT,ITYPE,ISWTCH,ITEXT,OUTF)
C
C Version 6.0, December 1989.
C (Arrays condensed from version 5.0 to allow 50% longer
C and 500% wider data files.)
C
C Designed and written in FORTRAN
C by Robert L. Dougherty
C
C C-language command line parser (main program)
C by Ryan Rumanang; revised by Ting Liang and
C Robert L. Dougherty
C
C Warning: Non-ANSI-Standard Fortran (END DO statements are used).
C
C ABCPLT is a group of subroutines that read data from a
C file and plot the data to the terminal or an output file.
C
C A front end for this subroutine has been written in C.
C The front end allows the use of a command line that
C gives the name of the input data file and provides
C several graphing options.
C
C As written, the program requires one data file, whose name
C is passed to ABCPLT from the calling program. (The calling
C program can create a temporary file if data are piped from
C standard input). This data file MUST have at least 2 lines,
C it MUST contain ONLY numbers that are readable by FORTRAN in
C list format; each line of the file MUST contain the same
C number of numbers. ABCPLT assumes these conditions, but it
C does not check for them. Unpredictable results will occur if
C these conditions are not met!
C
C The program consists of this routine and 8 other subroutines:
C
C COUNT -- Finds out how many lines are in the raw data file,
C and how many fields are in the first line.
C DATFILE -- Reads the contents of the raw data file into a
C data matrix.
C TCDFOPEN -- Opens and prepares to read the data file, ignoring
C commented lines above the actual data.
C DATCHEK -- Checks the data matrix for a valid categorical
C variable.
C UNIQUE -- Called by DATCHEK. Determines the number of unique
C values in an array.
C ASSIGN -- Assigns the proper elements of the data matrix to
C the plotting arrays. Used when data not categorical.
C DATAORG -- Used when dataset contains a categorical variable.
C Assigns the proper elements of the data matrix, by
C category, to the plotting arrays.
C PLOT -- Does the actual plotting.
C----------------------------------------------------------------------
C Set parameters for sizes of arrays. These can be changed within
C the limits allowed by available memory.
C Maximum # of records in the input data file.
PARAMETER (MAXN=3000)
C Maximum # of fields in the input data file.
PARAMETER (MAXM=100)
C Maximum # of curves.
PARAMETER (MAXC=10)
C Use the NEAR attribute for those variables passed from the C
C module.
INTEGER NCURV [NEAR],IX [NEAR],IY [NEAR],ICAT [NEAR],
+ ITYPE [NEAR],ISWTCH [NEAR],ITEXT [NEAR]
CHARACTER*80 FILNAM [NEAR], OUTF [NEAR]
DIMENSION IY(MAXC)
DIMENSION X(MAXN),Y(MAXC,MAXN),IDX(MAXN),CAT(MAXN),WORK(MAXN)
DIMENSION DATLIN(MAXM)
C Inspect the data file and find out how many cases and fields.
CALL COUNT(FILNAM,MAXM,DATLIN,NCASE,NFIELD)
IF (NCASE .GT. MAXN) THEN
write(*,*)"ERROR! Too many lines in data file!"
STOP
END IF
C Read the raw data file with the data.
CALL DATFILE(FILNAM,NCASE,NFIELD,MAXN,MAXM,MAXC,X,Y,ICAT,DATLIN,
+ IX,IY,CAT,NCURV)
C Decide whether the data set can be treated as categorical
KATEGOR=1
IF(ICAT.NE.0)THEN
CALL DATCHEK(MAXN,X,CAT,WORK,NCASE,IDX,KATEGOR)
END IF
C Call the appropriate subroutine to read data into X and Y vectors.
IF ((KATEGOR .GT. 1) .AND. (KATEGOR .LE. 10)) THEN
CALL DATAORG(MAXN,MAXC,NCASE,NCURV,WORK,
+ IDX,CAT,KATEGOR,X,Y)
ENDIF
C Use 6 as logical unit for output.
LUNOUT=6
C If output is to go on file, open file.
IF (ITYPE .EQ. 0) OPEN (UNIT=LUNOUT, FILE=OUTF)
IF (ITEXT .EQ. 1) THEN
C Write the data.
DO I=1,NCASE
WRITE(LUNOUT,*)X(I),(Y(J,I),J=1,NCURV)
END DO
ELSE
C Plot the data.
CALL PLOT (MAXN,MAXC,NCURV,NCASE,X,Y,WORK,ITYPE,ISWTCH,10)
END IF
C Return to the calling (C language) routine
RETURN
END
C======================================================================
SUBROUTINE COUNT(FN,MAXM,XYZ,NLINES,NFIELDS)
C A program to count the number of lines and the number of fields
C per line in a data file. Requires data file with at least 2 records
C and with only numeric data. Assumes that all records have the same
C number of fields. No more than 100 records per line.
C----------------------------------------------------------------------
DIMENSION XYZ(MAXM)
CHARACTER*80,FN
CHARACTER*800,TXT
CALL TCDFOPEN(12,FN)
C
C Find out how many lines, by reading the first field in each record.
C
NLINES=0
10 READ(12,*,END=11)X
NLINES=NLINES+1
GOTO 10
11 CONTINUE
CLOSE(12)
CALL TCDFOPEN(12,FN)
C Find out how many fields.
C Read the first line AS TEXT, then write it to a separate scratch file.
READ(12,100)TXT
CLOSE(12)
C Open a scratch file.
OPEN(UNIT=13,STATUS='UNKNOWN')
WRITE(13,100)TXT
C Read the numbers from the scratch file into vector.
C Repeat the READ for an increasing number of vector elements.
C When an error occurs, we've tried to read too many elements.
DO J=1,MAXM+1
NFIELDS=J-1
REWIND(13)
READ(13,*,ERR=14)(XYZ(I),I=1,J)
END DO
CLOSE(13)
C The only way to get here is if no error occurred: more fields in
C the data line than the value of maxm.
WRITE(*,200)
200 format(' ALERT: More data elements than allowed!')
NFIELDS=MAXM
GOTO 2
14 CLOSE(13)
2 CONTINUE
100 FORMAT(A800,I5)
CLOSE(UNIT=12)
13 RETURN
END
C======================================================================
SUBROUTINE DATFILE(FN,N,M,MAXN,MAXM,MAXC,X,Y,ICAT,DATLIN,IX,IY,
+ CAT,NCURV)
C This subroutine reads the numbers in a file into a data matrix,
C storing only those numbers needed for the plot.
C----------------------------------------------------------------------
CHARACTER*80 FN
DIMENSION X(MAXN),Y(MAXC,MAXN),CAT(MAXN),DATLIN(MAXM),IY(MAXC)
CALL TCDFOPEN(12,FN)
DO I=1,N
C Read a line at a time, then parse into the data matrices
READ(12,*)(DATLIN(J),J=1,M)
C Get the X-variable.
C If no explicit X-variable, create it.
IF (IX .EQ. 0) THEN
X(I)=REAL(I)
ELSE
X(I)=DATLIN(IX)
END IF
C The Y variables are stored in the columns of the Y matrix.
DO J=1,NCURV
Y(J,I)=DATLIN(IY(J))
END DO
C The category variable is stored in the CAT vector.
IF (ICAT .NE. 0) THEN
CAT(I)=DATLIN(ICAT)
END IF
END DO
CLOSE(UNIT=12)
RETURN
END
C======================================================================
SUBROUTINE TCDFOPEN(LUN,CDFNAM)
C Top-Commented Data File OPEN routine.
C
C Use TCDFOPEN, rather than OPEN, to open a data file that your
C program will read, so you can place comment lines above the
C actual data lines. The comment lines won't be seen by your
C program.
C
C TCDFOPEN is similar to its partner routine, CDFOPEN. But
C TCDFOPEN differs from CDFOPEN in several important ways.
C First, it only works with files that have all comment lines
C at the top. Next, instead of reading the entire file,
C TCDFOPEN only has to read the comment lines, position the
C file pointer to the first non-comment line, and exit.
C The calling program will then read from the file itself, not
C a copy of it. This reduces disk space needed for scratch files
C and saves time, especially with long files. I use it with
C long database-type files such as weather records.
C
C Arguments:
C LUN: Logical Unit Number to be associated with the file.
C CDFNAM: Commented Data File NAMe. A character string that names
C the file.
C
C Programmed by Bob Dougherty, USDA-ARS, Woodward, OK 73801
C
C----------------------------------------------------------------------
IMPLICIT INTEGER (A-Z)
C
CHARACTER CDFNAM*(*)
CHARACTER*1 POS1
C These indented statements may have to be changed for your application.
C Number of possible comment characters
PARAMETER (NCOM=4)
C Declare and define a string containing the possible
C characters used in first position of line for comment:
CHARACTER*4 COM
DATA COM/'"!#*'/
C End of application-specific statements.
C
C Open the commented data file. Use the temporary unit #.
OPEN (FILE=CDFNAM,UNIT=LUN,STATUS='OLD')
C
C Read each line of the commented data file; check for comments.
1 CONTINUE
READ(LUN,101,END=2) POS1
101 FORMAT(A1)
DO I=1,NCOM
IF (POS1 .EQ. COM(I:I)) GOTO 1
END DO
2 CONTINUE
C Reposition to the line just read.
BACKSPACE (LUN)
RETURN
END
C======================================================================
SUBROUTINE DATCHEK(MAXN,X,CAT,ARRAY1,N,IDX,KATEGOR)
DIMENSION IDX(MAXN),X(MAXN),CAT(MAXN),ARRAY1(MAXN)
C Some datasets will have one independent variable,
C one dependent variable, and one category variable.
C This program checks that the number of unique values
C in the category variable, times the number of unique
C values in the x-variable, is equal to the number of
C cases in the dataset. Note that this is not a rigorous
C test for the presence of a categorical variable.
C----------------------------------------------------------------------
C Presume it's not categorical unless determined otherwise.
KATEGOR=1
C How many unique values are in the supposed category column?
CALL UNIQUE(MAXN,N,CAT,ARRAY1,NUMCAT,IDX)
C Replace the category's value with its ID number.
DO I=1,N
CAT(I)=REAL(IDX(I))
END DO
C If more than 1 categories, OK
IF (NUMCAT .GT. 1) THEN
C How many unique values of the independent variable?
CALL UNIQUE(MAXN,N,X,ARRAY1,NUMX,IDX)
C Is the product of the 2 numbers of unique values
C the same as the number of cases in this data set?
IF (NUMX*NUMCAT .EQ. N) THEN
KATEGOR=NUMCAT
END IF
END IF
RETURN
END
C======================================================================
SUBROUTINE UNIQUE(MAXN,N,ARRAY,UNIQ,NUMUNIQ,ID)
C This subroutine answers the questions,
C "How many unique values are there in ARRAY?
C and "What is the category of each value in ARRAY?)
C (actually, the first N rows of ARRAY)
C----------------------------------------------------------------------
DIMENSION ARRAY(MAXN),UNIQ(MAXN),ID(MAXN)
C The first case is always unique.
NUMUNIQ=1
UNIQ(1)=ARRAY(1)
ID(1)=1
C examine each case after the first
DO I=2,N
C assume initially that this case is unique.
IMUNIQ=1
C Look at all known unique values, compare this value to each.
J=0
C While j <= numuniq, do the following
1 IF(J.LT.NUMUNIQ) THEN
J=J+1
C If this datum is the same as a known unique, it's not unique.
IF (ARRAY(I).EQ.UNIQ(J)) THEN
IMUNIQ=0
C Identify the datum by its category
ID(I)=J
C Set J so this loop will not continue
J=NUMUNIQ
ENDIF
GOTO 1
ENDIF
IF (IMUNIQ .EQ. 1)THEN
C Increment the number of unique values
NUMUNIQ=NUMUNIQ+1
C Add the datum to the list of unique values
UNIQ(NUMUNIQ)=ARRAY(I)
C Identify the datum by its category
ID(I)=NUMUNIQ
END IF
END DO
RETURN
END
C======================================================================
SUBROUTINE DATAORG(MAXN,MAXC,N,NCURV,WORKX,IDX,CAT,KATEGOR,X,Y)
C----------------------------------------------------------------------
DIMENSION X(MAXN),Y(MAXC,MAXN),WORKX(MAXN)
DIMENSION IDX(MAXN),CAT(MAXN)
DO I=1,N
WORKX(I)=X(I)
END DO
DO I=1,N
C The value of IDX for this case tells which unique value of X it is.
KASE=IDX(I)
X(KASE)=WORKX(I)
C The value of IDCAT tells which category this case is for.
KAT=REAL(CAT(I))
Y(KAT,KASE)=Y(1,I)
END DO
C Calculate new values for NCURV and N.
NCURV=KATEGOR
N=N/KATEGOR
RETURN
END
C======================================================================
SUBROUTINE PLOT (MAXN,MAXC,NPLOTS,NPTS,X,Y,YN,IFLAG,ISWTCH,LUNIT)
C Subroutine written by Bob Dougherty, Nov. 1982 (revised Aug. 1984)
C Based on a routine written by George Innis.
C This routine does simple line printer or dumb terminal plots, and can
C print up to 10 dependent variables against 1 independent variable.
C The call for this subroutine,
C CALL PLOT (NPLOTS,NPTS,X,Y,YN,IFLAG)
C is issued only once for a graph. The parameters are
C NPLOTS -- The total number of plots on the graph;
C NPTS -- The number of values that each variable takes;
C X -- An array containing the values of the ind. variable;
C Y -- An array containing the values of each of the dep. variables;
C YN -- An array which has no values. Its use is internal to the
C subroutine but it must be named in the call.
C IFLAG -- indicates whether the plot is to be a printer plot (for
C IFLAG=0) or a terminal plot (for IFLAG=1)
C ISWTCH -- Indicates whether the axes are to be switched (0=normal
C 1=switched)
C LUNIT -- The logical unit # if writing output to a file.
C Note: the program that calls this subroutine must dimension
c the arrays X, Y, and YN as follows:
C X(NPTS)
C Y(NPLOTS,NPTS)
C YN(NPTS)
C Note that each value in X corresponds to (NPLOTS) values in Y.
C For example, a printed graph of 3 plots, each with 20 points,
C may be called in this form:
C CALL PLOT(3,20,X,Y,YN,0)
C In this case, the following dimension statements in the main program
C would represent the minimum required array space:
C DIMENSION X(20),Y(3,20),YN(20)
C Here, Y(2,5) is Y-value of the 5th point in the 2nd plot . Its geometric
C location on the graph will be [X(5),Y(2,5)].
C For the case in which only one curve is needed, Y need only be dimensioned
C as (NPTS), and its values can be singly subscripted.
C----------------------------------------------------------------------
REAL X(MAXN),Y(MAXC,MAXN),YN(MAXN)
INTEGER COLUMNS
CHARACTER*1,BLANK,GRAPH(121,51)
CHARACTER*1,ISYM(10),ISYMBOL,ISYM1,ISYM2,BORDER
C
C ISYM is a vector containing the characters to represent points.
C ISYM2 is the character to represent overlapping points.
DIMENSION ZX(13)
DATA ISYM/'A','B','C','D','E','F','G','H','I','J'/,ISYM2/'*'/
DATA BORDER/'+'/
C Assign values for size of plot, based on the value of 'iflag'.
IF (IFLAG .EQ. 0) THEN
C Assign values for printer plot.
LINES=51
COLUMNS=109
NXTICK=7
ELSE
C Assign values for terminal plot.
LINES=18
COLUMNS=65
NXTICK=5
ENDIF
C Find maximum and minimum values of independent variable
XMIN=X(1)
XMAX=X(1)
DO I=1,NPTS
IF (X(I) .GT. XMAX) XMAX=X(I)
IF (X(I) .LT. XMIN) XMIN=X(I)
END DO
C Find maximum and minimum values of all dependent variables
YMIN=Y(1,1)
YMAX=Y(1,1)
DO I=1,NPLOTS
DO J=1,NPTS
IF (Y(I,J) .GT. YMAX) YMAX=Y(I,J)
IF (Y(I,J) .LT. YMIN) YMIN=Y(I,J)
END DO
END DO
C Initialize the graph matrix. Fill it with blanks.
BLANK =' '
DO I=1,COLUMNS
DO J=1,LINES
GRAPH(I,J)=BLANK
END DO
END DO
C Establish the scaling factors for the x and the y directions.
IF (ISWTCH .EQ. 0) THEN
XSCALE=(XMAX-XMIN)/(COLUMNS-1)
YSCALE=(YMAX-YMIN)/(LINES-1)
ELSE
XSCALE=(XMAX-XMIN)/(LINES-1)
YSCALE=(YMAX-YMIN)/(COLUMNS-1)
C Initialize the numbers to be used as tick labels on X axis.
END IF
IF (ISWTCH .EQ. 0) THEN
DO K=1,NXTICK
ZX(K)=(XMAX-XMIN)/(NXTICK-1)*(K-1)+XMIN
END DO
ELSE
DO K=1,NXTICK
ZX(K)=(YMAX-YMIN)/(NXTICK-1)*(K-1)+YMIN
END DO
END IF
C Fill the array yn in turn with each y vector; place symbol in graph matrix.
DO NCURV=1, NPLOTS
DO J=1,NPTS
YN(J)=Y(NCURV,J)
END DO
ISYM1=ISYM(NCURV)
C Put points for this curve in graph
DO I=1,NPTS
ISYMBOL=ISYM1
XX=X(I)
YY=YN(I)
IF (ISWTCH .EQ. 0) THEN
IX=(XX-XMIN)/XSCALE+1.5
IY=(YY-YMIN)/YSCALE+.5
ELSE
IY=(XX-XMIN)/XSCALE+.5
IX=(YY-YMIN)/YSCALE+1.5
END IF
IY=LINES-IY
IF (GRAPH(IX,IY).NE.BLANK) ISYMBOL=ISYM2
GRAPH(IX,IY)= ISYMBOL
ISYMBOL=ISYM1
END DO
END DO
C
C Print the graph
C
IF (ISWTCH .EQ. 1) THEN
YMAX=XMAX
YSCALE=XSCALE
END IF
IF (IFLAG .EQ. 0) THEN
WRITE(LUNIT,501)
YES=YMAX+YSCALE
DO I=1,LINES
YES=YES-YSCALE
WRITE(LUNIT,502)YES,BORDER,(GRAPH(J,I),J=1,COLUMNS),
+ BORDER,YES
END DO
WRITE(LUNIT,503)
WRITE(LUNIT,504)(ZX(I),I=1,NXTICK)
ELSE
WRITE(*,601)
YES=YMAX+YSCALE
DO I=1,LINES
YES=YES-YSCALE
WRITE(*,602)YES,BORDER,(GRAPH(J,I),J=1,COLUMNS),BORDER
END DO
WRITE(*,601)
WRITE(*,604)(ZX(I),I=1,NXTICK)
ENDIF
501 FORMAT(12X,'+',6(17('-'),'+'))
502 FORMAT(' ',E9.3,1X,1A1,109A1,1A1,1X,E9.3)
503 FORMAT(1H ,11X,'+',6(17('-'),'+'))
504 FORMAT (5X,E9.3,6(9X,E9.3))
601 FORMAT(12X,'+',4(15('-'),'+'))
602 FORMAT(' ',E9.3,1X,1A1,65A1,1A1)
604 FORMAT (6X,E9.3,4(7X,E9.3))
RETURN
END