===== Plotting a Single Curve =====


Let us plot the curve $y = t^2\exp(-t^2)$|$y = t**2*exp(-t**2)$ for
$t$ values between 0 and 3.  First we generate equally spaced
coordinates for $t$, say 51 values (50 intervals). Then we compute the
corresponding $y$ values at these points, before we call the
`plot(t,y)` command to make the curve plot.  Here is the complete
program:

!bc pro
from scitools.std import *

def f(t):
    return t**2*exp(-t**2)

t = linspace(0, 3, 51)    # 51 points between 0 and 3
y = zeros(len(t))         # allocate y with float elements
for i in xrange(len(t)):
    y[i] = f(t[i])

plot(t, y)
show()  # optional
!ec
If you have problems running this file, make sure you have installed
SciTools and one or more plotting programs, see Chapter ref{ev:tut:install}.

The first line imports all of SciTools and Easyviz that can be handy
to have when doing scientific computations. This includes everything
from `numpy` (from `numpy import *`),
all Easyviz plotting commands, some modules (`sys`, `math`), and
all of SciPy (`from scipy import *`) if SciPy is installed.
In the program above, we first
pre-allocate the `y` array and fill it with values, element by
element, in a Python loop. Alternatively, we may operate
on the whole `t` array at once, which yields faster and shorter code:

!bc pro
from scitools.std import *

def f(t):
    return t**2*exp(-t**2)

t = linspace(0, 3, 51)    # 51 points between 0 and 3
y = f(t)                  # compute all f values at once
plot(t, y)
show()                    # optional
!ec
The `f` function can also be skipped, if desired, so that we can write
directly
!bc cod
y = t**2*exp(-t**2)
!ec

To include the plot in electronic documents, we need a hardcopy of the
figure in PostScript, PNG, or another image format.  The `hardcopy`
command produces files with images in various formats:
!bc cod
hardcopy('tmp1.eps') # produce PostScript
hardcopy('tmp1.png') # produce PNG
!ec
An alternative name for `hardcopy` is `savefig`:
!bc cod
savefig('tmp1.eps') # produce PostScript
savefig('tmp1.png') # produce PNG
!ec
The filename extension determines the format: `.ps` or
`.eps` for PostScript, and `.png` for PNG.
Figure ref{fig:plot1a} displays the resulting plot. With `show(False)`
we can suppress the plot from being shown at the screen, which is
useful when create a large number of figure files in programs.

FIGURE:[figs/plot1a.eps] A simple plot in PostScript format. label{fig:plot1a}

On some platforms, some backends may result in a plot that is shown in
just a fraction of a second on the screen before the plot window disappears
(using the Gnuplot backend on Windows machines or using the Matplotlib
backend constitute two examples). To make the window stay on the screen,
add
!bc cod
raw_input('Press the Return key to quit: ')
!ec
at the end of the program. The plot window is killed when the program
terminates, and this satement postpones the termination until the user
hits the Return key.


===== Decorating the Plot =====

The $x$ and $y$ axes in curve plots should have labels, here $t$ and
$y$, respectively. Also, the curve should be identified with a label,
or legend as it is often called.  A title above the plot is also
common.  In addition, we may want to control the extent of the axes (although
most plotting programs will automatically adjust the axes to the range of the
data).
All such things are easily added after the `plot` command:

!bc cod
xlabel('t')
ylabel('y')
legend('t^2*exp(-t^2)')
axis([0, 3, -0.05, 0.6])   # [tmin, tmax, ymin, ymax]
title('My First Easyviz Demo')
!ec
This syntax is inspired by Matlab to make the switch between
Easyviz and Matlab almost trivial.
Easyviz has also introduced a more "Pythonic" `plot` command where
all the plot properties can be set at once:

!bc cod
plot(t, y,
     xlabel='t',
     ylabel='y',
     legend='t^2*exp(-t^2)',
     axis=[0, 3, -0.05, 0.6],
     title='My First Easyviz Demo',
     savefig='tmp1.eps',  # or hardcopy='tmp1.eps'
     show=True)
!ec

With `show=False` one can avoid the plot window on the screen and
just make the hardcopy. This feature is particularly useful if
one generates a large number of separate figures in the program.
The keyword `savefig` can be replaced by `hardcopy` if desired.

Note that we in the curve legend write `t` square as `t^2` (LaTeX style)
rather than `t**2` (program style). Whichever form you choose is up to
you, but the LaTeX form sometimes looks better in some plotting
programs (Matplotlib and Gnuplot are two examples).
See Figure ref{fig:plot1c} for what the modified
plot looks like and how `t^2` is typeset in Gnuplot.


FIGURE:[figs/plot1c.eps] A single curve with label, title, and axes adjusted. label{fig:plot1c}


===== Plotting Multiple Curves =====

A common plotting task is to compare two or more curves, which
requires multiple curves to be drawn in the same plot.
Suppose we want to plot the two functions $f_1(t)=t^2\exp(-t^2)$
and $f_2(t)=t^4\exp(-t^2)$. If we write two `plot` commands after
each other, two separate plots will be made. To make the second
`plot` command draw the curve in the first plot, we need to
issue a `hold('on')` command. Alternatively, we can provide all
data in a single `plot` command. A complete program illustrates the
different approaches:

!bc pro
from scitools.std import *   # for curve plotting

def f1(t):
    return t**2*exp(-t**2)

def f2(t):
    return t**2*f1(t)

t = linspace(0, 3, 51)
y1 = f1(t)
y2 = f2(t)

# Matlab-style syntax
plot(t, y1)
hold('on')
plot(t, y2)

xlabel('t')
ylabel('y')
legend('t^2*exp(-t^2)', 't^4*exp(-t^2)')
title('Plotting two curves in the same plot')
savefig('tmp2.eps')  # or hardcopy('tmp2.eps')

# Alternative "Pythonic" style
plot(t, y1, t, y2, xlabel='t', ylabel='y',
     legend=('t^2*exp(-t^2)', 't^4*exp(-t^2)'),
     title='Plotting two curves in the same plot',
     savefig='tmp2.eps')
!ec
The sequence of the multiple legends is such that the first legend
corresponds to the first curve, the second legend to the second curve,
and so on. The visual result appears in Figure ref{fig:plot2a}.

Doing a `hold('off')` makes the next `plot` command create a new
plot in the same window. This new plot just erases the previous curves.

FIGURE:[figs/plot2a.eps] Two curves in the same plot. label{fig:plot2a}

With the keyword argrument `grid=True` to `plot` we can add a
grid, which is frequently used when plotting curves (see
Figure ref{fig:plot2f}).

FIGURE:[figs/plot2f.eps] Curves with a grid. label{fig:plot2f}

The default location of the legends is dependent on the backend
(some have a fixed location, like Gnuplot, and some try to find
the most optimal location, like Matplotlib). One can control
the location by the `loc` keyword to the `legend` function, e.g.,
!bc
legend('t^2*exp(-t^2)', 't^4*exp(-t^2)', loc='upper left')
!ec
The most popular values are upper right, upper left, lower left,
and lower right, depending on the shape of the curves and extend
of the axes. The keyword argument `fancybox` draws a box around
the legends if `True`, otherwise no box is drawn. The corresponding
keywords for the `plot` function are `legend_loc` and `legend_fancybox`:
!bc
plot(t, y1, t, y2, xlabel='t', ylabel='y',
     legend=('t^2*exp(-t^2)', 't^4*exp(-t^2)'),
     legend_loc=`upper left`, legend_fancybox=True,
     axis=[0, 4, -0.1, 0.8],
     title='Plotting two curves in the same plot',
     savefig='tmp2.eps')
!ec
The `loc` and `fancybox` specifications work (at present)
with Gnuplot and Matplotlib only.


FIGURE: [figs/plot2l.eps, width=400] A figure with legends placed to the upper left with a box frame.

The `legend` function also accepts a list of legends instead of
the legends as separate positional arguments. This allows an overlapping
syntax between Matplotlib and Easyviz so that the same code can apply
either of the packages (however, Matplotlib's keywords to
`plot`, like `label` and `linewidth`, are not recognized so not all
syntax is interchangable).


===== Making Multiple Figures =====

The `hold` command either adds a new curve or replaces old curve(s) by
new ones. Often one wants to make multiple figures in a program,
realized as multiple windows on the screen. The `figure()` command
creates a new figure:
!bc cod
x = linspace(-2, 2, 81)
y1 = sin(pi*x)*exp(-0.5*x**2)
plot(x, y1)

figure()  # separate plot window
y2 = sin(pi*x/2)*exp(-0.5*x**2)
plot(x, y2)

figure()  # yet another plot window
y3 = sin(pi*x/4)*exp(-0.5*x**2)
plot(x, y3)
!ec
More information in the `figure` command is found later on under the
heading *Working with Axis and Figure Objects*.


===== Controlling Line Styles =====

When plotting multiple curves in the same plot, the individual curves
get distinct default line styles, depending on the program that is
used to produce the curve (and the settings for this program). It
might well happen that you get a green and a red curve (which is bad
for a significant portion of the male population).  Therefore,
we often want to control the line style in detail. Say we want the first
curve (`t` and `y1`) to be drawn as a red solid line and the second
curve (`t` and `y2`) as blue circles at the discrete data points.  The
Matlab-inspired syntax for specifying line types applies a letter for
the color and a symbol from the keyboard for the line type. For
example, `r-` represents a red (`r`) line (`-`), while `bo` means blue
(`b`) circles (`o`). The line style specification is added as an
argument after the $x$ and $y$ coordinate arrays of the curve:

!bc cod
plot(t, y1, 'r-')
hold('on')
plot(t, y2, 'bo')

# or
plot(t, y1, 'r-', t, y2, 'bo')
!ec
The effect of controlling the line styles can be seen in
Figure ref{fig:plot2c}.

FIGURE:[figs/plot2c.eps] Two curves in the same plot, with controlled line styles. label{fig:plot2c}

Assume now that we want to plot the blue circles at every 4 points only.
We can grab every 4 points out of the `t` array by using an appropriate
slice: `t2 = t[::4]`. Note that the first colon means the range from the
first to the last data point, while the second colon separates this
range from the stride, i.e., how many points we should "jump over"
when we pick out a set of values of the array.

!bc pro
from scitools.std import *

def f1(t):
    return t**2*exp(-t**2)

def f2(t):
    return t**2*f1(t)

t = linspace(0, 3, 51)
y1 = f1(t)
t2 = t[::4]
y2 = f2(t2)

plot(t, y1, 'r-6', t2, y2, 'bo3',
     xlabel='t', ylabel='y',
     axis=[0, 4, -0.1, 0.6],
     legend=('t^2*exp(-t^2)', 't^4*exp(-t^2)'),
     title='Plotting two curves in the same plot',
     hardcopy='tmp2.eps')
!ec

In this plot we also adjust the size of the line and the circles by
adding an integer: `r-6` means a red line with thickness 6 and `bo5`
means red circles with size 5. The effect of the given line thickness
and symbol size depends on the underlying plotting program. For
the Gnuplot program one can view the effect in Figure ref{fig:plot2g}.

FIGURE:[figs/plot2g.eps] Circles at every 4 points and extended line thickness (6) and circle size (3). label{fig:plot2g}


The different available line colors include
  * yellow:   `'y'`
  * magenta:  `'m'`
  * cyan:     `'c'`
  * red:      `'r'`
  * green:    `'g'`
  * blue:     `'b'`
  * white:    `'w'`
  * black:    `'k'`

The different available line types are
  * solid line:      `'-'`
  * dashed line:     `'--'`
  * dotted line:     `':'`
  * dash-dot line:   `'-.'`

During programming, you can find all these details in the
documentation of the `plot` function. Just type `help(plot)`
in an interactive Python shell or invoke `pydoc` with
`scitools.easyviz.plot`. This tutorial is available
through `pydoc scitools.easyviz`.

We remark that in the Gnuplot program all the different line types are
drawn as solid lines on the screen. The hardcopy chooses automatically
different line types (solid, dashed, etc.) and not in accordance with
the line type specification.

Lots of markers at data points are available:
  * plus sign:                     `'+'`
  * circle:                        `'o'`
  * asterisk:                      `'*'`
  * point:                         `'.'`
  * cross:                         `'x'`
  * square:                        `'s'`
  * diamond:                       `'d'`
  * upward-pointing triangle:      `'^'`
  * downward-pointing triangle:    `'v'`
  * right-pointing triangle:       `'>'`
  * left-pointing triangle:        `'<'`
  * five-point star (pentagram):   `'p'`
  * six-point star (hexagram):     `'h'`
  * no marker (default): `None`

Symbols and line styles may be combined, for instance as in `'kx-'`,
which means a black solid line with black crosses at the data points.


__Another Example.__ Let us extend the previous example with a third
curve where the data points are slightly randomly distributed around
the $f_2(t)$ curve:

!bc pro
from scitools.std import *

def f1(t):
    return t**2*exp(-t**2)

def f2(t):
    return t**2*f1(t)

t = linspace(0, 3, 51)
y1 = f1(t)
y2 = f2(t)

# Pick out each 4 points and add random noise
t3 = t[::4]      # slice, stride 4
random.seed(11)  # fix random sequence
noise = random.normal(loc=0, scale=0.02, size=len(t3))
y3 = y2[::4] + noise

plot(t, y1, 'r-')
hold('on')
plot(t, y2, 'ks-')   # black solid line with squares at data points
plot(t3, y3, 'bo')

legend('t^2*exp(-t^2)', 't^4*exp(-t^2)', 'data')
title('Simple Plot Demo')
axis([0, 3, -0.05, 0.6])
xlabel('t')
ylabel('y')
show()
savefig('tmp3.eps')   # or hardcopy
savefig('tmp3.png')   # or hardcopy
!ec
The plot is shown in Figure ref{fig:plot3}.

FIGURE:[figs/plot3.eps] A plot with three curves.  label{fig:plot3}

__Minimalistic Typing.__
When exploring mathematics in the interactive Python shell, most of us
are interested in the quickest possible commands.
Here is an example of minimalistic syntax for
comparing the two sample functions we have used in the previous examples:

!bc cod
t = linspace(0, 3, 51)
plot(t, t**2*exp(-t**2), t, t**4*exp(-t**2))
!ec

__Text.__ A text can be placed at a point $(x,y)$ using the call
!bc
text(x, y, 'Some text')
!ec

__More Examples.__ The examples in this tutorial, as well as
additional examples, can be found in the `examples` directory in the
root directory of the SciTools source code tree.

===== Math Syntax in Legends and Titles =====

Some backends understand some mathematical syntax. Easyviz accepts
LaTeX-style syntax and translates it to something appropriate for the
background in question. As a rule of thumb, write plain LaTeX syntax
if you need mathematical symbols and expressions in legends and
titles. Matplotlib will show the result in an excellent way, Gnuplot
PostScript output will handle super- and subscripts as well as greek
letters. All other backends will strip off backslashes, dollar signs,
curly braces, qand other annoying LaTeX syntax. Normally, power
expressions with double multiplication symbols are replaced by a hat.

===== Interactive Plotting Sessions =====

All the Easyviz commands can of course be issued in an interactive
Python session. The only thing to comment is that the `plot` command
returns a result:
!bc py
>>> t = linspace(0, 3, 51)
>>> plot(t, t**2*exp(-t**2))
[<scitools.easyviz.common.Line object at 0xb5727f6c>]
!ec
Most users will just ignore this output line.

All Easyviz commands that produce a plot return an object reflecting the
particular type of plot. The `plot` command returns a list of
`Line` objects, one for each curve in the plot. These `Line`
objects can be invoked to see, for instance, the value of different
parameters in the plot:
!bc py
>>> line, = plot(x, y, 'b')
>>> getp(line)
{'description': '',
 'dims': (4, 1, 1),
 'legend': '',
 'linecolor': 'b',
 'pointsize': 1.0,
 ...
!ec
Such output is mostly of interest to advanced users.


===== Making Animations =====
label{easyviz:movie}

A sequence of plots can be combined into an animation and stored in a
movie file. First we need to generate a series of hardcopies, i.e.,
plots stored in files.  Thereafter we must use a tool to combine the
individual plot files into a movie file.

__Example.__ The function
$f(x; m, s) = (2\pi)^{-1/2}s^{-1}\exp{\left[-{1\over2}\left({x-m\over s}\right)^2\right]}$|$f(x; m,s) = 1/(sqrt(2*pi)*s)*exp(-0.5*((x-m)/s)**2)$
is known as the Gaussian function or the probability density function
of the normal (or Gaussian) distribution.  This bell-shaped function is
"wide" for large $s$ and "peak-formed" for small $s$, see Figure
ref{fig:plot4}. The function is symmetric around $x=m$ ($m=0$ in the
figure).  Our goal is to make an animation where we see how this
function evolves as $s$ is decreased. In Python we implement the
formula above as a function `f(x, m, s)`.

FIGURE:[figs/plot4.eps] Different shapes of a Gaussian function. label{fig:plot4}

The animation is created by varying $s$ in a loop and for each $s$
issue a `plot` command. A moving curve is then visible on the screen.
One can also make a movie file that can be played as any other
computer movie using a standard movie player. To this end, each plot
is saved to a file, and all the files are combined together using some
suitable tool, which is reached through the `movie` function in
Easyviz. All necessary steps will be apparent in the complete program
below, but before diving into the code we need to comment upon a
couple of issues with setting up the `plot` command for animations.

The underlying plotting program will normally adjust the $y$ axis to the
maximum and minimum values of the curve if we do not specify the axis
ranges explicitly. For an animation such automatic axis adjustment is
misleading - the axis ranges must be fixed to avoid a jumping
axis. The relevant values for the axis range is the minimum and
maximum value of $f$. The minimum value is zero, while the maximum
value appears for $x=m$ and increases with decreasing $s$. The range
of the $y$ axis must therefore be $[0,f(m; m, \min s)]$.

The function $f$ is defined for all $-\infty < x < \infty$, but the
function value is very small already $3s$ away from $x=m$. We may therefore
limit the $x$ coordinates to $[m-3s,m+3s]$.

Now we are ready to take a look at the complete code
for animating how the Gaussian function evolves as the $s$ parameter
is decreased from 2 to 0.2:

!bc pro
from scitools.std import *
import time

def f(x, m, s):
    return (1.0/(sqrt(2*pi)*s))*exp(-0.5*((x-m)/s)**2)

m = 0
s_start = 2
s_stop = 0.2
s_values = linspace(s_start, s_stop, 30)
x = linspace(m -3*s_start, m + 3*s_start, 1000)
# f is max for x=m; smaller s gives larger max value
max_f = f(m, m, s_stop)

# Show the movie on the screen
# and make hardcopies of frames simultaneously
counter = 0
for s in s_values:
    y = f(x, m, s)
    plot(x, y, axis=[x[0], x[-1], -0.1, max_f],
         xlabel='x', ylabel='f', legend='s=%4.2f' % s,
         hardcopy='tmp%04d.png' % counter)
    counter += 1
    #time.sleep(0.2)  # can insert a pause to control movie speed

# Make movie file the simplest possible way
movie('tmp*.png')
!ec

Note that the $s$ values are decreasing (`linspace` handles this
automatically if the start value is greater than the stop value).
Also note that we, simply because we think it is visually more
attractive, let the $y$ axis go from -0.1 although the $f$ function is
always greater than zero.

__Remarks on Filenames.__
For each frame (plot) in the movie we store the plot in a file.  The
different files need different names and an easy way of referring to
the set of files in right order. We therefore suggest to use filenames
of the form `tmp0001.png`, `tmp0002.png`, `tmp0003.png`, etc.  The
printf format `04d` pads the integers with zeros such that `1` becomes
`0001`, `13` becomes `0013` and so on.  The expression `tmp*.png` will
now expand (by an alphabetic sort) to a list of all files in proper
order. Without the padding with zeros, i.e., names of the form
`tmp1.png`, `tmp2.png`, ..., `tmp12.png`, etc., the alphabetic order
will give a wrong sequence of frames in the movie. For instance,
`tmp12.png` will appear before `tmp2.png`.

Note that the names of plot files specified when making hardopies must
be consistent with the specification of names in the call to `movie`.
Typically, one applies a Unix wildcard notation in the call to
`movie`, say `plotfile*.png`, where the asterisk will match any set of
characters. When specifying hardcopies, we must then use a filename
that is consistent with `plotfile*.png`, that is, the filename must
start with `plotfile` and end with `.png`, but in between
these two parts we are free to construct (e.g.) a frame number padded
with zeros.

We recommend to always remove previously generated plot files before
a new set of files is made. Otherwise, the movie may get old and new
files mixed up. The following Python code removes all files
of the form `tmp*.png`:
!bc cod
import glob, os
for filename in glob.glob('tmp*.png'):
    os.remove(filename)
!ec
These code lines should be inserted at the beginning of the code example
above. Alternatively, one may store all plotfiles in a subfolder
and later delete the subfolder. Here is a suitable code segment:
!bc cod
import shutil, os
subdir = 'temp'            # name of subfolder for plot files
if os.path.isdir(subdir):  # does the subfolder already exist?
    shutil.rmtree(subdir)  # delete the whole folder
os.mkdir(subdir)           # make new subfolder
os.chdir(subdir)           # move to subfolder
# ...perform all the plotting...
# ...make movie...
os.chdir(os.pardir)        # optional: move up to parent folder
!ec

__Movie Formats.__
Having a set of (e.g.) `tmp*.png` files, one can simply generate a movie by
a `movie('tmp*.png')` call. The format of the movie is determined by
which video encoders that are installed on the computer. The `movie`
function runs through a list of encoders (`convert`, `mencoder`,
`ffmpeg mpeg_encode`, `ppmtompeg`, `mpeg2enc`, `html`) and choses the
first one which is installed. The fall back encoder `html` actually
does not create a video file, but makes insetad an HTML file that can
play the series of hardcopies made (`tmp*.png`, for instance).
When no filename is given to the `movie` function, the output file
with the movie has filestem `movie` and extension depending on the
video format and the encoder used. For example, if `convert` was used
to create an animated GIF file, the default output file is `movie.gif`.
Similarly, `movie.avi` is in AVI format, `movie.mpeg` is in MPEG format,
and so forth.

You can get complete control of the movie format and the name of the
movie file by supplying the `encoder` and `output_file` arguments to
the `movie` function. This is the recommended use. Here is an
example on generating an animated GIF file `tmpmovie.gif` with
the `convert` program from the ImageMagick software suite:
!bc cod
movie('tmp_*.png', encoder='convert', fps=2,
      output_file='tmpmovie.gif')
!ec
This call requires ImageMagick to be installed on the machine. The
argument `fps` stands for frames per second so here the speed of the
movie is slow in that there is a delay of half a second between each
frame (image file).  To view the animated GIF file, one can use the
`animate` program (also from ImageMagick) and give the movie file as
command-line argument. One can alternatively put the GIF file in a web
page in an IMG tag such that a browser automatically displays the
movie.

Making an HTML file that can play the movie in a web browser
is carried out by the call
!bc cod
movie('tmp_*.png', encoder='html', fps=10,
      output_file='tmpmovie.html')
!ec
Just load `tmpmovie.html` into a browser (e.g., run `firefox tmpmovie.html`
from the command line).

An AVI movie can be generated by the call
!bc cod
movie('tmp_*.png', encoder='ffmpeg', fps=4,
      output_file='tmpmovie.avi',
!ec
Alternatively, we may generate an MPEG movie using
the `ppmtompeg` encoder from the Netpbm suite of
image manipulation tools:
!bc cod
movie('tmp_*.png', encoder='ppmtompeg', fps=24,
      output_file='tmpmovie.mpeg',
!ec
The `ppmtompeg` supports only a few (high) frame rates.

The next sample call to `movie` uses the Mencoder tool and specifies
some additional arguments (video codec, video bitrate, and the
quantization scale):
!bc cod
movie('tmp_*.png', encoder='mencoder', fps=24,
      output_file='tmpmovie.mpeg',
      vcodec='mpeg2video', vbitrate=2400, qscale=4)
!ec
Here is yet another example:
!bc
movie('tmp_*.png', encoder='ffmpeg',
      output_file='tmpmovie1c.mpeg', vodec='mpeg2video')
!ec
The file `examples/movie_demo1.py` that comes with the SciTools source
code generates frames in a movie and creates movie files in many formats.

Playing movie files can be done by a lot of programs. Windows Media
Player is a default choice on Windows machines. On Unix, a variety
of tools can be used. For animated GIF files the `animate` program
from the ImageMagick suite is suitable, or one can simply
show the file in a web page with the HTML command
`<img src="tmpmovie.gif">`. AVI and MPEG files can be played by,
for example, the
`myplayer`, `vlc`, or `totem` programs.

__Making Movies in Batch.__ Sometimes it is desired to carry out
large numbers of computer experiments and create movies in each
individual experiments. Then one probably does not want to have
the screen full of movie windows. To turn off showing the movie
on the screen while creating the individual frames, just
give the `show=False` keyword argument to the `plot` function.
All hardcopies and the movies are then made in batch, which also
might speed up the program since rendering graphics on the screen
is avoided.

===== Controlling the Aspect Ratio of Axes =====

By default, Gnuplot, Matplotlib and other plotting packages
automatically calculate suitable physical sizes of the axis
in the plotting window. However, sometimes one wants to control
this, i.e., impose a certain ratio of the physical extent of the
axis.

In the `gnuplot` and `matplotlib`
backends, we set `daspectmode=manual` and
`daspect=[r,1,1]`, where `r` is the ratio of the y-axis length to
the x-axis length
(`r` equal to `1` gives a square plot area). For example,
!bc cod
plot(x, y, 'r-',
     axis=[0, 1, 0, 1],
     daspect=[1,1,1],
     daspectmode='manual')
!ec
Note that one should always use `axis` and set axes limits explicitly
when prescribing the aspect ratio.

Suppose the x-axis goes from 0 to 20 and the y-axis from -2 to 2.
Often we want the units on the axes to have the same length, i.e.,
the x-axis should be five times as long as the y-axis in this example.
This is accomplished by `daspect=[0.2,1,1])`.
Alternatively, one can apply `daspectmode='equal'` (which means
equal physical units on the axis).

Here is an example which demonstrates various aspects of setting
the aspect ratio:
!bc pro
from scitools.std import *
n = 20  # no of periods of a sine function
r = 80  # resolution of each period
x = linspace(0, n, r*n + 1)
amplitude = 1 + sin(2*pi*0.05*x)
y = amplitude*sin(2*pi*x)

# x-axis goes from 0 to 20, y-axis from -2 to 2.

subplot(2, 1, 1)
plot(x, y,
     axis=[x[0], x[-1], y.min(), y.max()],
     daspectmode='equal',
     title='daspectmode=equal',
     )
subplot(2, 1, 2)
plot(x, y,
     axis=[x[0], x[-1], y.min(), y.max()],
     daspect=[0.5,1,1],
     daspectmode='manual',
     title='daspectmode=manual, daspect=[0.5,1,1]',
     )

figure()
plot(x, y,
     axis=[x[0], x[-1], y.min(), y.max()],
     daspect=[1,1,1],
     daspectmode='manual',
     title='daspectmode=manual, daspect=[1,1,1]',
     )

show()
raw_input()
!ec

===== Moving Plot Window =====

When calculating long time series, it may be desirable to have a
moving plot window that follows the time series. The module
`MovingPlotWindow` was made for this purpose. There are three
different modes of this tool, where each mode moves the window
in a certain way. With `mode` set as `continuous movement`,
the plot window moves with the curves continuously.
With `mode` set as `continuous drawing`, the curves are drawn
from left to right in the plot window, as an animation (one step
at a time). When the curves reach the right border of the plot window,
the window (or more correctly, the x-axis) is moved in a jump
to the right so that the curves are coming in from the left border
again. With `mode` set as `jumps` the curves are plotted directly
in the window and shown for a specified period of time (the `pause`
parameter), then the axis jump one window to the right, and the
curves are displayed in this (time) window. The `jumps` mode is
well suited for quickly browsing a time series. The `continuous
drawing` mode is aimed at studing the "tip" of the time series
as they are computed, and `continuous movement` is a kind of
default choice for most purposes. Running the module file gives
a demo of the three modes.

Below is an example of how to compute a time series by finite
differences and comparing this series with the exact solutions.
For large times, there is a fequency discrepancy that one wants
to investigate.

@@@CODE ../../../lib/scitools/MovingPlotWindow.py def fromto:def _demo@if __name

An appropriate import statement is
!bc
from scitools.MovingPlotWindow import MovingPlotWindow
!ec


===== Advanced Easyviz Topics =====

The information in the previous sections aims at being sufficient for
the daily work with plotting curves. Sometimes, however, one wants to
fine-control the plot or how Easyviz behaves. First, we explain how to
set the backend. Second, we tell how to speed up the
`from scitools.std import *` statement.  Third, we show how to operate with
the plotting program directly and using plotting program-specific
advanced features. Fourth, we explain how the user can grab `Figure`
and `Axis` objects that Easyviz produces "behind the curtain".

=== Controlling the Backend ===

The Easyviz backend can either be set in a configuration file (see
"Setting Parameters in the Configuration File" below), by
importing a special backend in the program, or by adding a
command-line option
!bc
 --SCITOOLS_easyviz_backend name
!ec
where `name` is the name of the backend: `gnuplot`, `vtk`,
`matplotlib`, etc. Which backend you choose depends on what you have
available on your computer system and what kind of plotting
functionality you want.

An alternative method is to import a specific backend in a program. Instead
of the `from scitools.std import *` statement one writes
!bc cod
from numpy import *
from scitools.easyviz.gnuplot_ import *  # work with Gnuplot
# or
from scitools.easyviz.vtk_ import *      # work with VTK
!ec
Note the trailing underscore in the module names for the various backends.

The following program prints a list of the names of the
available backends on your computer system:
!bc pro
from scitools.std import *
backends = available_backends()
print 'Available backends:', backends
!ec
There will be quite some output explaining the missing backends and
what must be installed to use these backends. Be prepared for exceptions
and error messages too.


=== Importing Just Easyviz ===
label{easyviz:imports}

The `from scitools.std import *` statement imports many modules and packages:
!bc cod
from numpy import *
from scitools.numpyutils import *  # some convenience functions
from numpy.lib.scimath import *
from scipy import *                # if scipy is installed
import sys, operator, math
from scitools.StringFunction import StringFunction
from glob import glob
!ec
The `scipy` import can take some time and lead to slow start-up of plot
scripts. A more minimalistic import for curve plotting is
!bc cod
from scitools.easyviz import *
from numpy import *
!ec
Alternatively, one can edit the SciTools configuration file as
explained below in the section "Setting Parameters in the
Configuration File".

Many discourage the use of "star import" as shown above. For example,
the standard import of Numerical Python in all of its documentation is
!bc
import numpy as np
!ec
A similar import for SciTools and Easyviz is
!bc
import scitools.std as st
import numpy as np
!ec
Although `np` functions are important into the namespace of `st` in
this case, we recommend to distinguish the packages when using a prefix.
A typical plotting example will then read
!bc
x = np.linspace(0, 3, 51)
y = x**2*np.exp(-x)
st.plot(x, y, 'r-', title="Plot")
!ec

The corresponding syntax for the
minimalistic import of `scitools.easyviz` and `numpy` reads
!bc
import scitools.easyviz as ev
import numpy as np
!ec


=== Setting Parameters in the Configuration File ===

Easyviz is a subpackage of SciTools, and the the SciTools
configuration file, called `scitools.cfg` has several sections
(`[easyviz]`, `[gnuplot]`, and `[matplotlib]`) where parameters
controlling the behavior of plotting can be set. For example, the
backend for Easyviz can be controlled with the `backend` parameter:
!bc dsni
[easyviz]
backend = vtk
!ec
Similarly, Matplotlib's use of LaTeX can be controlled by a boolean
parameter:
!bc dsni
[matplotlib]
text.usetex = <bool> false
!ec
The text `<bool>` indicates that this is a parameter with a boolean

A configuration file with name `.scitools.cfg` file can be placed in
the current working folder, thereby affecting plots made in this
folder, or it can be located in the user's home folder, which will
affect all plotting sessions for the user in question. There is also a
common SciTools config file `scitools.cfg` for the whole site, located
in the directory where the `scitools` package is installed. It is
recommended to copy the `scitools.cfg`, either from installation or
the SciTools source folder `lib/scitools`, to `.scitools.cfg`
in your home folder. Then you can easily control the Easyviz backend
and other paramteres by editing your local `.scitools.cfg` file.

Parameters set in the configuration file can also be set directly
on the command line when running a program. The name of the
command-line option is
!bc dsni
--SCITOOLS_sectionname_parametername
!ec
where `sectionname` is the name of the section in the file
and `parametername` is the name of the
parameter. For example, setting the `backend` parameter in the
`[easyviz]` section by
!bc dsni
--SCITOOLS_easyviz_backend gnuplot
!ec
Here is an example where we use Matplotlib as backend, turn on
the use of LaTeX in Matplotlib, and avoid the potentially slow import
of SciPy:
!bc dsni
python myprogram.py --SCITOOLS_easyviz_backend matplotlib \
    --SCITOOLS_matplotlib_text.usetex true --SCITOOLS_scipy_load no
!ec


=== Working with the Plotting Program Directly ===

Easyviz supports just the most common plotting commands, typically the
commands you use "95 percent" of the time when exploring curves.
Various plotting packages have lots of additional commands for
diverse advanced features.  When Easyviz does not have a command
that supports a particular feature, one can grab the Python object
that communicates with the underlying plotting program (the
"backend") and work with this object directly, using plotting
program-specific command syntax.  Let us illustrate this principle
with an example where we add a text and an arrow in the plot, see
Figure ref{fig:plot2i}.

FIGURE:[figs/plot2i.eps] Illustration of a text and an arrow using Gnuplot-specific commands. label{fig:plot2i}

Easyviz does not support arrows at arbitrary places inside the plot,
but Gnuplot does. If we use Gnuplot as backend, we may grab the
`Gnuplot` object and issue Gnuplot commands to this object
directly. Here is an example of the typical recipe, written after the
core of the plot is made in the ordinary (plotting
program-independent) way:

!bc cod
if backend == 'gnuplot':
    g = get_backend()
    # g is a Gnuplot object, work with Gnuplot commands directly:
    g('set label "global maximum" at 0.1,0.5 font "Times,18"')
    g('set arrow from 0.5,0.48 to 0.98,0.37 linewidth 2')
    g.refresh()
    g.hardcopy('tmp2.eps')  # make new hardcopy

    g.reset()               # new plot
    data = Gnuplot.Data(t, t**3*exp(-t), with_='points 3 3',
                        title='t**3*exp(-t)')
    func = Gnuplot.Func('t**4*exp(-t)', title='t**4*exp(-t)')
    g('set tics border font "Courier,14"')
    g.plot(func, data)
!ec
For the available features and the syntax of commands, we refer to
the Gnuplot manual and the `demo.py` program in Python interface to
Gnuplot. Note that one must call `g.hardcopy` to save the figure
to file. A call to `savefig` or `hardcopy` remakes the plot, but
without the special calls `g('...')` so the label and arrow are
left out of the hardcopy in the example above.

Here is an example with Matplotlib:
!bc cod
if backend == 'matplotlib':
    pyplot = get_backend()
    # Work with standard matplotlib.pyplot functions
!ec
The files `grab_backend*.py` in the `examples` folder of the SciTools
source code contain many examples on how to do backend-specific
operations, especially with Matplotlib.  Note that after having issued
calls via the `pyplot` object, one must apply `pyplot.savefig` to
correctly save the plot (a plain `savefig` or `hardcopy` remakes the
plot without the features inserted by the `pyplot` object).

Here are some useful links to documentation of various plotting packages:

 * "Matplotlib Documentation": "http://matplotlib.sourceforge.net/contents.html"
 * "Gnuplot Documentation": "http://www.gnuplot.info/documentation.html"
 * "Gnuplot Tips (Not So Frequently Asked Questions)": "http://t16web.lanl.gov/Kawano/gnuplot/index-e.html"
 * "Grace User's Guide": "http://matplotlib.sourceforge.net/contents.html"
 * "PyX Documentation": "http://pyx.sourceforge.net/documentation.html"
 * "PyX Tutorial for Gnuplot Users": "http://alumni.cs.ucr.edu/~titus/pyxTutorial/"

The idea advocated by Easyviz goes as follows. You can quickly generate
plots with Easyviz using standard commands that are independent of
the underlying plotting package. However, when you need advanced
features, you must add plotting package-specific code as shown
above. This principle makes Easyviz a light-weight interface, but
without limiting the available functionality of various plotting programs.


=== Working with Axis and Figure Objects ===

Easyviz supports the concept of Axis objects, as in Matlab.
The Axis object represents a set of axes, with curves drawn in the
associated coordinate system. A figure is the complete physical plot.
One may have several axes in one figure, each axis representing a subplot.
One may also have several figures, represented by different
windows on the screen or separate hardcopies.

Users with Matlab experience may prefer to set axis
labels, ranges, and the title using an Axis object instead of
providing the information in separate commands or as part of a `plot`
command. The `gca` (get current axis) command returns an `Axis`
object, whose `set` method can be used to set axis properties:

!bc cod
plot(t, y1, 'r-', t, y2, 'bo',
     legend=('t^2*exp(-t^2)', 't^4*exp(-t^2)'),
     savefig='tmp2.eps')

ax = gca()   # get current Axis object
ax.setp(xlabel='t', ylabel='y',
        axis=[0, 4, -0.1, 0.6],
        title='Plotting two curves in the same plot')
show()  # show the plot again after ax.setp actions
!ec

The `figure()` call makes a new figure, i.e., a
new window with curve plots. Figures are numbered as 1, 2, and so on.
The command `figure(3)` sets the current figure object to figure number
3.

Suppose we want to plot our `y1` and `y2` data in two separate windows.
We need in this case to work with two `Figure` objects:
!bc cod
plot(t, y1, 'r-', xlabel='t', ylabel='y',
     axis=[0, 4, -0.1, 0.6])

figure()  # new figure

plot(t, y2, 'bo', xlabel='t', ylabel='y')
!ec
We may now go back to the first figure (with the `y1` data) and
set a title and legends in this plot, show the plot, and make a PostScript
version of the plot:
!bc cod
figure(1)  # go back to first figure
title('One curve')
legend('t^2*exp(-t^2)')
show()
savefig('tmp2_1.eps')
!ec
We can also adjust figure 2:
!bc
figure(2)  # go to second figure
title('Another curve')
savefig('tmp2_2.eps')
show()
!ec
The current `Figure` object is reached by `gcf` (get current figure),
and the `dump` method dumps the internal parameters in the `Figure`
object:
!bc cod
fig = gcf(); print fig.dump()
!ec
These parameters may be of interest for troubleshooting when Easyviz
does not produce what you expect.

Let us then make a third figure with two plots, or more precisely, two
axes: one with `y1` data and one with `y2` data.
Easyviz has a command `subplot(r,c,a)` for creating `r`
rows and `c` columns and set the current axis to axis number `a`.
In the present case `subplot(2,1,1)` sets the current axis to
the first set of axis in a "table" with two rows and one column.
Here is the code for this third figure:
!bc cod
figure()  # new, third figure
# Plot y1 and y2 as two axis in the same figure
subplot(2, 1, 1)
plot(t, y1, xlabel='t', ylabel='y')
subplot(2, 1, 2)
plot(t, y2, xlabel='t', ylabel='y')
title('A figure with two plots')
show()
savefig('tmp2_3.eps')
!ec

Note: The Gnuplot backend will overwrite the tickmarks on the $y$ axis
if two or more curves in the same subplot have significantly different
variations in $y$ direction. To avoid this cluttering of tickmarks,
set the axes extent explicitly.

If we need to place an axis at an arbitrary position in the figure, we
must use the command
!bc cod
ax = axes(viewport=[left, bottom, width, height])
!ec
The four parameteres `left`, `bottom`, `width`, `height`
are location values between 0 and 1 ((0,0) is the lower-left corner
and (1,1) is the upper-right corner). However, this might be a bit
different in the different backends (see the documentation for the
backend in question).

=== Mathematics and LaTeX in Legends, Title, and Axis Labels ===

Some plotting packages support nicely formatted mathematics as
axis labels, in legends, and in the figure title. For example,
Matplotlib accepts standard LaTeX syntax, while Gnuplot,
when saving figures to PostScript format, supports
greek letters, sub- and super-scripts, exponentials, etc.
Different plotting engines (backends) will require mathematics in
legends, titles, and labels to be formatted differently.

  * With Matplotlib we recommend to use standard LaTeX.
  * With Gnuplot we recommend plain text when plotting on
    the screen, and greek letters preceded with a backslash
    when saving to file. Gnuplot suports LaTeX syntax for
    sub- and super-scripts (underscore and hat, resp.).
    Other types of mathematics should be expressed in plain text.

The file `examples/math_text.py` tests different syntax in legends,
axis labels, and titles. Running this script with
`--SCITOOLS_easyviz_backend X` for different values of `X`
(`gnuplot`, `matplotlib`, `grace`, `pyx`, etc.) produces plots
that one can examine to see various formats treat mathematics with and
without LaTeX syntax.

If it is important to have Easyviz code that works with several
backends, one can apply a little if-else test:
!bc cod
from scitools.std import *
...
if backend == 'gnuplot':
    title_screen = 'mu=0.5, alpha=sum(i=1 to n) tau_i^2'
    title_eps = r'\mu=0.5, \alpha=sum(i=1 to n) \tau_i^2'
elif backend == 'matplotlib':
    title_screen = title_eps = \
          r'$mu=0.5$, $\alpha=\sum_{i=1}^n \tau_i^2$'
else:
    title_screen = title_eps = 'mu=0.5, alpha=sum(i=1 to n) tau_i^2'

plot(...)
...
title(title_screen)
show()
title(title_eps)
savefig('myplot.eps')
!ec

=== Turning Off All Plotting ===

Sometimes, especially during debugging or when trying out a large-scale
experiment, it is nice to turn off all plotting on the screen and
all making of hardcopies. This is easily done by
!bc cod
turn_off_plotting(globals())
!ec
All the plot functions now "do nothing" (actually they are `DoNothing`
objects from `scitools.misc`).
