mirror of https://github.com/jlizier/jidt
132 lines
4.9 KiB
Python
132 lines
4.9 KiB
Python
##
|
|
## 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/>.
|
|
##
|
|
|
|
# runHeartBreathRateKraskov.py kHistory lHistory knns numSurrogates
|
|
#
|
|
# runHeartBreathRateKraskov.py
|
|
# Version 1.0
|
|
# Joseph Lizier
|
|
# 3/2/2015
|
|
#
|
|
# Used to explore information transfer in the heart rate / breath rate example of Schreiber --
|
|
# but estimates TE using Kraskov-Stoegbauer-Grassberger estimation.
|
|
#
|
|
#
|
|
# Inputs
|
|
# - kHistory - destination embedding length
|
|
# - lHistory - source embedding length
|
|
# - knns - a scalar specifying a single, or vector specifying a comma separated list, for values of K nearest neighbours to evaluate TE (Kraskov) with.
|
|
# - numSurrogates - a scalar specifying the number of surrogates to evaluate TE from null distribution
|
|
#
|
|
# Run e.g. python runHeartBreathRateKraskov.py 2 2 1,2,3,4,5,6,7,8,9,10
|
|
|
|
from jpype import *
|
|
import sys
|
|
import os
|
|
import random
|
|
import math
|
|
import string
|
|
import numpy
|
|
# Import our readFloatsFile utility in the above directory:
|
|
sys.path.append(os.path.relpath(".."))
|
|
import readFloatsFile
|
|
|
|
# Change location of jar to match yours:
|
|
jarLocation = "../../../infodynamics.jar"
|
|
# Start the JVM (add the "-Xmx" option with say 1024M if you get crashes due to not enough memory space)
|
|
startJVM(getDefaultJVMPath(), "-ea", "-Djava.class.path=" + jarLocation)
|
|
|
|
# Read in the command line arguments and assign default if required.
|
|
# first argument in argv is the filename, so program arguments start from index 1.
|
|
if (len(sys.argv) < 2):
|
|
kHistory = 1;
|
|
else:
|
|
kHistory = int(sys.argv[1]);
|
|
if (len(sys.argv) < 3):
|
|
lHistory = 1;
|
|
else:
|
|
lHistory = int(sys.argv[2]);
|
|
if (len(sys.argv) < 4):
|
|
knns = [4];
|
|
else:
|
|
knnsStrings = sys.argv[3].split(",");
|
|
knns = [int(i) for i in knnsStrings]
|
|
if (len(sys.argv) < 5):
|
|
numSurrogates = 0;
|
|
else:
|
|
numSurrogates = int(sys.argv[4]);
|
|
|
|
# Read in the data
|
|
datafile = '../../data/SFI-heartRate_breathVol_bloodOx.txt'
|
|
rawData = readFloatsFile.readFloatsFile(datafile)
|
|
# As numpy array:
|
|
data = numpy.array(rawData)
|
|
# Heart rate is first column, and we restrict to the samples that Schreiber mentions (2350:3550)
|
|
heart = data[2349:3550,0]; # Extracts what Matlab does with 2350:3550 argument there.
|
|
# Chest vol is second column
|
|
chestVol = data[2349:3550,1];
|
|
# bloodOx = data[2349:3550,2];
|
|
|
|
timeSteps = len(heart);
|
|
|
|
print("TE for heart rate <-> breath rate for Kraskov estimation with %d samples:" % timeSteps);
|
|
|
|
# Using a KSG estimator for TE is the least biased way to run this:
|
|
teCalcClass = JPackage("infodynamics.measures.continuous.kraskov").TransferEntropyCalculatorKraskov
|
|
teCalc = teCalcClass();
|
|
|
|
teHeartToBreath = [];
|
|
teBreathToHeart = [];
|
|
|
|
for knnIndex in range(len(knns)):
|
|
knn = knns[knnIndex];
|
|
# Compute a TE value for knn nearest neighbours
|
|
|
|
# Perform calculation for heart -> breath (lag 1)
|
|
teCalc.initialise(kHistory,1,lHistory,1,1);
|
|
teCalc.setProperty("k", str(knn));
|
|
teCalc.setObservations(JArray(JDouble, 1)(heart),
|
|
JArray(JDouble, 1)(chestVol));
|
|
teHeartToBreath.append( teCalc.computeAverageLocalOfObservations() );
|
|
if (numSurrogates > 0):
|
|
teHeartToBreathNullDist = teCalc.computeSignificance(numSurrogates);
|
|
teHeartToBreathNullMean = teHeartToBreathNullDist.getMeanOfDistribution();
|
|
teHeartToBreathNullStd = teHeartToBreathNullDist.getStdOfDistribution();
|
|
|
|
# Perform calculation for breath -> heart (lag 1)
|
|
teCalc.initialise(kHistory,1,lHistory,1,1);
|
|
teCalc.setProperty("k", str(knn));
|
|
teCalc.setObservations(JArray(JDouble, 1)(chestVol),
|
|
JArray(JDouble, 1)(heart));
|
|
teBreathToHeart.append( teCalc.computeAverageLocalOfObservations() );
|
|
if (numSurrogates > 0):
|
|
teBreathToHeartNullDist = teCalc.computeSignificance(numSurrogates);
|
|
teBreathToHeartNullMean = teBreathToHeartNullDist.getMeanOfDistribution();
|
|
teBreathToHeartNullStd = teBreathToHeartNullDist.getStdOfDistribution();
|
|
|
|
print("TE(k=%d,l=%d,knn=%d): h->b = %.3f" % (kHistory, lHistory, knn, teHeartToBreath[knnIndex])), # , for no newline
|
|
if (numSurrogates > 0):
|
|
print(" (null = %.3f +/- %.3f)" % (teHeartToBreathNullMean, teHeartToBreathNullStd)),
|
|
print(", b->h = %.3f nats" % teBreathToHeart[knnIndex]),
|
|
if (numSurrogates > 0):
|
|
print("(null = %.3f +/- %.3f)" % (teBreathToHeartNullMean, teBreathToHeartNullStd)),
|
|
print
|
|
|
|
# Exercise: plot the results
|
|
|