% Copyright (c) 2019 Andrea Alberti % % All rights reserved. classdef parforNotifications < handle properties N; % number of iterations text = 'Please wait ...'; % text to show width = 50; showWarning = true; end properties (GetAccess = public, SetAccess = private) n; end properties (Access = private) inProgress = false; percent; DataQueue; usePercent; Nstr; NstrL; lastComment; end methods function this = parforNotifications() this.DataQueue = parallel.pool.DataQueue; afterEach(this.DataQueue, @this.updateStatus); end % Start progress bar function PB_start(this,N,varargin) assert(isscalar(N) && isnumeric(N) && N == floor(N) && N>0, 'Error: ''N'' must be a scalar positive integer.'); this.N = N; p = inputParser; addParameter(p,'message','Please wait: '); addParameter(p,'usePercentage',true); parse(p,varargin{:}); this.text = p.Results.message; assert(ischar(this.text), 'Error: ''Message'' must be a string.'); this.usePercent = p.Results.usePercentage; assert(isscalar(this.usePercent) && islogical(this.usePercent), 'Error: ''usePercentage'' must be a logical scalar.'); this.percent = 0; this.n = 0; this.lastComment = ''; if this.usePercent fprintf('%s [%s]: %3d%%\n',this.text, char(32*ones(1,this.width)),0); else this.Nstr = sprintf('%d',this.N); this.NstrL = numel(this.Nstr); fprintf('%s [%s]: %s/%s\n',this.text, char(32*ones(1,this.width)),[char(32*ones(1,this.NstrL-1)),'0'],this.Nstr); end this.inProgress = true; end % Iterate progress bar function PB_iterate(this,str) if nargin == 1 send(this.DataQueue,''); else send(this.DataQueue,str); end end function warning(this,warn_id,msg) if this.showWarning msg = struct('Action','Warning','Id',warn_id,'Message',msg); send(this.DataQueue,msg); end end function PB_reprint(this) p = round(100*this.n/this.N); this.percent = p; cursor_pos=1+round((this.width-1)*p/100); if p < 100 sep_char = '|'; else sep_char = '.'; end if this.usePercent fprintf('%s [%s%s%s]: %3d%%\n', this.text, char(46*ones(1,cursor_pos-1)), sep_char, char(32*ones(1,this.width-cursor_pos)),p); else nstr=sprintf('%d',this.n); fprintf('%s [%s%s%s]: %s/%s\n', this.text, char(46*ones(1,cursor_pos-1)), sep_char, char(32*ones(1,this.width-cursor_pos)),[char(32*ones(1,this.NstrL-numel(nstr))),nstr],this.Nstr); end end function updateStatus(this,data) if ischar(data) this.n = this.n + 1; p = round(100*this.n/this.N); if p >= this.percent+1 || this.n == this.N this.percent = p; cursor_pos=1+round((this.width-1)*p/100); if p < 100 sep_char = '|'; else sep_char = '.'; end if ~isempty(data) comment = [' (',data,')']; else comment = ''; end if this.usePercent fprintf('%s%s%s%s]: %3d%%%s\n',char(8*ones(1,58+numel(this.lastComment))), char(46*ones(1,cursor_pos-1)), sep_char, char(32*ones(1,this.width-cursor_pos)),p,comment); else nstr=sprintf('%d',this.n); fprintf('%s%s%s%s]: %s/%s%s\n',char(8*ones(1,55+2*numel(this.Nstr)+numel(this.lastComment))), char(46*ones(1,cursor_pos-1)), sep_char, char(32*ones(1,this.width-cursor_pos)),[char(32*ones(1,this.NstrL-numel(nstr))),nstr],this.Nstr,comment) end this.lastComment = comment; if p == 100 this.inProgress = false; end end else switch data.Action case 'Warning' warning(data.Id,[data.Message,newline]); if this.inProgress this.PB_reprint(); end end end end end end