Split AutoAnalyser into 2 classes, itself and the new AutoAnalyserChannelCalculator, keeping all the common functionality/generality for other calculator types in AutoAnalyser. This will allow us to have the AutoAnalyser for other types of calculators as well later.

This commit is contained in:
jlizier 2017-08-21 14:25:01 +10:00
parent 086bee5945
commit e75eb761ca
4 changed files with 594 additions and 300 deletions

View File

@ -18,12 +18,13 @@
package infodynamics.demos.autoanalysis;
import infodynamics.measures.continuous.ChannelCalculatorCommon;
import infodynamics.measures.discrete.ChannelCalculatorDiscrete;
import infodynamics.measures.continuous.InfoMeasureCalculatorContinuous;
import infodynamics.measures.discrete.InfoMeasureCalculatorDiscrete;
import infodynamics.utils.AnalyticMeasurementDistribution;
import infodynamics.utils.AnalyticNullDistributionComputer;
import infodynamics.utils.ArrayFileReader;
import infodynamics.utils.EmpiricalMeasurementDistribution;
import infodynamics.utils.EmpiricalNullDistributionComputer;
import infodynamics.utils.MatrixUtils;
import javax.swing.BorderFactory;
@ -89,13 +90,16 @@ public abstract class AutoAnalyser extends JFrame
// Set options for the Calculator type:
public final static String CALC_TYPE_DISCRETE = "Discrete";
// Child classes must define options for other calculator types
// and initialise the calcTypes array and unitsForEachCalc array
protected String[] calcTypes;
protected String[] unitsForEachCalc;
// Set additional general options for the Calculator type:
public final static String CALC_TYPE_GAUSSIAN = "Gaussian";
public final static String CALC_TYPE_KRASKOV = "Kraskov (KSG)";
public final static String CALC_TYPE_KERNEL = "Kernel";
protected String[] calcTypes = {
CALC_TYPE_DISCRETE, CALC_TYPE_GAUSSIAN,
CALC_TYPE_KRASKOV, CALC_TYPE_KERNEL};
protected String[] unitsForEachCalc = {"bits", "nats", "nats", "bits"};
public final static String CALC_TYPE_KOZ_LEO = "Kozachenko-Leonenko";
// Properties for each calculator
protected static final String DISCRETE_PROPNAME_BASE = "base";
@ -107,16 +111,15 @@ public abstract class AutoAnalyser extends JFrame
protected String[] commonContPropertyNames;
protected String[] commonContPropertiesFieldNames;
protected String[] commonContPropertyDescriptions;
protected String[] gaussianProperties;
protected String[] gaussianPropertiesFieldNames;
protected String[] gaussianPropertyDescriptions;
protected String[] kernelProperties;
protected String[] kernelPropertiesFieldNames;
protected String[] kernelPropertyDescriptions;
protected String[] kraskovProperties;
protected String[] kraskovPropertiesFieldNames;
protected String[] kraskovPropertyDescriptions;
// Children can define properties for specific continuous
// calculators
// Number of variables that this measure operates on (1 to 3)
protected int numVariables = 1;
// Labels for each of the fields to enter the column number for the variables.
// Should be overridden by the child classes.
protected String[] variableColNumLabels = null;
// Store which calculator type we're using:
@SuppressWarnings("rawtypes")
protected Class calcClass = null;
@ -128,6 +131,11 @@ public abstract class AutoAnalyser extends JFrame
protected String measureAcronym = null;
// String to describe the relationship between the variables
// being measured here, with format tokens %%d in order for
// each variable. To be assigned by the child class.
protected String variableRelationshipFormatString = null;
protected JButton computeButton;
protected JButton openDataButton;
// Stores the current data file
@ -145,12 +153,19 @@ public abstract class AutoAnalyser extends JFrame
// Number of rows and columns of the data:
protected int dataRows = 0;
protected int dataColumns = 0;
// Source column field
protected JTextField sourceColTextField;
// Destination column field
protected JTextField destColTextField;
// CheckBox for "all pairs?"
protected JCheckBox allPairsCheckBox;
// Boolean for whether we include the all combinations checkbox and label on the GUI
// (default false). Child classes can alter this in makeSpecificInitialisations()
protected boolean useAllCombosCheckBox = false;
// Which word should be used to describe combinations for this measure? "pairs", "variables", etc?
// Child classes should override this.
protected String wordForCombinations = null;
// CheckBox for "all variables?" OR "all pairs?"
protected JCheckBox allCombosCheckBox;
// Variable text fields
protected JTextField[] variableColTextFields;
// Boolean for whether we include the statistical significance checkbox and label on the GUI
// (default false). Child classes can alter this in makeSpecificInitialisations()
protected boolean useStatSigCheckBox = false;
// CheckBox for statistical significance
protected JCheckBox statSigCheckBox;
// CheckBox for statistical significance analytically
@ -252,7 +267,7 @@ public abstract class AutoAnalyser extends JFrame
Image watermarkImage = (new ImageIcon("JIDT-logo-watermark.png")).getImage();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1100,640);
setSize(1100,670);
setTitle(appletTitle);
// Centre in the middle of the screen
setLocationRelativeTo(null);
@ -262,7 +277,7 @@ public abstract class AutoAnalyser extends JFrame
calcTypeLabel.setToolTipText("Select estimator type. \"Discrete\" is for discrete or pre-binned data; all others for continuous data.");
calcTypeLabel.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
calcTypeComboBox = (JComboBox<String>) new JComboBox<String>(calcTypes);
calcTypeComboBox.setSelectedIndex(2); // Select Kraskov by default
calcTypeComboBox.setSelectedIndex(2); // Select 2nd continuous estimator by default
calcTypeComboBox.addActionListener(this);
// Don't set an empty border as it becomes clickable as well,
// we'll use an empty label instead
@ -270,7 +285,7 @@ public abstract class AutoAnalyser extends JFrame
// Create the fields for the data file
JLabel fileLabel = new JLabel("Data file:");
fileLabel.setToolTipText("Must be a text file of time-series values with time increasing in rows, and variables along columns");
fileLabel.setToolTipText("Must be a text file of samples or time-series values with time/sample increasing in rows, and variables along columns");
dataFileTextField = new JTextField(30);
dataFileTextField.setEnabled(false);
dataFileTextField.addMouseListener(this);
@ -283,29 +298,29 @@ public abstract class AutoAnalyser extends JFrame
dataFileDescriptorLabel.setHorizontalAlignment(JLabel.RIGHT);
dataFileDescriptorLabel.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
// From column:
JLabel sourceLabel = new JLabel("Source column:");
sourceLabel.setToolTipText("First column is 0.");
sourceColTextField = new JTextField(5);
sourceColTextField.setEnabled(true);
sourceColTextField.setText("0");
// Must add document listener, not add action listener
sourceColTextField.getDocument().addDocumentListener(this);
// To column:
JLabel destLabel = new JLabel("Destination column:");
destLabel.setToolTipText("First column is 0.");
destLabel.setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
destColTextField = new JTextField(5);
destColTextField.setEnabled(true);
destColTextField.setText("1");
destColTextField.getDocument().addDocumentListener(this);
// We define the all combos checkbox, but we won't add it later
// if it's not used for this measure type.
allCombosCheckBox = new JCheckBox("All " + wordForCombinations + "?");
allCombosCheckBox.setToolTipText("Compute for all column " + wordForCombinations + "?");
allCombosCheckBox.addChangeListener(this);
variableColTextFields = new JTextField[numVariables];
JLabel[] labels = new JLabel[numVariables];
for (int i = 0; i < numVariables; i++) {
labels[i] = new JLabel(variableColNumLabels[i] + " column:");
labels[i].setToolTipText("First column is 0.");
// This border was only done on the 2nd variable before, so may need
// to restrict its use:
labels[i].setBorder(BorderFactory.createEmptyBorder(0,0,10,0));
variableColTextFields[i] = new JTextField(5);
variableColTextFields[i].setEnabled(true);
variableColTextFields[i].setText(Integer.toString(i));
// Must add document listener, not add action listener
variableColTextFields[i].getDocument().addDocumentListener(this);
}
// Checkbox for all pairs
allPairsCheckBox = new JCheckBox("All pairs?");
allPairsCheckBox.setToolTipText("Compute for all pairs of columns?");
allPairsCheckBox.addChangeListener(this);
// CheckBox for statistical signficance
// We define the CheckBox for statistical signficance,
// but we won't add it later if it's not used for this measure type.
statSigCheckBox = new JCheckBox("Add stat. signif.?");
statSigCheckBox.setToolTipText("Compute the null surrogate distribution under the null hypothesis that source and target are not related?");
statSigCheckBox.addChangeListener(this);
@ -465,42 +480,40 @@ public abstract class AutoAnalyser extends JFrame
paramsPanel.add(dataFileDescriptorLabel, c);
// Add the all pairs label and checkbox
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.gridx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
paramsPanel.add(allPairsCheckBox, c);
c.gridx = -1; // reset to no indication
// Add the source selector
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last
c.fill = GridBagConstraints.NONE; //reset to default
c.weightx = 0.0; //reset to default
paramsPanel.add(sourceLabel, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
paramsPanel.add(sourceColTextField, c);
// Add the destination selector
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last
c.fill = GridBagConstraints.NONE; //reset to default
c.weightx = 0.0; //reset to default
paramsPanel.add(destLabel, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
paramsPanel.add(destColTextField, c);
if (useAllCombosCheckBox) {
// Add the all combos label and checkbox
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.gridx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
paramsPanel.add(allCombosCheckBox, c);
c.gridx = -1; // reset to no indication
}
// Add the CheckBoxes for statistical significance checks:
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last
c.fill = GridBagConstraints.NONE; //reset to default
c.weightx = 0.0; //reset to default
paramsPanel.add(statSigCheckBox, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
paramsPanel.add(statSigAnalyticCheckBox, c);
// Add the column number selectors
for (int i = 0; i < numVariables; i++) {
// Add the column selector for variable i
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last
c.fill = GridBagConstraints.NONE; //reset to default
c.weightx = 0.0; //reset to default
paramsPanel.add(labels[i], c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
paramsPanel.add(variableColTextFields[i], c);
}
if (useStatSigCheckBox) {
// Add the CheckBoxes for statistical significance checks:
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last
c.fill = GridBagConstraints.NONE; //reset to default
c.weightx = 0.0; //reset to default
paramsPanel.add(statSigCheckBox, c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
paramsPanel.add(statSigAnalyticCheckBox, c);
}
// Add dummy label for spacing
paramsPanel.add(dummyLabel1, c);
@ -579,7 +592,6 @@ public abstract class AutoAnalyser extends JFrame
statSigAnalyticCheckBox.setSelected(false);
statSigAnalyticCheckBox.setEnabled(false);
}
}
// Else nothing extra to do
}
@ -673,34 +685,24 @@ public abstract class AutoAnalyser extends JFrame
return;
}
int singleSourceColumn = -1, singleDestColumn = -1;
Vector<int[]> sourceDestPairs = new Vector<int[]>();
if (allPairsCheckBox.isSelected()) {
// We're doing all pairs
for (int s = 0; s < dataColumns; s++) {
for (int d = 0; d < dataColumns; d++) {
sourceDestPairs.add(new int[] {s, d});
int[] singleCalcColumns = new int[numVariables];
Vector<int[]> variableCombinations = new Vector<int[]>();
if (allCombosCheckBox.isSelected()) {
// We're doing all combinations
fillOutAllCombinations(variableCombinations);
} else {
// we're doing a single combination
for (int i = 0; i < numVariables; i++) {
singleCalcColumns[i] = Integer.parseInt(variableColTextFields[i].getText());
if ((singleCalcColumns[i] < 0) || (singleCalcColumns[i] >= dataColumns)) {
JOptionPane.showMessageDialog(this,
String.format("%s column must be between 0 and %d for this data set",
variableColNumLabels[i], dataColumns-1));
resultsLabel.setText(" ");
return;
}
}
} else {
// we're doing a single source-destination pair
singleSourceColumn = Integer.parseInt(sourceColTextField.getText());
singleDestColumn = Integer.parseInt(destColTextField.getText());
sourceDestPairs.add(new int[] {singleSourceColumn, singleDestColumn});
if ((singleSourceColumn < 0) || (singleSourceColumn >= dataColumns)) {
JOptionPane.showMessageDialog(this,
String.format("Source column must be between 0 and %d for this data set",
dataColumns-1));
resultsLabel.setText(" ");
return;
}
if ((singleDestColumn < 0) || (singleDestColumn >= dataColumns)) {
JOptionPane.showMessageDialog(this,
String.format("Destination column must be between 0 and %d for this data set",
dataColumns-1));
resultsLabel.setText(" ");
return;
}
variableCombinations.add(singleCalcColumns);
}
// Generate headers:
@ -745,8 +747,8 @@ public abstract class AutoAnalyser extends JFrame
try{
// Create both discrete and continuous calculators to make
// following code simpler:
ChannelCalculatorCommon calcContinuous = null;
ChannelCalculatorDiscrete calcDiscrete = null;
InfoMeasureCalculatorContinuous calcContinuous = null;
InfoMeasureCalculatorDiscrete calcDiscrete = null;
// Construct an instance of the selected calculator:
String javaConstructorLine = null;
@ -781,6 +783,14 @@ public abstract class AutoAnalyser extends JFrame
calcContinuous.getClass().getSimpleName() + "\n";
matlabConstructorLine = "calc = javaObject('infodynamics.measures.continuous.kernel." +
calcContinuous.getClass().getSimpleName() + "');\n";
} else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KOZ_LEO)) {
// Cover the calculator and any references to other classes
javaCode.append("import infodynamics.measures.continuous.kozachenko.*;\n");
javaConstructorLine = " calc = new " + calcContinuous.getClass().getSimpleName() + "();\n";
pythonPreConstructorLine = "calcClass = JPackage(\"infodynamics.measures.continuous.kozachenko\")." +
calcContinuous.getClass().getSimpleName() + "\n";
matlabConstructorLine = "calc = javaObject('infodynamics.measures.continuous.kozachenko." +
calcContinuous.getClass().getSimpleName() + "');\n";
} else {
throw new Exception("No recognised calculator selected: " +
selectedCalcType);
@ -798,15 +808,21 @@ public abstract class AutoAnalyser extends JFrame
javaCode.append(" ArrayFileReader afr = new ArrayFileReader(dataFile);\n");
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
javaCode.append(" int[][] data = afr.getInt2DMatrix();\n");
if (! allPairsCheckBox.isSelected()) {
javaCode.append(" int[] source = MatrixUtils.selectColumn(data, " + singleSourceColumn + ");\n");
javaCode.append(" int[] dest = MatrixUtils.selectColumn(data, " + singleDestColumn + ");\n\n");
if (! allCombosCheckBox.isSelected()) {
for (int i=0; i < numVariables; i++) {
javaCode.append(" int[] " + variableColNumLabels[i].toLowerCase() +
" = MatrixUtils.selectColumn(data, " + singleCalcColumns[i] + ");\n");
}
javaCode.append("\n");
}
} else {
javaCode.append(" double[][] data = afr.getDouble2DMatrix();\n");
if (! allPairsCheckBox.isSelected()) {
javaCode.append(" double[] source = MatrixUtils.selectColumn(data, " + singleSourceColumn + ");\n");
javaCode.append(" double[] dest = MatrixUtils.selectColumn(data, " + singleDestColumn + ");\n\n");
if (! allCombosCheckBox.isSelected()) {
for (int i=0; i < numVariables; i++) {
javaCode.append(" double[] " + variableColNumLabels[i].toLowerCase() +
" = MatrixUtils.selectColumn(data, " + singleCalcColumns[i] + ");\n");
}
javaCode.append("\n");
}
}
// 2. Python
@ -818,21 +834,38 @@ public abstract class AutoAnalyser extends JFrame
}
pythonCode.append("# As numpy array:\n");
pythonCode.append("data = numpy.array(dataRaw)\n");
if (! allPairsCheckBox.isSelected()) {
pythonCode.append("source = JArray(JInt, 1)(data[:," + singleSourceColumn + "].tolist())\n");
pythonCode.append("dest = JArray(JInt, 1)(data[:," + singleDestColumn + "].tolist())\n\n");
if (! allCombosCheckBox.isSelected()) {
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
for (int i=0; i < numVariables; i++) {
pythonCode.append(variableColNumLabels[i].toLowerCase() + " = JArray(JInt, 1)(data[:," +
singleCalcColumns[i] + "].tolist())\n");
}
pythonCode.append("\n");
} else {
for (int i=0; i < numVariables; i++) {
pythonCode.append(variableColNumLabels[i].toLowerCase() + " = data[:," +
singleCalcColumns[i] + "]\n");
}
pythonCode.append("\n");
}
}
// 3. Matlab
matlabCode.append("% " + loadDataComment);
matlabCode.append("data = load('" + dataFile.getAbsolutePath() + "');\n");
if (! allPairsCheckBox.isSelected()) {
if (! allCombosCheckBox.isSelected()) {
matlabCode.append("% Column indices start from 1 in Matlab:\n");
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
matlabCode.append("source = octaveToJavaIntArray(data(:," + (singleSourceColumn+1) + "));\n");
matlabCode.append("dest = octaveToJavaIntArray(data(:," + (singleDestColumn+1) + "));\n\n");
for (int i=0; i < numVariables; i++) {
matlabCode.append(variableColNumLabels[i].toLowerCase() + " = octaveToJavaIntArray(data(:," +
(singleCalcColumns[i]+1) + "));\n");
}
matlabCode.append("\n");
} else {
matlabCode.append("source = octaveToJavaDoubleArray(data(:," + (singleSourceColumn+1) + "));\n");
matlabCode.append("dest = octaveToJavaDoubleArray(data(:," + (singleDestColumn+1) + "));\n\n");
for (int i=0; i < numVariables; i++) {
matlabCode.append(variableColNumLabels[i].toLowerCase() + " = octaveToJavaDoubleArray(data(:," +
(singleCalcColumns[i]+1) + "));\n");
}
matlabCode.append("\n");
}
}
@ -936,59 +969,46 @@ public abstract class AutoAnalyser extends JFrame
String javaPrefix = " ";
String pythonPrefix = "";
String matlabPrefix = "";
if (sourceDestPairs.size() > 1) {
// We're doing all pairs
StringBuffer extraFormatTerms = new StringBuffer();
if (variableCombinations.size() > 1) {
// We're doing all combinations.
// Set up the loops for these:
String[] columnVariables = setUpLoopsForAllCombos(javaCode, pythonCode, matlabCode);
// Get the indents right from here on,
// and prepare a string of the column labels for
// each variable, to be used in later formatting.
for (int i = 0; i < numVariables; i++) {
javaPrefix += " ";
pythonPrefix += "\t";
matlabPrefix += "\t";
extraFormatTerms.append(columnVariables[i] + ", ");
}
// Set up loops in the code:
// 1. Java code
javaCode.append(" \n");
javaCode.append(" // Compute for all pairs:\n");
javaCode.append(" for (int s = 0; s < " + dataColumns +
"; s++) {\n");
javaCode.append(" for (int d = 0; d < " + dataColumns +
"; d++) {\n");
javaPrefix = " ";
javaCode.append(javaPrefix + "// For each source-dest pair:\n");
javaCode.append(javaPrefix + "if (s == d) {\n");
javaCode.append(javaPrefix + " continue;\n");
javaCode.append(javaPrefix + "}\n");
// 2. Python code
pythonCode.append("\n");
pythonCode.append("# Compute for all pairs:\n");
pythonCode.append("for s in range(" + dataColumns + "):\n");
pythonCode.append("\tfor d in range(" + dataColumns + "):\n");
pythonPrefix = "\t\t";
pythonCode.append(pythonPrefix+ "# For each source-dest pair:\n");
pythonCode.append(pythonPrefix + "if (s == d):\n");
pythonCode.append(pythonPrefix + "\tcontinue\n");
// 3. Matlab code
matlabCode.append("\n");
matlabCode.append("% Compute for all pairs:\n");
matlabCode.append("for s = 1:" + dataColumns + "\n");
matlabCode.append("\tfor d = 1:" + dataColumns + "\n");
matlabPrefix = "\t\t";
matlabCode.append(matlabPrefix + "% For each source-dest pair:\n");
matlabCode.append(matlabPrefix + "if (s == d)\n");
matlabCode.append(matlabPrefix + "\tcontinue;\n");
matlabCode.append(matlabPrefix + "end\n");
// Read in the data for these columns for all pairs
matlabCode.append(matlabPrefix + "% Column indices start from 1 in Matlab:\n");
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
javaCode.append(javaPrefix + "int[] source = MatrixUtils.selectColumn(data, s);\n");
javaCode.append(javaPrefix + "int[] dest = MatrixUtils.selectColumn(data, d);\n\n");
matlabCode.append(matlabPrefix + "source = octaveToJavaIntArray(data(:, s));\n");
matlabCode.append(matlabPrefix + "dest = octaveToJavaIntArray(data(:, d));\n\n");
pythonCode.append(pythonPrefix + "source = JArray(JInt, 1)(data[:, s].tolist())\n");
pythonCode.append(pythonPrefix + "dest = JArray(JInt, 1)(data[:, d].tolist())\n\n");
for (int i = 0; i < numVariables; i++) {
javaCode.append(javaPrefix + "int[] " + variableColNumLabels[i].toLowerCase() +
" = MatrixUtils.selectColumn(data, " + columnVariables[i] + ");\n");
matlabCode.append(matlabPrefix + variableColNumLabels[i].toLowerCase() +
" = octaveToJavaIntArray(data(:, " + columnVariables[i] + "));\n");
pythonCode.append(pythonPrefix + variableColNumLabels[i].toLowerCase() +
" = JArray(JInt, 1)(data[:, " + columnVariables[i] + "].tolist())\n");
}
} else {
javaCode.append(javaPrefix + "double[] source = MatrixUtils.selectColumn(data, s);\n");
javaCode.append(javaPrefix + "double[] dest = MatrixUtils.selectColumn(data, d);\n\n");
matlabCode.append(matlabPrefix + "source = octaveToJavaDoubleArray(data(:, s));\n");
matlabCode.append(matlabPrefix + "dest = octaveToJavaDoubleArray(data(:, d));\n\n");
pythonCode.append(pythonPrefix + "source = data[:, s]\n");
pythonCode.append(pythonPrefix + "dest = data[:, d]\n\n");
for (int i = 0; i < numVariables; i++) {
javaCode.append(javaPrefix + "double[] " + variableColNumLabels[i].toLowerCase() +
" = MatrixUtils.selectColumn(data, " + columnVariables[i] + ");\n");
matlabCode.append(matlabPrefix + variableColNumLabels[i].toLowerCase() +
" = octaveToJavaDoubleArray(data(:, " + columnVariables[i] + "));\n");
pythonCode.append(pythonPrefix + variableColNumLabels[i].toLowerCase() +
" = data[:, " + columnVariables[i] + "]\n");
}
}
javaCode.append("\n");
matlabCode.append("\n");
pythonCode.append("\n");
} else {
// For a single pair, we don't need to set up loops, and
// we've already read in the data to source and dest variables above
@ -1011,15 +1031,23 @@ public abstract class AutoAnalyser extends JFrame
} else {
setObservationsMethod = "setObservations";
}
StringBuffer methodArguments = new StringBuffer();
for (int i = 0; i < numVariables; i++) {
methodArguments.append(variableColNumLabels[i].toLowerCase());
if (i < numVariables - 1) {
// There are more variables to come:
methodArguments.append(", ");
}
}
// 1. Java
javaCode.append(javaPrefix + "// " + supplyDataComment);
javaCode.append(javaPrefix + "calc." + setObservationsMethod + "(source, dest);\n");
javaCode.append(javaPrefix + "calc." + setObservationsMethod + "(" + methodArguments + ");\n");
// 2. Python
pythonCode.append(pythonPrefix + "# " + supplyDataComment);
pythonCode.append(pythonPrefix + "calc." + setObservationsMethod + "(source, dest)\n");
pythonCode.append(pythonPrefix + "calc." + setObservationsMethod + "(" + methodArguments + ")\n");
// 3. Matlab
matlabCode.append(matlabPrefix + "% " + supplyDataComment);
matlabCode.append(matlabPrefix + "calc." + setObservationsMethod + "(source, dest);\n");
matlabCode.append(matlabPrefix + "calc." + setObservationsMethod + "(" + methodArguments + ");\n");
// Compute the result
String computeComment = "5. Compute the estimate:\n";
@ -1030,15 +1058,16 @@ public abstract class AutoAnalyser extends JFrame
matlabCode.append(matlabPrefix + "% " + computeComment);
matlabCode.append(matlabPrefix + "result = calc.computeAverageLocalOfObservations();\n");
String resultsPrefixString, extraFormatTerms;
if (sourceDestPairs.size() > 1) {
resultsPrefixString = String.format(measureAcronym + "_%s(col_%%d -> col_%%d) = ",
selectedCalcType);
extraFormatTerms = "s, d, ";
String resultsPrefixString;
if (variableCombinations.size() > 1) {
resultsPrefixString = String.format(measureAcronym + "_%s(%s) = ",
selectedCalcType, variableRelationshipFormatString);
} else {
resultsPrefixString = String.format(measureAcronym + "_%s(col_%d -> col_%d) = ",
selectedCalcType, singleSourceColumn, singleDestColumn);
extraFormatTerms = "";
resultsPrefixString = String.format(measureAcronym + "_%s(%s) = ",
selectedCalcType,
formatStringWithColumnNumbers(
variableRelationshipFormatString,
singleCalcColumns));
}
String resultsSuffixString = "";
@ -1076,18 +1105,11 @@ public abstract class AutoAnalyser extends JFrame
"%.4f " + units + resultsSuffixString + "\\n', ...\n\t" + matlabPrefix +
extraFormatTerms + "result" + statSigFormatTerms + ");\n");
if (sourceDestPairs.size() > 1) {
// We're doing all pairs
if (variableCombinations.size() > 1) {
// We're doing all combos
// Finalise the loops in the code:
// 1. Java code
javaCode.append(" }\n");
javaCode.append(" }\n");
// 2. Python code
// Nothing to do
// 3. Matlab code
matlabCode.append("\tend\n");
matlabCode.append("end\n");
finaliseLoopsForAllCombos(javaCode, pythonCode, matlabCode);
// And tell the user to see results in the console:
resultsLabel.setText("See console for all pairs calculation results");
@ -1126,11 +1148,11 @@ public abstract class AutoAnalyser extends JFrame
// Now make our own calculations here:
// TODO make the calculation in a separate thread, and have a
// button to cancel the calculation whilst it's running
for (int[] pair : sourceDestPairs) {
int sourceColumn = pair[0];
int destColumn = pair[1];
for (int[] columnCombo : variableCombinations) {
if (sourceColumn == destColumn) {
if ((variableCombinations.size() > 1) && skipColumnCombo(columnCombo)) {
System.out.print("Skipping column combo ");
MatrixUtils.printArray(System.out, columnCombo);
continue;
}
@ -1141,25 +1163,8 @@ public abstract class AutoAnalyser extends JFrame
calcContinuous.initialise();
}
// Set observations
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
calcDiscrete.addObservations(
MatrixUtils.selectColumn(dataDiscrete, sourceColumn),
MatrixUtils.selectColumn(dataDiscrete, destColumn));
} else {
// TODO We should be able to directly call setObservations(double[], double[])
// here but we can't right now because ChannelCalculator does not
// define this method. It would be complicated to fix this
// because it involves Conditional MI calculator it seems.
// Revisit this later -- for now fix by deferring to child classes
// calcContinuous.setObservations(
// MatrixUtils.selectColumn(data, sourceColumn),
// MatrixUtils.selectColumn(data, destColumn));
setObservations(calcContinuous,
MatrixUtils.selectColumn(data, sourceColumn),
MatrixUtils.selectColumn(data, destColumn));
}
setObservations(calcDiscrete, calcContinuous, columnCombo);
// Compute the result:
double result;
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
@ -1189,11 +1194,15 @@ public abstract class AutoAnalyser extends JFrame
} else {
// permutation test of statistical significance:
EmpiricalMeasurementDistribution measDist;
EmpiricalNullDistributionComputer empiricalNullDistCalc;
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
measDist = calcDiscrete.computeSignificance(numPermutationsToCheck);
empiricalNullDistCalc =
(EmpiricalNullDistributionComputer) calcDiscrete;
} else {
measDist = calcContinuous.computeSignificance(numPermutationsToCheck);
empiricalNullDistCalc =
(EmpiricalNullDistributionComputer) calcContinuous;
}
measDist = empiricalNullDistCalc.computeSignificance(numPermutationsToCheck);
resultsSuffixStringFormatted = String.format(
resultsSuffixString,
measDist.getMeanOfDistribution(),
@ -1204,11 +1213,16 @@ public abstract class AutoAnalyser extends JFrame
}
String resultsText;
if (sourceDestPairs.size() > 1) {
if (variableCombinations.size() > 1) {
// We're doing all pairs
resultsText = String.format(
resultsPrefixString + "%.4f %s" + resultsSuffixStringFormatted,
sourceColumn, destColumn, result, units);
// OLD:
// resultsText = String.format(
// resultsPrefixString + "%.4f %s" + resultsSuffixStringFormatted,
// sourceColumn, destColumn, result, units);
// NEW:
resultsText = String.format(formatStringWithColumnNumbers(
resultsPrefixString + "%%.4f %%s" + resultsSuffixStringFormatted,
columnCombo), result, units);
} else {
resultsText = String.format(
resultsPrefixString + "%.4f %s" + resultsSuffixStringFormatted,
@ -1219,7 +1233,7 @@ public abstract class AutoAnalyser extends JFrame
System.out.println(resultsText);
}
if ((sourceDestPairs.size() == 1) &&
if ((variableCombinations.size() == 1) &&
!selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
// Read the current property values back out (in case of
// automated parameter assignment)
@ -1249,11 +1263,64 @@ public abstract class AutoAnalyser extends JFrame
}
/**
* Method to allow child to fill out what all of the variable combinations would be that
* would be evaluated by this measure
*
* @param variableCombinations
*/
protected abstract void fillOutAllCombinations(Vector<int[]> variableCombinations);
/**
* Method to allow child classes to set up the loops over all combinations of
* columns
*
* @param javaCode
* @param pythonCode
* @param matlabCode
* @return A string array with the names used for the variables iterating over
* each column
*/
protected abstract String[] setUpLoopsForAllCombos(StringBuffer javaCode,
StringBuffer pythonCode, StringBuffer matlabCode);
/**
* Method to allow child classes to finalise the loops over all combinations of
* columns
*
* @param javaCode
* @param pythonCode
* @param matlabCode
*/
protected abstract void finaliseLoopsForAllCombos(StringBuffer javaCode,
StringBuffer pythonCode, StringBuffer matlabCode);
/**
* Method to allow child classes to format a string with
* an array of ints for the column numbers (since the number
* of these is variable, it's easier if the child classes do this)
*
* @param columnNumbers array of column numbers used to identify the variables.
* @return
*/
protected abstract String formatStringWithColumnNumbers(String formatStr, int[] columnNumbers);
/**
* Check whether this measure type should skip this particular
* combination of columns or not
* (e.g. for a pairwise measurement we do want to skip
* where the two columns are equal).
*
* @param columnCombo
* @return
*/
protected abstract boolean skipColumnCombo(int[] columnCombo);
/**
* Method to assign and initialise our continuous calculator class
* @throws Exception
*/
protected abstract ChannelCalculatorCommon assignCalcObjectContinuous(String selectedCalcType) throws Exception;
protected abstract InfoMeasureCalculatorContinuous assignCalcObjectContinuous(String selectedCalcType) throws Exception;
/**
* Method to assign and initialise our discrete calculator class
@ -1269,11 +1336,11 @@ public abstract class AutoAnalyser extends JFrame
*
*/
protected class DiscreteCalcAndArguments {
ChannelCalculatorDiscrete calc;
InfoMeasureCalculatorDiscrete calc;
int base;
String arguments;
DiscreteCalcAndArguments(ChannelCalculatorDiscrete calc, int base,
DiscreteCalcAndArguments(InfoMeasureCalculatorDiscrete calc, int base,
String arguments) {
this.calc = calc;
this.base = base;
@ -1281,16 +1348,17 @@ public abstract class AutoAnalyser extends JFrame
}
}
/**
/**
* Method to set the observations on the underlying calculator
*
* @param calc
* @param source
* @param dest
* @param calcDiscrete
* @param calcContinuous
* @param columnCombo int array for the columns of data being computed with.
* @throws Exception
*/
protected abstract void setObservations(ChannelCalculatorCommon calc,
double[] source, double[] dest) throws Exception;
protected abstract void setObservations(InfoMeasureCalculatorDiscrete calcDiscrete,
InfoMeasureCalculatorContinuous calcContinuous,
int[] columnCombo) throws Exception;
/**
@ -1417,45 +1485,23 @@ public abstract class AutoAnalyser extends JFrame
System.out.println("Getting calc properties");
String selectedCalcType = (String)
calcTypeComboBox.getSelectedItem();
String[] classSpecificPropertyNames = null;
String[] classSpecificPropertiesFieldNames = null;
String[] classSpecificPropertyDescriptions = null;
ChannelCalculatorCommon calc = null;
CalcProperties calcProperties = null;
try {
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
calcClass = discreteClass;
calc = null; // Not used
classSpecificPropertyNames = discreteProperties;
classSpecificPropertiesFieldNames = null; // Not used
classSpecificPropertyDescriptions = discretePropertyDescriptions;
} else {
calc = assignCalcObjectContinuous(selectedCalcType);
calcClass = calc.getClass();
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_GAUSSIAN)) {
classSpecificPropertyNames = gaussianProperties;
classSpecificPropertiesFieldNames = gaussianPropertiesFieldNames;
classSpecificPropertyDescriptions = gaussianPropertyDescriptions;
} else if (selectedCalcType.startsWith(CALC_TYPE_KRASKOV)) {
// The if statement will work for both MI Kraskov calculators
classSpecificPropertyNames = kraskovProperties;
classSpecificPropertiesFieldNames = kraskovPropertiesFieldNames;
classSpecificPropertyDescriptions = kraskovPropertyDescriptions;
} else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KERNEL)) {
classSpecificPropertyNames = kernelProperties;
classSpecificPropertiesFieldNames = kernelPropertiesFieldNames;
classSpecificPropertyDescriptions = kernelPropertyDescriptions;
} else {
calcClass = null;
throw new Exception("No recognised calculator selected: " +
selectedCalcType);
}
}
calcProperties = assignCalcProperties(selectedCalcType);
} catch (Exception ex) {
ex.printStackTrace(System.err);
JOptionPane.showMessageDialog(this,
ex.getMessage());
resultsLabel.setText("Cannot load requested calculator");
}
String[] classSpecificPropertyNames =
calcProperties.classSpecificPropertyNames;
String[] classSpecificPropertiesFieldNames =
calcProperties.classSpecificPropertiesFieldNames;
String[] classSpecificPropertyDescriptions =
calcProperties.classSpecificPropertyDescriptions;
calcClass = calcProperties.calcClass;
Object calc = calcProperties.calc;
// Now get all of the possible properties for this class:
propertyNames = new Vector<String>();
@ -1513,20 +1559,65 @@ public abstract class AutoAnalyser extends JFrame
// Now extract the default values for all of these properties:
propertyValues = new HashMap<String,String>();
for (String propName : propertyNames) {
String defaultPropValue = null;
try {
defaultPropValue = calc.getProperty(propName);
InfoMeasureCalculatorContinuous calcCont =
(InfoMeasureCalculatorContinuous) calc;
String propValue = calcCont.getProperty(propName);
propertyValues.put(propName, propValue);
} catch (Exception ex) {
ex.printStackTrace(System.err);
JOptionPane.showMessageDialog(this,
ex.getMessage());
propertyValues.put(propName, "Cannot find a value");
}
propertyValues.put(propName, defaultPropValue);
}
}
}
/**
* Structure to return calculator properties
*
* @author Joseph Lizier
*
*/
protected class CalcProperties {
// An default instantiation of the required calculator object
// for continuous data (this is not used for discrete)
InfoMeasureCalculatorContinuous calc;
// Class of the required calculator
@SuppressWarnings("rawtypes")
Class calcClass;
String[] classSpecificPropertyNames;
String[] classSpecificPropertiesFieldNames;
String[] classSpecificPropertyDescriptions;
}
/**
* Assign the property details for the calculator in use.
* Should be overridden by child classes, though they
* can refer here to handle discrete calculators.
*
* @param selectedCalcType String name of the calculator
* @return
* @throws Exception
*/
protected CalcProperties assignCalcProperties(String selectedCalcType)
throws Exception {
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
CalcProperties calcProperties = new CalcProperties();
calcProperties.calcClass = discreteClass;
calcProperties.calc = null; // Not used
calcProperties.classSpecificPropertyNames = discreteProperties;
calcProperties.classSpecificPropertiesFieldNames = null; // Not used
calcProperties.classSpecificPropertyDescriptions = discretePropertyDescriptions;
return calcProperties;
} else {
// We don't handle any other calculators here
return null;
}
}
@Override
public void changedUpdate(DocumentEvent e) {
// Source or dest col number updated
@ -1594,21 +1685,16 @@ public abstract class AutoAnalyser extends JFrame
// so we'll just act on potential changes from both.
// This won't cause a problem here
if (e.getSource() == allPairsCheckBox) {
if (e.getSource() == allCombosCheckBox) {
// "All pairs" checkbox -- update in case changed:
if (allPairsCheckBox.isSelected()) {
sourceColTextField.setEnabled(false);
destColTextField.setEnabled(false);
if (allCombosCheckBox.isSelected()) {
for (int i = 0; i < numVariables; i++) {
variableColTextFields[i].setEnabled(false);
}
} else {
sourceColTextField.setEnabled(true);
destColTextField.setEnabled(true);
}
} else if (e.getSource() == computeResultCheckBox) {
// Compute checkbox -- update in case changed:
if (computeResultCheckBox.isSelected()) {
computeButton.setText(buttonTextCodeAndCompute);
} else {
computeButton.setText(buttonTextCodeOnly);
for (int i = 0; i < numVariables; i++) {
variableColTextFields[i].setEnabled(true);
}
}
} else if (e.getSource() == statSigCheckBox) {
System.out.println("StatSigCheckBox state changed to " + statSigCheckBox.isSelected());
@ -1626,9 +1712,16 @@ public abstract class AutoAnalyser extends JFrame
statSigAnalyticCheckBox.setSelected(false);
statSigAnalyticCheckBox.setEnabled(false);
}
} else if (e.getSource() == computeResultCheckBox) {
// Compute checkbox -- update in case changed:
if (computeResultCheckBox.isSelected()) {
computeButton.setText(buttonTextCodeAndCompute);
} else {
computeButton.setText(buttonTextCodeOnly);
}
}
}
/**
* Checks whether the current calculator class implements the
* AnalyticNullDistributionComputer interface

View File

@ -0,0 +1,207 @@
/*
* Java Information Dynamics Toolkit (JIDT)
* Copyright (C) 2015, Joseph T. Lizier
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package infodynamics.demos.autoanalysis;
import infodynamics.measures.continuous.ChannelCalculator;
import infodynamics.measures.continuous.InfoMeasureCalculatorContinuous;
import infodynamics.measures.discrete.ChannelCalculatorDiscrete;
import infodynamics.measures.discrete.InfoMeasureCalculatorDiscrete;
import infodynamics.utils.MatrixUtils;
import java.util.Vector;
/**
* This abstract class provides a GUI to build a simple calculation
* over a source-target channel,
* and supply the code to execute it.
* Child classes fix this to a TE or MI calculation.
*
*
* @author Joseph Lizier
*
*/
public abstract class AutoAnalyserChannelCalculator extends AutoAnalyser {
/**
* Need serialVersionUID to be serializable
*/
private static final long serialVersionUID = 1L;
// Property names for specific continuous calculators:
protected String[] gaussianProperties;
protected String[] gaussianPropertiesFieldNames;
protected String[] gaussianPropertyDescriptions;
protected String[] kernelProperties;
protected String[] kernelPropertiesFieldNames;
protected String[] kernelPropertyDescriptions;
protected String[] kraskovProperties;
protected String[] kraskovPropertiesFieldNames;
protected String[] kraskovPropertyDescriptions;
/**
* Constructor to initialise the GUI for a channel calculator
*/
protected void makeSpecificInitialisations() {
numVariables = 2;
variableColNumLabels = new String[] {"Source", "Destination"};
useAllCombosCheckBox = true;
useStatSigCheckBox = true;
wordForCombinations = "pairs";
variableRelationshipFormatString = "col_%d -> col_%d";
}
@Override
protected void fillOutAllCombinations(Vector<int[]> variableCombinations) {
// All combinations here means all pairs
for (int s = 0; s < dataColumns; s++) {
for (int d = 0; d < dataColumns; d++) {
variableCombinations.add(new int[] {s, d});
}
}
}
@Override
protected String[] setUpLoopsForAllCombos(StringBuffer javaCode,
StringBuffer pythonCode, StringBuffer matlabCode) {
// Set up loops in the code:
// 1. Java code
javaCode.append(" \n");
javaCode.append(" // Compute for all pairs:\n");
javaCode.append(" for (int s = 0; s < " + dataColumns +
"; s++) {\n");
javaCode.append(" for (int d = 0; d < " + dataColumns +
"; d++) {\n");
String javaPrefix = " ";
javaCode.append(javaPrefix + "// For each source-dest pair:\n");
javaCode.append(javaPrefix + "if (s == d) {\n");
javaCode.append(javaPrefix + " continue;\n");
javaCode.append(javaPrefix + "}\n");
// 2. Python code
pythonCode.append("\n");
pythonCode.append("# Compute for all pairs:\n");
pythonCode.append("for s in range(" + dataColumns + "):\n");
pythonCode.append("\tfor d in range(" + dataColumns + "):\n");
String pythonPrefix = "\t\t";
pythonCode.append(pythonPrefix+ "# For each source-dest pair:\n");
pythonCode.append(pythonPrefix + "if (s == d):\n");
pythonCode.append(pythonPrefix + "\tcontinue\n");
// 3. Matlab code
matlabCode.append("\n");
matlabCode.append("% Compute for all pairs:\n");
matlabCode.append("for s = 1:" + dataColumns + "\n");
matlabCode.append("\tfor d = 1:" + dataColumns + "\n");
String matlabPrefix = "\t\t";
matlabCode.append(matlabPrefix + "% For each source-dest pair:\n");
matlabCode.append(matlabPrefix + "if (s == d)\n");
matlabCode.append(matlabPrefix + "\tcontinue;\n");
matlabCode.append(matlabPrefix + "end\n");
// Return the variables to index each column:
return new String[] {"s", "d"};
}
@Override
protected void finaliseLoopsForAllCombos(StringBuffer javaCode,
StringBuffer pythonCode, StringBuffer matlabCode) {
// 1. Java code
javaCode.append(" }\n");
javaCode.append(" }\n");
// 2. Python code
// Nothing to do
// 3. Matlab code
matlabCode.append("\tend\n");
matlabCode.append("end\n");
}
@Override
protected String formatStringWithColumnNumbers(String formatStr, int[] columnNumbers) {
// We format the source and target variable numbers into the
// return string here:
return String.format(formatStr,
columnNumbers[0], columnNumbers[1]);
}
@Override
protected boolean skipColumnCombo(int[] columnCombo) {
if (columnCombo[0] == columnCombo[1]) {
// source and destination columns are the same here,
// so don't compute the channel measure
return true;
}
return false;
}
@Override
protected void setObservations(InfoMeasureCalculatorDiscrete calcDiscrete,
InfoMeasureCalculatorContinuous calcContinuous,
int[] columnCombo) throws Exception {
String selectedCalcType = (String)
calcTypeComboBox.getSelectedItem();
int sourceColumn = columnCombo[0];
int destColumn = columnCombo[1];
// Set observations
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_DISCRETE)) {
ChannelCalculatorDiscrete cc = (ChannelCalculatorDiscrete) calcDiscrete;
cc.addObservations(
MatrixUtils.selectColumn(dataDiscrete, sourceColumn),
MatrixUtils.selectColumn(dataDiscrete, destColumn));
} else {
ChannelCalculator cc = (ChannelCalculator) calcContinuous;
cc.setObservations(
MatrixUtils.selectColumn(data, sourceColumn),
MatrixUtils.selectColumn(data, destColumn));
}
}
protected CalcProperties assignCalcProperties(String selectedCalcType)
throws Exception {
// Let the super class handle discrete calculators
CalcProperties calcProperties = super.assignCalcProperties(selectedCalcType);
if (calcProperties == null) {
// We need to assign properties for a continuous calculator
calcProperties = new CalcProperties();
calcProperties.calc = assignCalcObjectContinuous(selectedCalcType);
calcProperties.calcClass = calcProperties.calc.getClass();
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_GAUSSIAN)) {
calcProperties.classSpecificPropertyNames = gaussianProperties;
calcProperties.classSpecificPropertiesFieldNames = gaussianPropertiesFieldNames;
calcProperties.classSpecificPropertyDescriptions = gaussianPropertyDescriptions;
} else if (selectedCalcType.startsWith(CALC_TYPE_KRASKOV)) {
// The if statement will work for both MI Kraskov calculators
calcProperties.classSpecificPropertyNames = kraskovProperties;
calcProperties.classSpecificPropertiesFieldNames = kraskovPropertiesFieldNames;
calcProperties.classSpecificPropertyDescriptions = kraskovPropertyDescriptions;
} else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KERNEL)) {
calcProperties.classSpecificPropertyNames = kernelProperties;
calcProperties.classSpecificPropertiesFieldNames = kernelPropertiesFieldNames;
calcProperties.classSpecificPropertyDescriptions = kernelPropertyDescriptions;
} else {
calcProperties = null;
throw new Exception("No recognised calculator selected: " +
selectedCalcType);
}
}
return calcProperties;
}
}

View File

@ -18,7 +18,6 @@
package infodynamics.demos.autoanalysis;
import infodynamics.measures.continuous.ChannelCalculatorCommon;
import infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate;
import infodynamics.measures.continuous.gaussian.MutualInfoCalculatorMultiVariateGaussian;
import infodynamics.measures.continuous.kernel.MutualInfoCalculatorMultiVariateKernel;
@ -41,7 +40,7 @@ import java.awt.event.MouseListener;
* @author Joseph Lizier
*
*/
public class AutoAnalyserMI extends AutoAnalyser
public class AutoAnalyserMI extends AutoAnalyserChannelCalculator
implements ActionListener, DocumentListener, MouseListener {
/**
@ -59,6 +58,8 @@ public class AutoAnalyserMI extends AutoAnalyser
*/
protected void makeSpecificInitialisations() {
super.makeSpecificInitialisations();
// Set up the properties for MI:
measureAcronym = "MI";
appletTitle = "JIDT Mutual Information Auto-Analyser";
@ -159,7 +160,8 @@ public class AutoAnalyserMI extends AutoAnalyser
/**
* Method to assign and initialise our continuous calculator class
*/
protected ChannelCalculatorCommon assignCalcObjectContinuous(String selectedCalcType) throws Exception {
@Override
protected MutualInfoCalculatorMultiVariate assignCalcObjectContinuous(String selectedCalcType) throws Exception {
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_GAUSSIAN)) {
return new MutualInfoCalculatorMultiVariateGaussian();
} else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KRASKOV_ALG1)) {
@ -205,13 +207,6 @@ public class AutoAnalyserMI extends AutoAnalyser
base + ", " + timeDiff);
}
protected void setObservations(ChannelCalculatorCommon calc,
double[] source, double[] dest) throws Exception {
// We know this is a MutualInfoCalculatorMultiVariate
MutualInfoCalculatorMultiVariate miCalc = (MutualInfoCalculatorMultiVariate) calc;
miCalc.setObservations(source, dest);
}
/**
* @param args
*/

View File

@ -18,7 +18,6 @@
package infodynamics.demos.autoanalysis;
import infodynamics.measures.continuous.ChannelCalculatorCommon;
import infodynamics.measures.continuous.ConditionalMutualInfoMultiVariateCommon;
import infodynamics.measures.continuous.TransferEntropyCalculator;
import infodynamics.measures.continuous.gaussian.TransferEntropyCalculatorGaussian;
@ -41,7 +40,7 @@ import java.awt.event.MouseListener;
* @author Joseph Lizier
*
*/
public class AutoAnalyserTE extends AutoAnalyser
public class AutoAnalyserTE extends AutoAnalyserChannelCalculator
implements ActionListener, DocumentListener, MouseListener {
/**
@ -60,10 +59,17 @@ public class AutoAnalyserTE extends AutoAnalyser
*/
protected void makeSpecificInitialisations() {
super.makeSpecificInitialisations();
// Set up the properties for TE:
measureAcronym = "TE";
appletTitle = "JIDT Transfer Entropy Auto-Analyser";
calcTypes = new String[] {
CALC_TYPE_DISCRETE, CALC_TYPE_GAUSSIAN,
CALC_TYPE_KRASKOV, CALC_TYPE_KERNEL};
unitsForEachCalc = new String[] {"bits", "nats", "nats", "bits"};
// Discrete:
discreteClass = TransferEntropyCalculatorDiscrete.class;
discreteProperties = new String[] {
@ -214,7 +220,7 @@ public class AutoAnalyserTE extends AutoAnalyser
/**
* Method to assign and initialise our continuous calculator class
*/
protected ChannelCalculatorCommon assignCalcObjectContinuous(String selectedCalcType) throws Exception {
protected TransferEntropyCalculator assignCalcObjectContinuous(String selectedCalcType) throws Exception {
if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_GAUSSIAN)) {
return new TransferEntropyCalculatorGaussian();
} else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KRASKOV)) {
@ -294,13 +300,6 @@ public class AutoAnalyserTE extends AutoAnalyser
base + ", " + k + ", " + k_tau + ", " + l + ", " + l_tau + ", " + delay);
}
protected void setObservations(ChannelCalculatorCommon calc,
double[] source, double[] dest) throws Exception {
// We know this is a TransferEntropyCalculator
TransferEntropyCalculator teCalc = (TransferEntropyCalculator) calc;
teCalc.setObservations(source, dest);
}
/**
* @param args
*/