Subplots within a Tabbed figure - matlab

For the following script, the subplots/plots are going behind the tab, when executed. How can this be fixed?
h.mainfig = figure();
h.tabgroup = uitabgroup(h.mainfig, 'Position', [.05 .1 .9 .8]);
ntabs = 4;
for ii = 1:ntabs
h.tab(ii) = uitab(h.tabgroup, 'Title', sprintf('Tab_%i', ii));
for jj=1:2
ax(jj)=subplot(2,1,jj);plot(1:10,sin(1:10));
end
linkaxes(ax,'x');
end

This is due to a wrong call to subplot; it looks like Matlab creates too many axes and for some reason they are placed over the tabs.
A safe way to fix this is first create an axes right before entering the nested for-loop, then the subplots will be placed correctly.
Sample code:
clear
clc
close all
mainfig = figure();
tabgroup = uitabgroup(mainfig, 'Position', [.05 .1 .9 .8]);
for k = 1:4
tab(k)=uitab(tabgroup,'Title', sprintf('Tab_%i', k));
axes('parent',tab(k))
for jj = 1:2
subplot(2,1,jj);
plot(1:10,(1:10).^k);
end
end
Few screenshots:
and
Yay!

Related

How to plot an array using a for loop?

I want to plot inside a for loop. I tried the following code also used hold on but the plot is still blank. I don't know where I am getting wrong.
M2 = true(21, 6);
M2(1:2, 3:5) = false;
R = [0.5:0.1:2.5];
H=[0:5:25];
m=21,
n=6,
for i=1:m
for j=1:n
if M(i,j)==0
plot(H(i),R(j), 'color', 'r')
drawnow();
end
end
end
As Ander Biguri already said, the plot function actually does not draw anything when you provide only one point and do not specify any markers.
But, if you want to create some animated plot, that one of the points is displayed at a time:
h = scatter(0, 0, 'r');
xlim([min(H) max(H)]);
ylim([min(R) max(R)]);
for i=1:m
for j=1:n
if M(i,j)==0
set(h, 'xdata', H(i), 'ydata', R(j));
pause(0.5);
drawnow();
end
end
end
Or if you want to show all point together, you don't even need a loop:
[HH, RR] = meshgrid(H, R);
scatter(HH(~M), RR(~M), 'r');
xlim([min(H) max(H)]);
ylim([min(R) max(R)]);

How to speed up a very slow animated plot in MATLAB

I'm trying to create an animated plot but my code is very slow, perhaps the method I'm using is too naive. In the below example, I have 4 subplots each with 3 lines, which I update in a 'time' loop.
clc;clear;close all;
state = {'$x-Position$','$x-Velocity$','$y-Position$','$y-Velocity$'};
ylabels = {'$x$','$\dot{x}$','$y$','$\dot{y}$'};
options1 = {'interpreter','latex'};
options2 = {'interpreter','latex','fontsize',20};
maxT = 300;
for pp = 1:4
hh1(pp)=subplot(2,2,pp);
xlabel('$t$',options2{:});
ylabel(ylabels{pp},options2{:});
title(state{pp},options1{:})
xlim([0 maxT])
hold on
end
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
for k = 2:maxT
for p = 1:4
plot(hh1(p),k-1:k,x(p,k-1:k),'b','linewidth',2)
plot(hh1(p),k-1:k,z(p,k-1:k),'m')
plot(hh1(p),k-1:k,x_est(p,k-1:k),':k','linewidth',2)
end
drawnow;
end
As can be seen from the profiler output, the drawnow is killing the time. Is there any way I can be more efficient in creating this animation?
Because you want an animation, there is no alternative to using drawnow to update the frame. However, it's not drawnow in particular which is slowing you down - the profiler can be misleading... drawnow simply updates all of the graphics changes since the last re-draw, which in your case is a dozen new plots!
You'll find that hold is pretty slowing. For instance if you're wiser about your holding, remove the existing hold on and only hold when actually plotting
% ... above code the same but without 'hold on'
for p = 1:4
hold(hh1(p), 'on');
% plots
hold(hh1(p), 'off');
end
This saves ~10% time on my PC (12.3sec down to 11.3sec).
The real speed up comes from removing hold entirely, along with all of the individual plot calls! This method also doesn't touch the line formatting which will help with speed. See a previous question about updating plot data here.
Simply update the plot data instead of adding plots. This gives me a speedup of ~68% (12.3sec down to 4.0sec).
% ... your same setup
% Initialise plot data
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
plts = cell(4,3);
hh1 = cell(4,1);
% Loop over subplots and initialise plot lines
for p = 1:4
hh1{p}=subplot(2,2,p);
xlabel('$t$',options2{:});
ylabel(ylabels{p},options2{:});
title(state{p},options1{:})
xlim([0 maxT])
% Hold on to make 3 plots. Create initial points and set line styles.
% Store the plots in a cell array for later reference.
hold on
plts{p,1} = plot(hh1{p},1:2,x(p,1:2),'b','linewidth',2);
plts{p,2} = plot(hh1{p},1:2,z(p,1:2),'m');
plts{p,3} = plot(hh1{p},1:2,x_est(p,1:2),':k','linewidth',2);
hold off
end
% March through time. No replotting required, just update XData and YData
for k = 2:maxT
for p = 1:4
set(plts{p,1}, 'XData', 1:k, 'YData', x(p,1:k) );
set(plts{p,2}, 'XData', 1:k, 'YData', z(p,1:k) );
set(plts{p,3}, 'XData', 1:k, 'YData', x_est(p,1:k) );
end
drawnow;
end
Now the plotting is pretty optimised. If you want the animation to be even quicker then just plot every 2nd, 3rd, ..., nth timestep instead of every timestep by using for k = 2:n:maxT.

Playing .avi in linux

I have written a code to save two movies in Matlab. The problem is that, the movie "graphh.avi" is consist of first movie("chert") also. I want it to show just graphs and not the first saved movie("chert.avi").
Could anyone help? Any answer is highly appreciated.
clear all
close all
cla
h = plot(x, y, '.g', 'MarkerSize', 10);
set(gca,'Color',[0 0 0]);
set(gcf,'doublebuffer','on')
set(gca,'YTick',[]);
set(gca,'XTick',[]);
plot(x,y,'.g','markersize',10)
drawnow
currFrame = getframe;
writeVideo(vidObj,currFrame);
h = plot(x, y, '.g', 'MarkerSize', 10);
drawnow
hist(blocksize)
currFrame = getframe;
writeVideo(vid,currFrame);
end
close(vidObj);
close(vid)
The code after doing the first answer becomes as below. The problem solved but there is another problem now: black movie with green points became so messy.
clear all
close all
l = 20;
r = 3;
v = 0.5;
dt = 1;
nn=200;
figure(h1); % set figure 1 as current figure
h = plot(x, y, '.g', 'MarkerSize', 10);
set(gca,'Color',[0 0 0]);
set(gcf,'doublebuffer','on')
set(gca,'YTick',[]);
set(gca,'XTick',[]);
plot(x,y,'.g','markersize',10)
drawnow
currFrame = getframe(h1); % gets only figure 1
writeVideo(vidObj,currFrame);
h = plot(x, y, '.g', 'MarkerSize', 10);
drawnow
figure(h2); % set figure 2 as current figure
hist(blocksize)
currFrame = getframe(h2); % gets only figure 2
writeVideo(vid,currFrame);
end
close(vidObj);
close(vid);
Use figures handles when calling getframe. See how I modified your code:
% some code...
vvy = v.*sin(tetha);
h1 = figure('Color',[0 0 0])
axis([0 l 0 l])
% some more code...
h2 = figure
hold on
vid = VideoWriter('graphh.avi');
% and more code...
% for loop
figure(h1); % set figure 1 as current figure
% plot whatever on this figure
currFrame = getframe(h1); % gets only figure 1
writeVideo(vidObj,currFrame);
% blah blah...
figure(h2); % set figure 2 as current figure
% plot whatever on this figure
currFrame = getframe(h2); % gets only figure 2
writeVideo(vid,currFrame);
% end of loop
EDIT:
in your modified code you're calling h = plot(x, y, '.g', 'MarkerSize', 10); three times in a row for no reason, so get rid of it. the problem you encountered stems from plotting another set of point in addition to the previous one, so the axes get filled with points. One solution for that is to use set(h,'XData',x,'YData',y) like so:
figure(h1); % set figure 1 as current figure
set(gca,'Color',[0 0 0]);
set(gcf,'doublebuffer','on')
set(gca,'YTick',[]);
set(gca,'XTick',[]);
if exist('h','var') && ishandle(h) % if handle exists just change coordinates
set(h,'XData',x,'YData',y)
else % only for the first time you plot that
h = plot(x, y, '.g', 'MarkerSize', 10);
end
drawnow
currFrame = getframe(h1); % gets only figure 1
writeVideo(vidObj,currFrame);

MATLAB - hold on for subplot between different figures (Solved, but may have issues on Version R2012a)

I'm new to MATLAB, and I've been searching around for what I'm trying to do, but the results don't fit quite well.
I'm graphing plots of variations of transfer functions, the code I've done is below:
omega = 3;
K = omega * omega;
for zeta = 0.1:0.1:2
sys = tf(K,[1 2*zeta*omega omega]);
figure();
subplot(1,2,1);
step(sys);
title('Step response');
[num,den] = tfdata(sys, 'v');
disp(den);
r = roots(den);
subplot(1,2,2);
%hold (subplot(1,2,2), 'on');
plot(real(r), imag(r), 'o');
title('Pole Locations in Complex Plane');
end
Each time the loop runs, it will create a new figure. The first subplot should be unique for every figure, but the second subplot should plot the accumulation of all points (roots of denominator of all transfer functions) from figures before it. I tried to use hold (subplot(1,2,2), 'on'); to keep the second subplot, but it didn't work. My thought is that because the subplots are different figures, hold on cannot be used.
How can I solve this problem? Any help will be great.
A solution is to use 'Tag' in your subplot. I am using your code to edit:
omega = 3;
K = omega * omega;
for zeta = 0.1:0.1:2
sys = tf(K,[1 2*zeta*omega omega]);
figure();
sb = subplot(1,2,1);
set(sb, 'Tag', 'daddy') % Something to tag with - memorable
step(sys);
title('Step response');
[num,den] = tfdata(sys, 'v');
disp(den);
r = roots(den);
sb = subplot(1,2,2);
set(sb, 'Tag', 'child')
sb = findobj('Tag','child'); % Use MATLAB methods to find your tagged obj
set(sb,'NextPlot','add'); % set 'NextPlot' property to 'add'
plot(real(r), imag(r), 'o');
title('Pole Locations in Complex Plane');
end
DOes this work for you? btw. This is also in MATLAB central. You should use that too.

MATLAB update waitbar

I am trying to implement a "percent complete" bar in a MATLAB program, using the waitbar function. However, I am having trouble with it. Here is the code that I have currently:
in my GUI
POSITION = [53.3333 20 188.5446 20];
H = uiwaitbar(POSITION);
for percentageDone = 0;
uiwaitbar(H,percentageDone);
end
then
function h = uiwaitbar(varargin)
if ishandle(varargin{1})
ax = varargin{1};
value = varargin{2};
p = get(ax,'Child');
x(3:4) = value;
set(p,'XData',x)
return
end
pos = varargin{1};
bg_color = [1 1 1];
fg_color = [0 .5 0];
h = axes('Units','pixels',...
'Position',pos,...
'XLim',[0 100],'YLim',[0 1],...
'XTick',[],'YTick',[],...
'Color',bg_color,...
'XColor',bg_color,'YColor',bg_color);
patch([0 0 0 0],[0 1 1 0],fg_color,...
'Parent',h,...
'EdgeColor','none',...
'EraseMode','none');
end
Elsewhere in the script, I have a KeyPressFcn callback, in which the user inputs the answer to their questions. At the end of this callback, for every correct answer I want the waitbar to fill up a little. However, no matter what values I assign to percentageDone variable the waitbar in the GUI does not change at all.
Can anybody help me with this?
I'm confused, you say you are using the builtin function WAITBAR, but then you seem to be implementing one yourself..
Anyway, here is a rather useless example that shows a custom progress bar. Just keep pressing "next" :)
function progressBarDemo()
%# a figure and a plot area
hFig = figure('Menubar','none');
hAxPlot = axes('Parent',hFig, 'Box','on', ...
'Units','normalized', 'Position',[0.1 0.2 0.8 0.6]);
hLine = line('Parent',hAxPlot, 'XData',1:1000, 'YData',nan(1,1000), ...
'Color','b');
%# next button
uicontrol('Style','pushbutton', 'String','next', ...
'Callback',#buttonCallback);
%# progress bar axis
x = linspace(0, 1, 13+1); %# steps
hAx = axes('Parent',hFig, 'XLim',[0 1], 'YLim',[0 1], ...
'XTick',[], 'YTick',[], 'Box','on', 'Layer','top', ...
'Units','normalized', 'Position',[0 0.9 1 0.1]);
hPatch = patch([0 0 x(1) x(1)], [0 1 1 0], 'r', 'Parent',hAx, ...
'FaceColor','r', 'EdgeColor','none');
hText = text(0.5, 0.5, sprintf('%.0f%%',x(1)*100), ...
'Parent',hAx, 'Color','w', 'BackgroundColor',[.9 .5 .5], ...
'HorizontalAlign','center', 'VerticalAlign','middle', ...
'FontSize',16, 'FontWeight','bold');
counter = 2;
%# next button callback function
function buttonCallback(src,evt)
%# draw another random plot
set(hLine, 'YData',cumsum(rand(1000,1)-0.5))
%# update progress bar
set(hPatch, 'XData',[0 0 x(counter) x(counter)])
set(hText, 'String',sprintf('%.0f%%',x(counter)*100))
%# terminate if we have reached 100%
counter = counter + 1;
if counter > numel(x)
set(src, 'Enable','off', 'String','Done')
return
end
end
end
You're probably just missing a drawnow call after setting the XData property, to force a flush of the graphics events queue. If this does not fix your problem, then include enough code to reproduce the symptoms.
Have you tried using Progressbar from the File Exchange? It might save you a lot of hassle. I've always had good results with it.
Do you first create the waitbar? Something like this:
h = waitbar(0, '1', 'Name', 'My progress bar', 'CreateCancelBtn', 'setappdata(gcbf, ''canceling'', 1)');
After that, to update the waitbar:
Edit: fixed bug with text output: percentageDone must be multiplied by 100.
waitbar(percentageDone, h, sprintf('Already %d percent ready!', 100*percentageDone));