2014-01-21 28 views
0

我想创建一系列带有经纬度位置的一系列点在matplotlib.basemap地图上的动画图。每个点都有一系列的位置,我已经读入pandasDataFrame随着时间的推移动画Matplotlib底图上的多个点

我试过修改使用的程序HERE来做到这一点,但我得到一个错误,global name 'points' is not defined。我试图在init例程中声明这是全局的,但这并没有帮助。

我该怎么做?

实施例的数据:

day,id,  lon,  lat 
156, 1, 67.53453, -4.00454 
156, 2, 66.73453, 0.78454 
156, 3, 68.23453, -1.01454 
157, 1, 67.81453, -4.26454 
157, 2, 66.42653, 0.91454 
157, 3, 69.11253, -1.01454 
158, 1, 68.12453, -3.26454 
158, 2, 67.10053, 1.01454 
158, 3, 68.01253, -2.61454 

调用例程:

if datafile != None: 
    data = readdata(datafile) 
    dates = np.unique(data.daynr).values 

    x,y = m(0,0) 
    point = m.plot(x,y, 'ro', markersize=5)[0] 
    points = list() 

    anim = animation.FuncAnimation(plt.gcf(), animate, 
            init_func=init, frames=20, 
            interval=500, blit=True) 

    # Add current date/time or something to make unique 
    anim.save('movement.mp4', fps=15, 
       extra_args=['-vcodec', 'libx264']) 

initanimate,和数据读出的例程:

def init(): 
    for pt in points: 
     pt.set_data([], []) 
    return points 

def animate(i): 
    lons = data.lons[data.daynr==dates[i]] 
    lats = data.lats[data.daynr==dates[i]] 

    i = 0 
    for lon,lat, pt in zip(points, lons, lats): 
     x, y = map(lon,lat) 
     pt.set_data(x, y) 
     i = i + 1 
    return points 

def readdata(datafile): 
    dtypes = np.dtype([ 
        ('daynr',int),  #00 - Simulation day number 
        ('id',int),   #01 - Id 
        ('lon',float),  #02 - Longitude 
        ('lat',float),  #03 - Latitude 
        ]) 
    f = open(datafile, 'rb') 
    data = pd.read_csv(f, index_col=False, names=dtypes.names, 
          dtype=dtypes, header=None) 
    f.close() 
    return data 
+0

哪条线做你的程序中断吗? – waitingkuo

+0

at'for pt in points:'in'init()' – ryanjdillon

+0

你把所有的代码放在一个文件中吗? – waitingkuo

回答

2

所以......我的第一个问题是,我没有意识到python中的函数内的变量不被认为是全局函数。

要解决这个问题,我做了我init()animate(i)功能“子功能”,然后让其在父函数声明的变量为全球由init()animate(i)子功能(参见下面的代码)进行治疗。

我发现this blog article对我的解决方案非常有帮助。

正如this SO question

注:我已经编辑我的代码位对于这个答案的目的,所以请评论,如果这不适合您正常工作。

我的绘图功能和调用程序:

import pandas as pd 
import numpy as np 
import pyproj 
import matplotlib.pyplot as plt 
from mpl_toolkits.basemap import Basemap 


def makeplot(plot_data=False): 
''' plot function with optional data animation 
    if data is supplied (as a `pandas` DataFrame), subfuntions `init()` 
    and `animate(i)` will animate recurring, multiple position values 
    per unique day and save to file.''' 

    def init(): 
     # initialize each plot point created in the list `points` 
     for pt in points: 
      pt.set_data([], []) 
     return points 

    def animate(i): 
     #Only routine if `i` doesn't exceed number of unique days to animate 
     if i < len(data_dates): 
      print 'Animation frame:', i, '; Simulation Day:', data_dates[i] 

      lons = data.lons[data.daynr==dates[i]].values 
      lats = data.lats[data.daynr==dates[i]].values 

      j = 0 
      for pt,lon,lat in zip(points, lons, lats): 
       x, y = m(lon,lat) 
       pt.set_data(x, y) 
       j = j + 1 
     return points 

    # Define ellipsoid object for distance measurements 
    g = pyproj.Geod(ellps='WGS84') # Use WGS84 ellipsoid 
    r_equator = g.a # earth's radius at equator 
    r_poles = g.b # earth's radius through poles 

    lon0, lat0, map_width, map_height = center_map(poly_lons, poly_lats, 1.1) 

    m = Basemap(width=map_width,height=map_height, 
       rsphere=(r_equator, r_poles),\ 
       resolution='f', projection='laea',\ 
       lat_ts=lat0,\ 
       lat_0=lat0,lon_0=lon0) 

    # Draw parallels and meridians. 
    m.drawparallels(np.arange(-80.,81.,5.), labels=[1,0,0,0], fontsize=10) 
    m.drawmeridians(np.arange(-180.,181.,10.), labels=[0,0,0,1], fontsize=10) 
    m.drawmapboundary(fill_color='white') 
    m.drawcoastlines(linewidth=0.2) 
    m.fillcontinents(color='gray', lake_color='white') #aqua 

    # Animate if position data is supplied with plotting function 
    if plot_data == True: 
     # Automatically determine frame number 
     f_num = len(data_dates) 
     # Declare list of point objects 
     points = list() 

     # Create a placeholder plot point 
     x,y = m(0,0) 
     # Fill list with same number of placeholders as points to animate 
     for i in range(len(data.lons)): 
      points.append(m.plot(x,y, 'ro', markersize=5)[0]) 

     anim = animation.FuncAnimation(plt.gcf(), animate, 
             init_func=init, frames=f_num, 
             interval=500, blit=True) 

     # Save animation to file 
     anim.save('plot_animation.mp4', fps=f_num, 
        extra_args=['-vcodec', 'libx264']) 

    plt.show() 

if __name__ == '__main__': 

    # WGS84 datum 
    wgs84 = pyproj.Proj(init='EPSG:4326') 

    # CSV data with columns 'daynr', 'lons', and 'lats' 
    datafile = '/home/dude/datalocations/data.csv' 
    data = readwhales(whale_datafile) 
    data_dates = np.unique(data.daynr).values 

    makeplot(plot_data=True) 
相关问题