pythonmatplotlibscatter-plotmatplotlib-animation

Scatter animation in Python


I am attempting to animate a scatter plot in Python 3.6 (in Spyder IDE), for which there are several tutorials/examples (a, b, c, and many others), however my update function is somehow receiving a very different set of coordinates from what I think I'm providing.

The following is a reduced example code wherein 4 points proceed toward the center. I plot it twice, first as a line, second as an animation. The line plot looks right, but the animation shows very different behavior, both in terms of the locations of the points and their trajectories. I infer that I'm incorrectly supplying coordinate information to the update function, but I cannot seem to determine why/how.

I can supply figures showing what does vs. should happen, though I'll simply supply this sample code for now for brevity's sake.

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

npt=4
ntime=101
solx=np.zeros((npt,ntime))
soly=np.zeros((npt,ntime))
solx[0,0:]=np.linspace(0,40,ntime)
solx[1,0:]=solx[0,0:];
solx[2,0:]=100-solx[0,0:];
solx[3,0:]=solx[2,0:]
soly[0,0:]=np.linspace(0,80,ntime)
soly[1,0:]=200-soly[0,0:]
soly[2,0:]=soly[0,0:]
soly[3,0:]=soly[1,0:]


#%% Plots
colord=mpl.cm.gist_ncar(np.linspace(0,0.9,npt))
of2,oa2=plt.subplots(1)
for cnt in range(0,npt): oa2.plot(solx[cnt,0:],soly[cnt,0:],c=colord[cnt])

of3,oa3=plt.subplots()
osc3=oa3.scatter(solx[0:,0],soly[0:,0],c=colord,marker='+')
def aninit():
    osc3.set_offsets(np.stack((solx[0:,0],soly[0:,0]),axis=0))
    return osc3,
def aniupdate(i):
    osc3.set_offsets(np.stack((solx[0:,i],soly[0:,i]),axis=0))
    return osc3,

ani=anim.FuncAnimation(of3,aniupdate,init_func=aninit,frames=range(0,ntime),interval=100,blit=True,repeat=True,repeat_delay=1000)
plt.show()

Solution

  • If you replace

    np.stack((solx[0:,0],soly[0:,0]),axis=0)
    np.stack((solx[0:,i],soly[0:,i]),axis=0)
    

    with:

    list(zip(solx[0:,0],soly[0:,0]))
    list(zip(solx[0:,i],soly[0:,i]))
    

    or (if you want to use numpy arrays instead of lists:

    np.array([solx[0:,0],soly[0:,0]]).T
    np.array([solx[0:,i],soly[0:,i]]).T
    

    in the aninit() and aniupdate(i) functions the behaviour should be as expected.

    Here's the code I used to make the plots:

    def aninit():
        offsetlist = np.array([solx[0:,0],soly[0:,0]]).T
        osc3.set_offsets(offsetlist)
        return osc3,
    
    def aniupdate(i):
        offsetlist = np.array([solx[0:,i],soly[0:,i]]).T
        osc3.set_offsets(offsetlist)
        return osc3,
    

    enter image description here

    References: