PLOTT Subroutine

public subroutine PLOTT(Y, X, N)

NAME

plott(3f) - [M_datapac:GENERIC_LINE_PLOT] generate a line printer
plot of Y vs X for the terminal (71 characters wide)

SYNOPSIS

   SUBROUTINE PLOTT(Y,X,N)

    REAL(kind=wp),intent(in) :: X(:)
    REAL(kind=wp),intent(in) :: Y(:)
    INTEGER,intent(in)       :: N

DESCRIPTION

PLOTT(3f) yields a narrow-width (71-character) plot of Y(i) versus
X(i). Its narrow width makes it appropriate for use on a terminal.

Note values in the vertical axis vector (y) or the horizontal axis
vector (x) which are equal to or in excess of 10.0**10 will not
be plotted.

This convention greatly simplifies the problem of plotting when
some elements in the vector y (or x) are 'missing data', or when
we purposely want to ignore certain elements in the vector y (or x)
for plotting purposes (that is, we do not want certain elements in
y (or x) to be plotted). To cause specific elements in y (or x)
to be ignored, we replace the elements beforehand (by, for example,
use of the REPLAC(3f) subroutine) by some large value (like, say,
10.0**10) and they will subsequently be ignored in the plot subroutine.

Note that the storage requirements for this (and the other) terminal
plot subroutines are very small. This is due to the "one line at
a time" algorithm employed for the plot.

INPUT ARGUMENTS

Y The vector of (unsorted or sorted) observations to be plotted vertically.

X The REAL vector of (unsorted or sorted) observations to be plotted horizontally.

N The integer number of observations in the vector Y. There is no restriction on the maximum value of N for this subroutine.

OUTPUT

A narrow-width (71-character) terminal plot of y(i) versus x(i).
The body of the plot (not counting axis values and margins) is 25 rows
(lines) and 49 columns.

EXAMPLES

Sample program:

  program demo_plott
  use M_datapac, only : plott, label
  implicit none
  integer ::  i
  integer,parameter :: dp=kind(0.0d0)
  real(kind=dp), allocatable ::  x(:), y(:)
     call label('plott')
     y=[(real(i)/10.0,i=1,30)]
     x=y**3.78-6*y**2.52+9*y**1.26
     call plott(x,y,size(x))
  end program demo_plott

Results:

 The following is a plot of Y(I) (vertically) versus X(I) (horizontally)
                   I-----------I-----------I-----------I-----------I
  0.4000000E+01 -               X X X                              X
  0.3833356E+01 I              X     X
  0.3666712E+01 I                      X
  0.3500068E+01 I            X
  0.3333424E+01 I                        X
  0.3166780E+01 I          X
  0.3000137E+01 -                         X
  0.2833493E+01 I         X
  0.2666849E+01 I                                                X
  0.2500205E+01 I                           X
  0.2333561E+01 I       X
  0.2166917E+01 I                            X
  0.2000273E+01 -
  0.1833629E+01 I
  0.1666985E+01 I     X                        X                X
  0.1500341E+01 I
  0.1333698E+01 I                                X
  0.1167054E+01 I
  0.1000410E+01 -    X
  0.8337659E+00 I                                 X           X
  0.6671220E+00 I
  0.5004781E+00 I  X                                X
  0.3338342E+00 I                                           X
  0.1671903E+00 I                                     X    X
  0.5463774E-03 -                                      X X
                   I-----------I-----------I-----------I-----------I
            0.1000E+00  0.8250E+00  0.1550E+01  0.2275E+01  0.3000E+01

AUTHOR

The original DATAPAC library was written by James Filliben of the
Statistical Engineering Division, National Institute of Standards
and Technology.

MAINTAINER

John Urban, 2022.05.31

LICENSE

CC0-1.0

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: Y(:)
real(kind=wp), intent(in) :: X(:)
integer, intent(in) :: N

Source Code

SUBROUTINE PLOTT(Y,X,N)
REAL(kind=wp),intent(in) :: X(:)
REAL(kind=wp),intent(in) :: Y(:)
INTEGER,intent(in)       :: N
REAL(kind=wp) :: aim1, airow, anumcm, anumlm, anumr, anumrm
REAL(kind=wp) :: cutoff,  delx, dely, hold, xlable, xmax, xmin, xwidth, ylable, ylower, ymax, ymin
REAL(kind=wp) :: yupper, ywidth
INTEGER       :: i, icol, icolmx, irow, ixdel, n2, numcol, numlab, numr25, numr50, numr75, numrow
CHARACTER(len=4) :: iline
CHARACTER(len=4) :: iaxisc
CHARACTER(len=4) :: sbnam1 , sbnam2
CHARACTER(len=4) :: alph11 , alph12 , alph21 , alph22 , alph31 , alph32
CHARACTER(len=4) :: blank , hyphen , alphai , alphax

DIMENSION iline(72) , xlable(10)

DATA sbnam1 , sbnam2/'PLOT' , 'T   '/
DATA alph11 , alph12/'FIRS' , 'T   '/
DATA alph21 , alph22/'SECO' , 'ND  '/
DATA alph31 , alph32/'THIR' , 'D   '/
DATA blank , hyphen , alphai , alphax/' ' , '-' , 'I' , 'X'/
!
      cutoff = (10.0_wp**10) - 1000.0_wp
!
!     CHECK THE INPUT ARGUMENTS FOR ERRORS
!
      IF ( N<1 ) THEN
         WRITE (G_IO,99011)
         WRITE (G_IO,99012)
         WRITE (G_IO,99013) alph31 , alph32 , sbnam1 , sbnam2
         WRITE (G_IO,99001) N
         99001    FORMAT (' is non-negative (with value = ',I0,')')
         WRITE (G_IO,99011)
         RETURN
      ELSE
         IF ( N==1 ) THEN
            WRITE (G_IO,99011)
            WRITE (G_IO,99012)
            WRITE (G_IO,99013) alph31 , alph32 , sbnam1 , sbnam2
            WRITE (G_IO,99002) N
            99002       FORMAT (' has the value 1')
            WRITE (G_IO,99011)
            RETURN
         ELSE
!
            hold = Y(1)
            DO i = 2 , N
               IF ( Y(i)/=hold ) GOTO 50
            ENDDO
            WRITE (G_IO,99011)
            WRITE (G_IO,99012)
            WRITE (G_IO,99013) alph11 , alph12 , sbnam1 , sbnam2
            WRITE (G_IO,99014) hold
            WRITE (G_IO,99011)
            RETURN
         ENDIF
 50      continue
         hold = X(1)
         DO i = 2 , N
            IF ( X(i)/=hold ) GOTO 100
         ENDDO
         WRITE (G_IO,99011)
         WRITE (G_IO,99012)
         WRITE (G_IO,99013) alph21 , alph22 , sbnam1 , sbnam2
         WRITE (G_IO,99014) hold
         WRITE (G_IO,99011)
         RETURN
      ENDIF
!
 100  continue
      DO i = 1 , N
         IF ( Y(i)<cutoff ) GOTO 200
      ENDDO
      WRITE (G_IO,99011)
      WRITE (G_IO,99012)
      WRITE (G_IO,99013) alph11 , alph12 , sbnam1 , sbnam2
      WRITE (G_IO,99015)
      WRITE (G_IO,99016) cutoff
      WRITE (G_IO,99011)
      RETURN
 200  continue
      DO i = 1 , N
         IF ( X(i)<cutoff ) GOTO 300
      ENDDO
      WRITE (G_IO,99011)
      WRITE (G_IO,99012)
      WRITE (G_IO,99013) alph21 , alph22 , sbnam1 , sbnam2
      WRITE (G_IO,99015)
      WRITE (G_IO,99016) cutoff
      WRITE (G_IO,99011)
      RETURN
!
 300  continue
      n2 = 0
      DO i = 1 , N
         IF ( Y(i)<cutoff .AND. X(i)<cutoff ) THEN
            n2 = n2 + 1
            IF ( n2>=2 ) GOTO 400
         ENDIF
      ENDDO
      WRITE (G_IO,99011)
      WRITE (G_IO,99012)
      WRITE (G_IO,99003) alph11 , alph12 , alph21 , alph22
      99003 FORMAT (' The ',A4,A4,', and ',A4,A4)
      WRITE (G_IO,99004) sbnam1 , sbnam2
      99004 FORMAT (' input arguments to the ',A4,A4,' subroutine')
      WRITE (G_IO,99005)
      99005 FORMAT (' are such that too many points have been', ' excluded from the plot.')
      WRITE (G_IO,99006) n2
      99006 FORMAT (' only ',I0,' points are left to be plotted.')
      WRITE (G_IO,99011)
      RETURN
!
!-----START POINT-----------------------------------------------------
!
!     DEFINE THE NUMBER OF ROWS AND COLUMNS WITHIN THE PLOT--
!     THIS HAS BEEN SET TO 25 ROWS AND 49 COLUMNS.
!
 400  continue
      numrow = 25
      numcol = 49
      anumr = numrow
      anumrm = numrow - 1
      anumcm = numcol - 1
      numr25 = (numrow/4) + 1
      numr50 = (numrow/2) + 1
      numr75 = 3*(numrow/4) + 1
      ixdel = (numcol-1)/4
      numlab = 5
      anumlm = numlab - 1
!
!     SKIP A LINE, WRITE OUT AN IDENTIFYING LINE FOR THE TYPE OF PLOT,
!     WRITE OUT THE TOP HORIZONTAL AXIS OF THE PLOT, AND SKIP 1 LINE
!     FOR A MARGIN WITHIN THE PLOT.
!
      WRITE (G_IO,99007)
      99007 FORMAT (' ')
      WRITE (G_IO,99008)
!
      99008 FORMAT (' The following is a plot of Y(I) (vertically) versus X(I) (horizontally)')
      DO icol = 1 , numcol
         iline(icol) = hyphen
      ENDDO
      DO icol = 1 , numcol , ixdel
         iline(icol) = alphai
      ENDDO
      WRITE (G_IO,99017) (iline(i),i=1,numcol)
      WRITE (G_IO,99018) blank
!
!     DETERMINE THE MIN AND MAX VALUES OF Y, AND OF X.
!
      DO i = 1 , N
         IF ( Y(i)<cutoff ) THEN
            IF ( X(i)<cutoff ) THEN
               ymin = Y(i)
               ymax = Y(i)
               xmin = X(i)
               xmax = X(i)
               EXIT
            ENDIF
         ENDIF
      ENDDO
      DO i = 1 , N
         IF ( Y(i)<cutoff ) THEN
            IF ( X(i)<cutoff ) THEN
               IF ( Y(i)<ymin ) ymin = Y(i)
               IF ( Y(i)>ymax ) ymax = Y(i)
               IF ( X(i)<xmin ) xmin = X(i)
               IF ( X(i)>xmax ) xmax = X(i)
            ENDIF
         ENDIF
      ENDDO
      dely = ymax - ymin
      delx = xmax - xmin
      ywidth = dely/anumrm
      xwidth = delx/anumcm
!
!     DETERMINE AND WRITE OUT THE PLOT POSITIONS ONE LINE AT A TIME.
!
      DO irow = 1 , numrow
         DO icol = 1 , numcol
            iline(icol) = blank
         ENDDO
         airow = irow
         yupper = ymax + (1.5_wp-airow)*ywidth
         ylable = ymax + (1.0_wp-airow)*ywidth
         ylower = ymax + (0.5_wp-airow)*ywidth
         IF ( irow==numrow ) ylable = ymin
         DO i = 1 , N
            IF ( Y(i)<cutoff ) THEN
               IF ( X(i)<cutoff ) THEN
                  IF ( ylower<=Y(i) .AND. Y(i)<yupper ) THEN
                     icol = ((X(i)-xmin)/xwidth) + 1.5_wp
                     iline(icol) = alphax
                  ENDIF
               ENDIF
            ENDIF
         ENDDO
         icolmx = 1
         DO icol = 1 , numcol
            IF ( iline(icol)==alphax ) icolmx = icol
         ENDDO
         iaxisc = alphai
         IF ( irow==1 .OR. irow==numrow ) iaxisc = hyphen
         IF ( irow==numr25 .OR. irow==numr50 .OR. irow==numr75 ) iaxisc = hyphen
         WRITE (G_IO,99009) ylable , iaxisc , (iline(icol),icol=1,icolmx)
         99009 FORMAT (' ',E14.7,1X,A1,2X,50A1)
      ENDDO
!
!     SKIP 1 LINE FOR A BOTTOM MARGIN WITHIN THE PLOT, WRITE OUT THE
!     BOTTOM HORIZONTAL AXIS, AND WRITE OUT THE X AXIS LABELS.
!
      WRITE (G_IO,99018) blank
      DO icol = 1 , numcol
         iline(icol) = hyphen
      ENDDO
      DO icol = 1 , numcol , ixdel
         iline(icol) = alphai
      ENDDO
      WRITE (G_IO,99017) (iline(icol),icol=1,numcol)
      DO i = 1 , numlab
         aim1 = i - 1
         xlable(i) = xmin + (aim1/anumlm)*delx
      ENDDO
      WRITE (G_IO,99010) (xlable(i),i=1,numlab)
      99010 FORMAT (' ',9X,5E12.4)

99011 FORMAT (' **********************************************************************')
99012 FORMAT ('                    FATAL ERROR                    ')
99013 FORMAT (' The ',A4,A4,' input argument to the ',A4,A4,' subroutine')
99014 FORMAT (' has all elements = ',E15.8)
99015 FORMAT (' has all elements in excess of the cutoff')
99016 FORMAT (' value of ',E15.8)
99017 FORMAT (' ',18X,54A1)
99018 FORMAT (' ',15X,A1)

END SUBROUTINE PLOTT