from __future__ import print_function from scipy import interpolate import numpy as np 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 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