I'm trying to write a function that would detect all rising edges - indexes in a vector where value exceeds certain threshold. Something similar is described here: Python rising/falling edge oscilloscope-like trigger, but I want to add hysteresis, so that trigger won't fire unless the value goes below another limit.
I came up the following code:
import numpy as np
arr = np.linspace(-10, 10, 60)
sample_values = np.sin(arr) + 0.6 * np.sin(arr*3)
above_trigger = sample_values > 0.6
below_deadband = sample_values < 0.0
combined = 1 * above_trigger - 1 * below_deadband
Now in the combined
array there is 1
where the original value was above upper limit, -1
where the value was below lower limit and 0
where the value was in between:
>>> combined
array([ 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 0, 0,
1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1,
0, 0, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1, 0, 0, 1, 1, 1, 0, -1, -1])
My idea was to use some clever function that would process this vector sequentially and replace all sequences of zeros with whatever non-zero value was preceding them. Then the problem would boil down to simply finding where the value changes from -1
to 1
.
I though that greater
operation would fulfill this purpose if used correctly: -1
encoded as True
and 1
as False
:
- (
True
("-1") >-1
) ->True
("-1") - (
True
("-1") >1
) ->False
("1") - (
True
("-1") >0
) ->True
("-1") - (
False
("1") >-1
) ->True
("-1") - (
False
("1") >1
) ->False
("1") - (
False
("1") >0
) ->False
("1")
But the results are not what I expect:
>>> 1 - 2 * np.greater.accumulate(combined)
array([-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1])
It seems that the greater
function doesn't correctly compare booleans with numeric values in this scenario, even though it works fine when used on scalars or pair-wise:
>>> np.greater(False, -1)
True
>>> np.greater.outer(False, combined)
array([False, False, True, True, True, True, True, True, True,
True, True, False, False, False, False, False, False, False,
False, False, False, True, True, True, True, True, True,
True, True, True, False, False, False, False, False, False,
False, False, False, True, True, True, True, True, True,
True, True, True, True, False, False, False, False, False,
False, False, False, False, True, True])
Is this expected behavior? Am I doing something wrong here, is there any way around this?
Alternatively, maybe you could suggest another approach to this problem?
Thank you.