Update plot using hold on inside a for loop - matlab

I'm combining two plots using this code
plot(x1,y1,'.','MarkerSize',20,'Color','r');
hold on; grid on;
plot(x2,y2,'x','MarkerSize',10,'Color','b');
xlim([-a a]);
ylim([-a a]);
Now I want to change the values of x1,y1 and x2,y2 in order to have more than one point and one cross inside my figure. I tried to use a for loop where I compute new values, but every iteration this code generates another figure - whereas I want just one figure with all the points in it.
I did something like this:
for i=1:1:8
% do things that compute x1,x2,y1,y2
figure; hold on
plot(x1,y1,'.','MarkerSize',20,'Color','r');
hold on; grid on;
plot(x2,y2,'x','MarkerSize',10,'Color','b');
xlim([-a a]);ylim([-a a]);
i=i+1;
end
I also tried to put the hold on just before i=i+1 but still give me a new figure.

There are several things you can do:
The simple solution would be to put the figure command outside the loop:
figure(); hold on;
for ...
plot(x1, ...);
plot(x2, ...);
end
A better solution would be to first compute all values and then plot them:
[x1,y1,x2,y2] = deal(NaN(8,1));
for ind1 = 1:8
% do some computations
x1(ind1) = ...
...
y2(ind1) = ...
end
figure(); plot(x1,y1,'.',x2,y2,'x');
The best solution (in my opinion) would be to update existing plot objects with new data points as they become available:
[x1,y1,x2,y2] = deal(NaN(8,1));
figure(); hP = plot(x1,y1,'.',x2,y2,'x');
for ind1 = 1:8
% do some computations
hP(1).XData(ind1) = <newly-computed x1>
hP(1).YData(ind1) = <newly-computed y1>
hP(2).XData(ind1) = <newly-computed x2>
hP(2).YData(ind1) = <newly-computed y2>
end

Related

MATLAB: Blanked Plots when Looping on a Multidimensional Array

My goal output is to have four plots displaying (time, dist_a), (time, speed_a), (time, dist_b), and (time, speed_b) when looping through a multidimensional array. However, I am displaying only 2 blanked plots.
Here is my code:
time = rand(10, 1)
dist_a = rand(10,1)
dist_b = rand(10,1)
speed_a = rand(10,1)
speed_b = rand(10,1)
dist = cat(2, dist_a, dist_b);
speed = cat(2, speed_a, speed_b);
for k = 1:2
figure;
plot(time, dist(k));
plot(time, speed(k));
end
Your problems were two-fold. Firstly, you were only plotting a single point as opposed to a vector, changing dist(k) to dist(:,k) for example fixes this. Secondly, if you want four figures with a loop that executes twice, you need to include another figure command before the second plot. The following should do what you asked for, I also added in some formatting to make the plots looks nicer
for k = 1:2
figure
plot(time, dist(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('distance')
box on
grid on
figure
plot(time, speed(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('speed')
box on
grid on
end
which gives:

Handling and eliminating multiples entries in MatLab legend

I currently want to have the legend of graph, however i'm plotting several lines that should be group in only 3 types.
My currently option is to use a dummy plot out of the boundaries, plotting the relevant data and calling the legend just at the end. It works but it is prone to errors. I wanted to update the legend and select just a few of the plots.
I tried to use the leg_handle.String, but then it comes two problems:
It still plot 5 handles instead of 3.
It does not have the proper line style & color.
Any ideas?
Bellow follow the code (with dummy plot commented) and the pictures of the current version giving the error and what i want to look.
clear
figure()
hold on
%using
%dummy plot
% leg_text={'a','b','c'};
% plot(100,100,'-r')
% plot(100,100,'-b')
% plot(100,100,'-k')
for ii=1:20,
plot(1:11,linspace(0,ii,11),'-r')
end
for ii=30:50,
plot(1:11,linspace(0,ii,11),'-b')
end
for ii=70:80,
plot(1:11,linspace(ii,25,11),'-k')
end
Yaxl=[-1 80];
Xaxl=[1 11];
set(gca, 'Visible','on', ...
'Box','on', ...
'Layer','top',...
'Xlim',Xaxl, ...
'Ylim',Yaxl);
%using
% legend(leg_text)
%want to use
leg_hand=legend(gca,'show');
leg_hand.String=leg_hand.String([1 21 42]);
%extra comand will give the things that i wanted above
% leg_hand.String=leg_hand.String([1 2 3]);
What it gives:
What I expect to have:
I have tried this method using [a,b,c,d]=legend, but this give only the a handle that i already using.
This little workaround should do the job:
clear();
figure();
hold on;
h = gobjects(3,1);
for ii = 1:20
h(1) = plot(1:11,linspace(0,ii,11),'-r');
end
for ii = 30:50
h(2) = plot(1:11,linspace(0,ii,11),'-b');
end
for ii = 70:80
h(3) = plot(1:11,linspace(ii,25,11),'-k');
end
set(gca,'Box','on','Layer','top','Visible','on','Xlim',[1 11],'Ylim',[-1 80]);
legend(h,'A','B','C');
hold off;
Actually, what I did is very simple. I created an array of graphical objects of size 3 (one for each iteration) using the gobjects function. Then, inside each iteration, I assigned the last plotted line to its respective array placeholder. Finally, I created the legend using the three graphical objects I previously stored.
Alternatively:
clear();
figure();
hold on;
h1 = gobjects(20,1);
for ii = 1:20
h1(ii) = plot(1:11,linspace(0,ii,11),'-r');
end
h2 = gobjects(21,1);
for ii = 30:50
h2(ii-29) = plot(1:11,linspace(0,ii,11),'-b');
end
h3 = gobjects(11,1);
for ii = 70:80
h3(ii-69) = plot(1:11,linspace(ii,25,11),'-k');
end
set(gca,'Box','on','Layer','top','Visible','on','Xlim',[1 11],'Ylim',[-1 80]);
legend([h1(1) h2(1) h3(1)],'A','B','C');
hold off;
You create an array of graphical objects for storing the plot handlers produced by every iteration. Then you create the legend using the first (basically, any) item of each array of graphical objects.

Copy of polygon created in matlab figure despite using same figure handle throughout

figure;
poly = fill(sq(:,1), sq(:,2), 'b');
%% create cell "p" consisting of 5600 arrays of same size as sq
for i=1:5600
hold on
set(poly, 'X', p{i}(:,1),...
'Y', p{i}(:,2));
hold off
drawnow;
end
%% again create cell "q" consisting of 8700 arrays of same size as sq
for i=1:8700
hold on
set(poly, 'X', q{i}(:,1),...
'Y', q{i}(:,2));
hold off
drawnow;
end
I create a blue-filled polygon in first line and then move it all over the figure. When i run the above code, first section moves a polygon as controlled by p from initial point x0 to x1. Then i make another cell q in second section of code and use it to move blue-filled polygon again from x1 to x2. But this time a copy of the polygon is created at x1 which moves so that the previous polygon is still at x1 while this new polygon is moving to x2. Why is this happening?
I tried to write what you describe, using a little different code (more efficient), and made up the parts you didn't add. It's working, so if this is what you look for you can either adopt this code or compare it with yours and look for the problem.
My code:
% define some parameters and auxilary function:
sq_size = 3;
makeSq = #(xy) [xy(1) xy(2)
xy(1)+sq_size xy(2)
xy(1)+sq_size xy(2)+sq_size
xy(1) xy(2)+sq_size];
% create the first object:
sq = makeSq([1 1]);
poly = fill(sq(:,1), sq(:,2), 'b');
% setting the limmits for a constant view:
xlim([0 50+sq_size])
ylim([0 50+sq_size])
% first loop:
p = randi(50,10,2); % no need for cell here...
for k = 1:size(p,1)
temp_sq = makeSq(p(k,:));
set(poly, 'X', temp_sq(:,1),'Y',temp_sq(:,2));
drawnow;
pause(0.1)
end
% second loop:
q = randi(50,20,2); % no need for cell here...
set(poly,'FaceColor','g') % change to green to see we are in the second loop
for k = 1:size(q,1)
temp_sq = makeSq(q(k,:));
set(poly,'X',temp_sq(:,1),'Y',temp_sq(:,2));
drawnow;
pause(0.1)
end
The pause is only so you see the animation, it's not really needed.

Logarithmic Y scale, multiple value plot

I'd like to plot mutiple values onto the same graph with a logarithmic Y scale. The following code plots the values onto a linear scale graph and works, however trying to change 'plot' with 'semilogy' outputs a blank graph.
hold on;
for i = 1:10
[val1(i), val2, val3, val4] = myFunct(i, fileName);
end;
plot(val1);
hold off;
What do I need to change to create a Y scale that is logarithmic?
Edited code:
hold on;
for i = 1:10
[val1(i), val2, val3, val4] = myFunct(i, fileName);
end;
val1(1) = 0.000001; %index 1 is always zero, index 2 may or may not be zero
val1(2) = 0.000001;
semilogy(val1);
hold off;
Output of the above code:
Try this:
% Calculate
for i = 1:10
[val1(i), val2, val3, val4] = myFunct(i, fileName);
end
% Plot
figure;
plot(val1+eps);
set(gca, 'YScale','log');
The hold on command prevents the figure from being updated from the regular plot you did before to semilogy. To solve this you should close your figure and run the code again.
Note that there is no reason to use hold commands if you only have one plotting command. The purpose of hold is to enable several plotting commands to be overlayed in the same figure.

Subplots of multidimensional arrays in Matlab

I have a 10x10x10 array, z. How do I plot everything in the SAME window so that I would have the 3 plots for z(:,:,1) and below it the three plots for z(:,:,2) etc.?
This is what I have so far:
for i = 1:10
z=z(:,:,i);
figure(i)
subplot(1,2,1)
surf(z)
%code, obtain new array called "new1"...
subplot(1,2,2)
surf(new1)
%code, obtain new array called "new2"...
subplot(1,3,3)
surf(new2)
end;
I think the first two subplots are supposed to be subplot(1,3,1) and subplot(1,3,2). Also, try inserting hold on after each subplot command --- this should allow you to keep whatever has been plotted before.
for i = 1:10
z=z(:,:,i);
figure(i)
subplot(1,3,1)
hold on;
surf(z)
%code, obtain new array called "new1"...
subplot(1,3,2)
hold on;
surf(new1)
%code, obtain new array called "new2"...
subplot(1,3,3)
hold on;
surf(new2)
end;
What is new1 and new2? Are they the same for all rows? Or also 3D arrays?
I think you need something like this:
for i = 1:10
subplot(10*3,3,(i-1)*3+1)
surf(z(:,:,i))
subplot(10*3,3,(i-1)*3+2)
surf(new1)
subplot(10*3,3,(i-1)*3+3)
surf(new2)
end
Or more generally for variable size of z:
N = size(z,3);
for i = 1:N
subplot(N*3,3,(i-1)*3+1)
surf(z(:,:,i))
subplot(N*3,3,(i-1)*3+2)
surf(new1)
subplot(N*3,3,(i-1)*3+3)
surf(new2)
end