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.,
line graph, 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, the files contain data collected from a set of temperature
sensors built into one of the walls of a building. The data form a time
series in that data are taken from the sensor every five minutes.
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.
- 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 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.
Study the above code carefully so you understand what's going on.
This code is a bit tricky but it nicely shows how, from inside a
program, one can
request
the operating system to execute OS commands; a very common practice in
system
engineering.
Some 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
with but a single button called 'Plot.' Define an event handler for
this
button and let the event handler call the do_the_plot() subroutine.
Make sure that you also explore starting gnuplot all by itself;
either from the command line or through the Windows Explorer. Notice
how
you can type in commands such as plot(sin(x))
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