units for fft of temperature time series - matlab

I have a time series of air temperatures, that are measured in degrees C and the frequency of the signal is monthly. I compute the power spectra of the time series as:
L = length(temp);
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(temp,NFFT)/L;
Fs = 1; % one sample per month
f = Fs/2*linspace(0,1,NFFT/2+1); % frequency
Pxx = 2*abs(Y(1:NFFT/2+1)); % power
% Plot single-sided amplitude spectrum.
plot(f,Pxx,'-k');
xlabel('Frequency (c/month)'); % cycles per unit time
which results in the following plot.
What should the units be for the yaxis? Should it be ^{o}C?
The range of the time series is approx 20, so I guess 10 would work as the amplitude...

Let's say the original axes were T (vertical) and t (horizontal); after the transform, they are Y and X.
You correctly found that the units of X are reciprocals of the units of t. This is necessary for formulas like exp(2*pi*i*t*X) to make sense: the product t*X must be unitless.
Parseval's identity can be used to infer the units on the vertical axis. According to it,
(T units)2 (t units) = (Y units)2 (X units)
hence Y units = (T units) (t units). In your case this is degree-times-second, but this is better expressed as degree-per-frequency unit.
Indeed, the function produced by Fourier transform is amplitude density, expressing how much oscillation is there in every particular frequency range.

Related

How to convert a spectrum from spatial frequency to cyc/deg

I have a hard time wrapping my head around this since there is non-linearity involved. How do I convert a spectrum I have in units "1/m" (or cycles per m) to "cycles/deg"?
Example: For simplicity let's work in one dimension and the screen of a laptop is 768 pixels on which I show the highest pixel frequency. I use MATLAB/Octave style code but I hope it's clear enough to act as pseudo code:
X = 768
x = 0:X-1
y = cos(2*pi/X*(X/2)*x)
The frequency in this signal is now pi radiants or 0.5 cycles/pixel (sampling rate is 1 pixel). I can create the frequency vectors:
w = linspace(0, 2*pi, length(x)) % in radiants
f = linspace(0, 1, length(x)) % in 1/pixel or cycles/pixel
I can easily convert this to spatial frequency in units [m] and frequency [cycles/m] when I know the pixel size. Let's assume one pixel is 0.5mm:
xm = x*0.5e-3 % for image in m
fm = f/0.5e-3 % frequency in 1/m
Plotting y versus xm shows now a waveform with 1 cycle per mm. Plotting the FFT of y versus fm shows a peak at 1000 cycles/m (or 1 cycle per mm), as expected.
How do I need to modify fm to arrive at fdeg, in other words, to show the FFT of y in cycles per degree, assuming distance from the screen is 60cm? I would assume
fdeg = 1/(2*atan(1/fm)/(2*0.6)*180/pi)
That would give me 20.97 cycles/deg. However, using the small angle approximation, 1mm should be roughly 1mm/0.6*180/pi=0.9549e-3 degree, so we have 1cycle per 0.9549e-3 degrees or 1/0.9549e-3=10.47 cycles per degree. This is off by a factor of 2.

Matlab, FFT frequency range differences or are they the same?

I'm trying to understand how the FFT in matlab works, particularly, how to define the frequency range to plot it. It happens that I have read from matlab help links and from other discussions here and I think (guess) that I'm confused about it.
In the matlab link:
http://es.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html
they define such a frequency range as:
f = (0:n-1)*(fs/n)
with n and fs as:
n = 2^nextpow2(L); % Next power of 2 from length of signal x
fs = N/T; % N number of samples in x and T the total time of the recorded signal
But, on the other hand, in the previous post Understanding Matlab FFT example
(based on previous version of matlab), the resulting frequency range is defined as:
f = fs/2*linspace(0,1,NFFT/2+1);
with NFFT as the aforementioned n (Next power of 2 from length of signal x).
So, based on that, how these different vectors (equation 1 and final equation) could be the same?
If you can see, the vectors are different since the former has n points and the later has NFFT/2 points! In fact, the factor (fs/n) is different from fs/2.
So, based on that, how these different vectors (equation 1 and final equation) could be the same?
The example in the documentation from Mathworks plots the entire n-point output of the FFT. This covers the frequencies from 0 to nearly fs (exactly (n-1)/n * fs). They then make the following observation (valid for real inputs to the FFT):
The first half of the frequency range (from 0 to the Nyquist frequency fs/2) is sufficient to identify the component frequencies in the data, since the second half is just a reflection of the first half.
The other post you refer to just chooses to not show that redundant second half. It then uses half the number of points which also cover half the frequency range.
In fact, the factor (fs/n) is different from fs/2.
Perhaps the easiest way to make sense of it is to compare the output of the two expressions for some small value of n, says n=8 and setting fs=1 (since fs multiplies both expressions). On the one hand the output of the first expression [0:n-1]*(fs/n) would be:
0.000 0.125 0.250 0.500 0.625 0.750 0.875
whereas the output of fs/2*linspace(0,1,n/2+1) would be:
0.000 0.125 0.250 0.500
As you can see the set of frequencies are exactly the same up to Nyquist frequency fs/2.
The confusion is perhaps arising from the fact that the two examples which you have referenced are plotting results of the fft differently. Please refer to the code below for the references made in this explanation.
In the first example, the plot is of the power spectrum (periodogram) over the frequency range. Note, in the first plot, that the periodogram is not centered at 0, meaning that the frequency range appears to be twice that of the Nyquist sampling frequency. As mentioned in the mathworks link, it is common practice to center the periodogram at 0 to avoid this confusion (figure 2).
For the second example, taking the same parameters, the original plot is of amplitude of the fourier spectrum with a different normalization than in the first example (figure 3). Using the syntax of Matlab's full frequency ordering (as commented in the code), it is trivial to convert this seemingly different fft result to that of example 1; the identical result of the 0-centered periodogram is replicated in figure 4.
Thus, to answer your question specifically, the frequency ranges in both cases are the same, with the maximum frequency equal to the Nyquist sampling frequency as in:
f = fs/2*linspace(0,1,NFFT/2+1);
The key to understanding how the dfft works (also in Matlab) is to understand that you are simply performing a projection of your discrete data set into fourier space where what is returned by the fft() function in matlab are the coefficients of the expansion for each frequency component and the order of the coefficients is given (in Matlab as in example 2) by:
f = [f(1:end-1) -fliplr(f(1,2:end))];
See the Wikipedia page on the DFT for additional details:
https://en.wikipedia.org/wiki/Discrete_Fourier_transform
It might also be helpful for you to take the fft omitting the length as a power of 2 parameter as
y = fft(x).
In this case, you would see only a few non-zero components in y corresponding to the exact coefficients of your input signal. The mathworks page claims the following as a motivation for using or not using this length:
"Using a power of two for the transform length optimizes the FFT algorithm, though in practice there is usually little difference in execution time from using n = m."
%% First example:
% http://www.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html
fs = 10; % Sample frequency (Hz)
t = 0:1/fs:10-1/fs; % 10 sec sample
x = (1.3)*sin(2*pi*15*t) ... % 15 Hz component
+ (1.7)*sin(2*pi*40*(t-2)); % 40 Hz component
% Removed the noise
m = length(x); % Window length
n = pow2(nextpow2(m)); % Transform length
y = fft(x,n); % DFT
f = (0:n-1)*(fs/n); % Frequency range
power = y.*conj(y)/n; % Power of the DFT
subplot(2,2,1)
plot(f,power,'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf Periodogram}')
y0 = fftshift(y); % Rearrange y values
f0 = (-n/2:n/2-1)*(fs/n); % 0-centered frequency range
power0 = y0.*conj(y0)/n; % 0-centered power
subplot(2,2,2)
plot(f0,power0,'-o')
% plot(f0,sqrt_power0,'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf 0-Centered Periodogram} Ex. 1')
%% Second example:
% http://stackoverflow.com/questions/10758315/understanding-matlab-fft-example
% Let's redefine the parameters for consistency between the two examples
Fs = fs; % Sampling frequency
% T = 1/Fs; % Sample time (not required)
L = m; % Length of signal
% t = (0:L-1)*T; % Time vector (as above)
% % Sum of a 3 Hz sinusoid and a 2 Hz sinusoid
% x = 0.7*sin(2*pi*3*t) + sin(2*pi*2*t); %(as above)
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
% NFFT == n (from above)
Y = fft(x,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
% Plot single-sided amplitude spectrum.
subplot(2,2,3)
plot(f,2*abs(Y(1:NFFT/2+1)),'-o')
title('Single-Sided Amplitude Spectrum of y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
% Get the 0-Centered Periodogram using the parameters of the second example
f = [f(1:end-1) -fliplr(f(1,2:end))]; % This is the frequency ordering used
% by the full fft in Matlab
power = (Y*L).*conj(Y*L)/NFFT;
% Rearrange for nicer plot
ToPlot = [f; power]; [~,ind] = sort(f);
ToPlot = ToPlot(:,ind);
subplot(2,2,4)
plot(ToPlot(1,:),ToPlot(2,:),'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf 0-Centered Periodogram} Ex. 2')

How to find the frequency of a periodic sound signal?

I'm working on sound signals of a walking pattern, which has obvious regular patterns:
Then I thought I can get the frequency of walking (approximately 1.7Hz from the image) using FFT function:
x = walk_5; % Walking sound with a size of 711680x2 double
Fs = 48000; % sound frquency
L=length(x);
t=(1:L)/Fs; %time base
plot(t,x);
figure;
NFFT=2^nextpow2(L);
X=fft(x,NFFT);
Px=X.*conj(X)/(NFFT*L); %Power of each freq components
fVals=Fs*(0:NFFT/2-1)/NFFT;
plot(fVals,Px(1:NFFT/2),'b','LineSmoothing','on','LineWidth',1);
title('One Sided Power Spectral Density');
xlabel('Frequency (Hz)')
ylabel('PSD');
But then it doesn't give me what I expected:
FFT result:
zoom image has lots of noises:
and there is no information near 1.7Hz
Here is the graph from log domain using
semilogy(fVals,Px(1:NFFT));
It's pretty symmetric though:
I couldn't find anything wrong with my code. Do you have any solutions to easily extract the 1.7Hz from the walking pattern?
here is the link for the audio file in mat
https://www.dropbox.com/s/craof8qkz9n5dr1/walk_sound.mat?dl=0
Thank you very much!
Kai
I suggest you to forget about DFT approach since your signal is not appropriate for this type of analysis due to many reasons. Even by looking on the spectrum in range of frequencies that you are interested in, there is no easy way to estimate the peak:
Of course you could try with PSD/STFT and other funky methods, but this is an overkill. I can think of two, rather simple methods, for this task.
First one is based simply on the Auto Correlation Function.
Calculate the ACF
Define the minimum distance between them. Since you know that expected frequency is around 1.7Hz, then it corresponds to 0.58s. Let's make it 0.5s as the minimum distance.
Calculate the average distance between peaks found.
This gave me an approximate frequency of 1.72 Hz .
Second approach is based on the observation to your signal already has some peaks which are periodic. Therefore we can simply search for them using findpeaks function.
Define the minimum peak distance in a same way as before.
Define the minimum peak height. For example 10% of maximum peak.
Get the average difference.
This gave me an average frequency of 1.7 Hz.
Easy and fast method. There are obviously some things that can be improved, such as:
Refining thresholds
Finding both positive and negative peaks
Taking care of some missing peaks, i.e. due to low amplitude
Anyway that should get you started, instead of being stuck with crappy FFT and lazy semilogx.
Code snippet:
load walk_sound
fs = 48000;
dt = 1/fs;
x = walk_5(:,1);
x = x - mean(x);
N = length(x);
t = 0:dt:(N-1)*dt;
% FFT based
win = hamming(N);
X = abs(fft(x.*win));
X = 2*X(1:N/2+1)/sum(win);
X = 20*log10(X/max(abs(X)));
f = 0:fs/N:fs/2;
subplot(2,1,1)
plot(t, x)
grid on
xlabel('t [s]')
ylabel('A')
title('Time domain signal')
subplot(2,1,2)
plot(f, X)
grid on
xlabel('f [Hz]')
ylabel('A [dB]')
title('Signal Spectrum')
% Autocorrelation
[ac, lag] = xcorr(x);
min_dist = ceil(0.5*fs);
[pks, loc] = findpeaks(ac, 'MinPeakDistance', min_dist);
% Average distance/frequency
avg_dt = mean(gradient(loc))*dt;
avg_f = 1/avg_dt;
figure
plot(lag*dt, ac);
hold on
grid on
plot(lag(loc)*dt, pks, 'xr')
title(sprintf('ACF - Average frequency: %.2f Hz', avg_f))
% Simple peak finding in time domain
[pkst, loct] = findpeaks(x, 'MinPeakDistance', min_dist, ...
'MinPeakHeight', 0.1*max(x));
avg_dt2 = mean(gradient(loct))*dt;
avg_f2 = 1/avg_dt2;
figure
plot(t, x)
grid on
hold on
plot(loct*dt, pkst, 'xr')
xlabel('t [s]')
ylabel('A')
title(sprintf('Peak search in time domain - Average frequency: %.2f Hz', avg_f2))
Here's a nifty solution:
Take the absolute value of your raw data before taking the FFT. The data has a ton of high frequency noise that is drowning out whatever low frequency periodicity is present in the signal. The amplitude of the high frequency noise gets bigger every 1.7 seconds, and the increase in amplitude is visible to the eye, and periodic, but when you multiply the signal by a low frequency sine wave and sum everything you still end up with something close to zero. Taking the absolute value changes this, making those amplitude modulations periodic at low frequencies.
Try the following code comparing the FFT of the regular data with the FFT of abs(data). Note that I took a few liberties with your code, such as combining what I assume were the two stereo channels into a single mono channel.
x = (walk_5(:,1)+walk_5(:,2))/2; % Convert from sterio to mono
Fs = 48000; % sampling frquency
L=length(x); % length of sample
fVals=(0:L-1)*(Fs/L); % frequency range for FFT
walk5abs=abs(x); % Take the absolute value of the raw data
Xold=abs(fft(x)); % FFT of the data (abs in Matlab takes complex magnitude)
Xnew=abs(fft(walk5abs-mean(walk5abs))); % FFT of the absolute value of the data, with average value subtracted
figure;
plot(fVals,Xold/max(Xold),'r',fVals,Xnew/max(Xnew),'b')
axis([0 10 0 1])
legend('old method','new method')
[~,maxInd]=max(Xnew); % Index of maximum value of FFT
walkingFrequency=fVals(maxInd) % print max value
And plotting the FFT for both the old method and the new, from 0 to 10 Hz gives:
As you can see it detects a peak at about 1.686 Hz, and for this data, that's the highest peak in the FFT spectrum.

Comparing FFT of Function to Analytical FT Solution in Matlab

I am trying to compare the FFT of exp(-t^2) to the function's analytical fourier transform, exp(-(w^2)/4)/sqrt(2), over the frequency range -3 to 3.
I have written the following matlab code and have iterated on it MANY times now with no success.
fs = 100; %sampling frequency
dt = 1/fs;
t = 0:dt:10-dt; %time vector
L = length(t); %number of sample points
%N = 2^nextpow2(L); %necessary?
y = exp(-(t.^2));
Y=dt*ifftshift(abs(fft(y)));
freq = (-L/2:L/2-1)*fs/L; %freq vector
F = (exp(-(freq.^2)/4))/sqrt(2); %analytical solution
%Y_valid_pts = Y(W>=-3 & W<=3); %compare for freq = -3 to 3
%npts = length(Y_valid_pts);
% w = linspace(-3,3,npts);
% Fe = (exp(-(w.^2)/4))/sqrt(2);
error = norm(Y - F) %L2 Norm for error
hold on;
plot(freq,Y,'r');
plot(freq,F,'b');
xlabel('Frequency, w');
legend('numerical','analytic');
hold off;
You can see that right now, I am simply trying to get the two plots to look similar. Eventually, I would like to find a way to do two things:
1) find the minimum sampling rate,
2) find the minimum number of samples,
to reach an error (defined as the L2 norm of the difference between the two solutions) of 10^-4.
I feel that this is pretty simple, but I can't seem to even get the two graphs visually agree.
If someone could let me know where I'm going wrong and how I can tackle the two points above (minimum sampling frequency and minimum number of samples) I would be very appreciative.
Thanks
A first thing to note is that the Fourier transform pair for the function exp(-t^2) over the +/- infinity range, as can be derived from tables of Fourier transforms is actually:
Finally, as you are generating the function exp(-t^2), you are limiting the range of t to positive values (instead of taking the whole +/- infinity range).
For the relationship to hold, you would thus have to generate exp(-t^2) with something such as:
t = 0:dt:10-dt; %time vector
t = t - 0.5*max(t); %center around t=0
y = exp(-(t.^2));
Then, the variable w represents angular frequency in radians which is related to the normalized frequency freq through:
w = 2*pi*freq;
Thus,
F = (exp(-((2*pi*freq).^2)/4))*sqrt(pi); %analytical solution

FFTW and fft with MatLab

I have a weird problem with the discrete fft. I know that the Fourier Transform of a Gauss function exp(-x^2/2) is again the same Gauss function exp(-k^2/2). I tried to test that with some simple code in MatLab and FFTW but I get strange results.
First, the imaginary part of the result is not zero (in MatLab) as it should be.
Second, the absolute value of the real part is a Gauss curve but without the absolute value half of the modes have a negative coefficient. More precisely, every second mode has a coefficient that is the negative of that what it should be.
Third, the peak of the resulting Gauss curve (after taking the absolute value of the real part) is not at one but much higher. Its height is proportional to the number of points on the x-axis. However, the proportionality factor is not 1 but nearly 1/20.
Could anyone explain me what I am doing wrong?
Here is the MatLab code that I used:
function [nooutput,M] = fourier_test
Nx = 512; % number of points in x direction
Lx = 50; % width of the window containing the Gauss curve
x = linspace(-Lx/2,Lx/2,Nx); % creating an equidistant grid on the x-axis
input_1d = exp(-x.^2/2); % Gauss function as an input
input_1d_hat = fft(input_1d); % computing the discrete FFT
input_1d_hat = fftshift(input_1d_hat); % ordering the modes such that the peak is centred
plot(real(input_1d_hat), '-')
hold on
plot(imag(input_1d_hat), 'r-')
The answer is basically what Paul R suggests in his second comment, you introduce a phase shift (linearly dependent on the frequency) because the center of the Gaussian described by input_1d_hat is effectively at k>0, where k+1 is the index into input_1d_hat. Instead if you center your data (such that input_1d_hat(1) corresponds to the center) as follows you get a phase-corrected Gaussian in the frequency domain:
Nx = 512; % number of points in x direction
Lx = 50; % width of the window containing the Gauss curve
x = linspace(-Lx/2,Lx/2,Nx); % creating an equidistant grid on the x-axis
%%%%%%%%%%%%%%%%
x=fftshift(x); % <-- center
%%%%%%%%%%%%%%%%
input_1d = exp(-x.^2/2); % Gauss function as an input
input_1d_hat = fft(input_1d); % computing the discrete FFT
input_1d_hat = fftshift(input_1d_hat); % ordering the modes such that the peak is centered
plot(real(input_1d_hat), '-')
hold on
plot(imag(input_1d_hat), 'r-')
From the definition of the DFT, if the Gaussian is not centered such that maximum occurs at k=0, you will see a phase twist. The effect off fftshift is to perform a circular shift or swapping of left and right sides of the dataset, which is equivalent to shifting the center of the peak to k=0.
As for the amplitude scaling, that is an issue with the definition of the DFT implemented in Matlab. From the documentation for the FFT:
For length N input vector x, the DFT is a length N vector X,
with elements
N
X(k) = sum x(n)*exp(-j*2*pi*(k-1)*(n-1)/N), 1 <= k <= N.
n=1
The inverse DFT (computed by IFFT) is given by
N
x(n) = (1/N) sum X(k)*exp( j*2*pi*(k-1)*(n-1)/N), 1 <= n <= N.
k=1
Note that in the forward step the summation is not normalized by N. Therefore if you increase the number of points Nx in the summation while keeping the width Lx of the Gaussian function constant you will increase X(k) proportionately.
As for signal leaking into the imaginary frequency dimension, that is due to the discrete form of the DFT, which results in truncation and other effects, as noted again by Paul R. If you reduce Lx while keeping Nx constant, you should see a reduction in the amount of signal in the imaginary dimension relative to the real dimension (compare the spectra while keeping peak intensities in the real dimension equal).
You'll find additional answers to similar questions here and here.