# Module containing several functions to compute SPIKE profiles and distances # Copyright 2014-2015, Mario Mulansky # Distributed under the BSD License from __future__ import absolute_import import pyspike from pyspike import PieceWiseLinFunc from pyspike.generic import _generic_profile_multi, _generic_distance_multi, \ _generic_distance_matrix ############################################################ # spike_profile ############################################################ def spike_profile(*args, **kwargs): """ Computes the spike-distance profile :math:`S(t)` of the given spike trains. Returns the profile as a PieceWiseConstLin object. The SPIKE-values are defined positive :math:`S(t)>=0`. Valid call structures:: spike_profile(st1, st2) # returns the bi-variate profile spike_profile(st1, st2, st3) # multi-variate profile of 3 spike trains spike_trains = [st1, st2, st3, st4] # list of spike trains spike_profile(spike_trains) # profile of the list of spike trains spike_profile(spike_trains, indices=[0, 1]) # use only the spike trains # given by the indices The multivariate spike-distance profile is defined as the average of all pairs of spike-trains: .. math:: = \\frac{2}{N(N-1)} \\sum_{} S^{i, j}`, where the sum goes over all pairs :returns: The spike-distance profile :math:`S(t)` :rtype: :class:`.PieceWiseConstLin` """ if len(args) == 1: return spike_profile_multi(args[0], **kwargs) elif len(args) == 2: return spike_profile_bi(args[0], args[1]) else: return spike_profile_multi(args) ############################################################ # spike_profile_bi ############################################################ def spike_profile_bi(spike_train1, spike_train2): """ Specific function to compute a bivariate SPIKE-profile. This is a deprecated function and should not be called directly. Use :func:`.spike_profile` to compute SPIKE-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 spike-distance profile :math:`S(t)`. :rtype: :class:`.PieceWiseLinFunc` """ # 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!" # cython implementation try: from .cython.cython_profiles import spike_profile_cython \ as spike_profile_impl except ImportError: if not(pyspike.disable_backend_warning): print("Warning: spike_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 spike_distance_python \ as spike_profile_impl times, y_starts, y_ends = spike_profile_impl( spike_train1.get_spikes_non_empty(), spike_train2.get_spikes_non_empty(), spike_train1.t_start, spike_train1.t_end) return PieceWiseLinFunc(times, y_starts, y_ends) ############################################################ # spike_profile_multi ############################################################ def spike_profile_multi(spike_trains, indices=None): """ Specific function to compute a multivariate SPIKE-profile. This is a deprecated function and should not be called directly. Use :func:`.spike_profile` to compute SPIKE-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 indices: list or None :returns: The averaged spike profile :math:`(t)` :rtype: :class:`.PieceWiseLinFunc` """ average_dist, M = _generic_profile_multi(spike_trains, spike_profile_bi, indices) average_dist.mul_scalar(1.0/M) # normalize return average_dist ############################################################ # spike_distance ############################################################ def spike_distance(*args, **kwargs): """ Computes the SPIKE-distance :math:`D_S` of the given spike trains. The spike-distance is the integral over the spike distance profile :math:`D(t)`: .. math:: D_S = \\int_{T_0}^{T_1} S(t) dt. Valid call structures:: spike_distance(st1, st2) # returns the bi-variate distance spike_distance(st1, st2, st3) # multi-variate distance of 3 spike trains spike_trains = [st1, st2, st3, st4] # list of spike trains spike_distance(spike_trains) # distance of the list of spike trains spike_distance(spike_trains, indices=[0, 1]) # use only the spike trains # given by the indices In the multivariate case, the spike distance is given as the integral over the multivariate profile, that is the average profile of all spike train pairs: .. math:: D_S = \\int_0^T \\frac{2}{N(N-1)} \\sum_{} S^{i, j} dt :returns: The spike-distance :math:`D_S`. :rtype: double """ if len(args) == 1: return spike_distance_multi(args[0], **kwargs) elif len(args) == 2: return spike_distance_bi(args[0], args[1], **kwargs) else: return spike_distance_multi(args, **kwargs) ############################################################ # spike_distance_bi ############################################################ def spike_distance_bi(spike_train1, spike_train2, interval=None): """ Specific function to compute a bivariate SPIKE-distance. This is a deprecated function and should not be called directly. Use :func:`.spike_distance` to compute SPIKE-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 spike-distance. :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 spike_distance_cython \ as spike_distance_impl return spike_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 average profile return spike_profile_bi(spike_train1, spike_train2).avrg(interval) else: # some specific interval is provided: compute the whole profile return spike_profile_bi(spike_train1, spike_train2).avrg(interval) ############################################################ # spike_distance_multi ############################################################ def spike_distance_multi(spike_trains, indices=None, interval=None): """ Specific function to compute a multivariate SPIKE-distance. This is a deprecated function and should not be called directly. Use :func:`.spike_distance` to compute SPIKE-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) :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: The averaged multi-variate spike distance :math:`D_S`. :rtype: double """ return _generic_distance_multi(spike_trains, spike_distance_bi, indices, interval) ############################################################ # spike_distance_matrix ############################################################ def spike_distance_matrix(spike_trains, indices=None, interval=None): """ Computes the time averaged spike-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 spike distances :math:`D_S^{ij}` :rtype: np.array """ return _generic_distance_matrix(spike_trains, spike_distance_bi, indices, interval)