MATLAB: How do i make a plot from a data table with a random number of entries

polymerchain

I wrote a little script to make a video for the dynamic of 10 beads connected by springs from a data table.
The data table format:
timestep1 x1 y1 z1 x2 y2 z2 … x10 y10 z10
timestep2 x1 y1 z1 x2 y2 z2 … x10 y10 z10
timestep3 x1 y1 z1 x2 y2 z2 … x10 y10 z10
timestep increments with a fixed factor, xi yi zi are the cartesian coordinates of the i. bead wich change with every timestep.
here is the code:
A = readtable('\\wsl$\Debian\home\cpp\traj.txt');
t = A{:,1};
x0 = A{:,2};
y0 = A{:,3};
z0 = A{:,4};
x1 = A{:,5};
y1 = A{:,6};
z1 = A{:,7};
x2 = A{:,8};
y2 = A{:,9};
z2 = A{:,10};
x3 = A{:,11};
y3 = A{:,12};
z3 = A{:,13};
x4 = A{:,14};
y4 = A{:,15};
z4 = A{:,16};
x5 = A{:,17};
y5 = A{:,18};
z5 = A{:,19};
x6 = A{:,20};
y6 = A{:,21};
z6 = A{:,22};
x7 = A{:,23};
y7 = A{:,24};
z7 = A{:,25};
x8 = A{:,26};
y8 = A{:,27};
z8 = A{:,28};
x9 = A{:,29};
y9 = A{:,30};
z9 = A{:,31};
set(gca, 'XLim', [-5 5], 'YLim', [-5 5], 'ZLim', [-5 5]);
view(43,24);
hold on;
for i=1:1000
k = scatter3(x0(i), y0(i), z0(i),'filled','MarkerFaceColor','k');
a = scatter3(x1(i), y1(i), z1(i),'filled','MarkerFaceColor','r');
lx0 = linspace(x0(i),x1(i));
ly0 = linspace(y0(i),y1(i));
lz0 = linspace(z0(i),z1(i));
l0 = plot3(lx0,ly0,lz0);
b = scatter3(x2(i), y2(i), z2(i),'filled','MarkerFaceColor','g');
lx1 = linspace(x1(i),x2(i));
ly1 = linspace(y1(i),y2(i));
lz1 = linspace(z1(i),z2(i));
l1 = plot3(lx1,ly1,lz1);
c = scatter3(x3(i), y3(i), z3(i),'filled','MarkerFaceColor','b');
lx2 = linspace(x2(i),x3(i));
ly2 = linspace(y2(i),y3(i));
lz2 = linspace(z2(i),z3(i));
l2 = plot3(lx2,ly2,lz2);
d = scatter3(x4(i), y4(i), z4(i),'filled','MarkerFaceColor','y');
lx3 = linspace(x3(i),x4(i));
ly3 = linspace(y3(i),y4(i));
lz3 = linspace(z3(i),z4(i));
l3 = plot3(lx3,ly3,lz3);
e = scatter3(x5(i), y5(i), z5(i),'filled','MarkerFaceColor','m');
lx4 = linspace(x4(i),x5(i));
ly4 = linspace(y4(i),y5(i));
lz4 = linspace(z4(i),z5(i));
l4 = plot3(lx4,ly4,lz4);
f = scatter3(x6(i), y6(i), z6(i),'filled','MarkerFaceColor','c');
lx5 = linspace(x5(i),x6(i));
ly5 = linspace(y5(i),y6(i));
lz5 = linspace(z5(i),z6(i));
l5 = plot3(lx5,ly5,lz5);
g = scatter3(x7(i), y7(i), z7(i),'filled','MarkerFaceColor','b');
lx6 = linspace(x6(i),x7(i));
ly6 = linspace(y6(i),y7(i));
lz6 = linspace(z6(i),z7(i));
l6 = plot3(lx6,ly6,lz6);
h = scatter3(x8(i), y8(i), z8(i),'filled','MarkerFaceColor','k');
lx7 = linspace(x7(i),x8(i));
ly7 = linspace(y7(i),y8(i));
lz7 = linspace(z7(i),z8(i));
l7 = plot3(lx7,ly7,lz7);
j = scatter3(x9(i), y9(i), z9(i),'filled','MarkerFaceColor','r');
lx8 = linspace(x8(i),x9(i));
ly8 = linspace(y8(i),y9(i));
lz8 = linspace(z8(i),z9(i));
l8 = plot3(lx8,ly8,lz8);
drawnow
F(i) = getframe(gcf);
pause(0.01);
delete(a);
delete(b);
delete(c);
delete(d);
delete(e);
delete(f);
delete(g);
delete(h);
delete(j);
delete(k);
delete(l0);
delete(l1);
delete(l2);
delete(l3);
delete(l4);
delete(l5);
delete(l6);
delete(l7);
delete(l8);
end
video = VideoWriter('ConnectedBeads.avi', 'Uncompressed AVI');
video.FrameRate = 60;
open(video)
writeVideo(video,F);
close(video)
I'm sure this isnt a very dapper code. How can I improve it so It works for a random number of N beads with a table that looks like:
timestep1 x1 y1 z1 x2 y2 z2 … x10 y10 z10 … xN yN zN
timestep2 x1 y1 z1 x2 y2 z2 … x10 y10 z10 … xN yN zN
timestep3 x1 y1 z1 x2 y2 z2 … x10 y10 z10 … xN yN zN

Best Answer

Use arrays instead of numbered variables. You see how this code is much less repeating and easier to see what is happening where?
Because I don't have your data, I didn't test this code.
A = readtable('\\wsl$\Debian\home\cpp\traj.txt');
t = A{:,1};
x = A(:,2:3:end); x=cell2mat(x);
y = A(:,3:3:end); y=cell2mat(y);
z = A(:,4:3:end); z=cell2mat(z);
%create a clean figure and axis with handles
f=figure(1);clf(1)%you could also do f=figure; instead
ax=axis('Parent',f,...
'XLim', [-5 5], 'YLim', [-5 5], 'ZLim', [-5 5],...
'NextPlot','add');
view(43,24);
%how are you making sure you never run out of colors?
%consider either not explicitly choosing colors yourself, or using ColorList{mod(bead,end-1)+1}
ColorList={'k','r','g','b','y','m','c','b','k','r'};
h=[];
for bead=1:size(x,2)
%initialize all bead plots
h.scatter(bead) = scatter3(x(1,bead), y(1,bead), z(1,bead),...
'filled','MarkerFaceColor',ColorList{bead});
lx0 = linspace(x(1,bead),x(1,bead));
ly0 = linspace(y(1,bead),y(1,bead));
lz0 = linspace(z(1,bead),z(1,bead));
h.plot(bead) = plot3(lx0,ly0,lz0);
end
%initialize F properly here
for timestamp=1:numel(t)
for bead=1:size(x,2)
%update the XData,YData,ZData properties instead of deleting everything, which can now do with delete(h.plot),delete(h.scatter)
end
drawnow
F(timestamp) = getframe(f);
end
Related Question