The following tutorial leads the user through the creation of disipyl plots using the interactive Python interpreter. I also provide some longer examples in which I show the user how to derive specialized classes and functions to suit particular plotting needs.
You may find it useful to open another browser window with the auto-generated documentation. Doing so will help you gain familiarity with the function and classes which make up disipyl.
The tutorial assumes you've already installed disipyl
(and DISLIN) somewhere where the Python interpretter can find it (see the
section on installation for more details). I also assume the modules
Numeric
and RandomArray
(both part of the NumPy
package) are available
Throughout the tutorial we'll be creating and manipulating
disipyl objects both from the Python interactive
interpretter and in module files. Both interactive sessions and module code
will be setoff with grey boxes in a fixed font (assuming your browser
supports CSS). Interactive sessions will be distinguished from module code by
the presence of the interpretter prompt symbol
(>>>
).
For example, the following indicates an interactive session (the lines without the prompts show what values [if any] the interpetter returns).
>>> print "hello, python world!" hello, python world! >>>
This example shows a hypothetical function and class in a module:
## test.py def helloFunction(name): print "Hello %s, it's nice to meet you!" % name class AClass: def __init__(self): print "AClass created" def __del__(self): print "AClass destroyed"
Fire up the Python interpretter (see the documentation which came with you Python distribution if you don't know how to do that).
We'll check that everything is ready to go by running some demos. Type the following:
>>> from disipyl import demos >>> demos.showdemos()
A series of example plots will begin to appear. After each plot appears the program will wait until you hit the return key or click on the plot window with your right-mouse button before continuing.
To see a similar set of demos using the Tkinter GUI, type the following at the command-line from within the the disipyl directory (this assumes that the python interpretter is in your path):
$ python tkdisipyl.py
A small window with two buttons will appear, offering you a choice between the 2D and 3D demos. You can play around with both sets of demos. The 3D demos are particularly interesting because they provide a set of navigation buttons (e.g., rotate left, zoom in, etc.) so you can interactively explore the 3D plots.
Every valid drawing in disipyl consists of at least one instance of each of the following classes (or their descendants):
Canvas
PlotObject
AxisSystem
All three of these classes are primarily container classes - they maintain
a list of the subobjects which they are responsible for, and call each of
these subojects to draw themselves in turn. For example, a
PlotObject
instance must be assigned a valid
AxisSystem
(in the .axes
attribute). Similarly an
AxisSystem
should have two or more Axis
objects
(.xaxis
, .yaxis
, and sometimes a
.zaxis
).
All disipyl
objects are ultimately derived from the
Object
class, defined in the file pxdislin.py
. All
classes derived from Object
maintain a dictionary of
options
which are used to track and maintain the different types
of options which affect how the object is drawn. This dictionary of options
is accessed in a somewhat roundabout way - options are set using the __call__
method of the class, options are retrieved using the standard __getattr__
function. We can examine all the options of an object by using the __call__
method without any argument. To see how this works in action examine the
following code:
>>> from disipyl import pxdislin >>> message = pxdislin.Text(text='hello, disipyl world!') >>> message() *BEGIN OBJECT: Text TeX = 0 color = fore font = default fonttype = hardware height = 36 justify = left position = (0, 0) rotation = 0 text = 'hello, disipyl world!' ucoords = 1 *END OBJECT: Text >>> message(color = 'red', height = 48) >>> message.color 'red' >>>
After importing the appropriate module, we created a Text
object to which we gave the name message. We then invoked the
__call__
method (message()
) without any arguments,
which returned a printed message showing the various options for this
objects. We invoked the __call__
method a second time with
keyword arguments. These keyword arguments corresponded to the options we
wished to set. Finally, we examined a single option
(message.color
) using the standard attribute calling
mechanism.
Note, that options can only be set using the
__call__
method. Regular attributes can be set using the
standard attribute calling mechanism (.attribute
).
The first plot we will create will be a simple scatter plot. The module,
disipyl.plots
, provides a class, ScatterPlot
, which
provides reasonable default values for scatter plots. Once we've created our
plot, it's easy to refine it to get it just right.
Let's create the scatter plot:
>>> from disipyl import plots >>> s = plots.ScatterPlot(range(10),range(10)) >>> s.draw()
After importing the plots module we created a ScatterPlot object to which we assigned the variable name 's' (when working in the interactive interpretter it's most convenient to use short variable names; when creating module files you should use more descriptive names).
The plot we've just created isn't very exciting. It's a simple scatter plot where the x- and y-values are identical. We're going to spice up the plot, but first let's explore the plot object a little:
>>> s() *BEGIN OBJECT: ScatterPlot TeXmode = 1 defaultcanvastype = disipyl.pxdislin.Canvas symbols = <disipyl.pxdislin.SymbolGroup instance at 014197FC> *END OBJECT: ScatterPlot
Any disipyl object derived from the base class Object
will display it's options when called without any arguments. The
ScatterPlot
has relatively few options of its own. The option
TeXmode
specifies whether TeX style formatting of equations is
available. The option defaultcanvastype
specifies the type of
Canvas object the plot should generate if it needs to draw itself (as opposed
to being draw as a sub-object of a Canvas). When a ScatterPlot
object is created the initial set of data is represented by a
SymbolGroup
object. A SymbolGroup
is simply a
collection of individual Symbol
objects with similar options
(color, shape, etc.)
The reason that the ScatterPlot
object has relatively few
options is that it is primarily a container object, as noted above. When we
call the draw method for the ScatterPlot
object it in turn
invokes the draw methods of each of it's sub-objects. Let's take a look at
the sub-objects:
>>> dir(s) ['axes', 'canvas', 'dataobjects', 'dispostaxis', 'dispreaxis', 'labels', 'options', 'title', 'xlist', 'ylist']
Now we're ready to add some pizzaz to this plot.
>>> s.symbols(color='red', size=35, shape='fill triangle') >>> s.axes.xaxis(name='X-Axis', nameheight=40) >>> s.axes.yaxis(name='Y-Axis', nameheight=40) >>> s.draw()
This code changes the color, size and shape of the symbols used to represent the scatter of the data, and adds some axis labels.
What if we want to then add some more data to the plot? For example, we might want to add some more symbols representing another set of observations. This is relatively easy to do:
>>> group2 = pxdislin.SymbolGroup(range(10),range(9,-1,-1),color='blue', shape='fill circle',size=35) >>> s.add(group2) >>> s.draw()
Finally, we'll center and square-up the graph so that the units are the same length in the x- and y-directions. We'll also add a title:
>>> s.axes(squared=1,centered=1,grids=1,ngridlines=(2,2)) >>> s.title = pxdislin.Title(text="A Simple Graph",offset=-200) >>> s.draw()
We're now going to use disipyl to create a 3-D plot of the function: f(x,y) = Imag(Log(x+iy)). There's two ways to do this - the easy way and the hard way. We'll start with the easy way, to show you just how quickly one can create a plot in disipyl. Then for completeness we'll do it the hard way.
>>> import cmath >>> from disipyl import plots >>> def func(x,y): if x==0 and y==0: return 0 z = cmath.log(complex(x,y)) return z.imag >>> easy = plots.SurfacePlot(func,-2,2,0.5,-2,2,0.5) # set function to plot and axis limits >>> easy.axes(lengths3D=(2,2,1)) >>> easy.surface(topcolor=50,bottomcolor=200) >>> easy.title = pxdislin.Title(text="$f(x,y)=Im(\log(x+iy))$") >>> easy.draw()Most of the above is self-explanatory. The only additional operations performed after creating the plot were to change the relative scaling by which each of the axes is draw (by setting the
lengths3D
option), to set the colors used to draw the top and bottom of the surface
object, and to create a title.
>>> hard = plots.Plot3D() >>> surface = pxdislin3D.FunctionSurface(func, 0.3,0.3,3,3) >>> surface(topcolor=50,bottomcolor=200) >>> hard.add(surface) >>> hard.axes.limits(-2,2,-2,2,-3,3) >>> hard.axes(lengths3D=(2,2,1)) >>> hard.title = pxdislin.Title(text="$f(x,y)=Im(\log(x+iy))$") >>> hard.draw()
As you can see, the "hard way" isn't all that hard. The only real
difference is that we had to create our own FunctionSurface
object (in the easy example the SurfacePlot
object created it
for you), and we had to set our own axis limits..
If you are using the IDLE development environment you can use the
Diddle
classes in tkdisipyl.py
to interactively
explore your plot.
>>> from disipyl import tkdisipyl >>> d = tkdisipyl.Diddle(hard)
When you create a Diddle
object a Tk window should pop up
containing the plot and a number of navigation buttons. Try rotating,
tilting and zooming in on the plot.
The dispyl
package comes with a fairly good variety of
"pre-canned" plot types. However, sooner or later you'll want to make a
specialized plot for which none of the supplied classes is appropriate. In
such cases it's desirable to derive your own specialized plot class.
Most specialized plots can be derived from either the Plot2D
or Plot3D
classes. If you have very specialized needs you may
need to derive your class from the PlotObject
. The files
plots.py
and miscplots.py
are filled with examples
of specialized plot classes.
If you want to learn more about how to create disipyl plots, check out the
demo plots in demos.py
. I'll also try and add more examples to
this tutorial as development continues, so please check the disipyl website
for updates.