### How to create 3D animation of particles position vs time in python?

• I am trying to make a 3-D animation of stars' position vs time. I have the information of the stars' x, y and z co-ordinates over time. I was looking at the example of Matplotlib and did understood what I need to do but I don't want the connecting lines between different times. All I need is to show the position of the stars at different time and make a movie of it. This is the example I was looking at

https://matplotlib.org/gallery/animation/simple_3danim.html

After that I want to make it a bit complicated. I have the stars size and mass as well. I was wondering if I can change the size of the circles in the plot according to the radius and use different Colors for different mass range?

The answer you seek is going to be in the mplo3d documentation, not on this stackexchange.

• After that I want to make it a bit complicated. I have the stars size and mass as well. I was wondering if I can change the size of the circles in the plot according to the radius and use different Colors for different mass range?

That part has been addressed in previous questions and answers here, I remember reading maybe a year ago (+/- 0.9 years).

Here is something you may find helpful reprinted from my answer in Stack Overflow. It's based on astronomer and data scientist Jake VanderPlas' blogpost from 2013.

For your needs keep the dots but not the lines. What I recommend is that you start from this and get as far as you can, then ask a question in Stack Overflow showing what you've tried and explaining what you still need.

Here is the Lorenz attractor both in 3D and animated. The script is in the following link (along with many goodies) in Jake VanderPlas' Pythonic Perambulations. You can learn a lot by going line-by-line through the script - it's an elegant use of `matplotlib` objects.

https://jakevdp.github.io/blog/2013/02/16/animating-the-lorentz-system-in-3d/

I added these two lines just before `return` in the `animate` function, and then used ImageJ to import the "image stack" and save the "animated GIF":

``fname = "Astro_Jake_" + str(i+10000)[1:]fig.savefig(fname)``

Note: For OSX it seems to be necessary to set `blit = False` in `animation.FuncAnimation`.

Here is a minimal, simplified example of plotting lines in 3D based on the above:

``def lorentz_deriv((x, y, z), t0, sigma=10., beta=8./3, rho=28.0):    """Compute the time-derivative of a Lorentz system."""    return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]import numpy as npimport matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom scipy.integrate import odeint as ODEintx = np.linspace(0, 20, 1000)y, z = 10.*np.cos(x), 10.*np.sin(x) # something simplefig = plt.figure()ax = fig.add_subplot(1,2,1,projection='3d')ax.plot(x, y, z)# now Lorentztimes = np.linspace(0, 4, 1000) start_pts = 30. - 15.*np.random.random((20,3))  # 20 random xyz starting valuestrajectories = []for start_pt in start_pts:    trajectory = ODEint(lorentz_deriv, start_pt, times)    trajectories.append(trajectory)ax = fig.add_subplot(1,2,2,projection='3d')for trajectory in trajectories:    x, y, z = trajectory.T  # transpose and unpack     # x, y, z = zip(*trajectory)  # this also works!    ax.plot(x, y, z)plt.show()``

I wrote this before I knew of PIL. Apparently you can use PIL to generate your GIFs instead of using an external program like I did.

See

and have fun!

An example of a GIF with stars in it from the first blogpost (Nyan Cat):

• Hi I did manage to write the code. Here is what I did

``import numpy as npimport matplotlib.pyplot as pltimport mpl_toolkits.mplot3d.axes3d as p3import matplotlib.animation as animationimport pandas as pddf1=pd.read_pickle("properties.csv")x=np.array(df1['x'])*3.24078e-17y=np.array(df1['y'])*3.24078e-17z=np.array(df1['z'])*3.24078e-17data=[]for i in range(len(x)):    blank=[]    for j in range(len(x[i])):        dummy=[]        dummy.append(x[i][j])        dummy.append(y[i][j])        dummy.append(z[i][j])        blank.append((dummy))    data.append(np.array(blank))def animate_scatters(iteration, data, scatters):    for i in range(data[0].shape[0]):        scatters[i]._offsets3d = (data[iteration][i,0:1], data[iteration][i,1:2], data[iteration][i,2:])    return scattersdef main(data, save=False):    fig = plt.figure()    ax = p3.Axes3D(fig)    # Initialize scatters    scatters = [ ax.scatter(data[0][i,0:1], data[0][i,1:2], data[0][i,2:]) for i in range(data[0].shape[0]) ]    # Number of iterations    iterations = len(data)    # Setting the axes properties    ax.set_xlim3d([-10, 10])    ax.set_xlabel('X')    ax.set_ylim3d([-10, 10])    ax.set_ylabel('Y')    ax.set_zlim3d([-10, 10])    ax.set_zlabel('Z')    ax.set_title('Nuclear Star Cluster')    # Provide starting angle for the view.    ax.view_init(25, 10)    ani = animation.FuncAnimation(fig, animate_scatters, iterations, fargs=(data, scatters),                                       interval=50, blit=False, repeat=True)    if save:        Writer = animation.writers['ffmpeg']        writer = Writer(fps=30, metadata=dict(artist='Me'), bitrate=1800, extra_args=['-vcodec', 'libx264'])        ani.save('3d-scattered-animated.mp4', writer=writer)    plt.show()#print data[1]main(data, save=True)``

Now my problem is my data shape is changing with time, the number of particles is getting reduced. How do I incorporate that in the code?

Is this an answer? Shouldn't this be part of the question? Then edit your question accordingly.

@planetmaker Good point. However, this is looking more like a coding question now, and it may be better to ask it on Stack Overflow, where there are plenty of Python users who know matplotlib. OTOH, asking on SO can be a nerve-wracking experience, we're a bit gentler here on Astronomy. ;)

Okay well I think this is the end of the road for Astronomy SE for your question, since this is no longer even a little bit about Astronomy. You have some experience with Stack Overflow, they need fairly specific questions, and there is also Code Review SE and they require *running code* that only needs improvement. We should't post follow up questions in answer posts.

@PM2Ring ya that's why I posted at least something *here* to at least get them started.

I've only had a brief look at your code, but I noticed a couple of things. There's no need to import `pandas` just to read a .csv file if you aren't actually using any other Pandas features. You can use the `DictReader` in the `csv` module for that. Also, your `data` conversion looks very inefficient. If you find yourself using `for` loops on a Numpy array, you're probably doing it wrong. Especially nested `for` loops.

@PM2Ring There is nothing wrong using for loop or nested for loop with numpy arrays. I am just grouping the [x,y,z] for each particle which could have been done using np.hstack as well I guess

@ArpanDas when your data gets big you will have much better results if you follow that advice. "There's nothing wrong" will turn into "My script takes forever to run" to which the answer will be "You're *definitely* doing it wrong." Learn to let numpy do the work for you because numpy executes fast compiled code whereas nested python loops are far slower. Stacking and moving the order of axes of arrays have simple numpy syntax, and when you are done you can consider using `.copy()` to make a new instance of your reordered array (if you have enough memory) if caching/paging slows you down.