PGPLOT

PGPLOT is a multi-platform plotting library mainly written in FORTRAN 77, with interfaces available for several other languages (such as C, C++, Perl, or Tcl/Tk). The development started in 1983, by T. J. Pearson at California Institute of Technology. The last version was released in February 2001 (v. 5.2.2). PGPLOT is not free software, but can be used in non-commercial projects without charge.

PGPLOT example
Fig. 1: Example output of PGPLOT (pgdemo1.f)

Installation

PGPLOT is available as a package on most Unix-like operating system. On FreeBSD, just install graphics/pgplot:

# pkg install graphics/pgplot

Any Fortran application just has to be linked against -lX11, and either -lpgplot (shared library) or libpgplot.a (static library) to access the PGPLOT procedures.

If a package is not provided, we can build the PGPLOT library from source. The source code archive is hosted on the Caltech FTP. First, download and unpack the archive:

$ fetch ftp://ftp.astro.caltech.edu/pub/pgplot/pgplot5.2.tar.gz
# tar xfvz pgplot5.2.tar.gz
# cd pgplot/

Select the desired output device drivers in file drivers.list, and then create a Makefile with makemake. In this case, the output directory is set to ./, and the targeted platform to FreeBSD:

$ ./makemake ./ freebsd

List the available platforms with:

$ ./makemake ./ operating_system
The second argument must be one of the following operating systems:
  aix alliant arc bsd convex cray cygwin dos epix2 freebsd fujitsu gnuwin32 hp
  irix linux mac msdos next openstep osf1 salford sol2 solx86 sun4 ultrix vms win

Finally, run the Makefile to build the library:

$ make FCOMPL=gfortran10 CFLAGC=-I/usr/local/include/ LIBS="-L/usr/local/lib/ -lX11 -lm" 

Instead of passing the build options as arguments, simply alter the Makefile according to your set-up. The predefined paths most likely do not match the actual paths on modern Linux and Unix systems. Afterwards, the static libary libpgplot.a is written to the given output directory ./.

PGPLOT includes 17 example programs to demonstrate its capabilities (fig. 1). To compile them individually, run, for instance:

$ cd examples/
$ gfortran10 -o pgdemo1 pgdemo1.f -lpgplot -lX11
$ ./pgdemo1
Plot of Laplace’s equation
Fig. 2: PGPLOT output of Laplace’s equation solver

Example

The following example program solves Laplace’s equation

Laplace’s equation

numerically for a two-dimensional function f. After 8000 iterations, the result is plotted as a heatmap to an X window by PGPLOT (fig. 2). Set the output device to /GIF to write the plot to file pgplot.gif, or to ? to select the device at run-time.

! laplace.f90
program main
    implicit none (type, external)
    external :: pgclos, pgimag ! PGPLOT imports (FORTRAN 77).

    integer, parameter :: N     = 200   ! Number of columns, rows.
    integer, parameter :: NITER = 8000  ! Number of interations.

    real    :: f(N, N)
    real    :: vm(6)
    real    :: fmax, fmin
    integer :: rc

    ! Initialise PGPLOT.
    call pgplot_init('/XWINDOW', N, N, vm, rc)
    if (rc < 0) stop 'Error: Failed to open output device'

    ! Set initial values.
    f( 1, :) = 1.0
    f(2:, :) = 0.0

    ! Solve Laplace's equation.
    call laplace(f, NITER, 0.1**2, 0.1**2)

    ! Get minimum and maximum value.
    fmin = minval(f)
    fmax = maxval(f)

    ! Plot the heatmap.
    call pgimag(f, N, N, 1, N, 1, N, fmin, fmax, vm)

    ! Close the graphics device.
    call pgclos()
contains
    subroutine laplace(a, niter, dx2, dy2)
        real,    intent(inout) :: a(:, :)
        integer, intent(in)    :: niter
        real,    intent(in)    :: dx2
        real,    intent(in)    :: dy2
        integer                :: i, m, n

        n = size(a, 1)
        m = size(a, 2)

        do i = 1, niter
            a(2:n - 1, 2:m - 1) = ((a(3:, 2:m - 1) + a(:m - 2, 2:m - 1)) * dy2 + &
                                   (a(2:n - 1, 3:) + a(2:n - 1, :m - 2)) * dx2) / &
                                  (2 * (dx2 + dy2))
        end do
    end subroutine laplace

    subroutine pgplot_init(gd, n, m, vm, stat)
        !! Opens the given graphics device, sets the transformation matrix,
        !! initialises PGPLOT, and sets the colour palette.
        integer  :: pgopen
        external :: pgbox, pgctab, pgenv, pgmtxt, pgwnad

        character(len=*), intent(in)            :: gd
        real,             intent(out)           :: vm(6)
        integer,          intent(in)            :: n
        integer,          intent(in)            :: m
        integer,          intent(out), optional :: stat

        integer :: rc
        real    :: bright, contra

        if (present(stat)) stat = -1

        ! Open the given graphics device.
        rc = pgopen(gd)
        if (rc < 0) return

        ! Set the coordinate transformation matrix. In this case, world coordinate
        ! equals pixel number.
        vm = [ 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ]

        ! Set up window and viewport.
        call pgwnad(0.0, 1.0 + n, 0.0, 1.0 + m)

        ! Add border and output text.
        call pgbox('bcts', 0.0, 0, 'bcts', 0.0, 0)
        call pgmtxt('t', 1.0, 0.0, 0.0, "Laplace's equation using PGPLOT")

        ! Set up the rainbow colour palette.
        bright = 0.5; contra = 1.0
        call pgctab([ -0.5, 0.0, 0.17, 0.33, 0.50, 0.67, 0.83, 1.0, 1.7 ], &
                    [  0.0, 0.0,  0.0,  0.0,  0.6,  1.0,  1.0, 1.0, 1.0 ], &
                    [  0.0, 0.0,  0.0,  1.0,  1.0,  1.0,  0.6, 0.0, 1.0 ], &
                    [  0.0, 0.3,  0.8,  1.0,  0.3,  0.0,  0.0, 0.0, 1.0 ], &
                    9, contra, bright)

        if (present(stat)) stat = 0
    end subroutine pgplot_init
end program main

The implicit none (type, external) statement is a Fortran 2018 feature and may not be supported on older compilers. Build the example with:

$ gfortran10 -o laplace laplace.f90 -lpgplot -lX11
$ ./laplace

To link against the PGPLOT static library, run instead:

$ gfortran10 -o laplace laplace.f90 /usr/local/lib/libpgplot.a -lX11

Depending on the array size and the number of iterations, the solving may take several seconds.

Some aspects of PGPLOT can be configured through environment variables, such as font, foreground and background colour, or default output device, for example:

$ export PGPLOT_FOREGROUND=black
$ export PGPLOT_BACKGROUND=white
$ ./laplace

You may have to specify the path to file rgb.txt in environment variable PGPLOT_RGB.

Output Devices

PGPLOT supports a broad range of output devices, which depend on the used platform and the selected build options. Only the /NULL device is always available. The PGPLOT manual includes a complete list of interactive and non-interactive graphics devices. The parameter ? will let PGPLOT ask the user to select from a list of supported devices (tab. 1 and 2).

ParameterDescription
/GTERMColor gterm terminal emulator
/XTERMXTerm Tek terminal emulator
/TK4100Tektronix 4100 terminals
/XDISPpgdisp or figdisp server
/XWINDOWX11 window
/XSERVEA /XWINDOW window that persists for re-use
Tab. 1: Interactive devices in PGPLOT
ParameterDescription
/GIFGraphics Interchange Format file, landscape orientation
/VGIFGraphics Interchange Format file, portrait orientation
/HPGLHewlett Packard HPGL plotter, landscape orientation
/VHPGLHewlett Packard HPGL plotter, portrait orientation
/HPGL2Hewlett-Packard graphics
/LATEXLaTeX picture environment
/NULLNull device, no output
/PPMPortable Pixel Map file, landscape orientation
/VPPMPortable Pixel Map file, portrait orientation
/PSPostScript file, landscape orientation
/VPSPostScript file, portrait orientation
/CPSColour PostScript file, landscape orientation
/VCPSColour PostScript file, portrait orientation
/WDX window dump file, landscape orientation
/VWDX window dump file, portrait orientation
Tab. 2: Non-interactive devices in PGPLOT

References