Tan Phan
Tan Phan

Reputation: 99

Normalization - Signal with different sampling rates

I am trying to solve a signal processing problem. I have a signal like this enter image description here

My job is to use FFT to plot the frequency vs. signal. This is what I have coded so far:

def Extract_Data(filepath, pattern):

    data = []
    with open(filepath) as file:
        for line in file:
            m = re.match(pattern, line)

            if m:
                data.append(list(map(float, m.groups())))


    #print(data) 
    data = np.asarray(data)
    #Convert lists to arrays
    variable_array = data[:,1]
    time_array = data[:,0]

    return variable_array, time_array

def analysis_FFT(filepath, pattern):

    signal, time = Extract_Data(filepath, pattern)
    signal_FFT = np.fft.fft(signal)

    N = len(signal_FFT)
    T = time[-1]

    #Frequencies
    signal_freq = np.fft.fftfreq(N, d = T/N)

    #Shift the frequencies
    signal_freq_shift = np.fft.fftshift(signal_freq)

    #Real and imagniary part of the signal
    signal_real = signal_FFT.real
    signal_imag = signal_FFT.imag
    signal_abs = pow(signal_real, 2) + pow(signal_imag, 2)

    #Shift the signal
    signal_shift = np.fft.fftshift(signal_FFT)
    #signal_shift = np.fft.fftshift(signal_FFT)

    #Spectrum
    signal_spectrum = np.abs(signal_shift)

What I really concern about is the sampling rate. As you look at the plot, it looks like the sampling rate of the first ~0.002s is not the same as the rest of the signal. So I'm thinking maybe I need to normalize the signal

However, when I use np.fft.fftfreq(N, d =T/N), it seems like np.fft.ffreq assumes the signal has the same sampling rate throughout the domain. So I'm not sure how I could normalize the signal with np.fft. Any suggestions?

Cheers.

This is what I got when I plotted shifted frequency [Hz] with shifted signal enter image description here

Upvotes: 2

Views: 1770

Answers (1)

roadrunner66
roadrunner66

Reputation: 7941

I generated a synthetic signal similar to yours and plotted, like you did the spectrum over the whole time. Your plot was good as it pertains to the whole spectrum, just appears to not give the absolute value.

import numpy as np
import matplotlib.pyplot as p
%matplotlib inline

T=0.05 #  1/20 sec
n=5000 #  5000 Sa, so 100kSa/sec sampling frequency
sf=n/T
d=T/n
t=np.linspace(0,T,n)  
fr=260 # Hz
y1= - np.cos(2*np.pi*fr*t) * np.exp(- 20* t)
y2= 3*np.sin(2*np.pi*10*fr*t+0.5) *np.exp(-2e6*(t-0.001)**2)
y=(y1+y2)/30

f=np.fft.fftshift(np.fft.fft(y))
freq=np.fft.fftshift(np.fft.fftfreq(n,d))

p.figure(figsize=(12,8))
p.subplot(311)
p.plot(t,y ,color='green', lw=1  ) 
p.xlabel('time (sec)')
p.ylabel('Velocity (m/s)')
p.subplot(312)
p.plot(freq,np.abs(f)/n)
p.xlabel('freq (Hz)')
p.ylabel('Velocity (m/s)');


p.subplot(313)
s=slice(n//2-500,n//2+500,1)
p.plot(freq[s],np.abs(f)[s]/n)
p.xlabel('freq (Hz)')
p.ylabel('Velocity (m/s)');

enter image description here On the bottom, I zoomed in a bit to show the two main frequency components. Note that we are showing the positive and negative frequencies (only the positive ones, times 2x are physical). The Gaussians at 2600 Hz indicate the frequency spectrum of the burst (FT of Gaussian is Gaussian). The straight lines at 260 Hz indicate the slow base frequency (FT of sine is a delta).

That, however hides the timing of the two separate frequency components, the short (in my case Gaussian) burst at the start at about 2.6 kHz and the decaying low tone at about 260 Hz. The spectrogram plots spectra of short pieces (nperseg) of your signal in vertical as stripes where color indicates intensity. You can set some overlap between the time frames,which should be some fraction of the segment length. By stacking these stripes over time, you get a plot of the spectral change over time.

from scipy.signal import spectrogram 
f, t, Sxx =  spectrogram(y,sf,nperseg=256,noverlap=64)

p.pcolormesh(t, f[:20], Sxx[:20,:])
#p.pcolormesh(t, f, Sxx)
p.ylabel('Frequency [Hz]')
p.xlabel('Time [sec]')
p.show()

enter image description here

It is instructive to try and generate the spectrogram yourself with the help of just the FFT. Otherwise the settings of the spectrogram function might not be very intuitive at first.

Upvotes: 1

Related Questions