In [1]:
import k3d
import random
import numpy as np
import matplotlib

T = 1500
N = 10
P = 100
mod = 50

positions = [None] * N
colors = [None] * N
trajectories = [None] * N
colormaps = [k3d.colormaps.matplotlib_color_maps.hot]

for n in range(N):
    positions[n] = {}
    trajectories[n] = {}
    bang = False
    
    pos = np.zeros((P, 3), dtype=np.float32)
    velocity = np.zeros((P, 3), dtype=np.float32)
    velocity[:, 2] = 180.0 + np.random.random(P) * 0.1    
    
    pos[:, 0] = np.sin(n/N * 2.0 * np.pi) * 10.0
    pos[:, 1] = np.cos(n/N * 2.0 * np.pi) * 10.0
    
    cm = random.choice(colormaps)
    cm_space = np.linspace(np.min(cm[0::4]), np.max(cm[0::4]), 2048)
    
    c = (np.interp(cm_space, cm[::4], cm[3::4]) * 255).astype(np.uint32) + \
        (np.interp(cm_space, cm[::4], cm[2::4]) * 255).astype(np.uint32) * 256 + \
        (np.interp(cm_space, cm[::4], cm[1::4]) * 255).astype(np.uint32) * 256 ** 2
        
    colors[n] = c[np.random.randint(0, c.shape[0], P)]
    
    for t in range(T):
        if t > n * 30:        
            if np.mean(velocity[:, 2] < 30.0) and not bang:
                bang = True
                velocity[:, 0] += np.random.normal(size=P) * 55
                velocity[:, 1] += np.random.normal(size=P) * 55
                velocity[:, 2] += np.random.normal(size=P) * 35

            velocity[:, 2] -= 0.05
            velocity *= 0.995                
            pos += velocity * 0.001
        
        if t % mod == 0:
            positions[n][str(t/100.0)] = pos.copy()
In [2]:
for n in range(N):
    db = np.array([positions[n][k] for k in positions[n].keys()])
  
    for t in range(T//mod):
        anim = np.empty((P, T//mod + 1, 3), dtype=np.float32)
        anim.fill(np.nan)
        for p in range(P):
            anim[p, 0:t+1, :] = db[0:t+1, p]
            anim[p, t + 1, :] = anim[p, t, :]
            
        trajectories[n][str(t * mod/100.0)] = anim
In [3]:
plot = k3d.plot(grid=[-100,-100,-100,100,100,100], grid_auto_fit=False, camera_auto_fit=False)

for n in range(N):
    plot += k3d.points(positions[n], colors=colors[n], shader='3d', opacity=0.85, point_size=0.5)
    plot += k3d.line(trajectories[n], shader='simple')

text_positions= {
    '0.0': np.array([0,0,100]),
    '4.3': np.array([0,0,100]),
    '4.8': np.array([0,0,20])
}

text_size= {
    '0.0': 1,
    '4.0': 1,
    '4.8': 80
}

plot += k3d.texture_text('Happy New Year!', text_positions, size=text_size, color=0xaaaaaa)
plot.display()
In [4]:
plot.camera = [29.542883324245675,
 -25.92168776472573,
 5.31411376357905,
 7.077758917185657,
 -2.251048430642773,
 15.430438268131883,
 0.20569267725971274,
 -0.2848548297554603,
 0.9362415545609555]
plot.fps = 30
In [5]:
plot.start_auto_play()
In [ ]:
plot.stop_auto_play()