Axis scale and labeling in MATLAB plot [duplicate] - matlab

This question already has answers here:
matlab multiple x axis one below another
(3 answers)
Closed 7 years ago.
I've an FFT plot with negative and positive frequencies on X axis. I have a peak at Synchronous Frequency say 1X (1 times of fundamental frequency) and another peak sub synchronous frequency 0.30X (0.30 times of fundamental frequency). Now I want both the scaling to be labeled on the axis. I used the following code.
%for setting 1X frequency ( Synchronous frequency)
set(gca,'XTick',-5000:2500:5000)
set(gca,'XTickLabel',{'-2X','-1X','0','1X','-2X'})
%for setting 0.30X ( Sub harmonic frequency)
set(gca,'XTick',-700:700:700)
set(gca,'XTickLabel',{'-0.3X','0','0.3X'})
But I see only the second scaling where as the first is not being plotted. Is there any other way to plot this with 2 absolute values. Please find reference image. Thanks in advance.
As you can notice in the figure. I've been able to label the first set of frequencies (1X,1 1/2X, etc). Now I also want the second set(-30X , 0.30X etc) as I indicated with arrow arrow.

i am not sure what are you looking for but maybe this will work for you
c=[-3:3 -3:0.3:3]; % spacing of 1 and 0.3
c=c.*2500; % 2500 is fundamental frequency
c=unique(sort(c));
for i=1:length(c)
str1{i}=[num2str(c(i)/2500,'%.1f'),'X'];
end
plot(1,1,'+'); % random
hold on;
set(gca,'XTick',c,'XTickLabel',str1);
xlim([min(c) max(c)]);

Maybe I'm missing something or have misunderstood your question, but why don't you lump it into one command? As mentioned in the comments, the last set of commands overwrite the first one.
set(gca,'XTick',[-5000 -2500 -700 0 700 2500 5000])
set(gca,'XTickLabel',{'-2X','-1X','-0.3X','0','0.3X','1X','-2X'})

Related

'resample' to have the same size of signals

i have 4 (2 Rates and 2 Times) signals and i need to equalize their sizes. I cut them first off, because i need that too. Size of first time and rate signal is 3901, another 830. But not just to remove elements, i want to keep the curve. I thought i need interpolation and tried "resample" but it is not perfect. Looks like photo. How should i improve my codes? Any idea?
index=time >= 9.6 & tsyn <= 13.5; %time boundaries of first time signal
time1=tsyn(index); %first time signal
time_f=resample(time1,830,3901);
Rate1=CLU_YR1(index) %first rate signal
Rate_f=resample(Rate1,830,3901);
index2 = cm.Time.data >= 26.3 & cm.Time.data <= 30.45; %time boundaries of second time signal
time2=cm.Time.data(index2) %second time signal
Rat2=cm.BodySensor_SC1_Omega_B_z.data*(-180/pi) %second rate signal
Rate_p=Rat2(index2)
I suppose some of the misfit of your curves originates from the fact that the original sequence is not (close to) 0 at the end of the vector. From the matlab resample documentation:
When filtering, resample assumes that the input sequence, x, is zero before and after the samples it is given. Large deviations from zero at the endpoints of x can result in unexpected values for y.
What the best alternative is depends on what it is you want to do next. If you want to have a new, upsampled version (i.e. both signals of length 3901), you could look at interp1, which supports several different methods. If you choose to do this, keep in mind that the values in y(t) will be interpolated according to the values of t you provide. Since your time arrays do not seem to be aligned (one is between 9.6 and 13 sec, the other between 26 and 30), you are probably best off doing something along the lines of:
y_new = interp1( linspace(1,100,830), rate_p, linspace(1,100,3901), 'linear');
and the same for the time array.

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.

Any good ways to obtain zero local means in audio signals?

I have asked this question on DSP.SE before, but my question has got no attention. Maybe it was not so related to signal processing.
I needed to divide a discrete audio signal into segments to have some statistical processing and analysis on them. Therefore, segments with fixed local mean would be very helpful for my case. Length of segments are predefined, e.g. 512 samples.
I have tried several things. I do use reshape() function to divide audio signal into segments, and then calculate means of every segment as:
L = 512; % Length of segment
N = floor(length(audio(:,1))/L); % Number of segments
seg = reshape(audio(1:N*L,1), L, N); % Reshape into LxN sized matrix
x = mean(seg); % Calculate mean of each column
Subtracting x(k) from each seg(:,k) would make each local mean zero, yet it would distort audio signal a lot when segments are joined back.
So, since mean of hanning window is almost 0.5, substracting 2*x(k)*hann(L) from each seg(:,k) was the first thing I tried. But this time multiplying by 2 (to make the mean of hanning window be almost equal to 1) distorted the neighborhood of midpoints in each segments itself.
Then, I have used convolution by a smaller hanning window instead of multiplying directly, and subtracting these (as shown in figure below) from each seg(:,k).
This last step gives better results, yet it is still not very useful when segments are smaller. I have seen many amazing approaches here on this site for different problems. So I just wonder if there is any clever ways or existing methods to obtain zero local means which distorts an audio signal less. I read that, this property is useful in some decompositions such as EMD. So maybe I need such decompositions?
You can try to use a moving average filter:
x = cumsum(rand(15*512, 1)-0.5); % generate a random input signal
mean_filter = 1/512 * ones(1, 512); % generate a mean filter
mean = filtfilt(mean_filter, 1, x); % filtfilt is used instead of filter to obtain a symmetric moving average.
% plot the result
figure
subplot(2,1,1)
plot(x);
hold on
plot(mean);
subplot(2,1,2)
plot(x - mean);
You can tune the filter by changing the interval of the mean filter. Using a smaller interval, results in lower means inside each interval, but filters also more low frequencies out of your signal.

Frequency from fft data set matlab [duplicate]

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)

Matlab sin wave plotting

I am newbie on matlab sorry if the question is so silly. I search about it but I could not understand the issue clearly.
I want to work with interval int=(-20:20) which has 41 element on sin wave.
when I plot sin(int) it is ploting well but when I try to plot sin(50*int) evenif there must be a lot of change of y value than sin(int) there is not. When I change int=(-100:100) has 201 element, still same wrong plotting. I only take real plot when I change int=(-10:0.1:10) has again 201 element
What is the reason behind?
What you're describing is a signal processing problem called aliasing.
Basically, if you don't sample a sine wave often enough, the discretized sine wave can appear to have a lower frequency than the actual continuous wave did:
To fix this problem you must sample at least twice as often as the frequency of the signal. (See the sampling theorem.)
sin(x) has a frequency of 1 rad/s so you must sample at least as often as 2 rad/s = 0.318 Hz, or about 1 sample for every 3 units.
int=(-20:20) satisfies this requirement with a sampling rate of 1 Hz = 6.28 rad/s > 2 rad/s.
50*int, or -1000:50:1000 does not, as it has a sampling rate of 1/50 Hz = 0.1257 rad/s < 2 rads/s.
You are looking at something called "aliasing". sin is a periodic function with a period of 2*pi (because it's in radian, not in degrees). In some of your plots your "x-values" (which you don't really plot, which is not so good) are further apart than half a period.
Take a look at the following plots:
figure;
hold all;
plot(int2, sin(int2), 'o-');
plot(int1, sin(int1), 'o-');
figure;
hold all;
plot(50*int2, sin(50*int2), 'o-');
plot(50*int1, sin(50*int1), 'o-');
You'll see that in both figures, the points of int2 coincide with points of int1. In the second plot, however, linear interpolation between the few points of int1 paints a sine-wave that is not really there.