Search code examples
pythonscipyfft

Amplitude of rfft for real-valued array


I'm calculating the RFFT of a signal of length 3000 (sampled at 100 Hz) with only real valued entries:

from scipy.fft import rfft
coeffs = rfft(values)
coeffs = np.abs(coeffs)

With rfft I'm only getting half of the coefficients, i.e. the symmetric ones are dicarded (due to real valued input).

Is it correct to scale the values by coeffs = (2 / len(values)) * coeffs to get the amplitudes?

Edit: Below I have appended a plot of the amplitudes vs. Frequency (bins) for accelerometer and gyroscope (shaded area is standard deviation). For accelerometer the energy in the first FFT bin is much higher than in the other bins (> 2 in the first bin and around < 0.4 in the other bins). For gyroscope it is different and the energy is much more distributed.

Does that mean that for acccelerometer the FFT looks good but for gyroscope it is worse? Further, is it reasonable to cut the FFT at 100 Hz (i.e. take only bins < 100 Hz) or take the first few bins until 95% of the energy is kept?

enter image description here

enter image description here


Solution

  • The approximate relationship I provided in this post holds whether you throw out half the coefficients or not.

    So, if the conditions indicated in that post apply to your situation, then you could get an estimate of the amplitude of a dominant sinusoidal component with

    approx_sinusoidal_amplitude = (2 / len(values)) * np.abs(coeffs[k])
    

    for some index k corresponding to the frequency of the sinusoidal component (which according to the limitations indicated in my other post has to be at or near a multiple of 100/3000 ~ 0.033Hz in your case). For a dominant sinusoidal component, this index would typically correspond to a local peak in the frequency spectrum. Note however that if your signal is a mixture of various frequency components, the individual components may affect the frequency spectrum in such a way that the peak does not appear clearly.