How to speed up a very slow animated plot in MATLAB

倾然丶 夕夏残阳落幕 提交于 2019-12-13 01:04:00

问题


I'm trying to create an animated plot but my code is very slow, perhaps the method I'm using is too naive. In the below example, I have 4 subplots each with 3 lines, which I update in a 'time' loop.

clc;clear;close all;
state = {'$x-Position$','$x-Velocity$','$y-Position$','$y-Velocity$'};
ylabels = {'$x$','$\dot{x}$','$y$','$\dot{y}$'};
options1 = {'interpreter','latex'};
options2 = {'interpreter','latex','fontsize',20};
maxT = 300;

for pp = 1:4
    hh1(pp)=subplot(2,2,pp);
    xlabel('$t$',options2{:});
    ylabel(ylabels{pp},options2{:});
    title(state{pp},options1{:})
    xlim([0 maxT])
    hold on
end
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
for k = 2:maxT
    for p = 1:4
        plot(hh1(p),k-1:k,x(p,k-1:k),'b','linewidth',2)
        plot(hh1(p),k-1:k,z(p,k-1:k),'m')
        plot(hh1(p),k-1:k,x_est(p,k-1:k),':k','linewidth',2)
    end
    drawnow;
end

As can be seen from the profiler output, the drawnow is killing the time. Is there any way I can be more efficient in creating this animation?


回答1:


Because you want an animation, there is no alternative to using drawnow to update the frame. However, it's not drawnow in particular which is slowing you down - the profiler can be misleading... drawnow simply updates all of the graphics changes since the last re-draw, which in your case is a dozen new plots!

You'll find that hold is pretty slowing. For instance if you're wiser about your holding, remove the existing hold on and only hold when actually plotting

% ... above code the same but without 'hold on'
for p = 1:4
    hold(hh1(p), 'on');
    % plots
    hold(hh1(p), 'off');
end

This saves ~10% time on my PC (12.3sec down to 11.3sec).


The real speed up comes from removing hold entirely, along with all of the individual plot calls! This method also doesn't touch the line formatting which will help with speed. See a previous question about updating plot data here.

Simply update the plot data instead of adding plots. This gives me a speedup of ~68% (12.3sec down to 4.0sec).

% ... your same setup
% Initialise plot data
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
plts = cell(4,3);
hh1 = cell(4,1);

% Loop over subplots and initialise plot lines
for p = 1:4
    hh1{p}=subplot(2,2,p);
    xlabel('$t$',options2{:});
    ylabel(ylabels{p},options2{:});
    title(state{p},options1{:})
    xlim([0 maxT])
    % Hold on to make 3 plots. Create initial points and set line styles.
    % Store the plots in a cell array for later reference.
    hold on
    plts{p,1} = plot(hh1{p},1:2,x(p,1:2),'b','linewidth',2);
    plts{p,2} = plot(hh1{p},1:2,z(p,1:2),'m');
    plts{p,3} = plot(hh1{p},1:2,x_est(p,1:2),':k','linewidth',2);
    hold off
end
% March through time. No replotting required, just update XData and YData
for k = 2:maxT
    for p = 1:4
        set(plts{p,1}, 'XData', 1:k, 'YData', x(p,1:k) );
        set(plts{p,2}, 'XData', 1:k, 'YData', z(p,1:k) );
        set(plts{p,3}, 'XData', 1:k, 'YData', x_est(p,1:k) );
    end
    drawnow;
end    

Now the plotting is pretty optimised. If you want the animation to be even quicker then just plot every 2nd, 3rd, ..., nth timestep instead of every timestep by using for k = 2:n:maxT.



来源:https://stackoverflow.com/questions/50093938/how-to-speed-up-a-very-slow-animated-plot-in-matlab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!