Code covered by the BSD License  

Highlights from
progbar

image thumbnail

progbar

by

 

04 Oct 2001 (Updated )

progbar.m: general purpose progress bar for MATLAB

Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

[handle]=progbar(pb, progress, msg)
function [handle]=progbar(pb, progress, msg)

% progbar.m
%   general purpose progress bar for MATLAB. type 'progbar
%   demo' to get started. progbar has similar functionality
%   to the built-in "waitbar", but has better performance
%   for tight loops (since it ignores updates that come
%   faster than some fixed "period", default 100msec).
%
% USAGE:
%
% h = progbar                 initialises a new progbar (default settings)
% h = progbar(info)           initialises a new progbar
%     progbar(h,progress)     updates an existing progbar (progress in %)
%     progbar(h,progress,msg) update the progress and message on an existing progbar
%     progbar(h,-1)           closes an existing progbar (no error if already closed by user)
%
% info, if supplied, should be a structure with some
% or all of the following fields (listed as =<default>)
%
%    title='Progress'  title
%    msg=''            message
%    size=1            small integer dictating size of bar
%    period=0.1        a time in seconds dictating the minimum update
%                      rate of the progress bar
%    pos='centre'      any of 'topleft,top,top right,centreleft,centre,
%                        centreright,bottomleft,bottom,bottomright'. note
%                        american spelling accepted, but frowned upon.
%    color='blue'      RGB triple in MATLAB format, [R G B]. if you have
%                        the color tool 'rgb.m' on your path, you may use
%                        any format that rgb accepts. rgb.m is available
%                        at www.mathworks.com/matlabcentral
%    clearance=0       number between 0 and 1, affects appearance
%
% DEMOS:
%
% "progbar demo" - usage demonstration.
% "progbar perfdemo" - performance comparison with waitbar
%   (thanks to Bob Bemis).

% VERSION:  12/05/2010
% AUTHOR:   ben mitch
%
% CHANGES:
%   12/05/2010
%     * slight performance improvement suggested by Bob Bemis.
%     * some code tidying and improved commenting
%     * fixed slight bug in demo
%     * slightly improved help
%     * inspired by Bob Bemis, made changes for much
%     improved performance (twice as fast) during
%     ignored-by-time-period updates by (a) using cputime
%     instead of clock and (b) using try/catch instead of an
%     explicit call to ishandle().
%     * added perfdemo
%     * added testdemo (for testing, not for user)
%     * changed appearance to be, well, nicer
%     * new version confirmed to work in R14 (also thanks to Bob).



% update form
if nargin == 2 || nargin == 3

	% in case user has already closed it
	%
	% an alternative way to check is:
	%   if ~ishandle(pb) return; end
	%
	% this alternative is much faster IF the user HAS closed
	% the bar, but much slower if they haven't. since the user
	% closing the bar is the unlikely case, it makes more
	% sense to use the try/catch method, which is much faster
	% if the user HAS NOT closed the bar.
	try

		% get info
		info=get(pb, 'userdata');

	catch

		% ignore in that case
		return

	end

	% close
	if(progress==-1) close(pb); return; end

	% get out fast
	if (info.period)
		if (cputime - info.lastclock)<info.period return; end
		info.lastclock=cputime;
		set(pb,'userdata',info);
	end

	% check types
	if ~isnumeric(pb)
		error('pb should be a progress bar handle');
	end
	if ~isnumeric(progress)
		error('progress should be numeric');
	end

	% constrain
	if(progress<=0) progress=0.001; end
	if(progress>100) progress=100; end

	% do update
	BarHandle=get(get(pb,'Children'),'Children');
	set(BarHandle,'position',[0 0 progress 1],'visible','on');
	progress=ceil(progress-0.5);
	if isempty(info.title)
		set(pb,'name',[int2str(progress) '%']);
	else
		set(pb,'name',[int2str(progress) '% - ' info.title]);
	end

	% handle msg
	if nargin == 3
		ax=get(pb, 'children');
		ti=get(ax, 'title');
		set(ti, 'string', msg);
	end

	% ok
	drawnow
	return

end

if nargin<2

	if nargin==0 info.dummy='dummy'; end
	if nargin==1 info=pb; end

	% check type
	if isa(info, 'char')
		if strcmp(info, 'demo')
			progbar_demo
			return
		end
		if strcmp(info, 'perfdemo')
			progbar_perfdemo
			return
		end
		if strcmp(info, 'testdemo')
			progbar_testdemo
			return
		end
	end

	if ~isstruct(info)
		error('Single argument should be an info structure or ''demo''');
	end

	% extract
	if ~isfield(info,'title') info.title=''; end
	if ~isfield(info,'msg') info.msg=''; end
	if ~isfield(info,'size') info.size=1; end
	if ~isfield(info,'period') info.period=0.1; end
	if ~isfield(info,'pos') info.pos='centre'; end
	if ~isfield(info,'color') info.color=[0 0 192]/255; end
	if ~isfield(info,'clearance') info.clearance=0; end

	% check values
	if floor(info.size)~=info.size | info.size<1 | info.size>5
		error('size should be a small integer (1-5)');
	end
	if info.period<0
		error('period should not be negative');
	end
	if info.clearance<0 | info.clearance>1
		error('clearance should be between 0 and 1');
	end

	spars=get(0,'screensize');
	sl=spars(1);
	sb=spars(2);
	sw=spars(3);
	sh=spars(4);

	pw=200*info.size; % progress bar width
	ph=16*info.size; % progress bar height
	mh=~isempty(info.msg)*30;	% message bar height
	border=16;
	th=border+ph+border+mh; % total height
	tw=border+pw+border; % total width

	% check position
	switch info.pos
		case {'center','centre'}
			x=sl+sw/2;
			y=sb+sh/2;
		case {'centerleft','centreleft'}
			x=sl+sw/4;
			y=sb+sh/2;
		case {'centerright','centreright'}
			x=sl+3*sw/4;
			y=sb+sh/2;
		case {'top'}
			x=sl+sw/2;
			y=sb+3*sh/4;
		case {'topleft'}
			x=sl+sw/4;
			y=sb+3*sh/4;
		case {'topright'}
			x=sl+3*sw/4;
			y=sb+3*sh/4;
		case {'bottom'}
			x=sl+sw/2;
			y=sb+sh/4;
		case {'bottomleft'}
			x=sl+sw/4;
			y=sb+sh/4;
		case {'bottomright'}
			x=sl+3*sw/4;
			y=sb+sh/4;
		otherwise
			error(['pos ''' info.pos ''' was not recognised']);
	end

	info.lastclock=cputime;
	info.id='progbar';
	handle=figure(...
		'MenuBar','none',...
		'numbertitle','off',...
		'userdata',info,...
		'name',info.title);
	set(handle,'position',[x-tw/2 y-th/2 tw th]);
	set(handle,'resize','off');

	% get color
	color=info.color;
	if ~isempty(which('rgb.m'))
		color=rgb(color);
	end

	% check color
	if ~isa(color,'double') | size(color,1)~=1 | size(color,2)~=3
		close(handle);
		error('Unrecognised color');
	end

	rectangle('position',[0 0 0.001 1],'facecolor',color,'edgecolor',color,'visible','off')
	set(gca,'position',[border/tw border/th pw/tw ph/th])
	axis([0 100 -info.clearance 1+info.clearance])
	set(gca,'Xtick',[]);
	set(gca,'Ytick',[]);
	set(gca,'box','on');

	title(info.msg);
	drawnow
	return

end





% unrecognised call
error('incorrect usage - see "help progbar"');




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% USAGE DEMO
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function progbar_demo

disp([10 'progbar.m demonstration: press a key to move on' 10]);
disp('Simple usage:');
disp([10 'p=progbar;'])
p=progbar;
pause
disp(['progbar(p,20)']);
progbar(p,20);
pause
disp(['progbar(p,70)']);
progbar(p,70);
pause
disp(['progbar(p,100)']);
progbar(p,100);
pause
disp(['progbar(p,-1)']);
progbar(p,-1)
pause
disp([10 'Set some parameters:']);
disp([10 'info.color=[1 0 0]']);
disp(['info.title=''LMS''']);
disp(['info.size=2']);
disp([10 'p=progbar(info)']);
disp(['progbar(p,50)']);
info.color=[1 0 0];
info.title='LMS';
info.size=2;
info.period=0; % force instant update for this demo
p=progbar(info);
progbar(p,50);
pause
disp('progbar(p,-1)')
progbar(p,-1)
pause
disp([10 'Set some more parameters:']);
disp([10 'info.clearance=0.5']);
disp('info.msg=''Processing Least Mean Square algorithm''');
disp('p=progbar(info);');
disp('progbar(p,20)');
info.clearance=0.5;
info.msg='Processing Least Mean Square algorithm';
info.period=0; % force instant update for this demo
p=progbar(info);
progbar(p,20);
pause
disp('progbar(p,-1)')
progbar(p,-1)
pause
disp([10 'For other uses of color and period, and detailed help, type help progbar' 10]);





%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% PERFORMANCE DEMO
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function progbar_perfdemo

disp([10 'progbar.m performance demonstration' 10]);

N = 1e4;

disp('Tight loop using waitbar:');
disp('for n = 1:N');
disp('	waitbar(n/N, h);');
disp('end');

h = waitbar(0);
tic
for n = 1:N
	waitbar(n/N, h);
end
disp(['loop total time: ' num2str(toc)]);
close(h)
disp(' ')

disp('Tight loop using progbar:');
disp('for n = 1:N');
disp('	progbar(h, n/N*100);');
disp('end');

h = progbar;
tic
for n = 1:N
	progbar(h, n/N*100);
end
disp(['loop total time: ' num2str(toc)]);
progbar(h, -1)
disp(' ')




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% TEST DEMO (for, well, testing - not for the user)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function progbar_testdemo

N = 5e4;

disp('Tight loop using progbar:');

h = progbar;
tic
for n = 1:N
	progbar(h, n/N*100);
end
disp(['loop total time: ' num2str(toc)]);
progbar(h, -1)
disp(' ')




Contact us