Here's one way with convolution -
def cross_thresh_convolve(arr, thresh, N):
# Detect if arr crosses thresh for N consecutive times anywhere
return (np.convolve(arr>=thresh,np.ones(N,dtype=int))==N).any()
Alternatively with binary-dilation -
from scipy.ndimage.morphology import binary_erosion
def cross_thresh_erosion(arr, thresh, N):
return binary_erosion(arr>=thresh, np.ones(N)).any()
Sample runs -
In [43]: arr1 = np.array([1,2,1,3,4,5,6,7])
...: arr2 = np.array([1,2,1,3,4,2,6,7])
In [44]: print cross_thresh_convolve(arr1, thresh=3, N=4)
...: print cross_thresh_erosion(arr1, thresh=3, N=4)
...: print cross_thresh_convolve(arr2, thresh=3, N=4)
...: print cross_thresh_erosion(arr2, thresh=3, N=4)
True
True
False
False
Generic comparisons
To cover generic comparisons, say if we want to look for greater or less-than or even simply compare for equality against a value, we could use NumPy builtin comparison functions to replace the arr>=thresh part from earlier solutions and hence give ourselves generic implementations, like so -
def consecutive_comp_convolve(arr, comp, N, comparison=np.greater_equal):
return (np.convolve(comparison(arr,comp),np.ones(N,dtype=int))==N).any()
def consecutive_comp_erosion(arr, comp, N, comparison=np.greater_equal):
return binary_erosion(comparison(arr,comp), np.ones(N)).any()
Hence, our specific case runs would be -
consecutive_comp_convolve(arr1, comp=3, N=4, comparison=np.greater_equal)
consecutive_comp_erosion(arr1, comp=3, N=4, comparison=np.greater_equal)
consecutive_comp_convolve(arr2, comp=3, N=4, comparison=np.greater_equal)
consecutive_comp_erosion(arr2, comp=3, N=4, comparison=np.greater_equal)