diff --git a/demos/AutoAnalyser/runMIAutoAnalyser.bat b/demos/AutoAnalyser/runMIAutoAnalyser.bat
new file mode 100755
index 0000000..cb6a832
--- /dev/null
+++ b/demos/AutoAnalyser/runMIAutoAnalyser.bat
@@ -0,0 +1,8 @@
+@ECHO OFF
+
+REM Make sure the latest example source file is compiled.
+javac -classpath "..\java;..\..\infodynamics.jar" "..\java\infodynamics\demos\autoanalysis\AutoAnalyserMI.java"
+
+REM Run the example:
+java -classpath "..\java;..\..\infodynamics.jar" infodynamics.demos.autoanalysis.AutoAnalyserMI
+
diff --git a/demos/AutoAnalyser/runMIAutoAnalyser.sh b/demos/AutoAnalyser/runMIAutoAnalyser.sh
new file mode 100755
index 0000000..0b614d0
--- /dev/null
+++ b/demos/AutoAnalyser/runMIAutoAnalyser.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Make sure the latest example source file is compiled.
+javac -classpath "../java:../../infodynamics.jar" "../java/infodynamics/demos/autoanalysis/AutoAnalyserMI.java"
+
+# Run the example:
+java -classpath "../java:../../infodynamics.jar" infodynamics.demos.autoanalysis.AutoAnalyserMI
+
diff --git a/demos/AutoAnalyser/runTEAutoAnalyser.bat b/demos/AutoAnalyser/runTEAutoAnalyser.bat
index f1d923e..01b5435 100755
--- a/demos/AutoAnalyser/runTEAutoAnalyser.bat
+++ b/demos/AutoAnalyser/runTEAutoAnalyser.bat
@@ -3,6 +3,6 @@
REM Make sure the latest example source file is compiled.
javac -classpath "..\java;..\..\infodynamics.jar" "..\java\infodynamics\demos\autoanalysis\AutoAnalyserTE.java"
-# Run the example:
+REM Run the example:
java -classpath "..\java;..\..\infodynamics.jar" infodynamics.demos.autoanalysis.AutoAnalyserTE
diff --git a/demos/java/infodynamics/demos/autoanalysis/AutoAnalyser.java b/demos/java/infodynamics/demos/autoanalysis/AutoAnalyser.java
index 6e2d9ba..f94a037 100644
--- a/demos/java/infodynamics/demos/autoanalysis/AutoAnalyser.java
+++ b/demos/java/infodynamics/demos/autoanalysis/AutoAnalyser.java
@@ -300,8 +300,12 @@ public abstract class AutoAnalyser extends JFrame
// Set up for ~18 rows maximum (the +6 is exact to fit all props
// for Kraskov TE in without scrollbar)
Dimension d = propertiesTable.getPreferredSize();
+ int rowHeight = propertiesTable.getRowHeight();
propsTableScrollPane.setPreferredSize(
- new Dimension(d.width,propertiesTable.getRowHeight()*17+6));
+ new Dimension(d.width,rowHeight*17+6));
+ propsTableScrollPane.setMinimumSize(
+ new Dimension(d.width,rowHeight*17+6));
+ System.out.println("Row height was " + rowHeight);
// Button to compute
@@ -650,7 +654,8 @@ public abstract class AutoAnalyser extends JFrame
calcContinuous.getClass().getSimpleName() + "\n";
matlabConstructorLine = "calc = javaObject('infodynamics.measures.continuous.gaussian." +
calcContinuous.getClass().getSimpleName() + "');\n";
- } else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KRASKOV)) {
+ } else if (selectedCalcType.startsWith(CALC_TYPE_KRASKOV)) {
+ // The if statement will work for both MI Kraskov calculators
// Cover the calculator and any references to conditional MI calculator properties
javaCode.append("import infodynamics.measures.continuous.kraskov.*;\n");
javaConstructorLine = " calc = new " + calcContinuous.getClass().getSimpleName() + "();\n";
@@ -1106,7 +1111,8 @@ public abstract class AutoAnalyser extends JFrame
classSpecificPropertyNames = gaussianProperties;
classSpecificPropertiesFieldNames = gaussianPropertiesFieldNames;
classSpecificPropertyDescriptions = gaussianPropertyDescriptions;
- } else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KRASKOV)) {
+ } else if (selectedCalcType.startsWith(CALC_TYPE_KRASKOV)) {
+ // The if statement will work for both MI Kraskov calculators
classSpecificPropertyNames = kraskovProperties;
classSpecificPropertiesFieldNames = kraskovPropertiesFieldNames;
classSpecificPropertyDescriptions = kraskovPropertyDescriptions;
diff --git a/demos/java/infodynamics/demos/autoanalysis/AutoAnalyserMI.java b/demos/java/infodynamics/demos/autoanalysis/AutoAnalyserMI.java
new file mode 100644
index 0000000..5a2b39e
--- /dev/null
+++ b/demos/java/infodynamics/demos/autoanalysis/AutoAnalyserMI.java
@@ -0,0 +1,221 @@
+/*
+ * 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 .
+ */
+
+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;
+import infodynamics.measures.continuous.kraskov.MutualInfoCalculatorMultiVariateKraskov;
+import infodynamics.measures.continuous.kraskov.MutualInfoCalculatorMultiVariateKraskov1;
+import infodynamics.measures.continuous.kraskov.MutualInfoCalculatorMultiVariateKraskov2;
+import infodynamics.measures.discrete.MutualInformationCalculatorDiscrete;
+
+import javax.swing.JOptionPane;
+import javax.swing.event.DocumentListener;
+
+import java.awt.event.ActionListener;
+import java.awt.event.MouseListener;
+
+/**
+ * This class provides a GUI to build a simple mutual information calculation,
+ * and supply the code to execute it.
+ *
+ *
+ * @author Joseph Lizier
+ *
+ */
+public class AutoAnalyserMI extends AutoAnalyser
+ implements ActionListener, DocumentListener, MouseListener {
+
+ /**
+ * Need serialVersionUID to be serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ protected static final String DISCRETE_PROPNAME_TIME_DIFF = "time difference";
+
+ protected static final String CALC_TYPE_KRASKOV_ALG1 = CALC_TYPE_KRASKOV + " alg. 1";
+ protected static final String CALC_TYPE_KRASKOV_ALG2 = CALC_TYPE_KRASKOV + " alg. 2";
+
+ /**
+ * Constructor to initialise the GUI for MI
+ */
+ protected void makeSpecificInitialisations() {
+
+ // Set up the properties for MI:
+ measureAcronym = "MI";
+ appletTitle = "JIDT Mutual Information Auto-Analyser";
+
+ calcTypes = new String[] {
+ CALC_TYPE_DISCRETE, CALC_TYPE_GAUSSIAN,
+ CALC_TYPE_KRASKOV_ALG1, CALC_TYPE_KRASKOV_ALG2,
+ CALC_TYPE_KERNEL};
+ unitsForEachCalc = new String[] {"bits", "nats", "nats", "nats", "bits"};
+
+ // Discrete:
+ discreteClass = MutualInformationCalculatorDiscrete.class;
+ discreteProperties = new String[] {
+ DISCRETE_PROPNAME_BASE,
+ DISCRETE_PROPNAME_TIME_DIFF
+ };
+ discretePropertyDefaultValues = new String[] {
+ "2",
+ "0",
+ };
+ discretePropertyDescriptions = new String[] {
+ "Number of discrete states available for each variable (i.e. 2 for binary)",
+ "Time-lag from source to dest to consider MI across; must be >= 0 (0 for standard MI)",
+ };
+
+ // Continuous:
+ abstractContinuousClass = MutualInfoCalculatorMultiVariate.class;
+ // Common properties for all continuous calcs:
+ commonContPropertyNames = new String[] {
+ MutualInfoCalculatorMultiVariate.PROP_TIME_DIFF
+ };
+ commonContPropertiesFieldNames = new String[] {
+ "PROP_TIME_DIFF"
+ };
+ commonContPropertyDescriptions = new String[] {
+ "Time-lag from source to dest to consider MI across; must be >= 0 (0 for standard MI)"
+ };
+ // Gaussian properties:
+ gaussianProperties = new String[] {
+ };
+ gaussianPropertiesFieldNames = new String[] {
+ };
+ gaussianPropertyDescriptions = new String[] {
+ };
+ // Kernel:
+ kernelProperties = new String[] {
+ MutualInfoCalculatorMultiVariateKernel.KERNEL_WIDTH_PROP_NAME,
+ MutualInfoCalculatorMultiVariateKernel.DYN_CORR_EXCL_TIME_NAME,
+ MutualInfoCalculatorMultiVariateKernel.NORMALISE_PROP_NAME,
+ };
+ kernelPropertiesFieldNames = new String[] {
+ "KERNEL_WIDTH_PROP_NAME",
+ "DYN_CORR_EXCL_TIME_NAME",
+ "NORMALISE_PROP_NAME"
+ };
+ kernelPropertyDescriptions = new String[] {
+ "Kernel width to be used in the calculation.
If the property " +
+ MutualInfoCalculatorMultiVariateKernel.NORMALISE_PROP_NAME +
+ " is set, then this is a number of standard deviations; " +
+ "otherwise it is an absolute value.",
+ "Dynamic correlation exclusion time or
Theiler window (see Kantz and Schreiber); " +
+ "0 (default) means no dynamic exclusion window",
+ "(boolean) whether to normalise
each incoming time-series to mean 0, standard deviation 1, or not (recommended)",
+ };
+ // KSG (Kraskov):
+ kraskovProperties = new String[] {
+ MutualInfoCalculatorMultiVariateKraskov.PROP_NORMALISE,
+ MutualInfoCalculatorMultiVariateKraskov.PROP_K,
+ MutualInfoCalculatorMultiVariateKraskov.PROP_ADD_NOISE,
+ MutualInfoCalculatorMultiVariateKraskov.PROP_DYN_CORR_EXCL_TIME,
+ MutualInfoCalculatorMultiVariateKraskov.PROP_NORM_TYPE,
+ MutualInfoCalculatorMultiVariateKraskov.PROP_NUM_THREADS,
+ };
+ kraskovPropertiesFieldNames = new String[] {
+ "MutualInfoCalculatorMultiVariateKraskov.PROP_NORMALISE",
+ "MutualInfoCalculatorMultiVariateKraskov.PROP_K",
+ "MutualInfoCalculatorMultiVariateKraskov.PROP_ADD_NOISE",
+ "MutualInfoCalculatorMultiVariateKraskov.PROP_DYN_CORR_EXCL_TIME",
+ "MutualInfoCalculatorMultiVariateKraskov.PROP_NORM_TYPE",
+ "MutualInfoCalculatorMultiVariateKraskov.PROP_NUM_THREADS",
+ };
+ kraskovPropertyDescriptions = new String[] {
+ "(boolean) whether to normalise
each incoming time-series to mean 0, standard deviation 1, or not (recommended)",
+ "Number of k nearest neighbours to use
in the full joint kernel space in the KSG algorithm",
+ "Standard deviation for an amount
of random Gaussian noise to add to each variable, " +
+ "to avoid having neighbourhoods with artificially large counts.
" +
+ "(\"false\" may be used to indicate \"0\".). The amount is added in after any normalisation.",
+ "Dynamic correlation exclusion time or
Theiler window (see Kantz and Schreiber); " +
+ "0 (default) means no dynamic exclusion window",
+ "
Norm type to use in KSG algorithm between the points in each marginal space.
Options are: " +
+ "\"MAX_NORM\" (default), otherwise \"EUCLIDEAN\" or \"EUCLIDEAN_SQUARED\" (both equivalent here)",
+ "Number of parallel threads to use
in computation: an integer > 0 or \"USE_ALL\" " +
+ "(default, to indicate to use all available processors)",
+ };
+
+ }
+
+ /**
+ * Method to assign and initialise our continuous calculator class
+ */
+ protected ChannelCalculatorCommon assignCalcObjectContinuous(String selectedCalcType) throws Exception {
+ if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_GAUSSIAN)) {
+ return new MutualInfoCalculatorMultiVariateGaussian();
+ } else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KRASKOV_ALG1)) {
+ return new MutualInfoCalculatorMultiVariateKraskov1();
+ } else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KRASKOV_ALG2)) {
+ return new MutualInfoCalculatorMultiVariateKraskov2();
+ } else if (selectedCalcType.equalsIgnoreCase(CALC_TYPE_KERNEL)) {
+ return new MutualInfoCalculatorMultiVariateKernel();
+ } else {
+ throw new Exception("No recognised continuous calculator selected: " +
+ selectedCalcType);
+ }
+
+ }
+
+ /**
+ * Method to assign and initialise our discrete calculator class
+ */
+ protected DiscreteCalcAndArguments assignCalcObjectDiscrete() throws Exception {
+ String timeDiffPropValueStr, basePropValueStr;
+ try {
+ timeDiffPropValueStr = propertyValues.get(DISCRETE_PROPNAME_TIME_DIFF);
+ } catch (Exception ex) {
+ JOptionPane.showMessageDialog(this,
+ ex.getMessage());
+ resultsLabel.setText("Cannot find a value for property " + DISCRETE_PROPNAME_TIME_DIFF);
+ return null;
+ }
+ try {
+ basePropValueStr = propertyValues.get(DISCRETE_PROPNAME_BASE);
+ } catch (Exception ex) {
+ JOptionPane.showMessageDialog(this,
+ ex.getMessage());
+ resultsLabel.setText("Cannot find a value for property " + DISCRETE_PROPNAME_BASE);
+ return null;
+ }
+ int timeDiff = Integer.parseInt(timeDiffPropValueStr);
+ int base = Integer.parseInt(basePropValueStr);
+
+ return new DiscreteCalcAndArguments(
+ new MutualInformationCalculatorDiscrete(base, timeDiff),
+ base,
+ 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
+ */
+ public static void main(String[] args) {
+ new AutoAnalyserMI();
+ }
+}
diff --git a/demos/java/infodynamics/demos/autoanalysis/AutoAnalyserTE.java b/demos/java/infodynamics/demos/autoanalysis/AutoAnalyserTE.java
index 7d76997..652c361 100644
--- a/demos/java/infodynamics/demos/autoanalysis/AutoAnalyserTE.java
+++ b/demos/java/infodynamics/demos/autoanalysis/AutoAnalyserTE.java
@@ -219,7 +219,7 @@ public class AutoAnalyserTE extends AutoAnalyser
} catch (Exception ex) {
JOptionPane.showMessageDialog(this,
ex.getMessage());
- resultsLabel.setText("Cannot find a value for property " + DISCRETE_PROPNAME_BASE);
+ resultsLabel.setText("Cannot find a value for property " + DISCRETE_PROPNAME_K);
return null;
}
try {