1
$\begingroup$

I am getting the wrong output with the following simple implementation of Python fft. Can someone please explain what I need to fix?

import numpy as np
import matplotlib.pyplot as plt


def tone(fs, frequency, dur=1, amp=50):
    '''
    test tone
    '''
    nsamples = dur * fs
    t = np.linspace(0, dur, nsamples, endpoint=False)

    tone = amp*np.sin(frequency*2*np.pi*t)
    return tone

fs = 16000
dur = 0.5
freq = 1500

stim = tone(fs, freq, dur=dur)
time = np.linspace(0, dur, num=fs*dur)

t = np.linspace(0, fs, num=fs*dur)
fdata = np.fft.fft(stim)

hwp = int(np.shape(fdata)[0]/2)
tplt = t[:hwp]
fplt = fdata[:hwp]

plt.figure(num=1)
plt.plot(time, stim, 'b-')
plt.show()

plt.figure(num=2)
plt.plot(tplt, np.abs(fplt.real), 'b-')
plt.xscale('log')
plt.show()

Removing

, endpoint = False

will fix the implementation though I do not understand why.
Perhaps someone can explain(?)

$\endgroup$
  • 1
    $\begingroup$ Hi and welcome to SE! Please provide details on what exactly is wrong with your output; what output are you getting exactly and what do you expect it to be to be called "right"? Also it would be better to edit your original question with the additional details and not put it down below as an answer. $\endgroup$ – Dan Boschen Aug 30 '18 at 23:13
  • 1
    $\begingroup$ Please do not add "Answers" when you want to supply new information. Please just edit your question. $\endgroup$ – Peter K. Aug 31 '18 at 14:42
  • $\begingroup$ @DanBoschen I believe he refers to the fact that when setting endpoint = False inside the function tone(), the result of the FFT doesn't show a single peak but it has frequency components all over the horizontal axis. On the other hand, when setting endpoint = True, the FFT shows the expected result of one large peak in the frequency of the sinewave. $\endgroup$ – Tendero Aug 31 '18 at 16:32
2
$\begingroup$

UPDATE: I suspected Spectral Leakage but that is not the case here. The reason for this is the OP is choosing to plot just the real component of the FFT, with a linear magnitude scale so the actual effect of the spectral leakage cannot be seen. (We actually get spectral leakage when we use endpoint = true!). If you change the plot from fplt.real to np.abs(fplt) you will see the true magnitude plot that must include the real and imaginary components!).

Here is the result with endpoint = true and plotting the dB of the magnitude. plt.plot(tplt, 20*np.log10(np.abs(fplt)), 'b-'). The spectral leakage in this case is quite clear!

Endpoint = true log log plot

Here is the result with endpoint = false using plt.plot(tplt, 20*np.log10(np.abs(fplt)), 'b-')

Here we see noise that is nearly 300 dB down (floating point precision).

endpoint = false log log plot

$\endgroup$
  • $\begingroup$ d'oh... Thank you very much for the explanation - makes perfect sense! $\endgroup$ – user3877654 Aug 31 '18 at 16:56
  • $\begingroup$ It's great to see that this time you preferred not to use those rotating phasors !! $\endgroup$ – Fat32 Aug 31 '18 at 17:00
  • $\begingroup$ That's not what is happening though! $\endgroup$ – Dan Boschen Aug 31 '18 at 17:01
  • $\begingroup$ I was almost preparing my answer: It should be about one of those phasors rotating at a wrong frequency. Probably electromagnetic friction caused one them to slow down, so that the mismatch between the clockwise and counter clockwise pair created what's known as the beat frequency, aliased into those DC ranges and and the beats apparently have intervened with signal space congruency based on your fft computation engine at the numpy libraries. The engine should be oiled enough so that phasors always rotate without friction But I decided not to do, after seeing your answer! $\endgroup$ – Fat32 Aug 31 '18 at 17:06
  • 1
    $\begingroup$ Yes I realized that an updated the answer. I like @Fat32's answer better though! I will actually delete the later half which is entirely false. $\endgroup$ – Dan Boschen Aug 31 '18 at 17:09
1
$\begingroup$

The problem is that you are just plotting the real parts of the transforms. Plot the absolute value of the whole array (the magnitude of the complex numbers) and you will get the desired result.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.