Why are these two plots different? - matlab

Here I am plotting a spectrogram twice, once using imagesc and once using the spectrogram automatic plotting. I don't know why I get different scaling results, probably some filtering by the automatic plotting function but I would like to know what exactly and how to transform it so that it matches.
fs = 44100;
% Frequency sweep signal
sw = logspace(log10(500),log10(5000),fs*5);
x = 0.95 * sin(cumsum((2*pi*sw)/fs));
N = 128;
win_size = N;
noverlap = N/2;
win = window(#blackman,win_size);
[s,f,t] = spectrogram(x,win,noverlap,N,fs,'yaxis');
%% IMAGESC --- FIGURE 1
figure(1)
imagesc(t,f/1000,20*log(abs(s)));
title('Spectrogram');
set(gca,'Ydir','Normal');
xlabel('Time (secs)');
ylabel('Frequency (kHz)');
hcb=colorbar;
title(hcb,'Spectral Magnitude (dB)');
%% test with automatic spectrogram plot ---FIGURE2
figure(2)
spectrogram(x,win,noverlap,N,fs,'yaxis');
end
Help is appreciated :)

Change your code "imagesc(t,f/1000,20*log(abs(s)))" as imagesc(t,f/1000,20*log10(abs(s))).
log() is natural logarithm.
When you calculate dB scale, you should use log10(), not log().

Related

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.

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.

Solving convolutions in Matlab using `conv` or `fft`

This is follow-up question to my other SO post about performing multiple convolutions like
where the functions are defined in my code below.
I need to rescale the result of the convolution with respect to the number of time steps in the calculation, N.
N = 1000;
t = linspace(-10,10,N);
x = t.*exp(-t.^2);
y = exp(-4*t.^2).*cos(t);
z = (t-2)/((t-2).^2+3^2);
w = exp(-3*t.^2).*exp(2i*t);
% convolution
u = conv(conv(conv(x,y)/N,z)/N,w)/N;
% Fourier transform
L_x=fft(x)/N;
L_y=fft(y)/N;
L_z=fft(z)/N;
L_w=fft(w)/N;
L_u=L_x.*L_y.*L_z.*L_w; %convolution on frequency domain
v=ifft(L_u)*N;
figure(1)
ax1 = subplot(2,1,1);
ax2 = subplot(2,1,2);
plot(ax1,1:length(u),real(u))
title(ax1,'conv')
hold off
plot(ax2,t,real(v))
title(ax2,'fft')
xlabel(ax2,'t')
How do I scale the convolution correctly? (N.B. If I change to N=1e5 timesteps, the y-values decrease).
How do I ensure that the conv output spans the same time region as the fft output? Graph of real part of convolution below:

DFT code on Matlab does not work as intended

I am trying to implement a basic DFT algorithm on Matlab.
I simply use in phase and quadrature components of a sine wave with phase modulation(increasing frequency a.k.a chirp). I do compare my results with fft command of Matlab. My code gives the same results whenever there is no phase modulation(pure sine). Whenever I add chirp modulation, results differ. For example, when I use a chirp with some bandwidth around a carrier, the expected results should be a frequency distribution of chirp bandwidth starting from carrier frequency. However, I get a copy of that result backwards starting from carrier frequency as well. You can use my code below without modifying anything. Figure 5 is my result and figure 6 is the expected result. Carrier is 256 Hz with a 10Hz bandwidth of chirp. You can see the code below. The important part is for loop where I take dft of my signal. Also uou can see my dft result below.
close all;
clear all;
%% signal generation
t = (0:0.0001:1); % 1 second window
f = 256; %freq of input signal in hertz
bw = 10; % bandwidth sweep of signal
phaseInput = 2*pi*t*bw.*t;
signalInput = sin(2*pi*f*t + phaseInput); %input signal
inphase = sin(2*pi*f*t).*cos(phaseInput); %inphase component
quadrature = cos(2*pi*f*t).*sin(phaseInput); %quadrature component
figure
plot(t,signalInput,'b',t,inphase,'g',t,quadrature,'r');
title('Input Signal');
xlabel('Time in seconds');
ylabel('Amplitude');
%% sampling signal previously generated
Fs = 1024; %sampling freq
Ts = (0:1/Fs:1);%sample times for 1 second window
sPhase = 2*pi*Ts*bw.*Ts;
sI = sin(2*pi*f*Ts).*cos(sPhase);
sQ = cos(2*pi*f*Ts).*sin(sPhase);
hold on;
plot(Ts,sI+sQ,'b*',Ts,sI,'g*',Ts,sQ,'r*');
fftSize = Fs; %Using all samples in dft
sampleIdx = (0:1:fftSize-1)';
sampledI = sI(1:fftSize)';
sampledQ = sQ(1:fftSize)';
figure;
plot(sampleIdx,sampledI,sampleIdx,sampledQ);
title('Sampled IQ Components');
%% DFT Calculation
dftI = zeros(fftSize,1);
dftQ = zeros(fftSize,1);
for w = 0:fftSize-1
%exp(-2*pi*w*t) = cos(2*pi*w*t) - i*sin(2*pi*w*t)
cI = cos(2*pi*w*sampleIdx/fftSize); %correlation cos
cQ = -sin(2*pi*w*sampleIdx/fftSize); %correlation sin
dftI(w+1) = sum(sampledI.*cI - sampledQ.*cQ); %
dftQ(w+1) = sum(sampledI.*cQ + sampledQ.*cI);
end;
figure;
plot(Fs*sampleIdx/fftSize,dftI);
title('DFT Inphase');
xlabel('Hertz');
figure
plot(Fs*sampleIdx/fftSize,dftQ);
title('DFT Quadrature');
xlabel('Hertz');
figure;
plot(Fs*sampleIdx/fftSize,sqrt(dftQ.^2+dftI.^2));
%% For comparison
sampledInput = sin(2*pi*f*Ts + sPhase);
Y = fft(sampledInput(1:1024),1024);
Pyy = Y.*conj(Y)/1024;
f = (0:1023);
figure;
plot(f,Pyy)
title('Power spectral density')
xlabel('Frequency (Hz)')
the reason lies in the fact that two different signals will definitely give your two different frequency spectrums. check out the code below, you will find that the input of the dft algorithm you actually gave is sampledI+jsampledQ. as a result, what you are doing here is NOT merely decomposing your original signal into In-phase and quadrature components, instead, you are doing Hilbert transform here -- to change a real signal into a complex one.
cI = cos(2*pi*w*sampleIdx/fftSize); %correlation cos
cQ = -sin(2*pi*w*sampleIdx/fftSize); %correlation sin
dftI(w+1) = sum(sampledI.*cI - sampledQ.*cQ); %
dftQ(w+1) = sum(sampledI.*cQ + sampledQ.*cI);
so the sampledInput for comparison should be sampledInput = sI+1i*sQ;.

Fourier transform and LTI filter and frequency response in Matlab

I'm new to Matlab for LTI signal processing and wondering if anyone can help with something that I'm sure is meant to be basic. I've spent hours and hours researching and obtaining background information and still cannot obtain a clear path to tackle these problems. So far, from scratch, I have generated a signal required and managed to use the fft function to produce the signal's DFT:
function x = fourier_rikki(A,t,O)
Fs = 1000;
t = 0:(1/Fs):1;
A = [0.5,0,0.5];
N = (length(A) - 1)/2;
x = zeros(size(t));
f1 = 85;
O1 = 2*pi*f1;
for k = 1:length(A)
x1 = x + A(k)*exp(1i*O1*t*(k-N-1));
end
f2 = 150;
O2 = 2*pi*f2;
for k = 1:length(A);
x2 = x + A(k)*exp(1i*O2*t*(k-N-1));
end
f3 = 330;
O3 = 2*pi*f3;
for k = 1:length(A);
x3 = x + A(k)*exp(1i*O3*t*(k-N-1));
end
signal = x1 + x2 + x3;
figure(1);
subplot(3,1,1);
plot(t, signal);
title('Signal x(t) in the Time Domain');
xlabel('Time (Seconds)');
ylabel('x(t)');
X = fft(signal); %DFT of the signal
subplot(3,1,2);
plot(t, X);
title('Power Spectrum of Discrete Fourier Transform of x(t)');
xlabel('Time (Seconds)');
ylabel('Power');
f = linspace(0, 1000, length(X)); %?
subplot(3,1,3);
plot(f, abs(X)); %Only want the positive values
title('Spectral Frequency');
xlabel('Frequency (Hz)'); ylabel('Power');
end
At this stage, I'm assuming this is correct for:
"Generate a signal with frequencies 85,150,330Hz using a sampling frequency of 1000Hz - plot 1seconds worth of the signal and its Discrete Fourier Transform."
The next step is to "Find the frequency response of an LTI system that filters out the higher and lower frequencies using the Fourier Transform". I'm stuck trying to create an LTI system that does that! I have to be left with the 150Hz signal, and I'm guessing I perform the filtering on the FFT, perhaps using conv.
My course is not a programming course - we are not assessed on our programming skills and I have minimal Matlab experience - basically we have been left to our own devices to struggle through, so any help would be greatly appreciated! I am sifting through tonnes of different examples and searching Matlab functions using 'help' etc, but since each one is different and does not have a break down of the variables used, explaining why certain parameters/values are chosen etc. it is just adding to the confusion.
Among many (many) others I have looked at:
http://www.ee.columbia.edu/~ronw/adst-spring2010/lectures/matlab/lecture1.html
http://gribblelab.org/scicomp/09_Signals_and_sampling.html section 10.4 especially.
As well as Matlab Geeks examples and Mathworks Matlab function explanations.
I guess the worst that can happen is that nobody answers and I continue burning my eyeballs out until I manage to come up with something :) Thanks in advance.
I found this bandpass filter code as a Mathworks example, which is exactly what needs to be applied to my fft signal, but I don't understand the attenuation values Ast or the amount of ripple Ap.
n = 0:159;
x = cos(pi/8*n)+cos(pi/2*n)+sin(3*pi/4*n);
d = fdesign.bandpass('Fst1,Fp1,Fp2,Fst2,Ast1,Ap,Ast2',1/4,3/8,5/8,6/8,60,1,60);
Hd = design(d,'equiripple');
y = filter(Hd,x);
freq = 0:(2*pi)/length(x):pi;
xdft = fft(x);
ydft = fft(y);
plot(freq,abs(xdft(1:length(x)/2+1)));
hold on;
plot(freq,abs(ydft(1:length(x)/2+1)),'r','linewidth',2);
legend('Original Signal','Bandpass Signal');
Here is something you can use as a reference. I think I got the gist of what you were trying to do. Let me know if you have any questions.
clear all
close all
Fs = 1000;
t = 0:(1/Fs):1;
N = length(t);
% 85, 150, and 330 Hz converted to radian frequency
w1 = 2*pi*85;
w2 = 2*pi*150;
w3 = 2*pi*330;
% amplitudes
a1 = 1;
a2 = 1.5;
a3 = .75;
% construct time-domain signals
x1 = a1*cos(w1*t);
x2 = a2*cos(w2*t);
x3 = a3*cos(w3*t);
% superposition of 85, 150, and 330 Hz component signals
x = x1 + x2 + x3;
figure
plot(t(1:100), x(1:100));
title('unfiltered time-domain signal, amplitude vs. time');
ylabel('amplitude');
xlabel('time (seconds)');
% compute discrete Fourier transform of time-domain signal
X = fft(x);
Xmag = 20*log10(abs(X)); % magnitude spectrum
Xphase = 180*unwrap(angle(X))./pi; % phase spectrum (degrees)
w = 2*pi*(0:N-1)./N; % normalized radian frequency
f = w./(2*pi)*Fs; % radian frequency to Hz
k = 1:N; % bin indices
% plot magnitude spectrum
figure
plot(f, Xmag)
title('frequency-domain signal, magnitude vs. frequency');
xlabel('frequency (Hz)');
ylabel('magnitude (dB)');
% frequency vector of the filter. attenuates undesired frequency components
% and keeps desired components.
H = 1e-3*ones(1, length(k));
H(97:223) = 1;
H((end-223):(end-97)) = 1;
% plot magnitude spectrum of signal and filter
figure
plot(k, Xmag)
hold on
plot(k, 20*log10(H), 'r')
title('frequency-domain signal (blue) and filter (red), magnitude vs. bin index');
xlabel('bin index');
ylabel('magnitude (dB)');
% filtering in frequency domain is just multiplication
Y = X.*H;
% plot magnitude spectrum of filtered signal
figure
plot(f, 20*log10(abs(Y)))
title('filtered frequency-domain signal, magnitude vs. frequency');
xlabel('frequency (Hz)');
ylabel('magnitude (dB)');
% use inverse discrete Fourier transform to obtain the filtered time-domain
% signal. This signal is complex due to imperfect symmetry in the
% frequency-domain, however the imaginary components are nearly zero.
y = ifft(Y);
% plot overlay of filtered signal and desired signal
figure
plot(t(1:100), x(1:100), 'r')
hold on
plot(t(1:100), x2(1:100), 'linewidth', 2)
plot(t(1:100), real(y(1:100)), 'g')
title('input signal (red), desired signal (blue), signal extracted via filtering (green)');
ylabel('amplitude');
xlabel('time (seconds)');
Here is the end result...