1

How could I get a list of all the zeroes of a matplotlib graph? By zeroes I mean every coordinate where the y-value of my function is at 0 (very close to zero also works for what I'm trying to accomplish). My code and the graph it generates are down below.

THE .WAV FILE: https://drive.google.com/drive/folders/11nE0nyd9UPViicSIKNeiBqSNbdWGRbIl?usp=sharing

MY CODE:

from scipy.io import wavfile
import matplotlib.pyplot as plt
import numpy as np

samplerate, data = wavfile.read(r'C:\Users\jack_l\Downloads\louduntitled.wav')
length = data.shape[0] / samplerate
import matplotlib.pyplot as plt
import numpy as np
time = np.linspace(0., length, data.shape[0])
plt.plot(time, data[:, 1], label="Right channel")
plt.legend()
plt.xlabel("Time [s]")
plt.ylabel("Amplitude")
plt.show()

GRAPH:

Graph

  • 1
    The x values are 0 at exactly one point: x=0. I assume you mean the y values, but if you have the data, you don't need the plot which is just a single "view" of the data. – erip Jul 26 '22 at 14:08
  • erip Actually I think there isn't any 0 in his data, he kinda want an interpolation – ArrowRise Jul 26 '22 at 14:09
  • Yes, the best you can talk about for discretized continuous data is ranges where a 0 appears which makes the problem slightly easier: for each window defined by your timestep, check if the sign changes between the start and stop. – erip Jul 26 '22 at 14:11
  • @erip You're correct – I meant I want the coordinates where the y-value is equal to 0 (or very close to 0). How could I get what I'm looking for just using the data? – THEMOUNTAINSANDTHESKIES Jul 26 '22 at 14:18

2 Answers2

1

I believe you want to find all times where the y-value is zero.

What about finding zero-crossings of the array data[:, 1] (here a), and use the returned indices to find the interpolated time values where y-value is zero.

CODE

import matplotlib.pyplot as plt
import numpy as np
from scipy.io import wavfile

# load data
samplerate, data = wavfile.read(r'C:\Users\jack_l\Downloads\louduntitled.wav')
length = data.shape[0] / samplerate
time = np.linspace(0., length, data.shape[0])

a = data[:, 1] # here put your data
zc_idxs = np.where(np.diff(np.sign(a)))[0] # indices of element before zero crossing
t_zero = []
for zc_i in zc_idxs: # interpolate each zero crossing
    t1 = time[zc_i]
    t2 = time[zc_i + 1]
    a1 = a[zc_i]
    a2 = a[zc_i + 1]
    t_zero.append(t1 + (0 - a1) * ((t2 - t1) / (a2 - a1)))

plt.plot(time, a, label="Right channel")
plt.plot(t_zero, np.zeros((len(t_zero), 1)), 'o')
Radarrudi
  • 143
  • 6
0

We can't access to your data, so I used the cos function to have a similar shape.

Here is my code that perform a linear interpolation (there's a small error due to the non-linear behavior of the cos function)

import numpy as np

n = 2000
x = np.linspace(0, 10, n)
y = np.cos(x)

res = []
is_positive = y[0] > 0
for i in range(n):
    if y[i] == 0:
        res.append(x[i])
    elif (is_positive and y[i] < 0) or (not is_positive and y[i] > 0):
        x_gap = x[i] - x[i-1]
        coef_gap = y[i]/(y[i] - y[i-1])
        res.append(x[i] + x_gap*coef_gap)
        is_positive = not is_positive
        
analytic_res = [i*np.pi/2 for i in range(1,6,2)]

print(res)
print(analytic_res)

Output :

[1.5807794610537442, 4.722328378160516, 7.863877295269648]
[1.5707963267948966, 4.71238898038469, 7.853981633974483]

NB : if the very first value is zero, the code could have a weird behavior

ArrowRise
  • 608
  • 2
  • 7