2014-01-21 31 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) 
相關問題