Source code for cnmodel.util.find_point
from scipy import interpolate
import numpy as np
[docs]def find_point(x, y, peakindex, val, direction='left', limits=None):
"""
Given a waveform defined by *x* and *y* arrays, return the first time
at which the waveform crosses (y[peakindex] * val). The search begins at
*peakindex* and proceeds in *direction*.
Optionally, *limits* may specify a smaller search region in the form of
(t0, t1, dt).
"""
#F = interpolate.UnivariateSpline(x, y, s=0) # declare function
#To find x at y then do:
istart = 0
iend = len(y)
if limits is not None:
istart = int(limits[0] / limits[2])
iend = int(limits[1] / limits[2])
yToFind = y[peakindex] * val
if direction == 'left':
yreduced = np.array(y[istart:peakindex]) - yToFind
try:
Fr = interpolate.UnivariateSpline(x[istart:peakindex], yreduced, s=0)
except:
print 'find_point: insufficient time points for analysis'
print 'arg lengths:', len(x[istart:peakindex]), len(yreduced)
print 'istart, peakindex: ', istart, peakindex
print 'ytofine: ', yToFind
raise
res = float('nan')
return (res)
res = Fr.roots()
if len(res) > 1:
res = res[-1]
else:
yreduced = np.array(y[peakindex:iend]) - yToFind
try:
Fr = interpolate.UnivariateSpline(x[peakindex:iend], yreduced, s=0)
except:
print 'find_point: insufficient time points for analysis?'
print 'arg lengths:', len(x[peakindex:iend]), len(yreduced)
raise
res = float('nan')
return (res)
res = Fr.roots()
if len(res) > 1:
res = res[0]
#pdb.set_trace()
try:
res.pop()
except:
pass
if not res: # tricky - an empty list is False, but does not evaluate to False
res = float('nan') # replace with a NaN
else:
res = float(res) # make sure is just a simple number (no arrays)
return (res)
[docs]def find_crossing(data, start=0, direction=1, threshold=0):
"""Return the index at which *data* crosses *threshold*, starting
at index *start* and proceeding in *direction* (+/-1).
The value returned is a float indicating the interpolated index
position where the data crosses threshold, or NaN if the threshold was
never crossed.
"""
# Note: this function is very similar in purpose to find_point, but was
# added due to issues with interpolate.UnivariateSpline
assert direction in (1, -1)
cross_rising = data[start] < threshold
def test(x):
if cross_rising:
return x > threshold
else:
return x < threshold
while True:
next_ind = start + direction
if next_ind < 0 or next_ind >= len(data):
return np.nan
if test(data[next_ind]):
# crossed; return interpolated value
s1 = data[next_ind] - threshold
s2 = threshold = data[start]
return (next_ind * s2 + start * s1) / (s2 + s1)
start = next_ind