Frequency from fft data set matlab [duplicate] - matlab

This question already has answers here:
How do I obtain the frequencies of each value in an FFT?
(5 answers)
Closed 6 years ago.
I have a data set in a matrix in matlab. It contains 25,000 values taken every 0.5 ns; so the total time of the dataset is 1.25E-5 seconds.
The data set contains very high frequency noise that I am not interested in so I create another matrix is every 50th data point from the first matrix So the size of the matrix is 1000*.
I plot the absolute values from matlab's fft this matrix (I also normalise the amplitude and only plot the first half) and get the attached (two plots, second is a close up of the low frequencies I am interested in). How do I convert the x-axis to frequency?
Another point, if I take every data point (so I create an fft of the entire 25,000 points) then the x-axis is exactly the same; in other words, the size of my matrix seems to have no bearing on the x-axis returned by matlab. I've attached two links to the frequency spectrum, one of which is a close-up of the low frequencies I am interested in. It's axis goes from 0-50, so it is these values I need to convert to Hz.
Thankyou in advance!
Close up of frequency spectrum
frequency spectrum

From what I read on http://www.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html#bresqop-1, it appears that the units on the x-axis of the plotted FFT are Hz if the first vector, f, you put into the plot(f,power), is defined as a sequence of n elements (n being the number of data points put into the FFT) increasing from zero to the sample frequency.
Thus, for the first plot, which used every 50th of points that were taken at a frequency of 2 GHz, the sample frequency would be 40 MHz. Thus, f = (0:n-1)*4*10^7/(25000/50)
It goes on to show how to use the fftshift function to put the center of the output of the fft function at 0, but it's clear you already did that and chopped off the negative part.
So, once you have the right separation of fs/n, sampling frequency divided by number of data points used, in the vector that supplies the x-axis to the plot function, then the units of the x-axis will be Hz.
(I hope you still have the numbers to graph again? If not, this question might help: Confusion in figuring out the relation between actual frequency values and FFT plot indexes in MATLAB)

Related

Why is the number of sample frequencies in `scipy.signal.stft()` tied to the hop size?

This question relates to SciPy's Short-time Fourier Transform function for signal processing.
For some reason I don't understand, the size of the output 'array of sample frequencies' is exactly equal to the hop size. From the documentation:
nperseg : int, optional
Length of each segment. Defaults to 256.
noverlap : int, optional
Number of points to overlap between segments. If None, noverlap = nperseg // 2. Defaults to None. When specified, the COLA constraint must be met (see Notes below).
f : ndarray
Array of sample frequencies.
hop size H = nperseg - noverlap
I'm new to signal processing and Fourier transforms, but as far as I understand a STFT is just chopping an audio file into segments ('time frames') on which you perform a Fourier transform. So if I want to do a STFT on 100 time frames, I'd expect the output to be a matrix of size 100 x F, where F is an array of measured frequencies ('measured' probably isn't the right word here but you know what I mean).
This is kinda what SciPy's implementation does, but the size of f here is what bothers me. It's supposed to be an array describing the different frequencies, like [0Hz 500Hz 1000Hz], and it does, but for some reasons its size exactly the same as the hop size. If the hop size is 700, the number of measured frequencies is 700.
The hop size is the number of samples (i.e. time) between each time frame, and is correctly calculated as H = nperseg - noverlap, but what does this have to do with the frequency array?
Edit: Related to this question
An FFT is an square matrix transform from one orthogonal basis to another of the same dimension. This is because N is the exact number of orthogonal (e.g. that don't interfere with one another) complex sinusoids that fit in a time domain vector of length N.
A longer time vector can contain more frequency information (e.g. it's hard to tell 2 frequencies apart using just 3 sample points, but much easier with 3000 samples, etc.)
You can zero-pad your short time vector of length N to use a longer FFT, but that is identical to interpolating a nice curve between N frequency points, which makes all the FFT results interdependent.
For many purposes (visualization, etc.) an STFT is overlapped, where the adjacent segments share some overlapped data instead of just being end-to-end. This gives better time locality (e.g. the segments can be spaced closer but still be long enough so that each one can provide the frequency resolution required).

If we take STFT of a single sinusoid, and plot the value corresponding to carrier frequency in real imaginary plane, how many points should it be?

I created a sinusoid with frequency 550Hz that goes for 1 second
fs=44100;
Duration=1; %second
Len=Duration * fs; %length of sinusoid
t=(0:Len-1)/fs;
x=sin(2*pi*550*t);
for the purpose of exploring and learning, I have decided to take the short time Fourier transform of this signal. I did it as below:
window_len=0.02*fs; %length of the window
hop=window_len/3; %hop size
nfft=2^nextpow2(window_len);
window=hamming(window_len,'periodic');
[S,f,t]=spectrogram(x,window,hop,nfft,fs);
Now I want to plot the real versus imaginary value of S for the frequency equal to 550 and see what happens. First of all, in the frequency vector I didn’t have the exact 550. There was one 516.5 and 559.6. So, I just looked at the spectrogram and chose whichever that was close to it and picked that. When I tried to plot real vs imaginary of S for the frequency I chose (over all time frames), the values all fall in 3 points as it shows in the attached plot. Why three points?
Each STFT window can have a different complex phase depending on how the start (or middle) of the window is synchronized (or not) with the sinusoids period. So the real-complex IQ plot for the peak magnitude DFT result bin can be a circular scatter plot, depending on the number of DFT windows and the ratio between the stepping distance (or length - overlap) and the period of the sinusoid.
The phase of the STFT coefficients for the different windows depends on which data exactly the window "sees". So for your particular choice of window length and hop, it so happens that as you slide through your single-frequency sinusoid, there only three different data chunks that you window "sees". To see what I mean, just plot:
plot(x(1:window_len),'x')
plot(x(1+hop:window_len+hop),'x')
plot(x(1+2*hop:window_len+2*hop),'x')
plot(x(1+3*hop:window_len+3*hop),'x')
.. and if you continue you will see that the pattern repeats itself, i.e., the first plot for instance is the same as the fourth, the second as the fifth etc. Therefore you only have three different real-imaginary part combinations.
Of course, this will change if you change the window length and the hopsize, and you will get more points. For instance, try
window_len =nfft;
hop=ceil(window_len/4)
I hope that helps.

How do i get all the numbers of fft bins in a defined frequency band?

I use the matlab software. To my question.
I have a audio signal, on which i am applying a STFT. I take a segment
(46 ms, specifially chosen) out of my signal y(audio signal) and use a FFT on it. Then i go to the next segment, until to end of my audio signal.
My WAV-File is 10.8526 seconds long. If I have a sample frequency of
44100Hz, this means my y is 10.8526*fs = 478599.66 which is
shown in the workspace as 478 6000 x2 double.
The length of my fft is 2048. My signal are differentiated under lower frequency band [0 300], mfb [301 5000] and hfb [5001 22050(fs/2)].
The bands are just an example and not the actual matlab code. Basicall what i want (or what I am trying to do), is to get the values of my bins in the defined frequency band and do a arithmetic mean on it.
I chose 46 ms because, I want it as long as the fft length, or nearly as long as the fft. (It is not exact).Afterwards, I want to try plotting it, but that is not important right now. Any help is appreciated.
Fourier transform of a signal in time domain in a vector of size n will return another vector of size n of same signal but in frequency domain.
Frequency domain will be from 0 (dc offset) to your sampling frequency. But you will only be able to use half of that. Second half would have same values but mirrored.
You can obtain the center frequency of each useful bin with:
f = Fs*(0:(n/2))/n;

Resample signal at specific time lags

I have a 10x1100 matrix, which represents the coefficients of a scalogram for a signal of 1.1sec duration at 1kHz sampling rate. The scalogram has 10 frequencies, so basically the rows of the matrix are the frequency bins and the columns are the time points.
And then I want to resample that matrix to form a 10x10 matrix. To be more specific, what I want to do is the following (part of a paper I'm working on):
"The scalogram was then resampled at 10 time lags (t−100ms, t−200ms,...,and t−1s) to form a 10×10 scalogram matrix of time t."
So, how exactly should I make that resampling? I am aware of the Matlab functions downsample, resample, decimate, but I am not sure about the way I should resample that matrix. Should I just take every 100th element of my initial matrix or should I use the decimate function which also filters the signal? And if not the first case, how can I make Matlab resample at those specific 10 time lags?

FFT when data set has varying vector lengths

I have data from a model I am running. However the data is collected at each time step and there are varying numbers of time steps. It works out that although there are varying time steps, it is compensated by the change in time step so that all runs are running for the same time.
However I would think that when I have a vector that is 200 in length and one that is 900 in length, taking the FFT will give me inherently different frequencies. I feel like I should take the FFT with respect to the same time axis of all the samples.
The way I have the data now is just as row vectors were each entry is not associated with a space in time.
Is there a way to take the fft of each vector with respect to their place in a time axis rather than their place in the vector array?
My goal is to write a for loop and take the fft of many data sets, and then plot them to compare of frequency signatures change.
If you collect 200 samples in 1 second (200 Hz), you can resolve input data from 1 Hz (1/(1 sec)) to 100 Hz. If you sample for 1 second collecting 900 samples, you can resolve input from 1 Hz to 450 Hz. So both your samples have the same spacing (sampling in the frequency axis is 1 Hz), but they go up to different maximum frequencies!
If your issue is just about plotting, you can either throw away the high frequencies which are not available in all your plots:
totaltime=1; %# common total time of all datasets, in seconds
minsamplenumber=200;
figure;
hold all;
cutofffreq=((minsamplenumber/2+1)/totaltime);
freqscale=0:(1/totaltime):cutofffreq;
datasetcount=42;
ffts=NaN(minsamplenumber,datasetcount);
for i=1:datasetcount
data{i}=... %# collect your data; to make life easier always collect an even number..
ffts(:,i)=fft(data{i},minsamplenumber);
plot(freqscale,ffts{i}(1:end/2+1));
end
... or live with reality, and plot all data you have:
totaltime=1; %# common total time of all datasets, in seconds
figure;
hold all;
for i=1:42
data{i}=... %# collect your data; to make life easier always collect an even number..
ffts{i}=fft(data{i});
maxfreq(i)=((numel(ffts{i})/2+1)/totaltime);
freqscale{i}=0:(1/totaltime):maxfreq(i);
plot(freqscale{i},ffts{i}(1:end/2+1));
end
You could resample your data (by filtered interpolation) into constant length vectors where the sample rate was the same constant rate in each frame. You may have to overlap your FFT frames as well to get constant frame or window offsets.