how to transform frequency domain into time domain - matlab

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])

Related

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])

MATLAB: How to apply ifft correctly to bring a "filtered" signal back to the time doamin?

I am trying to get the output of a Gaussian pulse going through a coax cable. I made a vector that represents a coax cable; I got attenuation and phase delay information online and used Euler's equation to create a complex array.
I FFTed my Gaussian vector and convoluted it with my cable. The issue is, I can't figure out how to properly iFFT the convolution. I read about iFFt in MathWorks and looked at other people's questions. Someone had a similar problem and in the answers, someone suggested to remove n = 2^nextpow2(L) and FFT over length(t) instead. I was able to get more reasonable plot from that and it made sense to why that is the case. I am confused about whether or not I should be using the symmetry option in iFFt. It is making a big difference in my plots. The main reason I added the symmetry it is because I was getting complex numbers in the iFFTed convolution (timeHF). I would truly appreciate some help, thanks!
clc, clear
Fs = 14E12; %1 sample per pico seconds
tlim = 4000E-12;
t = -tlim:1/Fs:tlim; %in pico seconds
ag = 0.5; %peak of guassian
bg = 0; %peak location
wg = 50E-12; %FWHM
x = ag.*exp(-4 .* log(2) .* (t-bg).^2 / (wg).^2); %Gauss. in terms of FWHM
Ly = x;
L = length(t);
%n = 2^nextpow2(L); %test output in time domain with and without as suggested online
fNum = fft(Ly,L);
frange = Fs/L*(0:(L/2)); %half of the spectrum
fNumMag = abs(fNum/L); %divide by n to normalize
% COAX modulation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%phase data
mu = 4*pi*1E-7;
sigma_a = 2.9*1E7;
sigma_b = 5.8*1E6;
a = 0.42E-3;
b = 1.75E-3;
er = 1.508;
vf = 0.66;
c = 3E8;
l = 1;
Lso = sqrt(mu) /(4*pi^3/2) * (1/(sqrt(sigma_a)*a) + 1/(b*sqrt(sigma_b)));
Lo = mu/(2*pi) * log(b/a);
%to = l/(vf*c);
to = 12E-9; %measured
phase = -pi*to*(frange + 1/2 * Lso/Lo * sqrt(frange));
%attenuation Data
k1 = 0.34190;
k2 = 0.00377;
len = 1;
mldb = (k1 .* sqrt(frange) + k2 .* frange) ./ 100 .* len ./1E6;
mldb1 = mldb ./ 0.3048; %original eqaution is in inch
tfMag = 10.^(mldb1./-10);
% combine to make in complex form
tfC = [];
for ii = 1: L/2 + 1
tfC(ii) = tfMag(ii) * (cosd(phase(ii)) + 1j*sind(phase(ii)));
end
%END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%convolute both h and signal
fNum = fNum(1:L/2+1);
convHF = tfC.*fNum;
convHFMag = abs(convHF/L);
timeHF = ifft(convHF, length(t), 'symmetric'); %this is the part im confused about
% Ignore,
% tfC(numel(fNum)) = 0;
% convHF = tfC.*fNum;
% convHFMag = abs(convHF/n);
% timeHF = ifft(convHF);
%% plotting
% subplot(2, 2, 1);
% plot(t, Ly)
% title('Gaussian input');
% xlabel('time in seconds')
% ylabel('V')
% grid
subplot(2, 2, 1)
plot(frange, abs(tfC(1: L/2 + 1)));
set(gca, 'Xscale', 'log')
title('coax cable model')
xlabel('Hz')
ylabel('|H(s)|V/V')
grid
ylim([0 1.1])
subplot(2, 2, 2);
plot(frange, convHFMag(1:L/2+1), '.-', frange, fNumMag(1:L/2+1)) %make both range and function the same lenght
title('The input signal Vs its convolution with coax');
xlabel('Hz')
ylabel('V')
legend('Convolution','Lorentzian in frequecuency domain');
xlim([0, 5E10])
grid
subplot(2, 2, [3, 4]);
plot(t, Ly, t, timeHF)
% plot(t, real(timeHF(1:length(t)))) %make both range and function the same lenght
legend('Input', 'Output')
title('Signal at the output')
xlabel('time in seconds')
ylabel('V')
grid
It's important to understand deeply the principles of the FFT to use it correctly.
When you apply Fourier transform to a real signal, the coefficients at negative frequencies are the conjugate of the ones at positive frequencies. When you apply FFT to a real numerical signal, you can show mathematically that the conjugates of the coefficients that should be at negative frequencies (-f) will now appear at (Fsampling-f) where Fsampling=1/dt is the sampling frequency and dt the sampling period. This behavior is called aliasing and is present when you apply fft to a discrete time signal and the sampling period should be chosen small enaough for those two spectra not to overlap Shannon criteria.
When you want to apply a frequency filter to a signal, we say that we keep the first half of the spectrum because the high frequencies (>Fsampling/2) are due to aliasing and are not characteristics of the original signal. To do so, we put zeros on the second half of the spectra before multiplying by the filter. However, by doing so you also lose half of the amplitude of the original signal that you will not recover with ifft. The option 'symmetric' enable to recover it by adding in high frequencis (>Fsampling/2) the conjugate of the coefficients at lower ones (<Fsampling/2).
I simplified the code to explain briefly what's happening and implemented for you at line 20 a hand-made symmetrisation. Note that I reduced the sampling period from one to 100 picoseconds for the spectrum to display correctly:
close all
clc, clear
Fs = 14E10; %1 sample per pico seconds % CHANGED to 100ps
tlim = 4000E-12;
t = -tlim:1/Fs:tlim; %in pico seconds
ag = 0.5; %peak of guassian
bg = 0; %peak location
wg = 50E-12; %FWHM
NT = length(t);
x_i = ag.*exp(-4 .* log(2) .* (t-bg).^2 / (wg).^2); %Gauss. in terms of FWHM
fftx_i = fft(x_i);
f = 1/(2*tlim)*(0:NT-1);
fftx_r = fftx_i;
fftx_r(floor(NT/2):end) = 0; % The removal of high frequencies due to aliasing leads to losing half the amplitude
% HER YOU APPLY FILTER
x_r1 = ifft(fftx_r); % without symmetrisation (half the amplitude lost)
x_r2 = ifft(fftx_r, 'symmetric'); % with symmetrisation
x_r3 = ifft(fftx_r+[0, conj(fftx_r(end:-1:2))]); % hand-made symmetrisation
figure();
subplot(211)
hold on
plot(t, x_i, 'r')
plot(t, x_r2, 'r-+')
plot(t, x_r3, 'r-o')
plot(t, x_r1, 'k--')
hold off
legend('Initial', 'Matlab sym', 'Hand made sym', 'No sym')
title('Time signals')
xlabel('time in seconds')
ylabel('V')
grid
subplot(212)
hold on
plot(f, abs(fft(x_i)), 'r')
plot(f, abs(fft(x_r2)), 'r-+')
plot(f, abs(fft(x_r3)), 'r-o')
plot(f, abs(fft(x_r1)), 'k--')
hold off
legend('Initial', 'Matlab sym', 'Hand made sym', 'No sym')
title('Power spectra')
xlabel('frequency in hertz')
ylabel('V')
grid
Plots the result:
Do not hesitate if you have further questions. Good luck!
---------- EDIT ----------
The amplitude of discrete Fourier transform is not the same as the continuous one. If you are interested in showing signal in frequency domain, you will need to apply a normalization based on the convention you have chosen. In general, you use the convention that the amplitude of the Fourier transform of a Dirac delta function has amplitude one everywhere.
A numerical Dirac delta function has an amplitude of one at an index and zeros elsewhere and leads to a power spectrum equal to one everywhere. However in your case, the time axis has sample period dt, the integral over time of a numerical Dirac in that case is not 1 but dt. You must normalize your frequency domain signal by multiplying it by a factor dt (=1picoseceond in your case) to respect the convention. You can also note that this makes the frequency domain signal homogeneous to [unit of the original multiplied by a time] which is the correct unit of a Fourier transform.

From time domaine to frequency domain

I have a problem in my MATLAB program. I'm trying to find a cutoff frequency to create a low pass filter for compass data. I'm trying to go from the time domain to the frequency domain and find an Fc, so I used the FFT but it seems that's it's nor working.
This is what i have done:
dataset=xlsread('data.xlsx','Feuil1','A1:A751');
t=1:length(dataset);
z=abs(fft(dataset));
subplot(2,2,3)
plot(dataset)
title('dataNonFiltrer')
subplot(2,2,4)
plot(z)
title('frequenciel')
And i get this wish seems to be not correct:
You are just not plotting the data right.
To plot the fft of a signal X, do (from the docs):
Fs = 1000; % Sampling frequency of your data. YOU NEED TO KNOW THIS, change
L = length(X); % Length of signal
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('frequenciel X(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')

Applying bandpass in the Fourier for my signal in matlab

I'm trying to apply a bandpass around freq 0 without luck. I'd be happy to receive some help please
x=scan11(1,:)*1e-3/3e8; y=scan11(2,:);
plot(x,y) % my function
[XX,ff]=trans_fourier(y,mean(diff(x)));
plot(ff,abs(XX)) % gives the Fourier transform
I want to choose the freq around 0. let's suppose -1e13 till 1e13 and than to make ifft and to plot the signal after this filer.
How should I start doing this? the command
YY=bandpass(y,[-1e13 1e13],1/mean(diff(x)))
didn't help here unfortunately.
Since, i can't upload here files, here is also my question on matlab forum with all the files
matlab link
I am not sure what the contents of the trans_fourier function exactly are, but in 'plain matlab functions', you could attempt something along the lines of the following.
Nt = 1024; % Number of samples
Fs = 10; % Sampling frequency (samples / second)
t = (0:Nt-1)/Fs; % Time array
x = sin(t/10); % Low-frequency signal
x = x + 0.25*randn(1,Nt); % add some noise
X = fftshift(fft(x)); % FFT of signal with 0 Hz centered
fr = (-Nt/2 : Nt/2-1)/(Nt/Fs); % Frequency axis
% Filter: squared cosine (edit as desired)
fsl = 10; % Length of filter slope, in samples
filt = zeros(size(X));
filt(Nt/2+1+(-fsl:fsl)) = cos( linspace(-pi/2,pi/2,2*fsl+1) ).^2;
x_filt = real(ifft(ifftshift( filt.*X ))); % Filtered x
figure();
subplot(2,2,1); plot(t,x); ax=axis; title('original signal');
subplot(2,2,4); plot(t,x_filt); axis(ax); title('Low-pass filtered signal');
subplot(2,2,2); plot(fr,abs(X)); ax=axis; title('original amplitude spectrum');
subplot(2,2,3); plot(fr,abs(X).*filt); axis(ax); title('Filtered amplitude spectrum');
I am not sure what exactly you meant when you said
let's suppose -1e13 till 1e13
, but keep in mind that extracting a single fourier component (essentially setting all values of the spectrum to zero, except the one you are interested in) acts as a brick-wall filter, and you will get considerable artefacts if you take the inverse transform. Refer to this topic or this page if you're interested.

on the use and understanding of pwelch in matlab

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.