Animate a Particle#

In this tutorial, we will visualize the motion of a particle moving towards the origin in a 3D coordinate system using Plotly and NumPy in Python.

Simple Animation#

We’ll start by demonstrating a simple example of animating a point in 3D space using Plotly and then adapt this concept to animate a particle moving from its initial position towards the origin.

Step 1: Setting Up the Environment#

Import necessary libraries: plotly.graph_objects for plotting and numpy for numerical operations.

[51]:
import plotly.graph_objects as go
import numpy as np

Step 2: Defining the Path#

[52]:
# Define a simple path in 3D space
path = np.array([[0, 3, 1], [1, 4, 2], [2, 5, 3], [3, 6, 4]])
steps = len(path)
steps
[52]:
4

Here, path is a NumPy array representing a sequence of points in 3D space. steps is the number of points along the path.

Step 3: Initial Position of the Particle#

x=[path[0, 0]], y=[path[0, 1]], z=[path[0, 2]] set the initial position of the particle using the first (0th) index of the path array, which contains its \(x\), \(y\), and \(z\) coordinates.

[53]:
particle_trace = go.Scatter3d(
    x=[path[0, 0]], y=[path[0, 1]], z=[path[0, 2]],
    mode='markers',
    marker=dict(size=7, color='red')
)

Step 4: Layout Configuration#

updatemenus creates an interactive button in the plot. It’s configured to start the animation when clicked.

[54]:
layout = go.Layout(
    title="Particle Moving Towards the Origin",
    scene=dict(
        xaxis=dict(title='X Axis', range=[-4, 7]),
        yaxis=dict(title='Y Axis', range=[-4, 7]),
        zaxis=dict(title='Z Axis', range=[-4, 7])
    ),
    updatemenus=[dict(type="buttons", showactive=False,
                      y=1, x=0.8, xanchor='left', yanchor='bottom',
                      pad=dict(t=45, r=10),
                      buttons=[dict(label='Play',
                                    method='animate',
                                    args=[None, dict(frame=dict(duration=100, redraw=True),
                                                     fromcurrent=True)])])]
)

Note

Make sure that you are setting a right axis range to keep the particle inside the plot. You can leave it as defalut but you may not able to see tha animation with single particle because of the automated changing of axis range. It works well with path added animations

Step 5: Frames for the Animation#

This list comprehension creates a series of go.Frame objects, each representing a frame in the animation. Each frame updates the position of the particle to the kth step along the path. range(steps) iterates over the number of steps defined in the path, creating a frame for each step.

[55]:
frames = [go.Frame(data=[go.Scatter3d(
    x=[path[k, 0]], y=[path[k, 1]], z=[path[k, 2]],
    mode='markers',
    marker=dict(size=7, color='red')
)]) for k in range(steps)]

Step 6: Combining Everything#

Hit the play button to watch the animation. (Ratate the plot to watch it detaily)

[56]:
fig = go.Figure(data=[particle_trace], layout=layout, frames=frames)
fig.show()

Movement Towards the Origin#

Now, let’s adapt the above example to animate a particle moving from an initial position to the origin.

Step 1: Get the traces#

[57]:
# Coordinates of the origin and the particle
origin = [0, 0, 0]
particle = [1, 2, 3]

# Trace for the particle
particle_trace = go.Scatter3d(
    x=[1], y=[2], z=[3],
    mode='markers',
    marker=dict(size=10, color='red'),
    name='Particle'
)

# Trace for the origin
origin_trace = go.Scatter3d(
    x=[0], y=[0], z=[0],
    mode='markers+text',
    marker=dict(size=5, color='blue'),
    name='Origin',
    text=["O"],  # Text labels for point
    textposition="top center",  # Position of the text
    showlegend=False
)

# Trace for the connecting line
connecting_line_trace = go.Scatter3d(
    x=[origin[0], particle[0]],
    y=[origin[1], particle[1]],
    z=[origin[2], particle[2]],
    mode='lines',
    line=dict(color='green', width=2),
    name='Path'
)

Step 2: Modify the Path#

The path now linearly interpolates between the starting point and the origin.

[58]:
# Define the path from a starting point to the origin
start_point = [3, 3, 3]  # Starting position of the particle
path = np.linspace(particle, origin, num=steps)
path
[58]:
array([[1.        , 2.        , 3.        ],
       [0.66666667, 1.33333333, 2.        ],
       [0.33333333, 0.66666667, 1.        ],
       [0.        , 0.        , 0.        ]])

Step 3: Frames for the Animation#

[59]:
frames = [go.Frame(data=[go.Scatter3d(
    x=[path[k, 0]], y=[path[k, 1]], z=[path[k, 2]],
    mode='markers',
    marker=dict(size=7, color='red')
)]) for k in range(steps)]

Step 4: Combine All#

Hit the play button to see the animation

Note

Make sure that you are putting the animating traces before of all static traces in data list to keep static traces on the plot.

[60]:
fig = go.Figure(data=[particle_trace, origin_trace, connecting_line_trace], layout=layout, frames=frames)
fig.show()

By following these steps, you can create a basic animation in Plotly and then adapt it to show a particle moving towards the origin, demonstrating the flexibility and power of Plotly for dynamic visualizations.