redrun
redrun

Reputation: 23

FuncAnimation difficulty with markevery

I would like to sequentially plot a series of x,y coordinates while marking specified coordinates distinctly. It seems that 'markevery' allows users to do this in matplotlib plots, however, when I provide this property in my animation, I receive the error 'ValueError: markevery is iterable but not a valid form of numpy fancy indexing'. Any thoughts?

My actual 'mark_on' array will be much longer, so I think that using a linecollection isn't reasonable here.

frames = 100
def update_pos(num,data,line):
    line.set_data(data[...,:num])
    return line, 

def traj_ani(data):
    fig_traj = plt.figure()    
    l,= plt.plot([],[],'b', markevery = mark_on, marker = '*')
    plt.xlim(-90,90)
    plt.ylim(-90,90)
    pos_ani = animation.FuncAnimation(fig_traj, update_pos, frames = np.shape(data)[1], fargs = (data,l),
                                  interval = 20, blit = True)
    pos_ani.save('AgentTrajectory.mp4')

data = pd.read_csv('xy_pos.csv', header = None, skiprows = [0])
data = np.asarray(data)
mark_on = [20, 50, 100, 300, 600]
traj_ani(data)

Thanks!

Here is a complete, mini example of an animation that works:

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation 
import csv 
import pandas as pd 
import numpy as np 

Writer = animation.writers['ffmpeg']
writer = Writer(fps=2000, metadata=dict(artist='Me'), bitrate=1800)

def update_pos(num,data,line):
    line.set_data(data[...,:num])
    return line, 

def traj_ani(data):
    fig_traj = plt.figure()    
    l,= plt.plot([],[],'b')
    plt.xlim(0,1)
    plt.ylim(0,1)
    pos_ani = animation.FuncAnimation(fig_traj, update_pos, frames = 25, fargs = (data,l),
                                  interval = 200, blit = True)
    pos_ani.save('AgentTrajectory.mp4')


data = np.random.rand(2,25)
traj_ani(data)

In my full code, I would like to specify certain frames whose x-y coordinate should be marked with either a special character or by a different color.

Upvotes: 2

Views: 4443

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339310

It seems problematic to set a list of indizes to markevery, which contains indices not present in the ploted array. E.g. if the plotted array has 3 elements but the list set for markevery contains an index 5, a ValueError occurs.

The solution would need to be to set the markevery list in every iteration and make sure it only contains valid indizes.

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

mark_on = np.array([2,5,6,13,17,24])

def update_pos(num,data,line):
    line.set_data(data[...,:num])
    mark = mark_on[mark_on < num]
    line.set_markevery(list(mark))
    return line, 

def traj_ani(data):
    fig_traj = plt.figure()    
    l,= plt.plot([],[],'b', markevery = [], marker = '*', mfc="red", mec="red", ms=15)
    plt.xlim(0,1)
    plt.ylim(0,1)
    pos_ani = animation.FuncAnimation(fig_traj, update_pos, frames = 25, fargs = (data,l),
                                  interval = 200, blit = True)
    plt.show()

data = np.random.rand(2,25)
traj_ani(data)

Upvotes: 4

Related Questions