summaryrefslogtreecommitdiff
path: root/pyspike
diff options
context:
space:
mode:
Diffstat (limited to 'pyspike')
-rw-r--r--pyspike/DiscreteFunc.py9
-rw-r--r--pyspike/__init__.py3
-rw-r--r--pyspike/cython/cython_add.pyx33
-rw-r--r--pyspike/cython/cython_distances.pyx5
-rw-r--r--pyspike/cython/python_backend.py33
-rw-r--r--pyspike/spike_sync.py10
-rw-r--r--pyspike/spikes.py66
7 files changed, 107 insertions, 52 deletions
diff --git a/pyspike/DiscreteFunc.py b/pyspike/DiscreteFunc.py
index fe97bc2..caad290 100644
--- a/pyspike/DiscreteFunc.py
+++ b/pyspike/DiscreteFunc.py
@@ -170,10 +170,6 @@ expected."
start_ind, end_ind = get_indices(ival)
value += np.sum(self.y[start_ind:end_ind])
multiplicity += np.sum(self.mp[start_ind:end_ind])
- if multiplicity == 0.0:
- # empty profile, return spike sync of 1
- value = 1.0
- multiplicity = 1.0
return (value, multiplicity)
def avrg(self, interval=None, normalize=True):
@@ -190,7 +186,10 @@ expected."
"""
val, mp = self.integral(interval)
if normalize:
- return val/mp
+ if mp > 0:
+ return val/mp
+ else:
+ return 1.0
else:
return val
diff --git a/pyspike/__init__.py b/pyspike/__init__.py
index 069090b..08253fb 100644
--- a/pyspike/__init__.py
+++ b/pyspike/__init__.py
@@ -23,7 +23,8 @@ from .spike_sync import spike_sync_profile, spike_sync,\
spike_sync_profile_multi, spike_sync_multi, spike_sync_matrix
from .psth import psth
-from .spikes import load_spike_trains_from_txt, spike_train_from_string, \
+from .spikes import load_spike_trains_from_txt, save_spike_trains_to_txt, \
+ spike_train_from_string, import_spike_trains_from_time_series, \
merge_spike_trains, generate_poisson_spikes
# define the __version__ following
diff --git a/pyspike/cython/cython_add.pyx b/pyspike/cython/cython_add.pyx
index 8da1e53..25f1181 100644
--- a/pyspike/cython/cython_add.pyx
+++ b/pyspike/cython/cython_add.pyx
@@ -182,8 +182,8 @@ def add_discrete_function_cython(double[:] x1, double[:] y1, double[:] mp1,
cdef int index1 = 0
cdef int index2 = 0
cdef int index = 0
- cdef int N1 = len(y1)
- cdef int N2 = len(y2)
+ cdef int N1 = len(y1)-1
+ cdef int N2 = len(y2)-1
x_new[0] = x1[0]
while (index1+1 < N1) and (index2+1 < N2):
if x1[index1+1] < x2[index2+1]:
@@ -206,20 +206,21 @@ def add_discrete_function_cython(double[:] x1, double[:] y1, double[:] mp1,
y_new[index] = y1[index1] + y2[index2]
mp_new[index] = mp1[index1] + mp2[index2]
# one array reached the end -> copy the contents of the other to the end
- if index1+1 < len(y1):
- x_new[index+1:index+1+len(x1)-index1-1] = x1[index1+1:]
- y_new[index+1:index+1+len(x1)-index1-1] = y1[index1+1:]
- mp_new[index+1:index+1+len(x1)-index1-1] = mp1[index1+1:]
- index += len(x1)-index1-1
- elif index2+1 < len(y2):
- x_new[index+1:index+1+len(x2)-index2-1] = x2[index2+1:]
- y_new[index+1:index+1+len(x2)-index2-1] = y2[index2+1:]
- mp_new[index+1:index+1+len(x2)-index2-1] = mp2[index2+1:]
- index += len(x2)-index2-1
- # else: # both arrays reached the end simultaneously
- # x_new[index+1] = x1[-1]
- # y_new[index+1] = y1[-1] + y2[-1]
- # mp_new[index+1] = mp1[-1] + mp2[-1]
+ if index1+1 < N1:
+ x_new[index+1:index+1+N1-index1] = x1[index1+1:]
+ y_new[index+1:index+1+N1-index1] = y1[index1+1:]
+ mp_new[index+1:index+1+N1-index1] = mp1[index1+1:]
+ index += N1-index1
+ elif index2+1 < N2:
+ x_new[index+1:index+1+N2-index2] = x2[index2+1:]
+ y_new[index+1:index+1+N2-index2] = y2[index2+1:]
+ mp_new[index+1:index+1+N2-index2] = mp2[index2+1:]
+ index += N2-index2
+ else: # both arrays reached the end simultaneously
+ x_new[index+1] = x1[index1+1]
+ y_new[index+1] = y1[index1+1] + y2[index2+1]
+ mp_new[index+1] = mp1[index1+1] + mp2[index2+1]
+ index += 1
y_new[0] = y_new[1]
mp_new[0] = mp_new[1]
diff --git a/pyspike/cython/cython_distances.pyx b/pyspike/cython/cython_distances.pyx
index 7dc9cb9..ac5f226 100644
--- a/pyspike/cython/cython_distances.pyx
+++ b/pyspike/cython/cython_distances.pyx
@@ -428,9 +428,4 @@ def coincidence_value_cython(double[:] spikes1, double[:] spikes2,
mp += 2
coinc += 2
- if coinc == 0 and mp == 0:
- # empty spike trains -> spike sync = 1 by definition
- coinc = 1
- mp = 1
-
return coinc, mp
diff --git a/pyspike/cython/python_backend.py b/pyspike/cython/python_backend.py
index a1e3a65..6b7209a 100644
--- a/pyspike/cython/python_backend.py
+++ b/pyspike/cython/python_backend.py
@@ -560,7 +560,9 @@ def add_discrete_function_python(x1, y1, mp1, x2, y2, mp2):
index1 = 0
index2 = 0
index = 0
- while (index1+1 < len(y1)) and (index2+1 < len(y2)):
+ N1 = len(x1)-1
+ N2 = len(x2)-1
+ while (index1+1 < N1) and (index2+1 < N2):
if x1[index1+1] < x2[index2+1]:
index1 += 1
index += 1
@@ -581,20 +583,21 @@ def add_discrete_function_python(x1, y1, mp1, x2, y2, mp2):
y_new[index] = y1[index1] + y2[index2]
mp_new[index] = mp1[index1] + mp2[index2]
# one array reached the end -> copy the contents of the other to the end
- if index1+1 < len(y1):
- x_new[index+1:index+1+len(x1)-index1-1] = x1[index1+1:]
- y_new[index+1:index+1+len(x1)-index1-1] = y1[index1+1:]
- mp_new[index+1:index+1+len(x1)-index1-1] = mp1[index1+1:]
- index += len(x1)-index1-1
- elif index2+1 < len(y2):
- x_new[index+1:index+1+len(x2)-index2-1] = x2[index2+1:]
- y_new[index+1:index+1+len(x2)-index2-1] = y2[index2+1:]
- mp_new[index+1:index+1+len(x2)-index2-1] = mp2[index2+1:]
- index += len(x2)-index2-1
- # else: # both arrays reached the end simultaneously
- # x_new[index+1] = x1[-1]
- # y_new[index+1] = y1[-1] + y2[-1]
- # mp_new[index+1] = mp1[-1] + mp2[-1]
+ if index1+1 < N1:
+ x_new[index+1:index+1+N1-index1] = x1[index1+1:]
+ y_new[index+1:index+1+N1-index1] = y1[index1+1:]
+ mp_new[index+1:index+1+N1-index1] = mp1[index1+1:]
+ index += N1-index1
+ elif index2+1 < N2:
+ x_new[index+1:index+1+N2-index2] = x2[index2+1:]
+ y_new[index+1:index+1+N2-index2] = y2[index2+1:]
+ mp_new[index+1:index+1+N2-index2] = mp2[index2+1:]
+ index += N2-index2
+ else: # both arrays reached the end simultaneously
+ x_new[index+1] = x1[-1]
+ y_new[index+1] = y1[-1] + y2[-1]
+ mp_new[index+1] = mp1[-1] + mp2[-1]
+ index += 1
y_new[0] = y_new[1]
mp_new[0] = mp_new[1]
diff --git a/pyspike/spike_sync.py b/pyspike/spike_sync.py
index 617dd86..80f7805 100644
--- a/pyspike/spike_sync.py
+++ b/pyspike/spike_sync.py
@@ -215,7 +215,10 @@ def spike_sync_bi(spike_train1, spike_train2, interval=None, max_tau=None):
"""
c, mp = _spike_sync_values(spike_train1, spike_train2, interval, max_tau)
- return 1.0*c/mp
+ if mp == 0:
+ return 1.0
+ else:
+ return 1.0*c/mp
############################################################
@@ -257,7 +260,10 @@ def spike_sync_multi(spike_trains, indices=None, interval=None, max_tau=None):
coincidence += c
mp += m
- return coincidence/mp
+ if mp == 0.0:
+ return 1.0
+ else:
+ return coincidence/mp
############################################################
diff --git a/pyspike/spikes.py b/pyspike/spikes.py
index b18d7eb..486a4a0 100644
--- a/pyspike/spikes.py
+++ b/pyspike/spikes.py
@@ -2,6 +2,7 @@
# Copyright 2014, Mario Mulansky <mario.mulansky@gmx.net>
# Distributed under the BSD License
+
import numpy as np
from pyspike import SpikeTrain
@@ -25,7 +26,7 @@ def spike_train_from_string(s, edges, sep=' ', is_sorted=False):
############################################################
-# load_spike_trains_txt
+# load_spike_trains_from_txt
############################################################
def load_spike_trains_from_txt(file_name, edges,
separator=' ', comment='#', is_sorted=False,
@@ -47,16 +48,65 @@ def load_spike_trains_from_txt(file_name, edges,
:returns: list of :class:`.SpikeTrain`
"""
spike_trains = []
- spike_file = open(file_name, 'r')
- for line in spike_file:
- if len(line) > 1 and not line.startswith(comment):
- # use only the lines with actual data and not commented
- spike_train = spike_train_from_string(line, edges,
- separator, is_sorted)
- spike_trains.append(spike_train)
+ with open(file_name, 'r') as spike_file:
+ for line in spike_file:
+ if not line.startswith(comment): # ignore comments
+ if len(line) > 1:
+ # ignore empty lines
+ spike_train = spike_train_from_string(line, edges,
+ separator, is_sorted)
+ spike_trains.append(spike_train)
+ elif not(ignore_empty_lines):
+ # add empty spike train
+ spike_trains.append(SpikeTrain([], edges))
return spike_trains
+def import_spike_trains_from_time_series(file_name, start_time, time_bin,
+ separator=None, comment='#'):
+ """ Imports spike trains from time series consisting of 0 and 1 denoting
+ the absence or presence of a spike. Each line in the data file represents
+ one spike train.
+
+ :param file_name: The name of the data file containing the time series.
+ :param edges: A pair (T_start, T_end) of values representing the
+ start and end time of the spike train measurement
+ or a single value representing the end time, the
+ T_start is then assuemd as 0.
+ :param separator: The character used to seprate the values in the text file
+ :param comment: Lines starting with this character are ignored.
+
+ """
+ data = np.loadtxt(file_name, comments=comment, delimiter=separator)
+ time_points = start_time + time_bin + np.arange(len(data[0, :]))*time_bin
+ spike_trains = []
+ for time_series in data:
+ spike_trains.append(SpikeTrain(time_points[time_series > 0],
+ edges=[start_time,
+ time_points[-1]]))
+ return spike_trains
+
+
+############################################################
+# save_spike_trains_to_txt
+############################################################
+def save_spike_trains_to_txt(spike_trains, file_name,
+ separator=' ', precision=8):
+ """ Saves the given spike trains into a file with the given file name.
+ Each spike train will be stored in one line in the text file with the times
+ separated by `separator`.
+
+ :param spike_trains: List of :class:`.SpikeTrain` objects
+ :param file_name: The name of the text file.
+ """
+ # format string to print the spike times with given precision
+ format_str = "{0:.%de}" % precision
+ with open(file_name, 'w') as spike_file:
+ for st in spike_trains:
+ s = separator.join(map(format_str.format, st.spikes))
+ spike_file.write(s+'\n')
+
+
############################################################
# merge_spike_trains
############################################################