Search code examples
matlabmatlab-guidemat-file

MATLAB: Show a progress bar when saving file?


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!


Solution

  • 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
    

    A Potential Solution

    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);
    

    A Benchmark

    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
    

    enter image description here