bio_img_matlab

The MATLAB Blog

Practical Advice for People on the Leading Edge

Pair programming with Claude to produce computational art in MATLAB

I recently stumbled across @yuruyurau, a computational artist on X.com, who posts code snippets in a language called Processing. The results are beautiful, organic-looking animations such as this one
I wanted to play with these animations but since I don't speak Processing, I asked Claude.ai if it could convert them to MATLAB for me. I wasn't using fancy prompts, just things like
This did quite a good job of converting the animation in question and it came up with two versions. One was full of nested loops while the other was vectorized. I'll post that code later in the Discussions forum if anyone is interested but the code I want to talk about today came from my next prompt
function animated_pattern_2()
% Initialize variables
w = 400;
t = 0;
% Pre-generate i values for vectorization
i_vals = 1:10000;
x_vals = mod(i_vals, 200); % equivalent to i%200
y_vals = i_vals / 43;
% Create figure
fig = figure('Position', [100, 100, w, w], 'Color', [0.035, 0.035, 0.035]);
axis equal;
axis off;
xlim([0, w]);
ylim([0, w]);
hold on;
% Animation loop
for i=1:600
% Clear previous frame
cla;
set(gca, 'Color', [0.035, 0.035, 0.035]);
% Update time
t = t + pi/20;
% Vectorized calculations
k = 5 * cos(x_vals/14) .* cos(y_vals/30);
e = y_vals/8 - 13;
d = sqrt(k.^2 + e.^2).^2 / 59 + 4; % mag(k,e)^2/59+4
% Calculate q
q = 60 - 3*sin(atan2(k, e) .* e) + k .* (3 + 4./d .* sin(d.^2 - t*2));
% Calculate c
c = d/2 + e/99 - t/18;
% Calculate final point coordinates
points_x = q .* sin(c) + 200;
points_y = (q + d*9) .* cos(c) + 200;
% Plot points with stroke color (white with alpha ~0.26)
scatter(points_x, points_y, 1, [1, 1, 1], 'filled', 'MarkerFaceAlpha', 0.259);
drawnow;
pause(0.02); % Slightly slower since t increments by PI/20
end
end
 
% Run the animation
tic;animated_pattern_2();toc
Elapsed time is 43.586390 seconds.
I was pretty impressed with this, since the code seemed to work first time without any modification at all. I've not checked the math to see if the results are numerically the same but the animation looks similar enough for now. For the purposes of this blog post, I did change a couple of things manually though. The original had a while-loop that began with
while ishandle(fig)
This ensured that the program ran continuously until the user closed the figure window. However, I write blog posts as Live Scripts which have the ability to automatically produce videos from a finite series of frames. This works if I change to a for-loop so that's what we have here.
I also wrapped the call to the animation function in tic and toc commands because Claude has made a couple of mistakes that we see a lot in MATLAB code that aims to produce animations. Fixing these can make it run much faster and the tic/toc will help me demonstrate this.

Fixing the inefficient animation

I'd start off by getting rid of the pause(0.02) line. One often sees this in user code since the pause command is equivalent to doing a call to drawnow as well as pausing for some time, in this case 0.02 seconds per frame. We already have a call to drawnow and there is no need to limit the animation rate so lets just ditch it.
Next up, is the way it is forming the animation within the for-loop. Each iteration, it clears the frame with cla, sets the color to the same thing every time using set(gca, 'Color', [0.035, 0.035, 0.035]); and then creates a new scatter object. This is inefficient. What we can do instead is create an empty scatter object outside the loop and store its handle:
plothandle = scatter([], [], 1, [1, 1, 1], 'filled', 'MarkerFaceAlpha', 0.376); % Do this outside the loop
Inside the loop, we simply update the XData and YData of the existing scatter plot for every frame
set(plothandle,XData=points_x,YData=points_y);
function animated_pattern_3()
% Initialize variables
w = 400;
t = 0;
% Pre-generate i values for vectorization
i_vals = 1:10000;
x_vals = mod(i_vals, 200); % equivalent to i%200
y_vals = i_vals / 43;
% Create figure
fig = figure('Position', [100, 100, w, w], 'Color', [0.035, 0.035, 0.035]);
plothandle = scatter([], [], 1, [1, 1, 1], 'filled', 'MarkerFaceAlpha', 0.376); % Do this outside the loop
axis equal;
axis off;
xlim([0, w]);
ylim([0, w]);
hold on;
% Animation loop
for i=1:600
% Update time
t = t + pi/20;
% Vectorized calculations
k = 5 * cos(x_vals/14) .* cos(y_vals/30);
e = y_vals/8 - 13;
d = sqrt(k.^2 + e.^2).^2 / 59 + 4; % mag(k,e)^2/59+4
% Calculate q
q = 60 - 3*sin(atan2(k, e) .* e) + k .* (3 + 4./d .* sin(d.^2 - t*2));
% Calculate c
c = d/2 + e/99 - t/18;
% Calculate final point coordinates
points_x = q .* sin(c) + 200;
points_y = (q + d*9) .* cos(c) + 200;
% Plot points
set(plothandle,XData=points_x,YData=points_y);
drawnow;
end
end
 
% Run the animation
tic;animated_pattern_3();toc
Elapsed time is 21.577698 seconds.
The animation rendered in less than half the time and is 22 seconds faster. 12 of those saved seconds are trivial since they correspond to the pause commands but the other 10 seconds comes from our additional modifications.

Animation in a Live Script vs a .m file script

To make the code run even more quickly, we could run it outside of a Live Script. Copy and paste the above program into an .m file and it runs in 13.7 seconds on my machine while the original produced by Claude still takes around 40 seconds in a simple .m file.
This is because Live Scripts do a lot more than just render the animation in a figure. The Live Script also produces a mini-application with video controls. You can play the resulting video, export it to a file, change the speed and even move to any frame you like. All of this takes some time. Claude's original version provides enough time in the pause commands for the Live Script front end to do its magic. Our new version is fast enough that we see the difference in execution time between the simple .m version and the enhanced Live Script version.

Over to you

Is there anything else you'd change in the code generated by Claude? Perhaps try to convert some of @yuruyurau's other functions to MATLAB code using various AI models and let me know how it goes?
|
  • print

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.