I am trying to use the ifft function in MATLAB on some experimental data, but I don't get the expected results.
I have frequency data of a logarithmic sine sweep excitation, therefore I know the amplitude [g's], the frequency [Hz] and the phase (which is 0 since the point is a piloting point).
I tried to feed it directly to the ifft function, but I get a complex number as a result (and I expected a real result since it is a time signal). I thought the problem could be that the signal is not symmetric, therefore I computed the symmetric part in this way (in a 'for' loop)
x(i) = conj(x(mod(N-i+1,N)+1))
and I added it at the end of the amplitude vector.
new_amp = [amplitude x];
In this way the new amplitude vector is symmetric, but now I also doubled the dimension of that vector and this means I have to double the dimension of the frequency vector also.
Anyway, I fed the new amplitude vector to the ifft but still I don't get the logarithmic sine sweep, although this time the output is real as expected.
To compute the time [s] for the plot I used the following formula:
t = 60*3.33*log10(f/f(1))/(sweep rate)
What am I doing wrong?
Thank you in advance
If you want to create identical time domain signal from specified frequency values you should take into account lots of details. It seems to me very complicated problem and I think it need very strength background on the mathematics behind it.
But I think you may work on some details to get more acceptable result:
1- Time vector should be equally spaced based on sampling from frequency steps and maximum.
t = 0:1/fs:N/fs;
where: *N* is the length of signal in frequency domain, and *fs* is twice the
highest frequency in frequency domain.
2- You should have some sort of logarithmic phases on the frequency bins I think.
3- Your signal in frequency domain must be even to have real signal in time domain.
I hope this could help, even for someone to improve it.
Related
I want to calculate the Fourier series of a signal using FFT on matlab. And I came across the following unexpected issue. Mere example
If I define a grid and then compute the fft as:
M=59;
x= deal(1*(0:M-1)/M);
y=3*cos(2*pi*x);
Yk=fftshift(fft2(y)/(M));
which gives me the exact analytic values expected: Yk(29)=1.5; Yk(31)=1.5; zeros anything else
but if I define the grid as, and repeat the fft calculation:
x=0:1/(M-1):1;
y=3*cos(2*pi*x);
Yk=fftshift(fft2(y)/(M));
got the Yk's values completely screwed up
This is an annoying issue since I have to analyse many signals data that was sampled as in the second method so the Yk's values will be wrong. Is there a way to workaround this? an option to tell something to the fft function about the way the signal was sampled. Have no way to resample the data in the correct way.
The main reason to avoid have spectral leaking, is that I do further operations with these Fourier terms individually Real and Imag parts. And the spectral leaking is messing the final results.
The second form of sampling includes one sample too many in the period of the cosine. This causes some spectral leaking, and adds a small shift to your signal (which leads to non-zero imaginary values). If you drop the last point, you'll cosine will again be sampled correctly, and you'll get rid of both of these effects. Your FFT will have one value less, I don't know if this will affect your analyses in any way.
x = 0:1/(M-1):1;
y = 3*cos(2*pi*x);
Yk = fftshift(fft2(y(1:end-1))/(M-1));
>> max(abs(imag(Yk)))
ans =
1.837610523517500e-16
I have taken a 32Gbps NRZ signal measurement using a real time oscilloscope. I have the time and values in 2 different columns (time domain data). I have imported the 2 values to two different arrays in Matlab (NRZ_time, NRZ_values).
Now, I want to compute the FFT of the signal. I know it can be done like this.
NRZ_fft = fft(NRZ_values);
Then, I want to plot the magnitude and phase response which I am doing with
figure;
plot(abs(NRZ_fft));
figure;
plot(angle(NRZ_fft));
I am sure the magnitude response is correct but the phase response is wrong according to me. Can someone confirm, I am doing it right or not?
Also I want to find the sampling frequency from this data. There are 65521 samples. The first value in the time column is -0.0000000166801500 and the last value is 0.0000000345073500. So, the length of the signal is:
0.0000000345073500 - (-0.0000000166801500) = 5.1187e-008.
How do I calculate the sampling frequency from this data?
I am having a samll problem while converting a spectrum to a time series. I have read many article sand I htink I am applying the right procedure but I do not get the right results. Could you help to find the error?
I have a time series like:
When I compute the spectrum I do:
%number of points
nPoints=length(timeSeries);
%time interval
dt=time(2)-time(1);
%Fast Fourier transform
p=abs(fft(timeSeries))./(nPoints/2);
%power of positive frequencies
spectrum=p(1:(nPoints/2)).^2;
%frequency
dfFFT=1/tDur;
frequency=(1:nPoints)*dfFFT;
frequency=frequency(1:(nPoints)/2);
%plot spectrum
semilogy(frequency,spectrum); grid on;
xlabel('Frequency [Hz]');
ylabel('Power Spectrum [N*m]^2/[Hz]');
title('SPD load signal');
And I obtain:
I think the spectrum is well computed. However now I need to go back and obtain a time series from this spectrum and I do:
df=frequency(2)-frequency(1);
ap = sqrt(2.*spectrum*df)';
%random number form -pi to pi
epsilon=-pi + 2*pi*rand(1,length(ap));
%transform to time series
randomSeries=length(time).*real(ifft(pad(ap.*exp(epsilon.*i.*2.*pi),length(time))));
%Add the mean value
randomSeries=randomSeries+mean(timeSeries);
However, the plot looks like:
Where it is one order of magnitude lower than the original serie.
Any recommendation?
There are (at least) two things going on here. The first is that you are throwing away information, and then substituting random numbers for that information.
The FFT of a real sequence is a sequence of complex numbers consisting of a real and imaginary part. Converting those numbers to polar form gives you magnitude and phase angle. You are capturing the magnitude part with p=aps(fft(...)), but you are not capturing the phase angle (which would involve atan2(...)). You are then making up random numbers (epsilon=...) and using those to replace the original numbers when you reconstruct your time-series. Also, as the FFT of a real sequence has a particular symmetry, substituting random numbers for the phase angle destroys that symmetry, which means that the IFFT will in general no longer be a real sequence, but a sequence of complex numbers - and again, you're only looking at the real portion of the IFFT, so you're throwing away information again. If this is an audio signal, the results may sound somewhat like the original (or they may be completely different), but the waveform definitely won't match...
The second issue is that in many implementations, ifft(fft(...)) will scale the result by the number of points in the signal. There are several different ways to avoid that, with differing results, but sometimes more attractive in different scenarios, depending on what you are trying to do. You can either scale the fft() result before you do the ifft(), or scale the ifft() result at the end, or in some cases, I've even seen both being scaled by a factor of sqrt(N) - doing it twice has the end result of scaling the final result by N, but it is a bit less efficient since you do the scaling twice...
I am using the FFT function in Matlab in an attempt to analyze the output of a Travelling Wave Laser Model.
The of the model is in the time domain in the form (real, imaginary), with the idea being to apply the FFT to the complex output, to obtain phase and amplitude information in the frequency domain:
%load time_domain field data
data = load('fft_data.asc');
% Calc total energy in the time domain
N = size(data,1);
dt = data(2,1) - data (1,1);
field_td = complex (data(:,4), data(:,5));
wavelength = 1550e-9;
df = 1/N/dt;
frequency = (1:N)*df;
dl = wavelength^2/3e8/N/dt;
lambda = -(1:N)*dl +wavelength + N*dl/2;
%Calc FFT
FT = fft(field_td);
FT = fftshift(FT);
counter=1;
phase=angle(FT);
amptry=abs(FT);
unwraptry=unwrap(phase);
Following the unwrapping, a best fit was applied to the phase in the region of interest, and then subtracted from the phase itself in an attempt to remove wavelength dependence of phase in the region of interest.
for i=1:N % correct phase and produce new IFFT input
bestfit(i)=1.679*(10^10)*lambda(i)-26160;
correctedphase(i)=unwraptry(i)-bestfit(i);
ReverseFFTinput(i)= complex(amptry(i)*cos(correctedphase(i)),amptry(i)*sin(correctedphase(i)));
end
Having performed the best fit manually, I now have the Inverse FFT input as shown above.
pleasework=ifft(ReverseFFTinput);
from which I can now extract the phase and amplitude information in the time domain:
newphasetime=angle(pleasework);
newamplitude=abs(pleasework);
However, although the output for the phase is greatly different compared to the input in the time domain
the amplitude of the corrected data seems to have varied little (if at all!),
despite the scaling of the phase. Physically speaking this does not seem correct, as my understanding is that removing wavelength dependence of phase should 'compress' the pulsed input i.e shorten pulse width but heighten peak.
My main question is whether I have failed to use the inverse FFT correctly, or the forward FFT or both, or is this something like a windowing or normalization issue?
Sorry for the long winded question! And thanks in advance.
You're actually seeing two effects.
First the expected one goes. You're talking about "removing wavelength dependence of phase". If you did exactly that - zeroed out the phase completely - you would actually get a slightly compressed peak.
What you actually do is that you add a linear function to the phase. This does not compress anything; it is a well-known transformation that is equivalent to shifting the peaks in time domain. Just a textbook property of the Fourier transform.
Then goes the unintended one. You convert the spectrum obtained with fft with fftshift for better display. Thus before using ifft to convert it back you need to apply ifftshift first. As you don't, the spectrum is effectively shifted in frequency domain. This results in your time domain phase being added a linear function of time, so the difference between the adjacent points which used to be near zero is now about pi.
I'm working on a control system that measures the movement of a vibrating robot arm. Because there is some deadtime, I need to look into the future of the somewhat noisy signal.
My idea was to use the frequencies in the sampled signal and produce a fourier function that could be used for extrapolation.
My question: I already have the FFT of the signal vector (containing 60-100 values e.g.) and can see the main frequencies in the amplitude spectrum. Now I want to have a function f(t) which fits to the signal, removes some noise, and can be used to predict the near future of the signal. How do I calculate the coefficients for the sine/cosine functions out of the complex FFT data?
Thank you so much!
AFAIR FFT essentially produces output as a sum of sine functions with different frequencies. The importance of each frequency is the height of each peak. So what you really want to do here is filter out some frequencies (ie. high frequencies for the arm to move gently) and then come back to the time domain.
In matlab this should be like going through the vector of what you got from fft, setting some values to 0 (or doing something more complex to it) and then use ifft to come back to time domain and make the prediction based on what you get.
There's also one thing you should consider while doing this - Nyquist frequency - this means that the highest frequency that you get on your fft is half of the sampling frequency.
If you use an FFT for data that isn't periodic within the FFT aperture length, then you may need to use a window to reduce spurious frequencies due to "spectral leakage". Frequency estimation techniques to better estimate "between bin" frequency content may also be appropriate. The phase of each cosine sinusoid, relative to the edge of the window, is usually atan2(imag[i], real[i]). The frequency depends on the sample rate and bin number versus the length of the FFT.
You might also want to look into using a Kalman filter instead of an FFT.
Added: If your signal isn't exactly integer periodic in the FFT length, then you may want to do an fftshift before the FFT to move the resulting phase measurement reference point to the center of your data vector, instead of a possibly discontinuous circular edge.