Append (x,y) coordinates to variable in Matlab loop for function call - matlab

I have scatter plot of several thousand points, which lie above a lower boundary defined by several line segments. My goal is to find the shortest distance from every point to the lower boundary (which is composed of linear and sloped line segments that connect) above which the pt lies, and sum this distance for all points for later post-processing.
I found a point-to-line function script online (https://www.mathworks.com/matlabcentral/fileexchange/64396-point-to-line-distance) which I have tested in isolation, and would now like to integrate into my script. The function take an array of points (class double) such as [0.1,0.7;0,0.5;...] and also takes two [x,y] points which lie on the line to which the shortest distance is to be calculated.
So far I have written a while loop which loops through all rows in a dataset already saved to the workspace (with the exception of zeroes which I would like to ignore). I then use a nested if loop to check if a given point is in the x range of the given lower boundary segment (I always want to calculate the shortest distance to the lower boundary segment above which a given pt lies), and lastly I try to append the given (x,y) coordinate of the point to a variable which will become one of the function inputs. The two points which define the lower boundary line segment are hard coded for each segment and do not change.
Here is a snippet of my code:
short_deviation = 0;
idx = 1;
while idx <= numel(my_data(:,5)) && not(my_data(idx,5) == 0)
...
if my_data(idx,5) < my_data(2,9) && my_data(idx,5) > my_data(1,9) % check that pt is in x range of lower segment
pt(:,idx) = my_data(idx,3:4); % CURRENT ERROR - Try to append given pt to list for function input
v1 = my_data(1,9:10); % two hard coded x,y pts which lie on lower boundary to which I want the distance
v2 = my_data(2,9:10);
distance_2D(idx) = point_to_line_dist(pt, v1, v2); % calling function
end
...
idx = idx + 1;
end
When I run the current code I get the following error message:
Unable to perform assignment because the size of the left side is 1-by-1 and the size of the right side is 1-by-2.
Error in My_script (line xxx)
pt(:,idx) = my_data(idx,3:4);
Now that I write out this code, I think another potential error is that I call the function distance_2D inside the if loop - I'm also not sure if the syntax for calling the function is correct (little experience here), but I haven't gotten to this point because of the previous error I mentioned.

The error indicates that pt is previously of the wrong size. For your code to run, it must have two rows, otherwise the data won't fit. You could use
pt=zeros(2,numel(my_data(:,5)))

Related

Find elements of a matrix from another

I am work from a skeleton of an image. Wanting to fill some incomplete branches, I extracted the end points of the skeleton and implemented Dijkstra's algorithm to find the minimal paths that can be between the points (I get a matrix FR 500x500).
I applied a constraint of cost and orientation to limit the undesirable connections. My problem is that I still have unwanted links because some starting point belong to several paths with different costs. Then I extracted these starting points to keep only those whose cost is the lowest (matrix P 75x3 with column 1 and 2 which are the coordinates X and Y of the starting points and column 3 the cost).
I now try to code that I want to take all possible paths those who have a starting point and a cost corresponding to the matrix FP but I do not see how to do.
I would like to indicate in this code that each starting point has the "right" to take only the least expensive path
NumberPath = 0;
S=size(EP); %EP = matrix 90x2 coordinates x and y of skeleton's end points
NumP=S(1);
for i=1:NumP-1
for j=i+1:NumP
FP = ED(i,:);
LP = ED(j,:);
[cost,path] = dijkstra(PC,Weight); % PC = matrix of all possible paths
dimPath = size(path);
dx=LP(1)-FP(1);
dy=LP(2)-FP(2);
if dx>0 && dx/dy>0 % Constraints of orientation
NumberPath = NumberPath+1;
if (cost<55) % Constraints of Cost
for p=1:dimPath(2)
FR(PC(path(1,p),2),PC(path(1,p),1))=NumberPath;
% FR=Matrix 500x500 with all paths according to conditions
Cost(i,j)=cost; % Matrix of all cost < 55
P(NumberPath,:)=FP; % Starting Point of each path
L(NumberPath,:)=LP; % End Point of each path
end
end
end
end

Link closest points accross altitudes in Matlab and form chains

I have a 3d matrix with scattered points (Nx4 matrix, x-y-z-data). My aim is to link the closest points together and register each chain in an Kx4 array (x, y, z, data), K being the chain length. The total number of chains depends on the points...
A particularity is that these lines only go upwards (z+), I don't want to link points on same z, or go down.
I have been trying different strategies so far, one being with another array shape (Mx4xNz - basically meaning the values were stacked per z's instead of being all on a 2d matrix):
[edited after some progress, using delaunay/nearestneighbor]
pick a point at level Zn
go to level Zn+1, look for the closest point in a range of coordinates x,y using delaunayTriangulation and nearestNeighbor
register the point into a vector
(I suspect there are other possibilities using nearestNeighbor with the Nx4 matrix, but i can't think how to 'direct' the search upwards and chain the successive points... )
I find myself with the following problem :
The finding of nearest point upwards seems to work well but in 1 direction only!!
Linking doesn't work:
Linking works:
During the loop I have the warning :
Warning: Duplicate data points have been detected and removed.
The Triangulation indices are defined with respect to the unique set of points in
delaunayTriangulation property X.
Lign=zeros(max_iter,4,s);
for i = 1:s;
pp_id=i;
for n=1:max_iter-1;
Wn=W(:,:,n); % W is the data 3d-matrix Mx4xNz
Wnn=W(:,:,n+1);
Point_n = Wn(pp_id,:);
xn= Point_n(1);
yn= Point_n(2);
zn= Point_n(3);
vn= Point_n(4);
if xn==0|yn==0|zn==0|vn==0;
break
end
% Look for nearest neighbour at next level
DT=delaunayTriangulation(Wnn(:,[1:2]));
[pp_id, d]=nearestNeighbor(DT,[Point_n(1),Point_n(2)]);
% limit range
if d>10
break
end
% extraction of values at new pp_id
Point_n=Wnn(pp_id,:);
% register point in line
Lign(n,:,i)=Point_n;
end
end
Anyone has an idea as to why this is happens?

Issue with reading data in text files and plotting a graph (Matlab)

I use the following code to collect data from two text files join them together and then plot them. For some reason, I appear to get two plots rather than 1, I am not sure why this is happening.
load MODES1.dat; % read data into the MODES1 matrix
x1 = MODES1(:,1); % copy first column of MODES1 into x1
y1 = MODES1(:,2); % and second column of MODES1 into y1
load MODES.dat; % read data into the MODES matrix
x = MODES(:,1); % copy first column of MODES into x
y = MODES(:,2); % and second column of MODES into y
% Joining the two sets of data
endx = [x1;x];
endy = [y1;y];
figure(1)
plot(endx,endy)
xlabel('Unique Threshold Strains','FontSize',12);
ylabel('Probabilities of occurrence','FontSize',12);
title('\it{Unique Values versus frequencies of occurrence}','FontSize',16);
Thanks
Your problem is quite a simple one. Matlab's plot command creates a point for each data point defined by the parameters and connects those points in the order they appeared in the first parameter. To get an idea of this behavior, try
x = [0;1;-1;2;-2;3;-3;4;-4;5];
plot(x,x.^2);
You won't get the quadratic function graph you might expect.
To fix this, you must sort you input arrays identically. Sorting one array is simple (sort(endx)), but you want to sort both in the same way. Matlab actually gives you a function to do this, but it only works on matrices, so you need to do some concatenating/seperating:
input = sortrows( [endx endy] );
endx = input(:,1);
endy = input(:,2);
This will sort the rows of the matrix built by putting endy right of endx with respect to the first column (endx). Now your inputs are correctly sorted and the resulting plot should only show one line. (More accurately, one line which does not at some point go back where it came from.)
Another way to achieve this, depending on you actual use case and data origin, would be to build the mean value of both parts of x, so instead of endx = [x1;x];, you'd build endx = mean([x1 x],2);.
Yet another way is to drop the line altogether and go with
plot(endx,endy,'.');
or
plot(endx,endy,'LineStyle','none');
But this is only useful if your data points are very close to each other.

Matlab Plot Smoothing having no effect

I'm currently having some trouble with the 'smooth' command, namely that it seems to have no effect on the generated plot. I have already used the following script to generate a plot
for h=1:4
linespec = {'rx', 'gx', 'bx', 'yx'};
hold on
for b=1:365
y=mean(mean(A(b,6*(h-1)+1:6*h)));
p(h)=plot(b,y,linespec{h});
end
hold off
end
Going row by row in data set A and taking the average of the values in the first six columns, then column 7 through 12, 13 through 18 and 19 through 14; generating four plots in total.
The next step was to smooth the resultant plot by averaging the values over a span of 9. So, I tweaked the script to the following;
for h=1:4
linespec = {'rx', 'gx', 'bx', 'yx'};
hold on
for b=1:365
y=mean(mean(A(b,6*(h-1)+1:6*h)));
w = smooth(y,9,'moving');
p(h)=plot(b,w,linespec{h});
end
hold off
end
Essentially just adding the w variable and replacing y with w in the plot command. Yet this has no effect whatsoever on my plot. Matlab doesn't throw up any errors either, so there doesn't seem to be a problem with the input size. Does anyone have an idea as to what the issue might be?
In either version of the loop, you appear to be plotting individual values of y against individual values of b. I presume, then, that y is a single value. You can't smooth a point, so the smooth operation is having no effect.
From the start, you don't need to make a loop to calculate the various means; mean can take a 2D matrix and return a vector. Calculate y in one go, then smooth that vector (should have length 365, I presume - depends on the size of input A). e.g.:
b = 1:365;
y=mean(A(:,6*(h-1)+1:6*h),2);
w = smooth(y,9,'moving');
plot(b,y,'rx');
hold on
plot(b,w,'gx');

First Derivative filter Matlab

I have recently been tasked with using a first derivative filter on an image of myself. The instructor said that I should first fix the value of y and preform f(x+1) - f(x) on the rows and then fix the new "X" values and preform f(y+1)-f(y) on the columns.
Note: I have been asked to do this task manually, not using filter2() or any other programmed function, so please do not suggest that I use filter2() or similar. Thanks!
I tried calling up all the pixels and subtracting each successive one by doing
fid = fopen('image.raw')
myimage = fread(fid,[512 683], '*int8')
fclose(fid)
imsz = size(myimage)
x = imsz(1)
for I = 1:512
for J = 1:683
X(I) - X(I-1) = XX
But it doesnt seem to work, and I dont quite understand why. If you could help me, or point me in the right direction, I would be very appreciative.
First of all, your code is syntatically incorrect:
There is no end statement to any of your loops, and besides, you don't even need loops here.
You seem to read your image into the variable myimage, but you're using an undefined variable X when attempting to calculate the derivative.
The order of your assignment statements is reversed. The variable you wish to assign to should be written in the left hand part of the assignement.
I strongly suggest that you read online tutorials and get yourself familiar with MATLAB basics before taking on more complicated tasks.
As to your specific problem:
MATLAB encourages vectorized operations, i.e operations on entire arrays (vectors or matrices) at once. To subtract adjacent values in an array, what you're basically doing is subtracting two arrays, shifted by one element with respect to each other. For one dimensional arrays, that would translate in MATLAB to:
a(2:end) - a(1:end-1)
where a is your array. The end keyword specifies the last index in the array.
To compute the derivative of an image (a 2-D matrix), you need to decide along which axis you want to perform that operation. To approximate the derivate along the y-axis, do this:
X(2:end, :) - X(1:end-1, :)
You can verify that this gives you the same result as diff(X, 1) (or simply diff(X)). To compute the approximate derivative along the x-axis, which is equivalent to diff(X, 2), do this:
X(:, 2:end) - X(:, 1:end-1)
The colon (:) is the same as writing 1:end as the array subscript for the corresponding dimension.
If your filtered image is div then
for Y = 1:682
for X = 1:511
div(X, Y) = myimage(X + 1, Y + 1) - myimage(X,Y);
end
end
Remember the last row and the last column are not filtered!