summaryrefslogtreecommitdiff
path: root/pyspike
diff options
context:
space:
mode:
authorMario Mulansky <mario.mulansky@gmx.net>2014-09-18 17:09:58 +0200
committerMario Mulansky <mario.mulansky@gmx.net>2014-09-18 17:09:58 +0200
commitb20d416c4765b2280526c633ca62f43677b1d26a (patch)
treed7e4e719edf41b4adee94bf3811ea573d7235b21 /pyspike
parenteb076dcd9d76ed3b848c78fb067c1ad6a1d6da23 (diff)
add spike-distance, PWL function (probably buggy)
Diffstat (limited to 'pyspike')
-rw-r--r--pyspike/__init__.py4
-rw-r--r--pyspike/distances.py99
-rw-r--r--pyspike/function.py33
3 files changed, 129 insertions, 7 deletions
diff --git a/pyspike/__init__.py b/pyspike/__init__.py
index 6895bd8..a5f146a 100644
--- a/pyspike/__init__.py
+++ b/pyspike/__init__.py
@@ -1,5 +1,5 @@
__all__ = ["function", "distances", "spikes"]
-from function import PieceWiseConstFunc
-from distances import isi_distance
+from function import PieceWiseConstFunc, PieceWiseLinFunc
+from distances import isi_distance, spike_distance
from spikes import spike_train_from_string, merge_spike_trains
diff --git a/pyspike/distances.py b/pyspike/distances.py
index f4989c8..2ea80e7 100644
--- a/pyspike/distances.py
+++ b/pyspike/distances.py
@@ -7,11 +7,11 @@ Copyright 2014, Mario Mulansky <mario.mulansky@gmx.net>
import numpy as np
-from pyspike import PieceWiseConstFunc
+from pyspike import PieceWiseConstFunc, PieceWiseLinFunc
def isi_distance(spikes1, spikes2, T_end, T_start=0.0):
- """ Computes the instantaneous isi-distance S_isi (t) of the two given spike
- trains.
+ """ Computes the instantaneous isi-distance S_isi (t) of the two given
+ spike trains.
Args:
- spikes1, spikes2: ordered arrays of spike times.
- T_end: end time of the observation interval.
@@ -50,6 +50,7 @@ def isi_distance(spikes1, spikes2, T_end, T_start=0.0):
# check which spike is next - from s1 or s2
if s1[index1+1] <= s2[index2+1]:
index1 += 1
+ # break condition relies on existence of spikes at T_end
if index1 >= len(nu1):
break
spike_events[index] = s1[index1]
@@ -63,3 +64,95 @@ def isi_distance(spikes1, spikes2, T_end, T_start=0.0):
max(nu1[index1], nu2[index2])
index += 1
return PieceWiseConstFunc(spike_events, isi_values)
+
+
+def get_min_dist(spike_time, spike_train, start_index=0):
+ """ Returns the minimal distance |spike_time - spike_train[i]|
+ with i>=start_index
+ """
+ d = abs(spike_time - spike_train[start_index])
+ start_index += 1
+ while start_index < len(spike_train):
+ d_temp = abs(spike_time - spike_train[start_index])
+ if d_temp > d:
+ break
+ else:
+ d = d_temp
+ start_index += 1
+ return d
+
+
+def spike_distance(spikes1, spikes2, T_end, T_start=0.0):
+ """ Computes the instantaneous spike-distance S_spike (t) of the two given
+ spike trains.
+ Args:
+ - spikes1, spikes2: ordered arrays of spike times.
+ - T_end: end time of the observation interval.
+ - T_start: begin of the observation interval (default=0.0).
+ Returns:
+ - PieceWiseLinFunc describing the spike-distance.
+ """
+ # add spikes at the beginning and end of the interval
+ t1 = np.empty(len(spikes1)+2)
+ t1[0] = T_start
+ t1[-1] = T_end
+ t1[1:-1] = spikes1
+ t2 = np.empty(len(spikes2)+2)
+ t2[0] = T_start
+ t2[-1] = T_end
+ t2[1:-1] = spikes2
+
+ spike_events = np.empty(len(t1)+len(t2)-2)
+ spike_events[0] = T_start
+ spike_events[-1] = T_end
+ y_starts = np.empty(len(spike_events)-1)
+ y_starts[0] = 0.0
+ y_ends = np.empty(len(spike_events)-1)
+
+ index1 = 0
+ index2 = 0
+ index = 1
+ dt_p1 = 0.0
+ dt_f1 = get_min_dist(t1[1], t2, 0)
+ dt_p2 = 0.0
+ dt_f2 = get_min_dist(t2[1], t1, 0)
+ isi1 = t1[1]-t1[0]
+ isi2 = t2[1]-t2[0]
+ while True:
+ print(index, index1, index2)
+ if t1[index1+1] < t2[index2+1]:
+ index1 += 1
+ # break condition relies on existence of spikes at T_end
+ if index1+1 >= len(t1):
+ break
+ spike_events[index] = t1[index1]
+ # first calculate the previous interval end value
+ dt_p1 = dt_f1 # the previous time now was the following time before
+ s1 = dt_p1
+ s2 = (dt_p2*(t2[index2+1]-t1[index1]) + dt_f2*(t1[index1]-t2[index2])) / isi2
+ y_ends[index-1] = (s1*isi2 + s2*isi1) / ((isi1+isi2)**2/2)
+ # now the next interval start value
+ dt_f1 = get_min_dist(t1[index1+1], t2, index2)
+ s1 = dt_f1
+ isi1 = t1[index1+1]-t1[index1]
+ # s2 is the same as above, thus we can compute y2 immediately
+ y_starts[index] = (s1*isi2 + s2*isi1) / ((isi1+isi2)**2/2)
+ else:
+ index2 += 1
+ if index2+1 >= len(t2):
+ break
+ spike_events[index] = t2[index2]
+ # first calculate the previous interval end value
+ dt_p2 = dt_f2 # the previous time now was the following time before
+ s1 = (dt_p1*(t1[index1+1]-t2[index2]) + dt_f1*(t2[index2]-t1[index1])) / isi1
+ s2 = dt_p2
+ y_ends[index-1] = (s1*isi2 + s2*isi1) / ((isi1+isi2)**2/2)
+ # now the next interval start value
+ dt_f2 = get_min_dist(t2[index2+1], t1, index1)
+ s2 = dt_f2
+ isi2 = t2[index2+1]-t2[index2]
+ # s2 is the same as above, thus we can compute y2 immediately
+ y_starts[index] = (s1*isi2 + s2*isi1) / ((isi1+isi2)**2/2)
+ index += 1
+
+ return PieceWiseLinFunc(spike_events, y_starts, y_ends)
diff --git a/pyspike/function.py b/pyspike/function.py
index c1de9cb..adf4dbb 100644
--- a/pyspike/function.py
+++ b/pyspike/function.py
@@ -44,8 +44,6 @@ class PieceWiseConstFunc:
Returns:
- the average a.
"""
- print(self.x)
- print(self.y)
return np.sum((self.x[1:]-self.x[:-1]) * self.y) / \
(self.x[-1]-self.x[0])
@@ -58,3 +56,34 @@ class PieceWiseConstFunc:
"""
return np.sum((self.x[1:]-self.x[:-1]) * np.abs(self.y)) / \
(self.x[-1]-self.x[0])
+
+
+class PieceWiseLinFunc:
+ """ A class representing a piece-wise linear function. """
+
+ def __init__(self, x, y1, y2):
+ """ Constructs the piece-wise linear function.
+ Params:
+ - x: array of length N+1 defining the edges of the intervals of the pwc
+ function.
+ - y1: array of length N defining the function values at the left of the
+ intervals.
+ - y2: array of length N defining the function values at the right of the
+ intervals.
+ """
+ self.x = x
+ self.y1 = y1
+ self.y2 = y2
+
+ def get_plottable_data(self):
+ """ Returns two arrays containing x- and y-coordinates for immeditate
+ plotting of the piece-wise function.
+ """
+ x_plot = np.empty(2*len(self.x)-2)
+ x_plot[0] = self.x[0]
+ x_plot[1::2] = self.x[1:]
+ x_plot[2::2] = self.x[1:-1]
+ y_plot = np.empty_like(x_plot)
+ y_plot[0::2] = self.y1
+ y_plot[1::2] = self.y2
+ return x_plot, y_plot