BA 371 - VB.Net & gnuplot
In this lab we'll explore communicating data between our application
program and a third party program's API. We have already done some of
this when our program interacted with a database management
system. However, programmatic interaction with most third party
programs is not quite as 'nice.'
For this lab, we'll be 'talking' to a plotting package. gnuplot
is an open source, generic utility for plotting data. The plotter has
several
output formats among which are the screen (kind of handy), png, jpeg,
etc. (gif is no longer
supported because of patent issues).
For those of you who are thinking about writing your own plotting
software,
beware; it's hard work and the devil is in the details. Getting a basic
line graph
or bar graph up is not hard, but getting it lined up properly and
managing
the tick marks, the labels, the legends etc., is not at all trivial.
Tools such as gnuplot are nice because they work well and can be
interfaced
with your own, custom-written software. Although gnuplot was originally
written
for Unix and hence, runs well on Linux, it was recently ported to
Windows.
The port, however, was just that; it was a port, not a rewrite. Hence
it's
a little rough on the Windows side... good enough for our purposes,
though.
Gnuplot is an interactive, command-driven program. It
takes its input (the commands), however, in several ways. For instance,
we can feed it a file
with commands--a so-called 'script'--or we can talk to it using its
command line interpreter.
We
can also freely switch from one to the other; i.e., first feed it a file with
commands and then fine tune or add to the plot with further commands
given on its command
line.
Architecture
We want to use gnuplot as a back-end plotter of our BA372 project
software
written
in VB.Net; e.g., we
could use our VB.Net software to let users specify
what sort of plot they want and for retrieving the associated data from
the
database. VB.Net will then prepare two files with gnuplot data:
- The gnuplot control file: an ASCII (text) file with
gnuplot commands.
- The gnuplot data file: an ASCII (text) file containing
the data to be plotted.
The control file
contains the commands for gnuplot on how to plot; e.g.,
plot a line graph with time on the x-axis, color schemes, etc., as well as the plot
command itself.
The data file
contains the data to be plotted.
Below are two links pointing to examples of a gnuplot control file and
the
associated data file. The statements starting with a '#' in the control
file
indicate comments and contain explanations of how to write the files.
Note that the files contain data collected from a set of five
temperature
sensors built into one of the walls of a building. The data form five
time
series in that data are taken from each of the five sensors every five
minutes for a period of five hours.
gnuplot control file.txt
gnuplot data file.txt
Important: both the control
file and the data can be written by a program
such as one written in VB.Net. This then suggests the following general
method
for
using gnuplot from inside a VB.Net program:
- Let the VB.Net program collect the information on the data that
should be plotted; perhaps by doing queries to a database.
- In your program, connect to a database and retrieve the data
needed for the plot.
- Let your program write both the gnuplot control file and the
gnuplot data file.
- Let (as in the example above) the control file point gnuplot to
the
data file.
- Let your program 'call' the operating system asking it to start a
gnuplot session and hand it over the control file.
Step 4. is demonstrated with the following VB.Net code (run this as a
console app):
CAREFUL!!! Since your instructor has no control over where you
store the gnuplot control and data file on your system, you must make
SURE(!!!!) that the references to those files --both in your program
and in the gnuplot control file-- are correct. If you point gnuplot to
the wrong file or somewhere into oblivion, it will not work correctly.
Public Class Gnuplot
Shared Sub Main()
Dim control_file As String = "C:\temp\gnuplot_controlfile.txt"
do_the_plot(control_file)
End Sub
Shared Sub do_the_plot(ByRef control_file As String)
Dim winroot As String
Dim strCmdLine As String
Dim strCmdParam As String
winroot = System.Environment.GetEnvironmentVariable("SystemRoot")
strCmdLine = winroot + "\system32\cmd"
strCmdParam = "/C C:\""Program Files""\gnuplot\bin\pgnuplot /noend " + control_file
Try
System.Diagnostics.Process.Start(strCmdLine, strCmdParam)
Catch E As Exception
Console.WriteLine(E.Message)
End Try
End Sub
End Class
Notice how you can invoke gnuplot by means of a simple call to the do_the_plot()
subroutine. Simply pass it the name of the control file and you're in
business.
This is very 'dense' code. It does a lot in just a few lines; so
here's abit of explanation of the do_the_plot()code:
- The string winroot
is set to the root of your operating system using the system's
environment variable SystemRoot
(you do not have to set this variable; it's part of your OS).
- Next, we build the OS command to start a (DOS/Windows)
command-line interpreter
(winroot + "\system32\cmd").
- Next, we set the string strCmdParam to the
actual command we want to hand over to the (DOS/Windows) command
interpreter (the /C
option says that a
command will follow). Notice how we specify a command to start gnuplot,
handing it over the gnuplot_controlfile.
Notice how since the file path contains a space in "Program Files"
(a
very nasty habit that should be discouraged!), we must include the
folder name in double
quotation marks.
- Finally, we call the OS (System.Diagnostics.Process.Start)
asking it to start the (DOS/Windows) command line interpreter (strCmdLine) passing it
the actual command (strCmdParam).
In summary, from out of VB.Net, we build a command to be executed
by
the OS command-line
interpreter, then call the OS to start the command-line interpreter,
handing
it over the command to run inside the command-line interpreter... Makes
sense?
Note also that the filenames in the code above are hardwired and that
you most likely want to create
them on the fly, passing them around as strings. Note also that the gnuplot_datafile
referenced in the gnuplot_controlfile
must exist(!) and must be referenced with a full path so that gnuplot
can
actually find it (this might be a bit of a puzzle if you're not used to
addressing
files using the operating system.)
Compile and run this code. Note: if, when you run this, you get a lot
of unexpected exceptions thrown at you, do a 'save all...' first.
Also, in the actual plot, note the gap in the curve for variable
'third.' Compare this with the NaN (Not a
Number) entries in the data file.
Note that when gnuplot starts, it also starts a gnuplot interpreter
window.
Although in our case we'll very likely not make much use of this,
you can use the menus in this window to fine tune the graph. You can
also
issue additional gnuplot commands through the interpreter.
Note that when we invoke gnuplot through a console application, gnuplot
gets started from a (DOS/Windows) command shell that stays on the
screen until
we quit
gnuplot. However, if you instead use the techniques learned in the
lesson
on VB.Net
Visual Programming and launch the application from a Windows
application,
the command-line window does not show.
To practice this, try writing a
tiny Windows application with a form
containing but a single button. Define an event handler for
this
button and let the event handler call the do_the_plot() subroutine.
Next, try and see if you can make your program not only call the do_the_plot()subroutine,
but also make it write the gnuplot control and datafile; e.g.,
make the program write a datafile with a 100 random numbers, the
numbers 1-100, or any other series of numbers. Hint: to make a bare
bones plot, all the gnuplot datafile must contain is a bunch of
numbers, one per line, and all the gnuplot control file must contain is
the plot your_datafile
command. Give it a shot!
To top it all of, make an access database with a few numbers in a
column and write a program that connects to the database, does a query
to get the numbers out, writes them to the gnuplot datafile, then
writes the gnuplot control file and finally calls the do_the_plot()
subroutine.
Want to see another cool little thing? Ignore the gnuplot datafile
altogether and plot a mathematical function directly from the control
file. All the control file needs to contain is one of the following
strings: plot(sin(x))
or plot(tan(x), or
plot 1. Experiment
a little; see what happens.
Make sure that you also explore starting gnuplot all by itself
rather than from your VB.Net program. Notice
how
you can type in commands such as plot(sin(x)) in
its command window.
Finally, gnuplot is a powerful(!!)
plotting package that can handle pretty much any sort of
plot you can think of. To acquaint yourself with it, refer to the
on-line gnuplot
manual