Plot cell array without loop - arrays

I have the following code:
SimRun = 0
Count = 0
for b = 1:0.5:3000
.
.
.
.
Count = Count + 1;
ArrayT(Count) = Time;
ArrayTgo(Count) = tgo;
ArrayY(Count) = Y;
ArrayYD(Count) = YD;
end
SimRun = SimRun + 1;
MAT_ArrayT{SimRun,:} = ArrayT;
MAT_ArrayTgo{SimRun,:} = ArrayTgo;
MAT_ArrayY{SimRun,:} = ArrayY;
MAT_ArrayYD{SimRun,:} = ArrayYD;
As you can see, I have 2 for loops. From the inner loop I receive a vector and from the outer loop I receive in the end a cell array where each cell is a vector.
Now, I had like to plot the cell array to plot basically around 6000 lines and I did it as follows:
for i = 1:SimRun
figure(1)
hold on
plot(MAT_ArrayT{i,:},MAT_ArrayY{i,:})
figure(2)
hold on
plot(MAT_ArrayT{i,:},MAT_ArrayYD{i,:})
end
However this solution takes pretty much time to draw all the lines.
Is there any better solution to store "lines" and plot all of them in one hit at the end?
Thank you.

The plot command takes a matrix and plots each column as a separate line. Assuming you have column vectors in your cell arrays, and they're all the same length, you can do this:
x = [MAT_ArrayT{:}];
y = [MAT_ArrayY{:}];
plot(x,y)
Even better would be to store those vectors in a numeric matrix to start with, so you don't need to make the extra copy.

Related

MATLAB Add Mouse Click Coordinate to Matrix?

I am creating an image processing project in matlab. I want to get 5 coordinates from image with mouse and save them to a matrix. When I run project, I click only once but the matrix is taking same coordinates. How can I fix it ?
function ImageClickCallback ( objectHandle , eventData )
array = 3:2;
for i = 1:3
axesHandle = get(objectHandle,'Parent');
coordinates = get(axesHandle,'CurrentPoint');
coordinates = coordinates(1,1:2);
array(i,1) = coordinates(1);
array(i,2) = coordinates(2);
end
disp(array);
For example when I click a point on image, I am taking this result. I can't select another points.
99.3806 37.1915
99.3806 37.1915
99.3806 37.1915
A much safer alternative would be to use ginput, with which you can select a variable number of points and store their coordinates easily. You don't need a loop; the coordinates are stored once all the points are selected.
Here is a simple example:
clear
clc
close all
A = imread('peppers.png');
imshow(A,[]);
hold on
%// Number of points
N = 5;
array = zeros(N,2);
%// Use a for loop and plot 1 point at a time.
for k = 1:N
[array(k,1),array(k,2)] = ginput(1);
%// Display the points
scatter(array(k,1),array(k,2),60,'k','filled')
end
Sample output for array:
123.0000 87.0000
95.0000 206.0000
256.0000 85.0000
236.0000 253.0000
395.0000 117.0000
And the image with the points displayed:
Therefore, you could would look like this:
function ImageClickCallback ( objectHandle , eventData )
array = zeros(3,2);
[array(:,1),array(:,2)] = ginput(3);

Connecting random points in MATLAB without intersecting lines

I need help with solving this problem. I have randomly generated points (example on Picture #1) and I want to connect them with lines (example on Picture #2). Lines can't be intersected and after connection, the connected points should look like an irregular area.
%Generating random points
xn = randi([3 7],1,10);
yn = randi([3 6],1,10);
%Generated points
xn = [6,3,7,7,6,6,6,4,6,3];
yn = [5,3,4,3,3,6,5,4,6,3];
Picture #1:
Result should be like this:
Picture #2:
Any idea how to solve this?
I suppose for the general case it can be very difficult to come up with a solution. But, assuming your points are scattered "nicely" there is quite a simple solution.
If you sort your points according to the angle above the x axis of the vector connecting the point and the center of the point cloud then:
P = [xn;yn]; %// group the points as columns in a matrix
c = mean(P,2); %// center point relative to which you compute the angles
d = bsxfun(#minus, P, c ); %// vectors connecting the central point and the dots
th = atan2(d(2,:),d(1,:)); %// angle above x axis
[st si] = sort(th);
sP = P(:,si); %// sorting the points
And that's about it. To plot the result:
sP = [sP sP(:,1)]; %// add the first point again to close the polygon
figure;plot( sP(1,:), sP(2,:), 'x-');axis([0 10 0 10]);
This algorithm will fail if several points has the same angle w.r.t the center of the point cloud.
An example with 20 random points:
P = rand(2,50);
You could adapt the code from another answer I gave for generating random simple polygons of an arbitrary number of sides. The difference here is you already have your set of points chosen and thus implicitly the number of sides you want (i.e. the same as the number of unique points). Here's what the code would look like:
xn = [6,3,7,7,6,6,6,4,6,3]; % Sample x points
yn = [5,3,4,3,3,6,5,4,6,3]; % Sample y points
[~, index] = unique([xn.' yn.'], 'rows', 'stable'); % Get the unique pairs of points
x = xn(index).';
y = yn(index).';
numSides = numel(index);
dt = DelaunayTri(x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
while numEdges ~= numSides
if numEdges > numSides
triIndex = vertexAttachments(dt, boundaryEdges(:,1));
triIndex = triIndex(randperm(numel(triIndex)));
keep = (cellfun('size', triIndex, 2) ~= 1);
end
if (numEdges < numSides) || all(keep)
triIndex = edgeAttachments(dt, boundaryEdges);
triIndex = triIndex(randperm(numel(triIndex)));
triPoints = dt([triIndex{:}], :);
keep = all(ismember(triPoints, boundaryEdges(:,1)), 2);
end
if all(keep)
warning('Couldn''t achieve desired number of sides!');
break
end
triPoints = dt.Triangulation;
triPoints(triIndex{find(~keep, 1)}, :) = [];
dt = TriRep(triPoints, x, y);
boundaryEdges = freeBoundary(dt);
numEdges = size(boundaryEdges, 1);
end
boundaryEdges = [boundaryEdges(:,1); boundaryEdges(1,1)];
x = dt.X(boundaryEdges, 1);
y = dt.X(boundaryEdges, 2);
And here's the resulting polygon:
patch(x,y,'w');
hold on;
plot(x,y,'r*');
axis([0 10 0 10]);
Two things to note:
Some sets of points (like the ones you chose here) will not have a unique solution. Notice how my code connected the top 4 points in a slightly different way than you did.
I made use of the TriRep and DelaunayTri classes, both of which may be removed in future MATLAB releases in favor of the delaunayTriangulation class.

Matlab Cell Array Data

I have a cell array it is 100x1, variable name is CellA. As you will see from the png file attached, the cell array contains various size matrices in each of the 100 different cells.
I want to extract that data. Actually, I am trying to find the number of unique elements in each cell and their frequency. Below is my code which gets dimensional errors:
for i=1:length(CellA)
if isempty(CellA{i})
continue;% do nothing
else
unqmz(i,:) = unique(CellA{i})';
countmz(i,:) = histc(CellA{i}, unqmz(i))';
end
Eventually, I want to plot count versus unique number for each different cell array where the total number of counts for that cell exceeds a pre-determined value. e.g.) 4
You can also do it this way:
unqmz = cellfun(#unique, CellA, 'uni', 0);
countmz = arrayfun(#(n) histc(CellA{n},unqmz{n}), 1:numel(CellA), 'uni', 0).';
See if this works out for you -
%// Get result data into unqmz and countmz
unqmz = cell(numel(CellA),1);
countmz = cell(numel(CellA),1);
for ii=1:numel(CellA)
if isempty(CellA{ii})
continue;% do nothing
else
unqmz(ii) = {unique(CellA{ii})'} %//'
countmz(ii) = {histc(CellA{ii}, cell2mat(unqmz(ii)))'} %//'
end
end
%// Count of number of unique numbers in each cell
count_uniqs = cellfun(#numel,unqmz);
%// Plot (assuming you want to plot everything in one figure window)
figure,
for k = 1:size(countmz,1)
if count_uniqs(k)>4
plot(cell2mat(unqmz(k)),cell2mat(countmz(k)),'x')
hold on
end
end

Concatenating 1D matrices of different sizes

I perhaps am going about this wrong, but I have data{1}, data{2}...data{i}. Within each, I have .type1, .type2.... .typeN. The arrays are different lengths, so horizontal concatenation does not work.
For simplicity sake
>> data{1}.type1
ans =
1
2
3
>> data{2}.type1
ans =
2
4
5
6
Results should be [1;2;3;2;4;5;6]
I've been trying to loop it but not sure how? I will have a variable number of files (a,b..). How do I go about looping and concatenating? Ultimately I need a 1xN array of all of this..
My working code, thanks..figured it out..
for i = 1:Types
currentType = nTypes{i}
allData.(currentType)=[];
for j = 1:nData
allData.(currentType) = [allData.(currentType); data{j}.(currentType)(:,3)]; %3rd column
end
end
Look at cat, the first argument is the dimension. In your simple example it would be:
result = cat(1,a,b);
Which is equivalent to:
result = [a;b];
Or you can concatenate them as row vectors and transpose back to a column vector:
result = [a',b']';
For the case of a structure inside a cell array I don't think there will be any way around looping. Let's say you have a cell array with M elements and N "types" as the structure fields for each element. You could do:
M=length(data);
newData=struct;
for i=1:M
for j=1:N
field=sprintf('type%d',j); % //field name
if (M==1), newData.(field)=[]; end % //if this is a new field, create it
newData.(field)=[newData.(field);data{i}.(field)];
end
end

Turning an array in to a matrix in MATLAB

I need to turn a large array into a matrix in the following way: to take the first m entries of the array and make that the 1st row of the matrix.
For example: if I had an array that was 100 entries long, the corresponding matrix would be 10 rows and each row would be 10 entries of the array with the order preserved.
I've tried the following code:
rows = 10
row_length = 10
a = randi(1,100);
x = zeros(rows,row_length)
for i=1:rows
x(i) = a(i:i+row_length)
end
but with no luck. I'm stuck on how to slide the window along by row_length so that i will start from row_length+1 in the second (and subsequent) iterations of the loop.
The best way to do it is to use Matlab's reshape function:
reshape(a,row_length,[]).'
It will reshape by first assigning down the columns which is why I transpose at the end (i.e. .')
However just for the sake of your learning, this is how you could have done it your way:
rows = 10
row_length = 10
a = rand(1,100)
x = zeros(rows,row_length)
for i=1:row_length:rows*row_length %// use two colons here, the number between them is the step size
x(i:i+row_length-1) = a(i:i+row_length-1) %// You need to assign to 10 elements on the left hand side as well!
end

Resources