MATLAB update waitbar - matlab

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));

Related

Error in MATLAB colorbar tick labeling?

I am plotting 9 subplots as shown in figure below with one color bar for three subplots.
Here I want to show the highest value in color bar as > value, surprisingly when I manually edit the tick label as h.TickLabels{end} = ['>' h.TickLabels{end}]; the color bar starts repeating the value.
When I remove h.TickLabels{end} = ['>' h.TickLabels{end}]; the color bar show no problem. When I change the figure size in set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 8 8]) as [0 0 5 5] colorbar labeling again changes.
How to resolve this error?
Below are my working example and output image:
data = [1 2 3; 5 7 3; 12 29 14; 1 7 3; 2 8 3; 5 4 1; 2 2 1; 2 3 1; 1 5 2];
for i=1:9
subplot(3, 3, i)
plot(data(i,:));
if ismember(i, [1:3])
caxis([0 20])
if i==3
h = colorbar('Fontsize', 6, 'LineWidth', 0.15, 'TickDirection', 'out',...
'TickLength', 0.02);
set(h, 'Position', [.935 .6867 .01 .2533])
h.TickLabels{end} = ['>' h.TickLabels{end}];
end
end
if ismember(i, [4:6])
caxis([0 6])
if i==6
h = colorbar('Fontsize', 6, 'LineWidth', 0.15, 'TickDirection', 'out',...
'TickLength', 0.02);
set(h, 'Position', [.935 .3733 .01 .2533])
h.TickLabels{end} = ['>' h.TickLabels{end}];
end
end
if ismember(i, [7:9])
caxis([0 4])
if i==9
h = colorbar('Fontsize',6, 'LineWidth', 0.15, 'TickDirection', 'out',...
'TickLength', 0.02);
set(h, 'Position', [.936 .06 .01 .2533])
h.TickLabels{end} = ['>' h.TickLabels{end}];
end
end
end
set(gcf, 'PaperUnits', 'inches', 'PaperPosition', [0 0 8 8])
print('test', '-djpeg', '-r300')
close all
Why is this happening?
Manually changing the TickLabels changes the TickLabelsMode property to manual and the control gets lost for zooming/panning/resizing the figure window.
How can this be fixed?
Use a listener that will adjust the ticks itself. It may require undocumented features. You can take ideas on implementing a listener for colorbar from Yair Altman's this utility. This is for ticklabels of axes and would require some tweaking to work for colorbar.
or a relatively simpler approach would be to:
Change the 'TicksMode' to manual i.e.:
Before this line h.TickLabels{end} = ['>' h.TickLabels{end}];, include
this line:
set(h, 'Ticks', get(h,'Ticks')); %or h.Ticks = h.Ticks; for >= R2014b
This ensures that the ticks remain the same and hence the number of ticks also remains the same and therefore ticklabels will not malfunction on zooming/panning/resizing the figure window.
If you want to have more or less ticks than you originally get then set them as:
%Adjust the increment as desired. I set it as 1 (default)
set(h, 'Ticks', in1:1:in2); %or h.Ticks = in1:1:in2; for >= R2014b
%where in1 and in2 are the 1st and 2nd input args you used for caxis respectively
or if you're only concerned with the output jpeg file and your ticklabels are malfunctioned in the output image file then:
Set the PaperUnits / PaperPosition at the beginning of the plotting instead of doing that at the end. This will not automate the ticklabels but will only make the temporary adjustment.
As Sardar wrote, the only option to solve this automatically, and not lose the auto-scaling of the ticks when the figure window size is changed is to add a listener. This is how to do it:
Copy the following function to an m-file, and save it in the folder you work on this figure (i.e. your current path):
function set_cb_lables
% add '>' to the last tick label in all colorbars
h = findobj(gcf,'Type','Colorbar'); % get all colorbars handels
set(h,{'TickLabelsMode'},{'auto'}); % change thier mode to 'auto'
tiklbl = get(h,{'TickLabels'}); % get all tick labels after the change
for k = 1:numel(tiklbl)
tiklbl{k}{end} = ['>' tiklbl{k}{end}]; % add '>' to the last tick
end
set(h,{'TickLabels'},tiklbl); % replace the current ticklabels with tiklbl
end
Then, in your code, add this line after the loop:
set(gcf,'SizeChangedFcn','set_cb_lables'); % aplly the function 'set_cb_lables' upon any size change
This will add '>' automatically to the last tick label upon any resizing of the figure.
This solution is better than just getting the ticks before adding the '>' because now if the window gets bigger, the colorbar is populated automatically with more ticks.

delete a line in a for loop with MATLAB

i'm struggling with this matter probably
i'm just starting with Matlab.this is my code,i
wanna rotate a two links arm,using rotation matrix:
clear all
close all
clc
myaxes = axes('Xlim',[-1 1 ],'Ylim',[-1 1],'Zlim',[-1 1]);
view(3);
grid on;
axis equal;
hold on
xlabel('X')
ylabel('y')
zlabel('Z')
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 =(0:0.5:15) ;
for i = 1:length(alfa_1)
M3(:,:,i) = [cosd(alfa_1(i)) -sind(alfa_1(i)) 0
sind(alfa_1(i)) cosd(alfa_1(i)) 0
0 0 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5;0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1;0; 0];
figure(1)
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
hold on
M3_1(:,:,i) = [cosd(alfa_2(i)) -sind(alfa_2(i)) 0
sind(alfa_2(i)) cosd(alfa_2(i)) 0
0 0 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)],[P_1(2,i,i) P_2_2(2,i,i)],[P_1(3,i,i) P_2_2(3,i,i)],'color','r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
hold on
end
should i use delete function to obtain an animation without plotting
all the lines but only the current line?!?.
thanks in advance for your help and support.
You can use the drawnow function in MATLAB for this purpose. This function can be used inside a for loop to force a plot to be rendered every iteration, instead of being stored in a buffer until after the loop.
Update figure window and execute pending callbacks
An example: for a simpler code consider a object moves on circle
t = 0:0.05:2*pi;
x = cos(t);
y = sin(t);
for k=1:length(t)
plot(x(k),y(k),'ko')
axis([-1.2 1.2 -1.2 1.2])
axis square
drawnow
end
Please note the axis function in this method. If the axis lines are deleted from the code then, in every iteration, the axis limits will change and the animation is not smooth.
What about your code:
clear all
close all
clc
view(3);
xlabel('X');
ylabel('y');
zlabel('Z');
P_0 = [0; 0; 0] ;
P_1 = [-0.5;0; 0] ;
P_2 = [-1; 0; 0] ;
alfa_1 = 0:1:30 ;
alfa_2 = (0:0.5:15) ;
for i = 1:length(alfa_1)
% Calculate new values for plotting
M3(:,:,i) = [cosd(alfa_1(i)), -sind(alfa_1(i)), 0
sind(alfa_1(i)), cosd(alfa_1(i)), 0
0 , 0 , 1] ;
P_1(:,i,i) = M3(:,:,i)*[-0.5; 0; 0] ;
P_2(:,i,i) = M3(:,:,i)*[-1; 0; 0] ;
% Clear figure 1 and hold for all plots
figure(1)
clf
% Hold only needs to be applied around plots on same axes
hold on
line([0 P_1(1,i,i)],[0 P_1(2,i,i)],[0 P_1(3,i,i)]);
scatter(P_1(1,i,i),P_1(2,i,i));
% Recalculate plotting values
M3_1(:,:,i) = [cosd(alfa_2(i)), -sind(alfa_2(i)), 0
sind(alfa_2(i)), cosd(alfa_2(i)), 0
0 , 0 , 1] ;
P_2_2(:,i,i) = M3_1(:,:,i)*P_2(:,i,i);
line([P_1(1,i,i) P_2_2(1,i,i)], [P_1(2,i,i) P_2_2(2,i,i)], [P_1(3,i,i) P_2_2(3,i,i)], 'color', 'r');
scatter(P_2_2(1,i,i), P_2_2(2,i,i))
% Set axis limits for consistency in all plots, show grid
axis([-2 2 -2 2])
grid on
% Hold off is good practice to avoid later accidental plotting on same axes
hold off
% Draw from the buffer
drawnow
end
you can save(if you want) this animation with getFrame function and play it with movie function
and another function may helps you is comet.

Subplots within a Tabbed figure

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!

Adding text to a figure - MATLAB

I wrote a code that shows a figure devided to 2 parts;
the first one showing the main image, and the second one is a slider showing the rest of the images.
Now I need to add text to the main part (Like "Help" or "guide" text).
How can I do it?
This is my main sub-code:
%# design GUI
numSubs = 10; % Num of sub-images.
mx = numImgs-numSubs+1;
hFig = figure('Menubar','none');
% The Main Image:
hAx = axes('Position',[0 0.3 1 0.8], 'Parent',hFig);
hMainImg = imshow(img, 'Parent',hAx);
% the slider
hPanel = uipanel('Position',[0 0.04 1 0.26], 'Parent',hFig);
uicontrol('Style','slider', 'Parent',hFig, ...
'Callback',#slider_callback, ...
'Units','normalized', 'Position',[0 0 1 0.04], ...
'Value',1, 'Min',1, 'Max',mx, 'SliderStep',[1 10]./mx);
subImg = zeros(numSubs,1);
for i=1:numSubs
%# create axis, show frame, hookup click callback
hAx = axes('Parent',hPanel, ...
'Position',[(i-1)/numSubs 0 1/numSubs 1]);
% Load img number i
name=frames(i).name;
img=imread(name,'jpg');
subImg(i) = imshow(img, 'Parent',hAx);
value = i;
set(subImg(i), 'ButtonDownFcn',{#click_callback value})
axis(hAx, 'normal')
hold off;
end
Any suggestions?
Thanks in advance.
Use this construction:
hT = uicontrol('style', 'text', 'string', 'HELLO WORLD', 'position', [...])
It will create static text in the figure at position position. You can use all the regular options for uicontrols like 'parent' or 'units'.
However, since your image is in an axis, the better/easier way to do it is using
hT = text(X, Y, 'HELLO WORLD')
with X and Y the desired coordinates of the text in the axes.
You can set additional options via set:
set(hT, 'color', 'r', 'backgroundcolor', 'k', 'fontsize', 10, ...)
You can get a list of all options by issuing set(hT) on a mock text object.

Matlab - how to draw pixels on a black full screen?

I want matlab to show me a full screen, all black, and to be able to set pixels on it.
Is it even possible?
You can't totally do that using pure MATLAB code. On Windows, I tried different combinations, but the taskbar will still be on top (the one with the Start button):
%# 1)
sz = get(0, 'ScreenSize');
figure('Menubar','none', 'WindowStyle','modal', ...
'Units','pixels', 'Position', [0 0 sz(3) sz(4)])
%# 2)
figure('Menubar','none', 'Units','normalized', 'Position',[0 0 1 1])
%# 3)
hFig = figure('Menubar','none', 'Units','normalized', 'Position',[0 0 1 1]);
set(hFig, 'Units','pixels')
p = get(hFig, 'Position');
set(hFig, 'Position', [1 31 p(3) p(4)-8]);
You would have to write a MEX function and call the the Win32 API directly. Fortunately, there should be existing submissions on FEX implementing such functionality.
Here is an example of creating a full screen figure, and drawing points with the mouse. I am using the WindowAPI solution by Jan Simon
%# open fullscreen figure
hFig = figure('Menubar','none');
WindowAPI(hFig, 'Position','full');
%# setup axis
axes('Color','k', 'XLim',[0 1], 'YLim',[0 1], ...
'Units','normalized', 'Position',[0 0 1 1], ...
'ButtonDownFcn',#onClick)
The callback function:
function onClick(hObj,ev)
%# draw point
p = get(hObj,'CurrentPoint');
line(p(1,1), p(1,2), 'Color','r', 'LineStyle','none', ...
'Marker','.', 'MarkerSize',40, 'Parent',hObj)
end
Check out psychophysics toolbox. It does exactly what you are looking for and more.
Try this:
screen_size = get(0, 'ScreenSize');
buff=zeros(screen_size(3),screen_size(4));
for i=1:50
buff(screen_size(3)/2-i,screen_size(4)/2+i)=100;
end
f1 = image(buff)
colormap(gray)
set(gcf,'windowstyle','modal');
set(gcf,'OuterPosition', screen_size);
set(gcf,'position',screen_size);
set(gcf,'Units','normal', 'outerposition',[0 0 1 1])
set(gca,'Visible', 'Off', 'Position',[0 0 1 1])
Use Alt+F4 (or equivalent) to kill the window. I don't fully understand why you have to do it this way, but it is the only way I've ever found to remove the window frame and make the plot extend full screen.