Got Questions? Get Answers.
Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
FFT: DC component of single-sided amplitude spectrum is doubled

Subject: FFT: DC component of single-sided amplitude spectrum is doubled

From: Hermano Cappa

Date: 5 Mar, 2010 16:27:10

Message: 1 of 7

Hello,

I want to calculate the amplitude spectrum of a measured signal and plot only a single side of this spectrum (with the DC component). To keep the energy the same I have to double the amplitude of the components in the spectrum EXCEPT the DC component (the value of the DC component must remain the same). How can I do this on a proper way in my code?


N_sample = length(displacement_x);
data_harm_x = 2/N_sample*fft(displacement_x);

xstem = 0:1:(N_points/2)-1;
ystem_abs = abs(data_harm_x(1:N_points/2,:));
stem(xstem,ystem_abs);

Thanks

Subject: FFT: DC component of single-sided amplitude spectrum is doubled

From: Frank

Date: 5 Mar, 2010 16:50:44

Message: 2 of 7

If you have the Signal Processing Toolbox, see the "periodogram"
function. It takes care of all that for you.

Subject: FFT: DC component of single-sided amplitude spectrum is doubled

From: Wayne King

Date: 5 Mar, 2010 17:29:25

Message: 3 of 7

"Hermano Cappa" <cappasteven@gmail.com> wrote in message <hmrbcu$ged$1@fred.mathworks.com>...
> Hello,
>
> I want to calculate the amplitude spectrum of a measured signal and plot only a single side of this spectrum (with the DC component). To keep the energy the same I have to double the amplitude of the components in the spectrum EXCEPT the DC component (the value of the DC component must remain the same). How can I do this on a proper way in my code?
>
>
> N_sample = length(displacement_x);
> data_harm_x = 2/N_sample*fft(displacement_x);
>
> xstem = 0:1:(N_points/2)-1;
> ystem_abs = abs(data_harm_x(1:N_points/2,:));
> stem(xstem,ystem_abs);
>
> Thanks

Hi Hermano, as Frank rightly suggests the SPT functions take care of the scaling for you. There are also spectrum objects, spectrum.periodogram, etc. that do this as well

Ex: Compare the brute force way with spectrum.periodogram

x = randn(1024,1);
% scaling one-sided PSD estimate by brute force when normalized frequency is used
xFFT = fft(x);
xFFT = 1/(2*pi*length(x))*abs(xFFT(1:513)).^2; xFFT(2:end)=2*xFFT(2:end);
H = spectrum.periodogram;
Hpsd = psd(H,x,'NFFT',length(x));
plot(Hpsd)
figure
plot(Hpsd.Frequencies/pi, 10*log10(xFFT));
grid on


Hope that helps,
Wayne

Subject: FFT: DC component of single-sided amplitude spectrum is doubled

From: Hermano Cappa

Date: 8 Mar, 2010 09:41:05

Message: 4 of 7

"Wayne King" <wmkingty@gmail.com> wrote in message <hmrf1l$9su$1@fred.mathworks.com>...
> "Hermano Cappa" <cappasteven@gmail.com> wrote in message <hmrbcu$ged$1@fred.mathworks.com>...
> > Hello,
> >
> > I want to calculate the amplitude spectrum of a measured signal and plot only a single side of this spectrum (with the DC component). To keep the energy the same I have to double the amplitude of the components in the spectrum EXCEPT the DC component (the value of the DC component must remain the same). How can I do this on a proper way in my code?
> >
> >
> > N_sample = length(displacement_x);
> > data_harm_x = 2/N_sample*fft(displacement_x);
> >
> > xstem = 0:1:(N_points/2)-1;
> > ystem_abs = abs(data_harm_x(1:N_points/2,:));
> > stem(xstem,ystem_abs);
> >
> > Thanks
>
> Hi Hermano, as Frank rightly suggests the SPT functions take care of the scaling for you. There are also spectrum objects, spectrum.periodogram, etc. that do this as well
>
> Ex: Compare the brute force way with spectrum.periodogram
>
> x = randn(1024,1);
> % scaling one-sided PSD estimate by brute force when normalized frequency is used
> xFFT = fft(x);
> xFFT = 1/(2*pi*length(x))*abs(xFFT(1:513)).^2; xFFT(2:end)=2*xFFT(2:end);
> H = spectrum.periodogram;
> Hpsd = psd(H,x,'NFFT',length(x));
> plot(Hpsd)
> figure
> plot(Hpsd.Frequencies/pi, 10*log10(xFFT));
> grid on
>
>
> Hope that helps,
> Wayne

Hi Wayne, thanks for your reply. The solution you proposed give the "amplitude" in dB/Hz. But I want to plot the amplitude in meters instead of dB/Hz because the unit of my signal is also in meters. Can I also use the stem function to plot the spectrum?

Thanks

Subject: FFT: DC component of single-sided amplitude spectrum is doubled

From: Wayne King

Date: 8 Mar, 2010 12:30:06

Message: 5 of 7

"Hermano Cappa" <cappasteven@gmail.com> wrote in message <hn2gnh$fjs$1@fred.mathworks.com>...
> "Wayne King" <wmkingty@gmail.com> wrote in message <hmrf1l$9su$1@fred.mathworks.com>...
> > "Hermano Cappa" <cappasteven@gmail.com> wrote in message <hmrbcu$ged$1@fred.mathworks.com>...
> > > Hello,
> > >
> > > I want to calculate the amplitude spectrum of a measured signal and plot only a single side of this spectrum (with the DC component). To keep the energy the same I have to double the amplitude of the components in the spectrum EXCEPT the DC component (the value of the DC component must remain the same). How can I do this on a proper way in my code?
> > >
> > >
> > > N_sample = length(displacement_x);
> > > data_harm_x = 2/N_sample*fft(displacement_x);
> > >
> > > xstem = 0:1:(N_points/2)-1;
> > > ystem_abs = abs(data_harm_x(1:N_points/2,:));
> > > stem(xstem,ystem_abs);
> > >
> > > Thanks
> >
> > Hi Hermano, as Frank rightly suggests the SPT functions take care of the scaling for you. There are also spectrum objects, spectrum.periodogram, etc. that do this as well
> >
> > Ex: Compare the brute force way with spectrum.periodogram
> >
> > x = randn(1024,1);
> > % scaling one-sided PSD estimate by brute force when normalized frequency is used
> > xFFT = fft(x);
> > xFFT = 1/(2*pi*length(x))*abs(xFFT(1:513)).^2; xFFT(2:end)=2*xFFT(2:end);
> > H = spectrum.periodogram;
> > Hpsd = psd(H,x,'NFFT',length(x));
> > plot(Hpsd)
> > figure
> > plot(Hpsd.Frequencies/pi, 10*log10(xFFT));
> > grid on
> >
> >
> > Hope that helps,
> > Wayne
>
> Hi Wayne, thanks for your reply. The solution you proposed give the "amplitude" in dB/Hz. But I want to plot the amplitude in meters instead of dB/Hz because the unit of my signal is also in meters. Can I also use the stem function to plot the spectrum?
>
> Thanks
Hi Hermano,
I'm assuming from your post that when you say "the unit of my signal is also in meters" that you have a signal which is a function of time where the dependent variable, the function value, is in meters? In other words, you have some kind of displacement measure. If that is right you can just plot the absolute value of the Fourier transform, but you'd have to scale it properly to approximate the amplitude of the sinusoidal components. A simple example:

Fs =1000;
t= 0:1/Fs:1-(1/Fs);
x=cos(2*pi*100*t)+0.5*sin(2*pi*250*t);
xDFT = fft(x);
xDFT = xDFT(1:length(x)/2+1);
DeltaF =Fs/length(x);
Freq = 0:DeltaF:500;
plot(Freq,2*abs(xDFT)/length(x));
xlabel('Hz'); ylabel('|x(t)| (meters)');
set(gca,'ytick',[0 0.25 0.5 0.75 1 1.5])

If your signal is corrupted by noise, this simple example is not going to be effective and there are other things you can do. But since we don't your signal details... For other possibilities, see my post in
http://www.mathworks.com/matlabcentral/newsreader/view_thread/275383#723194

Also, I have assumed that you are sampling your signal as function of time (at one position in space) and not as a function of space. I hope I have not misunderstood your details.

Wayne

Subject: FFT: DC component of single-sided amplitude spectrum is doubled

From: Steve Amphlett

Date: 8 Mar, 2010 13:25:10

Message: 6 of 7

"Wayne King" <wmkingty@gmail.com> wrote in message <hn2qke$fnp$1@fred.mathworks.com>...
> "Hermano Cappa" <cappasteven@gmail.com> wrote in message <hn2gnh$fjs$1@fred.mathworks.com>...
> > "Wayne King" <wmkingty@gmail.com> wrote in message <hmrf1l$9su$1@fred.mathworks.com>...
> > > "Hermano Cappa" <cappasteven@gmail.com> wrote in message <hmrbcu$ged$1@fred.mathworks.com>...
> > > > Hello,
> > > >
> > > > I want to calculate the amplitude spectrum of a measured signal and plot only a single side of this spectrum (with the DC component). To keep the energy the same I have to double the amplitude of the components in the spectrum EXCEPT the DC component (the value of the DC component must remain the same). How can I do this on a proper way in my code?
> > > >
> > > >
> > > > N_sample = length(displacement_x);
> > > > data_harm_x = 2/N_sample*fft(displacement_x);
> > > >
> > > > xstem = 0:1:(N_points/2)-1;
> > > > ystem_abs = abs(data_harm_x(1:N_points/2,:));
> > > > stem(xstem,ystem_abs);
> > > >
> > > > Thanks
> > >
> > > Hi Hermano, as Frank rightly suggests the SPT functions take care of the scaling for you. There are also spectrum objects, spectrum.periodogram, etc. that do this as well
> > >
> > > Ex: Compare the brute force way with spectrum.periodogram
> > >
> > > x = randn(1024,1);
> > > % scaling one-sided PSD estimate by brute force when normalized frequency is used
> > > xFFT = fft(x);
> > > xFFT = 1/(2*pi*length(x))*abs(xFFT(1:513)).^2; xFFT(2:end)=2*xFFT(2:end);
> > > H = spectrum.periodogram;
> > > Hpsd = psd(H,x,'NFFT',length(x));
> > > plot(Hpsd)
> > > figure
> > > plot(Hpsd.Frequencies/pi, 10*log10(xFFT));
> > > grid on
> > >
> > >
> > > Hope that helps,
> > > Wayne
> >
> > Hi Wayne, thanks for your reply. The solution you proposed give the "amplitude" in dB/Hz. But I want to plot the amplitude in meters instead of dB/Hz because the unit of my signal is also in meters. Can I also use the stem function to plot the spectrum?
> >
> > Thanks
> Hi Hermano,
> I'm assuming from your post that when you say "the unit of my signal is also in meters" that you have a signal which is a function of time where the dependent variable, the function value, is in meters? In other words, you have some kind of displacement measure. If that is right you can just plot the absolute value of the Fourier transform, but you'd have to scale it properly to approximate the amplitude of the sinusoidal components. A simple example:
>
> Fs =1000;
> t= 0:1/Fs:1-(1/Fs);
> x=cos(2*pi*100*t)+0.5*sin(2*pi*250*t);
> xDFT = fft(x);
> xDFT = xDFT(1:length(x)/2+1);
> DeltaF =Fs/length(x);
> Freq = 0:DeltaF:500;
> plot(Freq,2*abs(xDFT)/length(x));
> xlabel('Hz'); ylabel('|x(t)| (meters)');
> set(gca,'ytick',[0 0.25 0.5 0.75 1 1.5])
>
> If your signal is corrupted by noise, this simple example is not going to be effective and there are other things you can do. But since we don't your signal details... For other possibilities, see my post in
> http://www.mathworks.com/matlabcentral/newsreader/view_thread/275383#723194
>
> Also, I have assumed that you are sampling your signal as function of time (at one position in space) and not as a function of space. I hope I have not misunderstood your details.


Going back to the original question...

Yes, the DC component is doubled. You'll need to scale it by 1/length(x), not 2/length(x). Probably simplest to scale the whole spectrum by 2/length(x) and then divide the first point by 2. The Nyquist component is also doubled.

Subject: FFT: DC component of single-sided amplitude spectrum is doubled

From: Hermano Cappa

Date: 9 Mar, 2010 17:33:03

Message: 7 of 7

"Steve Amphlett" <Firstname.Lastname@Where-I-Work.com> wrote in message <hn2trm$ajq$1@fred.mathworks.com>...
> "Wayne King" <wmkingty@gmail.com> wrote in message <hn2qke$fnp$1@fred.mathworks.com>...
> > "Hermano Cappa" <cappasteven@gmail.com> wrote in message <hn2gnh$fjs$1@fred.mathworks.com>...
> > > "Wayne King" <wmkingty@gmail.com> wrote in message <hmrf1l$9su$1@fred.mathworks.com>...
> > > > "Hermano Cappa" <cappasteven@gmail.com> wrote in message <hmrbcu$ged$1@fred.mathworks.com>...
> > > > > Hello,
> > > > >
> > > > > I want to calculate the amplitude spectrum of a measured signal and plot only a single side of this spectrum (with the DC component). To keep the energy the same I have to double the amplitude of the components in the spectrum EXCEPT the DC component (the value of the DC component must remain the same). How can I do this on a proper way in my code?
> > > > >
> > > > >
> > > > > N_sample = length(displacement_x);
> > > > > data_harm_x = 2/N_sample*fft(displacement_x);
> > > > >
> > > > > xstem = 0:1:(N_points/2)-1;
> > > > > ystem_abs = abs(data_harm_x(1:N_points/2,:));
> > > > > stem(xstem,ystem_abs);
> > > > >
> > > > > Thanks
> > > >
> > > > Hi Hermano, as Frank rightly suggests the SPT functions take care of the scaling for you. There are also spectrum objects, spectrum.periodogram, etc. that do this as well
> > > >
> > > > Ex: Compare the brute force way with spectrum.periodogram
> > > >
> > > > x = randn(1024,1);
> > > > % scaling one-sided PSD estimate by brute force when normalized frequency is used
> > > > xFFT = fft(x);
> > > > xFFT = 1/(2*pi*length(x))*abs(xFFT(1:513)).^2; xFFT(2:end)=2*xFFT(2:end);
> > > > H = spectrum.periodogram;
> > > > Hpsd = psd(H,x,'NFFT',length(x));
> > > > plot(Hpsd)
> > > > figure
> > > > plot(Hpsd.Frequencies/pi, 10*log10(xFFT));
> > > > grid on
> > > >
> > > >
> > > > Hope that helps,
> > > > Wayne
> > >
> > > Hi Wayne, thanks for your reply. The solution you proposed give the "amplitude" in dB/Hz. But I want to plot the amplitude in meters instead of dB/Hz because the unit of my signal is also in meters. Can I also use the stem function to plot the spectrum?
> > >
> > > Thanks
> > Hi Hermano,
> > I'm assuming from your post that when you say "the unit of my signal is also in meters" that you have a signal which is a function of time where the dependent variable, the function value, is in meters? In other words, you have some kind of displacement measure. If that is right you can just plot the absolute value of the Fourier transform, but you'd have to scale it properly to approximate the amplitude of the sinusoidal components. A simple example:
> >
> > Fs =1000;
> > t= 0:1/Fs:1-(1/Fs);
> > x=cos(2*pi*100*t)+0.5*sin(2*pi*250*t);
> > xDFT = fft(x);
> > xDFT = xDFT(1:length(x)/2+1);
> > DeltaF =Fs/length(x);
> > Freq = 0:DeltaF:500;
> > plot(Freq,2*abs(xDFT)/length(x));
> > xlabel('Hz'); ylabel('|x(t)| (meters)');
> > set(gca,'ytick',[0 0.25 0.5 0.75 1 1.5])
> >
> > If your signal is corrupted by noise, this simple example is not going to be effective and there are other things you can do. But since we don't your signal details... For other possibilities, see my post in
> > http://www.mathworks.com/matlabcentral/newsreader/view_thread/275383#723194
> >
> > Also, I have assumed that you are sampling your signal as function of time (at one position in space) and not as a function of space. I hope I have not misunderstood your details.
>
>
> Going back to the original question...
>
> Yes, the DC component is doubled. You'll need to scale it by 1/length(x), not 2/length(x). Probably simplest to scale the whole spectrum by 2/length(x) and then divide the first point by 2. The Nyquist component is also doubled.


Oke, thank you very much for helping me Wayne and Steve.

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us