I've been trying to get the fourier transform of the data in file S1L1E here https://github.com/gergobes/data-for-fft/blob/c0b664379c0eeab04abdc541e34d6e636e841eb0/S1L1E. First column is time, 2nd column is amplitude of first wave and 3rd column is the amplitude of another wave. The code I tried is;
import matplotlib.pyplot as plt
import numpy as np
from scipy.fft import fft, fftfreq
data = np.loadtxt("S1L1E")
time = data[:,0]
amp_left = data[:,1]
amp_right = data[:,2]
plt.plot(time, amp_left)
plt.plot(time, amp_right)
plt.show()
# fft attempt
samplerate = 5000
duration = time[-1]
N = int(samplerate * duration)
x = time
y = amp_left
yf = fft(y)
xf = fftfreq(len(y))
plt.plot(xf, abs(yf))
plt.show()
I tried for the first wave but got only a spike at 0. What am I doing wrong? It's my first time trying a fft so I'm kinda lost here. I would appreciate any help.
Related
I have four cosines with frequencies 400e-3, 500e-3, 600e-3 and 700e-3 and I am trying to do the FFT of them but under the time I need, I cannot distinguish the four. Is there a way to distinguish the peaks without changing the tmax time of 1.76 and the frequencies?
import numpy as np
import scipy.fftpack
from scipy.fftpack import fftfreq
from scipy.fft import fft
import matplotlib.pyplot as plt
t = np.linspace(0,1.76,2400)
f = [400e-3, 500e-3, 600e-3, 700e-3] # these are the frequencies
yy = 0
for i in f:
y = 0.5*np.cos(2*np.pi*i*t)
yy = yy + y
plt.figure(0)
plt.plot(t, yy)
f = fftfreq(len(t), np.diff(t)[0])
yf = fft(yy)
plt.figure(1)
plt.plot(f[:t.size//2], np.abs(yf[:t.size//2]))
plt.show()
Here are the results:
The solution was to increase tmax of
t = np.linspace(0,1.76,2400)
i.e. 1.76. FFT makes bins the size of 1/tmax and the small tmax is, the bigger the bins are leading to less resolution.
I want to plot a power spectrum from my data set (array of about 2000 values, the data is recorded every minute).
I've gotten so far as:
y= np.fft.fft(data)
abs = np.abs(y) #absolute value
p = np.square(abs) #power
but am confused about setting the frequency.
I've tried using freqs = np.fft.fftfreq(len(y)), but when I plot the result it looks like, which can't be right.
What am I doing wrong?
Here is an example to plot the power spectrum:
import matplotlib.pyplot as plt
import numpy as np
t = np.linspace(0,2000,200)
data = 2 * np.sin(2*np.pi *60*t) + 2 * np.sin(2*np.pi *42*t)
spectrum = np.fft.fft(data)
power_spectrum = np.square(np.abs(spectrum))
fig, ax = plt.subplots()
ax.plot(np.arange(len(power_spectrum)), power_spectrum)
plt.show()
I am trying to do an FFT on a .wav file that contains only a 1 kHz sin wave. When I plot the result, I expect the peak to be at the fundamental (1 kHz) but instead, I see the peak at what seems to be the 3rd harmonic (3 kHz). I have tried 2 other .wav files at 440 Hz and 2 kHz with the same result. I used a frequency counter to verify the .wav files contain the frequencies I expect.
For comparison, I use the commented code below to generate and plot a sin function which displays correctly.
import matplotlib.pyplot as plt
import numpy as np
import wave, struct
sound_file = wave.open('c:\downloads\SineWave_1000Hz.wav', 'r')
file_length = sound_file.getnframes()
data = sound_file.readframes(file_length)
data = struct.unpack('{n}h'.format(n=file_length), data)
data = np.array(data)
sound_file.close()
#x = np.linspace(0.0, 1, 600)
#y = np.sin(50.0 * 2.0*np.pi*x)
#yf = fft(y)
yf = fft(data)
plt.xlim(0, 4000)
plt.plot( np.abs(yf))
plt.grid()
plt.show()
I am trying to plot the fft of a wav file, I have successfully completed it using the regular fft but I wanted to experiment with rfft as my application was to perform this in music. When I try to plot xf and yf (figure 2) I run into an issue where xf is half the length of yf and I can't figure out why, I assume its due to the negative frequencies missing but I thought changing both function calls to rfft and rfftfreq would handle it.
import numpy as np
import soundfile as sf
import matplotlib.pyplot as plt
square = 'square.wav'
sine = 'sine.wav'
k = '1Khz.wav'
cello = 'cello.wav'
data, fs = sf.read(k)
#Plot the Signal
N = len(data)
T = 1.0/fs
x = np.linspace(0, (N*T), N)
plt.plot(x, data)
plt.grid()
count = 0
yf = np.fft.rfft(data)
xf = np.fft.rfftfreq(yf.size, d=T)
plt.figure(2)
plt.plot(xf, yf)
plt.show()
The sizes used for numpy.fft.rfft and numpy.fft.rfftfreq need to match. As such you should use your data.size rather yf.size (since the size of yf is already reduced by not including the negative frequencies) as argument to rfftfreq:
yf = np.fft.rfft(data)
xf = np.fft.rfftfreq(data.size, d=T)
Finally note that as you plot yf with plt.plot(xf, yf) you would get a warning about the imaginary part being lost. If you are interested in plotting the magnitude of the frequency spectrum, you should rather use plt.plot(xf, abs(yf)).
You need to convert the frequencies to the sample rate. See https://stackoverflow.com/a/27191172/7919597 or the doc of rfftfreq:
signal = np.array([-2, 8, 6, 4, 1, 0, 3, 5, -3, 4], dtype=float)
fourier = np.fft.rfft(signal)
n = signal.size
sample_rate = 100
freq = np.fft.fftfreq(n, d=1./sample_rate)
print(freq)
freq = np.fft.rfftfreq(n, d=1./sample_rate)
print(freq)
I have two lists of float values, one for time and other for voltage values taken from an oscilloscope (I assume). I have to draw an amplitude spectrum plot, but i'm not exactly sure what function I need to use and what parameters I need to give it, I tried fft(u), but it didn't work.
Any help is appreciated, let me know if you need more info.
Use numpy.
As an example, let me show how I analysed the frequencies in a stereo WAV file;
First I read the data and separated it in the left and right channels;
import wave
import numpy as np
wr = wave.open('input.wav', 'r')
sz = 44100 # Read and process 1 second at a time.
da = np.fromstring(wr.readframes(sz), dtype=np.int16)
left, right = da[0::2], da[1::2]
Next I run a discrete fourier transform on it;
lf, rf = abs(np.fft.rfft(left)), abs(np.fft.rfft(right))
And we plot the left channel with mathplotlib;
import matplotlib.pyplot as plt
plt.figure(1)
a = plt.subplot(211)
r = 2**16/2
a.set_ylim([-r, r])
a.set_xlabel('time [s]')
a.set_ylabel('sample value [-]')
x = np.arange(44100)/44100
plt.plot(x, left)
b = plt.subplot(212)
b.set_xscale('log')
b.set_xlabel('frequency [Hz]')
b.set_ylabel('|amplitude|')
plt.plot(lf)
plt.savefig('sample-graph.png')
The graph looks something like this;
Here is the Frequency-Time spectrum of the signal, stored in the wave file
import wave
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
signal_wave = wave.open('voice.wav', 'r')
sample_frequency = 16000
data = np.fromstring(signal_wave.readframes(sample_frequency), dtype=np.int16)
sig = signal_wave.readframes(-1)
sig = np.fromstring(sig, 'Int16')
For the wave file
sig = sig[:]
For some segment of the wave file
sig = sig[25000:32000]
To plot spectrum of the signal wave file
plt.figure(1)
c = plt.subplot(211)
Pxx, freqs, bins, im = c.specgram(sig, NFFT=1024, Fs=16000, noverlap=900)
c.set_xlabel('Time')
c.set_ylabel('Frequency')
plt.show()