Matlab FFT: Power Spectral Density or Amplitude Spectral Density? - matlab

The amplitude of a FFT should be depending on the length of the signal.
To display the result in a independent way the Power Spectral Density or the Amplitude Spectral Density should be used. There are calculated as follows:
Amplitude FFT = Y
Signal Length = L
Power Spectral Density PSD = Y^2/L
Amplitude Spectral Density ASD = Y/sqrt(L)
https://www.sjsu.edu/people/burford.furman/docs/me120/FFT_tutorial_NI.pdf
My problem is, that the result of the Matlab fft is already indipendent from the signal length and I do not understand if this is already a PSD or a ASD.
Let's take the Matlab example Noisy Signal: https://ch.mathworks.com/help/matlab/ref/fft.html
If we make the FFT on the same signal, but twice or ten times longer, the FFT amplitude does not change.
This because of the line:
P2 = abs(Y/L);
where the amplitude is divided through the signal length. But why is the formula different from the PSD or the ASD formula and we still obtain amplitudes indipendent from the signal length?
In this example it is shown, that the two signals, ones for 50s, ones for 500s, has almost the same amplitudes.
% Signal 1
sps = 1000; % Sampling frequency
T = 1/sps; % Sampling period
Frequency1 = 150; % frequency 1 [Hz]
SignalAmplitude1 = 1; % mm/s
Frequency2 = 45; % dominant frequency [Hz]
SignalAmplitude2 = 1.2; % mm/s
L = 50; % Length of signal, sek.
L = L*1000; % convert to ms
time = (0:L-1)*T; % Time vector
Signal = cos(2*pi*Frequency1*time)*SignalAmplitude1 + sin(2*pi*Frequency2*time)*SignalAmplitude2;
f = sps*(0:(L/2))/L;
FFTcomplex = fft(Signal);
P2 = abs(FFTcomplex)/L;
P1 = P2(:,round(1:L/2+1));
P1(:,2:end-1) = 2*P1(:,2:end-1);
Ampl_FFT_1 = P1;
% Signal 2
sps = 1000; % Sampling frequency
T = 1/sps; % Sampling period
Frequency1 = 150; % frequency 1 [Hz]
SignalAmplitude1 = 1; % mm/s
Frequency2 = 45; % dominant frequency [Hz]
SignalAmplitude2 = 1.2; % mm/s
L = 500; % Length of signal, sek.
L = L*1000; % convert to ms
time = (0:L-1)*T; % Time vector
Signal = cos(2*pi*Frequency1*time)*SignalAmplitude1 + sin(2*pi*Frequency2*time)*SignalAmplitude2;
f = sps*(0:(L/2))/L;
FFTcomplex = fft(Signal);
P2 = abs(FFTcomplex)/L;
P1 = P2(:,round(1:L/2+1));
P1(:,2:end-1) = 2*P1(:,2:end-1);
Ampl_FFT_2 = P1;
sum(Ampl_FFT_2)-sum(Ampl_FFT_1)

Related

FFT Not Getting Expected Results And Too Much Noise

Here's my code:
close all;clc;clear all;
f=fopen ('sum_021223.txt');
Adata=cell2mat(textscan(f, '%f %f %f %f %f'));
time=Adata(:,5);
data = Adata;
data(:,5:end) = 0;
final=size(data,1);
data(1,1)=data(2,1);
testsum=sum(data,2);
Fs = .5; % Sampling frequency
T = 1/Fs; % Sampling period
L = final; % Length of signal
t = (0:L-1)*T;
t=t';
Y=fft(testsum)
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
% P1(1,1)=P1(2,1);
plot(f,P1)
title("Single-Sided Amplitude Spectrum of X(t)")
xlabel("f (Hz)")
ylabel("|P1(f)|")
I believe I setup my code correct. I am sampling data once per 2 seconds. I have 30530 rows of data (About 17 hours worth)
However my FFT just looks like a bunch of noise, and I would expect some spikes around the smaller frequencies that would represent changes in air temperature and such over the day I took the data.
The input data on Dropbox.
I tried to set P1(1,1) to be equal to P1(2,1). This somewhat helped, but not really.
Your FFT looks corect, you have a very noisy data. You can maybe plot a power spectrum of that signal. You can distinguish different parts in the signal, here is function:
close all;clc;clear all;
f=fopen ('sum_021223.txt');
Adata=cell2mat(textscan(f, '%f %f %f %f %f'));
time=Adata(:,5);
data = Adata;
data(:,5:end) = 0;
final=size(data,1);
data(1,1)=data(2,1);
testsum=sum(data,2);
Fs = .5; % Sampling frequency
T = 1/Fs; % Sampling period
L = numel(testsum); % Length of signal
t = (0:L-1)*T;
t=t';
[f,y]=MyPower(testsum,Fs);
plot(f,y)
title("Single-Sided Amplitude Spectrum of X(t)")
xlabel("f (Hz)")
ylabel("|P1(f)|")
ylim([0,6e-3]);
function [f,y]=MyPower(y,freq)
tuReal = "seconds";
samples=numel(y);
period=1/freq;
time=linspace(0,samples*period,samples)';
signal=y;
Fs=freq;
% Compute effective sampling rate.
tNumeric = time2num(time,tuReal);
[Fs,irregular] = effectivefs(tNumeric);
Ts = 1/Fs;
% Resample non-uniform signals.
x = signal;
if irregular
x = resample(x,tNumeric,Fs,'linear');
end
% Set Welch spectrum parameters.
L = fix(length(x)/4.5);
noverlap = fix(L*50/100);
win = window(#hamming,L);
% Compute the power spectrum.
[ps,f] = pwelch(x,win,noverlap,[],Fs);
w = 2*pi*f;
% Convert frequency unit.
factor = funitconv('rad/TimeUnit', 'Hz', 'seconds');
w = factor*w;
Fs = 2*pi*factor*Fs;
% Remove frequencies above Nyquist frequency.
I = w<=(Fs/2+1e4*eps);
w = w(I);
ps = ps(I);
% Configure the computed spectrum.
ps = table(w, ps, 'VariableNames', ["Frequency", "SpectrumData"]);
ps.Properties.VariableUnits = ["Hz", ""];
ps = addprop(ps, {'SampleFrequency'}, {'table'});
ps.Properties.CustomProperties.SampleFrequency = Fs;
f=ps.Frequency;
y=ps.SpectrumData;
end

Generate a sequence of pulses in Matlab

I have a half wave sin:
Rc = 1e2; % [b/s] chip rate
T =1; % [s/b] inverse of chip rate
Fs = 2e2; % [Hz] sampling frequency
dt = 1/Fs; % [s]
sps = 40;
dt2=dt/sps;
T = 1;
% single pulse time reference
t = 0:dt2:2*T;
pulse_half_Sine = sin(pi*t/(2*T)).^3;
I have a modulated signal
N=1e4;
bits=randi([0,1],N,1);
modOrder = 2;
modData = pammod(bits,modOrder);
I want to do a convolution of the signal and the pulse. The duration of the envelope is T and the symbolic speed = 2/T. Thus, the maximum should be at the point T/2. I do so, but I don't get the countdown points of time.
over_data=upsample(modData,length(pulse_half_Sine)-1);
plot(t, pulse_half_Sine);
signal1 = conv(over_data,pulse_half_Sine);

Amplitude and Phase of result of FFT in MATLAB

I tried to extract amplitude & phase values from the fft function result in the Matlab. I implemented the script as below
clear;
sf = 100; %sampling frequency
si = 1/sf; dt=si; %time sampling interval
L = 10; %Length of signal
t = linspace(0,L,L/dt+1);%(0:L-1)*dt; %time vector
t(end)=[];
fr = 4 %frequency
data = cos(2*pi*fr*t);
df = sf/length(data3); %frequency increment
f = linspace(0,length(data3)/2,length(data3)/2)*df; %frequency
fft_result =fft(data)/length(data);
spec_fft = abs(fft_result); %amplitude
pha_fft = angle(fft_result); %phase
When I checked the results of amplitude and phase values, of course, they showed peak values at a specific frequency that I specified. But, other frequencies also have amplitude. Of course, their values are very very small, but because of this problem, the phase spectrum didn't show me a clear result. Why other frequencies also have amplitude values?
And I made a cosine function that is not shifted. So I think the phase value should show the zero value, but it wasn't. Why this problem occurred?
These values won't be exactly zero due to the floating point operations involved. You generated a 4 Hz cosine with amplitude of 1. Taking the single-sided amplitude and phase spectrum shows an amplitude of 1, and a phase of 0 radians at the 4 Hz bin:
clear;
sf = 100; %sampling frequency
si = 1/sf; dt=si; %time sampling interval
L = 10; %Length of signal
t = linspace(0,L,L/dt+1);%(0:L-1)*dt; %time vector
t(end)=[];
fr = 4; %frequency
data = cos(2*pi*fr*t);
df = sf/length(data); %frequency increment
N = length(data);
f = ((0:(N/2))/ N) * sf; %frequency
fft_result =fft(data)/N;
spec_fft = abs(fft_result); %amplitude
% single sided amplitude
amp_single_side = spec_fft(1:N/2+1);
amp_single_side(2:end-1) = 2*amp_single_side(2:end-1);
% single sided phase
phase_single_side = angle(fft_result(1:N/2+1));
four_hertz_bin = find(f == 4);
four_hertz_amp = amp_single_side(four_hertz_bin);
four_hertz_phase = phase_single_side(four_hertz_bin);
figure;
subplot(2,1,1);
plot(f, amp_single_side)
xlabel('Frequency');
ylabel('Amplitude');
hold on;
plot(f(four_hertz_bin), four_hertz_amp, 'ro');
subplot(2,1,2);
plot(f, phase_single_side);
xlabel('Frequency');
ylabel('Phase');
hold on;
plot(f(four_hertz_bin), four_hertz_phase, 'ro');

Scaling amplitudes by two for the FFT in MATLAB

I just read the example of Mablab tutorial, trying to studying the FFT function.
Can anyone tell me that for the final step, why P1(2:end-1) = 2*P1(2:end-1). In my opinion, it is not necessary to multiply by 2.
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sampling period
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
%--------
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
%---------
X = S + 2*randn(size(t));
%---------
plot(1000*t(1:50),X(1:50))
title('Signal Corrupted with Zero-Mean Random Noise')
xlabel('t (milliseconds)')
ylabel('X(t)')
Y = fft(X);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
plot(f,P1)
title('Single-Sided Amplitude Spectrum of X(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
Y = fft(S);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
plot(f,P1)
title('Single-Sided Amplitude Spectrum of S(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
Matlab sample
The reason for the multiplication by 2 is that the spectrum returned by fft is symmetric about the DC component. Since they are showing the single-sided amplitude spectrum, the amplitude of each point is going to be doubled to account for the contributions of data on the other side of the spectrum. For example, the single-sided amplitude of pi/4 is the amplitude at pi/4 plus the amplitude at -pi/4.
The first sample is skipped since it is the DC point and therefore shared between the two sides of the spectrum.
So for example, if we look at the fft of their example signal with a 50Hz sinusoid of amplitude 0.7 and a 120Hz sinusoid of amplitude 1.
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sampling period
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
% Compute the FFT
Y = fft(S);
% Compute the amplitudes
amplitude = abs(Y / L);
% Figure out the corresponding frequencies
f = Fs/L*[0:(L/2-1),-L/2:-1]
% Plot the result
plot(f, amplitude)
When we plot this, you'll see that it's symmetric and the original input amplitude is only realized by combining the amplitudes from both sides of the spectrum.
A slightly more explicit version of what they have done would be to be the following which sums the two halves of the spectrum
P1(2:end-1) = P1(2:end-1) + P2((L/2+2):end);
But since by definition the spectrum is symmetric, the opt to simply multiply by 2.

Confused with fft Matlab

I am little bit confused with fft. That would be good if anyone can help me. first, I want to convert fft output in time domain. Where t = f/k and K = BW/Tm (BW = bandwidth & Tm = transmit time). After that again i need to take fft and ouput should be box (rectangular function) which is having width of BW(40e9).
f1 = 1e6; % first cutoff frequency
f2 = 4e6; % second cutoff frequency
BW = 40e9; % bandwidth
Tm = 0.2e-3; % transmit time
fs = 1e7; % sampling frequency
c = 3e8; % speed of light
w1 = f1/ (fs/2); % normalizing first cutoff frequency
w2 = f2/ (fs/2): % normalizing second cutoff frequency
[b,a] = butter(2, [w1,w2], 'bandpass');
load('fb2040');
x = fb2040(3,:);
y_filt = filter(b,a,x); % filtering
nfft = length(y_filt);
res = fft(y_filt, nfft)/ nfft;
f = fs/2 * linspace(0,1,nfft/2+1);
res = res(1:nfft/2+1);
figure, plot(f,abs(res));
xlabel('frequency in MHz');
ylabel('amp');
return