找到数组低于特定阈值的第一个索引(并保持低于一段时间)

Find the first index for which an array goes below a certain threshold (and stay below for some time)

A 为一维 numpy 数组、阈值 t 和 window 长度 K

如何找到最小索引 j,使得 A[j:j+K] < t?(即 A 第一次低于阈值 在宽度为 K) 的完整 window 上。

我已经尝试过(未完成)循环的事情,但它似乎远非最佳,我想也许有一个聪明的 "numpy way" 可以做到这一点。


旁注:我们想要测试在某个 window 长度 期间我们是否低于阈值 而不是 ponctual 值这一事实有助于避免 on/off/on/off/on/off 接近阈值的人工制品(另见 Hysteresis"hysteresis is intentionally added to an electronic circuit to prevent unwanted rapid switching [...] compensate for contact bounce in switches, or noise in an electrical signal.")。

方法 #1

我们可以使用1D convolution-

np.flatnonzero(np.convolve(A<t, np.ones(K,dtype=int))==K)[0]-K+1

想法是在与阈值比较后得到布尔数组,然后运行一个1D卷积,内核长度与window相同,填充1s.这给了我们每次滑动的总和 window。所以,总和为 K 的所有 windows 就是我们要找的那些。使用 flatnonzero 获取有效 windows 的起始索引。最后,select第一个

方法 #2

binary-erosion-

from scipy.ndimage.morphology import binary_erosion

np.flatnonzero(binary_erosion(A<t, np.ones(K), origin=-(K//2)))[0]

这 运行 是一个长度与 window 相同的滑动内核,并侵蚀掉所有 windows 没有 window 长度 True 的内核按顺序,给我们留下有效的。同样,使用 flatnonzero 获取索引,最后使用 select 第一个。我们需要将 arg origin 与二进制侵蚀一起使用,这样我们 select 就开始了。

方法 #3

这是另一个发现岛屿的 -

# Get mask of valid elements with comparison against thresh
mask = np.r_[False,A<t,False]

# Get indices of starts and ends for the valid islands
idx = np.flatnonzero(mask[:-1] != mask[1:])
start,stop = idx[::2],idx[1::2]

# Get the island lengths and check for lengths >=K and mask  start indices
# and select the first one among them
out = start[(stop - start)>=K][0]