Could anyone help how should I use the interp1-function on MATLAB on data such as the following:
-99
3
1
7
10
10
22
29
-99
-99
25
26
60
142
78
124
74
26
13
18
The -99 data values correspond to error-values and I would like to interpolate them...advices? =) Thank you!
Not around Matlab at the moment but I reckon you could do something like this:
Y = [-99
3
1
7
10
10
22
29
-99
-99
25
26
60
142
78
124
74
26
13
18];
%Make an array of x values - I'm assuming yours are evenly spaced
Xi = 1:length(Y);
%remove the -99 points
errors = Y == -99;
X = Xi(~errors);
Y = Y(~errors);
Yi = interp1(X, Y, Xi);
So in the code X and Y are the x and y coord vectors of the points you want to interpolate, i.e. your input points (without the errors!), and Xi is a vector of the location of the points you would like to interpolate values for (if you think about X being location and Y being value). The point Yi will be the interpolated values corresponding to Xi, which I think in this case will be your original vector with the -99 points replaced by linearly interpolated values. Funny stuff might happen at the edges :/ check the docs. Hope there are no errors.
Lets say your array is a.
x = find(a ~= -99);
y = a(x);
xi = 1:length(a);
yi = interp1(x, y, xi);
yi is what you are looking for.
Related
The plot in MATLAB looks like this:
The code to generate this is very simple:
y = [0 18 450];
x = [0 5.3 6.575];
plot(x,y);
How could I know the values of 119 equally spaced discrete points on this plot?
In simple MATLAB plots, the points are connected together by simple linear interpolation. Simply put, a straight line is drawn between each pair of points. You can't physically get these points from the graph other than those you used to plot the points (at least not easily...).
If you however do desire 119 points at equally spaced intervals that would theoretically be obtained from the above set of 4 points, you can use the interp1 function to do so:
y = [0 18 450];
x = [0 5.3 6.575]
yy = interp1(x, y, linspace(min(x),max(x),119), 'linear');
interp1 performs linear (note the 'linear' flag at the end...) interpolation given a set of key points defined by x and y points and a set of x points to use to interpolate between the key x points to generate the interpolated y points stored in yy. linspace in this case generates a linearly increasing array from the smallest value in x to the largest value in x with 119 of these points.
Here's a running example with your data:
>> format compact;
>> y = [0 18 450];
>> x = [0 5.3 6.575];
>> yy = interp1(x, y, linspace(min(x),max(x),119), 'linear');
>> yy
yy =
Columns 1 through 8
0 0.1892 0.3785 0.5677 0.7570 0.9462 1.1354 1.3247
Columns 9 through 16
1.5139 1.7031 1.8924 2.0816 2.2709 2.4601 2.6493 2.8386
Columns 17 through 24
3.0278 3.2171 3.4063 3.5955 3.7848 3.9740 4.1633 4.3525
Columns 25 through 32
4.5417 4.7310 4.9202 5.1094 5.2987 5.4879 5.6772 5.8664
Columns 33 through 40
6.0556 6.2449 6.4341 6.6234 6.8126 7.0018 7.1911 7.3803
Columns 41 through 48
7.5696 7.7588 7.9480 8.1373 8.3265 8.5157 8.7050 8.8942
Columns 49 through 56
9.0835 9.2727 9.4619 9.6512 9.8404 10.0297 10.2189 10.4081
Columns 57 through 64
10.5974 10.7866 10.9759 11.1651 11.3543 11.5436 11.7328 11.9220
Columns 65 through 72
12.1113 12.3005 12.4898 12.6790 12.8682 13.0575 13.2467 13.4360
Columns 73 through 80
13.6252 13.8144 14.0037 14.1929 14.3822 14.5714 14.7606 14.9499
Columns 81 through 88
15.1391 15.3283 15.5176 15.7068 15.8961 16.0853 16.2745 16.4638
Columns 89 through 96
16.6530 16.8423 17.0315 17.2207 17.4100 17.5992 17.7885 17.9777
Columns 97 through 104
34.6540 53.5334 72.4128 91.2921 110.1715 129.0508 147.9302 166.8096
Columns 105 through 112
185.6889 204.5683 223.4477 242.3270 261.2064 280.0857 298.9651 317.8445
Columns 113 through 119
336.7238 355.6032 374.4826 393.3619 412.2413 431.1206 450.0000
Given a matrix Z(i,j) such that it maps to two arrays X(i), and Y(j).
I am trying to find elements of Z (and hence the corresponding X and Y) within a certain range.
I am now doing the following using logical indexing. Given this example
X = 1:5;
Y = 1:5;
Z = [17 24 1 8 15
23 5 6 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9]
Z((X>1 & X<4),Y==3)
This works fine, but now I wish to find the minimum of the returned values from this particular range,
Which I do with
min(Z((X>1 & X<4),Y==3))
But now how I get back the corresponding X and Y values of the minimum? Since my logical indexing returns an array, all methods I have tried so far returns the index of the min in the answer array, not the original Z matrix.
I can't use
[row col] = find(Z==min(Z((X>1 & X<4),Y==3)))
Because of the repeats. What are my alternatives?
To retrieve the original indices, you have to keep the memory of the indices of your two conditions on x and y (which I put in the arrays cX and cY) and then use the function ind2sub.
NB: your code is a little bit confusing since x stands for the lines
and y for the columns, but I have kept the same convention in my
answer.
In practice, this gives:
% --- Definition
X = 1:5;
Y = 1:5;
Z = [17 24 1 8 15
23 5 6 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9];
% --- Get the values of interest
cX = find(X>1 & X<4);
cY = find(Y==3);
v = Z(cX,cY);
% --- Get position of the minimum in the initial array
[~, I] = min(v(:));
[Ix, Iy] = ind2sub([numel(cX) numel(cY)], I);
i = cX(Ix); % i = 2
j = cY(Iy); % j = 3
Best,
One approach -
%// Calculate all indices of the grid created with those two X-Y conditions
idx = bsxfun(#plus,(find(Y==3)-1)*size(Z,1),find((X>1 & X<4)).') %//'
%// Get the index corresponding to minimum from that grided Z
[~,min_idx] = min(Z(idx(:)))
%// Get corresponding X-Y indices by using indices calculated earlier
[indX,indY] = ind2sub([numel(X) numel(Y)],idx(min_idx))
I am programming for task that finds the neighbor of a given pixel x in image Dthat can formula as:
The formula shown pixels y which satisfy the distance to pixel x is 1, then they are neighbor of pixel x. This is my matlab code. However, it still takes long time to find. Could you suggest a faster way to do it. Thank you so much
%-- Find the neighborhood of one pixel
% x is pixel coordinate
% nrow, ncol is size of image
function N = find_neighbor(x,nrow,ncol)
i = x(1);
j = x(2);
I1 = i+1;
if (I1 > nrow)
I1 = nrow;
end
I2 = i-1;
if (I2 < 1)
I2 = 1;
end
J1 = j+1;
if (J1 > ncol)
J1 = ncol;
end
J2 = j-1;
if (J2 < 1)
J2 = 1;
end
N = [I1, I2, i, i; j, j, J1, J2];
For example: ncol=128; nrow=128; x =[30;110] then output
N =31 29 30 30; 110 110 111 109]
For calling the function in loop
x=[30 31 32 33; 110 123 122 124]
for i=1:length(x)
N = find_neighbor(x(:,i),nrow,ncol);
end
Here's a vectorized approach using bsxfun:
% define four neighbors as coordinate differences
d = [-1 0 ; 1 0 ; 0 -1 ; 0 1]';
% add to pixel coordinates
N = bsxfun(#plus, x, permute(d, [1 3 2]));
% make one long list for the neighbors of all pixels together
N = reshape(N, 2, []);
% identify out-of-bounds coordinates
ind = (N(1, :) < 1) | (N(1, :) > nrow) | (N(2, :) < 1) | (N(2, :) > ncol);
% and remove those "neighbors"
N(:, ind) = [];
The permute is there to move the "dimension" of four different neighbors into the 3rd array index. This way, using bsxfun, we get the combination of every pair of original pixel coordinates with every pair of relative neighbor coordinates. The out-of-bounds check assumes that nrow belongs to the first coordinate and ncol to the second coordinate.
With
ncol=128;
nrow=128;
x = [30 31 32 33; 110 123 122 124];
the result is
N =
29 30 31 32 31 32 33 34 30 31 32 33 30 31 32 33
110 123 122 124 110 123 122 124 109 122 121 123 111 124 123 125
Different neighbors of different pixels can end up to be the same pixel, so there can be duplicates in the list. If you only want each resulting pixel once, use
% remove duplicates?
N = unique(N', 'rows')';
to get
N =
29 30 30 30 31 31 31 32 32 32 33 33 33 34
110 109 111 123 110 122 124 121 123 124 122 123 125 124
Matlab's performance is horrible when calling small functions many time. The Matlab approach is to do vectorize as much as possible. A vectorized version of your code:
function N = find_neighbor(x,nrow,ncol)
N = [min(x(1,:)+1,nrow), max(x(1,:)-1,1), x(1,:), x(1,:); x(2,:), x(2,:),min(x(2,:)+1,ncol), max(x(2,:)-1,1)];
end
and usage
x=[30 31 32 33; 110 123 122 124]
N = find_neighbor(x,nrow,ncol);
BTW, for pixels on the border , your solution always gives 4 neighbors. This is wrong. the neighbors of (1,1) for examples should be only (2,1) and (1,2), while you add two extra (1,1).
The solution to this is quite simple - delete all neighbors that are outside the image
function N = find_neighbor(x,nrow,ncol)
N = [x(1,:)+1, x(1,:)-1, x(1,:), x(1,:); x(2,:), x(2,:),x(2,:)+1, x(2,:)-1];
N(:,N(1,:)<1 | N(1,:)> nrow | N(2,:)<1 | N(2,:)>ncol)=[];
end
I am struggling with the concepts behind plotting a surface polar plot.
I am trying to plot the values measured by a sensor at a combination of different angles over a hemisphere.
I have an array containing the following information:
A(:,1) = azimuth values from 0 to 360º
A(:,2) = zenith values from 0 to 90º
A(:,3) = values measured at the combination of angles of A(:,1) and A(:,2)
For example, here is a snippet:
0 15 0.489502132167206
0 30 0.452957556748497
0 45 0.468147850273115
0 60 0.471115818950192
0 65 0.352532182508945
30 15 0.424997863795610
30 30 0.477814980942155
30 45 0.383999653859467
30 60 0.509625464595446
30 75 0.440940431784788
60 15 0.445028058361392
60 30 0.522388502880219
60 45 0.428092266657885
60 60 0.429315072676194
60 75 0.358172892912138
90 15 0.493704001125912
90 30 0.508762762699997
90 45 0.450598496609200
90 58 0.468523071441297
120 15 0.501619699042408
120 30 0.561755273071577
120 45 0.489660355057938
120 60 0.475478615354648
120 75 0.482572226928475
150 15 0.423716506205776
150 30 0.426735372570756
150 45 0.448548968227972
150 60 0.478055144126694
150 75 0.437389584937356
To clarify, here is a piece of code that shows the measurement points on a polar plot.
th = A(:,1)*pi/180
polar(th,A(:,2))
view([180 90])
This gives me the following plot:
I would like now to plot the same thing, but instead of the points, use the values of these points stored in A(:,3). Then, I would like to interpolate the data to get a colored surface.
After some research, I found that I need to interpolate my values over a grid, then translate to Cartesian coordinates. From there I do not know how to proceed. Could someone point me in the right direction?
I have trouble getting the concept of the interpolation, but this is what I have attempted:
x1 = linspace(0,2*pi,100)
x2 = linspace(0,90,100)
[XX,YY] = meshgrid(x1,x2)
[x,y] = pol2cart(th,A(:,2))
gr=griddata(x,y,A(:,3),XX,YY,'linear')
With this piece of code, your example data points are converted into cartesian coords, and then plotted as "lines". The two tips of a line are one data point and the origin.
az = bsxfun(#times, A(:,1), pi/180);
el = bsxfun(#times, A(:,2), pi/180);
r = A(:,3);
[x,y,z] = sph2cart(az,el,r);
cx = 0; % center of the sphere
cy = 0;
cz = 0;
X = [repmat(cx,1,length(x));x'];
Y = [repmat(cy,1,length(y));y'];
Z = [repmat(cz,1,length(z));z'];
Still thinking how to interpolate the data so you can draw a sphere. See my comments to your question.
looking for an efficient way to vectorize a search
say A is 2 by 4 array
x y z a
.2 0.97 34.2 4.5
and B is a 1 by 1000 array
a x x x x y y y z z a .........
How do I get the corresponding row 2 values of A for array B. Looking for a vectorized efficient solution, I have an if loop that works but not efficient.
Thanks
I currently have
A(2,A(1,:)==B(:))
but this doesn't work as both arrays have different sizes.
Thanks
You can use the second output from the ismember function, like this:
%Setup
A = [24 25 26 1; 0.2 0.97 34.2 4.5]
B = [1 24 24 24 24 25 25 25 26 26 1];
%Use ismember to get matching indexes
[~, ixs] = ismember(B, A(1,:))
%Use indexes to get desired result
out = A(2,ixs)