diff --git a/build.xml b/build.xml index 4da9e99..68331db 100755 --- a/build.xml +++ b/build.xml @@ -151,6 +151,7 @@ + diff --git a/demos/java/infodynamics/demos/Example4TeContinuousDataKraskov.java b/demos/java/infodynamics/demos/Example4TeContinuousDataKraskov.java index 16bb593..ccbc221 100755 --- a/demos/java/infodynamics/demos/Example4TeContinuousDataKraskov.java +++ b/demos/java/infodynamics/demos/Example4TeContinuousDataKraskov.java @@ -18,6 +18,7 @@ package infodynamics.demos; +import infodynamics.utils.MatrixUtils; import infodynamics.utils.RandomGenerator; import infodynamics.measures.continuous.kraskov.TransferEntropyCalculatorKraskov; @@ -78,7 +79,9 @@ public class Example4TeContinuousDataKraskov { // We can also compute the local TE values for the time-series samples here: // (See more about utility of local TE in the CA demos) - @SuppressWarnings("unused") double[] localTE = teCalc.computeLocalOfPreviousObservations(); + System.out.printf("Notice that the mean of locals, %.4f nats," + + " equals the previous result\n", + MatrixUtils.sum(localTE)/(double)(numObservations-1)); } } diff --git a/demos/octave/example6DynamicCallingMutualInfo.m b/demos/octave/example6DynamicCallingMutualInfo.m index 0d10f38..e546ed2 100755 --- a/demos/octave/example6DynamicCallingMutualInfo.m +++ b/demos/octave/example6DynamicCallingMutualInfo.m @@ -25,14 +25,13 @@ % one of three concrete implementations (kernel estimator, Kraskov estimator or % linear-Gaussian estimator) by dynamically supplying the class name of % the concrete implementation. -% -% This is the Octave/Matlab equivalent to the demos/java/lateBindingDemo % Change location of jar to match yours: javaaddpath('../../infodynamics.jar'); %--------------------- -% 1. Properties for the calculation (these are dynamically changeable): +% 1. Properties for the calculation (these are dynamically changeable, you could +% load them in from another properties file): % The name of the data file (relative to this directory) datafile = '../data/4ColsPairedNoisyDependence-1.txt'; % List of column numbers for variables 1 and 2: @@ -43,7 +42,7 @@ variable2Columns = [3,4]; % infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate % which we wish to use for the calculation. % Note that one could use any of the following calculators (try them all!): -% implementingClass = 'infodynamics.measures.continuous.kraskov.MutualInfoCalculatorMultiVariateKraskov1'; % MI([1,2], [3,4]) = 0.35507 +% implementingClass = 'infodynamics.measures.continuous.kraskov.MutualInfoCalculatorMultiVariateKraskov1'; % MI([1,2], [3,4]) = 0.36353 % implementingClass = 'infodynamics.measures.continuous.kernel.MutualInfoCalculatorMultiVariateKernel'; % implementingClass = 'infodynamics.measures.continuous.gaussian.MutualInfoCalculatorMultiVariateGaussian'; implementingClass = 'infodynamics.measures.continuous.kraskov.MutualInfoCalculatorMultiVariateKraskov1'; diff --git a/demos/python/example6DynamicCallingMutualInfo.py b/demos/python/example6DynamicCallingMutualInfo.py index 8867085..ef677ce 100755 --- a/demos/python/example6DynamicCallingMutualInfo.py +++ b/demos/python/example6DynamicCallingMutualInfo.py @@ -25,13 +25,12 @@ # one of three concrete implementations (kernel estimator, Kraskov estimator or # linear-Gaussian estimator) by dynamically supplying the class name of # the concrete implementation. -# -# This is the Python equivalent to the demos/java/lateBindingDemo from jpype import * import random import string import numpy +import readFloatsFile # Change location of jar to match yours: jarLocation = "../../infodynamics.jar" @@ -56,15 +55,10 @@ variable2Columns = [2,3] implementingClass = "infodynamics.measures.continuous.kraskov.MutualInfoCalculatorMultiVariateKraskov1" #--------------------- -# 2. Load in the data (space separate numbers, one time step per line, each column is a variable) -f = open(datafile) -data = [] -for line in f: - data.append([float(x) for x in line.split()]) - +# 2. Load in the data +data = readFloatsFile.readFloatsFile(datafile) # As numpy array: A = numpy.array(data) - # Pull out the columns from the data set which correspond to each of variable 1 and 2: variable1 = A[:,variable1Columns] variable2 = A[:,variable2Columns] diff --git a/demos/python/readFloatsFile.py b/demos/python/readFloatsFile.py new file mode 100755 index 0000000..3c0df03 --- /dev/null +++ b/demos/python/readFloatsFile.py @@ -0,0 +1,27 @@ +## +## Java Information Dynamics Toolkit (JIDT) +## Copyright (C) 2012, 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 . +## + +def readFloatsFile(filename): + "Read a 2D array of floats from a given file" + with open(filename) as f: + # Space separate numbers, one time step per line, each column is a variable + array = [] + for line in f: # read all lines + array.append([float(x) for x in line.split()]) + return array + diff --git a/demos/python/readIntsFile.py b/demos/python/readIntsFile.py new file mode 100755 index 0000000..3eaf1a4 --- /dev/null +++ b/demos/python/readIntsFile.py @@ -0,0 +1,27 @@ +## +## Java Information Dynamics Toolkit (JIDT) +## Copyright (C) 2012, 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 . +## + +def readIntsFile(filename): + "Read a 2D array of int from a given file" + with open(filename) as f: + # Space separate numbers, one time step per line, each column is a variable + array = [] + for line in f: # read all lines + array.append([int(x) for x in line.split()]) + return array + diff --git a/demos/r/example3TeContinuousDataKernel.r b/demos/r/example3TeContinuousDataKernel.r index c62ebfd..44e557b 100755 --- a/demos/r/example3TeContinuousDataKernel.r +++ b/demos/r/example3TeContinuousDataKernel.r @@ -51,3 +51,10 @@ cat("TE result ", result, "bits; expected to be close to ", log(1/(1-covariance result2 <- .jcall(teCalc,"D","computeAverageLocalOfObservations") cat("TE result ", result2, "bits; expected to be close to 0 bits for uncorrelated Gaussians but will be biased upwards\n") +# We can get insight into the bias by examining the null distribution: +nullDist <- .jcall(teCalc,"Linfodynamics/utils/EmpiricalMeasurementDistribution;", + "computeSignificance", 100L) +cat("Null distribution for unrelated source and destination", + "(i.e. the bias) has mean", .jcall(nullDist, "D", "getMeanOfDistribution"), + "bits and standard deviation", .jcall(nullDist, "D", "getStdOfDistribution"), "\n") + diff --git a/demos/r/example4TeContinuousDataKraskov.r b/demos/r/example4TeContinuousDataKraskov.r index 6bb9407..d2ea19c 100755 --- a/demos/r/example4TeContinuousDataKraskov.r +++ b/demos/r/example4TeContinuousDataKraskov.r @@ -56,3 +56,9 @@ cat("TE result ", result, "nats; expected to be close to ", log(1/(1-covariance result2 <- .jcall(teCalc,"D","computeAverageLocalOfObservations") cat("TE result ", result2, "nats; expected to be close to 0 nats for uncorrelated Gaussians\n") +# We can also compute the local TE values for the time-series samples here: +# (See more about utility of local TE in the CA demos) +localTE <- .jcall(teCalc,"[D","computeLocalOfPreviousObservations") +cat("Notice that the mean of locals", sum(localTE)/(numObservations-1), + "nats equals the above result\n") + diff --git a/demos/r/example5TeBinaryMultivarTransfer.r b/demos/r/example5TeBinaryMultivarTransfer.r new file mode 100755 index 0000000..bf77477 --- /dev/null +++ b/demos/r/example5TeBinaryMultivarTransfer.r @@ -0,0 +1,69 @@ +## +## Java Information Dynamics Toolkit (JIDT) +## Copyright (C) 2012, 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 . +## + +# = Example 5 - Multivariate transfer entropy on binary data = + +# Multivariate transfer entropy (TE) calculation on binary data using the discrete TE calculator: + +# Load the rJava library and start the JVM +library("rJava") +.jinit() + +# Change location of jar to match yours: +# IMPORTANT -- If using the default below, make sure you have set the working directory +# in R (e.g. with setwd()) to the location of this file (i.e. demos/r) !! +.jaddClassPath("../../infodynamics.jar") + +# Generate some random binary data. +numObservations <- 100 +sourceArray<-matrix(sample(0:1,numObservations*2, replace=TRUE),numObservations,2) +sourceArray2<-matrix(sample(0:1,numObservations*2, replace=TRUE),numObservations,2) +# Destination variable takes a copy of the first bit of the source in bit 1, +# and an XOR of the two bits of the source in bit 2: +destArray <- cbind( c(0L, sourceArray[1:numObservations-1,1]), # column 1 + c(0L, 1L*xor(sourceArray[1:numObservations-1,1], + sourceArray[1:numObservations-1,2]))) # column 2 + +# Convert the 2D arrays to Java format: +sourceArrayJava <- .jarray(sourceArray, "[I", dispatch=TRUE) +sourceArray2Java <- .jarray(sourceArray2, "[I", dispatch=TRUE) +destArrayJava <- .jarray(destArray, "[I", dispatch=TRUE) + +# Create a TE calculator and run it: +teCalc<-.jnew("infodynamics/measures/discrete/TransferEntropyCalculatorDiscrete", 4L, 1L) +.jcall(teCalc,"V","initialise") # V for void return value +# We need to construct the joint values for the dest and source before we pass them in, +# and need to use the matrix conversion routine when calling from Matlab/Octave: +mUtils<-.jnew("infodynamics/utils/MatrixUtils") +.jcall(teCalc,"V","addObservations", + .jcall(mUtils,"[I","computeCombinedValues", sourceArrayJava, 2L), + .jcall(mUtils,"[I","computeCombinedValues", destArrayJava, 2L)) +result<-.jcall(teCalc,"D","computeAverageLocalOfObservations") +cat("For source which the 2 bits are determined from, result should be close to 2 bits : ", result, "\n") + +.jcall(teCalc,"V","initialise") +.jcall(teCalc,"V","addObservations", + .jcall(mUtils,"[I","computeCombinedValues", sourceArray2Java, 2L), + .jcall(mUtils,"[I","computeCombinedValues", destArrayJava, 2L)) +result2<-.jcall(teCalc,"D","computeAverageLocalOfObservations") +cat("For random source, result should be close to 0 bits in theory: ", result2, "\n"); +cat("Result for random source is inflated towards 0.3 due to finite observation length ", + .jcall(teCalc,"I","getNumObservations"), "\n", + "One can verify that the answer is consistent with that from a\n", + "random source by checking: teCalc.computeSignificance(1000); ans.pValue\n"); + diff --git a/demos/r/example6DynamicCallingMutualInfo.r b/demos/r/example6DynamicCallingMutualInfo.r new file mode 100755 index 0000000..61bac34 --- /dev/null +++ b/demos/r/example6DynamicCallingMutualInfo.r @@ -0,0 +1,90 @@ +## +## Java Information Dynamics Toolkit (JIDT) +## Copyright (C) 2012, 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 . +## + +# Example 6 - Mutual information calculation with dynamic specification of calculator + +# This example shows how to write R code to take advantage of the +# common interfaces defined for various information-theoretic calculators. +# Here, we use the common form of the infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate +# interface (which is never named here) to write common code into which we can plug +# one of three concrete implementations (kernel estimator, Kraskov estimator or +# linear-Gaussian estimator) by dynamically supplying the class name of +# the concrete implementation. + +# Load the rJava library and start the JVM +library("rJava") +.jinit() + +# Change location of jar to match yours: +# IMPORTANT -- If using the default below, make sure you have set the working directory +# in R (e.g. with setwd()) to the location of this file (i.e. demos/r) !! +.jaddClassPath("../../infodynamics.jar") + +#--------------------- +# 1. Properties for the calculation (these are dynamically changeable, you could +# load them in from another properties file): +# The name of the data file (relative to this directory) +datafile <- "../data/4ColsPairedNoisyDependence-1.txt" +# List of column numbers for variables 1 and 2: +# (you can select any columns you wish to be contained in each variable) +variable1Columns <- c(1,2) # array indices start from 1 in R +variable2Columns <- c(3,4) +# The name of the concrete implementation of the interface +# infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate +# which we wish to use for the calculation. +# Note that one could use any of the following calculators (try them all!): +# implementingClass <- "infodynamics/measures/continuous/kraskov/MutualInfoCalculatorMultiVariateKraskov1" # MI([1,2], [3,4]) = 0.36353 +# implementingClass <- "infodynamics/measures/continuous/kernel/MutualInfoCalculatorMultiVariateKernel" +# implementingClass <- "infodynamics/measures/continuous/gaussian/MutualInfoCalculatorMultiVariateGaussian" +implementingClass <- "infodynamics/measures/continuous/kraskov/MutualInfoCalculatorMultiVariateKraskov1" + +#--------------------- +# 2. Load in the data +data <- read.csv(datafile, header=FALSE, sep="") +# Pull out the columns from the data set which correspond to each of variable 1 and 2: +variable1 <- data[, variable1Columns] +variable2 <- data[, variable2Columns] +# Extra step to extract the raw values from these data.frame objects: +variable1 <- apply(variable1, 2, function(x) as.numeric(x)) +variable2 <- apply(variable2, 2, function(x) as.numeric(x)) + +#--------------------- +# 3. Dynamically instantiate an object of the given class: +# (in fact, all java object creation in octave/matlab is dynamic - it has to be, +# since the languages are interpreted. This makes our life slightly easier at this +# point than it is in demos/java/example6LateBindingMutualInfo where we have to handle this manually) +miCalc<-.jnew(implementingClass) + +#--------------------- +# 4. Start using the MI calculator, paying attention to only +# call common methods defined in the interface type +# infodynamics.measures.continuous.MutualInfoCalculatorMultiVariate +# not methods only defined in a given implementation class. +# a. Initialise the calculator to use the required number of +# dimensions for each variable: +.jcall(miCalc,"V","initialise", length(variable1Columns), length(variable2Columns)) +# b. Supply the observations to compute the PDFs from: +.jcall(miCalc,"V","setObservations", + .jarray(variable1, "[D", dispatch=TRUE), + .jarray(variable2, "[D", dispatch=TRUE)) +# c. Make the MI calculation: +miValue <- .jcall(miCalc,"D","computeAverageLocalOfObservations") + +cat("MI calculator", implementingClass, "\n computed the joint MI as ", + miValue, "\n") + diff --git a/readme-template.txt b/readme-template.txt index 548035a..1e89fa4 100755 --- a/readme-template.txt +++ b/readme-template.txt @@ -61,6 +61,8 @@ Javadocs for the toolkit are included in the full distribution at javadocs. They can also be generated using "ant javadocs" (useful if you are on an SVN view). Further, they will soon be posted on the web. +The project wiki also contains further information on various aspects; see http://code.google.com/p/information-dynamics-toolkit/ to start. + Further documentation is provided by the Usage examples below. You can also join our email discussion group jidt-discuss at http://groups.google.com/d/forum/jidt-discuss @@ -73,21 +75,25 @@ Several sets of demonstration code are distributed with the toolkit: a. demos/java -- basic examples on easily using the Java toolkit -- run these from the shell scripts in this directory -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/SimpleJavaExamples - b. demos/octave -- basic examples on easily using the Java toolkit from Octave or Matlab environments -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/OctaveMatlabExamples + b. Several demo sets mirror the SimpleJavaExamples to demonstrate the use of the toolkit in non-Java environments: - c. demos/python -- basic examples on easily using the Java toolkit from Python -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/PythonExamples - - d. demos/octave/CellularAutomata -- using the Java toolkit to plot local information dynamics profiles in cellular automata; the toolkit is run under Octave or Matlab -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/CellularAutomataDemos + i. demos/octave -- basic examples on easily using the Java toolkit from Octave or Matlab environments -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/OctaveMatlabExamples - e. demos/octave/SchreiberTransferEntropyExamples -- recreates the transfer entropy examples in Schreiber's original paper presenting this measure; shows the correct parameter settings to reproduce these results -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/SchreiberTeDemos + ii. demos/python -- basic examples on easily using the Java toolkit from Python -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/PythonExamples + + iii. demos/r -- basic examples on easily using the Java toolkit from R -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/R_Examples + + c. demos/octave/CellularAutomata -- using the Java toolkit to plot local information dynamics profiles in cellular automata; the toolkit is run under Octave or Matlab -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/CellularAutomataDemos - f. demos/octave/DetectingInteractionLags -- demonstration of using the transfer entropy with source-destination lags; the demo is run under Octave or Matlab -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/DetectingInteractionLags + d. demos/octave/SchreiberTransferEntropyExamples -- recreates the transfer entropy examples in Schreiber's original paper presenting this measure; shows the correct parameter settings to reproduce these results -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/SchreiberTeDemos + + e. demos/octave/DetectingInteractionLags -- demonstration of using the transfer entropy with source-destination lags; the demo is run under Octave or Matlab -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/DetectingInteractionLags - g. demos/java/InterregionalTransfer -- higher level example using collective transfer entropy to infer effective connections between "regions" of data -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/InterregionalTransfer + f. demos/java/InterregionalTransfer -- higher level example using collective transfer entropy to infer effective connections between "regions" of data -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/InterregionalTransfer - h. demos/octave/NullDistributions -- investigating the correspondence between analytic and bootstrapped distributions for TE and MI under null hypotheses of no relationship; the demo is run under Octave or Matlab -- see description at https://code.google.com/p/information-dynamics-toolkit/wiki/NullDistributions + g. demos/octave/NullDistributions -- investigating the correspondence between analytic and bootstrapped distributions for TE and MI under null hypotheses of no relationship; the demo is run under Octave or Matlab -- see description at https://code.google.com/p/information-dynamics-toolkit/wiki/NullDistributions - i. java/unittests -- the JUnit test cases for the Java toolkit are included in the distribution -- these case also be browsed to see simple use cases for the various calculators in the toolkit -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/JUnitTestCases + h. java/unittests -- the JUnit test cases for the Java toolkit are included in the distribution -- these case also be browsed to see simple use cases for the various calculators in the toolkit -- see description at http://code.google.com/p/information-dynamics-toolkit/wiki/JUnitTestCases ============= Citation