From b20d416c4765b2280526c633ca62f43677b1d26a Mon Sep 17 00:00:00 2001 From: Mario Mulansky Date: Thu, 18 Sep 2014 17:09:58 +0200 Subject: add spike-distance, PWL function (probably buggy) --- pyspike/__init__.py | 4 +-- pyspike/distances.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++-- pyspike/function.py | 33 ++++++++++++++++-- 3 files changed, 129 insertions(+), 7 deletions(-) (limited to 'pyspike') 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 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 -- cgit v1.2.3