I have a simple problem but since I have not used MATLAB Fourier Transform tools I need some help. I have a plot obtained from n excel file. The plot is in time domain. Time range for the plot is 0 to 50 ps. And I have data for the y component of the plot every 0.5 fs. Basically the plot contains 100000 data printed every 0.5fs. Now I want to get the Fourier transform of this plot. What should i do? The following is a simple format for my excel file that includes the data I needed to have the time-domain plot.
0 116.0080214
0.0005 116.051128
0.001 116.0939229
0.0015 116.1362197
0.002 116.1776665
0.0025 116.2178118
0.003 116.256182
.
.
.
.
50.0 123.000
The first column is time in ps. Thank you so much in advance for you helps. Best, HRJ
I have adapted this page for the solution.
Fs = 100000/50; % Sampling frequency (in 1/ps)
T = 1/Fs; % Sample time (in ps)
L = 100000; % Length of signal
t = (0:L-1)*T; % Time vector; your first column should replace this
% Sum of a 50 1/ps sinusoid and a 120 1/ps sinusoid
% Your second column would replace y
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
y = x + 2*randn(size(t)); % Sinusoids plus noise
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
close all
subplot(2,1,1)
% Plot your original signal
plot(Fs*t(1:100),y(1:100))
title('Signal Corrupted with Noise')
xlabel('time (fs)')
% Plot single-sided amplitude spectrum.
subplot(2,1,2)
plot(f,2*abs(Y(1:NFFT/2+1)))
title('Single-Sided Amplitude Spectrum of y(t)')
xlabel('Frequency (1/ps)')
ylabel('|Y(f)|')
Related
Here is the code I use to plot a function in frequency domain in Matlab:
dt = 1/10000; % sampling rate
et = 0.1; % end of the interval
t = 0:dt:et; % sampling range
y = 2+sin(2.*pi.*50.*t)+18.*sin(2.*pi.*90.*t)+6.*sin(2.*pi.*180.*t); % sample the signal
subplot(2,1,1); % first of two plots
plot(t,y); grid on % plot with grid
xlabel('Time (s)'); % time expressed in seconds
ylabel('Amplitude'); % amplitude as function of time
Y = fft(y); % compute Fourier transform
n = size(y,2)/2; % 2nd half are complex conjugates
amp_spec = abs(Y)/n; % absolute value and normalize
subplot(2,1,2); % second of two plots
freq = (0:100)/(2*n*dt); % abscissa viewing window
stem(freq,amp_spec(1:101)); grid on % plot amplitude spectrum
xlabel('Frequency (Hz)'); % 1 Herz = number of cycles/second
ylabel('Amplitude'); % amplitude as function of frequency
The problem is, when I zoom in my graph I don't see peaks exactly on 50Hz, 90Hz and 180Hz.
What did I do wrong in my code?
The problem is that in order to get perfect spectra (peaks on 50,90,180 and 0 otherwise), your interval should be a multiplier of all the frequencies.
Explanation: consider y=sin(2.*pi.*t). Use your code to plot it with:
1) et = 1-dt;
2) et = 1;
In the first case, if you zoom in, you will see that peak is perfectly on 1 Hz. In the second case it is not (also very close).
Why? Because you are working with the finite number of points, and, consequently, finite number of frequencies. If 1 Hz is among this set of frequencies (1st case), you will get perfect peak at 1 Hz at zeros at all others frequencies.
In case 2 there is no 1 Hz frequency in your set, so you will get peak on the nearest frequencies (and also it will have finite width).
Ultimately, in your original code, there are no 50, 90, 180 Hz frequencies in your full set of frequencies.
I'm using the pwelch method in matlab to compute the power spectra for some wind speed measurements. So, far I have written the following code as an example:
t = 10800; % number of seconds in 3 hours
t = 1:t; % generate time vector
fs = 1; % sampling frequency (seconds)
A = 2; % amplitude
P = 1000; % period (seconds), the time it takes for the signal to repeat itself
f1 = 1/P; % number of cycles per second (i.e. how often the signal repeats itself every second).
y = A*sin(2*pi*f1*t); % signal
fh = figure(1);
set(fh,'color','white','Units', 'Inches', 'Position', [0,0,6,6],...
'PaperUnits', 'Inches', 'PaperSize', [6,6]);
[pxx, f] = pwelch(y,[],[],[],fs);
loglog(f,10*(pxx),'k','linewidth',1.2);
xlabel('log10(cycles per s)');
ylabel('Spectral Density (dB Hz^{-1})');
I cannot include the plot as I do not have enough reputation points
Does this make sense? I'm struggling with the idea of having noise at the right side of the plot. The signal which was decomposed was a sine wave with no noise, where does this noise come from? Does the fact that the values on the yaxis are negative suggest that those frequencies are negligible? Also, what would be the best way to write the units on the y axis if the wind speed is measured in m/s, can this be converted to something more meaningful for environmental scientists?
Your results are fine. dB can be confusing.
A linear plot will get a good view,
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
y = sin(2 * pi * 50 * t); % 50Hz signal
An fft approach,
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
subplot(1,2,1);
plot(f,2*abs(Y(1:NFFT/2+1)))
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
pwelch approach,
subplot(1,2,2);
[pxx, freq] = pwelch(y,[],[],[],Fs);
plot(freq,10*(pxx),'k','linewidth',1.2);
xlabel('Frequency (Hz)');
ylabel('Spectral Density (Hz^{-1})');
As you can see they both have peak at 50Hz.
Using loglog for both,
So "noise" is of 1e-6 and exists in fft as well, and can be ignored.
For your second question, I don't think the axis will change it will be frequency again. For Fs you should use the sampling frequency of wind speed, like if you have 10 samples of speed in one second your Fs is 10. Higher frequencies in your graph means more changes in wind speed and lower frequencies represent less changes for the speed.
with this code i am only getting half og the fft spectrum from 0 to positive infinity . i am trying to mirror this along the y axis to get the other half which is symmetric to this one from 0 to negative infinity.
Fs = 1000; %sampling rate
Ts = 1/Fs; %sampling time interval
t = -10:Ts:10-Ts; %sampling period
n = length(t); %number of samples
y = heaviside(t)-heaviside(t-4); %the step curve
matlabFFT = figure; %create a new figure
YfreqDomain = fft(y); %take the fft of our step funcion, y(t)
y=abs(YfreqDomain);
plot(y)
xlabel('Sample Number')
ylabel('Amplitude')
title('Using the Matlab fft command')
grid
axis([-100,100,0,5000])
That's normal behaviour. The FFT returns the spectrum in positive frequencies only (between 0 and Fs). You can use fftshift to correct that. The zero frequency will then be at the center of the x axis. So you should use
plot(fftshift(y))
axis([-100+1e4,100+1e4,0,5000])
The following Matlab script is for filtering a signal consisting of a 50 Hz and 120 Hz sine. I am calculating the frequnecy in rad/s as Fp= (2*PI * 30)/1000=0.184.
I have kept fp=0.184 and fst=0.185, as I want to filter out both 50 hz and 120 Hz.
But when I am plotting the FFT of the output of the filter, what I am getting is a sine at 50 Hz. Why this 50Hz sine is coming even after filtering?
Ideally there should not be any peak in the plot.
Before filtering
after filtering
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t =(0:L-1)*T; % Time vector
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t); % Sum of a 50 Hz sinusoid and a 120 Hz sinusoid %
y = x + 2*randn(size(t)); % Sinusoids plus noise
y = x ;
plot(Fs*t(1:50),y(1:50));title('Signal');xlabel('time (milliseconds)')
%pause;
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L; f = Fs/2*linspace(0,1,NFFT/2+1);
% Plot single-sided amplitude spectrum.
plot(f,2*abs(Y(1:NFFT/2+1)))
title('Single-Sided Amplitude Spectrum of y(t)');xlabel('Frequency(Hz)');ylabel('|Y(f)|')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Now let us see Low Pass Filtering of this signal
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Fp= (2*pi * 30)/1000; %=0.184 %only frequncies less than 30Hz will be passed
d=fdesign.lowpass('Fp,Fst,Ap,Ast',0.184,0.185,2,60);
designmethods(d);
Hd = design(d,'equiripple'); fvtool(Hd);
Filterd_Output = filter(Hd,y);
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Filtered_Freq = fft(Filterd_Output,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
% Plot single-sided amplitude spectrum.
plot(f,2*abs(Filtered_Freq(1:NFFT/2+1)))
title('Single-Sided Amplitude Spectrum of Low Pass Filtered_Output')
xlabel('Frequency (Hz)');ylabel('|Filtered_Freq_Amplitude|')
Update
As suggested I compared the original spectrum with the filterd one. This explains me a lot. But is there any way so that I can reduce this spike at 50 Hz further?
You incorrectly specify the normalized frequencies for the filter. Matlab assumes the frequency to be in [0, 1], not in [0, pi].
Replace
d=fdesign.lowpass('Fp,Fst,Ap,Ast',0.184,0.185,2,60);
with
d=fdesign.lowpass('Fp,Fst,Ap,Ast', 2*30/Fs, 2*35/Fs,2,60);
or alternatively
d=fdesign.lowpass('Fp,Fst,Ap,Ast', 30, 35,2,60, Fs);
and it should work as expected.
The following Matlab scrip (taken from MATLAB help for fft) runs perfectly fine
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz sinusoid and a 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
y = x + 2*randn(size(t)); % Sinusoids plus noise
plot(Fs*t(1:50),y(1:50))
title('Signal Corrupted with Zero-Mean Random Noise')
xlabel('time (milliseconds)')
But I am unable to understand why we needed Fs*t in plot(). Why I am making it dimension less?
Your vector t is defined in terms of samples, i.e. t(10) is the value taken as the 10th sample.
If you want to plot the signal vs. time, you will have to multiply the sampling instance with the sampling time, i.e. time = FS*t .
If you don't scale, you eventually plot the signal vs. the sampling instances. Then, however, the label "time(ms)" is not correct.