steve_bank
Diabetic retinopathy and poor eyesight. Typos ...
Finding zero crossings is straight forward. Just look for a sign change in the data an unambiguous indication of a zero.
The problem is given a peak that is mathematically exactly at zero the odds of it being exactly zero with sampled data and digital commutation is low.
My solution was to find the peaks and see how close to zero they are. Set a limit window for a zero. Alternatively the data could be rounded to a limited number of decimal places.
The 1st derivative is used to find an infection point indicating a peak. The derivative is dy/dx but dividing by dx is unnecessary.
In the plot there is a local minimum at abound 0.55 seconds close to zero. Vary the number added to y + y2 in the code to move the curve up and down about zero to test the code.
Python
The problem is given a peak that is mathematically exactly at zero the odds of it being exactly zero with sampled data and digital commutation is low.
My solution was to find the peaks and see how close to zero they are. Set a limit window for a zero. Alternatively the data could be rounded to a limited number of decimal places.
The 1st derivative is used to find an infection point indicating a peak. The derivative is dy/dx but dividing by dx is unnecessary.
In the plot there is a local minimum at abound 0.55 seconds close to zero. Vary the number added to y + y2 in the code to move the curve up and down about zero to test the code.
Python
Code:
import numpy as np
import array as ar
import math as ma
import matplotlib.pyplot as plt
def plotxy(xlo,xhi,ylo,yhi,x,y,title,xlabel,ylabel):
# single y plot
font1 = {'family': 'arial',
'color': 'black',
'weight': 'heavy',
'size': 15,
}
[fig, p1] = plt.subplots(1)
p1.plot(x,y,linewidth=2.0,color="k")
p1.grid(color='k', linestyle='-', linewidth=1)
p1.grid(which='major', color='k',linestyle='-', linewidth=0.8)
p1.grid(which='minor', color='k', linestyle='-', linewidth=0.3)
p1.set_xlim(xlo,xhi)
p1.set_ylim(ylo,yhi)
p1.set_title(title, fontdict = font1)
p1.set_xlabel(xlabel, fontdict = font1)
p1.set_ylabel(ylabel, fontdict = font1)
p1.minorticks_on()
plt.show()
def sign(x):
if x >= 0: return 1
return -1
def find_zeros(zmin,x,y):
zcount = 0
n = len(x) - 1
n2 = n - 1
z = ar.array('i') # indeces of zeros
# find xero crossings
for i in range(n):
if y[i] < 0 and y[i+1] > 0:
z.append(i)
zcount += 1
if y[i] > 0 and y[i+1] < 0:
z.append(i)
zcount += 1
# check if peaks are zeros
for i in range(n2):
if sign(y[i+1]-y[i]) != sign(y[i+2]-y[i+1]): # inflection point
# approaching zero from the positive
if y[i+1] >= 0 and y[i+1] < zmin and sign(y[i+1]-y[i]) == -1:
z.append(i+1)
zcount += 1;
# approaching zero from the negative
if y[i+1] <= 0 and y[i+1] > -zmin and sign(y[i+1]-y[i]) == 1:
z.append(i+1)
zcount += 1
# check end points
if abs(y[0]) >= 0 and abs(y[0]) < zmin:
z.append(i)
zcount += 1
if abs(y[n-1]) >= 0 and abs(y[0]) < zmin:
z.append(i)
zcount += 1
z = np.sort(z)
return z
n = 1000
t = np.linspace(0,1,n)
f1 = 2
f2 = 3
y = np.sin(2*np.pi*f1*t)
y2 = np.sin(2*np.pi*f2*t)
y = y + y2 + 0.2235
z = find_zeros(.001,t,y)
nz = len(z)
print(" zero count ",nz)
print("time Y")
for i in range(nz): print("%.10f % .10f"%(t[z[i]],y[z[i]]))
plotxy(min(t),1,-3,3,t,y,"sines","time","")