Plotting an ode solution when clicking on the axes - matlab

I am attempting to write some code that will allow me to click on the axes and the ode solution with the clicked point as the initial condition will be plotted. Here is what I have tried thus far:
function myui
clc
close all
xmin=2;
xmax=10;
ymin=-4;
ymax=4;
f=#(t,y) y^2-t
fig=figure;
ax=axes('Units','pixels',...
'XLim',[xmin,xmax],...
'YLim',[ymin,ymax],...
'ButtonDownFcn',#plotode)
function plotode(source,event)
initcond=get(ax,'CurrentPoint');
initcond=initcond(1,1:2)
[t,y]=ode45(f,[initcond(1),xmax],initcond(2));
plot(t,y)
hold on
[t,y]=ode45(f,[initcond(1),xmin],initcond(2));
plot(t,y)
axis([xmin xmax ymin ymax])
hold off
end
end
I have several questions.
I can only click one time. I'd like to click several times and draw several curves.
The curve can shoot to plus or minus infinity quite quickly, so I'd like to halt ode 45 if it leaves my axes window.
I'd appreciate it if someone could share some complete code that works as I could really learn quite a bit.
Thanks.

All,
I've added some steps to my code that performs the task I wished to see.
function myui
% clear command window and close all open figures
clc
close all
% define our function
f=#(t,y) y^2-t;
% axes boundaries
tmin=2;
tmax=10;
ymin=-4;
ymax=4;
% steps for quiver
tstep=20;
ystep=20;
% create a figure window
fig=figure;
% create axes with limits
ax=axes('Units','Normalized',...
'XLim',[tmin,tmax],...
'YLim',[ymin,ymax]);
% create direction field with quiver
[T,Y]=meshgrid(linspace(tmin,tmax,tstep),...
linspace(ymin,ymax,ystep));
S=Y.^2-T;
L=sqrt(1+S.^2);
quiver(T,Y,1./L,S./L,0.5,'r','ButtonDownFcn',#plotode)
axis tight
hold on
% set ButtonDownFcn on axes ax
set(ax,'ButtonDownFcn',#plotode);
% function plots initial conditions and solutions
function plotode(source,event)
warning('off','MATLAB:ode45:IntegrationTolNotMet');
initcond=get(ax,'CurrentPoint');
initcond=initcond(1,1:2);
[t,y]=ode45(f,[initcond(1),tmax],initcond(2));
plot(t,y,'b','linewidth',1)
[t,y]=ode45(f,[initcond(1),tmin],initcond(2));
plot(t,y,'b','linewidth',1)
plot(initcond(1),initcond(2),'ro')
set(ax,'XLim',[tmin,tmax],'YLim',[ymin,ymax],...
'ButtonDownFcn',#plotode);
end
end
It produces this image when I click on the axes with my mouse several times.
I'd still love to listen to some instruction and suggestions.
Thanks.

Related

How to delete existing graph and plot a new graph?

In my program, I am doing a least squared optimization problem, i.e. \sum_{i} (y_{i}-y_{i}^{market})^2. At the same time, I want to plot the modeled y_{i} against the y_{i}^{market}. To program it which suit my needs, I define OutputFcn during my optimization and write the code as follow: (Suppose x represent the x-coord
figure()
hold on
plot(x,[y_{1},y_{2},...,y_{n}]);
plot(x,[y_{1}^{market},y_{2}^{market},...,y_{n}^{market}]);
When I run the program, I can draw a new calculated curves on the same plot. Unfortunately, the final plot is difficult to view it. In order to make it to be visible to read, I want to delete the curve (calculated values) obtained in the previous iteration and plot the new curve (calculated values) in the new iteration on the existing plot. What should I do to the current code to fulfill my needs?
Something like:
hold on
for iterations
clf
% PLOT STUFF
drawnow
pause(0.1)
end
clf clears the figure
drawnow forces drawing on screen
pause stops execution for a bit so you have time to see it.

Matlab doesn't save the new dimension of the plot

I'm trying to save a figure with a no-default dimension, but I always obtain the default size plot.
figure
for i=1:6
for j=1:4
subplot(6,4,j+(i-1)*4)
[...]
end
end
w=600; h=800;
set(gcf,'Position',[30 60 w h]);
set(gcf, 'PaperUnits', 'centimeters');
set(gcf,'PaperPositionMode','manual')
print('test','-depsc');
It is mainly a 6-by-4 subplot. I looked for a solution on internet, I found many comments about Position, PaperUnits, PaperPositionMode, but none has worked so far. The only solution that works is when I export as .fig.
What I actually realized, is that after the set(gcf,'Position',[30 60 w h]) the window dimension of the plot is correct, but the subplot are squeezed like when the dimension is the default. If I just insert a pause and manually resize the window (even by almost nothing), the subplots expand nicely within the larger window. But still, with the print command the result is not the desired one.
I tried also with saveas and I got the same result.
Ah, if I manually save the figure, it works perfectly, but, of course, I need to automatize the process!
Thanks for your help!
Although i can't reproduce this behaviour as MATLAB 2014b automatically handles axes resizing, i'll still post an answer, that may need some adjustments.
Basically, what you need to do is :
% Get a handle to your figure object
Myfig=gcf;
% Get all of your figure Children - Warning : if you have a global
% legend in your figure, it will belong to your figure Children and you
% ll have to ignore it
AllChildren=get(Myfig,'Children');
MyAxes=findobj(AllChildren,'type','axes');
% Now you have your axes objects, whose Position attributes should be in
% normalized units. What you need to do now is to store these positions
% before changing the size of your figure, to reapply them after
% resizing (the beauty of normalized positions).
Positions=zeros(size(MyAxes,1),4);
for ii=1:size(MyAxes,1)
Positions(ii,:)=get(MyAxes(ii),'Position');
end
% Resize your figure
w=600;
h=800;
set(gcf,'Position',[30 60 w h]);
% Reuse the positions you stored to resize your subplots
for ii=1:size(MyAxes,1)
set(MyAxes(ii),'Position',Positions(ii,:));
end
This should do the trick.

Matlab graphics do not update in successive runs

I have created a matlab figure plot and then plotted several rectangles.
for i=1:size(rect,2)/2
rectangle('Position',[rect(i)-1,rect(i+2*size(rect,2)),5,2])
end
Now i want to loop them thru a for-loop simulating the passage of time.
daspect([1,1,1])
for t=0:0.1:6.28
for i=1:size(rect,2)/2
rectangle('Position',[rect(i)-1-2*sint(t),rect(i+2*size(rect,2))-2*sin(t),5,2])
end
pause(0.1)
end
The trouble with the rectangle command is that for t=0, the figures are good but for t=0.1, the new figures overlap with figures of t=0 thus spoiling the graphics. What is the fix? I am not even using hold on.
What about using findobj to look for rectangles and delete them as new ones appear?
for t=0:0.1:6.28
for i=1:size(rect,2)/2
hRect = findobj('Type','rectangle')
delete(hRect)
rectangle('Position',[rect(i)-1-2*sint(t),rect(i+2*size(rect,2))-2*sin(t),5,2])
end
pause(0.1)
end
Something like this should work to clear the rectangle before plotting the next one
for t=0:0.1:6.28
delete(h)
for i=1:size(rect,2)/2
h=rectangle('Position',[rect(i)-1-2*sint(t),rect(i+2*size(rect,2))-2*sin(t),5,2])
end
pause(0.1)
end

Matlab: replace one plot maintaining others

I have a figure in which I plot some disperse points and then a trajectory. I want to switch between different trajectories by plotting them in the same figure as the points, but without creating new figures, i.e., "erasing" the first trajectory and then plotting the new one.
Is there a way of doing this?
Perhaps this little demo will be helpful:
xy = rand(20,2);
figure
% Plot first iteration and output handles to each
h = plot(xy(:,1),xy(:,2),'b.',xy(1:2,1),xy(1:2,2),'r-');
axis([0 1 0 1])
% Update second plot by setting the XData and YData properties of the handle
for i = 2:size(xy,1)-1
set(h(2),{'XData','YData'},{xy(i:i+1,1),xy(i:i+1,2)})
drawnow
pause(0.1);
end
You should read up on handle graphics in Matlab and the get and set functions.

Show more than one figure one by one in MATLAB

I have 20 figures to display one after another like slide show. Can I do it using Imshow in Matlab? Any sort of help will be appreciated.
Couple options:
Open a figure for each plot
Open and close a figure for each plot
Reuse one figure
Open a figure for each plot
for i=1:20
h = figure;
%plot here
pause
end
Open and close a figure for each plot
for i=1:20
h = figure;
%plot
pause
close gcf
end
Reuse one figure
h=figure
for i=1:20
clf(h);
%plot
pause
end
OR depending on what you are plotting, you can use the refreshdata method.
If you use #Jonas' method, and if you have dual monitors, you have to force the figure to the main monitor for getframe to actually work, as per. You can do this via:
ff=figure;
movegui(ff)
You can use MOVIE to display plots/images one after the other. For this, you create the figures, capture them via GETFRAME, and then you can call movie. See this example from the help for getframe
Z = peaks; surf(Z)
axis tight
set(gca,'NextPlot','replacechildren');
for j = 1:20
surf(sin(2*pi*j/20)*Z,Z)
F(j) = getframe;
end
movie(F,20) % Play the movie twenty times