%% (Internal) A progress bar class for showing evolution of a process to users % % Description: % A progress-bar object to show the progress of a process. If the process % is a loop, and the iteration number is known a priori, the object can inform % the remaining time to finish the loop. If the iteration number is % unknown, the object informs the mean duration of a loop. % If the process is linear, the object can indicate the advance in the % execution. The interface is very simple, and this example show the way of % using it. % % Example: % % %% start of algorithm % clear % % pb = progress_bar('Progress bar demo', 'Start of algorithm'); % % pause(2) % % %% initialization code % % pb.checkpoint('Initialization'); % % pause(4) % % %% some iteration known a priori % % pb.Loops2Do = 10; % pb.Title = 'Iterations known a priori'; % % for ii = 1:10 % % pb.start_loop(); % % pause(3+randn(1)) % % pb.checkpoint('Step 1'); % % pause(3+randn(1)) % % pb.checkpoint('Step 2'); % % pause(3+randn(1)) % % pb.checkpoint('Step 3'); % % pause(3+randn(1)) % % pb.end_loop(); % % end % % %% some iteration unknown a priori % % pb.reset(); % pb.Title = 'Iterations Unknown a priori'; % % for ii = 1:round(8+2*rand(1)) % % pb.start_loop(); % % pause(3+randn(1)) % % pb.checkpoint('Step 1'); % % pause(3+randn(1)) % % pb.checkpoint('Step 2'); % % pause(3+randn(1)) % % pb.checkpoint('Step 3'); % % pause(3+randn(1)) % % pb.end_loop(); % % end % % %this clear and close all. % clear pb % % Author: Mariano Llamedo Soria (llamedom at {electron.frba.utn.edu.ar; unizar.es} % Version: 0.1 beta % Birthdate : 23/8/2011 % Last update: 24/3/2014 % Copyright 2008-2015 % classdef progress_bar < handle properties(GetAccess = private, Constant) %constant for the waitbar bar_position = [0.05 0.3 0.9 0.25]; default_evolution = 0.1; long_loop_in_sec = 10; % seconds update_msg_time = 10; % seconds loops2weight = 20; % last 20 loops end properties ( Access = private ) bUIpresent = usejava('desktop'); wb_handle = []; wb_axes_hdl = []; LoopTimes = []; counter = 0; obj_tic = []; Cleanup_hdl = []; bPBcreated = false; childs parent update_counter time_elapsed time_weighting end properties(SetAccess = private, GetAccess = public) LoopMeanTime = []; end properties Message = ''; Title = ''; Loops2Do = []; LoopsDone = 0; end methods function obj = progress_bar(Title, Message, wb_handle) if( nargin > 0 && ischar(Title) ) obj.Title = Title; end if( nargin > 1 && ischar(Message) ) obj.Message = Message; end if( obj.bUIpresent ) % log to a waitbar obj.update_counter = 0; obj.time_elapsed = 0; if( nargin < 3 || ~ishandle(wb_handle) ) obj.wb_handle = waitbar(0, obj.Message, 'name', obj.Title ); else obj.wb_handle = wb_handle; end set(obj.wb_handle, 'Tag', 'progress_bar_class'); obj.wb_axes_hdl = findobj(obj.wb_handle,'Type','Axes'); set(obj.wb_axes_hdl, 'units','normalized' ); set(obj.wb_axes_hdl, 'position', obj.bar_position); else % TODO:log to stdout end obj.time_weighting = linspace(1,0.1,obj.loops2weight); obj.time_weighting = obj.time_weighting / sum(obj.time_weighting); %to clean and delete the waitbar. % obj.Cleanup_hdl = onCleanup(@()DoPBHouseKeeping(, obj.wb_handle)); obj.bPBcreated = true; end function hide(obj) set(obj.wb_handle, 'Visible', 'off'); end function show(obj) set(obj.wb_handle, 'Visible', 'on'); end function checkpoint(obj, Message ) if( ischar(Message) ) obj.Message = Message; end if( isempty(obj.LoopMeanTime) ) %first loop, learning times. Just to show time evolution. obj.counter = obj.counter + obj.default_evolution; currTime = 0; else %estimate progress currTime = toc(obj.obj_tic); if( isempty(obj.parent) ) aux_mean_time = obj.LoopMeanTime; aux_LoopsDone = obj.LoopsDone; aux_Loop2do = obj.Loops2Do; else aux_mean_time = obj.parent.LoopMeanTime + obj.LoopMeanTime; aux_LoopsDone = obj.parent.LoopsDone * obj.Loops2Do + obj.LoopsDone; aux_Loop2do = obj.parent.Loops2Do * obj.Loops2Do ; end if( ~isempty(aux_Loop2do) && aux_Loop2do > 0 ) obj.counter = aux_LoopsDone/aux_Loop2do; else obj.counter = currTime/aux_mean_time; end end % take care always a waitbar to draw. if( obj.bUIpresent && ~ishandle(obj.wb_handle) ) obj.wb_handle = waitbar(0); set(obj.wb_handle, 'Tag', 'progress_bar'); obj.wb_axes_hdl = findobj(obj.wb_handle,'Type','Axes'); set(obj.wb_axes_hdl, 'units','normalized' ); set(obj.wb_axes_hdl, 'position', obj.bar_position ); end if( obj.bUIpresent ) waitbar( obj.counter - fix(obj.counter), obj.wb_handle, obj.Message ); end if( isempty(obj.parent) ) aux_LoopMeanTime = obj.LoopMeanTime; else aux_LoopMeanTime = obj.parent.LoopMeanTime; end if( isempty(aux_LoopMeanTime) ) if( obj.bUIpresent && ~isempty(obj.obj_tic) ) %Learning phase set(obj.wb_handle, 'Name', [ obj.Title '. Learning loop time ...' ]); end else if( isempty(obj.parent) ) aux_Time2Finish = (obj.Loops2Do-obj.LoopsDone) * obj.LoopMeanTime; else aux_Time2Finish = (obj.parent.Loops2Do - obj.parent.LoopsDone) * obj.parent.LoopMeanTime + (obj.Loops2Do-obj.LoopsDone) * obj.LoopMeanTime; end if( obj.bUIpresent ) obj.update_counter = obj.update_counter + obj.LoopMeanTime; if( obj.update_counter > obj.update_msg_time ) obj.update_counter = 0; if( isempty(obj.Loops2Do) ) set(obj.wb_handle, 'Name', [ adjust_string(obj.Title, 30) ' - [' Seconds2HMS( aux_LoopMeanTime ) ' s/loop]']); else set(obj.wb_handle, 'Name', [ adjust_string(obj.Title, 30) ' - Finishing in ' Seconds2HMS(aux_Time2Finish) ]); end end end end end function start_loop(obj) %start of loop. Reset timers obj.obj_tic = tic; if( isempty(obj.parent) ) aux_mean_time = obj.LoopMeanTime; else aux_mean_time = obj.parent.LoopMeanTime + obj.LoopMeanTime; end if( obj.bUIpresent && ~isempty(aux_mean_time) && aux_mean_time > obj.long_loop_in_sec ) % long process: progress within a loop. waitbar( 0, obj.wb_handle, 'Start of loop.' ); % else % short process: total progress end end function end_loop(obj) %end of loop. Calculate averages. obj.LoopTimes = [obj.LoopTimes; toc(obj.obj_tic)]; obj.LoopsDone = obj.LoopsDone + 1; if( length(obj.loops2weight) >= obj.loops2weight ) % last loop is the most weighted obj.LoopMeanTime = mean([ (rowvec(obj.LoopTimes((end-obj.loops2weight+1):end))*flipud(colvec(obj.time_weighting))) (obj.time_elapsed / obj.LoopsDone) ]); else obj.LoopMeanTime = mean(obj.LoopTimes); end obj.time_elapsed = obj.time_elapsed + obj.LoopTimes(end); if( obj.bUIpresent ) if( obj.LoopMeanTime > obj.long_loop_in_sec ) % long process: progress within a loop. waitbar( 1, obj.wb_handle, 'End of loop.' ); % else % short process: total progress end end end function pb_inner = AddInerLoop(obj, strMessage) pb_inner = progress_bar(obj.Title, strMessage, obj.wb_handle); pb_inner.parent = obj; obj.childs = [ obj.childs; pb_inner ]; end function reset(obj) obj.LoopTimes = []; obj.LoopMeanTime = []; obj.counter = 0; obj.LoopsDone = 0; obj.Loops2Do = []; obj.obj_tic = []; obj.Message = ''; obj.update_counter = 0; obj.time_elapsed = 0; if( obj.bUIpresent ) waitbar( 0, obj.wb_handle, obj.Message ); set(obj.wb_handle, 'Name', obj.Title); end end function set.Message(obj,value) if( ischar(value) ) obj.Message = value; if( obj.bUIpresent && obj.bPBcreated ) waitbar( obj.counter - fix(obj.counter), obj.wb_handle, obj.Message ); end else warning('progress_bar:BadArg', 'Message must be a string.'); end end function set.Title(obj,value) if( ischar(value) ) obj.Title = value; if( obj.bUIpresent && obj.bPBcreated ) set(obj.wb_handle, 'Name', obj.Title); end else warning('progress_bar:BadArg', 'Title must be a string.'); end end function set.Loops2Do(obj,value) if( isempty(value) || (isnumeric(value) && value > 0 ) ) obj.Loops2Do = value; else warning('progress_bar:BadArg', 'Loops2Do must be a number > 1.'); end end function delete(obj) if( obj.bUIpresent ) if( ishandle(obj.wb_handle) ) % waitbar close delete(obj.wb_handle) end else end end end end