Gnuplot is a free plotting tool that can be run from the command-line or invoked by third-party applications. Despite its name, the program is not related to the GNU project. The plotting commands and the input data are read from files or stdin. Plots can either be displayed inside a window (fig. 1) or exported in various image formats. The development of Gnuplot started already in 1986.

Fig. 1: Gnuplot called from Fortran

Command-Line Execution

The Fortran example below writes the processed data to a text file data.txt and then uses the intrinsic Fortran 2008 routine execute_command_line() to call Gnuplot. Additional Fortran modules are not required.

! example.f90
program main
    implicit none
    character(len=*), parameter :: FILE_NAME = 'data.txt'   ! File name.
    integer,          parameter :: N         = 10           ! Number of values.

    real, dimension(N) :: x, y
    integer            :: i, fu

    x(1) = 0.0
    y(1) = 0.0

    do i = 2, N
        x(i) = 0.1 * i
        y(i) = x(i)**2
    end do

    open (action='write', file=FILE_NAME, newunit=fu, status='replace')

    do i = 1, N
        write (fu, *) x(i), y(i)
    end do

    close (fu)

    call execute_command_line('gnuplot -p plot.plt')
end program main

The Gnuplot commands to display the plot are stored in file plot.plt:

# plot.plt
set term x11 font "-*-helvetica-medium-r-*-*-14-*-*-*-*-*-*-*"
set title "Fortran Example"
set nokey
set grid
set xlabel "x"
set ylabel "y"
plot m using 1:2 with linespoints

The file will then be read by Gnuplot to perform the actual plotting:

$ gfortran10 -o example example.f90
$ ./example

Unix Pipes

Instead of transfering the output data to Gnuplot by file, we can feed plotting options and data values directly by connecting both applications with Unix pipes. The output of the Fortran program will become the input of Gnuplot.

The following example shows how to plot a shaded height map based on Perlin noise with Gnuplot (fig. 2). The Fortran program will simply print the height map to stdout. If we set the dgrid3d option followed by the correct dimensions of the matrix, Gnuplot will map a non-grid input to the internal grid format automatically. We could then output single coordinates (x, y, z) line by line instead of the matrix as a whole. Obviously, this is a lot slower.

Gnuplot Perlin noise
Fig. 2: Perlin noise generated in Fortran and visualised by Gnuplot

The Fortran module perlin.f90 provides the basic Perlin noise implementation that is called by the example. Gnuplot will additionally interpolate the surface.

! example.f90
program main
    use :: perlin
    implicit none
    integer, parameter :: WIDTH  = 128
    integer, parameter :: HEIGHT = 64
    integer            :: x, y
    real               :: r
    real               :: matrix(WIDTH, HEIGHT)

    ! Set Perlin noise seed.
    call random_seed()
    call random_number(r)
    call perlin_noise_seed(int(r * 10**6))

    ! Set Gnuplot options.
    print '(a)', 'unset key'                           ! Disable legend.
    print '(a)', 'set cbtics scale 0'                  ! Disable colourbar tics.
    print '(a)', 'set title "Perlin Noise in Fortran"' ! Set title.
    print '(a)', 'set pm3d interpolate 2, 2'           ! Draw 3d data as colour map.
    print '(a)', 'splot "-" matrix with pm3d'          ! Plot matrix data in 3d.

    ! Calculate matrix values and print them to stdout.
    do y = 1, HEIGHT
        do x = 1, WIDTH
            matrix(x, y) = perlin_noise(real(x * .1), real(y * .1), 0.4, 8) * 100
            write (*, '(f8.5, " ")', advance='no') matrix(x, y)
        end do
        write (*, *)
    end do
end program main

The example can be compiled and executed with:

$ gfortran10 -c perlin.f90
$ gfortran10 -o example example.f90 perlin.o
$ ./example | gnuplot -p

We do not need to run the example each time to display the plot. Instead, redirect the output to a file first, then pipe the file contents to Gnuplot:

$ ./example > data.txt
$ cat data.txt | gnuplot -p

Fortran Libraries

A selection of Gnuplot libraries is available for Fortran: