Browsed by
Tag: Fourier Series

Creating Animated Plots in MATLAB

Creating Animated Plots in MATLAB

This tutorial will demonstrate how to create animated plots using MATLAB. This will be demonstrated through the use of a Fourier approximation of a square wave. The infinite series representing the Fourier approximation of a square wave is:
 
x_{square}(t)= \frac{4}{\pi} \sum_{k=1}^\infty \frac{\sin\left(2\pi (2k-1) ft \right)}{(2k-1)}  
We will now create an animated GIF showing the first 20 terms in this Fourier approximation. For this plot, the only information that changes for each series in title and the y-data for the Fourier approximation. This can be handled efficiently by only updating that information for each iteration of the loop.

%% Define waveform properties
f = 1;          % Frequency (Hz)
t = 0:.001:2;   % Eval time (s)
Y_Fourier = zeros(size(t)); % Preallocate

%% Generate the frames
for k = 1:20;
    Y_Fourier = (4/pi)*sin(2*pi*(2*k-1)*f*t)/(2*k-1) + Y_Fourier;
    if k == 1
        % Only create the plot for 1st iteration, update wave for
        % subsequent
        figure();
        hold('on'); grid('on');
        ylim([-1.5 1.5]);
        set(gca, 'xtick', 0:0.5:2);
        h1 = plot(t, square(t*2*pi), 'LineWidth', 2);
        h2 = plot(t,Y_Fourier, 'LineWidth', 2);
        legend('Square Wave (1 Hz)', 'Fourier Approximation');
        xlabel('Time (s)');
        ylabel('Amplitude');
    else
        % Update y data
        set(h2, 'ydata', Y_Fourier)
    end
    title(['k = ' num2str(k)]);

Creating the frames

To create the frames for the animated GIF, we will save each plot of the Fourier approximation to a *.png file. It is possible to create an animation without first saving the frames to files by using the getframe() function within MATLAB. However, this method allows for easier control over the animation resolution as well as works in cases where the frames were created using other means, e.g. images obtained from a camera.

Each frame will be generated using the print() function. The necessary inputs for this process is the frame name, the image format, and the image resolution. For this example, the animation will be created with a resolution of 150 PPI. Keep in mind that this animation will be displayed on a screen and images with resolutions greater than the screen resolution will be displayed at the screen resolution.

    % Save as png with a resolution of 150 pixels per inch
    print(['Frame ' num2str(k)], '-dpng', '-r150');
end

Assembling the frames into an animated GIF image

Finally, now that the frames are created, we can assemble the into an animated GIF using the imwrite() command. Two of the necessary inputs for the imwrite command is the image data X and a color scale associated with that data included in map. The GIF image format only supports 8 bit images. If the image being read with imread() is greater than uint8, a conversion may be necessary.

GifName = 'SquareWaveAnimation.gif';
delay = 0.5;    % Delay between frames (s)
for ii = 1:20
    [A, ~] = imread(['Frame ' num2str(ii) '.png']);
    [X, map] = rgb2ind(A, 256);
    if ii == 1
        imwrite(X, map, GifName, 'gif', 'LoopCount', inf, 'DelayTime', delay)
    else
        imwrite(X, map, GifName, 'gif', 'WriteMode', 'append', 'DelayTime', delay)
    end
end

The result

The output from the above code becomes:

SquareWaveAnimation

Full code

%% Define waveform properties
f = 1;          % Frequency (Hz)
t = 0:.001:2;   % Eval time (s)
Y_Fourier = zeros(size(t)); % Preallocate

%% Generate the frames
for k = 1:20;
    Y_Fourier = (4/pi)*sin(2*pi*(2*k-1)*f*t)/(2*k-1) + Y_Fourier;
    if k == 1
        % Only create the plot for 1st iteration, update wave for
        % subsequent
        figure();
        hold('on'); grid('on');
        ylim([-1.5 1.5]);
        set(gca, 'xtick', 0:0.5:2);
        h1 = plot(t, square(t*2*pi), 'LineWidth', 2);
        h2 = plot(t,Y_Fourier, 'LineWidth', 2);
        legend('Square Wave (1 Hz)', 'Fourier Approximation');
        xlabel('Time (s)');
        ylabel('Amplitude');
    else
        % Update y data
        set(h2, 'ydata', Y_Fourier)
    end
    title(['k = ' num2str(k)]);
    % Save as png with a resolution of 150 pixels per inch
    print(['Frame ' num2str(k)], '-dpng', '-r150');
end

%% Now time to generate the animated gif
GifName = 'SquareWaveAnimation.gif';
delay = 0.5;    % Delay between frames (s)
for ii = 1:20
    [A, ~] = imread(['Frame ' num2str(ii) '.png']);
    [X, map] = rgb2ind(A, 256);
    if ii == 1
        imwrite(X, map, GifName, 'gif', 'LoopCount', inf, 'DelayTime', delay)
    else
        imwrite(X, map, GifName, 'gif', 'WriteMode', 'append', 'DelayTime', delay)
    end
end