diff options
Diffstat (limited to 'pyspike/isi_distance.py')
-rw-r--r-- | pyspike/isi_distance.py | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/pyspike/isi_distance.py b/pyspike/isi_distance.py new file mode 100644 index 0000000..e91dce2 --- /dev/null +++ b/pyspike/isi_distance.py @@ -0,0 +1,230 @@ +# Module containing several functions to compute the ISI profiles and distances +# Copyright 2014-2015, Mario Mulansky <mario.mulansky@gmx.net> +# Distributed under the BSD License + +from __future__ import absolute_import + +import pyspike +from pyspike import PieceWiseConstFunc +from pyspike.generic import _generic_profile_multi, _generic_distance_multi, \ + _generic_distance_matrix + + +############################################################ +# isi_profile +############################################################ +def isi_profile(*args, **kwargs): + """ Computes the isi-distance profile :math:`I(t)` of the given + spike trains. Returns the profile as a PieceWiseConstFunc object. The + ISI-values are defined positive :math:`I(t)>=0`. + + Valid call structures:: + + isi_profile(st1, st2) # returns the bi-variate profile + isi_profile(st1, st2, st3) # multi-variate profile of 3 spike trains + + spike_trains = [st1, st2, st3, st4] # list of spike trains + isi_profile(spike_trains) # profile of the list of spike trains + isi_profile(spike_trains, indices=[0, 1]) # use only the spike trains + # given by the indices + + The multivariate ISI distance profile for a set of spike trains is defined + as the average ISI-profile of all pairs of spike-trains: + + .. math:: <I(t)> = \\frac{2}{N(N-1)} \\sum_{<i,j>} I^{i,j}, + + where the sum goes over all pairs <i,j> + + + :returns: The isi-distance profile :math:`I(t)` + :rtype: :class:`.PieceWiseConstFunc` + """ + if len(args) == 1: + return isi_profile_multi(args[0], **kwargs) + elif len(args) == 2: + return isi_profile_bi(args[0], args[1]) + else: + return isi_profile_multi(args) + + +############################################################ +# isi_profile_bi +############################################################ +def isi_profile_bi(spike_train1, spike_train2): + """ Specific function to compute a bivariate ISI-profile. This is a + deprecated function and should not be called directly. Use + :func:`.isi_profile` to compute ISI-profiles. + + :param spike_train1: First spike train. + :type spike_train1: :class:`.SpikeTrain` + :param spike_train2: Second spike train. + :type spike_train2: :class:`.SpikeTrain` + :returns: The isi-distance profile :math:`I(t)` + :rtype: :class:`.PieceWiseConstFunc` + + """ + # check whether the spike trains are defined for the same interval + assert spike_train1.t_start == spike_train2.t_start, \ + "Given spike trains are not defined on the same interval!" + assert spike_train1.t_end == spike_train2.t_end, \ + "Given spike trains are not defined on the same interval!" + + # load cython implementation + try: + from .cython.cython_profiles import isi_profile_cython \ + as isi_profile_impl + except ImportError: + if not(pyspike.disable_backend_warning): + print("Warning: isi_profile_cython not found. Make sure that \ +PySpike is installed by running\n 'python setup.py build_ext --inplace'!\n \ +Falling back to slow python backend.") + # use python backend + from .cython.python_backend import isi_distance_python \ + as isi_profile_impl + + times, values = isi_profile_impl(spike_train1.get_spikes_non_empty(), + spike_train2.get_spikes_non_empty(), + spike_train1.t_start, spike_train1.t_end) + return PieceWiseConstFunc(times, values) + + +############################################################ +# isi_profile_multi +############################################################ +def isi_profile_multi(spike_trains, indices=None): + """ Specific function to compute the multivariate ISI-profile for a set of + spike trains. This is a deprecated function and should not be called + directly. Use :func:`.isi_profile` to compute ISI-profiles. + + + :param spike_trains: list of :class:`.SpikeTrain` + :param indices: list of indices defining which spike trains to use, + if None all given spike trains are used (default=None) + :type state: list or None + :returns: The averaged isi profile :math:`<I(t)>` + :rtype: :class:`.PieceWiseConstFunc` + """ + average_dist, M = _generic_profile_multi(spike_trains, isi_profile_bi, + indices) + average_dist.mul_scalar(1.0/M) # normalize + return average_dist + + +############################################################ +# isi_distance +############################################################ +def isi_distance(*args, **kwargs): + """ Computes the ISI-distance :math:`D_I` of the given spike trains. The + isi-distance is the integral over the isi distance profile + :math:`I(t)`: + + .. math:: D_I = \\int_{T_0}^{T_1} I(t) dt. + + In the multivariate case it is the integral over the multivariate + ISI-profile, i.e. the average profile over all spike train pairs: + + .. math:: D_I = \\int_0^T \\frac{2}{N(N-1)} \\sum_{<i,j>} I^{i,j}, + + where the sum goes over all pairs <i,j> + + + + Valid call structures:: + + isi_distance(st1, st2) # returns the bi-variate distance + isi_distance(st1, st2, st3) # multi-variate distance of 3 spike trains + + spike_trains = [st1, st2, st3, st4] # list of spike trains + isi_distance(spike_trains) # distance of the list of spike trains + isi_distance(spike_trains, indices=[0, 1]) # use only the spike trains + # given by the indices + + :returns: The isi-distance :math:`D_I`. + :rtype: double + """ + + if len(args) == 1: + return isi_distance_multi(args[0], **kwargs) + elif len(args) == 2: + return isi_distance_bi(args[0], args[1], **kwargs) + else: + return isi_distance_multi(args, **kwargs) + + +############################################################ +# _isi_distance_bi +############################################################ +def isi_distance_bi(spike_train1, spike_train2, interval=None): + """ Specific function to compute the bivariate ISI-distance. + This is a deprecated function and should not be called directly. Use + :func:`.isi_distance` to compute ISI-distances. + + :param spike_train1: First spike train. + :type spike_train1: :class:`.SpikeTrain` + :param spike_train2: Second spike train. + :type spike_train2: :class:`.SpikeTrain` + :param interval: averaging interval given as a pair of floats (T0, T1), + if None the average over the whole function is computed. + :type interval: Pair of floats or None. + :returns: The isi-distance :math:`D_I`. + :rtype: double + """ + + if interval is None: + # distance over the whole interval is requested: use specific function + # for optimal performance + try: + from .cython.cython_distances import isi_distance_cython \ + as isi_distance_impl + + return isi_distance_impl(spike_train1.get_spikes_non_empty(), + spike_train2.get_spikes_non_empty(), + spike_train1.t_start, spike_train1.t_end) + except ImportError: + # Cython backend not available: fall back to profile averaging + return isi_profile_bi(spike_train1, spike_train2).avrg(interval) + else: + # some specific interval is provided: use profile + return isi_profile_bi(spike_train1, spike_train2).avrg(interval) + + +############################################################ +# isi_distance_multi +############################################################ +def isi_distance_multi(spike_trains, indices=None, interval=None): + """ Specific function to compute the multivariate ISI-distance. + This is a deprecfated function and should not be called directly. Use + :func:`.isi_distance` to compute ISI-distances. + + :param spike_trains: list of :class:`.SpikeTrain` + :param indices: list of indices defining which spike trains to use, + if None all given spike trains are used (default=None) + :param interval: averaging interval given as a pair of floats, if None + the average over the whole function is computed. + :type interval: Pair of floats or None. + :returns: The time-averaged multivariate ISI distance :math:`D_I` + :rtype: double + """ + return _generic_distance_multi(spike_trains, isi_distance_bi, indices, + interval) + + +############################################################ +# isi_distance_matrix +############################################################ +def isi_distance_matrix(spike_trains, indices=None, interval=None): + """ Computes the time averaged isi-distance of all pairs of spike-trains. + + :param spike_trains: list of :class:`.SpikeTrain` + :param indices: list of indices defining which spike trains to use, + if None all given spike trains are used (default=None) + :type indices: list or None + :param interval: averaging interval given as a pair of floats, if None + the average over the whole function is computed. + :type interval: Pair of floats or None. + :returns: 2D array with the pair wise time average isi distances + :math:`D_{I}^{ij}` + :rtype: np.array + """ + return _generic_distance_matrix(spike_trains, isi_distance_bi, + indices=indices, interval=interval) |