ptclTk/Tcl and PGPLOT
The PGPLOT library is
C high-level callable graphics library. It has become the de-facto
standard for display of astronomical data. Along with the standard primitives to draw lines, write text
and annotate plots, there are also high level routines which use these primitives to build up
more complicated graphs such as histograms and contour maps. PGPLOT also has the
capability for interactive graphics where the user can interact with the plots using the
While it would be quite possible for me to fill the entire cookbook with PGPLOT information an excellent tutorial style manual already exists for the library written by Tim Pearson of CalTech the package’s author. If you work at a Starlink node this manual should be available to you, if not it’s available on the web at http://astro.caltech.edu/~tjp/pgplot/contents.html.
A simple example program is shown below, taken from Chapter 2 of the PGPLOT manual. It shows how a simple plot can be generated in just a few lines of code, the output from the program is shown in Figure 1.
A commonly asked question is how to get PGPLOT to produce valid encapsulated postscript (EPSF)
files. Most PGPLOT postscript files are valid EPSF files, except for multi-page plots. Some problems
do exists however, valid EPSF files should have a
%%BoundingBox comment line in the header of the
file, PGPLOT places this line in the trailer of the file where some programs will fail to find it. This
comment can be moved into the file header using any text editor. If you do not wish to do this you can
also modify the way PGPLOT deals with bounding boxes using the
Additionally PGPLOT Postscript files do not contain a screen preview section. A device-independent
screen preview can be added to PGPLOT files with the program
ps2epsi by George Cameron,
available with the GhostScript PostScript interpreter.
Some of the more useful environment variables which control the behaviour of PGPLOT are listed below, the list is not exhaustive, for a full list you should see the relevant sections of the PGPLOT manual.
PGPLOT_DIRDirectory name. Unless told otherwise by environment variables
PGPLOT_RGB, PGPLOT looks for the files it needs at run-time in this directory. The binary font file is
grfont.datand the color-name database is
rgb.txt. If this variable is undefined, or if the specified file does not exist in this directory, PGPLOT looks in the current default directory, e.g.
setenv PGPLOT_DIR /usr/local/lib/pgplot/. For Starlink users this environment variable will be set at login when you source the Starlink
loginfile, or by typing the
starlinkcommand at the UNIX prompt.
PGPLOT_DEVDevice specification. If this variable is defined, it is used as the default device specification: if the device specification given to
PGBEG(or supplied by the user in response to the PGPLOT prompt) is a blank string, this device specification is used, e.g.
setenv PGPLOT_DEV /xwin. The Starlink distributed version of Native PGPLOT has an additional device,
/gwm, that allows plotting in GWM Windows.
PGPLOT_TYPEDevice type. If this variable is defined, it is used as the default device type: if the device specification supplied to PGBEG consists of a file name without a trailing slash (/) and device type, this device type is assumed, e.g.
setenv PGPLOT_TYPE ps
PGPLOT_BUFFERIf this variable is defined, with any non-null value, PGPLOT buffers output. The effect is the same as if
PGBBUFis called immediately after opening the graphics device, and PGEBUF immediately before closing it. It will have no effect on programs that already include these calls. On some devices, buffering output can lead to large improvements in speed, but enabling buffering may upset synchronization between graphical output and other program activity, e.g.
setenv PGPLOT_BUFFER yes
Problems dealing with PGPLOT’s Postscript output are amongst the most common complaints about the package. PGPLOT has several environment variables which control the output from its Postscript device driver
PGPLOT_PS_WIDTH (default 7800)
PGPLOT_PS_HEIGHT (default 10500)
PGPLOT_PS_HOFFSET (default 350)
PGPLOT_PS_VOFFSET (default 250)These variables tell PGPLOT how big an image to produce. The driver uses resolution elements of 0.001 inches, (i.e. milli-inches)giving an “apparent” resolution of 1000 pixels per inch. The true resolution is device-dependent. The image dimensions are therefore 7.8 inches horizontally by 10.5 inches vertically (portrait mode) by default. These defaults while defined with American 8.5 x 11-inch paper in mind, rather than the European A4 size sheets, are appropriate in most circumstances. The maximum dimensions of a PGPLOT image are
HEIGHT, with the lower left corner offset by
VOFFSETvertically from the lower left corner of the paper. The “top” of the paper is the edge that comes out of the printer first.
PGPLOT_IDENTIf this variable is defined (with any value), the user name, date and time are written in the bottom right corner of each page.
PGPLOT_PS_BBOXNormally, PGPLOT computes the bounding box for the entire plot (the smallest rectangle that includes all the graphics) as it creates the PostScript file, and writes this information in a %%BoundingBox comment in the file trailer. Some programs that read encapsulated PostScript files expect to find the %%BoundingBox comment in the file header, not the trailer, and may not display the plot correctly. To fix this problem, you may need to move the comment from the trailer to the header with a text editor or special program. Alternatively, you can define
PGPLOT_PS_BBOX = MAX. This tells PGPLOT to put a %%BoundingBox comment in the header of the PostScript file; the bounding box is one which encompasses the whole plotable area, not a minimal one, because PGPLOT does not know the correct bounding box until it has finished writing the file.
PGPLOT_PS_DRAW_BBOXIf this variable is set, the bounding box (the smallest rectangle that includes all the graphics) is drawn on each page.
PGPLOT_PS_VERBOSE_TEXTIf this variable is set, the text of each plotted character string is included in the PostScript file as a comment before the sequence of vectors that represents the string. This makes the file slightly larger, but it can be useful if you want to hand edit the PostScript file.
PGPLOT_PS_EOFNormally the output file does not contain special end-of-file characters. But if environment variable
PGPLOT_PS_EOFis defined (with any value) PGPLOT writes a Control-D job-separator character at the beginning and at the end of the file. This is appropriate for Apple LaserWriters using the serial interface, but it may not be appropriate for other PostScript devices.
NOto suppress use of a PostScript font for the graph markers; markers are then emulated by line-drawing. If this option is not requested, PGPLOT graph markers are scaled geometrically with the character-height attribute and the line-width attribute is ignored. This is different from most of the other drivers, where the line-width used for markers is set by the line-width attribute rather than the character-height attribute. Requesting this option makes the PostScript driver behave like the other drivers, but it also makes the PostScript files larger.
Another group of commonly asked questions about PGPLOT concern how to put Greek
characters, or super- and sub-scripts into text strings (such as axis annotations) in PGPLOT. The
PGPTXT subroutine, along with all the routines that call it such as the higher level
PGLAB) uses escape sequences embedded in the text string to print these characters.
Escape sequences are characters which are not plotted, but instead instruct the program to
change font, draw superscripts, subscripts or non-ASCII characters (e.g. Greek letters). All
escape sequences start with a backslash character “\”. The following escape sequences are
While plots can be made interactive using standard PGPLOT functions, e.g.
PGCURS, the BUTTON
library extends this functionality to allow you to easily create interactive FORTRAN applications
using graphic buttons, see Figure 2.
The program which produced the plot shown in Figure 2 is shown below, and is compiled using the
f77 -o sample sample.f libbutton.a -lpgplot -lX11 (assuming that
shared library has been built and is in the current directory).
The BUTTON library is available from http://www.ucm.es/info/Astrof/button/button.html along with installation instructions and a description of the library functions.
pgperl package is a dynamically loadable Perl module which interfaces to
library. Perl provides a superset of the features of the useful UNIX utilities
sed and is the
“Swiss-Army Chainsaw” of UNIX programming. Users of PONGO and SM packages will be familiar
with this style of programming.
The simple example shown below, taken from the
pgperl distribution, shows how the
routines are interfaced into a simple Perl script, the output from this script is shown in
For every PGPLOT
Fortran function the
pgperl module provides an equivalent Perl function with the
same arguments. Thus the user of the module should refer to the PGPLOT manual to learn all about
how to use
pgperl and for the complete list of available functions. More information on
pgperl can be
found at http://www.aao.gov.au/local/www/kgb/pgperl/.
Passing simple numbers and arrays to the PGPLOT subroutines via the
pgperl module any
CHARACTER scalar variable maps to a Perl scalar, since Perl doesn’t care
about the differences between strings, integers or reals. Therefore to draw a line to point
To plot ten points of data held in in Perl arrays
@y with plot symbol 17 the Perl arrays are
passed (by reference) to the PGPLOT module as follows:
Label the axes:
Draw a single point, note that when ,
pgpoint() can take a scalar argument rather than an array:
Many of the PGPLOT calls (e.g.
pggray) take 2D arrays as arguments. Several methods to access these
subroutines are provided by
@x is a 1D array of 1D arrays. Alternatively
@x could be a flat 1D array with 128x128
elements, 2D routines such as
pggray() are programmed to do the right thing as long as the
number of elements match.
read() function reads the binary data from a file and the
pggray() function displays it
as a grey-scale image. This saves unpacking the image data in to a potentially very large 2D perl
array. However the types must match. The string must be packed as a “
f*” for example to use
pggray. This is intended as a short-cut for sophisticated users. Even more sophisticated users
will want to download the PDL module which provides a wealth of functions for manipulating
Some PGPLOT functions (e.g.
pgfunx) take functions as callback arguments. In Perl simply pass a
subroutine reference or a name, for example:
In addition to the implicit rules mentioned above PGPLOT now provides a scheme for explictly handling binary data in all routines.
If your scalar variable (e.g. \$x) holds binary data (i.e. ’packed’) then simply pass PGPLOT a reference to it (e.g. \$x). Thus one can say:
This is very efficient as we can be sure the data never gets copied and will always be interpreted as binary.
Python is one of the new breed of object-oriented programming languages. It is commonly used both for scripting and as a stand alone rapid development language. One of the properties of the language is that it provides facilities for the easy integration of external services. It should therefore come as no surprise that there are currently several different Python interfaces to the PGPLOT subroutine libraries. Due to the nature of the language, being a rapid development tool, it should also come as no surprise that the documentation is a bit on the patchy side.
The most well documented seems to be an interface to PLplot. While based on PGPLOT, and having a similar API, PLplot is not derived from the PGPLOT source and care must be taken when using it if you are used to PGPLOT. More information on PLplot can be found in Section 3.10.
Both of the other interfaces require the installation of the NumPy libraries. NumPy is a collection of C extension modules to the Python programming language which add multi-dimensional array objects. These new objects give Python the number crunching power of numeric languages like Matlab and IDL while maintaining all of the advantages of the general-purpose programming language Python. If you are running Linux it is possible that NumPy may already be installed, else or otherwise, it can be found at http://andrich.net/python/.
One interface also requires you to install SWIG. The Simplified Wrapper and Interface Generator (SWIG) is is a software development tool that connects programs written in C, C++, and Objective-C with a variety of high-level programming languages. SWIG is primarily used with common scripting languages such as Perl, Python, and Tcl/Tk but has been extended to include languages such as Java.
More details of the interfaces available, including some basic usage and installation instructions, can be found on the UBC Python Page at http://www.geog.ubc.ca/~phil/ubc_python.html.
For users of aips++ a PGPLOT binding for GLISH has been developed. While the PGPLOT library itself has a large number of device drivers, only the Tk and PostScript drivers are available from GLISH. More information on the PGPLOT bindings in GLISH can be found at http://aips2.nrao.edu/released/docs/reference/Glish/node97.html.
ptclTk/Tcl and PGPLOT
ptcl registers PGPLOT functions as
tcl commands. It allows you to create plots from the command
line or from scripts. If the
tk extensions are installed it is simple to create graphical user interfaces
(GUIs) allowing you to directly interact with the plots. More information on
ptcl can be found at
Unbeknown to some, PGPLOT commonly comes in two flavours on Starlink supported machines. The original or “Native” version which uses the low level graphics package GRPCKG, which was also written at Caltech, and a version developed by Starlink, in collaboration with Dr Pearson, which uses RAL GKS. The two versions have identical subroutine interfaces and in most cases, applications can be moved from one version to the other simply by re-linking.
Starlink currently supports both the native version and the Starlink versions. Most packages available
in the Starlink Software Collection (USSC) currently are linked against the Starlink version. Work is
ongoing to port these applications to the Native version. More information can be found in SUN/15
which describes the use of PGPLOT on Starlink systems. Use of the Starlink/GKS version is
deprecated. The Starlink distributed version of Native PGPLOT has an additional device,
allows plotting in GWM Windows.
To compile a program and link it to the native version of PGPLOT you should use the following command line:
While to use the Starlink version you should use:
Or to link the code in an ADAM application:
More detailed discussion of the differences between the two versions can be found in SUN/15.
The Graphical Kernel System (GKS) is a device independent low level graphics system designed to be the kernel of a wide variety of higher-level graphics systems. It is very comprehensive but does not itself set out to provide the most convenient or user-friendly interface for all applications. For high level graphics you are recommended to use the PGPLOT library, while for low-level graphics you may prefer to use SGS rather than play with GKS directly.
More information on the GKS system can be found in the Starlink GKS document SUN/83. While detailed API information can be found in the RAL GKS User Guide and the RAL GKS Reference Manual (obtainable from your Starlink site manager or Starlink user support at RAL).
With the current movement away from pseudo- to true-colour XWindow displays, a common problem when writing software is trying to find what sort of X display the person running your package has available. A good indicator as to the type of X display available is whether the colour table is writable. If it is, then your user is probably sitting in front of a pseudo-colour display. If it’s not, then it is more likely that the display is True Colour (see Section 11).
GKS provides a function to enquire whether the colour table (amongst other attributes) is writable, formally called “Inquire Dynamic Modification of Workstation Attributes”, i.e.
Where the variables are defined as:
WTYPE = _INTEGER(Read)
IERR = _INTEGER(Returned)
PLBUN = _INTEGER(Returned)
PMBUN = _INTEGER(Returned)
TXBUN = _INTEGER(Returned)
FABUN = _INTEGER(Returned)
PAREP = _INTEGER(Returned)
COLREP = _INTEGER(Returned)
WKTR = _INTEGER(Returned)
If the colour table is writable,
COLREP will be returned as 1. More information on other useful GKS
functions can be found in the RAL GKS Reference Manual, which can be found online at
Before compiling a program that uses the GKS include file
GKS_PAR you must first execute the
Programs are linked with GKS by:
The Simple Graphics System (SGS) is a low-level graphics subroutine library sitting above the GKS package allowing easier access to GKS features. Full details of the SGS library package can be found in SUN85.
PLplot is a library of C functions that are useful for making scientific plots from a program written in C, C++, or Fortran. The PLplot library can be used to create standard x-y plots, semilog plots, log-log plots, contour plots, 3D plots, mesh plots, bar charts and pie charts. Multiple graphs (of the same or different sizes) may be placed on a single page with multiple lines in each graph. Different line styles, widths and colors are supported. A virtually infinite number of distinct area fill patterns may be used. There are almost 1000 characters in the extended character set. This includes four different fonts, the Greek alphabet and a host of mathematical, musical, and other symbols. The fonts can be scaled to any desired size. A variety of output devices are supported. More information on PLplot can be found at http://emma.la.asu.edu/plplot/.
One important feature available in PLplot, which is not (trivially) available in PGPLOT is the ability to represent a single-valued function of two variables as a surface.
As usual, we would like to refer to a three dimensional point in terms of some meaningful user-specified coordinate system. These are called three-dimensional world coordinates. We need to specify the ranges of these coordinates, so that the entire surface is contained within the cuboid defined by , and . Typically, we shall want to view the surface from a variety of angles, and to facilitate this, a two-stage mapping of the enclosing cuboid is performed. Firstly, it is mapped into another cuboid called the normalized box whose size must also be specified by the user, and secondly this normalized box is viewed from a particular azimuth and elevation so that it can be projected onto the two-dimensional window.
This two-stage transformation process allows considerable flexibility in specifying how the surface is depicted. The lengths of the sides of the normalized box are independent of the world coordinate ranges of each of the variables, making it possible to use “reasonable” viewing angles even if the ranges of the world coordinates on the axes are very different. The size of the normalized box is determined essentially by the size of the two-dimensional window into which it is to be mapped. The normalized box is centered about the origin in the and directions, but rests on the plane . It is viewed by an observer located at altitude, , and azimuth, , where both angles are measured in degrees. The altitude should be restricted to the range zero to ninety degrees for proper operation, and represents the viewing angle above the plane. The azimuth is defined so that when , the observer sees the plane face on, and as the angle is increased, the observer moves clockwise around the box as viewed from above the plane. The azimuth can take on any value.
PLENV (equivalent to the PGPLOT
PGENV routine) is used in the usual way to
establish the size of the two-dimensional window.
PLW3D must then be called to establish the range of the three dimensional world
coordinates, the size of the normalized box and the viewing angles. After calling
PLW3D, the actual
surface is drawn by a call to
The values of the function are stored in a two-dimensional array where the array element contains the value of the function at the point , . (The two-dimensional array is a vectored array instead of a fixed size array. points to an array of pointers which each point to a row of the matrix.) Note that the values of the independent variables and do not need to be equally spaced, but they must lie on a rectangular grid. Thus two further arrays and are required as arguments to plot3d to specify the values of the independent variables. The values in the arrays and must be strictly increasing with the index. The argument opt specifies how the surface is outlined. If , a line is drawn representing as a function of for each value of , if , a line is drawn representing z as a function of for each value of , and if , a net of lines is drawn. The first two options may be preferable if one of the independent variables is to be regarded as a parameter, whilst the third is better for getting an overall picture of the surface. If side is equal to one then sides are drawn on the figure so that the graph doesn’t appear to float.
PLMESH is similar to
PLOT3D, except that it is used for drawing mesh plots. Mesh plots
allow you to see both the top and bottom sides of a surface mesh, while 3D plots allow you to
see the top side only (like looking at a solid object). The side option is not available with
Labelling a three-dimensional or mesh plot is somewhat more complicated than a two dimensional
plot due to the need for skewing the characters in the label so that they are parallel to
the coordinate axes. The routine
PLBOX3 thus combines the functions of box drawing and
Let us get it clear right from the start, JPEG is not an image format, instead the ANSI JPEG
specification lays down a definition for a family of compression algorithms. In fact the JPEG
specification is commonly used in two file formats JFIF and TIFF. The JFIF format is a simple format
used for applications that just need to store image data, this is the format that is commonly referred to
as being “JPEG” and files in this format usually have
.jpeg endings. The second, more
complex, TIFF file format is used by applications that need to store extra data about images
(e.g. colour correction curves). However TIFF, while more flexible, are far less portable than JFIF since
different applications implement different subsets of TIFF specification. It should be noted that the
official standard for JPEG image compression is not available on-line, you have to order a paper copy
from ANSI (or ISO).
The forthcoming JPEG Part 3 standard defines a file format called SPIFF. This format should be backwards compatible with the JFIF image standard, although it has some technical advantages. However its major advantage is that it is an official ANSI standard, where JFIF and TIFF are not. At this time it is unclear as to whether SPIFF will replace JFIF, or whether JFIF will continue to be widely used with the new SPIFF standard being ignored by the rest of the world.
The JPEG standard is optimised for “real-world” images, cartoons and other non-realistic images are not handled well, since JPEG is a lossy algorithm. This means that the output image is not identical to the image, you trade off output image quality against a smaller file size, by adjusting a compression parameter (how lossy the image will be) on image generation.
The Independent JPEG Group (IJG) has a freely redistributable implementation of the JPEG (JFIF)
image compression/decompression algorithms. The distributed programs provide conversion
between JPEG format and image files formats such as PPM/PGM, GIF, BMP, and Targa. The
core programs used to do this is
cjpeg to compress an image file into JPEG format and
djpeg to decompress a JPEG file back into a conventional format. The core compression and
libjpeg.so, which is written in C can easily be reused in your own programs
The code is available for both commercial and non-commercial use, and the latest version of the code
can be obtained via anonymous FTP from ftp://ftp.uu.net/graphics/jpeg/. Detailed
documentation on how to code using the library API is provided along with the distribution (see the
If you are using a Linux system it is likely that the library, and associated applications, are already
installed. RedHat 6.0 ships with
libjpeg.so shared object library as part of the standard
libjpeg library is also distributed as part of the Starlink Base Set, if you are
using a Starlink supported machine you can link your program to the Starlink distributed
GIF files use Lempel-Ziv-Welsh (LZW) compression algorithm to encode the image data to save space, however there is a great deal of controversy over the GIF legal position (see Section 15) due to the Unisys patent issue.
Eric S. Raymond, the maintainer of
giflib has this to say about Unisys’s licensing: “Due to Unisys’s
increasingly aggressive interpretation of its patent claims on the LZW compression format, I can no
longer recommend the use of the
giflib library or utilities.
giflib may be withdrawn in the near
If you need to deal with GIF images it is recommended that you use the the
The way round the entire legal mess surrounding the GIF image standard is simply not to use the
LZW compression algorithm. The
libungif library follows this approach and is designed to handle
uncompressed GIFs. These are image files that, while not using LZW compression, are still
recognizable as GIF files by decoders which expect normal (compressed) GIFs. The obvious problem is
that the uncompressed GIF images will be larger than those encoded using the LZW algorithm. This
library speaks both GIF87a and GIF89.
The latest version of the
libungif library can be obtained from the anonymous FTP archive at
ftp://prtr-13.ucsc.edu/pub/libungif/. Extensive documentation on how to code using the library
API is included with the distribution. However if you are using a Linux system it is likely
that the library, and associated applications, are already installed. RedHat 6.0 for instance
ships with both
libungif.so shared object libraries as part of the standard
ANGIF is a C library to generate GIF format output. It can generate animated or, a bit of a standard breaker here, true colour (24bpp) GIFs. Due to the legal problems surrounding the format ANGIF is LZW free. Command line test programs are included with the distribution.
It should be noted that ANGIF is in pre-beta release, the only documentation available is the source code comments. Although there doesn’t appear to be a home page for the library yet, it can be downloaded via HTTP from http://phil.ipal.org/freeware/angif/.
The Portable Network Graphics (PNG) format was designed to replace the older and simpler GIF format and, to some extent, the much more complex TIFF format.
PNG format several major advantages over GIF. Firstly it uses alpha channels, allowing you to have variable transparency images. Unlike GIF, which implements a simple binary transparency (either a pixel is transparent or opaque) PNG specifies 254 levels of partial transparency. Instead of storing three bytes for each pixel for red, green and blue (RGB), four are now stored, these being red, green, blue and alpha (RGBA). PNG supports both true colour, greyscale and palette-based (pseudo) colour images, unlike GIF which supports only pseudo colour images. All three types of PNG image support alpha channels, although the size of true colour PNG images effectively rules them out for use on the web. Additionally, the format makes use of gamma correction, allowing cross-platform control of image brightness. Finally, the PNG format specifies two-dimensional interlacing (progressive display) rather than the one-dimensional scheme used by GIF images.
PNG also compresses better than GIF in almost every case, but the difference is generally only around 5 to 25 per cent. Additionally, and quite importantly, PNG is free of any legal entanglement.
For those of you wanting to implement programs to handle PNG images, the official PNG library
libpng is available via anonymous FTP from ftp://swrinde.nde.swri.edu/pub/png/src/. This
zlib, a general purpose lossless compression library. A copy of the library can be
found at the same FTP site, but the latest version and more information about the library can be found
More information on the PNG format, programming resources and supporting applications can be found online at http://www.libpng.org/pub/png/.
The Multiple-image Network Graphics (MNG) format has been implemented by the same people that brought you PNG, and it therefore shares the same modular philosophy. The idea behind the format is to provide a home for all of the multi-image capabilities that have no place in PNG. While it has fairly extensive animation and image-manipulation capabilities, there is no serious expectation that it will ever integrate audio or video. In other words this format it intended to replace multi-image GIF animations.
Though the MNG specification itself has not yet been promoted to release status, as of 11
May 1999 it was officially frozen by a vote of the MNG developers. Although relatively
mature, MNG is still a draft proposal. There is therefore no general use MNG reference
library (along the same lines as
libjpeg for example). However, there are already several
applications with partial MNG support, the main UNIX application being ImageMagick (see
The Python Imaging Library (PIL) adds an image object to your Python interpreter. You can load image objects from a variety of file formats, including BMP, EPS, GIF, JPEG, PNG, PPM, TIFF and XBM, and apply a rich set of image operations to them. See the feature sheet at http://www.python.org/sigs/image-sig/Imaging.html for more details.
gd is a C graphics library that allows you to quickly draw images with lines, arcs, text, multiple colors,
cut and paste from other images, and flood fills, and write out the result as a PNG file. More
information can be found at http://www.boutell.com/gd/gd.html.
A simple example of the
gd library in use, taken from the documentation, is shown below:
When run, this program creates an image, allocates two colours (the first colour allocated becomes the background colour) and draws a diagonal line (note that 0, 0 is the upper left corner) before writing the image to a PNG file.
gdfrom other languages
gd library can also be accessed from languages other than C. There is an API for both the Perl,
see http://stein.cshl.org/WWW/software/GD/GD.html, and Tcl scripting languages, see