I have a matrix with n rows and 4 columns. The columns are x0, y0, and x1, y1 (so basically I have n pairs of point coordinates in 2D). I want to draw a line between corresponding point pairs (that is, only between x0, y0 and x1, y1 of one row).
Is it possible to do it without a loop? Because the following works but is very slow.
for i = 1:size(A.data, 1)
plot([A.data(i, 1), A.data(i, 3)], [A.data(i, 2), A.data(i, 4)], 'k-')
end
I came here looking for the same answer. I basically want a horizontal line for each x,y point, starting with that point's x-y value, and ending at the x value of the next xy pair, without a line joining that segment to that of the next xy pair. I can make the segments by adding new points between, with the old y and the new x, but I didn't know how to break up the line segments. But your wording (matrix) gave me an idea. What if you load your xy pairs to a pair of x, y vectors and - wait for it - separate your pairs with nan's in both the x and y vectors. I tried that with a very long sine wave, and it seems to work. A ton of disjoint line segments, that plot and zoom instantly. :) See if it solves your problem.
% LinePairsTest.m
% Test fast plot and zoom of a bunch of lines between disjoint pairs of points
% Solution: put pairs of x1,y1:x2,y2 into one x and one y vector, but with
% pairs separated by x and or y = nan. Nan is wonderful, because it leaves
% your vector intact, but it doesn't plot.
close all; clear all;
n = 10000; % lotsa points
n = floor(n/3); % make an even set of pairs
n = n * 3 - 1; % ends with a pair
x = 1:n; % we'll make a sine wave, interrupted to pairs of points.
% For other use, bring your pairs in to a pair of empty x and y vectors,
% padding between pairs with nan in x and y.
y = sin(x/3);
ix = find(0 == mod(x,3)); % index 3, 6, 9, etc. will get...
x(ix) = nan; % nan.
y(ix) = nan; % nan.
figure;
plot(x,y,'b'); % quick to plot, quick to zoom.
grid on;
This works for the data structure I have:
data = [
0, 0, 1, 0;...
1, 0, 1, 1;...
1, 1, 0, 1;...
0, 1, 0, 0 ...
];
figure(1);
hold off;
%slow way
for i = 1:size(data, 1)
plot([data(i, 1) data(i, 3)], [data(i, 2) data(i, 4)], 'r-');
hold on;
end
%fast way ("vectorized")
plot([data(:, 1)' data(:, 3)'], [data(:, 2)' data(:, 4)'], 'b-');
axis equal
This particular example draws a square.
The key is that MATLAB draws lines column-wise in the arguments. That is, if the arguments of plot have n columns, the line will have n-1 segments.
In a "connect-the-dots" scenario where all points in the vectors must be connected, this is irrelevant because MATLAB will transpose to get a column vector if it needs to. It becomes important in my application because I do not want to connect every point on the list - only pairs of points.
Try line for example
X=[1:10 ; 2*(1:10)];
Y=fliplr(X);
line(X,Y)
Related
I have a figure in matlab, where xlabel is 2 power n values, where n is an integer and ylable includes any vector values, I need to plot those values and keep x vector to be equal spaced. What I do now is correct but small spaces in xlabel are shown when x values are small while that becomes larger with higher values of x values.
That is what I did:
M = [2, 4, 8, 16, 32, 64, 128, 256];
s1 = [104 136 168 200 232 264 296 328];
figure(1)
semilogy(M, s1, 'ko-', 'LineWidth', 1); hold on; %
grid;
axis ([0 256 0 600])
xticks(M);
One way to have evenly spaced xticks is to use a linear vector (0,1,2,3,etc...) the same length as your data. You plot your y data versus this xa (X Apparent) vector, then just modify the xticklabels to display the proper power of 2 corresponding to each point.
So for your code:
max_xa = numel(M)-1 ; % number of "x" points (-1 because we'll start at 0)
xa = 0:max_xa ; % generate the x-apparent vector
figure
% Plot your "sl" values versus "xa"
semilogy(xa, s1, 'ko-', 'LineWidth', 1); grid on ;
axis ([0 max_xa 0 600]) % adust limits
xticklabels(M); % adjust X tick labels
will generate the following figure:
Note: We started the X apparent vector at 0 instead of 1 because otherwise Matlab would automatically insert a xtick at the value 0 and our xticklabels would all be offset by one position.
Your issues will remain unless you drop some xticklabels or better use loglog to plot which retains the feature of parabolic data.
Use following lines in your code:
loglog(M, s1, 'ko-', 'LineWidth', 1); hold on; %
You will get this result 1
General idea
I have been working on a linear algebra project, in which the idea is to test if a given set of vectors (a matrix) is linearly dependent/independent. For this the next program receives a matrix named value (user input/MxN), and make a first pass for the criterion (this part has no problems) next if the vectors are linearly dependent it must test if between the inner vectors there is some LI/LD subset, for this it starts iterating making permutations of the rows and making the criterion for it, if this results in LI subset, it must graph the vectors and the space formed by the vectors. Even when the size of the initial matrix is MxN, the matrix is usually expected to be 2 or 3 columns, R2 or R3).
Problem
In the second pass once the system is marked as linearly dependent, the system overlaps the graphics in the same windows , the desired output would be to make a first pass and if the system is LD show the a initial graph and later start graphing in separated windows the graphs of the permuted matrix formed.
NewMatrix iterates over the original "value" matrix and keeps forming the permutations of rows/vector to check the criterion again (it does, but in the same window). Note that the initial matrix "value" is defined by the user and is supposed to be already entered at the start point of the code showed.
Code
RangS=rank(R) //LI or ld criterion
[r, c] = size(value)
if (rank(value))==r
set(handles.text3,'String',('System>LI'));
figure(3);
hold on;
z = zeros(size(value, 1), 1);
quiver3(z, z, z, value(:, 1), value(:, 2), z, 0);
grid on
view(45, 45);
s=sum(value);
quiver3(0,0,0,s(1),s(2),0,'r');
points=[X' Y'];
else
set(handles.text3,'String',('System>LD'));
figure(3); //this graph should be done apart
hold on;
z = zeros(size(value, 1), 1);
quiver3(z, z, z, value(:, 1), value(:, 2), z, 0);
grid on
view(45, 45);
points=[X' Y'];
for jj = 1:size(value,1)-1 //here starts permuting vectors>credits to MikeLimaOscar
for kk = jj+1:size(value,1)
NewMatrix= value([jj,kk],:)
F=rref(NewMatrix);
RangS=rank(R) //the same criterion applied to the permutated matrices
[r, c] = size(NewMatrix)
if (rank(NewMatrix))==r
set(handles.text3,'String',('Subsystem :LI'));
figure(3); there should be one graph for every permutated matrix
hold on;
z = zeros(size(NewMatrix, 1), 1);
quiver3(z, z, z, NewMatrix(:, 1), NewMatrix(:, 2), z, 0);
grid on
view(45, 45);
s=sum(NewMatrix);
quiver3(0,0,0,s(1),s(2),0,'r');
points=[X' Y'];
else
set(handles.text3,'String',('Subsystem:LD'));
figure(3);
hold on;
z = zeros(size(NewMatrix, 1), 1);
quiver3(z, z, z, NewMatrix(:, 1), NewMatrix(:, 2), z, 0);
grid on
view(45, 45);
points=[X' Y'];
end
end
end
end
You're plotting all the graphs on the same window [figure(3)].
Providing Different arguments to figure can solve the problem.
Specific index for every window
Permutation(jj) |Permutation 1 | Permutation 2 | Permutation 3
____________________________________________________________________
|[1]submatrix 1 | [4]submatrix 1 |[6]submatrix 1
submatrix(kk) |[2]submatrix 2 | [5]submatrix 2 |[7]submatrix 2
|[3]submatrix 3 | |[8]submatrix 3
| | |[9]submatrix 4
____________________________________________________________________
Last index | 3 | 5 | 9
____________________________________________________________________
The indices in brackets will be used as figure argument
Permutation 1, just use submatrix indices kk, index_1 = kk
Permutation 2, use submatrix indices kk and the Last index submatrices from permutation 1
index_2 = Last index(Permutation 1) + kk
Permutation 3, use submatrix indices kk and the Last index submatrices from permutation 2
index_3 = Last index(Permutation 2) + kk
Generalization, a part from the first permutation, the index in nth Permutation is
index_n = Last index(Permutation n-1)) + kk
For the given question total of submatrices for a given Permutation jj can be computed as
total(Permutation jj) = numel(jj+1:size(value,1))
Please read through the comments
% Check if the entire matrix is linear independent or not
if LI
% Linear independent
% Plot the graph in window #1
figure(1)
else
% Linear dependent
% Plot the graph in window #1
figure(1)
% Starting index for next Permutation
Last_index = 0;
% Figure() argument initialization
index = 0;
% Permutation begins here
for jj = 1:size(value,1)-1
% submatrices for a given permutation jj begins here
for kk = jj+1:size(value,1)
% Check if submatrix is linear independent or not
if submatrix(kk) from permutation (jj) is LI
% Linear independent
% Plot the graph in window #index
index = Last_index + kk
figure(index)
else
% Linear dependent
% Plot the graph in window #index
index = Last_index + kk
figure(index)
end
% End of checking if submatrix is linear independent or not
end
% Update last index for the next permutation starting index
Last_index = Last_index + numel(jj+1:size(value,1))
% End of submatrices for a given permutation jj
end
% End of Permutation
end
% End of checking if the entire matrix is linear independent or not
I need to plot a cell array with the following format in Matlab:
{[vector1], [vector2], ...}
Into a 2D graph with the index of the vector as the y and the vector as the x
([vector1], 1), ([vector2], 2), ...
Here's a simple option:
% some arbitrary data:
CellData = {rand(10,1)*50,rand(10,1)*50,rand(10,1)*50};
% Define x and y:
x = cell2mat(CellData);
y = ones(size(x,1),1)*(1:size(x,2));
% plot:
plot(x,y,'o')
ylim([0 size(x,2)+1])
so you plot each vector of x on a separate y value:
It will work as long as your cell array is just a list of vectors.
EDIT: For non equal vectors
You'll have to use a for loop with hold:
% some arbitrary data:
CellData = {rand(5,1)*50,rand(6,1)*50,rand(7,1)*50,rand(8,1)*50,rand(9,1)*50};
figure;
hold on
for ii = 1:length(CellData)
x = CellData{ii};
y = ones(size(x,1),1)*ii;
plot(x,y,'o')
end
ylim([0 ii+1])
hold off
Hope this answers your question ;)
Here's my (brute force) interpretation of your request. There are likely more elegant solutions.
This code generates a dot plot that puts the values from the vectors at each index on the y axis—bottom to top. It can accommodate vectors of different lengths. You could make it a dot plot of vector distributions, but you might need to add some jitter to the x value, if multiple occurrences of identical or nearly identical values are possible.
% random data--three vectors from range 1:10 of different lengths
for i = 1:3
dataVals{i} = randi(10,randi(10,1),1);
end
dotSize = 14;
% plot the first vector with dots and increase the dot size
% I happen to like filled circles for this, and this is how I do it.
h = plot(dataVals{1}, ones(length(dataVals{1}), 1),'.r');
set(h,'markers', dotSize);
ax = gca;
axis([0 11 0 4]); % set axis limits
% set the Y axis labels to whole numbers
ax.YTickLabel = {'','','1','','2','','3','','',}';
hold on;
% plot the rest of the vectors
for i=2:length(dataVals)
h = plot(dataVals{i}, ones(length(dataVals{i}),1)*i,'.r');
set(h, 'markers', dotSize);
end
hold off
Without any data this is the best I can come up with for what you want:
yourCell = {[0,0,0],[1,1,1],[2,2,2]}; % 1x3 cell
figure;
plot(cell2mat(yourCell));
ylabel('Vector Values');
xlabel('Index of Vector');
It makes a plot like this:
Hope this helps.
I am trying to simulate the trajectories of a few particles in 2D on Matlab. I have the x- and y- coordinates of these particles as a function of time, which I store as matrix x and y. The column in both x and y corresponds to the time, while the row corresponds to the particle number: 1, 2, etc.
I know how to do the animation for one particle with pause, but I am not sure how to customize the code for multiple particles' trajectories. Basically, my idea is that on the initial plot, I have 3 markers which correspond to the initial position of the particles, say particle A, B and C. Then, I would like to follow the movement of these 3 markers, and here is where I encountered the problem: I don't know how to sort the subsequent points according to the particle identity. For example, I want to specify the first point I plot in the second time point as particle A, second point as particle B and third point in particle C.
I have done something similar to this, but in my simulation, the number of particles may be 100, which makes it impractical to create x1, x2, ..., x100, y1, y2, ..., y100 for the animation to work:
y = rand(3, 20); % Generate random sample data.
x = rand(size(y, 1), size(y, 2));
% Now we have x and y sample data and we can begin.
% Extract into separate arrays
x1 = sort(x(1,:));
x2 = sort(x(2,:));
x3 = sort(x(3,:));
y1 = y(1,:);
y2 = y(2,:);
y3 = y(3,:);
for k = 1 : length(x1)
plot(x1(1:k), y1(1:k), 'r*-', 'LineWidth', 2);
xlim([min(x(:)), max(x(:))]);
ylim([min(y(:)), max(y(:))]);
grid on;
hold on;
plot(x2(1:k), y2(1:k), 'g*-', 'LineWidth', 2);
plot(x3(1:k), y3(1:k), 'b*-', 'LineWidth', 2);
hold off;
fprintf('Plotted points 1 through %d\n', k);
pause(0.8);
end
Any ideas or suggestions will be greatly appreciated!
In order to plot all graphs at once, we might make an 2D array.
Below is an example.
y = rand(3, 20); % Generate random sample data.
x = rand(size(y, 1), size(y, 2));
% Now we have x and y sample data and we can begin.
% Extract into separate arrays
x = sort(x');
y=y';
M=size(x);
N=M(2);
for k = 1 : length(x)
if k==1;
zeroPad=zeros(1,N);
x0=[zeroPad;x(1,1:N)];
y0=[zeroPad;y(1,1:N)];
plot(x0(1:2,1:N), y0(1:2,1:N), '*', 'LineWidth', 2);
else
plot(x(1:k,1:N), y(1:k,1:N), '*-', 'LineWidth', 2);
end
xlim([min(x(:)), max(x(:))]);
ylim([min(y(:)), max(y(:))]);
grid on;
fprintf('Plotted points 1 through %d\n', k);
pause(0.8);
end
One trick was added.
At the first iteration, I added zeros before x and y.
Some unnecessary codes were removed.
Let's say I am at the point (0, 0) in MATLAB and I want to move in the coordinate plane, let's say by the vector [1, 1]. Clearly, I could just manually add 1 and 1 to the x and y coordinates, or I could set v = [1, 1] and increment x by v(1) and y by v(2) or something along those lines. However, let's say I didn't want to do this. For example, suppose my aim is to plot the graph generated by the following algorithm.
Start at the point (0, 0)
Alternate between the displacement vectors (1, 1) and (1, -1) until you reach (100, 0).
Graph it.
How would I do this using the vector directly? In other words, is there something in MATLAB which allows you to directly do something like position = current position + vector? Thanks!
Here is a way to do it from what I understood:
clc
clear
%// The 2 displacement vectors
d1 = [1 1];
d2 = [1 -1];
%// Create a matrix where each row alternates between d1 and d2.
%// In the following for-loop we will access each row one by one to create the displacement.
D = repmat([d2;d1],51,1);
%/ Initialize matrix of positions
CurrPos = zeros(101,2);
%// Calculate and plot
hold all
for k = 2:101
CurrPos(k,:) = CurrPos(k-1,:) + D(k,:); %// What you were asking, I think.
%// Use scatter to plot.
scatter(CurrPos(k,1),CurrPos(k,2),40,'r','filled')
end
box on
grid on
And the output:
Is this what you had in mind?