1

I have n curves that I want to draw using matplotlib's animation (each curve corresponds to a gpx file recorded with a fitness tracker or a smartphone). It works well when using only one track or two tracks. But as soon as I want to adapt it to using n curves, I am lost. Here is my code:

import matplotlib.animation as anim
import matplotlib.pyplot as plt
import numpy as np

tracks  = {}
xdata   = {}
ydata   = {}

# in my case n_tracks would rather correspond to a couple of 100
n_tracks    = 2
n_waypts    = 100

for ii in range(n_tracks):
    # generate fake data
    lat_pts = np.linspace(10+ii*1,20+ii*1,n_waypts)
    lon_pts = np.linspace(10+ii*1,20+ii*1,n_waypts)

    tracks[str(ii)] = np.array( [lat_pts, lon_pts] )

    xdata[str(ii)]  = []
    ydata[str(ii)]  = []

fig = plt.figure()
ax1 = fig.add_subplot( 1,1,1, aspect='equal', xlim=(0,30), ylim=(0,30) )

plt_tracks  = [ax1.plot([], [], marker=',', linewidth=1)[0] for _ in range(n_tracks)]
plt_lastPos = [ax1.plot([], [], marker='o', linestyle='none')[0] for _ in range(n_tracks)]

def animate(i):
    # x and y values to be plotted
    for jj in range(n_tracks):
        xdata[str(jj)].append( tracks[str(jj)][0,i] )
        ydata[str(jj)].append( tracks[str(jj)][1,i] )

    # update x and y data
    for jj in range(n_tracks):
        plt_tracks[jj].set_data(  xdata[str(jj)][:],  ydata[str(jj)][:] )
        plt_lastPos[jj].set_data( xdata[str(jj)][-1], ydata[str(jj)][-1] )

    return plt_tracks, plt_lastPos

anim    = anim.FuncAnimation( fig, animate, frames=n_waypts, interval=20, blit=True )
plt.show()

The dictionary tracks contains the tracks, where for each track we have an array with longitude and an array with latitude data. The dictionary xdata and ydata is used for plotting purposes.

I have two lists with plotting objects, plt_tracks and plt_lastPos, where the first is used for successively plotting the track and the latter to indicate the latest position.

The error message reads RuntimeError: The animation function must return a sequence of Artist objects. So, my mistake seems to be the return statement, but simply adding a , at the end does not help here. Any hint on what I am missing would be greatly appreciated.

1 Answer 1

1

Your are supposed to return an iterable of "artists" (that is of things to draw, that is of result of a "plot" call for example.

plt_tracks is such an iterable.
plt_lastPos also is.

But (plt_tracks, plt_lastPos) (with implicit parenthesis here) is a pair of such iterable. So an iterable of iterable of artists

So, simply put all them in a list. Replace

    return plt_tracks, plt_lastPos

by

    return plt_tracks + plt_lastPos
Sign up to request clarification or add additional context in comments.

2 Comments

probably worth its own question, but how would I add a changing text, corresponding to a third artist here, which I would initiate with plt_text = ax1.text(10,10,'') ?
@Alf. Same way. Initiate, indeed, with plt_text = ax1.text(10,10,''). Then in your animate function, update the text with whatever you want. plt_text.set_text("i="+str(i)) for example. And add plt_text to the list of artists animate returns. Note that plt_text is a single artist, whereas plt_tracks and plt_lastPost are list of artist. So it would go return plt_tracks + plt_lastPos + [plt_text]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.