/*
* @(#)Chart.java 0.0.2 99/08/06
*
* Copyright (c) 1999 by Willie Wheeler. All rights reserved.
*/
package stats;
import java.awt.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import lang.*;
/**
* Abstract base class for displaying probabilities in a graphical form.
*
* @version 0.0.2 08/06/99
* @author Willie Wheeler
*/
public abstract class Chart extends JComponent implements TableModelListener {
public static final String MODEL_PROPERTY = "model";
public static final String TITLE_PROPERTY = "title";
public static final String COLORS_PROPERTY = "colors";
public static Color[] defaultColors = new Color[] {
Color.red, Color.blue, Color.green, Color.yellow, Color.lightGray,
Color.cyan, Color.magenta, Color.orange, Color.gray, Color.white,
Color.pink, Color.black
};
protected static NumberFormat nf = NumberFormat.getNumberInstance();
static {
nf.setMinimumFractionDigits(3);
nf.setMaximumFractionDigits(3);
}
protected MVDTableModel model;
protected int[] independentIndices;
protected int dependentIndex;
protected int[] conditioningState;
protected String title;
protected int[][] states;
protected String[] stateNames;
protected double[] stateValues;
protected Color[] stateColors;
/**
* Builds a chart to display the unconditional distribution of the
* model's zeroth dependent variable over all independent variables.
*
* @param model the model from which the variables and
* distribution are obtained
*/
public Chart(ContingencyTableModel model) {
setModel(model);
setStateColors(defaultColors);
}
/**
* Builds a chart to display the unconditional distribution of the model's
* zeroth dependent variable over the specified set of independent
* variables. For example, to specify independent variables 0 and 2, pass
* new int[] { 0, 2 } into the independentIndices
* parameter.
*
* @param model the model from which the variables and
* distribution are obtained
* @param independentIndices array of independent variable indices
*/
public Chart(ContingencyTableModel model, int[] independentIndices) {
setModel(model, independentIndices);
setStateColors(defaultColors);
}
/**
* Builds a chart to display the unconditional distribution of the
* specified dependent variable over the specified set of independent
* variables.
*
* @param model the model from which the variables and
* distribution are obtained
* @param independentIndices array of independent variable indices
* @param dependentIndex dependent variable index
*/
public Chart(ContingencyTableModel model,
int[] independentIndices,
int dependentIndex) {
setModel(model, independentIndices, dependentIndex);
setStateColors(defaultColors);
}
/**
* Builds a chart to display a conditional distribution of the specified
* dependent variable over the specified set of independent variables.
* The conditioning state is specified in the same way that any other
* state is specified.
*
* @param model the model from which the variables and
* distribution are obtained
* @param independentIndices array of independent variable indices
* @param dependentIndex dependent variable index
* @param conditioningState conditioning state specification
*/
public Chart(ContingencyTableModel model,
int[] independentIndices,
int dependentIndex,
int[] conditioningState) {
setModel(model, independentIndices, dependentIndex, conditioningState);
setStateColors(defaultColors);
}
public void setModel(ContingencyTableModel model) {
int numIndependents = model.getNumIndependents();
int[] independentIndices = new int[numIndependents];
for (int i = 0; i < numIndependents; i++) {
independentIndices[i] = i;
}
setModel(model, independentIndices, 0, null);
}
public void setModel(ContingencyTableModel model,
int[] independentIndices) {
setModel(model, independentIndices, 0, null);
}
public void setModel(ContingencyTableModel model,
int[] independentIndices,
int dependentIndex) {
setModel(model, independentIndices, dependentIndex, null);
}
public void setModel(ContingencyTableModel model,
int[] independentIndices,
int dependentIndex,
int[] conditioningState) {
// Replace the old model with the new.
MVDTableModel oldModel = this.model;
if (oldModel != null) { oldModel.removeTableModelListener(this); }
this.model = model;
model.addTableModelListener(this);
// Set the variable indices and conditioning state.
this.independentIndices = independentIndices;
this.dependentIndex = dependentIndex;
this.conditioningState = conditioningState;
// Set the title.
setTitle(getDefaultTitle());
// Set the state information.
this.states = model.states(independentIndices);
this.stateNames = model.getStatesAsStrings(states);
// Set the state values.
if (dependentIndex == model.FREQUENCY_OFFSET) {
// Very inefficient array copy.
int[] freqDist =
model.getFrequencyDistribution(states, conditioningState);
this.stateValues = new double[freqDist.length];
for (int i = 0; i < freqDist.length; i++) {
this.stateValues[i] = (double)freqDist[i];
}
} else if (dependentIndex == model.ESTIMATE_OFFSET) {
this.stateValues =
model.getEstimateDistribution(states, conditioningState);
}
// Fire a property change event.
firePropertyChange(MODEL_PROPERTY, oldModel, this.model);
}
public MVDTableModel getModel() { return model; }
public int getNumIndependents() { return independentIndices.length; }
public int[] getIndependentIndices() { return independentIndices; }
public int getDependentIndex() { return dependentIndex; }
public int[] getCondition() { return conditioningState; }
public int getNumStates() { return states.length; }
public String getStateName(int stateIndex) {
return stateNames[stateIndex];
}
public double getStateValue(int stateIndex) {
return stateValues[stateIndex];
}
public void setStateColors(Color[] stateColors) {
Color[] oldStateColors = this.stateColors;
this.stateColors = stateColors;
firePropertyChange(COLORS_PROPERTY, oldStateColors, this.stateColors);
}
public Color getStateColor(int stateIndex) {
return stateColors[stateIndex % stateColors.length];
}
public void setTitle(String title) {
String oldTitle = this.title;
this.title = title;
firePropertyChange(TITLE_PROPERTY, oldTitle, this.title);
}
public String getTitle() { return title; }
public String getDefaultTitle() {
String independents = getIndependentsAsString();
String dependent = getDependentAsString();
String condition = getConditionAsString();
StringBuffer buffer = null;
// Treat frequencies specially.
if (dependent.equals(ContingencyTableModel.FREQUENCY)) {
buffer = new StringBuffer("Fr(" + independents);
if (condition != "") { buffer.append(" | " + condition); }
buffer.append(")");
}
// Treat estimates specially.
else if (dependent.equals(ContingencyTableModel.ESTIMATE)) {
buffer = new StringBuffer("Pr^(" + independents);
if (condition != "") { buffer.append(" | " + condition); }
buffer.append(")");
}
// Otherwise...
else {
buffer = new StringBuffer(dependent + " vs. " + independents);
if (condition != "") { buffer.append(", given " + condition); }
}
// Return the buffer contents.
return buffer.toString();
}
//
// Accessing the variables, conditions, and states as strings.
//
public String getIndependentsAsString() {
return model.getIndependentsAsString(independentIndices);
}
public String getDependentAsString() {
return model.getDependent(dependentIndex).getName();
}
public String getConditionAsString() {
return model.getConditionAsString(conditioningState);
}
public String getStateValueAsString(int stateIndex) {
double value = getStateValue(stateIndex);
if (model.getDependent(dependentIndex) instanceof IntegralVariable) {
return String.valueOf((int)value);
} else {
return nf.format(value);
}
}
// Handling events.
public void tableChanged(TableModelEvent e) {
if (model instanceof ContingencyTableModel) {
ContingencyTableModel ctm = (ContingencyTableModel)model;
if (dependentIndex == ctm.FREQUENCY_OFFSET) {
// Very inefficient array copy.
int[] freqDist =
ctm.getFrequencyDistribution(states, conditioningState);
stateValues = new double[freqDist.length];
for (int i = 0; i < freqDist.length; i++) {
stateValues[i] = freqDist[i];
}
} else if (dependentIndex == ctm.ESTIMATE_OFFSET) {
stateValues =
ctm.getEstimateDistribution(states, conditioningState);
}
}
repaint();
}
}