0

I have the following code right now, to show growth of a curve:

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation

def move_curve(i, line, x, y, z):
    # Add points rather than changing start and end points.
    line.set_data(x[:i+1], y[:i+1])
    line.set_3d_properties(z[:i+1])

fig = plt.figure()
ax = fig.gca(projection='3d')
x = [1, 3, 8, 11, 17]
y = [7, 2, -5, 3, 5]
z = [5, 7, 9, 13, 18]

i = 0
line = ax.plot([x[i], x[i+1]], [y[i],y[i+1]], [z[i],z[i+1]])[0]
ax.set_xlim3d([1, 17])
ax.set_ylim3d([-5, 7])
ax.set_zlim3d([5, 18])

line_ani = animation.FuncAnimation(fig, move_curve, 5, fargs=(line, x, y, z))
plt.show()

I want to show the different lines in different colours. Also, I want to update the length of the axis as the curve grows.

How to do that? I am new to python so I might be missing something simple. Thanks for the help!

Ank
  • 1,864
  • 4
  • 31
  • 51

2 Answers2

2

Here is how @MrT's answer would look like using FuncAnimation. The advantage is that you do not need to care about autoscaling; that is done automatically on the fly.

import matplotlib.pyplot as plt
import matplotlib.animation as anim
import mpl_toolkits.mplot3d.axes3d as p3

fig = plt.figure()
ax = fig.gca(projection='3d')

x = [1, 3, 8, 11, 17]
y = [7, 2, -5, 3, 5]
z = [5, 7, 9, 13, 18]

#colour map
colors = ["green", "blue", "red", "orange"]

def init():
    ax.clear()

def update(i): 
    newsegm, = ax.plot([x[i], x[i + 1]], [y[i], y[i + 1]], [z[i], z[i + 1]], colors[i])

ani = anim.FuncAnimation(fig, update, init_func=init, 
                         frames = range(len(x)-1), interval = 300, repeat=True)
plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
1

You can use ArtistAnimation and attribute an individual colour to each line segment:

import matplotlib.pyplot as plt
import matplotlib.animation as anim
import mpl_toolkits.mplot3d.axes3d as p3

fig = plt.figure()
ax = fig.gca(projection='3d')

x = [1, 3, 8, 11, 17]
y = [7, 2, -5, 3, 5]
z = [5, 7, 9, 13, 18]

#colour map
cmap = ["green", "blue", "red", "orange"]

#set up list of images for animation with empty list
lines=[[]]
for i in range(len(x) - 1):
    #create next segment with new color 
    newsegm, = ax.plot([x[i], x[i + 1]], [y[i], y[i + 1]], [z[i], z[i + 1]], cmap[i])
    #append new segment to previous list
    lines.append(lines[-1] + [newsegm])

#animate list of line segments
ani = anim.ArtistAnimation(fig, lines, interval = 300)
plt.show()

Output:

enter image description here

Mr. T
  • 11,960
  • 10
  • 32
  • 54
  • Is there a way to update the axis also, as the new lines are added? – Ank Apr 09 '18 at 15:12
  • I'm afraid I don't understand, what you mean by "update the axis"? What exactly should be updated? – Mr. T Apr 09 '18 at 17:38
  • You mean that it autoscales to the lines presented in each frame? I am not sure this is possible with ArtistAnimation. And there might be [some drawbacks with this approach in 3D](https://stackoverflow.com/q/16143493/8881141). But imho the worst problem would be a perception problem. If all elements, objects and reference frame, change dramatically, it might be difficult to understand, what we see. This wouldn't be of course the case, if we have 100 frames with only marginal changes - in this case the zoom effect would probably look rather appealing. – Mr. T Apr 10 '18 at 18:51
  • I would recommend using `FuncAnimation` instead of artist animation. – ImportanceOfBeingErnest Apr 11 '18 at 10:21
  • @ImportanceOfBeingErnest I tried first to adapt the `FuncAnimation` script of the OP, but didn't find a way to add individual colours. How would you do this? And what would be the advantage of using `FuncAnimation`? – Mr. T Apr 11 '18 at 20:30
  • 1
    I gave an answer below on how that would look, being as close as possible to your solution. – ImportanceOfBeingErnest Apr 11 '18 at 23:14