-
Notifications
You must be signed in to change notification settings - Fork 2
/
progress.m
210 lines (197 loc) · 5.7 KB
/
progress.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
function n = progress(rate,title)
%PROGRESS Text progress bar
% Similar to waitbar but without the figure display.
%
% Start:
% PROGRESS('init'); initializes the progress bar with title 'Please wait...'
% PROGRESS('init',TITLE); initializes the progress bar with title TITLE
% PROGRESS(RATE); sets the length of the bar to RATE (between 0 and 1)
% PROGRESS(RATE,TITLE); sets the RATE and the TITLE
% PROGRESS('close'); (optionnal) closes the bar
%
% Faster version for high number of loops:
% The function returns a integer indicating the length of the bar.
% This can be use to speed up the computation by avoiding unnecessary
% refresh of the display
% N = PROGRESS('init'); or N = PROGRESS('init',TITLE);
% N = PROGRESS(RATE,N); changes the length of the bar only if different
% from the previous one
% N = PROGRESS(RATE,TITLE); changes the RATE and the TITLE
% PROGRESS('close'); (optionnal) closes the bar
%
% The previous state could be kept in a global variable, but it is a bit
% slower and doesn't allows nested waitbars (see examples)
%
% Known bug: Calling progress('close') shortly afer another call of the
% function may cause strange errors. I guess it is because of the
% backspace char. You can add a pause(0.01) before to avoid this.
%
% Examples:
% progress('init');
% for i=1:100
% progress(i/100, sprintf('loop %d/100',i));
%
% % computing something ...
% pause(.1)
% end
% progress('close'); % optionnal
%
%
% % Inside a script you may use:
% n = progress('init','wait for ... whatever');
% for i=1:100
% n = progress(i/100,n);
%
% % computing something ...
% pause(.1)
% end
% progress('close');
%
%
% % Add a time estimation:
% progress('init','Processing...');
% tic % only if not already called
% t0 = toc; % or toc if tic has already been called
% tm = t0;
% L = 100;
% for i=1:L
% tt = ceil((toc-t0)*(L-i)/i);
% progress(i/L,sprintf('Processing... (estimated time: %ds)',tt));
%
% % computing something ...
% pause(.1)
% end
% progress('close');
%
%
% % Add a faster time estimation:
% n = progress('init','Processing...');
% tic % only if not already called
% t0 = toc; % or toc if tic has already been called
% tm = t0;
% L = 100;
% for i=1:L
% if tm+1 < toc % refresh time every 1s only
% tm = toc;
% tt = ceil((toc-t0)*(L-i)/i);
% n = progress(i/L,sprintf('Processing... (estimated time: %ds)',tt));
% else
% n = progress(i/L,n);
% end
%
% % computing something ...
% pause(.1)
% end
% progress('close');
%
% % Nested loops:
% % One loop...
% n1 = progress('init','Main loop');
% for i=0:7
% n1 = progress(i/7,n1);
%
% % ... and another, inside the first one.
% n2 = progress('init','Inside loop');
% for j=0:50
% n2 = progress(j/50,n2);
%
% % computing something ...
% pause(.01)
% end
% progress('close');
% end
% pause(.01)
% progress('close');
% 31-08-2007
% By Joseph martinot-Lagarde
% joseph.martinot-lagarde@m4x.org
% Adapted from:
% MMA 31-8-2005, martinho@fis.ua.pt
% Department of Physics
% University of Aveiro, Portugal
%% The simplest way to bypass it...
% n = 0; return
%% Width of the bar
%If changes are made here, change also the default title
lmax=70; % TM: changed from lmax=50;
%% Erasing the bar if necessary
% not needed, but one could find it prettier
if isequal(rate,'close')
% there were 3 '\n' added plus the title and the bar itself
fprintf(rep('\b',2*lmax+3))
return
end
%% The init
if isequal(rate,'init') % If in init stage
cont = 0; % we don't continue a previous bar
back = '\n'; % add a blank line at the begining
rate = 0; % start from 0
else
cont = 1; % we continue a previous bar
end
%% No need to update the view if not necessary
% optional, but saves a LOT of time
% length of the displayer bar in number of char
% double([0,1]) to int([0,lmax-1])
n = min(max( ceil(rate*(lmax-2)) ,0),lmax-2);
% If the 2nd arg is numeric, assumed to be the previous bar length
if nargin >=2 && isnumeric(title)
if n == title % If no change, do nothing
return
else % otherwise continue
n_ = title;
clear title
end
else % draw the whole bar
n_ = -1;
end
%% The title
% If a new title is given, display it
if exist('title','var')
Ltitle = length(title);
if Ltitle > lmax % If too long, cut it
title = [title(1:lmax) '\n']
else % otherwise center it
title = [rep(' ',floor((lmax-Ltitle)/2)) title rep(' ',ceil((lmax-Ltitle)/2)) '\n'];
end
if cont % If not in init stage, erase the '\n' and the previous title
back = rep('\b',lmax+1);
end
else
if cont % If not in init stage, give a void title
title = '';
back = ''; % has to be set
else % else set a default title
title = ' Please wait... \n';
end
end
%% The bar
% '\f' should draw a small square (at least in Windows XP, Matlab 7.3.0 R2006b)
% If not, change to any desired single character, like '*' or '#'
if ~cont || n_ == -1 % at the begining disp the whole bar
str = ['[' rep('*',n) rep(' ',lmax-n-2) ']\n'];
if cont % If not in init stage, erase the previous bar
back = [back, rep('\b',lmax+1)];
end
else % draw only the part that changed
str = [rep('*',n-n_) rep(' ',lmax-n-2) ']\n'];
back = [back, rep('\b',lmax-n_)];
end
%% The print
% Actually make the change
fprintf([back title str]);
return
%% Function to repeat a char n times
function cout = rep(cin,n)
if n==0
cout = [];
return
elseif length(cin)==1
cout = cin(ones(1,n));
return
else
d = [1; 2];
d = d(:,ones(1,n));
cout = cin(reshape(d,1,2*n));
return
end