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]