Oregon State University
Oregon State University Home Page

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:
  1. The gnuplot control file: an ASCII (text) file with gnuplot commands.
  2. 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:
  1. Let the VB.Net program collect the information on the data that should be plotted; perhaps by doing queries to a database.
  2. Let your program write both the gnuplot control file and the gnuplot data file.
  3. Let (as in the example above) the control file point gnuplot to the data file.
  4. 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:

  1. 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).
  2. Next, we build the OS command to start a (DOS/Windows) command-line interpreter (winroot + "\system32\cmd").
  3. 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.
  4. 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).
  5. 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