Using LiveGraph in your own applications

In this section of this section we describe the general architecture of the LiveGraph system and provide an overview of the modules you will be in touch with when using LiveGraph in your own software. We include a Java example on how to start using the LiveGraph API instantly.

This manual refers to LiveGraph version 1.1.X.
While version 2.0.X is similar in general, there are several key improvements.
We are working on the manual for version 2.0.X and will make it available as soon as possible. Meanwhile, you can explore the source annotated JavaDoc reference (also work in progress).

On this page:

LiveGraph architecture

The LiveGraph system consists of two active parts and a communication channel between the two modules.

The most visible part is the LiveGraph plotter application. This is a Java application with a rich GUI. It is capable of plotting graphs based on data contained in a data stream in real-time. The distinctive features of the plotter that separate it from other plotting software are described in the motivation section. The user manual provides online help for using the plotter.

At this point it is important to note that the LiveGraph plotter is a stand-alone Java application (requires Java 6 or later; some features run with Java 5).

LiveGraph architecture (click to enlarge)
Fig. 1: LiveGraph architecture
Click image to enlarge.

A second crucial part of LiveGraph is the data writer API. This Java package provides tools for writing data to a stream that can be read by the plotter. The interface provided by the data writer API is easy and straight forward. It handles all low level operations transparently and does not require the developer to worry about any of the details of the data stream format.

As a communication channel between the writer API and the plotter application LiveGraph uses a data file. The data file is an extended CSV text file. A data writer keeps a file output stream open and writes new data to the file whenever the application passes a dataset to it. At the same time the plotter application keeps a file input stream open on the same file. Every second or so (the interval length is configurable) the plotter examines the file and checks whether it was modified since the last check. If the data file was modified, the plotter reads the data added since the last update and updates the graph on the screen.

ToC

Data Writer API

If you are not using Java you will have to take care of creating the data files yourself. This should be very straight forward, as the data file format is very simple. Please refer to the data file format definition for details.

If you are using Java you can make use of the LiveGraph data writer API. This simple API handles all data file matters for your application.

The API is distributed in Java packages org.LiveGraph.dataFile.common and org.LiveGraph.dataFile.write; it also includes the package org.LiveGraph.demoDataSource which contains examples. The package org.LiveGraph.dataFile.common includes helper classes; the package org.LiveGraph.dataFile.write includes the main writer API. When you are interested in a detailed description of the API, please refer to the appropriate Javadoc reference page. At this stage we want to provide a kick-start example.

DataStreamWriterFactory

The first class you need to know about is org.LiveGraph.dataFile.write.DataStreamWriterFactory. The most interesting methods in this class are the static createDataWriter(…)-methods. They create new writer objects for a unique files located in a specified directory. The file's name is constructed form a specified basis and the current date and time. This makes creating verbose file names and managing data files very easy.

For instance, the statement

  DataStreamWriterFactory.createDataWriter("C:\\TutorialDir",
                                           "TutorialData", "dat");

creates a writer which writes to the file c:\TutorialDir\TutorialData.07.03.13-19.09.21.dat (assuming it was executed at 19:09:21 on the 13.03.2007).

If that file already exists than the names c:\TutorialDir\TutorialData.07.03.13-19.09.21(1).dat, c:\TutorialDir\TutorialData.07.03.13-19.09.21(2).dat and so on will be automatically used instead.

This mechanism allows you to do all you data file management in just one line.

DataStreamWriter

The second class you need to know about is org.LiveGraph.dataFile.write.DataStreamWriter.

DataStreamWriter objects are actually used for writing data to files. DataStreamWriter does not extend java.io.Writer because the structure of the data being written is different and the making use of the methods published by the standard API class would be counter-intuitive; however, DataStreamWriter objects should be used in much the same manner as a normal Writer in an application.

The class provides methods for setting up the data file separator, adding information lines and comments to the data file, defining the number of and the labels for the data series and, eventually, for writing the data.

Before any data is sent to the writer the data series should be set up with a series of calls to addDataSeries(String). Once a dataset is written to the stream, no more data series may be added.

A dataset is written by a series of calls to one of the setDataValue(...) methods. Calls to those methods do not cause any data to be written. Instead, the values are associated with the appropriate data series and cached. In order to actually write the data to the underlying stream the method writeDataSet() must be invoked. It flushes the cache to the data stream and prepares for the processing of the next dataset.

In order to allow for concise code when using this class in applications, no methods of DataStreamWriter throw any I/O exceptions. If an IOException is thrown by the underlying stream, it is immediately caught by the writer itself. In order to allow the application to nevertheless access and control the error handling, the methods hadIOException(), getIOException() and resetIOException() are provided.

ToC

Example for using the LiveGraph Writer API

Here is a short example for using the writer API. This example is also included in most distributions in class  org.LiveGraph.demoDataSource.LiveGraphDemo.

In this example a data file is created in the current working directory. Four data series are added to the data file. Then, the file is filled with data in bursts of 1 to 10 datasets at a time. Between the bursts the execution is paused for 0 to 1000 milliseconds. This way a data generating simulation is emulated. The program stops after 100000 datasets have been written.

Below is the source code of the example (note the applicable licence). You can also download the complete example source code or browse its Javadoc reference.

package org.LiveGraph.demoDataSource;

import org.LiveGraph.dataFile.write.DataStreamWriter;
import org.LiveGraph.dataFile.write.DataStreamWriterFactory;


/**
 * This class is used for generating a demo data file for demonstration and
 * testing purposes.
 * It creates a data file and fills it with data. This happens in bursts
 * of 1 to 10 datasets at a time.
 * Between the bursts the execution is paused for 0 to 10 milliseconds.
 * This way a data generating simulation is emulated.
 * The program stops after 100000 datasets have been written.
 
 * <p><strong>LiveGraph</strong> (http://www.live-graph.org).</p>
 * <p>Copyright (c) 2007 by G. Paperin.</p>
 * <p>File: LiveGraphDemo.java</p>
 * <p><u>Licence</u>: See http://www.live-graph.org/licence.html.</p>
 *
 * @author Greg Paperin
 * @version 1.0.1
 */
public class LiveGraphDemo {

public static final String DEMO_DIR = System.getProperty("user.dir");

public static final int MIN_SLEEP = 0;
public static final int MAX_SLEEP = 1000;
public static final int MIN_BURST = 1;
public static final int MAX_BURST = 10;
public static final int MAX_DATASETS = 100000;

public void exec() {
 
 
// Print a welcome message:
 
System.out.println("Welcome to the LiveLog demo.");
 
 
// Setup a data writer object:
 
DataStreamWriter out = DataStreamWriterFactory.createDataWriter(DEMO_DIR,
                               
"LiveGraphDemo");
 
 
// Set a values separator:
 
out.setSeparator(";");
 
 
// Add a file description line:
 
out.writeFileInfo("LiveGraph demo file.");
 
 
// Set-up the data series:
 
out.addDataSeries("Time");
  out.addDataSeries
("Dataset number");
  out.addDataSeries
("Burst number");
  out.addDataSeries
("Random value");
 
 
// Loop until enough datasets a written:
 
int datasetNumber = 0;
 
int burstNumber = 0;
 
long startMillis = System.currentTimeMillis();
 
while (MAX_DATASETS > datasetNumber) {
 
   
// Status message:
   
System.out.println("Datasets written so far: " + datasetNumber + ". "
            
+ "Now writing burst " + burstNumber + "...");
   
   
// Write a few datasets to the file:
   
int burstSize = (int) (MIN_BURST + (Math.random()
                       
* (double) (MAX_BURST - MIN_BURST)));
   
for (int b = 0; b < burstSize && MAX_DATASETS > datasetNumber; b++) {
     
     
// Set-up the data values:
     
out.setDataValue(System.currentTimeMillis() - startMillis);
      out.setDataValue
(datasetNumber);
      out.setDataValue
(burstNumber);
      out.setDataValue
(Math.random());
     
     
// Write dataset to disk:
     
out.writeDataSet();
     
     
// Check for IOErrors:     
     
if (out.hadIOException()) {
       
out.getIOException().printStackTrace();
        out.resetIOException
();
     
}
     
     
datasetNumber++;
   
}
   
burstNumber++;
   
   
   
// Pause:
   
Thread.yield();
   
long sleep = (long) (MIN_SLEEP + (Math.random()
                         
* (double) (MAX_SLEEP - MIN_SLEEP)));
   
try { Thread.sleep(sleep); } catch (InterruptedException e) {}
   
Thread.yield();
 
}   
 
 
// Finish:
 
out.close();
  System.out.println
("Demo finished. Cheers.");
}

public static void main(String[] unusedArgs) {
  (
new LiveGraphDemo()).exec()
}

}
// public class LiveGraphDemo

Fig. 2: Example for using LiveGraph Writer API.

Many thanks to the Java2Html-tool for the layout.

ToC

Starting the LiveGraph plotter automatically from within your application

Now that you know how to create a data stream which can be use by the LiveGraph plotter to visualise your data you need to integrate the plotter into your software.

This is very easy to do — regardless which programming language you are using. However, since the plotter is a Java application, you will need to have Java 6 or later (Java 5 for a limited feature set) running on the computer which executes your own application.

You can integrate LiveGraph seamlessly into your software in such a way that the user gets the impression that the plotter is a part of your own system. This requires only two simple steps:

  1. You set-up the settings suitable for your needs that will be used by the plotter when it opens, and you store these settings in files.
  2. You start LiveGraph as a separate OS process on your machine and use command line parameters to configure the plotter to use your previously set-up settings when it starts up.

The two steps are described in more detail below:

Setting up your plotter configuration

Normally, when LiveGraph plotter starts up it remembers the settings which applied when it was closed the last time. If it is the first time the plotter is used on a particular machine, a set of default settings applies. However, it is easy to create your own settings for LiveGraph. This way you can achieve that plotter begins visualising your data stream immediately after it starts up - without the user having to first open your data stream manually. You can pre-configure all application settings to match the specifics of your data.

LiveGraph settings are saved in 3 files:

  • Data file settings are saved in a file with the extension .lgdfs.
  • Graph settings are saved in a file with the extension .lggs.
  • Data series settings are saves in a file with the extension .lgdss.

If you are developing your software in Java you should use the LiveGraph library for creating the settings files. Otherwise you can create the files directly. Both methods are described in the following paragraphs.

The easiest way for creating and manipulating LiveGraph settings files is using the LiveGraph Settings API.

The Settings API is contained in the package org.LiveGraph.settings. In order to obtain that package you need to download one of the LiveGraph distributions that include the plotter application.

You only need to use classes DataFileSettings, GraphSettings and DataSeriesSettings in the package org.LiveGraph.settings. They directly correspond to the three groups of settings described above (note that each settings group corresponds to a separate window in the GUI).

Assume that your application will be logging its data to the file "/yourapplication/data.csv", and that you would like to update the graph view every 5 seconds. You can use a series of statements like the following to create an appropriate settings file:

  DataFileSettings dfs = new DataFileSettings();
  dfs.setDataFile("/yourapplication/data.csv");
  dfs.setUpdateFrequency(5000);
  dfs.save("/yourapplication/startup.lgdfs");

Note – the last statement saves your settings to the file /yourapplication/startup.lgdfs.

You can configure all the other settings in a similar manner. For further information on each setting please refer to the user manual. For further information on the Settings API please download or browse the JavaDoc reference.

An alternative possibility is writing the settings files directly. You should use this method if you are using a different programming language than Java.

Settings files are simple XML files. They are in clear text and all identifiers are self explanatory. The reader should be saved from the boring task of reading a definition for the settings file format. Instead we ask to perform the following actions:

  1. Run LiveGraph.
  2. Quit LiveGraph by closing the main window.
  3. Examine the contents of the directory from where you run LiveGraph.

There you will find three files: session.lgdfs, session.lggd and session.lgdss. These are the 3 settings files.

Open those with your favourite text editor and you will immediately agree that reading a detailed description of these files here would be a waste of your time. For a information about the meaning of each settings key refer to the section about the corresponding window in the user manual.

By using the examples in the manner described above you should be able to easily create valid settings files from your application regardless of the programming language you are using, provided you have access to the local hard drive.

Starting the LiveGraph plotter from within your own application

When you are running Java you can start LiveGraph directly – i.e. within the same JVM. The LiveGraph application is abstracted by the class org.LiveGraph.LiveGraph. You can obtain an instance of the application through a statement like

  LiveGraph app = LiveGraph.application();

Now you can  run the application as follows:

  app.exec(new String[0]);

When you want to automatically load your custom settings (see the previous subsection to learn how to create appropriate settings files) you need to pass the exec-method the appropriate command line parameters. For information on command line parameters refer to the user manual. An example could look like this:

  app.exec(new String[] {"-dfs", "/yourapplication/startup.lgdfs"});

An alternative method is to start LiveGraph as a separate process. This is the way to go when you are not using Java or when you want to run LiveGraph within a separate JVM.

For this you use the procedure to create autonomous OS processes appropriate for your programming language and operating system. In order to load your settings you need use command line parameters which you pass to the process. For details, refer to the user manual.

ToC

Summary

You should now be able to seamlessly integrate LiveGraph in any application. In this section we discussed the general architecture of the LiveGraph system. We reviewed in detail how to create data log streams and provided a Java example. Finally we demonstrated how the LiveGraph plotter component can be seamlessly executed from any application.