how do i make a plot from a data table with a random number of entries

1 view (last 30 days)
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
  1 Comment
KSSV
KSSV on 5 Aug 2020
It looks like you can use gscatter. All at once can be plotted. You have made it complex by taking different number of variables.

Sign in to comment.

Accepted Answer

Rik
Rik on 5 Aug 2020
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
  3 Comments
Rik
Rik on 5 Aug 2020
First a little housekeeping: This time I edited your post for you. Next time, please use the tools explained on this page to make your post more readable. If you feel my answer solved your issue, please mark it as accepted answer.
The easiest way to make sure your data is an array, is to load it as an array, e.g. with A=readmatrix('traj.txt','NumHeaderLines',0);.
To avoid indexing errors in your last iteration, you can replace bead+1 by min(bead+1,end).
moritz123
moritz123 on 6 Aug 2020
"Use arrays instead of numbered variables." was definetly the right answer. Again, thank you!
Here my solution with arrays that gets the job done:
A = readtable('\\wsl$\Debian\home\cpp\traj.txt');
time = A{:,1};
%using arrays
x = A(:,2:3:end);
x= table2array(x);
y = A(:,3:3:end);
y= table2array(y);
z = A(:,4:3:end);
z= table2array(z);
set(gca, 'XLim', [-40 45], 'YLim', [-40 50], 'ZLim', [-40 45]);
view(25,-25);
hold on;
h=[];
l =[];
for t =1:length(time)
for bead=1:size(x,2)-1
h(bead) = scatter3(x(t,bead), y(t,bead), z(t,bead),'filled','MarkerFaceColor','b');
lx = linspace(x(t,bead),x(t,bead + 1));
ly = linspace(y(t,bead),y(t,bead + 1));
lz = linspace(z(t,bead),z(t,bead + 1));
l(bead) = plot3(lx,ly,lz);
end
h(size(x,2)) = scatter3(x(t,size(x,2)), y(t,size(x,2)), z(t,size(x,2)),'filled','MarkerFaceColor','b');
drawnow
F(t) = getframe(gcf);
pause(0.01);
delete(h);
delete(l);
end
video = VideoWriter('100Beads.avi', 'Uncompressed AVI');
video.FrameRate = 60;
open(video)
writeVideo(video,F);
close(video)

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!