MODULE GraphingRoutines
!-------------------------------------------------------------------------
! Module that contains the subroutines for producing various kinds
! of graphs:
!    ScatterPlot
!    DensityPlot
!    . . .
!-------------------------------------------------------------------------

CONTAINS

  !-ScatterPlot-----------------------------------------------------------
  ! Subroutine to produce a scatter plot of data points stored in a file,
  ! the first line of which contains values for X_Min, X_Max, Y_Min, and
  ! Y_Max, in this order. Local identifiers used are:
  !   Horiz_Limit,
  !   Vert_Limit     : limits on the size of the graphics window 
  !                    (constants)
  !   Window         : two-dimensional character array -- the graphics
  !                    window
  !   PlotChar       : plotting character -- represents a point on the
  !                    graph
  !   X_Min, X_Max   : minimum and maximum X values
  !   Y_Min, Y_Max   : minimum and maximum Y values
  !   DeltaX, DeltaY : X and Y increments
  !   X, Y           : a point on the graph
  !   X_Loc, Y_Loc   : location of a point in the window
  !   Count          : counts units on Y-axis for labeling purposes
  !   EndOfFile      : end-of-file indicator
  !
  ! Accepts:          FileName
  ! Output (screen):  The graphics window
  !-----------------------------------------------------------------------
  
  SUBROUTINE ScatterPlot(FileName)
    
    IMPLICIT NONE
    CHARACTER(*), INTENT(IN) :: FileName
    REAL :: X_Min, X_Max, Y_Min, Y_Max, DeltaX, DeltaY, X, Y
    INTEGER, PARAMETER :: Horiz_Limit = 70, Vert_Limit = 20
    INTEGER :: X_Loc, Y_Loc, EndOfFile, Count
    CHARACTER(1), DIMENSION(0: Horiz_Limit, 0:Vert_Limit) :: Window
    CHARACTER(1), PARAMETER :: PlotChar = "*"
  
    OPEN (UNIT = 20, FILE = FileName, STATUS = "OLD")
  
    READ (20, *)  X_Min, X_Max, Y_Min, Y_Max
    DeltaX = (X_Max - X_Min) / REAL(Horiz_Limit)
    DeltaY = (Y_Max - Y_Min) / REAL(Vert_Limit)
  
    Window = " "
  
    ! Read data pairs and turn on points in window corresponding to pairs
  
    DO Count = 1, 100
       READ (20, *, IOSTAT = EndOfFile) X, Y
       IF (EndOfFile < 0) EXIT
       ! If end of file, terminate repetition
  
       ! Otherwise plot point
       X_Loc = NINT((X - X_Min)/ DeltaX)
       Y_Loc = NINT((Y - Y_Min)/ DeltaY)
       Window(X_Loc, Y_Loc) = PlotChar
    END DO
 
    ! Draw the window together with labeled Y-axis
  
    Y = Y_Max
    Count = 5 * (Vert_Limit / 5)
    DO Y_Loc = Vert_Limit, 0, -1
       IF (MOD(Count, 5) == 0) THEN
          PRINT '(1X, F8.2, ":", 200A)', &
             Y, (Window(X_Loc,Y_Loc), X_Loc = 0, Horiz_Limit)
       ELSE
          PRINT '(9X, ":", 200A)', &
             (Window(X_Loc,Y_Loc), X_Loc = 0, Horiz_Limit)
       END IF
       Count = Count - 1
       Y = Y - DeltaY
    END DO
  
    ! Draw a labeled X-axis
  
    PRINT '(9X, 200A)', (".", X_Loc = 0, Horiz_Limit)
    PRINT '(3X, 50F10.3)', &
       (X_Min + X_Loc*DeltaX, X_Loc = 0, Horiz_Limit, 10)
  
  END SUBROUTINE ScatterPlot

!     . . .

END MODULE GraphingRoutines
  

PROGRAM Scatter_Plot_of_Data
!-------------------------------------------------------------------------
! Program to produce a scatter plot of a data set stored in a file.
! The name of the file is passed to subroutine ScatterPlot imported 
! from module GraphingRoutines.  Identifiers used are:
!   FileName : name of file containing data set to be plotted
!   Plot     : subroutine called to produce scatter plot
!
! Input:  FileName
! Output: User prompts and the scatter plot
!-------------------------------------------------------------------------

  USE GraphingRoutines, ONLY: ScatterPlot

  IMPLICIT NONE
  CHARACTER(20) :: FileName

  PRINT *, "This program produces a scatter plot of data points"
  PRINT *, "stored in a data file.  The first line of this file"
  PRINT *, "must contain the minimum and maximum x values and"
  PRINT *, "the minimum and maximum y values, in this order."
  WRITE (*, '(/ 1X, A)', ADVANCE = "NO") "Enter the name of the data file: "
  READ *, FileName
  CALL ScatterPlot(FileName)

END PROGRAM Scatter_Plot_of_Data
