package ChaosDemos;
import java.awt.*;
import java.util.*;
import java.net.URL;
import graph.*;
/**
* Plots data in separate frame and allows linear fit for range between two points
* selected with the mouse.
*/
public class linearFitPlot extends Frame {
private int length;
private Graph2D graph;
private Label resultBox;
private DataSet data;
private DataSet lineFit;
private DataSet rangePlotted;
private Axis xaxis,yaxis;
private URL markerURL;
private URL documentBase;
private boolean clicked;
private double xmin,xmax;
private double[] graphData;
private String slopeString="Slope = ";
private String interceptString="Intercept = ";
private String xAxisString="X";
private String yAxisString="Y";
private boolean showSlope=true;
private boolean showIntercept=true;
//************************************************************************
/**
* @param in_data array of data in x,y pairs
* @param in_documentBase URL giving location of marler.txt file for markers
*/
//************************************************************************
public linearFitPlot(double[] in_data, URL in_documentBase) {
lineFit=null;
rangePlotted=null;
length=in_data.length;
graphData=new double[length];
System.arraycopy(in_data,0,graphData,0,length);
documentBase=in_documentBase;
setLayout(new BorderLayout());
graph=new Graph2D();
add("Center",graph);
resultBox=new Label(" ",Label.CENTER);
add("South",resultBox);
graph.drawzero = false;
graph.drawgrid = false;
graph.clearAll = true;
graph.borderTop = 40;
graph.borderRight=20;
graph.borderLeft=20;
graph.borderBottom=20;
//MCC 3/19/97 change to new setTitleFont etc.
// x-axis
xaxis = graph.createAxis(Axis.BOTTOM);
xaxis.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
xaxis.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
xaxis.setTitleText(xAxisString);
// yaxis
yaxis = graph.createAxis(Axis.LEFT);
yaxis.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
yaxis.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
yaxis.setTitleText(yAxisString);
try {
markerURL = new URL(documentBase,"marker.txt");
graph.setMarkers(new Markers(markerURL));
} catch(Exception e) {
System.out.println("Failed to create Marker URL!");
}
data = graph.loadDataSet(in_data,length/2);
data.linestyle = 1;
data.linecolor = Color.red;
data.marker = 1;
data.markerscale = 2;
data.markercolor = Color.red;
xaxis.attachDataSet(data);
yaxis.attachDataSet(data);
graph.setDataBackground(new Color(255,200,175));
graph.setBackground(new Color(200,150,100));
clicked=false;
}
//************************************************************************
/**
* Event handler:
* Stops iteration on minimising and handles close window event
* (May fail under Windows95)
*/
//************************************************************************
public boolean handleEvent(Event evt) {
switch (evt.id) {
case Event.WINDOW_DESTROY:
this.dispose();
return super.handleEvent(evt);
default:
return super.handleEvent(evt);
}
}
//************************************************************************
/* Selects nearest point and on second click does linear fit to points between
* (and including) the clicked points.
*/
//************************************************************************
public boolean mouseDown(Event evt, int x, int y) {
double xcoord=0;
double ycoord=0;
boolean xcoordValid=false;
boolean ycoordValid=false;
Rectangle gr=graph.bounds();
if (graph.datarect.width != 0.) {
xcoord = xaxis.minimum + (xaxis.maximum - xaxis.minimum) *
((float)(x - gr.x - graph.datarect.x))/( (float) graph.datarect.width);
if(xcoord > xaxis.minimum & xcoord < xaxis.maximum) xcoordValid=true;
}
if (graph.datarect.height != 0.) {
ycoord = yaxis.maximum - (yaxis.maximum - yaxis.minimum) *
((float)(y - gr.y - graph.datarect.y))/( (float) graph.datarect.height);
if(ycoord > yaxis.minimum & ycoord < yaxis.maximum) ycoordValid=true;
}
// System.out.println("xcoord= "+ xcoord+" "+xcoordValid);
// System.out.println(y+" "+datarect.y+" "+datarect.height);
// System.out.println("ycoord= "+ ycoord+" "+ycoordValid);
// System.out.println("r.y ="+ graph.datarect.y+" height= "+graph.datarect.height);
// System.out.println("g.y ="+ gr.y+" g.height= "+gr.height);
// System.out.println("r.x ="+ graph.datarect.x+" width= "+graph.datarect.width);
// System.out.println("g.x ="+ gr.x+" g.width= "+gr.width);
// System.out.println("min= "+yaxis.minimum+" max= "+yaxis.maximum);
if(xcoordValid && ycoordValid) {
if(!clicked) {
xmin=xcoord;
clicked=true;
}
else {
xmax=xcoord;
clicked=false;
if(xmin > xmax) {
double xswap=xmin;
xmin=xmax;
xmax=xswap;
}
fit(xmin, xmax);
}
}
return true;
}
//************************************************************************
/**
* Does fit (see Numerical Recipes)
*/
//************************************************************************
private void fit(double xmin,double xmax) {
int imin=0,imax=length/2;
imin=findPoint(xmin);
imax=findPoint(xmax);
if(imax==0) imax=1;
if(imin==length) imin=length-1;
if(imin==imax) imax=imax+1;
double Sx=0,S=0,Sy=0,Stt=0,ty=0;
for(int i=imin;i<=imax;i++) {
S++;
Sx=Sx+graphData[2*i];
}
double xbar=Sx/S;
for(int i=imin;i<=imax;i++) {
double ti=graphData[2*i]-xbar;
double yi=graphData[2*i+1];
Stt=Stt+ti*ti;
Sy=Sy+yi;
ty=ty+ti*yi;
}
double b=ty/Stt;
double a=(Sy-Sx*b)/S;
double[] fitData = new double[4];
fitData[0]=graphData[0];
fitData[1]=a+b*fitData[0];
fitData[2]=graphData[length-2];
fitData[3]=a+b*fitData[2];
if(lineFit!=null) graph.detachDataSet(lineFit);
lineFit = graph.loadDataSet(fitData,2);
lineFit.linestyle = 1;
lineFit.linecolor = Color.blue;
xaxis.attachDataSet(lineFit);
yaxis.attachDataSet(lineFit);
double[] rangeData=new double[4];
rangeData[0]=graphData[2*imin];
rangeData[1]=graphData[2*imin+1];
rangeData[2]=graphData[2*imax];
rangeData[3]=graphData[2*imax+1];
if(rangePlotted!=null)graph.detachDataSet(rangePlotted);
rangePlotted = graph.loadDataSet(rangeData,2);
rangePlotted.linestyle = 0;
rangePlotted.marker=1;
rangePlotted.markerscale=2;
rangePlotted.markercolor=Color.black;
xaxis.attachDataSet(rangePlotted);
yaxis.attachDataSet(rangePlotted);
graph.repaint();
String result="";
if(showSlope) result=result+slopeString+" "+b+" ";
if(showIntercept) result=result+interceptString+" "+a;
resultBox.setText(result);
}
//************************************************************************
/**
* Finds nearst point
*/
//************************************************************************
private int findPoint(double x) {
double dmin=Math.abs(x-graphData[0]);
int imin=0;
for (int i=1;i