0

I'm not a beginner, but I'm also not advanced dev of python code. I'm been trying to animate points movement in scatter plot and to put annotation on every point. All I have done is animation of one point with no annotation. I've searched similar solutions, but it's so confusing. Any help is welcome. This is what I've done.

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import matplotlib.animation as animation

frame_count = 0
points = reading_file("some_data") # this method is not of intrest

def make_one_point(i):
    global frame_count, points

    ex = [1]
    ey = [1]
    ez = [1]
    point = points[i]
    frame = point[frame_count]
    ex[0] = frame[0]
    ey[0] = frame[1]
    ez[0] = frame[2]
    frame_count += 1

    return ex, ey, ez

def update(i):
    global frame_count, points

    if frame_count < len(points[i]):
        return make_one_point(i)
    else:
        frame_count = 0
        return make_one_point(i)


fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
ax1.set_xlim3d(-500, 2000)
ax1.set_ylim3d(-500, 2000)
ax1.set_zlim3d(0, 2000)

x = [1]
y = [1]
z = [1]
scat = ax1.scatter(x,y,z)

def animate(i):
    scat._offsets3d = update(0)

ani = animation.FuncAnimation(fig, animate, 
    frames=len(points[10]),
    interval=100, repeat=True)

plt.show()

How to animate more points at the same time, and put annontation on every one of them? There are 50 points, and I'm not so consern about efficiency, just to make it work.

This code output is moving one point animation

Riao
  • 3
  • 1
  • 4
  • Possible duplicate of [Animating 3D scatter plot using Python mplotlib via serial data](https://stackoverflow.com/questions/50342300/animating-3d-scatter-plot-using-python-mplotlib-via-serial-data) – Diziet Asahi Oct 07 '18 at 12:46
  • I've read it before posting my question, and I think it's not a duplicate, because I am trying something different here. – Riao Oct 07 '18 at 13:28
  • It would be helpful in the future to explain *why* the possible duplicate does not answer your question. – Diziet Asahi Oct 07 '18 at 19:21
  • Firstly, thank you for answering and I'm sorry, this is my first time using stackoverflow. Possible duplicate does not answer my question because there wasn't solved adding text on points in plot, and points are fixed, possible duplicate solution just adds new points. But here, I'm trying to move points, and add text for every point. – Riao Oct 08 '18 at 08:34

1 Answers1

2

It turns out animating Text in 3D was harder than I anticipated. Not surprisingly, I was able to find the solution to the problem in an answer from @ImportanceOfBeingErnest. I then simply adapted the code I had already written in a previous answer, and produced the following code:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D, proj3d
import matplotlib.animation as animation


N_points = 10


def update(num, my_ax):
    # the following corresponds to whatever logic must append in your code
    # to get the new coordinates of your points
    # in this case, we're going to move each point by a quantity (dx,dy,dz)
    dx, dy, dz = np.random.normal(size=(3,N_points), loc=0, scale=1) 
    debug_text.set_text("{:d}".format(num))  # for debugging
    x,y,z = graph._offsets3d
    new_x, new_y, new_z = (x+dx, y+dy, z+dz)
    graph._offsets3d = (new_x, new_y, new_z)
    for t, new_x_i, new_y_i, new_z_i in zip(annots, new_x, new_y, new_z):
        # animating Text in 3D proved to be tricky. Tip of the hat to @ImportanceOfBeingErnest
        # for this answer https://stackoverflow.com/a/51579878/1356000
        x_, y_, _ = proj3d.proj_transform(new_x_i, new_y_i, new_z_i, my_ax.get_proj())
        t.set_position((x_,y_))
    return [graph,debug_text]+annots


# create N_points initial points
x,y,z = np.random.normal(size=(3,N_points), loc=0, scale=10)

fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection="3d")
graph = ax.scatter(x, y, z, color='orange')
debug_text = fig.text(0, 1, "TEXT", va='top')  # for debugging
annots = [ax.text2D(0,0,"POINT") for _ in range(N_points)] 

# Creating the Animation object
ani = animation.FuncAnimation(fig, update, fargs=[ax], frames=100, interval=50, blit=True)
plt.show()

enter image description here

Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75