You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.1 KiB
95 lines
3.1 KiB
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
|
|
|