IaGraph
ManualThis is a package of interactive graphing tools, built upon the Climate Data Analysis Tools (CDAT) suite produced by the Program for Climate Model Diagnosis and Intercomparison (PCMDI) at Lawrence Livermore National Laboratory (LLNL). The package will create line plots, scatter plots, and contour plots with a single line of Python code.
Sometimes the plot generated will also be suitable for publications, and procedures in this package will allow you to write those plots to a Postscript or GIF file, but usually you will want a more complex plot for publications, which this package cannot make. If you want a graphing package for Python that has more features, here are some you might want to look at: CDAT, ChartDirector, DISLIN, gmt, GracePlot, Matplotlib, and SciPy.
What distinguishes this package from other plotting packages for Python is the emphasis on graphing using a single line of Python code. Other packages do not require much more code (maybe 3-5 more lines), and in fact this package uses those other graphing packages to make its graphs. But for the purposes of interactive plotting, 3 lines is 2 lines too many. I try to emulate IDL (Interactive Data Language) syntax (though not IDL array indexing, since Python and IDL index their arrays completely differently).
The home page for the package contains the package license, installation and downloading instructions, a complete listing of package contents, help for the modules, and probably all the description and examples most users need to use the package. Most users can ignore this manual you're currently reading.
That being said, this manual describes the programming logic behind the package and also contains a more detailed description of the capabilities of this package.
The manual is subdivided into these categories:
Because the package is designed to be used for interactive plotting,
I use a procedural logic instead of object-oriented or functional.
Thus, all key commands are called as procedures instead of functions
or methods.
I also try to emulate the IDL direct graphics structure.
IaGraph
is built upon CDAT's Visualization Control System (VCS).
VCS works by decomposing the elements of a graph into objects
and placing those objects onto a VCS canvas. Up to 8 VCS canvases
can be defined at one time in a Python session. In IaGraph
,
each time a graph is created
(e.g. with a plot
or
contour
command), a new VCS canvas is created
onto which the plot is placed. This new canvas is then set
as the "active canvas" stored in the IaGraph
"system variables" class (Sysvar
),
to enable us to manipulate the plot even after rendering.
Any previous active canvas stored in the system variables class
is cleared then overwritten when a new plot is created.
Note that since when a new plot is created the existing active
canvas is used, the new plot does not contribute to the 8 VCS canvas
limit. Only when a new window is opened
(using the window
command) and a plot made
in this new window is another VCS canvas initialized.
Besides storing the active canvas,
global control over many plot settings is accomplished through
Sysvar
(which is defined in __init__.py).
The system variables are all class attributes of
Sysvar
; Sysvar
has no
instance variables (although class attributes are changed
via a class instance). Thus, all system variables are available
once IaGraph
is imported, are available to all instances of
the class, and will persist as long as the Python session is open.
Admittedly, this is not very pretty and smacks of a Fortran
common block. It was, however, the only way I could think of
of allowing some level of global control over IaGraph
plots.
The syntax of the Sysvar
class is similar
to IDL syntax. For instance, the main plotting system variables
in IDL (!P variables) are prefixed by p_
in
Sysvar
. Likewise, axes system variables (!X and !Y in IDL)
are prefixed by x_
and y_
in
Sysvar
. Because Sysvar
attributes
are all class attributes it's best to refer to an attribute
with the __class__
tag. Thus, if
sysvar
(= IaGraph.Sysvar()
) is a
realization of Sysvar
, the x-axis VCS font
code is sysvar.__class__.x_font
.
The default values for a number of the parameters in the
plotting commands are all set as an attribute of Sysvar
.
Through system variables you can also control some aspects of
a plot that are not controllable via a procedure keyword, or to
directly supercede the internal defaults of a procedure.
Procedures generally use the following logic in deciding which
value to use for a parameter, if there is more than one choice:
None
.
None
, the value of
the corresponding system variable is used.
None
, the procedure assigns a local default
setting for that parameter.
Note that p_
, x_
, and y_
system variables are never (at least I think are never) changed by
an IaGraph
procedure.
The only system variables that are changed by
IaGraph
procedure(s) are the
active_canvas,
active_canvas_base_gm,
active_canvas_base_tpl,
inactive_canvases,
inactive_canvases_base_gm,
and
inactive_canvases_base_tpl
attributes.
A number of plot attributes can be controlled via
system variables, including: font and font height of
overall title, axes titles, and axes tick labels.
Sysvar
also allows you to directly control which
ticks are labeled: set [xy]_tickvalues
. This
is particularly useful if you want to have non-numeric labels,
such as latitude/longitude values. For more information on
changing graphics properties via system variables see
here.
Remember, once you change the setting of a system variable,
that setting is retained for the rest of the Python session,
until it is changed again!
A full list of all Sysvar
attributes (and their
default values) is found here.
The precise rules of how a procedure chooses its parameter settings
can be viewed via the help
command for the procedure.
Plots are created and manipulated via procedures and either
create or operate on the active canvas, as stored in the
active_canvas
attribute in the Sysvar
class.
There are 2 exceptions: the loadct
procedure and
helper functions.
The procedures that create an active canvas (and overwrite any
previously existing active canvas) are:
contour
,
plot
, and
plotct
.
The procedures that operate on an active canvas (and do not change
anything in the active canvas) are:
active2gif
and
active2ps
.
The loadct
takes a VCS canvas and specified
color map index (passed in as the two positional arguments)
and sets the active color map for that canvas to the specified map.
For consistency with the rest of the package,
loadct
should have operated on the
active canvas, but for some reason Python won't let me.
This workaround worked, so for this one key procedure I had
the canvas passed in as an argument.
Helper functions can be procedural or functional. Usually they
do tasks that are non-central to the package and thus are not
available with a from IaGraph import *
command.
One example of this is wavelen2rgb
which returns
an RGB triple given a wavelength of visible light. To use helper
functions, you'll have to import them via their full package/module
pathname. Thus, for wavelen2rgb
import it via:
import IaGraph.wavelen2rgb.wavelen2rgb as wavelen2rgb
.
[Back up top to the Introduction.]
The plot
command creates both line and scatter plots,
since scatter plots are just line plots without the lines.
The default of plot
is to make a line plot with
solid connecting lines and a square as the plot symbol.
You can change the line type through the linestyle
keyword and plot symbol through the psym
keyword.
To remove connecting lines, set psym
to a value greater
than zero. Negative psym
plots connecting lines and a
psym
of 0 gives a line plot without any plot symbols.
Here are lists of the available plot symbols and line styles:
Note that for the "dash" linestyle, the VCS routine I use to dump plots to Postscript and GIF does not seem to reproduce the dash spacings as they appear on screen; the dashes are much closer together in the Postscript and GIF versions. Thus, I'd recommend you use "long-dash" if you want a readable dash.
Plot symbol size is controlled by the symht
keyword.
The default value of 7 gives squares that have an approximate
on-screen size of 2 mm.
Keywords shared in common between plot
and other
plotting procedures (e.g. contour
) are described
here.
The plot
procedure is
somewhat special in that while CDAT is the dependency you
wish to have in order to get full performance from the
routine, plot
will still provide some
functionality if you only have
Grace
and
gracePlot
installed, or even if you only have
the Tk widgets in the
ScientificPython package installed.
See the help for plot
for details.
[Back up top to the Introduction.]
The contour
command can produce three types of
contour plots: plots with contour lines only, plots with
smooth, filled contours, and plots with both filled contours
and lines overlain.
When contour lines are plotted, negative contours are long-dashed and
positive contours are solid.
Contour
defaults to plotting both filled contours
with lines overlain, along with a color bar key below the plot.
Obviously if only contour lines are plotted, there's no color bar
key plotted. If you are doing filled contours and wish to suppress
the color bar, set keyword colorbar
to 0.
The procedure defaults to automatically calculate contours for you.
The system variable p_maxnlev
sets
the maximum number of level intervals that will be allowed
in this automatically calculation.
If you want specific keywords, specify them
through the c_levels
keyword.
You can choose which color table to use in the filled contours
via the ctindex
keyword. The command
loadct()
will list all available values.
The default is 13 (rainbow, violet to red, 390-680 nm).
Continents are turned off by default. To plot outlines of modern
continents, set the continents
keyword to a non-zero
value.
[Back up top to the Introduction.]
The procedure loadct
will set a color map for the
VCS canvas that is passed into loadct
. All plotting
procedures that use a color map (e.g. contour
) set
the active color map using loadct
; the color map
is specified to the plotting routine
via the ctindex
keyword.
A list of the color maps defined in loadct
is found
here.
If you wish to add your own color map,
I'd suggest you just hack the code for loadct
.
Just add an additional elif
statement after the
elif
block that selects the default color map
(i.e. after the "elif cmap_index == 99:
" statement).
In your new elif
block, assign a color map index to
be the loadct
reference to your color map, and set all
values of loadct_cmap.index[i]
to RGB triples, for
indices i
from 16 to 239, inclusive.
[Back up top to the Introduction.]
The active canvas (stored in system variable active_canvas
)
can be written to a
Postscript file using active2ps
and a
GIF file using active2gif
.
The active2ps
routine writes the plot to landscape.
The active2gif
routine also writes to landscape.
However, the GIF file is not rotated 90 degrees like the Postscript
file is, so you can view the file without having to rotate the image.
Both routines will replace any prexisting graphics file of
the same name.
[Back up top to the Introduction.]
plotct
:
Produces a plot of a loadct
color table, with values
of color indices shown. You can use this to visualize what the
color map you're using will look like. This procedure creates a
new plot and overwrites and existing active canvas.
[Back up top to the Introduction.]
The plot
and contour
procedures
share some keywords. Here we describe how to use those keywords:
annot
:
The placement of axes titles and the overall title is pretty
standard, and so I won't discuss them. However, I've added an
additional annotation feature to the plot generation
routines (e.g. plot
, contour
) that
I think I should probably explain a little. Often I like to add
additional information about what a plot contains, how it was made,
etc.; this information
I plot out at the top of the page in small type. The annot
keyword enables you to include such text.
If the keyword is defined, the default values of
position
adjust to give you more space
at the top of the page to add the annotation. The
size of the plot isn't changed, but the location on the
page is.
position
:
The position of the plot on the page can be moved by the
position
keyword or its system variable
equivalent. This keyword is a
4-element list [bbllx, bblly, bburx, bbury] of
the bounding box (x,y) coordinates in normalized values. The
data origin is the lower-left corner, and the upper-right corner
of the data box is the upper-right corner of position.
[xy]range
:
The xrange
and yrange
keywords allow
you to control what part of the x- and y-axes are plotted.
Each keyword accepts a 2-element list of minimum and maximum
values specifying the interval.
Note that these keywords set the range of the
[xy]-axis used to calculate "neat" tickmarks,
from which the actual axis range is set;
depending on what the [xy]range
values
are, the actual plot range may look different.
If you want the range to be precisely certain values,
set them through the [xy]_tickvalues
system variable.
The [xy]_range
system variables do the same thing as the
[xy]range
keywords.
If you wish to directly control axis tick labels, set the
[xy]_tickvalues
system variable.
title
:
String scalar specifying the overall title.
[xy]title
:
String scalar specifying the [xy]-axis title.
A number of graphics attributes, besides those with an equivalent
graphics keyword (noted above), can be controlled via system variables.
The programming logic of systems variables is described
here.
The Sysvar
class
docstring documentation
provides enough details (along with a list of the default values)
for most of the variables.
Here we describe how to change graphics settings for system variables
that could use some more description.
In all the examples given, we assume that:
sysvar = IaGraph.Sysvar()
is an instance of the Sysvar
class.
Remember, since all system variables are Sysvar
class attributes it is good practice to refer to those attributes
with the __class__
attribute, e.g.
sysvar.__class__.p_font
.
Font Type and Height:
p_font
changes the font of the overall title, while
[xy]_font
sets the font of the axes text. The font
code is an integer that follows the VCS code for font.
The height is set for overall graphics and the axes text
through the p_fontht
and [xy]_fontht
system variables, respectively. This is an integer and is in
arbitrary units. You can approximately convert these values to
normalized units by multiplying by p_fontht2norm
.
A setting of 40 font height units gives capital letters that
are approximately 1/4 inch on screen (assuming landscape orientation
output).
Ticks:
The p_ticklen
variables gives general tick lengths,
in normalized units. Axes tick lengths are specified by
[xy]_ticklen
.
The plotting routines, by default, calculate the number of tick
marks based upon a "nice" division of the axes ranges. The
maximum number of ticks that will be allowed in this default
calculation is controlled by [xy]_tickmaxnum
.
You can also directly set the x- and y-axis tick labels
through [xy]_tickvalues
. This system variable
is a dictionary where the dictionary key is the tick marks'
numerical value and the dictionary value is a string labeling
each tick mark.
Remember, once you change the setting of a system variable,
that setting is retained for the rest of the Python session,
until it is changed again!
Thus, if you change the font height system variable, all
subsequent IaGraph
plots made during that Python session
will use that height.
[Back up top to the Introduction.]
The code is pretty well-commented, so you should be able to read it to figure out what it does. However, there are a few design decisions I made that I thought I should point out.
The first one I wanted to point out because it could result in you running out of memory if you make a zillion plots. Because every time you make a plot you need to create a whole bunch of VCS objects, the question comes what you should name these objects. A static name isn't any good, because if you have a multiplicity of plots, there's no guarantee that each plot's object of the same name will be identical (in fact, the reverse is usually true). And since I wanted the capability of being able to go back to any plot in memory at will and revising it (which requires all component objects to remain defined for the duration of the plot's life), I needed to create a naming system that gave every VCS object a unique name. (Additionally, I couldn't figure out a way to remove a name from the VCS object list, if the object itself isn't defined, so even if I saved the names of all VCS objects I wanted removed, I couldn't remove them because the local objects that instantiated the list entry are undefined after the procedure exits.)
Thus, the VCS objects created by
IaGraph
all have a suffix based
upon the system time, in fraction of
a second. The suffix is long enough to guarantee no reuse of names
for at least 100 days; as long as the Python session is closed before
then, every name will be guaranteed to be unique.
Unfortunately, as long as you don't close your Python session, all VCS objects created during that session will remain defined. If you make many plots, this could result in many VCS objects being created, which may result in you running out of memory. I don't know when this limit is reached; no problems resulted when I made 100 consecutive simple x-y plots in one window during one session on my modest Linux box (which has 255 Mb memory and 498 Mb swap).
The second design decision regards the names of the graphics
method and template objects (again here I mean the name that shows
up in a show
method, not the name of an object instance).
In the all the routines of the package, I assume the following is true:
plot
and oplot
are xvsy graphics methods and have names beginning with the
string 'xygm'. The exception is when oplot
is
called for no connecting lines, in which case the graphics
method created is the scatter method. However, the name still
begins 'xygm'.
plot
and oplot
have names beginning with the string 'mytpl'.
contour
and ocontour
for isofill plots
have names beginning with the string 'fillgm'.
contour
and ocontour
for isofill plots
have names beginning with the string 'filltp'.
contour
and ocontour
for isoline plots
have names beginning with the string 'linegm'.
contour
and ocontour
for isoline plots
have names beginning with the string 'linetp'.
The third decision was to store the names
of the base graphics method and template used on a canvas as
a system variable.
By "base" I mean the graphics method and template used when
the plot was first created (e.g. by a plot
or
contour
command). I stored these values as
system variables in order to retrieve the
definitions of plot range, and other settings, for overplots.
Finally, the plot
command uses the xvsy graphics
method for both the cases when you have connecting lines and
when you do not. I do this by assuming the background color is
white and setting the line color to white when you have the case
of no connecting lines. However, since oplot
might
be plotting over a filled contour plot, in oplot
I do not assume that the background color is white
and go through the extra work of
using the scatter graphics method
to take care of the case when there are no connecting lines.
[Back up top to the Introduction.]
Here's a list of some glitches that periodically arise. I list these separately from my bugs list since they're not worth fixing and reasonably easy to work-around.
Date Problem Fix 16 Jun 2004 There is a substantial difference in rendering time if you close a window manually and then plot another plot vs. keeping that window open and plotting another plot into that existing window. I don't know why this happens. For now I'd manually close the window if you want it to be faster. 09 Jan 2004 When I make a zillion plots, I run out of memory. Close the Python session and restart. See the coding tricks discussion above. 22 Dec 2003 Sometimes, the plot doesn't render exactly like you expect. For instance, a filled contour plot with contour lines will only print contour lines. This seems to be an inconsistent problem and I don't know why it happens. The fix: quit out of that Python session and re-run the script. Doing that once or twice has always fixed the problem for me.
[Back up top to the Introduction.]
Here's a partial list of improvements that need to be made in this package:
[xy]style
keywords.
plot
and contour
to read in
axes from just an MV data object. For plot
generate an x-axis if only a single vector is passed in.
[Back up top to the Introduction.]
Copyright © 2003-2004 Johnny Lin. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found here.
The Transparent copy of this document is located at http://www.johnny-lin.com/py_pkgs/IaGraph/Doc/manual.html.
[Back up top to the Introduction.]
Return to IaGraph Home Page.
Return to Johnny Lin's Python
Library.
Updated: June 16, 2004 by Johnny Lin <email address>.