Index synchronization - matlab

I have a one column which shows my distance and another column with corresponding time like below:
Y=[1;3;6;7.5;7;10;13] and t=[1;2;3;5;8;10;11]
In case of plotting, it would be easy just using below command:
plot(t,Y)
which gives me what I want, a vector of distance according to corresponding times but what if I want to use another function like findpeak on mix of my column not just over one column like Y.
Indeed I want to find the local peak in a vector which its time sequence in not completed. I have to interpolate missing data in Y at the corresponding time by NaN. Indeed my data should be Like below: Y=[1;3;6;NaN;7.5;NaN;NaN;7;NaN;10;13] and t=[1;2;3;4;5;6;7;8;9;10;11]. Firstly, how to do that, and secondly how could I find the peaks in Y vector with NaN.
I hope I well explained the problem.
Thanks

This is two questions (which have been answered on SO before): first question is how to interpolate within a dataset to estimate missing points. Use interp1 to interpolate missing entries:
Y=[1;3;6;NaN;7.5;NaN;NaN;7;NaN;10;13];
t=[1;2;3;4;5;6;7;8;9;10;11];
% here's where it all happens ...
ind = ~isnan(Y);
Ynew = interp1(t(ind),Y(ind),t,'cubic');
figure
plot(t,Y,'o')
hold on
plot(t,Ynew,':.')
The second question is how to find peaks. This is a more open ended question which depends on what you are looking for (are local maxima ok, what kind of thresholds are you using?). You can use findpeaks for instance:
[ypeaks ipeaks]=findpeaks(Ynew);
plot(t(ipeaks),ypeaks,'*r')

Related

finding power spectrum of signal using two approaches

I am trying to find power spectrum of the signal. The length of the signal is 100000, sample frequency is 1000Hz,and the number of points is 100000. I found the power spectrum using two approaches. The first one is by taking all the length as one part and found power spectrum for it while the second approach is by dividing the signal into 100*1000and find spectrum for each row then get the mean for all rows. My problem is that I must get the same answer in both approaches but I got different answers. I do not know what is the error in my code.
N=100000;
SF=1000;
a=0.1;
b=0.3;
amplitude1=1;
amplitude2=0.5;
t=0:1/SF:100;
f1=SF*a;
f2=SF*b;
A=amplitude1*sin(2*pi*f1*t)+amplitude2*sin(2*pi*f2*t);
Y=2*randn(1,length(A))+A;
bin=[0 :N/2];
fax_Hz=(bin*SF)/N;
FFT=fft(Y);
spectra=2/(SF*length(Y))*(FFT.*conj(FFT));
plot(fax_Hz,spectra(1,1:50001));
D=reshape(Y(1,1:100000),[100,1000]);
M=length(D(1,:));
for i=1:100
FFT_1(i,:)=fft(D(i,:));
S(i,:)=(2/(SF*M))*(FFT_1(i,:).*conj(FFT_1(i,:)));
end
S_f=mean(S);
figure
plot (S_f);
I just update the code. I do not know but when I added noise to signal the two plots looks shifted.
The main problem is with reshape you are working with each row being a separate sequence. Reshape however fills the first column before moving to the second one.
You can use the following instead.
D=reshape(A(1,1:100000),[1000,100]).';
Normalization is another problem. You can either use ifft instead of fft as it is normalized by default (not sure why). Or alternatively keep your normalization and instead of using mean you should can use sum, maybe that is due to a mistake you might have made. There still seems to be a small discrepancy in the amplitudes, not sure where that is coming from.
At the end to plot use the following:
bin=[0 :N];
fax_Hz=(bin*SF)/N;
FFT=ifft(A);
spectra=FFT.*conj(FFT);
plot(fax_Hz,spectra); hold on
D=reshape(A(1,1:100000),[1000,100]).';
M=length(D(1,:));
for i=1:100
FFT_1(i,:)=ifft(D(i,:));
S(i,:)=FFT_1(i,:).*conj(FFT_1(i,:));
end
S_f=mean(S);
plot(fax_Hz(1:100:end-1), S_f);
Note: the fax_Hz(1:100:end-1) is a hacky way of getting the length of the vectors to be the same.

Finding intersection between two functions using Matlab or Scilab

I'm doing this:
>> plot(x,y1,x,y2);
>> x=0:0.001:5;
>> y1=sin(x)+cos(1+x.^2)-1;
>> y2 = ((1/2).*x)-1;
>> find (y1==y2)
And getting this:
ans =
Empty matrix: 1-by-0
As an answer and it is simply driving me crazy! I do not know why Matlab and Scilab does not give me the answer of the intersects. I have been trying to make the intervals smaller like x = 0:0.0001:5; but it did not change anything. How can I make it return to me the intersection values?
Thank you.
You have to remember that Matlab is used to find numerical solutions to problems. You are providing a discrete set of input points x=0:0.001:5; and asking it to calculate the discrete output points y1[x] and y2[x]. This means that y1 and y2 are not continuous and don't necessarily intersect as their continuous counterparts do. I don't have Matlab so I did not run your code, but your discrete functions most likely do not interset. That is to say, there is no pair of points a = y1[x_i] and b = y2[x_i] where a = b. Instead what you most likely want to do is look for points where y2-y1 is on one side of zero at a particular input, and on the other side of zero for the next input. This would mean that the function's continuous conterparts would have crossed somewhere in between.
The case where the functions meet but don't cross is a little more tricky but the same kind of idea.
EDIT:
This sort of thing is easiest to wrap your head around with image so I created one illustrate what I mean.
Here I used many fewer points than you are trying to use, but the idea is the same. You can see that the continuous versions of y1 and y2 cross in several places, but what you're asking matlab to do is find a point in y1 that is equal to a point in y2 for identical values of x. In this image you can see that many are close, but your computer stores floating point numbers to a very high precision and so the chances of them actually being equal is very small.
When you increase the number of sample points, the image starts to look more like its' continuous counterpart.
The two existing answers explain why you can't find an exact intersection so easily. But what you really need is an answer to what to do instead to obtain precise intersections?
In your specific case, you know the analytical functions which you want to figure out the intersection of. You can use fzero with an (optionally anonymous) function to find the zero of the function defined by the difference of your two original functions:
y1fun = #(x) sin(x)+cos(1+x.^2)-1;
y2fun = #(x) ((1/2).*x)-1;
diff_fun = #(x) y1fun(x)-y2fun(x);
x0 = 1; % starting point for fzero's zero search
x_cross = fzero(diff_fun,x0);
Now, this will give you one zero of the difference function, i.e. one intersection of your functions. It turns out that finding every zero of a function is a challenging task. Generally you have to call fzero multiple times with various starting points x0. If you suspect what your functions look like, this is not hopeless at all.
So what happens if your functions are more messy? In the general case, you can use an interpolating function to play the part of y1fun and y2fun in the example above, for instance by using interp1:
% generate data
xdata = 0:0.001:5;
y1data = sin(xdata)+cos(1+xdata.^2)-1;
y2data = ((1/2).*xdata)-1;
y1fun = #(x) interp1(xdata,y1data,x);
y2fun = #(x) interp1(xdata,y2data,x);
x0 = 1; % starting point for fzero's zero search
x_cross = fzero(#(x)y1fun(x)-y2fun(x),x0);
which leads back to the original problem. Note that interp1 by default uses linear interpolation, depending on what your function looks like and how your data are scatted you can choose other options. Also note the option for extrapolation (to be avoided).
So in both cases, you get one crossing for each call to fzero. By choosing the starting points carefully, you should be able to find all the zeros, as exactly as possible.
Maybe the two vectors do not have exactly equal values anywhere. You could try to search for a smallest difference:
abs(y1-y2)<tolerance
where tolerance=0.001 is a small number

spdiags and features scaling

According to libsvm faqs, the following one-line code scale each feature to the range of [0,1] in Matlab
(data - repmat(min(data,[],1),size(data,1),1))*spdiags(1./(max(data,[],1)-min(data,[],1))',0,size(data,2),size(data,2))
so I'm using this code:
v_feature_trainN=(v_feature_train - repmat(mini,size(v_feature_train,1),1))*spdiags(1./(maxi-mini)',0,size(v_feature_train,2),size(v_feature_train,2));
v_feature_testN=(v_feature_test - repmat(mini,size(v_feature_test,1),1))*spdiags(1./(maxi-mini)',0,size(v_feature_test,2),size(v_feature_test,2));
where I use the first one to train the classifier and the second one to classify...
In my humble opinion scaling should be performed by:
i.e.:
v_feature_trainN2=(v_feature_train -min(v_feature_train(:)))./(max(v_feature_train(:))-min((v_feature_train(:))));
v_feature_test_N2=(v_feature_test -min(v_feature_train(:)))./(max(v_feature_train(:))-min((v_feature_train(:))));
Now I compared the classification results using these two scaling methods and the first one outperforms the second one.
The question are:
1) What exactly does the first method? I didn't understand it.
2) Why the code suggested by libsvm outperforms the second one (e.g. 80% vs 60%)?
Thank you so much in advance
First of all:
The code described in the libsvm does something different than your code:
It maps every column independently onto the interval [0,1].
Your code however uses the global min and max to map all the columns using the same affine transformation instead of a separate transformation for each column.
The first code works in the following way:
(data - repmat(min(data,[],1),size(data,1),1))
This subtracts each column's minimum from the entire column. It does this by computing the row vector of minima min(data,[],1) which is then replicated to build a matrix the same size as data. Then it is subtracted from data.
spdiags(1./(max(data,[],1)-min(data,[],1))',0,size(data,2),size(data,2))
This generates a diagonal matrix. The entry (i,i) of this matrix is 1 divided by the difference of the maximum and the minimum of the ith column: max(data(:,i))-min(data(:,i)).
The right multiplication of this diagonal matrix means: Multiply each column of the left matrix with the corresponding diagonal entry. This effectively divides column i by max(data(:,i))-min(data(:,i)).
Instead of using a sparse diagonal matrix, you could do this even more efficiently with bsxfun:
bsxfun(#rdivide, ...
bsxfun(#minus, ...
data, min(data,[],1)), ...
max(data,[],1)-min(data,[],1))
Which is the matlab way of writing:
Divide:
The difference of:
each column and its respective minimum
by the difference of each column's max and min.
I know this has already been answered correctly, but I would like to present another solution that I think is also correct and I found more intuitive/shorther then the one presented by knedlsepp. I am new to matlab and as I was studying knedlsepp solution, I found it more intuitive to solve this problem with the following formula:
function [ output ] = feature_scaling( y)
output = (y - repmat(min(y),size(y,1),1)) * diag(1./(max(y) - min(y)));
end
I find it a bit easier to use diag this way instead of spdiags, but I believe it produces the same result for the purpose of this excercise.
Multiplying the first term by the second, effectively divides each member of the matrix (Y-min(Y)) by the scalar value 1/(max(y)-min(y)), achieving the desired result.
In case someone prefers a shorter version, maybe this can be of help.

How to remove the outliers located outside the predication bound in Matlab?

Hey guys I have one question related to processing of Time series, I have xy data and want to remove the outliers, so i defined it by ones that located outside the the prediction bound, I applied the regress functions [B, Bint, R, Rint, stats] = regress(y, x);but iam confused how to remove that ones?
any help??
Straight from the docs
[b,bint,r,rint] = regress(y,X) returns an n-by-2 matrix rint of
intervals that can be used to diagnose outliers. If the interval
rint(i,:) for observation i does not contain zero, the corresponding
residual is larger than expected in 95% of new observations,
suggesting an outlier.
Therefore, to find the location of outliers in your data, it should be just:
n = rint(:,1)>0|rint(:,2)<0;
Then you can either remove them, plot them in a different colour, or whatever.

Matlab get an average plot out of several plot

I'm just getting started with matlab and I'm trying to plot some graph with it.
The problem is I don't know how to get the average data out of 10 plot().
Can anyone guide me for it? Thank you :)
Assuming you don't have access to the original data you used for doing the plots:
plot_data = get(get(gca,'Children'),'YData'); % cell array of all "y" data of plots
average = mean(cell2mat(plot_data));
In order for this to work, you have to use this code right after doing the plots, that is, without plotting to any other figure (gca is a handle to the current axes).
Assume your data is stored row-wise in a m x n matrix A, with n columns corresponding to different values of the continuous error, and m rows corresponding to different curves. Then to inspect the mean over the curves just use
Amean = mean(A,1);
plot(Amean)
Please take a look at this link: it solve my problem getting the average plot.
https://www.mathworks.com/matlabcentral/fileexchange/27134-plot-average-line
After downloading the files just put those script on your working folder and add this line to your script.
plotAverage(gca,[],'userobustmean',0)