Index: trunk/greenstone3-extensions/vishnu/src/vishnu/util/Hgram.java
===================================================================
--- trunk/greenstone3-extensions/vishnu/src/vishnu/util/Hgram.java	(revision 8283)
+++ trunk/greenstone3-extensions/vishnu/src/vishnu/util/Hgram.java	(revision 8283)
@@ -0,0 +1,378 @@
+package vishnu.util;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.imageio.*;
+import javax.imageio.stream.*;
+import java.io.*;
+import java.util.*;
+import java.awt.image.*;
+
+public class Hgram extends JFrame
+{
+    public static int TOP = 0;
+    public static int LARGEST = 1;
+
+    // data is an array with each entry being the frequency of a bin
+    public static int BIN_DATA = 0;
+
+    // data comes in raw format and needs to be allocated to bins
+    public static int RAW_DATA = 1;
+    
+    double[] data;
+    
+    // default size of frame
+    int width = 400;
+    int height = 400;
+
+    // axis limits of histogram
+    double xmin;
+    double xmax;
+
+    // number of bins, bin frequencies and width
+    int noBins;
+    double bins[];
+    double binWidth;
+    
+    BufferedImage offScreen=null;
+    Dimension offScreenSize;
+    Graphics2D offGraphics;
+    
+    String label = null;
+    
+    double median = -1;
+    int med_bin = -1;
+    int mode = -1;
+    
+    
+    public Hgram()
+    {
+	init();
+    }
+
+    
+    public void setData(double[] d, int m){
+	data = d; 
+	mode = m;
+	xmin = getMinimum(data);
+	xmax = getMaximum(data);
+	createBins(data,noBins,xmin, xmax);
+    }
+
+      
+    public void setBins(double[] b){ bins = b; }
+
+
+    public void setBinNumber(int i){ noBins = i; }
+
+    
+    public void setMaximum(double i){ xmax = i; }
+    
+    
+    public void setMinimum(double i){ xmin = i; }
+
+
+    public void setBinWidth(double i){ binWidth = i; }
+    
+    
+    public void setLabel(String l){ label = l; }
+  
+
+    public void init()
+    {
+	this.setDefaultLookAndFeelDecorated(true);
+        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+	this.setSize(width,height);
+	this.setLocation(0,0);
+	this.setVisible(true);
+	
+	this.addComponentListener( new ComponentAdapter(){
+		public void componentResized(ComponentEvent evt){
+		    update();
+		}
+	    });
+	
+	
+	this.addMouseListener(new MouseAdapter(){
+		public void mousePressed(MouseEvent evt)
+		{
+    		    int intX = evt.getX();
+	    	    int intY = evt.getY();
+		}
+		
+		public void mouseClicked(MouseEvent event)
+		{
+		    int x = event.getX();
+		    int y = event.getY();
+		    
+		    if( event.getClickCount() == 1 )
+			{
+			}
+		}
+	    });
+	
+	
+	this.addMouseMotionListener(new MouseMotionAdapter()
+	    {
+		public void mouseMoved(MouseEvent event)
+		{
+		    int x = event.getX();
+		    int y = event.getY();
+		    getBin(x,y);
+		}
+	    });
+    }
+
+    
+    public int getBin(int x, int y){ return -1; }
+    
+    
+    private int getMaxBin()
+    {
+	int maxIndex = -1;
+	double max = 0;
+	
+	for( int i = 0; i < bins.length; i++ ){
+	    if( bins[i] > max ){
+		max = bins[i];
+		maxIndex = i;
+	    }
+	}
+	
+	return maxIndex;
+    }
+    
+    
+    public void plot()
+    {
+	update();
+    }
+    
+      
+    public double getMaximum(double[] d)
+    {
+	double max = 0; 
+
+	for( int i = 0; i < d.length; i++ ){
+	    if( d[i] > max ) max = d[i];
+	}
+	return max;
+    }
+ 
+
+
+    public double getMinimum(double[] d)
+    {
+	double min = d[0]*d[0]*1000;
+
+	for( int i = 0; i < d.length; i++ )
+	    {
+		if( d[i] < min ) min = d[i];
+	    }
+	return min;
+    }
+
+
+    public double getFirstMaximum(double[] d)
+    {
+	double max = 0;
+	for( int i = 0; i < bins.length; i++ )
+	    {
+		if( bins[i] > max )
+		    {
+			max = bins[i];
+		    }
+	    }
+	return max;
+    }
+
+
+    public double getSecondMaximum(double[] d)
+    {
+	double max_1 = 0;
+	double max_2 = 0;
+	for( int i = 0; i < d.length; i++ ){
+	    if( d[i] > max_1 ){
+		max_2 = max_1;
+		max_1 = d[i];
+	    }
+	    else if( d[i] > max_2 ){
+		max_2 = d[i];
+	    }
+	}
+	return max_2;
+    }
+
+ 
+    public void createBins(double[] data, int noBins, double xmin, double xmax)
+    {
+	bins = new double[noBins];
+	binWidth = (double)(xmax-xmin)/noBins;
+	
+	for( int i = 0; i < data.length; i++ ){
+	    int bin = (int)Math.round((double)(data[i]-xmin)/binWidth);
+	    if( bin >= noBins ) bin = noBins-1;
+	    bins[bin]++;
+	}
+	
+	for( int i = 0; i < noBins; i++ ){
+	    bins[i] = (double)bins[i]/data.length;
+	}
+    }
+    
+    
+    public void update()
+    {
+	if( bins == null ) return;
+	
+	Dimension d = this.getSize();
+	width = d.width;
+	height = d.height;
+        offScreen = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB ); 
+	offGraphics = (Graphics2D)offScreen.getGraphics();
+        offGraphics.setColor(Color.white);
+        offGraphics.fillRect(0,0,width,height);
+    	BasicStroke myStroke = new BasicStroke(2,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER);
+        offGraphics.setStroke(myStroke);	
+	
+	int xaxis = (int)(0.8 * width); 
+	int xBuffer = (int)(0.1 * width);
+	
+	int yaxis = (int)(0.8 * d.height);
+	int yBuffer = (int)(0.1 * d.height);
+	
+	double maxBinLength = (double)xaxis/bins.length;
+	int effBinLength = (int)(0.8 * maxBinLength);
+	int binBuffer = (int)(0.1 * effBinLength);
+	
+	double max_1 = getFirstMaximum(bins);
+	double max_2 = getSecondMaximum(bins);
+	double max = max_1;
+	boolean cut = false;
+	
+	if( max_1 > 1.5 * max_2 ){
+	    cut = true;
+	    max = max_2;
+	}
+	
+	double pixelPerUnit = (double)yaxis/max; 
+	
+
+	/**** draw the bins ****/
+
+	for( int i = 0; i < bins.length; i++ ){
+	    int level = (int)(bins[i]* pixelPerUnit);
+	    double bound = (double)((int)(100 * (i * (double)(xmax-xmin)/bins.length + xmin)))/100;
+	    offGraphics.setColor(Color.blue);
+	    offGraphics.fillRect(xBuffer + (int)(i*maxBinLength)+binBuffer,height-yBuffer-level,effBinLength,level);
+	}
+
+	if( label != null ){
+	    FontMetrics fm   = offGraphics.getFontMetrics(offGraphics.getFont());
+	    int x = width/2 - fm.stringWidth(label)/2;		
+	    offGraphics.drawString(label,x,yBuffer);
+	}
+
+
+	/**** draw axes and ticks ****/
+
+	offGraphics.setColor(Color.blue);
+	
+	int x = xBuffer + binBuffer;
+	int y = height-yBuffer;
+	offGraphics.drawLine(x, y+5, x, y-5);
+	
+	String tickStr = String.valueOf(xmin);
+	offGraphics.drawString(tickStr,x-5,y+20);
+	
+	x = xBuffer + binBuffer+(int)(bins.length*maxBinLength)+binBuffer;
+	y = height-yBuffer;
+	offGraphics.drawLine(x, y+5, x, y-5);
+	tickStr = String.valueOf(xmax);
+	offGraphics.drawString(tickStr,x-5,y+20);
+	
+        repaint();
+    }
+    
+    
+    public void paint(Graphics g)
+    {
+        Graphics2D g2 = (Graphics2D)g;
+	
+	if( offScreen!=null )
+	    g2.drawImage(offScreen, 0, 0, null);
+    }
+    
+    
+    public void printBins()
+    {
+	for( int i = 0; i < bins.length; i++ ){
+	    double low = i*binWidth;
+	    double up = (i+1)*binWidth;
+	    System.out.println("Bin.." + i + " " + low + " " + up + " " + bins[i]); 
+	}
+    }
+
+
+    public void save(String name, String type)
+    {
+	
+	try{
+	    Iterator imageWriters =
+		ImageIO.getImageWritersByFormatName(type);
+	    ImageWriter imageWriter = (ImageWriter)imageWriters.next();
+	    File file = new File( name + "." + type );
+	    ImageOutputStream ios =
+		ImageIO.createImageOutputStream( file );
+	    imageWriter.setOutput( ios );
+	    imageWriter.write( offScreen );
+	} catch( IOException ie ) {
+	    ie.printStackTrace();
+	}
+    }
+
+}
+
+ // accepts raw data
+    /*public Hgram(double[] data, int noBins, double min, double max)
+    {
+	super("JHistogram");
+	init();
+	createBins(data,noBins,min,max);
+	update();
+	}*/
+    
+    
+    // accepts both raw and binned data
+    /*public Hgram(double[] data, int noBins, int mode)
+    {
+	super("JHistogram");
+	this.mode = mode;
+	init();
+	createBins(data,noBins,getMinimum(data),getMaximum(data));
+	update();
+	}*/
+    
+
+
+/*
+	int level = (int)(bins[med_bin]* pixelPerUnit);
+	offGraphics.fillRect(xBuffer + (int)(med_bin*maxBinLength)+binBuffer,height-yBuffer-level,effBinLength,level);
+	String med_string = String.valueOf(median);
+	med_string = med_string.substring(0,med_string.indexOf('.')+3);
+	offGraphics.drawString(med_string, xBuffer + (int)(med_bin*maxBinLength)+binBuffer-10,height-yBuffer-level-10);
+	    
+	//saveHistogram(offScreen);
+	
+	repaint();
+	    }
+	    }*/
+
+  /*
+    public Hgram(double[] data, int noBins)
+    {
+	init();
+	createBins(data,noBins,getMinimum(data),getFirstMaximum(data));
+	update();
+	}*/
Index: trunk/greenstone3-extensions/vishnu/src/vishnu/util/Misc.java
===================================================================
--- trunk/greenstone3-extensions/vishnu/src/vishnu/util/Misc.java	(revision 8283)
+++ trunk/greenstone3-extensions/vishnu/src/vishnu/util/Misc.java	(revision 8283)
@@ -0,0 +1,240 @@
+package vishnu.util;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+public class Misc {
+
+    // quickSort
+    private static void qs(int l, int r, double v[][])
+    {
+	if( l < r )
+	{
+		int i = l;
+		int j = r;
+		double pivot = v[1][(l+r)/2];
+		do
+		{
+
+			while( v[1][i] < pivot )
+			{
+				i++;
+			} 
+			while( v[1][j] > pivot )
+			{
+				j--;
+			}
+
+			if( i <= j )
+			{
+				if( i < j )
+				{
+					double t1 = v[1][i];	
+					double t0 = v[0][i];
+					v[1][i] = v[1][j];
+					v[1][j] = t1;
+					v[0][i] = v[0][j];
+					v[0][j] = t0;
+				}
+				i++;
+				j--;
+			}
+		
+		}
+		while( i <= j );
+		qs(l,j,v);
+		qs(i,r,v);
+		
+	}
+    }
+
+    
+    
+    // quickSort
+    private static void qs(int l, int r, double v[])
+    {
+	if( l < r )
+	{
+		int i = l;
+		int j = r;
+		double pivot = v[(l+r)/2];
+		do
+		{
+
+			while( v[i] < pivot )
+			{
+				i++;
+			} 
+			while( v[j] > pivot )
+			{
+				j--;
+			}
+
+			if( i <= j )
+			{
+				if( i < j )
+				{
+					double t1 = v[i];	
+					v[i] = v[j];
+					v[j] = t1;
+				}
+				i++;
+				j--;
+			}
+		
+		}
+		while( i <= j );
+		qs(l,j,v);
+		qs(i,r,v);
+		
+	}
+    }
+
+
+ // quickSort
+    private static void qs(int l, int r, int v[])
+    {
+	if( l < r )
+	{
+		int i = l;
+		int j = r;
+		int pivot = v[(l+r)/2];
+		do
+		{
+
+			while( v[i] < pivot )
+			{
+				i++;
+			} 
+			while( v[j] > pivot )
+			{
+				j--;
+			}
+
+			if( i <= j )
+			{
+				if( i < j )
+				{
+					int t1 = v[i];	
+					v[i] = v[j];
+					v[j] = t1;
+				}
+				i++;
+				j--;
+			}
+		
+		}
+		while( i <= j );
+		qs(l,j,v);
+		qs(i,r,v);
+	}
+    }
+
+
+ // quickSort
+    private static void qs(int l, int r, int[] v, Object[] objArr)
+    {
+        if( l < r ){
+            int i = l;
+            int j = r;
+
+            int pivot = v[(l+r)/2];
+
+            do{
+                while( v[i] < pivot ){
+                    i++;
+                }
+                while( v[j] > pivot ){
+                    j--;
+                }
+
+                if( i <= j ){
+                    if( i < j ){
+                        int t1 = v[i];
+                        v[i] = v[j];
+                        v[j] = t1;
+
+                        Object tobj = objArr[i];
+                        objArr[i] = objArr[j];
+                        objArr[j] = tobj;
+ }
+                    i++;
+                    j--;
+                }
+
+            }
+            while( i <= j );
+            qs(l,j,v,objArr);
+            qs(i,r,v,objArr);
+        }
+    }
+
+
+    // quickSort
+    private static void qs(int l, int r, float[] v, Object[] objArr)
+    {
+	if( l < r ){
+	    int i = l;
+	    int j = r;
+	    
+	    float pivot = v[(l+r)/2];
+	    
+	    do{
+		while( v[i] < pivot ){
+		    i++;
+		} 
+		while( v[j] > pivot ){
+		    j--;
+		}
+		
+		if( i <= j ){
+		    if( i < j ){
+			float t1 = v[i];	
+			v[i] = v[j];
+			v[j] = t1;
+			
+			Object tobj = objArr[i];
+			objArr[i] = objArr[j];
+			objArr[j] = tobj;
+		    }
+		    i++;
+		    j--;
+		}
+		
+	    }
+	    while( i <= j );
+	    qs(l,j,v,objArr);
+	    qs(i,r,v,objArr);
+	}
+    }
+    
+
+    public static void quickSort(int[] v)
+    {
+	qs(0,v.length-1,v);
+    }
+
+    public static void quickSort(float[] v, Object[] objArr)
+    {
+	qs(0,v.length-1,v,objArr);
+    }
+
+    public static void quickSort(int[] v, Object[] objArr)
+    {
+	qs(0,v.length-1,v,objArr);
+    }
+
+    public static void quickSort(double v[])
+    {
+	qs(0,v.length-1,v);
+    }
+
+
+    public static void quickSort(double v[][])
+    {
+	qs(0,v[0].length-1,v);
+    }
+}
+    
+    
