spiketools.transforms

Transform spike trains or time-resolved signals onto new time axes.

Examples

Shared example setup used throughout the documentation:

import numpy as np

from spiketools import gamma_spikes, gaussian_kernel, kernel_rate, time_warp

np.random.seed(0)
rates = np.array([6.0] * 10 + [5.6, 6.3, 5.9, 6.5, 5.8, 6.1, 5.7, 6.4, 6.0, 5.5], dtype=float)
orders = np.array([0.2] * 10 + [1.0, 2.0, 2.0, 3.0, 1.0, 2.0, 3.0, 2.0, 1.0, 3.0], dtype=float)
spiketimes = gamma_spikes(rates=rates, order=orders, tlim=[0.0, 5000.0], dt=1.0)

kernel = gaussian_kernel(25.0, dt=1.0)
rates, rate_time = kernel_rate(spiketimes, kernel, tlim=[0.0, 5000.0], dt=1.0, pool=True)
warped_spikes = time_warp(spiketimes[0], rate_time, rate_time)
  1"""Transform spike trains or time-resolved signals onto new time axes.
  2
  3Examples
  4--------
  5Shared example setup used throughout the documentation:
  6
  7```python
  8import numpy as np
  9
 10from spiketools import gamma_spikes, gaussian_kernel, kernel_rate, time_warp
 11
 12np.random.seed(0)
 13rates = np.array([6.0] * 10 + [5.6, 6.3, 5.9, 6.5, 5.8, 6.1, 5.7, 6.4, 6.0, 5.5], dtype=float)
 14orders = np.array([0.2] * 10 + [1.0, 2.0, 2.0, 3.0, 1.0, 2.0, 3.0, 2.0, 1.0, 3.0], dtype=float)
 15spiketimes = gamma_spikes(rates=rates, order=orders, tlim=[0.0, 5000.0], dt=1.0)
 16
 17kernel = gaussian_kernel(25.0, dt=1.0)
 18rates, rate_time = kernel_rate(spiketimes, kernel, tlim=[0.0, 5000.0], dt=1.0, pool=True)
 19warped_spikes = time_warp(spiketimes[0], rate_time, rate_time)
 20```
 21"""
 22
 23from __future__ import annotations
 24
 25import pylab
 26
 27__all__ = [
 28    "resample",
 29    "time_stretch",
 30    "time_warp",
 31]
 32
 33
 34def time_warp(events, told, tnew):
 35    """Map event times from one timeline onto another by interpolation.
 36
 37    Parameters
 38    ----------
 39    events:
 40        Event times to transform.
 41    told:
 42        Original reference time axis.
 43    tnew:
 44        New reference axis aligned to `told`.
 45
 46    Returns
 47    -------
 48    np.ndarray
 49        Warped event times. Values outside the interpolation range become `nan`.
 50
 51    Examples
 52    --------
 53    >>> time_warp([0.0, 5.0, 10.0], [0.0, 10.0], [0.0, 20.0]).tolist()
 54    [0.0, 10.0, 20.0]
 55    """
 56    return pylab.interp(events, told, tnew, left=pylab.nan, right=pylab.nan)
 57
 58
 59def time_stretch(spiketimes, stretchstart, stretchend, endtime=None):
 60    """Stretch trial-wise spike times between two markers to a common duration.
 61
 62    Parameters
 63    ----------
 64    spiketimes:
 65        Canonical spike representation. The function modifies and returns this
 66        array in place.
 67    stretchstart:
 68        One start time per trial.
 69    stretchend:
 70        One end time per trial.
 71    endtime:
 72        Common target end time. Defaults to the mean of `stretchend`.
 73
 74    Examples
 75    --------
 76    >>> spikes = pylab.array([[1.0, 3.0, 2.0], [0.0, 0.0, 1.0]])
 77    >>> stretched = time_stretch(spikes.copy(), pylab.array([0.0, 0.0]), pylab.array([4.0, 2.0]), endtime=4.0)
 78    >>> stretched[0].tolist()
 79    [1.0, 3.0, 4.0]
 80    """
 81    if endtime is None:
 82        endtime = stretchend.mean()
 83
 84    trials = pylab.unique(spiketimes[1, :])
 85
 86    for i, trial in enumerate(trials):
 87        trialmask = spiketimes[1, :] == trial
 88        trialspikes = spiketimes[0, trialmask]
 89        trialspikes -= stretchstart[i]
 90        se = stretchend[i] - stretchstart[i]
 91        trialspikes /= se
 92        trialspikes *= endtime - stretchstart[i]
 93        trialspikes += stretchstart[i]
 94        spiketimes[0, trialmask] = trialspikes
 95
 96    return spiketimes
 97
 98
 99def resample(vals, time, new_time):
100    """Interpolate a time-resolved signal onto a new time axis.
101
102    Parameters
103    ----------
104    vals:
105        Values sampled on `time`.
106    time:
107        Original sampling points.
108    new_time:
109        Target sampling points.
110
111    Examples
112    --------
113    >>> resample([0.0, 1.0], [0.0, 2.0], [0.0, 1.0, 2.0]).tolist()
114    [0.0, 0.5, 1.0]
115    """
116    if len(vals) > 0:
117        return pylab.interp(new_time, time, vals, right=pylab.nan, left=pylab.nan)
118    return pylab.ones(new_time.shape) * pylab.nan
def resample(vals, time, new_time):
100def resample(vals, time, new_time):
101    """Interpolate a time-resolved signal onto a new time axis.
102
103    Parameters
104    ----------
105    vals:
106        Values sampled on `time`.
107    time:
108        Original sampling points.
109    new_time:
110        Target sampling points.
111
112    Examples
113    --------
114    >>> resample([0.0, 1.0], [0.0, 2.0], [0.0, 1.0, 2.0]).tolist()
115    [0.0, 0.5, 1.0]
116    """
117    if len(vals) > 0:
118        return pylab.interp(new_time, time, vals, right=pylab.nan, left=pylab.nan)
119    return pylab.ones(new_time.shape) * pylab.nan

Interpolate a time-resolved signal onto a new time axis.

Parameters
  • vals:: Values sampled on time.
  • time:: Original sampling points.
  • new_time:: Target sampling points.
Examples
>>> resample([0.0, 1.0], [0.0, 2.0], [0.0, 1.0, 2.0]).tolist()
[0.0, 0.5, 1.0]
def time_stretch(spiketimes, stretchstart, stretchend, endtime=None):
60def time_stretch(spiketimes, stretchstart, stretchend, endtime=None):
61    """Stretch trial-wise spike times between two markers to a common duration.
62
63    Parameters
64    ----------
65    spiketimes:
66        Canonical spike representation. The function modifies and returns this
67        array in place.
68    stretchstart:
69        One start time per trial.
70    stretchend:
71        One end time per trial.
72    endtime:
73        Common target end time. Defaults to the mean of `stretchend`.
74
75    Examples
76    --------
77    >>> spikes = pylab.array([[1.0, 3.0, 2.0], [0.0, 0.0, 1.0]])
78    >>> stretched = time_stretch(spikes.copy(), pylab.array([0.0, 0.0]), pylab.array([4.0, 2.0]), endtime=4.0)
79    >>> stretched[0].tolist()
80    [1.0, 3.0, 4.0]
81    """
82    if endtime is None:
83        endtime = stretchend.mean()
84
85    trials = pylab.unique(spiketimes[1, :])
86
87    for i, trial in enumerate(trials):
88        trialmask = spiketimes[1, :] == trial
89        trialspikes = spiketimes[0, trialmask]
90        trialspikes -= stretchstart[i]
91        se = stretchend[i] - stretchstart[i]
92        trialspikes /= se
93        trialspikes *= endtime - stretchstart[i]
94        trialspikes += stretchstart[i]
95        spiketimes[0, trialmask] = trialspikes
96
97    return spiketimes

Stretch trial-wise spike times between two markers to a common duration.

Parameters
  • spiketimes:: Canonical spike representation. The function modifies and returns this array in place.
  • stretchstart:: One start time per trial.
  • stretchend:: One end time per trial.
  • endtime:: Common target end time. Defaults to the mean of stretchend.
Examples
>>> spikes = pylab.array([[1.0, 3.0, 2.0], [0.0, 0.0, 1.0]])
>>> stretched = time_stretch(spikes.copy(), pylab.array([0.0, 0.0]), pylab.array([4.0, 2.0]), endtime=4.0)
>>> stretched[0].tolist()
[1.0, 3.0, 4.0]
def time_warp(events, told, tnew):
35def time_warp(events, told, tnew):
36    """Map event times from one timeline onto another by interpolation.
37
38    Parameters
39    ----------
40    events:
41        Event times to transform.
42    told:
43        Original reference time axis.
44    tnew:
45        New reference axis aligned to `told`.
46
47    Returns
48    -------
49    np.ndarray
50        Warped event times. Values outside the interpolation range become `nan`.
51
52    Examples
53    --------
54    >>> time_warp([0.0, 5.0, 10.0], [0.0, 10.0], [0.0, 20.0]).tolist()
55    [0.0, 10.0, 20.0]
56    """
57    return pylab.interp(events, told, tnew, left=pylab.nan, right=pylab.nan)

Map event times from one timeline onto another by interpolation.

Parameters
  • events:: Event times to transform.
  • told:: Original reference time axis.
  • tnew:: New reference axis aligned to told.
Returns
  • np.ndarray: Warped event times. Values outside the interpolation range become nan.
Examples
>>> time_warp([0.0, 5.0, 10.0], [0.0, 10.0], [0.0, 20.0]).tolist()
[0.0, 10.0, 20.0]