how to find points between boundaries

Hi, I have a text file of data points taken from the coordinates of a point at time t and time t+10us, from this I can derive velocity and trajectory, a plot is attached. What I want to do with the data is figure out a way to work on the whole array at once without breaking it down into smaller arrays. The tricky bit is making sure you have the correct drops paired (t,t+10us), I have ways to do this but have not included it in the code below which I wanted to simplify as much as possible.
Plot shows the position of the points and the boundaries plotted between them, the boundaries demarcate something I am calling a 'slice'. So slice1 is empty,slice2 has 2 points,slice3 has 2 points,slice4 has 2 points, etc. What I don't know how to do simply (I found a very convoluted way of doing it) is how to use the vector B in such a way as to identify which points fall within the slice, ideally for anything that falls on or around the dashed boundary I would like to be able to see if it belonged to which of the neighbouring slices, for example if one slice had 2 points and its neighbour only 1 point then the boundary point should belong to slice 2. Any pointers?
Best regards
Steve
clear all
close all
clc
Ax=[1.6 1.2 2.2 2.7 2.4 3.3 3.33 4.8 4.9 5.7 5.1 6.6 6.2]';%simplified and reduced x data
Ay=[0.3 0.7 0.33 0.2 0.64 0.4 0.7 0.35 0.67 0.38 0.61 0.32 0.65]';%simplified and reduced y data
B=[0 1 2 3 4 5 6 7]';
scatter(Ax,Ay,'filled','b')
axis([0 7 0 0.8])
hold on
y1=get(gca,'ylim');
plot([B(:,1),B(:,1)],y1,'--r')
box on;grid minor
xlabel('x coordinates');
ylabel('y coordinates');
print('PointsFigure', '-dpng','-r0');
resultsVars={ 'SliceID','amount_of_points_in_slice','point1_Xcoord','point2_Xcoord','point1_Ycoord','point2_Ycoord',}

2 Comments

YOu can use <= and >= inequalities to get the indices you want.
Yes KSSV, its figuring out how to do that on an array all at once.

Sign in to comment.

 Accepted Answer

Guillaume
Guillaume on 12 Mar 2018
Edited: Guillaume on 12 Mar 2018
So do you know which points are at t or t+10 or are you actually trying to find the displacement? If the latter, then a PTV (particle tracking velocimetry), or if the points are dense, PIV (particle image velocimetry) algorithm is what you need. These are very mature. I believe there's a FEX submission.
To answer your question, dividing Ay into slices is easily done with discretize:
sliceID = discretize(Ax, B);
Or, since you also want to know the number of points in each slice, with histcounts:
[bincount, ~, sliceID] = histcounts(Ax, B)
You can easily identify the borderline points:
tolerance = 0.1; %whatever you want it to be
[whichpoint, whichborder] = find(abs(Ax - B.') <= tolerance) %require R2016b or later
And move them to a different bin if you wish.

8 Comments

Hi Guillaume, The points at t have a lower yvalue than those at t=10us, the trick is getting the sortrows done by x first, and then once I have the right IDs for the points in a slice I can do the velocity&trajectory. I had not heard of discrete so will look into that, much appreciated!
Hi Guillaume, Spent a few hours trying to understand how to get discrete to work with accummarray, I now have it working how I want, thank you very much. Steve
If you wanted to split your array in a cell array of bins (not particularly a good idea):
sliceID = discretize(Ax, B);
BinnedAx = accumarray(sliceID, Ax, [], @(v) {v});
Hi Guillaume,
I'll probably get mocked for this but I've tried reading a lot off documentation on the anonymous functions and there's something I still don't quite get.
In your example you have "@(v) {v})" as the anonymous function. As I understand it "@(v)" is the handle for the anonymous function, and what comes after it is the function itself, what I don't understand is what is being passed into it, the "v". I actually use and tweak an accumarray that I have working but I am mystified as to how it works and what its doing, and this for me seems to be the stumbling block (it still works though).
Nobody is going to mock anybody. Anonymous functions are hard to grasp if you've never used them before.
The syntax of an anonymous function is
@(inputarglist) code_that_uses_inputs
In this particular case, the anonymous function I wrote is exactly equivalent to:
function unnamedoutput = anonymousfunction(v)
unnamedoutput = {v};
end
All it does is put the vector of values that accumarray gives to the function into a single cell array. accumarray then concatenate all these cell arrays into a single cell array and you end up with a cell array where each cell is a vector of the value corresponding to a unique subs.
Anonymous functions are actually a bit wimpy in matlab. They have some limitations not present in other languages (no branching, no assignment). There are also some subtleties associated with anonymous functions due to them being closures.
If you show your accumarray code, I can explain how it work exactly.
I'm happy to open a new question for this as the help is above and beyond the scope of the initial question.
code:
fun = @(r){sortedData(r,3:end)};
Slice_uniq_OUT=accumarray(sortedData(:,7),sortedData(:,1),[],fun);%
r was something I used in an accummarray someone helped me with before, but I have no 'r' variable anywhere in this script.
sortedData(:,7) is sliceID.
sortedData(:,1) is a column that just numbers each row sequentially (1:710)
sortedData(r,3:end) - r=??, 3:end is the x,y, volume and sliceID
So the anonymous function is taking the output from accumarray (for example '(v)') and making the larger cell array containing the output from accumarray?
r is just an input variable to the function. You can use any name you want for that variable, same as you can use any name you want for the inputs of a normal function. The anonymous function is equivalent to:
function unnamedoutput = anonymousfunction(r)
unnamedoutput = {sorteddata(r, 3:end);
end
with sorteddata captured when you create the function (this is the closure bit I linked to above).
Overall, the whole lot is equivalent to:
fun = @(r){sortedData(r,3:end)};
subs = sortedData(:, 7);
data = sortedData(:, 1);
uniquesubs = unique(subs);
Slice_uniq_OUT = cell(uniquesubs(end), 1);
for i = 1:numel(uniquesubs)
toaccumulate = data(subs == uniquesubs(i));
Slice_uniq_OUT(i) = fun(toaccumulate); %the r variable in the anonymous function receives toaccumulate
%without the anonymous function, this is equivalent to:
%Slice_uniq_OUT(i) = {sortedData(toaccumulate, 3:end)};
end
Your accumarray is more complicated than needed. The indirection throught the row index in column 1 is not needed. A simpler version would be:
Slice_uniq_OUT = accumarray(sortedData(:, 7), sortedData(:, 3:end), [], @(m) {m}); %the @(m) {m} simply wraps each submatrix into a cell array
Also note that it is often not necessary to split the main matrix into submatrices. Doing calculation by group is often easier on the whole matrix (using splitapply and similar)

Sign in to comment.

More Answers (0)

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!