use specgram in axes in GUI matlab - matlab

I create a matlab gui and have some element in it with some axes. I plot one of my desire plot in ploter1 ( first axes ) using
plot(handles.ploter1,xx); title(handles.ploter1,'Waveform');
and it is ok,but I want use specgram and plot specgram result in another axes by I dont know how can do it :(
I test
specgram(wav,N,fs,hamming(N/4),round(0.9*N/4));xlabel('time, s');
or
specgram(handles.ploter2,wav,N,fs,hamming(N/4),round(0.9*N/4));xlabel('time, s');
but return me error or nothing !!!
please help me. thank you very much

EDIT
as mentioned in the comments by bdecaf, what should work, is to set the current axes:
axes(handles.ploter2);
now, when using just
spectrogram(x,window,noverlap,F)]
the plot should be on the specified axes. If not, try:
hold on
before!
OLD
specgram or spectogram does not have a parameter for the plot. You have to define it later on.
I suggest to get the result first by:
[S,F,T]=spectrogram(x,window,noverlap,F)]
and then plot it on a specific axes:
plot(handles.ploter2, S,F)
But I am not sure about which parameter you want to plot. Please take a look at the docs.
From the docs:
[S,F,T] = spectrogram(...) returns a vector of frequencies, F, and a vector of times, T, at which the spectrogram is computed. F has length equal to the number of rows of S. T has length k (defined above) and the values in T correspond to the center of each segment.
[S,F,T] = spectrogram(x,window,noverlap,F) uses a vector F of frequencies in Hz. F must be a vector with at least two elements. This case computes the spectrogram at the frequencies in F using the Goertzel algorithm. The specified frequencies are rounded to the nearest DFT bin commensurate with the signal's resolution. In all other syntax cases where nfft or a default for nfft is used, the short-time Fourier transform is used. The F vector returned is a vector of the rounded frequencies. T is a vector of times at which the spectrogram is computed. The length of F is equal to the number of rows of S. The length of T is equal to k, as defined above and each value corresponds to the center of each segment.
[S,F,T] = spectrogram(x,window,noverlap,F,fs) uses a vector F of frequencies in Hz as above and uses the fs sampling frequency in Hz. If fs is specified as empty [], it defaults to 1 Hz.

Related

Matlab ksdensity for bivariate data with more evaluation points

I'm running Matlab code for kernel density, i.e., [f,xi] = ksdensity(x), where x is a two column bivariate data. The resulting output f is the density vector, while xi is the meshgrid of evaluation points that is 30x30 in dimension. See the documentation here: Link.
I'm trying to increase number of evaluation points that I receive from this code. There is an option mentioned in the documentation called 'NumPoints' that is only applicable for univariate data. Is there an option or ways that I can increase the meshgrid points of evaluation points of bivariate data to, say, 100x100?
You need to use the optional second input argument pts to specify the range and number of the output points in your grid. See this example in the documentation. Depending on your input data, you could specify something like this:
pts = [linspace(min(x(:,1)),max(x(:,1)),1000).' linspace(min(x(:,2)),max(x(:,2)),1000).'];
The NumPoints is npoints in the ksdensity(). e.g., [f,xi] = ksdensity(x, 'npoints', 1000) will return 1000 points of xi and f.

Fourier Analysis - MATLAB

Good evening guys,
I wanna ask you a question regarding the analysis of a function in the domain of frequencies (Fourier). I have two vectors: one containing 7700 values for pressure, and the other one containing 7700 values (same number) for time.
For example, I call the firt vector "a" and the second one "b". With the command "figure(1),plot(a,b)" I obtain the curve in the domain of time.
How can I do to plot this curve in the domain of frequency, to make Fourier transform?
I've read about the function "fft", but I've not understood very well how it can be used...can anyone help me?
Thanks in advance for your attention!
fft returns spectrum as complex numbers. In order to analyze it you have to use its absolute value or phase. In general, it should look like this (let's assume that t is vector containing time and y is the one with actual signal, N is the number of samples):
fY = fft(y) / (N/2) % scale it to amplitude, typically by N/2
amp_fY = abs(fY)
phs_fY = angle(fY)
Additionally, it would be nice to have FFT with known frequency resolution. For that, you need sampling period/frequency. Let's call that frequency fs:
fs = 1/(t(1) - t(0))
and the vector of frequencies for FFT (F)
should be:
F = (0:fs/N:(N-1)*fs/N)
and finally plots:
plot(F, amp_fY)
% or plot(F, phs_fy) according to what you need
I you can use stem instead of plot to get some other type of chart.
Note that the DC component (the average value) will be doubled on the plot.
Hope it helps

Sampling at exactly Nyquist rate in Matlab

Today I have stumbled upon a strange outcome in matlab. Lets say I have a sine wave such that
f = 1;
Fs = 2*f;
t = linspace(0,1,Fs);
x = sin(2*pi*f*t);
plot(x)
and the outcome is in the figure.
when I set,
f = 100
outcome is in the figure below,
What is the exact reason of this? It is the Nyquist sampling theorem, thus it should have generated the sine properly. Of course when I take Fs >> f I get better results and a very good sine shape. My explenation to myself is that Matlab was having hardtime with floating numbers but I am not so sure if this is true at all. Anyone have any suggestions?
In the first case you only generate 2 samples (the third input of linspace is number of samples), so it's hard to see anything.
In the second case you generate 200 samples from time 0 to 1 (including those two values). So the sampling period is 1/199, and the sampling frequency is 199, which is slightly below the Nyquist rate. So there is aliasing: you see the original signal of frequency 100 plus its alias at frequency 99.
In other words: the following code reproduces your second figure:
t = linspace(0,1,200);
x = .5*sin(2*pi*99*t) -.5*sin(2*pi*100*t);
plot(x)
The .5 and -.5 above stem from the fact that a sine wave can be decomposed as the sum of two spectral deltas at positive and negative frequencies, and the coefficients of those deltas have opposite signs.
The sum of those two sinusoids is equivalent to amplitude modulation, namely a sine of frequency 99.5 modulated by a sine of frequency 1/2. Since time spans from 0 to 1, the modulator signal (whose frequency is 1/2) only completes half a period. That's what you see in your second figure.
To avoid aliasing you need to increase sample rate above the Nyquist rate. Then, to recover the original signal from its samples you can use an ideal low pass filter with cutoff frequency Fs/2. In your case, however, since you are sampling below the Nyquist rate, you would not recover the signal at frequency 100, but rather its alias at frequency 99.
Had you sampled above the Nyquist rate, for example Fs = 201, the orignal signal could ideally be recovered from the samples.† But that would require an almost ideal low pass filter, with a very sharp transition between passband and stopband. Namely, the alias would now be at frequency 101 and should be rejected, whereas the desired signal would be at frequency 100 and should be passed.
To relax the filter requirements you need can sample well above the Nyquist rate. That way the aliases are further appart from the signal and the filter has an easier job separating signal from aliases.
† That doesn't mean the graph looks like your original signal (see SergV's answer); it only means that after ideal lowpass filtering it will.
Your problem is not related to the Nyquist theorem and aliasing. It is simple problem of graphic representation. You can change your code that frequency of sine will be lower Nyquist limit, but graph will be as strange as before:
t = linspace(0,1,Fs+2);
plot(sin(2*pi*f*t));
Result:
To explain problem I modify your code:
Fs=100;
f=12; %f << Fs
t=0:1/Fs:0.5; % step =1/Fs
t1=0:1/(10*Fs):0.5; % step=1/(10*Fs) for precise graphic representation
subplot (2, 1, 1);
plot(t,sin(2*pi*f*t),"-b",t,sin(2*pi*f*t),"*r");
subplot (2, 1, 2);
plot(t1,sin(2*pi*f*t1),"g",t,sin(2*pi*f*t),"r*");
See result:
Red star - values of sin(2*pi*f) with sampling rate of Fs.
Blue line - lines which connect red stars. It is usual data representation of function plot() - line interpolation between data points
Green curve - sin(2*pi*f)
Your eyes and brain can easily understand that these graphs represent the sine
Change frequency to more high:
f=48; % 2*f < Fs !!!
See on blue lines and red stars. Your eyes and brain do not understand now that these graphs represent the same sine. But your "red stars" are actually valid value of sine. See on bottom graph.
Finally, there is the same graphics for sine with frequency f=50 (2*f = Fs):
P.S.
Nyquist-Shannon sampling theorem states for your case that if:
f < 2*Fs
You have infinite number of samples (red stars on our plots)
then you can reproduce values of function in any time (green curve on our plots). You must use sinc interpolation to do it.
copied from Matlab Help:
linspace
Generate linearly spaced vectors
Syntax
y = linspace(a,b)
y = linspace(a,b,n)
Description
The linspace function generates linearly spaced vectors. It is similar to the colon operator ":", but gives direct control over the number of points.
y = linspace(a,b) generates a row vector y of 100 points linearly spaced between and including a and b.
y = linspace(a,b,n) generates a row vector y of n points linearly spaced between and including a and b. For n < 2, linspace returns b.
Examples
Create a vector of 100 linearly spaced numbers from 1 to 500:
A = linspace(1,500);
Create a vector of 12 linearly spaced numbers from 1 to 36:
A = linspace(1,36,12);
linspace is not apparent for Nyquist interval, so you can use the common form:
t = 0:Ts:1;
or
t = 0:1/Fs:1;
and change the Fs values.
The first Figure is due to the approximation of '0': sin(0) and sin(2*pi). We can notice the range is in 10^(-16) level.
I wrote the function reconstruct_FFT that can recover critically sampled data even for short observation intervals if the input sequence of samples is periodic. It performs lowpass filtering in the frequency domain.

Radially Power Spectrum Analysis

First - I need to plot this radially averaged spectrum 1-D, against the wavenumber |k|. But early I calculate the |k| using two matrix, so I have a matrix that represent |k|. So I have to radial average this matrix too?
Second - If I remove a mean value from my data before using the FFT2 function, I expected to see only a difference in the amplitude of the values, but actually I am noting a difference in the shape of the radially averaged spectrum.
I am trying to use this to analyse magnetic field data.
Thanks for any help!!
The explanation for your second question follows from the additive property of the FFT:
FFT(c) = FFT(a+b) = FFT(a) + FFT(b)
If b is an offset - namely the mean value - which you remove from signal c, then the spectrum of c-b will equal your original spectrum minus the spectrum of a constant, b, but the FFT of a constant results in sinc wiggles! So by removing the mean value of the signal you are removing a sinc glitch at zero frequency.

Can I adjust spectogram frequency axes?

The MATLAB documentation examples for the spectrogram function gives examples that have the frequency axis set to [0 500]. Can I change this to something like [0 100]? Obviously running the axis command will do this for me, but that adjusts the end result and "blows up" the resultant plot, make it pixelated. I am basically looking to build a spectrogram that only looks for frequencies between 0-100, not rescaling after building the spectrogram.
Here's an example from that documentation:
T = 0:0.001:2;
X = chirp(T,0,1,150);
spectrogram(X,256,250,256,1E3,'yaxis');
This produces the following:
Everything below 350Hz is unneeded. Is there a way to not include everything between 350 to 500 when building the spectrogram, rather than adjusting axes after the fact?
From the documentation:
[S,F,T] = spectrogram(x,window,noverlap,F) uses a vector F of frequencies in Hz. F must be a vector with at least two elements. This case computes the spectrogram at the frequencies in F using the Goertzel algorithm. The specified frequencies are rounded to the nearest DFT bin commensurate with the signal's resolution. In all other syntax cases where nfft or a default for nfft is used, the short-time Fourier transform is used. The F vector returned is a vector of the rounded frequencies. T is a vector of times at which the spectrogram is computed. The length of F is equal to the number of rows of S. The length of T is equal to k, as defined above and each value corresponds to the center of each segment.
Does that help you?
The FFT is so fast that it is better to increase the resolution and then just discard the unwanted data. If you need better spectral resolution (more frequency bins) then increase the FFT size. To get smoother looking spectrum in time dimension, increase the noverlap value to reduce the increments for each consequtive FFT. In this case you would not specify the F. If FFT size is 1024 then you get 1024/2+1 frequency bins.
FFTN = 512;
start = 512*(350/500); % Only care about freq bins above this value
WIN_SIZE = FFTN;
overlap = floor(FFTN*0.8);
[~,F,T,P] = spectrogram(y, WIN_SIZE, overlap, FFTN);
f = 0:(length(F)-1);
f = f*((Fs/2)/length(F));
P = P(start:512,:);
f = f(1,start:512);
imagesc(T,f,10*log10(P),[-70 20]);