I am trying to plot a cobweb diagram using the following code:
function cobweb(f,a,b,x0,x1,N)
x(1)=0.2; % plot orbit starting at x0
for i=1:100
x(i+1)= 3*x(i)*(1-x(i));
plot([x(i),x(i)],[x(i),x(i+1)]);
hold on
plot([x(i),x(i+1)],[x(i+1),x(i+1)]);
hold on
end
hold on
r = 3;
x = 0:0.01:1; %// set some x
f = (r.*x.*(1-x));
hold on
plot(x,f,'k')
hold on
plot([x(1), 0], [x(1), 3*x(1)*(1-x(1))])
I want the first line to be drawn up from the x-axis, however it's currently starting from (x(1),x(1)), where x(1) is the initial point.
I understand that this is because of my loop so I tried adding an extra plot for the initial line by plot([x(1), 0], [x(1), 3*x(1)*(1-x(1))]), however I still get the same result.
The function I am plotting is f = 3x(1-x).
You probably want to move that line:
plot([x(1), 0], [x(1), 3*x(1)*(1-x(1))])
before the for loop and add a hold on after it before you enter the loop. You can then remove the other hold on inside the for loop and further down the code, as they are redundant.
Related
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:
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
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.
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.
I was wondering if anyone knew how to do an animation plot of
x = (dataset of 1000 points)
y = (dataset of 1000 points)
plot(x,y)
big problem is these are datasets that i am trying to plot , or x,y coordinates as opposed to a function which I would know how to plot via an animation.
I tried to do frames in a for loop but it gave me dots and didn't join them in a line graph so I couldn't really watch the path being traced out.
code I used was
for i = 1:length(DATASET1)
pause(0.1)
plot(DATASET1(i),DATASET2(i))
draw on
end
If what you want is for the plot to "grow" point by point: the easiest way is to create an empty plot and then update its XData and YData properties at each iteration:
h = plot(NaN,NaN); %// initiallize plot. Get a handle to graphic object
axis([min(DATASET1) max(DATASET1) min(DATASET2) max(DATASET2)]); %// freeze axes
%// to their final size, to prevent Matlab from rescaling them dynamically
for ii = 1:length(DATASET1)
pause(0.01)
set(h, 'XData', DATASET1(1:ii), 'YData', DATASET2(1:ii));
drawnow %// you can probably remove this line, as pause already calls drawnow
end
Here's an example1 obtained with DATASET1 = 1:100; DATASET2 = sin((1:100)/6);
1 In case someone's interested, the figure is an animated gif which can be created by adding the following code (taken from here) within the loop, after the drawnow line:
frame = getframe(1);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if ii == 1;
imwrite(imind,cm,filename,'gif','Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append');
end
Looks like you were close. Not sure draw on is any command though.
See if the code here inspires you to solve your case -
%// Sample x and y values assumed for demo.
x = 1:1000;
y = x.^2;
%// Plot starts here
figure,hold on
%// Set x and y limits of the plot
xlim([min(x(:)) max(x(:))])
ylim([min(y(:)) max(y(:))])
%// Plot point by point
for k = 1:numel(x)
plot(x(k),y(k),'-') %// Choose your own marker here
%// MATLAB pauses for 0.001 sec before moving on to execue the next
%%// instruction and thus creating animation effect
pause(0.001);
end
Since R2014b, you can work with annimatedline object (doc and how-to) that is meant to handle animated graphs pretty well. Basically, the annimatedline object has a addpoints function that adds new points to the line without having to redefine the existing points, along with a clearpoints function that clears lines for more complex animations.
Here is an example:
h = animatedline;
axis([0,4*pi,-1,1])
x = linspace(0,4*pi,1000);
y = sin(x);
for k = 1:length(x)
addpoints(h,x(k),y(k));
drawnow
end