Source code for ipfx.time_series_utils
import sys
import numpy as np
import scipy.signal as signal
[docs]def find_time_index(t, t_0):
""" Find the index value of a given time (t_0) in a time series (t).
Parameters
----------
t : time array
t_0 : time point to find an index
Returns
-------
idx: index of t closest to t_0
"""
assert t[0] <= t_0 <= t[-1], "Given time ({:f}) is outside of time range ({:f}, {:f})".format(t_0, t[0], t[-1])
idx = np.argmin(abs(t - t_0))
return idx
[docs]def calculate_dvdt(v, t, filter=None):
"""Low-pass filters (if requested) and differentiates voltage by time.
Parameters
----------
v : numpy array of voltage time series in mV
t : numpy array of times in seconds
filter : cutoff frequency for 4-pole low-pass Bessel filter in kHz (optional, default None)
Returns
-------
dvdt : numpy array of time-derivative of voltage (V/s = mV/ms)
"""
if has_fixed_dt(t) and filter:
delta_t = t[1] - t[0]
sample_freq = 1. / delta_t
filt_coeff = (filter * 1e3) / (sample_freq / 2.) # filter kHz -> Hz, then get fraction of Nyquist frequency
if filt_coeff < 0 or filt_coeff >= 1:
raise ValueError("bessel coeff ({:f}) is outside of valid range [0,1); cannot filter sampling frequency {:.1f} kHz with cutoff frequency {:.1f} kHz.".format(filt_coeff, sample_freq / 1e3, filter))
b, a = signal.bessel(4, filt_coeff, "low")
v_filt = signal.filtfilt(b, a, v, axis=0)
dv = np.diff(v_filt)
else:
dv = np.diff(v)
dt = np.diff(t)
dvdt = 1e-3 * dv / dt # in V/s = mV/ms
# some data sources, such as neuron, occasionally report
# duplicate timestamps, so we require that dt is not 0
return dvdt[np.fabs(dt) > sys.float_info.epsilon]
[docs]def has_fixed_dt(t):
"""Check that all time intervals are identical."""
dt = np.diff(t)
return np.allclose(dt, np.ones_like(dt) * dt[0])
[docs]def average_voltage(v, t, start=None, end=None):
"""Calculate average voltage between start and end.
Parameters
----------
v : numpy array of voltage time series in mV
t : numpy array of times in seconds
start : start of time window for spike detection (optional, default None)
end : end of time window for spike detection (optional, default None)
Returns
-------
v_avg : average voltage
"""
if start is None:
start = t[0]
if end is None:
end = t[-1]
start_index = find_time_index(t, start)
end_index = find_time_index(t, end)
return v[start_index:end_index].mean()
[docs]def flatnotnan(a):
"""
Returns indices that are non nan in a flattened version of a
Parameters
----------
a: np.array
Returns
-------
res: np.array
Output array containing indices of an array that are not nan
"""
notnan = np.argwhere(~np.isnan(a))
return notnan.flatten()