Finding minimal jump zero crossings in numpy
Here's a solution that gives the midpoint of crossings involving a noise threshold to filter potentially multiple fluctuations around zero applied across multiple data points. It give the correct answers for the two examples you supplied. However, I've made a couple of assumptions:
- You didn't define precisely what range of data points to consider to determine the midpoint of the crossing, but I've used your sample code as a basis - it was detecting crossings where
ABS(start | end) >= 10
hence I've used the minimum range where this condition holds.
NB: This does not detect a transition from +15 to -6.
EDIT: Actually it's not always the minimum range, but the code should be enough for you to get started and adjust as needed. - I've assumed that it is ok to also use pandas (to track the indexes of data points of interest). You could probably avoid pandas if essential.
import numpy as np
import pandas as pd
arr = np.array([12, 15, 9, 8, -1, 1, -12, -10, 10])
sgn = pd.Series(np.sign(np.trunc(arr/10)))
trailingEdge = sgn[sgn!=0].diff()
edgeIndex = np.array(trailingEdge[trailingEdge!=0].index)
edgeIndex[:-1] + np.diff(edgeIndex) / 2
gives:
array([3., 7.])
and
arr = [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
gives:
array([10.])
Base case
I guess you want
import numpy as np
x = np.array([10, -50, -30, 50, 10, 3, -200, -12, 123])
indices = np.where(np.logical_and(np.abs(np.diff(x)) >= 20, np.diff(np.sign(x)) != 0))[0]
read as: indices, where ((absolute differences of x) are larger or equal 20) and (the sign flips)
which returns
array([0, 2, 5, 7])
Periodic signal
The usual numpy functions don't cover this case. I would suggest simply adding the first element in the end, via the pad function:
import numpy as np
x = np.array([10, 5, 0, -5, -10])
x = np.pad(x, (0, 1), 'wrap')
indices = np.where(np.logical_and(np.abs(np.diff(x)) >= 20, np.diff(np.sign(x)) != 0))[0]