In numpy, I would like to detect the points at which the signal crosses from (having been previously) below a certain threshold, to being above a certain other threshold. T
Modifications I had to do for my work, all based on the answer above by Bas Swinckels, to permit detection of threshold-crossing when using standard as well as reversed thresholds.
I'm not happy with the naming tough, maybe it should now read th_hi2lo and th_lo2hi instead of th_lo and th_hi? Using the original values, the behaviour ist the same tough.
def hyst(x, th_lo, th_hi, initial = False):
"""
x : Numpy Array
Series to apply hysteresis to.
th_lo : float or int
Below this threshold the value of hyst will be False (0).
th_hi : float or int
Above this threshold the value of hyst will be True (1).
"""
if th_lo > th_hi: # If thresholds are reversed, x must be reversed as well
x = x[::-1]
th_lo, th_hi = th_hi, th_lo
rev = True
else:
rev = False
hi = x >= th_hi
lo_or_hi = (x <= th_lo) | hi
ind = np.nonzero(lo_or_hi)[0] # Index für alle darunter oder darüber
if not ind.size: # prevent index error if ind is empty
x_hyst = np.zeros_like(x, dtype=bool) | initial
else:
cnt = np.cumsum(lo_or_hi) # from 0 to len(x)
x_hyst = np.where(cnt, hi[ind[cnt-1]], initial)
if rev:
x_hyst = x_hyst[::-1]
return x_hyst
And as above a test of the code to see what it does:
x = np.linspace(0,20, 1000)
y = np.sin(x)
h1 = hyst(y, -0.2, 0.2)
h2 = hyst(y, +0.5, -0.5)
plt.plot(x, y, x, -0.2 + h1*0.4, x, -0.5 + h2)
plt.legend(('input', 'output, classic, hyst(y, -0.2, +0.2)',
'output, reversed, hyst(y, +0.5, -0.5)'))
plt.title('Thresholding with hysteresis')
plt.show()