Interpolation with matlab - matlab

I have a vector with different values.
Some of the values are zeros and sometimes they even come one after another.
I need to plot this vector against another vector with the same size but I can't have zeros in it.
What is the best way I can do some kind of interpolation to my vector and how do I do it?
I tried to read about interpolation in mat-lab but I didn't understand good enough to implement it.
If it's possible to explain it to me step by step I will be grateful since I'm new with this program.
Thanks

Starting from a dataset consisting of two equal length vectors x,y, where y values equal to zero are to be excluded, first pick the subset excluding zeros:
incld = y~=0;
Then you interpolate over that subset:
yn = interp1(x(incld),y(incld),x);
Example result, plotting x against y (green) and x against yn (red):
edit
Notice that, by the definition of interpolation, if terminal points are zero, you will have to take care of that separately, for instance by running the following before the lines above:
if y(1)==0, y(1) = y(find(y~=0,1,'first'))/2; end
if y(end)==0, y(end) = y(find(y~=0,1,'last'))/2; end
edit #2
And this is the 2D version of the above, where arrays X and Y are coordinates corresponding to the entries in 2D array Z:
[nr nc]=size(Z);
[X Y] = meshgrid([1:nc],[1:nr]);
X2 = X;
Y2 = Y;
Z2 = Z;
excld = Z==0;
X2(excld) = [];
Y2(excld) = [];
Z2(excld) = [];
ZN = griddata(X2,Y2,Z2,X,Y);
ZN contains the interpolated points.
In the figure below, zeros are shown by dark blue patches. Left is before interpolation, right is after:

Related

Calculating the root-mean-square-error between two matrices one of which contains NaN values

This is a part of a larger project so I will try to keep only the relevant parts (The variables and my attempt at the calculations)
I want to calculate the root mean squared error between Zi_cubic and Z_actual
RMSE formula
Given/already established variables
rng('default');
% Set up 2,000 random numbers between -1 & +1 as our x & y values
n=2000;
x = 2*(rand(n,1)-0.5);
y = 2*(rand(n,1)-0.5);
z = x.^5+y.^3;
% Interpolate to a regular grid
d = -1:0.01:1;
[Xi,Yi] = meshgrid(d,d);
Zi_cubic = griddata(x,y,z,Xi,Yi,'cubic');
Z_actual = Xi.^5+Yi.^3;
My attempt at a calculation
My approach is to
Arrange Zi_cubic and Z_actual as column vectors
Take the difference
Square each element in the difference
Sum up all the elements in 4 using nansum
Divide by the number of finite elements in 4
Take the square root
D1 = reshape(Zi_cubic,[numel(Zi_cubic),1]);
D2 = reshape(Z_actual,[numel(Z_actual),1]);
D3 = D1 - D2;
D4 = D3.^2;
D5 = nansum(D4)
d6 = sum(isfinite(D4))
D6 = D5/d6
D7 = sqrt(D6)
Apparently this is wrong. I'm either mis-applying the RMSE formula or I don't understand what I'm telling matlab to do.
Any help would be appreciated. Thanks in advance.
Your RMSE is fine (in my book). The only thing that seems possibly off is the meshgrid and griddata. Your inputs to griddata are vectors and you are asking for a matrix output. That is fine, but you're potentially undersampling your input space. In other words, you are giving n samples as inputs, but perhaps you are expected to give n^2 samples as inputs? Here's some sample code for a smaller n to demonstrate this effect more clearly:
rng('default');
% Set up 2,000 random numbers between -1 & +1 as our x & y values
n=100; %Reduced because scatter is slow to plot
x = 2*(rand(n,1)-0.5);
y = 2*(rand(n,1)-0.5);
z = x.^5+y.^3;
S = 100;
subplot(1,2,1)
scatter(x,y,S,z)
%More data, more accurate ...
[x2,y2] = meshgrid(x,y);
z2 = x2.^5+y2.^3;
subplot(1,2,2)
scatter(x2(:),y2(:),S,z2(:))
The second plot should be a lot cleaner and thus will likely provide a more accurate estimate of Z_actual later on.
I also thought you might be running into some issues with floating point numbers and calculating RMSE but that appears not to be the case. Here's some alternative code which is how I would write RMSE.
d = Zi_cubic(:) - Z_actual(:);
mask = ~isnan(d);
n_valid = sum(mask);
rmse = sqrt(sum(d(mask).^2)/n_valid);
Notice that (:) linearizes the matrix. Also it is useful to try and use better variable names than D1-D7.
In the end though these are just suggestions and your code looks fine.
PS - I'm assuming that you are supposed to be using cubic interpolation as that is another place you could perhaps deviate from what's expected ...

MATLAB: meshgrid pairs whoe sums<=1

I need some help with MATLAB coding. I have two variables x=0:0.1:1 and y=0:0.1:1. I want to generate the meshgrid only for those points which satisfy the condition x+y<=1. Please help me.
[X,Y] = meshgrid(x,y) returns two matrixes, representing points from (0,0) to (1,1). The requirement to remove values where x + y >= 1 works well on a graph - basically just draw a diagonal line, creating a triangle. However, it doesn't work very well for matrices - who's ever heard of a triangle matrix?
What you can do is set the excluded values to some 'bad' value, and then ignore them. I chose to set them to NaN, because functions like surf won't plot nan's:
x = 0:.1:1;
y = 0:.1:1;
[X,Y] = surf(x,y);
X(X+Y>=1) = nan;
Y(X+Y>=1) = nan;
surf(X,Y,X.*Y)

How do I write correlation coefficient manually in matlab?

The following is a function that takes two equal sized vectors X and Y, and is supposed to return a vector containing single correlation coefficients for image correspondence. The function is supposed to work similarly to the built in corr(X,Y) function in matlab if given two equal sized vectors. Right now my code is producing a vector containing multiple two-number vectors instead of a vector containing single numbers. How do I fix this?
function result = myCorr(X, Y)
meanX = mean(X);
meanY = mean(Y);
stdX = std(X);
stdY = std(Y);
for i = 1:1:length(X),
X(i) = (X(i) - meanX)/stdX;
Y(i) = (Y(i) - meanY)/stdY;
mult = X(i) * Y(i);
end
result = sum(mult)/(length(X)-1);
end
Edit: To clarify I want myCorr(X,Y) above to produce the same output at matlab's corr(X,Y) when given equal sized vectors of image intensity values.
Edit 2: Now the format of the output vector is correct, however the values are off by a lot.
I recommend you use r=corrcoef(X,Y) it will give you a normalized r value you are looking for in a 2x2 matrix and you can just return the r(2,1) entry as your answer. Doing this is equivalent to
r=(X-mean(X))*(Y-mean(Y))'/(sqrt(sum((X-mean(X)).^2))*sqrt(sum((Y-mean(Y)).^2)))
However, if you really want to do what you mentioned in the question you can also do
r=(X)*(Y)'/(sqrt(sum((X-mean(X)).^2))*sqrt(sum((Y-mean(Y)).^2)))

Can someone explain how to graph this sum in MATLAB using contourf?

I'm going to start off by stating that, yes, this is homework (my first homework question on stackoverflow!). But I don't want you to solve it for me, I just want some guidance!
The equation in question is this:
I'm told to take N = 50, phi1 = 300, phi2 = 400, 0<=x<=1, and 0<=y<=1, and to let x and y be vectors of 100 equally spaced points, including the end points.
So the first thing I did was set those variables, and used x = linspace(0,1) and y = linspace(0,1) to make the correct vectors.
The question is Write a MATLAB script file called potential.m which calculates phi(x,y) and makes a filled contour plot versus x and y using the built-in function contourf (see the help command in MATLAB for examples). Make sure the figure is labeled properly. (Hint: the top and bottom portions of your domain should be hotter at about 400 degrees versus the left and right sides which should be at 300 degrees).
However, previously, I've calculated phi using either x or y as a constant. How am I supposed to calculate it where both are variables? Do I hold x steady, while running through every number in the vector of y, assigning that to a matrix, incrementing x to the next number in its vector after running through every value of y again and again? And then doing the same process, but slowly incrementing y instead?
If so, I've been using a loop that increments to the next row every time it loops through all 100 values. If I did it that way, I would end up with a massive matrix that has 200 rows and 100 columns. How would I use that in the linspace function?
If that's correct, this is how I'm finding my matrix:
clear
clc
format compact
x = linspace(0,1);
y = linspace(0,1);
N = 50;
phi1 = 300;
phi2 = 400;
phi = 0;
sum = 0;
for j = 1:100
for i = 1:100
for n = 1:N
sum = sum + ((2/(n*pi))*(((phi2-phi1)*(cos(n*pi)-1))/((exp(n*pi))-(exp(-n*pi))))*((1-(exp(-n*pi)))*(exp(n*pi*y(i)))+((exp(n*pi))-1)*(exp(-n*pi*y(i))))*sin(n*pi*x(j)));
end
phi(j,i) = phi1 - sum;
end
end
for j = 1:100
for i = 1:100
for n = 1:N
sum = sum + ((2/(n*pi))*(((phi2-phi1)*(cos(n*pi)-1))/((exp(n*pi))-(exp(-n*pi))))*((1-(exp(-n*pi)))*(exp(n*pi*y(j)))+((exp(n*pi))-1)*(exp(-n*pi*y(j))))*sin(n*pi*x(i)));
end
phi(j+100,i) = phi1 - sum;
end
end
This is the definition of contourf. I think I have to use contourf(X,Y,Z):
contourf(X,Y,Z), contourf(X,Y,Z,n), and contourf(X,Y,Z,v) draw filled contour plots of Z using X and Y to determine the x- and y-axis limits. When X and Y are matrices, they must be the same size as Z and must be monotonically increasing.
Here is the new code:
N = 50;
phi1 = 300;
phi2 = 400;
[x, y, n] = meshgrid(linspace(0,1),linspace(0,1),1:N)
f = phi1-((2./(n.*pi)).*(((phi2-phi1).*(cos(n.*pi)-1))./((exp(n.*pi))-(exp(-n.*pi)))).*((1-(exp(-1.*n.*pi))).*(exp(n.*pi.*y))+((exp(n.*pi))-1).*(exp(-1.*n.*pi.*y))).*sin(n.*pi.*x));
g = sum(f,3);
[x1,y1] = meshgrid(linspace(0,1),linspace(0,1));
contourf(x1,y1,g)
Vectorize the code. For example you can write f(x,y,n) with:
[x y n] = meshgrid(-1:0.1:1,-1:0.1:1,1:10);
f=exp(x.^2-y.^2).*n ;
f is a 3D matrix now just sum over the right dimension...
g=sum(f,3);
in order to use contourf, we'll take only the 2D part of x,y:
[x1 y1] = meshgrid(-1:0.1:1,-1:0.1:1);
contourf(x1,y1,g)
The reason your code takes so long to calculate the phi matrix is that you didn't pre-allocate the array. The error about size happens because phi is not 100x100. But instead of fixing those things, there's an even better way...
MATLAB is a MATrix LABoratory so this type of equation is pretty easy to compute using matrix operations. Hints:
Instead of looping over the values, rows, or columns of x and y, construct matrices to represent all the possible input combinations. Check out meshgrid for this.
You're still going to need a loop to sum over n = 1:N. But for each value of n, you can evaluate your equation for all x's and y's at once (using the matrices from hint 1). The key to making this work is using element-by-element operators, such as .* and ./.
Using matrix operations like this is The Matlab Way. Learn it and love it. (And get frustrated when using most other languages that don't have them.)
Good luck with your homework!

Finding the belonging value of given point on a grid of 3D histogram?

I use 2D dataset like below,
37.0235000000000 18.4548000000000
28.4454000000000 15.7814000000000
34.6958000000000 20.9239000000000
26.0374000000000 17.1070000000000
27.1619000000000 17.6757000000000
28.4101000000000 15.9183000000000
33.7340000000000 17.1615000000000
34.7948000000000 18.2695000000000
34.5622000000000 19.3793000000000
36.2884000000000 18.4551000000000
26.1695000000000 16.8195000000000
26.2090000000000 14.2081000000000
26.0264000000000 21.8923000000000
35.8194000000000 18.4811000000000
to create a 3D histogram.
How can I find the histogram value of a point on a grid? For example, if [34.7948000000000 18.2695000000000] point is given, I would like to find the corresponding value of a histogram for a given point on the grid.
I used this code
point = feat_vec(i,:); // take the point given by the data set
X = centers{1}(1,:); // take center of the bins at one dimension
Y = centers{2}(1,:); // take center of the bins at other dim.
distanceX = abs(X-point(1)); // find distance to all bin centers at one dimension
distanceY = abs(Y-point(2)); // find distance to center points of other dimension
[~,indexX] = min(distanceX); // find the index of minimum distant center point
[~,indexY] = min(distanceY); // find the index of minimum distant center point for other dimension
You could use interp2 to accomplish that!
If X (1-D Vector, length N) and Y (1-D vector, length M) determine discrete coordinate on the axes where your histogram has defined values Z (matrix, size M x N). Getting value for one particular point with coordinates (XI, YI) could be done with:
% generate grid
[XM, YM] = meshgrid(X, Y);
% interpolate desired value
ZI = interp2(XM, YM, Z, XI, YI, 'spline')
In general, this kind of problem is interpolation problem. If you would want to get values for multiple points, you would have to generate grid for them in similar fashion done in code above. You could also use another interpolating method, for example linear (refer to linked documentation!)
I think you mean this:
[N,C] = hist3(X,...) returns the positions of the bin centers in a
1-by-2 cell array of numeric vectors, and does not plot the histogram.
That being said, if you have a 2D point x=[x1, x2], you are only to look up the closest points in C, and take the corresponding value in N.
In Matlab code:
[N, C] = hist3(data); % with your data format...
[~,indX] = min(abs(C{1}-x(1)));
[~,indY] = min(abs(C{2}-x(2)));
result = N(indX,indY);
done. (You can make it into your own function say result = hist_val(data, x).)
EDIT:
I just saw, that my answer in essence is just a more detailed version of #Erogol's answer.