Thursday, June 2, 2011

Plotting Graph

This article presents a step by step tutorial to implement a simple graph plotting program.


Step 1 : Data Sampling
There are two sources of data, the first one is the real world data such as stock price.
The second one is from a mathematical equation, for example, we may plot a graph for the equation

y=x2

If we limit x in the range of 0 to 6, we would take 7 sample points and have the following sequence of data :
x={0,1,2,3,4,5,6}
y={0,1,4,9,16,25,36}

Since the data is evenly spaced along the x-dimension, we can ignore the x sequence and just focused on the y sequence. To input the sequence to our program, we prepare a data file known as data.txt. The file can be created using any text editor. The data file contains 7 rows with one data value in each row.


Contents of data.txt as follows :
0
1
4
9
16
25
36

Step 2 : read the data
Once the data is ready, we must read it from the data file into our program. The data will be stored in a double[] array. File reading is done by the API in the BufferedReader class.


Step 3 : scaling
Suppose we are plotting a graph in a panel with size 600x300 pixels. To evenly distribute the 7 data points along the x direction, the gap between every data point will be 100 pixels. That is, the x-coordinates in pixels will be (0,100,200,300,400,500,600).
In this case, the scaling factor will be 100, which can be calculated from the following formula :

xScale = PANEL_WIDTH/(NUMBER_OF_DATA_POINT-1)
       = 600 / (7-1) 
       = 600 / 6
       = 100

The scaling factor in the y-dimension can be calculated as

yScale = PANEL_HEIGHT/(MAX_DATA-MIN_DATA)
       = 300 / (36-0) 
       = 8.333

Step 4 : Ploting the data point
We will use a red circle to plot the data point. This can be done by the fillOval API

Step 5 : Connecting the data points
Just use the drawLine() API will do.

Full Source Code

/******************************************************************************
* File : Visualizer.java
* Author : http://java.macteki.com/
* Description :
*   Visualize a sequence of data by ploting a graph just like the MS excel.
* Requirement : data.txt which contains the sequence of data.
* Tested with : JDK 1.6
******************************************************************************/

class Visualizer extends javax.swing.JPanel
{
  double[] data=null;
  double minData=1e308, maxData=-1e308;

  void readData() throws Exception
  {
    String filename="data.txt";
    java.io.BufferedReader br=new java.io.BufferedReader(
      new java.io.FileReader(filename));

    // count number of lines
    int count=0;
    String line="";
    while ((line=br.readLine())!=null) count++;
    br.close();

    double[] a=new double[count]; 
    this.data=a;


    // re-open the file    
    br=new java.io.BufferedReader(
      new java.io.FileReader(filename));

    // read data line by line and store them in an array
    count=0;
    while ((line=br.readLine())!=null) 
    {
      double y=Double.parseDouble(line);
      a[count++]=y;
      if (y<minData) minData=y;
      if (y>maxData) maxData=y;
    }

  }

  // this will be called automatically when the panel is displayed
  public void paintComponent(java.awt.Graphics gr)
  {
    if (data==null) return;
    gr.setColor(java.awt.Color.GRAY);
    gr.fillRect(0,0,getWidth(),getHeight());

    int width=getWidth();
    int height=getHeight();
    double xScale = (double) width/(double)(data.length-1);
    double yScale = (double) height/(double) (maxData-minData);
    double xp=-999,yp=0;  // previous point
    for (int i=0;i<data.length;i++)
    {
      double x=i*xScale;
      double y=(data[i]-minData)*yScale;
      y=height-y;  // top-down transformation
      gr.setColor(java.awt.Color.RED);
      gr.fillOval((int)x-5,(int)y-5,10,10); 
      // connect previous point with current point
      gr.setColor(java.awt.Color.BLUE);
      if (xp!=-999) gr.drawLine((int)xp,(int)yp,(int)x,(int)y);
      xp=x;  yp=y;
    }
  }

  public static void main(String[] args) throws Exception
  {
    javax.swing.JFrame window=new javax.swing.JFrame();
    window.setTitle("Macteki Data Visualizer");
    window.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
    Visualizer panel=new Visualizer();
    window.add(panel);
    panel.setPreferredSize(new java.awt.Dimension(600,300));
    panel.readData();
    window.pack();
    window.setVisible(true);
  }
}

No comments:

Post a Comment