/*
* -------------------------------------------------------------------------
* $Id: CVPanel.java,v 1.3 2004/10/14 16:20:03 estewart Exp $
* -------------------------------------------------------------------------
* Copyright (c) 2004 Visual Numerics Inc. All Rights Reserved.
*
* This software is confidential information which is proprietary to
* and a trade secret of Visual Numerics, Inc. Use, duplication or
* disclosure is subject to the terms of an appropriate license
* agreement.
*
* VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
* SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
* NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
* ITS DERIVATIVES.
*--------------------------------------------------------------------------
*/
/*
* CorrelationPicture
* Copyright (c), 2003, Gary H. McClelland
* Shows relationship between degree of scatter in a scattergram
* and the correlation coefficient. A slider allows user to change
* the degree of scatter and observe the resulting changes in the
* correlation coefficient.
*/
/**
* @author Gary H. McClelland
* @created 2 October 2003
*/
package com.imsl.demo.stats;
import com.imsl.chart.*;
import com.imsl.stat.Random;
import com.imsl.stat.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import javax.swing.*;
import javax.swing.event.*;
public class CVPanel extends JPanel {
private JFrame parentFrame;
private JPanelChart jPanelChart;
private JPanel jPanel;
private JLabel jLabel;
private JSlider wtSlider;
private JButton jButton;
private Random rand;
Chart chart;
AxisXY axis;
Data scat;
double x[], y[];
final int numberOfPoints = 30;
public CVPanel(javax.swing.JFrame parent) {
this.parentFrame = parent;
initComponents();
setPreferredSize(new java.awt.Dimension(
parent.getSize().width, (int)(0.85*parent.getSize().height)));
jPanelChart.setPreferredSize(new java.awt.Dimension(
parent.getSize().width, (int)(0.66*parent.getSize().height)));
//basic chart setup, layout of slider
jPanelChart.setChart(new Chart());
chart = jPanelChart.getChart();
axis = new AxisXY(chart);
//want fixed, unchanging range for both axes
//allowing rescaling would make changes jumpy
final double[] range = {0,100};
final DecimalFormat df = new java.text.DecimalFormat("###");
axis.getAxisX().setWindow(range);
axis.getAxisY().setWindow(range);
axis.getAxisX().setAutoscaleInput(Axis.AUTOSCALE_OFF);
axis.getAxisY().setAutoscaleInput(Axis.AUTOSCALE_OFF);
axis.getAxisX().getAxisTitle().setTitle("X Values");
axis.getAxisY().getAxisTitle().setTitle("Y Values");
axis.getAxisX().setTextFormat(df);
axis.getAxisY().setTextFormat(df);
//generate two random variables
x = newSample(numberOfPoints,123321);
y = newSample(numberOfPoints,321123);
//correlation of the two random variables will be near zero
//but we want it to be exactly zero
x = adjustToZero(x,y);
drawGraph(0.0);
}
private void initComponents() {
jPanel = new JPanel();
jPanelChart = new com.imsl.chart.JPanelChart();
setLayout(new BorderLayout());
jPanel.setLayout(new FlowLayout());
jLabel = new JLabel("<html><center>Move the slider to adjust the "+
"<br>correlation between -1 and +1.</center></html>");
jPanel.add(jLabel);
wtSlider = new JSlider(JSlider.HORIZONTAL,-500,500,0);
wtSlider.setMajorTickSpacing(100);
wtSlider.setMinorTickSpacing(25);
wtSlider.setPaintTicks(true);
wtSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent evt) {
sliderChanged(evt);
}
});
jPanel.add(wtSlider);
add(jPanel, BorderLayout.NORTH);
jPanelChart.setPreferredSize(new java.awt.Dimension(500, 500));
add(jPanelChart, BorderLayout.CENTER);
}
// generates random normal variable of length k
// rescaled to min = 0 and max = 100
private double[] newSample(int k, int seed) {
rand = new Random(seed);
double v[] = new double[k];
double min = 1000;
double max = -1000;
for(int i=0; i<=k-1; i++) {
v[i] = rand.nextNormalAR(); //nextNormalAR();
if(v[i] < min) min = v[i];
if(v[i] > max) max = v[i];
}
for(int i=0; i<k; i++)
v[i] = 100 * (v[i] - min)/(max - min);
return v;
}
private double getCorrelation(double[] x, double[] y) {
double mat[][] = new double[y.length][2];
for(int i=0; i<= y.length-1; i++) {
mat[i][0] = x[i];
mat[i][1] = y[i];
}
Covariances cov = new Covariances(mat);
double[][] cor = new double[2][2];
try {
cor = cov.compute(Covariances.STDEV_CORRELATION_MATRIX);
} catch (Exception e) {}
return cor[0][1];
}
//computes weighted average of two variables
//weight ranges from -1 to +1
private double[] applyWeight(double wt, double u[], double v[]) {
double w[] = new double[v.length];
for(int i=0; i<=v.length-1; i++)
if(wt >= 0)
w[i] = (1-wt)*v[i] + wt*u[i];
else
w[i] = (1+wt)*v[i] - wt*(100-u[i]);
return w;
}
//finds weighted average of the two variables that produces a
//zero correlation between that weighted average and one of the
//variables.
private double[] adjustToZero(double u[], double v[]) {
double r = getCorrelation(v,u);
double minwt = -1;
double maxwt = 1;
double wt = 0;
double tol = .0001;
int maxIter = 100;
int iter = 0;
while(Math.abs(r) > tol && iter < maxIter) {
if(r > 0) { //look down
maxwt = wt;
wt = (minwt + wt)/2;
} else { //look up
minwt = wt;
wt = (maxwt + wt)/2;
}
r = getCorrelation(v,applyWeight(wt,v,u));
iter = iter + 1;
}
return applyWeight(wt,v,u);
}
//slider determines weight and hence correlation
private void sliderChanged(ChangeEvent e) {
JSlider source = (JSlider)e.getSource();
//get new weight from slider
double wt = (double)source.getValue()/500.;
drawGraph(wt);
repaint();
}
//draws scattergram with variable y and the x variable being
//a weighted average of x and y.
private void drawGraph(double wt) {
double r = getCorrelation(applyWeight(wt,y,x),y);
final DecimalFormat df = new DecimalFormat("0.000");
try{
chart.getChartTitle().setTitle("r = " + df.format(r));
chart.getChartTitle().setFontSize(16);
if(r < 0)
chart.getChartTitle().setTextColor(Color.red);
else
chart.getChartTitle().setTextColor(Color.blue);
//get rid of old data if it exists or it persists on graph
if(scat != null) scat.remove();
scat = new Data(axis, applyWeight(wt,y,x), y);
scat.setDataType(Data.DATA_TYPE_MARKER);
scat.setMarkerType(Data.MARKER_TYPE_FILLED_CIRCLE);
scat.setMarkerColor(Color.black);
}
catch (Exception e) {}
}
}