I have a MATLAB GUI (developed in GUIDE) where I give the user the option to save certain data-structure variables (as a .mat file). However, this is a large .mat file and it can take up to a minute to save this file. Without any sort of progress indication, I have no way of telling the user when the file is saved (allowing them to perform other actions in the GUI). Is there a way of creating a waitbar that is linked to the progress of the save function? Any help would be appreciated!
You cannot monitor the progress of the save
command in MATLAB. This is because MATLAB does not perform the save operation in another thread, but rather uses the program's main thread which prevents you from performing any actions while saving the file.
You could provide a dialog that tells the user that the save is occuring and simply remove it when the save is complete.
dlg = msgbox('Save operation in progress...');
save('output.mat');
if ishghandle(dlg)
delete(dlg);
end
If you really want to save multiple variables and monitor the progress, you could use the -append
flag to save
and append each variable independently.
vars2save = {'a', 'b', 'c', 'd'};
outname = 'filename.mat';
hwait = waitbar(0, 'Saving file...');
for k = 1:numel(vars2save)
if k == 1
save(outname, vars2save{k})
else
save(outname, vars2save{k}, '-append');
end
waitbar(k / numel(vars2save), hwait);
end
delete(hwait);
I did a benchmark to see how this second approach affects the total save time. It appears that using -append
to save each variable has less of a performance hit than expected. Here is the code and the results from that.
function saveperformance
% Number of variables to save each time through the test
nVars = round(linspace(1, 200, 20));
outname = 'filename.mat';
times1 = zeros(numel(nVars), 1);
times2 = zeros(numel(nVars), 1);
for k = 1:numel(nVars)
% Delete any pre-existing files
if exist('outname')
delete(outname)
end
% Create variable names
vars2save = arrayfun(@(x)['x', num2str(x)], 1:nVars(k), 'Uniform', 0);
% Assign each variable with a random matrix of dimensions 50000 x 2
for m = 1:numel(vars2save)
eval([vars2save{m}, '=rand(50000,2);']);
end
% Save all at once
tic
save(outname, vars2save{:});
times1(k) = toc;
delete(outname)
% Save one at a time using append
tic
for m = 1:numel(vars2save)
if m == 1
save(outname, vars2save{m});
else
save(outname, vars2save{m}, '-append');
end
end
times2(k) = toc;
end
% Plot results
figure
plot(nVars, [times1, times2])
legend({'All At Once', 'Append'})
xlabel('Number of Variables')
ylabel('Execution Time (seconds)')
end