1413 lines
48 KiB
HTML
1413 lines
48 KiB
HTML
<!--startcut ==============================================-->
|
|
<!-- *** BEGIN HTML header *** -->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML><HEAD>
|
|
<title>Numerical Workbenches, part III LG #71</title>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
|
|
ALINK="#FF0000">
|
|
<!-- *** END HTML header *** -->
|
|
|
|
<CENTER>
|
|
<A HREF="http://www.linuxgazette.com/">
|
|
<IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.png"
|
|
WIDTH="600" HEIGHT="124" border="0"></A>
|
|
<BR>
|
|
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="qubism.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue71/spiel.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="lg_backpage71.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
<P>
|
|
</CENTER>
|
|
|
|
<!--endcut ============================================================-->
|
|
|
|
<H4 ALIGN="center">
|
|
"Linux Gazette...<I>making Linux just a little more fun!</I>"
|
|
</H4>
|
|
|
|
<P> <HR> <P>
|
|
<!--===================================================================-->
|
|
|
|
<center>
|
|
<H1><font color="maroon">Numerical Workbenches, part III</font></H1>
|
|
<H4>By <a href="mailto:cspiel@hammersmith-consulting.com">Christoph Spiel</a></H4>
|
|
</center>
|
|
<P> <HR> <P>
|
|
|
|
<!-- END header -->
|
|
|
|
|
|
|
|
|
|
<p>Parts I and II of this little series on numerical math workbenches on
|
|
GNU/Linux have covered rather dry subjects like matrix manipulations and <em>
|
|
for</em>-loops. This part brings more color to the screens as it turns to the
|
|
graphical capabilities of GNU/Octave, Scilab, and Tela. It will deviate from
|
|
the previous way of presenting the three applications, because the differences
|
|
of the graphical backends are far too big to allow for a uniform treatment
|
|
with only a few explanations on the differences.</p>
|
|
|
|
<p>The article starts with an introduction applicable to all programs. To give
|
|
the reader maximum benefit, all applications have to solve the same three real
|
|
life <a href="#problems">problems</a>. This simplifies the comparison despite
|
|
the differences of the implementations. In the last part, <a href="#octave">
|
|
Octave</a>, <a href="#scilab">Scilab</a>, and <a href="#tela">Tela</a> have to
|
|
tackle the given tasks.</p>
|
|
|
|
<h2><a name="introduction">Introduction</a></h2>
|
|
|
|
<dl>
|
|
<dt><strong><a name="item_Discrete_Data_Only">Discrete Data
|
|
Only</a></strong><br>
|
|
</dt>
|
|
|
|
<dd>As all three applications are designed to work with vectors and matrices,
|
|
their graphics backends only understand this kind of data. Doh! For the user
|
|
this means that the graph of a mathematical function like
|
|
|
|
<pre>
|
|
{ sin(x)/x for x <> 0
|
|
y := f(x) = {
|
|
{ 1 for x == 0
|
|
</pre>
|
|
|
|
<p>cannot be drawn from the above expression, but the function has to be
|
|
transformed into discrete pairs (<em>x(i)</em>, <em>y(i)</em>). This
|
|
transformation is called sampling. To sample <em>f(x)</em>, we pick
|
|
values <em>x</em> where we are interested in <em>f(x)</em> and compute
|
|
<em>f</em> for the given <em>x</em>. Any reader who has followed the earlier
|
|
parts, will immediately recognize that this involves a vector operation.</p>
|
|
|
|
<pre>
|
|
### GNU/Octave code
|
|
</pre>
|
|
|
|
<pre>
|
|
function y = f(x)
|
|
if x == 0.0
|
|
y = 1.0;
|
|
else
|
|
y = sin(x) ./ x;
|
|
endif
|
|
endfunction
|
|
</pre>
|
|
|
|
<pre>
|
|
x = linspace(0.0, 4*pi, 50);
|
|
y = f(x);
|
|
</pre>
|
|
|
|
<p><em>linspace(start, end, n)</em> returns a vector from <em>start</em> to
|
|
<em>end</em>, whose <em>n</em> elements are evenly spaced. The
|
|
vectors <em>x</em> and <em>y</em> can be passed to an appropriate
|
|
plotting function.</p>
|
|
|
|
<p>If data already are in vectorized form, they can be displayed
|
|
immediately.</p>
|
|
</dd>
|
|
|
|
<dt><strong><a name="item_Complexity_at_Large">Complexity at
|
|
Large</a></strong><br>
|
|
</dt>
|
|
|
|
<dd>How do we actually display a graph? This question leads us to the
|
|
fundamental problem all applications run into when it comes to graphical
|
|
output of data: either complicated or many simple function calls! Let us first
|
|
consider the complexity for the user of a call to solve a system of linear
|
|
equations
|
|
|
|
<pre>
|
|
x = a \ b # Octave, Scilab
|
|
</pre>
|
|
|
|
<p>or</p>
|
|
|
|
<pre>
|
|
x = linsolve(a, b) // Tela
|
|
</pre>
|
|
|
|
<p>Even if we try hard to artificially complicate the calls (yet leaving them
|
|
useful), we hit the end of the road at</p>
|
|
|
|
<pre>
|
|
x = linsolve(a, b, "CompletePivoting", "DoIterativeRefinement")
|
|
</pre>
|
|
|
|
<p>This is, with the two additional parameters -- pivoting strategy and
|
|
iterative refinement of the solution -- the user completely controls <em>
|
|
linsolve()</em>. All other ``decisions'' can reasonably be taken by the
|
|
workbench itself, for example, what algorithm to use if matrix <em>a</em>
|
|
has a special form.</p>
|
|
|
|
<p>Contrast this with the 2d-graph of</p>
|
|
|
|
<pre>
|
|
x = [2.25, 2.27, 2.42, ...]
|
|
y = [0.363, 0.360, 0.337, ...]
|
|
</pre>
|
|
|
|
<p>What options can we think of?</p>
|
|
|
|
<ul>
|
|
<li>Draw isolated data points or connect data points with straight lines.</li>
|
|
|
|
<li>Which symbol to draw at each data point? A dot, star, circle, or asterisk?
|
|
What color should the data points be?</li>
|
|
|
|
<li>Which kind of line to draw between the data points? Continuous, dashed,
|
|
dotted, or dash-dotted? What line thickness and what color is the line?</li>
|
|
|
|
<li>Scale the plot to fit within the plotting window?</li>
|
|
|
|
<li>Draw coordinate axes? Linear or logarithmic <em>x</em> or <em>y</em> axis?
|
|
Both axes logarithmic?</li>
|
|
|
|
<li>Graduate or annotate the axes?</li>
|
|
|
|
<li>...</li>
|
|
</ul>
|
|
|
|
<p>Many more reasonable options are conceivable. The point is: we cannot
|
|
expect plotting to be as simple to use as is for example solving a system of
|
|
linear equations -- not because the applications are badly written, but
|
|
because the topic is inherently more complicated on the user's side. Hence,
|
|
nobody should be surprised if she ever needs 20 or more lines to define a
|
|
publication quality plot in Octave, Scilab, or Tela.</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<h2><a name="problems">Problems</a></h2>
|
|
|
|
<p>To make the competition interesting, I put up problems, which are not too
|
|
far away from the Real World(tm). Each of the three applications will have to
|
|
cope with three different types of plots:</p>
|
|
|
|
<ol>
|
|
<li><strong><a name="item_2D_Plot_of_Discrete_Data">2D Plot of Discrete
|
|
Data</a></strong><br>
|
|
|
|
|
|
<p>Display three sets of data (<a href="misc/spiel/l1.ascii">l1.ascii</a>, <a
|
|
href="misc/spiel/l2.ascii">l2.ascii</a>, <a href="misc/spiel/l3.ascii">
|
|
l3.ascii</a>) on a single page. The sets have a different number of data
|
|
points.</p>
|
|
|
|
<p>The data are stored as two columns, column 1 holds the <em>
|
|
x</em>-value, and column 2 the <em>y</em>-value:</p>
|
|
|
|
<pre>
|
|
0.2808 3.419E-07
|
|
0.3711 3.459E-07
|
|
0.4882 3.488E-07
|
|
...
|
|
</pre>
|
|
|
|
<p>The graph must show title, axes captions, and legend. The <em>x</em> and
|
|
<em>y</em> ranges are supplied by the user.</p>
|
|
</li>
|
|
|
|
<li><strong><a name="item_3D_Plot_of_a_Function">3D Plot of a
|
|
Function</a></strong><br>
|
|
Plot Rosenbrock's function (in two dimensions)
|
|
|
|
<pre>
|
|
f(u, v) = 100*(v - u^2)^2 + (1 - u)^2
|
|
</pre>
|
|
|
|
<p>as a 3d-surface in the parameter ranges -3 <= <em>
|
|
u</em> <= 3 and -2 <= <em>
|
|
v</em> <= 4.</p>
|
|
|
|
<p>Annotate the plot with title and axes captions.</p>
|
|
</li>
|
|
|
|
<li><strong><a name="item_Contour_Plot_of_a_Function">Contour Plot of a
|
|
Function</a></strong><br>
|
|
Plot function
|
|
|
|
<pre>
|
|
g(u, v) = exp(u) * (4*u^2 + 2*v^2 + 4*u*v + 2*v + 1)
|
|
</pre>
|
|
|
|
<p>with contours, this is, <em>f(u, v) = z</em> for given <em>z</em> in the
|
|
parameter ranges -4.5 <= <em>u</em> <= -0.5 and
|
|
-1 <= <em>v</em> <= 3.</p>
|
|
|
|
<p>The iso-lines are defined by a user-specified ``weight'' function.</p>
|
|
|
|
<pre>
|
|
( z - z_0 ) 3
|
|
z_iso = (z_1 - z_0) * ( --------- ) + z_0
|
|
( z_1 - z_0 )
|
|
</pre>
|
|
|
|
<p>where <em>z_0</em> and <em>z_1</em> are the minimum and maximum values of
|
|
<em>g(u, v)</em> in the plot's range.</p>
|
|
|
|
<p>Again, annotate the plot with title and axes captions.</p>
|
|
</li>
|
|
</ol>
|
|
|
|
<p>All graphics must be rendered for two devices,</p>
|
|
|
|
<ul>
|
|
<li>X11 terminal and</li>
|
|
|
|
<li>Postscript printer.</li>
|
|
</ul>
|
|
|
|
<h2><a name="octave">Octave</a></h2>
|
|
|
|
<p>You know Gnuplot? Then learning to use GNU/Octave's plot functions will be
|
|
a piece of cake. All you need to do is precede the Gnuplot commands with a
|
|
``<code>g</code>'' to reach at the Octave equivalent. -- Oh, you haven't tried
|
|
Gnuplot yet? Then I will guide you through the examples. However, having a
|
|
Gnuplot manual (online or dead-tree edition) ready may be helpful.</p>
|
|
|
|
If you do not want to download Gnuplot's manual, you can use one of the <a
|
|
href=
|
|
"http://pi3.informatik.uni-mannheim.de/staff/mitarbeiter/westmann/gnuplot.html">
|
|
publicly accessible versions</a>.
|
|
|
|
<h3><a name="octave: 2d discrete data plot">Octave: 2D Discrete Data
|
|
Plot</a></h3>
|
|
|
|
<p>For an easier discussion, I have split the code into blocks. Each block
|
|
gathers commands that belong together. The blocks are labeled with numbers in
|
|
square brackets, to allow for referencing them in the text.</p>
|
|
|
|
<pre>
|
|
### [1] Read data set_i into N_i-times-2 matrices
|
|
set1 = load("l1.ascii");
|
|
set2 = load("l2.ascii");
|
|
set3 = load("l3.ascii");
|
|
</pre>
|
|
|
|
<pre>
|
|
### [2] Reset Gnuplot
|
|
graw("reset;");
|
|
clearplot;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [3] Define decorations and plot area
|
|
gset title "Comparison of sets L1, L2, and L3";
|
|
gset xlabel "Temperature / K";
|
|
gset ylabel "Voltage / V";
|
|
gset key top left;
|
|
gset xrange [0 : 100];
|
|
gset yrange [8e-8 : 2e-6];
|
|
</pre>
|
|
|
|
<pre>
|
|
### [4] Plot data
|
|
hold on;
|
|
gplot set1 title "Set L1" with points;
|
|
gplot set2 title "Set L2" with points;
|
|
gplot set3 title "Set L3" with points;
|
|
hold off;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [5] Switch to PostScript output and plot into file
|
|
gset terminal push;
|
|
gset terminal postscript;
|
|
gset output "oct1.eps";
|
|
replot;
|
|
gset terminal pop;
|
|
gset output;
|
|
</pre>
|
|
|
|
<p><img height="450" alt=
|
|
"[Graphics: The Gnuplot window that has been opened by Octave's graphics commands shows the three data sets. The data points are drawn with blue, green, and red markers. The markers themselves have different shape. The plot has a title. Both axes show the annotations as defined by the gset-commands.]"
|
|
src="misc/spiel/oct1.png" width="600"> The output to the Postscript terminal,
|
|
block [6], produced a <a href="misc/spiel/oct1.eps">printable version
|
|
(eps)</a> of the graphics.</p>
|
|
|
|
<p>Block [1] should be clear from the previous articles. The first
|
|
interaction with Gnuplot happens in [2], where Gnuplot is reset to a known
|
|
state and the X11-plot window gets cleared. A known state is helpful when
|
|
still experimenting with Gnuplot's options. In our case reseting is
|
|
unnecessary, but it does not hurt.</p>
|
|
|
|
<p>The block of <code>gset</code> commands, [3] is self explaining except</p>
|
|
|
|
<pre>
|
|
gset key top left
|
|
</pre>
|
|
|
|
<p>which means: ``put the legend (or key) inside the plotting area at the
|
|
north-west corner''. <code>xrange</code> and <code>yrange</code> with their
|
|
special interval syntax set the width and height of the plot range.</p>
|
|
|
|
<p>Now, the actual data can be rendered into the plot window [4]. Because the
|
|
data sets have different sizes, they cannot be gathered in a single matrix.
|
|
Hence, each data set must be plotted by itself, and Gnuplot must be told --
|
|
with <code>hold on</code> -- that it should collect all <code>
|
|
gplot</code> commands until the last plot of the set is completed and
|
|
<code>hold off</code> is called. The calls to <em>gplot</em> essentially
|
|
contain the data matrix</p>
|
|
|
|
<pre>
|
|
gplot set1
|
|
</pre>
|
|
|
|
<p>The title, which shows up in the plot's legend, is assigned in the call to
|
|
<code>gplot</code>, too.</p>
|
|
|
|
<p>Block [5] is specific to the way Gnuplot works. For each plot it uses
|
|
a <em>terminal</em> and an <em>output</em> file (remember that in UN*X
|
|
everything is a file, as for example is the console). When Gnuplot is running
|
|
under X, the terminal type defaults to X11 and output file defaults to
|
|
Gnuplot's X11-graphic window. Both, <em>terminal</em> and <em>
|
|
output</em> file can be changed independently with <code>gset</code>
|
|
commands. Thus, to get the same graphics in a different format, we switch from
|
|
the current terminal to Postscript, and put an ordinary file's name at the
|
|
output. Function <code>replot</code> replays all plot commands for us, we
|
|
do not have to write them again. After that the terminal and output settings
|
|
are undone, which is optional, but helpful if the user wants to twiddle some
|
|
more <code>gset</code>'s and repeatedly check their influence on the graph's
|
|
appearance.</p>
|
|
|
|
<h3><a name="octave: 3d function plot">Octave: 3D Function Plot</a></h3>
|
|
|
|
<pre>
|
|
### [1] Define function
|
|
function z = f(u, v)
|
|
## truncated Rosenbrock function
|
|
z = 100.0*(v - u.^2).^2 + (1.0 - u).^2;
|
|
zv = z(:);
|
|
zv(find(zv > 100.0)) = 100.0;
|
|
z = reshape(zv, size(z));
|
|
endfunction
|
|
</pre>
|
|
|
|
<pre>
|
|
### [2] Sample function f()
|
|
x = linspace(-3, 3, 40);
|
|
y = linspace(-2, 4, 40);
|
|
[xx, yy] = meshgrid(x, y);
|
|
z_splot = splice_mat(xx, yy, f(xx, yy));
|
|
</pre>
|
|
|
|
<pre>
|
|
### [3] Reset Gnuplot
|
|
graw("reset;");
|
|
clearplot;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [4] Define decorations and viewing direction
|
|
gset data style line;
|
|
gset title "Rosenbrock Function";
|
|
gset xlabel "u";
|
|
gset ylabel "v";
|
|
gset view 30, 160;
|
|
gset hidden;
|
|
gset nokey
|
|
gset parametric;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [5] Plot
|
|
gsplot z_splot;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [6] Switch to PostScript output and plot into file
|
|
gset terminal push;
|
|
gset terminal postscript;
|
|
gset output "oct2.eps";
|
|
replot;
|
|
gset terminal pop;
|
|
gset output;
|
|
gset noparametric;
|
|
</pre>
|
|
|
|
<pre>
|
|
system("gzip --best --force oct2.eps");
|
|
</pre>
|
|
|
|
<p><img height="450" alt=
|
|
"[Graphics: The Gnuplot window shows a red-mesh that is 'deformed' according to function f(u, v). The whole plot looks like the imprint of a boomerang.]"
|
|
src="misc/spiel/oct2.png" width="600"> A <a href="misc/spiel/oct2.eps.gz">
|
|
printer-ready version</a> (eps.gz) is available, too.</p>
|
|
|
|
<p>Again the first block, [1], should be easy to understand for anyone who has
|
|
read Part 1 and 2 of this series for it only uses known functions. In
|
|
contrast, [2] introduces two new functions. Out friend <em>linspace()</em>
|
|
quickly generates two vectors which will define where <em>f(u, v)</em> will be
|
|
evaluated: from vectors <em>x</em> and <em>y</em>, a grid is constructed,
|
|
this is, two matrices <em>xx</em> and <em>yy</em>, where each pair of
|
|
matrix elements <em>(xx(i, j), yy(i, j))</em>,
|
|
1 <= <em>i</em>, <em>j</em> <= 40, define a (grid-)
|
|
point at which function <em>z = f(u, v)</em> will be evaluated.
|
|
The matrix of all <em>z</em>-values at the grid points then simply is <code>zz
|
|
= f(xx, yy)</code>. However, we are not done at this point, because Octave
|
|
requires to pass a specially formatted matrix to the 3d-plot
|
|
function <em>gsplot</em>.</p>
|
|
|
|
<p>The user-defined function <a href="misc/spiel/splice_mat.m">
|
|
splice_mat()</a> does exactly the needed operation: collect the grid data <em>
|
|
xx</em> and <em>yy</em> along with the <em>z</em>-values in matrix <em>
|
|
z_plot</em>. Matrix <em>z_plot</em> can be handed over to <em>gsplot</em>
|
|
without further ado (given Gnuplot is in parametric mode. (we will be in
|
|
parametric mode and for the given kind of problem parametric mode is the only
|
|
way to go (and I don't want to introduce another level of parenthesis
|
|
(really!))))</p>
|
|
|
|
<p>Block [4], a collection of <code>gset</code>s, looks almost familiar.
|
|
Some new settings are</p>
|
|
|
|
<ul>
|
|
<li><strong><a name="item_gset_data_style_line">gset data style
|
|
line</a></strong><br>
|
|
Join adjacent mesh-points with (by default: red) lines.</li>
|
|
|
|
<li><strong><a name="item_gset_view_x_angle%2C_z_angle">gset view x_angle,
|
|
z_angle</a></strong><br>
|
|
Rotate the view point around the <em>x</em>-axis by <em>x_angle</em> degrees,
|
|
then rotate around the new <em>z</em>-axis by <em>z_angle</em> degrees.</li>
|
|
|
|
<li><strong><a name="item_gset_hidden">gset hidden</a></strong><br>
|
|
Suppress invisible mesh lines. The back side of the mesh is drawn differently
|
|
(green in the X11-window and with dashed black lines in the
|
|
Postscript terminal).</li>
|
|
|
|
<li><strong><a name="item_gset_nokey">gset nokey</a></strong><br>
|
|
Suppress any legend.</li>
|
|
|
|
<li><strong><a name="item_gset_parametric">gset parametric</a></strong><br>
|
|
See GNU/Octave's documentation. (<code>help -i gsplot</code> from Octave, or
|
|
<code>info octave --node='Three-Dimensional Plotting'</code> from the
|
|
shell.)</li>
|
|
</ul>
|
|
|
|
<p>After so much preparation, the actual plot command, <code>gsplot
|
|
z_splot</code> in [5] looks trivial.</p>
|
|
|
|
<p>The Postscript block [6] is similar to [5] in Section <a href=
|
|
"#octave: 2d discrete data plot">``Octave: 2d discrete data plot''</a>. The
|
|
only additional job [6] does is gzipping the eps-file. In general <em>
|
|
system(``shell-commands'')</em> executes <em>shell-commands</em> in a
|
|
sub-shell. Obviously, this is extremely useful when interacting with an
|
|
external application, like gzip(1).</p>
|
|
|
|
<h3><a name="octave: contour function plot">Octave: Contour Function
|
|
Plot</a></h3>
|
|
|
|
<pre>
|
|
### [1] Define function
|
|
function z = g(u, v)
|
|
z = exp(u) .* (4.0*u.^2 + 2.0*v.^2 + 4.0*u.*v + 2.0*v + 1.0);
|
|
endfunction
|
|
</pre>
|
|
|
|
<pre>
|
|
### [2] Define weight function for iso-line distances
|
|
function y = pow_weight(x, n)
|
|
## Map interval X onto itself, weight with N-th power.
|
|
d = max(x) - min(x);
|
|
y = d*((x - min(x))/d).^n + min(x);
|
|
endfunction
|
|
</pre>
|
|
|
|
<pre>
|
|
### [3] Sample function g()
|
|
x = linspace(-4.5, -0.5, 40);
|
|
y = linspace(-1.0, 3.0, 40);
|
|
[xx, yy] = meshgrid(x, y);
|
|
zz = g(xx, yy);
|
|
z_splot = splice_mat(xx, yy, zz);
|
|
</pre>
|
|
|
|
<pre>
|
|
### [4] Compute iso-line distances
|
|
iso_levels = pow_weight(linspace(min(min(zz))*1.01, ...
|
|
max(max(zz))*0.99, 12), 3.0);
|
|
il_str = sprintf("%f,", iso_levels);
|
|
il_str = il_str(1 : length(il_str)-1); # remove last ","
|
|
</pre>
|
|
|
|
<pre>
|
|
### [5] Reset Gnuplot
|
|
graw("reset;");
|
|
clearplot;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [6] Define decorations and viewing direction
|
|
gset data style line;
|
|
gset title "Contour Plot of g(u, v)";
|
|
gset xlabel "u";
|
|
gset ylabel "v";
|
|
gset contour base;
|
|
gset nosurface;
|
|
gset view 0, 0;
|
|
eval(sprintf("gset cntrparam levels discrete %s", il_str));
|
|
gset parametric;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [7] Plot
|
|
gsplot z_splot;
|
|
</pre>
|
|
|
|
<pre>
|
|
### [8] Switch to PostScript output and plot into file
|
|
gset terminal push;
|
|
gset terminal postscript;
|
|
gset output "oct3.eps";
|
|
replot;
|
|
gset terminal pop;
|
|
gset output;
|
|
gset noparametric;
|
|
</pre>
|
|
|
|
<p><img height="450" alt=
|
|
"[Graphics: The Gnuplot window shows 12 iso-lines each with a different color. The plot exhibits a saddle point of g(u, v) in the right third of the image.]"
|
|
src="misc/spiel/oct3.png" width="600"> A <a href="misc/spiel/oct3.eps">
|
|
printable version (eps)</a> is available, too.</p>
|
|
|
|
<p>After working through the 2d discrete and the 3d function plot examples,
|
|
the top three blocks [1-3] of the contour function script should not
|
|
raise many questions. In block [4] however, I have to prepare a trick,
|
|
which I must play at the end of block [6]. The job is to plot contour
|
|
lines with a user-defined function. The values of this function and therefore
|
|
the positions of the iso-lines are not known in advance.</p>
|
|
|
|
<p>Gnuplot offers several ways to define iso-lines, for example, automatic
|
|
computation of a given number of (linearly spaced) contours or defining a
|
|
minimum and a maximum contour value with a fixed increment between two
|
|
adjacent contours. Our problem requires a more general solution because the
|
|
iso-lines are not equally spaced along the <em>z</em>-axis. For completely
|
|
arbitrary iso-line values, as the third way if specifying contour lines,
|
|
Gnuplot has the following <code>gset</code> command</p>
|
|
|
|
<pre>
|
|
gset cntrparam discrete z1, z2, ..., zN
|
|
</pre>
|
|
|
|
<p>where <em>z1</em>, <em>z2</em>, ..., <em>zN</em> are the <em>z</em>-values
|
|
of the iso-lines given as <em>floating point literals</em>. Thus,</p>
|
|
|
|
<pre>
|
|
gset cntrparam discrete 0.2, 0.4, 0.8
|
|
</pre>
|
|
|
|
<p>is a perfect call, whereas</p>
|
|
|
|
<pre>
|
|
z1 = 0.2
|
|
z2 = 0.4
|
|
z3 = 0.8
|
|
gset cntrparam discrete z1, z2, z3
|
|
</pre>
|
|
|
|
<p>is nothing but a syntax error as would be</p>
|
|
|
|
<pre>
|
|
gset cntrparam discrete iso_levels
|
|
</pre>
|
|
|
|
<p>Remember, <code>gset</code> needs floating point literals!</p>
|
|
|
|
<p>We are stuck unless we apply a bit of magic. If we present a complete
|
|
<code>gset</code> line to Octave, one where the values of vector <em>
|
|
iso_levels</em> are ``interpolated'' into (Perl programmers do this all day
|
|
long), the race is won. Here is how the trick is played:</p>
|
|
|
|
<pre>
|
|
# Convert iso_levels to comma-separated string. Octave reuses
|
|
# the format specifier list if there are more items to print than
|
|
# there are format specifiers. Don't try this with C's printf :-)
|
|
il_string = sprintf("%f,", iso_levels)
|
|
</pre>
|
|
|
|
<pre>
|
|
# Remove comma past last contour value in the string.
|
|
il_string = il_string(1 : length(il_string)-1)
|
|
</pre>
|
|
|
|
<pre>
|
|
# Play interpolation trick a second time
|
|
gset_string = sprintf("gset cntrparam levels discrete %s", il_string);
|
|
</pre>
|
|
|
|
<pre>
|
|
# Execute the command which is stored in the variable gset_string
|
|
eval(gset_string);
|
|
</pre>
|
|
|
|
<p>For readers who do not like abstract descriptions, this is a transcript of
|
|
a session (where long lines have been edited to fit):</p>
|
|
|
|
<pre>
|
|
octave:10> il_string = sprintf("%f,", iso_levels)
|
|
il_string = 0.583444,0.592029,0.652120,0.815224,1.132847,1.656497, \
|
|
2.437679,3.527900,4.978667,6.841486,9.167864,12.009307,
|
|
octave:11> il_string = il_string(1 : length(il_string)-1)
|
|
il_string = 0.583444,0.592029,0.652120,0.815224,1.132847,1.656497, \
|
|
2.437679,3.527900,4.978667,6.841486,9.167864,12.009307
|
|
octave:12> gset_string = sprintf("gset cntrparam levels discrete %s", \
|
|
il_string)
|
|
gset_string = gset cntrparam levels discrete 0.583444,0.592029, \
|
|
0.652120,0.815224,1.132847,1.656497,2.437679,3.527900, \
|
|
4.978667,6.841486,9.167864,12.009307
|
|
</pre>
|
|
|
|
<p>In the script, no temporary variable <em>gset_string</em> has been
|
|
introduced, but <em>sprintf()</em> sends its output directly to <em>
|
|
eval()</em>.</p>
|
|
|
|
<p>Block [6]: Gnuplot does not excel in plotting contours. In fact the
|
|
GNuplot user-manual suggests not to use it directly. Anyhow, we proceed,
|
|
because the out approach is easier to understand. The following three <code>
|
|
gset</code>s switch Gnuplot into contour-mode:</p>
|
|
|
|
<pre>
|
|
gset contour base # draw contours in the xy-plane
|
|
gset nosurface # do not draw the surface's mesh
|
|
gset view 0, 0 # view the xy-plane from above
|
|
</pre>
|
|
|
|
<p>Blocks [7] and [8] closely resemble those we have already seen in
|
|
Section <a href="#octave: 2d discrete data plot">``Octave: 2D Discrete Data
|
|
Plot''</a> and <a href="#octave: 3d function plot">``Octave: 3D Function
|
|
Plot''</a>.</p>
|
|
|
|
<p>More demo plots of Gnuplot can be found at <a href=
|
|
"http://www.gnuplot.org/gnuplot/gpdocs/all2.htm">
|
|
http://www.gnuplot.org/gnuplot/gpdocs/all2.htm</a></p>
|
|
|
|
<h2><a name="scilab">Scilab</a></h2>
|
|
|
|
<p>And now for a rather different approach ...</p>
|
|
|
|
<p>Scilab goes a different way to cope with the complexity, which we have
|
|
discussed in Section <a href="#complexity at large">Complexity at Large</a>.
|
|
In contrary to Gnuplot, Scilab does not strictly separate plotting and
|
|
setting, but offers a plethora (buckle up, then try: <code>apropos
|
|
plot</code>) of different plot commands to produce different kinds of plots.
|
|
Furthermore, the plot functions themselves take many arguments that change the
|
|
plots' appearances. Some of the arguments are so cryptic that you almost
|
|
certainly will want to have the appropriate man-page within sight.</p>
|
|
|
|
<p>For the reader who wants to look at the on-line help, but does not have
|
|
Scilab installed, the <a href=
|
|
"http://www.num.uni-sb.de/~ehrhardt/Ue_PraMa/scilab/doc/html/manual/docu023.html">
|
|
Scilab manual</a> is available online.</p>
|
|
|
|
<h3><a name="scilab: 2d discrete data plot">Scilab: 2D Discrete Data
|
|
Plot</a></h3>
|
|
|
|
<pre>
|
|
// [1] Read data set_i into N_i-times-2 matrices
|
|
set1 = read("l1.ascii", -1, 2);
|
|
set2 = read("l2.ascii", -1, 2);
|
|
set3 = read("l3.ascii", -1, 2);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [2] Clear plot window's contents
|
|
xbasc();
|
|
</pre>
|
|
|
|
<pre>
|
|
// [3] Plot data; 1st plot command defines plot area
|
|
plot2d(set1(:, 1), set1(:, 2), -1, "011", ..
|
|
rect = [0, 8e-8, 100, 2e-6]);
|
|
plot2d(set2(:, 1), set2(:, 2), -2, "000");
|
|
plot2d(set3(:, 1), set3(:, 2), -3, "000");
|
|
</pre>
|
|
|
|
<pre>
|
|
// [4] Define decorations
|
|
xtitle(["Comparison of sets", "L1, L2, and L3"], ..
|
|
"Temperature / K", "Voltage / V");
|
|
legends(["Set L1 ", "Set L2 ", "Set L3 "], [-1, -2, -3], 2);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [5] Save plot window's contents to file; convert file to PostScript
|
|
xbasimp(0, "sci1.xps");
|
|
unix("scilab -save_p sci1.xps.0 Postscript");
|
|
</pre>
|
|
|
|
<p><img height="447" alt=
|
|
"[Graphics: Please see the image caption of '2D Discrete Data Plot' in the Octave section.]"
|
|
src="misc/spiel/sci1.png" width="600"> The <a href="misc/spiel/sci1.eps">
|
|
Encapsulated Postscript output</a> is available, too.</p>
|
|
|
|
<p>Block [1] reads the data from disk-files into matrices.</p>
|
|
|
|
<p>Block [2] clears the graphics window (if it exists). Even more
|
|
important, <em>xbasc()</em> deletes all graphics commands that have been
|
|
recorded for the window. The mnemonic for <em>xbasc()</em> is x-bas-c for
|
|
<strong>x</strong>11-function, <strong>bas</strong>ic level, <strong>
|
|
c</strong>lear.</p>
|
|
|
|
<p>Tip: When playing with Scilab's plot functions, preceding the plot function
|
|
call with a clear command often saves keystrokes</p>
|
|
|
|
<pre>
|
|
xbasc(); plot2d(...);
|
|
</pre>
|
|
|
|
<p>in one line can be recalled for editing with a single C-p and replayed with
|
|
a single hit of the return-key.</p>
|
|
|
|
<p>In Block [3] the enigma raises its head! What in the world does</p>
|
|
|
|
<pre>
|
|
plot2d(set1(:, 1), // vector of x-values
|
|
set1(:, 2), // vector of y-values
|
|
-1, // style index
|
|
"011", // decoration control
|
|
rect = [0, 8e-8, 100, 2e-6]); // plot dimensions
|
|
</pre>
|
|
|
|
<p>do? I have added a comment for each argument, yet, to what does a ``style
|
|
index'' of -1 refer to? A badly dressed hacker? And what does the string in
|
|
``decoration control'' mean?</p>
|
|
|
|
<dl>
|
|
<dt><strong><a name="item_Style_index">Style index</a></strong><br>
|
|
</dt>
|
|
|
|
<dd>controls the kind of marker to draw for each data point or the color of
|
|
the line that joins the data points. A positive value <em>i</em> means:
|
|
draw a line with color <em>i</em>, a negative value means: use marker
|
|
type <em>abs(i)</em>. Note that <em>plot2d()</em> draws either markers or
|
|
lines, never both. If markers and lines are required for the same data set,
|
|
two plots with different style indices are necessary.</dd>
|
|
|
|
<dt><strong><a name="item_Decoration_control">Decoration
|
|
control</a></strong><br>
|
|
</dt>
|
|
|
|
<dd>always is a string of length 3. Each character of the string controls
|
|
a certain aspect of the plot's decorations.
|
|
|
|
<dl>
|
|
<dt><strong><a name="item_Character_1">Character 1</a></strong><br>
|
|
</dt>
|
|
|
|
<dd>Toggle display of the plot caption. '<code>0</code>' is no caption,
|
|
'<code>1</code>' tells Scilab to display a caption.</dd>
|
|
|
|
<dt><strong><a name="item_Character_2">Character 2</a></strong><br>
|
|
</dt>
|
|
|
|
<dd>Control how the size of the plot is computed. Valid characters range from
|
|
'<code>0</code>' to '<code>8</code>'. Please see <em>plot2d()</em>
|
|
documentation for details.
|
|
|
|
<p>Here, we use '<code>1</code>' for the first plot and '<code>0</code>' for
|
|
all others. '<code>1</code>' lets the user explicitely specify the plot range
|
|
in the <code>rect</code> argument to <em>plot2d()</em>. If <em>
|
|
plot2d()</em> is called with '<code>0</code>', the size of a previous plot is
|
|
used and no size computation is done.</p>
|
|
</dd>
|
|
|
|
<dt><strong><a name="item_Character_3">Character 3</a></strong><br>
|
|
</dt>
|
|
|
|
<dd>Set the type of axes drawn around the plot. The user can choose from six
|
|
different values. We choose '<code>1</code>' for the first plot, which gives
|
|
axes on the bottom and the left hand side. The following plots use
|
|
'<code>0</code>', which means nothing is drawn around the plot.</dd>
|
|
</dl>
|
|
</dd>
|
|
</dl>
|
|
|
|
<p>Gee, that is quite a mouthful! Block [4] will give us some rest.</p>
|
|
|
|
<pre>
|
|
xtitle([title_line1; title_line2; ...], x_label, y_label)
|
|
</pre>
|
|
|
|
<p>Puts a possibly multi-line title into an existing plot and optionally
|
|
decorates the <em>x</em> and <em>y</em>-axis with labels.</p>
|
|
|
|
<pre>
|
|
legends([legend_1, legend_2, ...], [style_1, style_2, ...], position)
|
|
</pre>
|
|
|
|
<p>Places a legend in a plot where the position is given by <em>position</em>.
|
|
<em>position = 1</em> refers to the north east corner. The remaining corners
|
|
are enumerated counter-clockwise, this is, <em>position = 2</em> will put the
|
|
legend in the north west corner. The <em>style_i</em> parameters refer to the
|
|
same numbers that we have used as style indices in the <em>plot2d()</em>
|
|
calls. They determine which kind of marker or line is drawn right next to the
|
|
legend's text. The text is given by <em>legend_i</em>.</p>
|
|
|
|
<p>Finally, Block [5] converts the data in the graphics window to a
|
|
Postscript file.</p>
|
|
|
|
<pre>
|
|
xbasimp(0, "sci1.xps")
|
|
</pre>
|
|
|
|
<p>Replays all graphics commands for window 0 (our only graphics window)
|
|
into <em>sci1.xps</em>. The function's name has nothing to do with a
|
|
X11-daemon named ``bas'', but has its stem from <strong>x</strong>11 and
|
|
<strong>bas</strong>ic level as <em>xbasc()</em>. The ``<strong>imp</strong>''
|
|
comes from the French word ``imprimer'', which means ``to print''. From which
|
|
language does ``fsck'' come from? N vcls, I guess.</p>
|
|
|
|
<p>File <em>sci1.xps</em> almost contains valid Postscript, but not
|
|
quite. The contents must be processed by Scilab</p>
|
|
|
|
<pre>
|
|
scilab -save_p sci1.xps.0 Postscript
|
|
</pre>
|
|
|
|
<p>adding the correct Postscript header and repositioning the graphics on the
|
|
page. The external Scilab is called by the <em>
|
|
unix(``shell-commands'')</em> function.</p>
|
|
|
|
<h3><a name="scilab: 3d function plot">Scilab: 3D Function Plot</a></h3>
|
|
|
|
<pre>
|
|
// [1] Define function
|
|
function z = f(u, v)
|
|
// truncated Rosenbrock function
|
|
z = 100.0*(v - u.^2).^2 + (1.0 - u).^2
|
|
z(find(z > 100)) = 100;
|
|
endfunction
|
|
</pre>
|
|
|
|
<pre>
|
|
// [2] Define sampling grid for f()
|
|
x = linspace(-3, 3, 40);
|
|
y = linspace(-2, 4, 40);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [3] Clear plot window's contents
|
|
xbasc();
|
|
</pre>
|
|
|
|
<pre>
|
|
// [4] Plot
|
|
fplot3d(x, y, f, 65, 1.5);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [5] Define decoration
|
|
xtitle("Rosenbrock Function", "u", "v");
|
|
</pre>
|
|
|
|
<pre>
|
|
// [6] Save plot window's contents to file; convert file to PostScript
|
|
xbasimp(0, "sci2.xps");
|
|
unix("scilab -save_p sci2.xps.0 Postscript; " ..
|
|
+ "gzip --best --force sci2.eps");
|
|
</pre>
|
|
|
|
<p><img height="447" alt=
|
|
"[Graphics: Please see the image caption of '3D Function Plot' in the Octave section.]"
|
|
src="misc/spiel/sci2.png" width="600"> Here is the gzipped <a href=
|
|
"misc/spiel/sci2.eps.gz">Encapsulated Postscript version</a> (eps.gz) of the
|
|
graphics.</p>
|
|
|
|
<p>After so much new stuff in Section <a href="#scilab: 2d discrete data
|
|
plot">Scilab: 2D Discrete Data Plot</a> the only unknown here hides in
|
|
Block [4]:</p>
|
|
|
|
<pre>
|
|
fplot3d(x_vector, y_vector, function_of_x_and_y, alpha, theta)
|
|
</pre>
|
|
|
|
<p>The vectors <em>x_vector</em> and <em>y_vector</em> define the grid on
|
|
which <em>function_of_x_and_y</em> is evaluated. Comparing <em>fplot3d()</em>
|
|
with Octave's <em>gsplot</em> we notice, that Scilab generates the grid for
|
|
us. Function <em>fplot3d()</em> is a convenience function, built on top
|
|
of</p>
|
|
|
|
<pre>
|
|
plot3d(x_vector, y_vector, z_matrix, alpha, theta)
|
|
</pre>
|
|
|
|
<p>which resembles <em>gsplot</em> (and Tela's <em>mesh()</em>).</p>
|
|
|
|
<p>The parameters <em>theta</em> and <em>alpha</em>, define the elevation of
|
|
the view point and the rotation around the <em>z</em>-axis respectively.</p>
|
|
|
|
<h3><a name="scilab: contour function plot">Scilab: Contour Function
|
|
Plot</a></h3>
|
|
|
|
<pre>
|
|
// [1] Define function
|
|
function z = g(u, v)
|
|
z = exp(u) .* (4.0*u.^2 + 2.0*v.^2 + 4.0*u.*v + 2.0*v + 1.0)
|
|
endfunction
|
|
</pre>
|
|
|
|
<pre>
|
|
// [2] Define weight function for iso-line distances
|
|
function y = pow_weight(x, n)
|
|
// Map interval X onto itself, weight with N-th power.
|
|
d = max(x) - min(x)
|
|
y = d*((x - min(x))/d).^n + min(x)
|
|
endfunction
|
|
</pre>
|
|
|
|
<pre>
|
|
// [3] Define sampling grid for g()
|
|
x = linspace(-4.5, -0.5, 40);
|
|
y = linspace(-1.0, 3.0, 40);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [4] Evaluate g() at points defined by X and Y
|
|
z = eval3d(g, x, y);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [5] Compute iso-line distances
|
|
iso_levels = pow_weight(linspace(min(z)*1.01, max(z)*0.99, 12), 3.0);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [6] Clear plot window's contents
|
|
xbasc();
|
|
</pre>
|
|
|
|
<pre>
|
|
// [7] Set format of iso-line annotation and plot
|
|
xset("fpf", "%.2f");
|
|
contour2d(x, y, z, iso_levels);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [8] Define decoration
|
|
xtitle("Contour Plot of g(u, v)", "u", "v");
|
|
</pre>
|
|
|
|
<pre>
|
|
// [9] Save plot window's contents to file; convert file to PostScript
|
|
xbasimp(0, "sci3.xps");
|
|
unix("scilab -save_p sci3.xps.0 Postscript");
|
|
</pre>
|
|
|
|
<p><img height="447" alt=
|
|
"[Graphics: Please see the image caption of 'Contour Function Plot' in the Octave section for the image's description.]"
|
|
src="misc/spiel/sci3.png" width="600"> The output is available as <a href=
|
|
"misc/spiel/sci3.eps">printer-ready version</a> (eps), too.</p>
|
|
|
|
<p>Remember the difficulties we had with the user-defined iso-lines in
|
|
Octave/Gnuplot? The problem can be solved in Scilab without any tricks, magic,
|
|
or bribery. As with <em>plot3d()</em>, Scilab defines a convenience
|
|
function</p>
|
|
|
|
<pre>
|
|
fcontour2d(x_vector, y_vector, function_of_x_and_y, levels)
|
|
</pre>
|
|
|
|
<p>as a wrapper around</p>
|
|
|
|
<pre>
|
|
contour2d(x_vector, y_vector, z_matrix, levels)
|
|
</pre>
|
|
|
|
<p>However, as we must know the maximum and minimum value of <em>g(u, v)</em>
|
|
on the grid, <em>fcontour2d()</em> would not save us anything. Thus, Block [4]
|
|
computes <em>g(u, v)</em> on the grid defined by <em>x</em> and <em>
|
|
y</em>:</p>
|
|
|
|
<pre>
|
|
z = eval3d(g, x, y)
|
|
</pre>
|
|
|
|
<p>In Block [7], we use <em>z</em> and <em>iso_levels</em> from
|
|
Block [5]. The <em>xset()</em> call sets the <strong>f</strong>loating
|
|
<strong>p</strong>oint <strong>f</strong>ormat (``fpf'') to
|
|
``<code>%.2f</code>'', which is a C-printf format specifier that forces all
|
|
contour line numbers to have two digits after the decimal point.</p>
|
|
|
|
<p>All other blocks only use functions already discussed in the other
|
|
plots.</p>
|
|
|
|
<p>More demo plots of Scilab are found at <a href=
|
|
"http://www-rocq.inria.fr/scilab/doc/demos_html/node183.html">INRIA's Scilab
|
|
site</a>.</p>
|
|
|
|
<p>Scilab has much more to offer than the functions we have seen right above.
|
|
For example, it supplies</p>
|
|
|
|
<ul>
|
|
<li>Low-level functions to draw points, lines, polygons, etc.</li>
|
|
|
|
<li>
|
|
<p>Surface facets which are the building blocks for 3d-environments. (See for
|
|
example Enrico Segre's amazing <a href=
|
|
"http://www.polito.it/~segre/scigallery.html">Scigallery</a>)</p>
|
|
</li>
|
|
|
|
<li>High-level GUI-interface for rapid development of tailor-made Scilab
|
|
applications.</li>
|
|
|
|
<li>Feedback functions that allow passing back information from any graphics
|
|
window to Scilab.</li>
|
|
</ul>
|
|
|
|
<h2><a name="tela">Tela</a></h2>
|
|
|
|
<p>In the sections on <a href="#octave">Octave</a> and <a href="#scilab">
|
|
Scilab</a>, we have seen that both applications save auxiliary ``state'' of
|
|
the plot window. Gnuplot does so to the max: <code>gplot</code> or <code>
|
|
gsplot</code> have almost no parameters. The state is controlled by <code>
|
|
gset</code> commands. Scilab stores some state of the plot window as, for
|
|
example, the legend and title.</p>
|
|
|
|
<p>Tela uses the external application PlotMTV to display graphs. With PlotMTV,
|
|
Tela is located on the other side of the spectrum: its plots have no state,
|
|
and all information about the plot has to go into the call to the actual
|
|
plotting function. The advantage of Tela's approach is that multiple plots do
|
|
not interfere (unless we force them to do so by calling <code>hold(on)</code>
|
|
or <code>hold(off)</code> as we will see soon). The downside is that the calls
|
|
to plotting functions can get rather long.</p>
|
|
|
|
<p>As has been in the discussions of the other plotting applications, it is
|
|
helpful to have a PlotMTV manual within reach.</p>
|
|
|
|
<h3><a name="tela: 2d discrete data plot">Tela: 2D Discrete Data Plot</a></h3>
|
|
|
|
<pre>
|
|
// [1] Read data set_i into N_i-times-2 matrices
|
|
set1 = import1("l1.ascii");
|
|
set2 = import1("l2.ascii");
|
|
set3 = import1("l3.ascii");
|
|
</pre>
|
|
|
|
<pre>
|
|
// [2] Define plotting function
|
|
function do_plot(d1, d2, d3)
|
|
{
|
|
hold(on); // postpone actual plotting until hold(off)
|
|
</pre>
|
|
|
|
<pre>
|
|
// render set 1
|
|
plot(d1[:, 1], d1[:, 2],
|
|
"linestyle", 0,
|
|
"markertype", 2,
|
|
"linelabel", "Set L1",
|
|
// Define decorations
|
|
"toplabel", "Comparison of sets",
|
|
"subtitle", "L1, L2, and L3",
|
|
"xlabel", "Temperature / K",
|
|
"ylabel", "Voltage / V",
|
|
// Define plot area
|
|
"xmin", 0,
|
|
"xmax", 100,
|
|
"ymin", 8e-8,
|
|
"ymax", 2e-6);
|
|
// render set 2
|
|
plot(d2[:, 1], d2[:, 2],
|
|
"linestyle", 0,
|
|
"markertype", 3,
|
|
"linelabel", "Set L2");
|
|
// render set 3
|
|
plot(d3[:, 1], d3[:, 2],
|
|
"linestyle", 0,
|
|
"markertype", 4,
|
|
"linelabel", "Set L3");
|
|
</pre>
|
|
|
|
<pre>
|
|
hold(off); // plot!
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [3] Plot to X11 window
|
|
do_plot(set1, set2, set3);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [4] Plot into a postscript file
|
|
plotopt("-o tela1.eps -printcmd 'cat' -noxplot -print");
|
|
do_plot(set1, set2, set3);
|
|
</pre>
|
|
|
|
<p>Hmm, this script looks differently! It does -- because I have to play
|
|
another trick that has to do with the statelessness plot functions. As Tela
|
|
``forgets'' the parameters after displaying graphics in an X11-window, I would
|
|
have to retype everything with output redirected to a Postscript file. Well,
|
|
code duplication is known to be the root of many (not all) evil. Thus, the
|
|
Tela plots are wrapped into a function. The further strategy is displaying the
|
|
plot in an X11 window, changing the output file and type, which is somewhat
|
|
analogous to Gnuplot, and then plotting again into an eps-file:</p>
|
|
|
|
<pre>
|
|
do_plot(...); // display plot in X11 window
|
|
plotopt("-o foo.eps -printcmd 'cat' -noxplot -print"); // redirect output
|
|
do_plot(...); // render plot in Encapsulated Postscript file foo.eps
|
|
</pre>
|
|
|
|
<p><img height="800" alt=
|
|
"[Graphics: Please see the image caption of '2D Discrete Data Plot' in the Octave section.]"
|
|
src="misc/spiel/tela1.png" width="600"> <a href="misc/spiel/tela1.eps">
|
|
Encapsulated Postscript version</a> of the graphics.</p>
|
|
|
|
<p>Function <em>do_plot</em> in Block [2] takes care of all output
|
|
by using function <em>plot()</em>. The general structure of Tela's <em>
|
|
plot()</em>, in fact all Tela plot functions, is first passing the mandatory
|
|
data arguments as vectors or matrices followed by optional key-value
|
|
strings.</p>
|
|
|
|
<pre>
|
|
plot(x_vector, y_vector // data
|
|
"option_key1", "option_value1", // option 1
|
|
"option_key2", "option_value2", // option 2
|
|
...
|
|
"option_keyN", "option_valueN"); // option N
|
|
</pre>
|
|
|
|
<p>Note that putting one key-value pair per line enhances the readability of
|
|
the whole call.</p>
|
|
|
|
<p>The key-value strings themselves are self-explaining. Non-obvious
|
|
associations like linestyle => 0 (= invisible line) or
|
|
markertype => 2 (= plus sign) must be looked up in the manual or
|
|
in a reference plot which shows all available line styles.</p>
|
|
|
|
<h3><a name="tela: 3d function plot">Tela: 3D Function Plot</a></h3>
|
|
|
|
<pre>
|
|
function v = linspace(a, b; n)
|
|
{
|
|
if (isdefined(n)) nn = n else nn = 100;
|
|
v = a + (0 : nn - 1) * (b - a) / (nn - 1)
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [1] Define function
|
|
function z = f(u, v)
|
|
{
|
|
// truncated Rosenbrock function
|
|
z = 100.0*(v - u^2)^2 + (1.0 - u)^2;
|
|
z[find(z > 100.0)] = 100.0;
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [2] Sample function f()
|
|
x = linspace(-3.0, 3.0, 40);
|
|
y = linspace(-2.0, 4.0, 40);
|
|
[xx, yy] = grid(x, y);
|
|
zz = f(xx, yy);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [3] Define plot function
|
|
function do_plot(x, y, zz)
|
|
{
|
|
mesh(zz,
|
|
"xgrid", x,
|
|
"ygrid", y,
|
|
"toplabel", "Rosenbrock Function",
|
|
"xlabel", "u",
|
|
"ylabel", "v",
|
|
"hiddenline", "true",
|
|
"eyepos.z", 2.0)
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [4] Render plot into X11 window
|
|
do_plot(x, y, zz);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [5] Plot into a postscript file
|
|
plotopt("-o tela2.eps -printcmd 'cat' -noxplot -print");
|
|
do_plot(x, y, zz);
|
|
system("gzip --best --force tela2.eps");
|
|
</pre>
|
|
|
|
<p><img height="800" alt=
|
|
"[Graphics: Please see the image caption of '3D Function Plot' in the Octave section.]"
|
|
src="misc/spiel/tela2.png" width="600"> An gzipped <a href=
|
|
"misc/spiel/tela2.eps.gz">Encapsulated Postscript version</a> (eps.gz) of the
|
|
plot is available, too.</p>
|
|
|
|
<p>Tela has no built in <em>linspace()</em> function, so I quickly define
|
|
one.</p>
|
|
|
|
<p>Block [2] resembles Block [2] in Section <a href="#octave: 3d
|
|
function plot">``Octave: 3D Function Plot''</a>, where Octave's <em>
|
|
meshgrid()</em> has been replaced by Tela's <em>grid()</em>.</p>
|
|
|
|
<p>The 3d-mesh plotting function <em>mesh()</em> takes a matrix of <em>
|
|
z</em>-values as its first argument; the grid-specification is given in the
|
|
options:</p>
|
|
|
|
<pre>
|
|
mesh(z_matrix,
|
|
"xgrid", x_vector,
|
|
"ygrid", y_vector);
|
|
</pre>
|
|
|
|
<p>Of course, the sizes of <em>z_matrix</em>, <em>x_vector</em>, and <em>
|
|
y_vector</em> must be compatible.</p>
|
|
|
|
<h3><a name="tela: contour function plot">Tela: Contour Function Plot</a></h3>
|
|
|
|
<pre>
|
|
function v = linspace(a, b; n)
|
|
{
|
|
if (isdefined(n)) nn = n else nn = 100;
|
|
v = a + (0 : nn - 1) * (b - a) / (nn - 1)
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [1] Define function
|
|
function z = g(u, v)
|
|
{
|
|
z = exp(u) * (4.0*u^2 + 2.0*v^2 + 4.0*u*v + 2.0*v + 1.0)
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [2] Define weight function for iso-line distances
|
|
function y = pow_weight(x, n)
|
|
{
|
|
// Map interval X onto itself, weight with N-th power.
|
|
d = max(x) - min(x);
|
|
y = d*((x - min(x))/d)^n + min(x)
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [3] Sample function f()
|
|
x = linspace(-4.5, -0.5, 40);
|
|
y = linspace(-1.0, 3.0, 40);
|
|
[xx, yy] = grid(x, y);
|
|
zz = g(xx, yy);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [4] Compute iso-line distances
|
|
iso_levels = pow_weight(linspace(min(zz)*1.01, max(zz)*0.99, 12), 3.0);
|
|
il_str = sformat("``", iso_levels);
|
|
il_str = il_str[2 : length(il_str)];
|
|
</pre>
|
|
|
|
<pre>
|
|
// [5] Define plot function
|
|
function do_plot(x, y, zz, iso_levels_str)
|
|
{
|
|
contour(zz,
|
|
"xgrid", x,
|
|
"ygrid", y,
|
|
"toplabel", "Contour Plot of g(u, v)",
|
|
"xlabel", "u",
|
|
"ylabel", "v",
|
|
"contours", iso_levels_str)
|
|
};
|
|
</pre>
|
|
|
|
<pre>
|
|
// [6] Render plot into X11 window
|
|
do_plot(x, y, zz, il_str);
|
|
</pre>
|
|
|
|
<pre>
|
|
// [7] Plot into a postscript file
|
|
plotopt("-o tela3.eps -printcmd 'cat' -noxplot -print");
|
|
do_plot(x, y, zz, il_str);
|
|
</pre>
|
|
|
|
<p><img height="800" alt=
|
|
"[Graphics: Please see the image caption of 'Contour Function Plot' in the Octave section for the image's description.]"
|
|
src="misc/spiel/tela3.png" width="600"> Also available is an Encapsulated
|
|
Postscript <a href="misc/spiel/tela3.eps">printer version</a>.</p>
|
|
|
|
<p>Tela requires us to play a similar trick on PlotMTV as we had to when
|
|
convincing Octave to pass the contours' values to Gnuplot. However, the trick
|
|
in Block [4] is not as involved. Again, the first step is to compute the
|
|
vector <em>iso_levels</em>. Function <em>sformat()</em> works
|
|
analogously to Octave's <em>sprintf()</em>, though the vectors are differently
|
|
formatted as the transcript shows (<em>il_str</em> has been edited to fit the
|
|
line).</p>
|
|
|
|
<pre>
|
|
>il_str = sformat("``", iso_levels);
|
|
>il_str
|
|
"#(0.583444, 0.592029, 0.65212, 0.815224, 1.13285, 1.6565, \
|
|
2.43768, 3.5279, 4.97867, 6.84149, 9.16786, 12.0093)"
|
|
</pre>
|
|
|
|
<p>PlotMTV does understand a vector that is enclosed in parenthesis, but the
|
|
leading sharp-sign must go</p>
|
|
|
|
<pre>
|
|
il_str = il_str[2 : length(il_str)];
|
|
</pre>
|
|
|
|
<p>In this form, <em>il_string</em> can be passed as value to the option key
|
|
<code>contours</code> in function <em>contour()</em>.</p>
|
|
|
|
<p>More demo plots of PlotMTV can be found at <a href=
|
|
"http://csep1.phy.ornl.gov/cornell_proceedings/tutorials/Plotmtv/overview.html">
|
|
ORNL</a> and at <a href=
|
|
"http://www.hammersmith-consulting.com/plotmtv-us-g.html">HSC</a>.</p>
|
|
|
|
<p>By the way, PlotMTV suits perfectly as graphical backend for home grown
|
|
scripts and programs. The PlotMTV manual consistently helps the reader to
|
|
develop programmatic interfaces for her own applications.</p>
|
|
|
|
<h2><a name="closing comments on graphics">Closing Comments on
|
|
Graphics</a></h2>
|
|
|
|
<p>We have seen how to get publication ready data and function plots from
|
|
GNU/Octave, Scilab, and Tela. Sometimes the solutions have been intricate,
|
|
because of implementations' restrictions. However, all <a href="#problems">
|
|
problems</a> could be solved.</p>
|
|
|
|
<p>The effort in creating pleasantly looking graphs appears to be high and
|
|
almost independent of the chosen application.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- *** BEGIN bio *** -->
|
|
<SPACER TYPE="vertical" SIZE="30">
|
|
<P>
|
|
<H4><IMG ALIGN=BOTTOM ALT="" SRC="../gx/note.gif">Christoph Spiel</H4>
|
|
Chris runs an Open Source Software consulting company in Upper Bavaria/Germany.
|
|
<EM>Despite being trained as a physicist -- he holds a PhD in physics from Munich
|
|
University of Technology -- his main interests revolve around numerics,
|
|
heterogenous programming environments, and software engineering. He can be
|
|
reached at
|
|
<A HREF="mailto:cspiel@hammersmith-consulting.com">cspiel@hammersmith-consulting.com</A>.</EM>
|
|
|
|
<!-- *** END bio *** -->
|
|
|
|
<!-- *** BEGIN copyright *** -->
|
|
<P> <hr> <!-- P -->
|
|
<H5 ALIGN=center>
|
|
|
|
Copyright © 2001, Christoph Spiel.<BR>
|
|
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
|
|
Published in Issue 71 of <i>Linux Gazette</i>, October 2001</H5>
|
|
<!-- *** END copyright *** -->
|
|
|
|
<!--startcut ==========================================================-->
|
|
<HR><P>
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="qubism.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue71/spiel.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="lg_backpage71.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</BODY></HTML>
|
|
<!--endcut ============================================================-->
|