Plotting FFT fails due to vectors not having the same length - matlab

I have a csv data of time(1st column) and current amplitude(2nd column). I want to plot FFT of the current. This is actually simulation data over 30ns and data step was 1ps. I can plot the current vs Time in MATLAB. But while doing FFT function, It is not plotting at all as it says
Error using plot
Vectors must be the same length.
Error in FFT_Ideal_current_maxstep_1ps (line 25).
plot(f,Y)
Can anyone help me? I have attached the MATLAB code and the CSV file as well.
I also want to plot the power spectral density. It would be nice if anyone can help. I want to get the FFT and psd over 2GHz or more frequency spectrum range
MATLAB code1:
% open data file
fid = fopen('current_maxstep_1ps.csv');
% Read data in from csv file
readData = textscan(fid,'%f %f','Headerlines',1,'Delimiter',',');
% Extract data from readData
t = readData{1,1}(:,1);
x = readData{1,2}(:,1);
N = length(x);
ts = 0.000000000001;
Fs = 1/ts;
tmax = (N-1)*ts;
tm = 0:ts:tmax;
f = 0:Fs/(N-1):Fs/2;
y = fftshift(fft(x));
Y = abs(y);
plot(f,Y)
Also there is another MATLAB code I tried which plots (here is the picture: FFT picture of code 2) but showing in time domain and I want frequency spectrum like spikes of apmlitudes along the frequency spectrum.
MATLAB Code2:
% open data file
fid = fopen('Ideal_current_maxstep_1ps.csv');
% Read data in from csv file
readData = textscan(fid,'%f %f','Headerlines',1,'Delimiter',',');
% Extract data from readData
xData = readData{1,1}(:,1);
yData = readData{1,2}(:,1);
Ts = 1e-12;
Fs = 1/Ts;
%Fs = 1000;
%Ts = 1/Fs;
X = fft(yData);
plot(xData, abs(X))

The problem is that the length of f and Y are not the same. You can check it using length(f) and length(Y). The reason is that fft also calculates the negative frequencies. Therefore, you should define f as follows:
f = -Fs/2:Fs/(N-1):Fs/2;
Note that the fft is conjugate symmetric, because the input data is real.
You can limit the plotted frequency range using the xlim command as follows:
xlim([0 3*10^9]) % limit x range between 0Hz and 3GHz

Related

MATLAB FFT waveform plot with detrend and shift only has one spike

I have some beginner, basic Physionet data I am trying to apply FFT to, but I'm a bit confused by the results I'm getting and don't think they're correct. I'm mostly using code from this example and from the fftshift documentation page with some tweaks but I'm not too sure what's wrong with my code or results. I have attached my code and snapshots of the results I'm getting.
load aami3am.mat
Fs = 720; % Sampling frequency
T = 1/Fs; % Sample time
L = 60000; % Length of signal
t = (0:L-1)*T; % Time vector
plot(t(1:43081),val(1:43081))
title('aami4b_h Signal')
xlabel('Seconds')
ylabel('ECG Amplitude')
NFFT = 2^nextpow2(L);
val = detrend(val);
Y = fft(val,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
plot(f,2*abs(Y(1:NFFT/2+1)))
title('FFT')
yY = fftshift(Y);
fshift = (-L/2:L/2-1)*(Fs/L);
powershift = abs(yY).^2/L;
plot(fshift(1:L),powershift(1:L))
title('FFT Shifted')
I'm using 43081 because there are 43081 values in the .mat file over the 60 seconds of data.

inverse fourier transform of data does not give correct amplitude

I'm trying to calculate the inverse Fourier transform of some data using Matlab. I start with raw data in the frequency domain and want to visualise the data in the time domain. Here is my MWE:
a = 1.056;
% frequency of data (I cannot change this)
w = linspace(-100,100,1e6);
L = length(w); % no. sample points
ts = L/1000; % time sampling
Ts = ts/L; % sampling rate
Fs = 1/Ts; % sampling freq
t = (-L/2:L/2-1)*ts/L; % time
Y = sqrt(pi/a)*exp(-w.^2/(4*a)); % my data
yn = Fs*ifftshift(ifft(fftshift(Y(end:-1:1)))) % numerical soln
ya = exp(-a*t.^2); % analytic solution
figure; hold on
plot(t,yn,'.')
plot(t,ya,'-')
xlabel('time, t')
legend('numerical','analytic')
xlim([-5,5])
I have adapted the code from this question however the amplitude is too large:
Can you please tell me what I'm doing wrong?
There are three issues with your code:
You define ts = L/1000 and then compute Fs, which gives you 1000. But Fs is given by the w array you've set up: the full range of w is 2*pi*Fs:
Fs = -w(1)/pi; % sampling freq
Ts = 1/Fs; % sampling rate
Or, equivalently, set Fs = mean(diff(w))*L / (2*pi)
w is defined, but does not include 0. Just like you define t carefully to include the 0 in just the right place, so should you define w to include 0 in just the right place. One simple way to do this is to define it with one more value, then delete the last value:
w = linspace(-100,100,1e6+1);
w(end) = [];
If your input data does not include the 0 frequency, you should resample it so that it does. The DFT (FFT) expects a 0 frequency bin.
You're using ifftshift and fftshift reversed: fftshift shifts the origin from the leftmost array element to the middle, and ifftshift shifts it from the middle to the left. You define your signal with the origin in the middle, so you need to use ifftshift on it to move the origin where the fft and ifft functions expect it. Use fftshift on the output of these two functions to center the origin for display. Because your data is even sized, these two functions do exactly the same thing, and you will not notice the difference. But if the data were odd sized, you'd see the difference.
The following code gives a perfect match:
a = 1.056;
% frequency of data (I cannot change this)
w = linspace(-100,100,1e6+1); w(end) = [];
L = length(w); % no. sample points
Fs = -w(1)/pi; % sampling freq
Ts = 1/Fs; % sampling rate
t = (-L/2:L/2-1)*Ts; % time
Y = sqrt(pi/a)*exp(-w.^2/(4*a)); % my data
yn = Fs*fftshift(ifft(ifftshift(Y(end:-1:1)))); % numerical soln
ya = exp(-a*t.^2); % analytic solution
figure; hold on
plot(t,yn,'.')
plot(t,ya,'-')
xlabel('time, t')
legend('numerical','analytic')
xlim([-5,5])

Surface plot using multiple excel files

I'm just a beginner with MATLAB.
I need to represent my data using a 3D plot. I tried using the surf function but in my case this is a little bit tricky. From the code you will see that I am looping through multiple excel files to extract data from it.
Using a 3-dimensional plot I need to represent my Fv array as the 'X' coordinate, my FTsiga as the 'Y' coordinate and the the third coordinate should be each excel file that I am looping through.
A plot of (Fv,FTsiga) looks like the figure that is attached herewith.
Fv(x-axis) , FTsiga(y-axis)
The code that I have written so far couldn't seem to execute because MATLAB crashed due to insufficient memory or because it got stuck in a loop. The latter is more likely I guess.
% Matlab trial code: Trying to loop through excel files strored in directory
source_dir = 'C:\UTwente\Q4\Structural Health and Condition monitoring\Case Roadbridge (Zwartewaterbrug)\Excel data'
source_files = dir(fullfile(source_dir, '*xlsx'));
len = length(source_files);
matrix = zeros(len,32);
X = zeros(len,32); Y = zeros(len,32); Z = zeros(len,32);
%looping through excel file in directory
for i=1:len
data= xlsread(source_files(i).name,'Measurement data');
for j=1:32
sig = data(:,j);
sig = sig - mean(sig); % Remove d-c Offset
L = length(sig);
Fs = 1000; % Sampling Frequency
Fn = Fs/2; % Nyquist Frequency
FTsig = fft(sig)/L;
Fv = linspace(0, 1, fix(length(FTsig)/2)+1)*Fn; % Frequency Vector
Iv = 1:length(Fv); % Index Vector
FTsiga = double(abs(FTsig(Iv))*2); % Truncate, Magnitude, Convert To Double
sgf_sm = sgolayfilt(FTsiga, 5, 501); % Create ‘sgolayfilt’ Filtered FFT
[~, idx] = max( sgf_sm ); % Getting the value of the modal frequency
peakfreq = Fv( idx );
matrix(i,j) = peakfreq; % Matrix of all peak frequencies
[X,Y,Z] = meshgrid(Fv,FTsiga,i);
end
surf(Fv,FTsiga,i);
end

Matlab power spectrum analysis

I would like to reproduce this image, but with my own EEG data.
For what I understand, it is a power spectrum analysis done on filtered data.
I recorded the EEG signal with a sampling rate of 1000Hz, with DC amplifiers (Low: DC; High:200). My Data is: 68 (electrodes) x 185080 (data points).
I have tried to use the following code from:http://uk.mathworks.com/help/signal/ug/psd-estimate-using-fft.html
Fs = 1000;
t = 0:1/Fs:1-1/Fs;
x = Data;
%x = cos(2*pi*100*t) + randn(size(t));
N = length(x);
xdft = fft(x);
xdft = xdft(1:N/2+1);
psdx = (1/(Fs*N)) * abs(xdft).^2;
psdx(2:end-1) = 2*psdx(2:end-1);
freq = 0:Fs/length(x):Fs/2;
plot(freq,10*log10(psdx))
grid on
title('Periodogram Using FFT')
xlabel('Frequency (Hz)')
ylabel('Power/Frequency (dB/Hz)')
but this is what I obtain:
I am struggling understanding how to proceed in order to obtain an analysis of my EEG signal as in the first image. Any help would be very much appreciated.
Here's a simple example of how to do PSD using fft from scratch and without the DSP toolbox:
%this does not include any filtering
x = [0:0.01:pi];
y = sin(100*x);
nfft = 2^nextpow2(length(y));
Fs = 100;
psd1 = abs(fft(y,nfft)).^2/length(y)/Fs;%compute the PSD and normalize
plot([0:50/(length(psd1)/2):50],psd1(1:length(psd1)/2+1))
xlabel('Frequency (Hz)');
ylabel('PSD');
grid on
title('PSD from FFT');
The result:
If this method results in a similar one to what you posted then I think the other's comments about your data having some issues may be valid.

how to transform frequency domain into time domain

I had created a 3 three different frequency signal and filter out the signal i don't want. But when i using ifft in matlab, it shows a wrong graph.How to transform my frequency domain spectrum back into my 3 second time domain graph? Below my code is as below:
clc
clear all
Fs = 8192;
T = 1/Fs;
%create tones with different frequency
t=0:T:1;
t2=1:T:2;
t3=2:T:3;
y1 = sin(2*pi*220*t);
y2 = sin(2*pi*300*t2);
y3 = sin(2*pi*440*t3);
at=y1+y2+y3;
figure;
plot(t,y1,t2,y2,t3,y3),title('Tones with noise');
[b,a]=butter(2,[2*290/Fs,2*350/Fs],'stop');
e=filter(b,a,at);
et=(ifft(abs(e)));
figure,
plot(et)
As it is now, et is in the frequency domain, because of the fft. You don't need to fft. just plot(e) and you'll get the time domain filtered waveform. Yo can check the filter performance in the freq. domain by fft though, just
plot(abs(fftshift(fft(fftshift(e)))));
xlim([4000 5000])
Edit:
Your code as it is written on the question has the following bug: at has exactly 1 second of info in it (or 8192 elements). If you plot(at) you'll see the sum of frequencies alright, but they all happen in the same time. This is how to fix it:
clear all
Fs = 8192; % or multiply by 3 if needed
T = 1/Fs;
%create tones with different frequency
t=0:T:3;
y1 = sin(2*pi*220*t).*(t<1);
y2 = sin(2*pi*300*t).*(t<2 & t>=1);
y3 = sin(2*pi*440*t).*(t>=2);
at=y1+y2+y3;
[b,a]=butter(2,[2*290/Fs,2*350/Fs],'stop');
e=filter(b,a,at);
figure,
plot(t,e)
dt=t(2)-t(1);
N=length(at);
df=1/(N*dt); % the frequency resolution (df=1/max_T)
if mod(N,2)==0
f_vector= df*((1:N)-1-N/2); % frequency vector for EVEN length vectors: f =[-f_max,-f_max+df,...,0,...,f_max-df]
else
f_vector= df*((1:N)-0.5-N/2); % frequency vector for ODD length vectors f =[-f_max,-f_max+fw,...,0,...,f_max]
end
freq_vec=f_vector;
fft_vec=fftshift(fft(e));
plot(freq_vec,abs(fft_vec))
xlim([0 1000])